]> git.decadent.org.uk Git - dak.git/blobdiff - daklib/checks.py
auto-decruft: Disable short options for NVI
[dak.git] / daklib / checks.py
index b7931f2f6d8e60a2b893f6a304b357fe88cefd31..70e1f5e398dd3b17e4e5d1f9127f15e4dfb84abb 100644 (file)
@@ -31,11 +31,12 @@ from daklib.regexes import *
 from daklib.textutils import fix_maintainer, ParseMaintError
 import daklib.lintian as lintian
 import daklib.utils as utils
 from daklib.textutils import fix_maintainer, ParseMaintError
 import daklib.lintian as lintian
 import daklib.utils as utils
-from daklib.upload import InvalidHashException
+import daklib.upload
 
 import apt_inst
 import apt_pkg
 from apt_pkg import version_compare
 
 import apt_inst
 import apt_pkg
 from apt_pkg import version_compare
+import datetime
 import errno
 import os
 import subprocess
 import errno
 import os
 import subprocess
@@ -56,7 +57,7 @@ class Reject(Exception):
     """exception raised by failing checks"""
     pass
 
     """exception raised by failing checks"""
     pass
 
-class RejectStupidMaintainerException(Exception):
+class RejectExternalFilesMismatch(Reject):
     """exception raised by failing the external hashes check"""
 
     def __str__(self):
     """exception raised by failing the external hashes check"""
 
     def __str__(self):
@@ -112,13 +113,11 @@ class SignatureAndHashesCheck(Check):
     def check_replay(self, upload):
         # Use private session as we want to remember having seen the .changes
         # in all cases.
     def check_replay(self, upload):
         # Use private session as we want to remember having seen the .changes
         # in all cases.
-        session = DBConn().session()
+        session = upload.session
         history = SignatureHistory.from_signed_file(upload.changes)
         r = history.query(session)
         if r is not None:
         history = SignatureHistory.from_signed_file(upload.changes)
         r = history.query(session)
         if r is not None:
-            raise Reject('Signature for changes file was already seen at {0}'.format(r.seen))
-        session.add(history)
-        session.commit()
+            raise Reject('Signature for changes file was already seen at {0}.\nPlease refresh the signature of the changes file if you want to upload it again.'.format(r.seen))
         return True
 
     """Check signature of changes and dsc file (if included in upload)
         return True
 
     """Check signature of changes and dsc file (if included in upload)
@@ -162,15 +161,32 @@ class SignatureAndHashesCheck(Check):
         try:
             for f in files:
                 f.check(upload.directory)
         try:
             for f in files:
                 f.check(upload.directory)
-        except IOError as e:
-            if e.errno == errno.ENOENT:
-                raise Reject('{0} refers to non-existing file: {1}\n'
-                             'Perhaps you need to include it in your upload?'
-                             .format(filename, os.path.basename(e.filename)))
-            raise
-        except InvalidHashException as e:
+        except daklib.upload.FileDoesNotExist as e:
+            raise Reject('{0}: {1}\n'
+                         'Perhaps you need to include the file in your upload?'
+                         .format(filename, unicode(e)))
+        except daklib.upload.UploadException as e:
             raise Reject('{0}: {1}'.format(filename, unicode(e)))
 
             raise Reject('{0}: {1}'.format(filename, unicode(e)))
 
+class SignatureTimestampCheck(Check):
+    """Check timestamp of .changes signature"""
+    def check(self, upload):
+        changes = upload.changes
+
+        now = datetime.datetime.utcnow()
+        timestamp = changes.signature_timestamp
+        age = now - timestamp
+
+        age_max = datetime.timedelta(days=365)
+        age_min = datetime.timedelta(days=-7)
+
+        if age > age_max:
+            raise Reject('{0}: Signature from {1} is too old (maximum age is {2} days)'.format(changes.filename, timestamp, age_max.days))
+        if age < age_min:
+            raise Reject('{0}: Signature from {1} is too far in the future (tolerance is {2} days)'.format(changes.filename, timestamp, abs(age_min.days)))
+
+        return True
+
 class ChangesCheck(Check):
     """Check changes file for syntax errors."""
     def check(self, upload):
 class ChangesCheck(Check):
     """Check changes file for syntax errors."""
     def check(self, upload):
@@ -240,16 +256,16 @@ class ExternalHashesCheck(Check):
             return
 
         if ext_size != f.size:
             return
 
         if ext_size != f.size:
-            raise RejectStupidMaintainerException(f.filename, 'size', f.size, ext_size)
+            raise RejectExternalFilesMismatch(f.filename, 'size', f.size, ext_size)
 
         if ext_md5sum != f.md5sum:
 
         if ext_md5sum != f.md5sum:
-            raise RejectStupidMaintainerException(f.filename, 'md5sum', f.md5sum, ext_md5sum)
+            raise RejectExternalFilesMismatch(f.filename, 'md5sum', f.md5sum, ext_md5sum)
 
         if ext_sha1sum != f.sha1sum:
 
         if ext_sha1sum != f.sha1sum:
-            raise RejectStupidMaintainerException(f.filename, 'sha1sum', f.sha1sum, ext_sha1sum)
+            raise RejectExternalFilesMismatch(f.filename, 'sha1sum', f.sha1sum, ext_sha1sum)
 
         if ext_sha256sum != f.sha256sum:
 
         if ext_sha256sum != f.sha256sum:
-            raise RejectStupidMaintainerException(f.filename, 'sha256sum', f.sha256sum, ext_sha256sum)
+            raise RejectExternalFilesMismatch(f.filename, 'sha256sum', f.sha256sum, ext_sha256sum)
 
     def check(self, upload):
         cnf = Config()
 
     def check(self, upload):
         cnf = Config()
@@ -284,7 +300,7 @@ class BinaryCheck(Check):
         fn = binary.hashed_file.filename
         control = binary.control
 
         fn = binary.hashed_file.filename
         control = binary.control
 
-        for field in ('Package', 'Architecture', 'Version', 'Description'):
+        for field in ('Package', 'Architecture', 'Version', 'Description', 'Section'):
             if field not in control:
                 raise Reject('{0}: Missing mandatory field {0}.'.format(fn, field))
 
             if field not in control:
                 raise Reject('{0}: Missing mandatory field {0}.'.format(fn, field))
 
@@ -345,6 +361,11 @@ class BinaryCheck(Check):
                 except:
                     raise Reject('{0}: APT could not parse {1} field'.format(fn, field))
 
                 except:
                     raise Reject('{0}: APT could not parse {1} field'.format(fn, field))
 
+        # "Multi-Arch: no" breaks wanna-build, #768353
+        multi_arch = control.get("Multi-Arch")
+        if multi_arch == 'no':
+            raise Reject('{0}: Multi-Arch: no support in Debian is broken (#768353)'.format(fn))
+
 class BinaryTimestampCheck(Check):
     """check timestamps of files in binary packages
 
 class BinaryTimestampCheck(Check):
     """check timestamps of files in binary packages
 
@@ -668,6 +689,7 @@ class NoSourceOnlyCheck(Check):
 
         if not allow_no_arch_indep_uploads \
            and 'all' not in changes.architectures \
 
         if not allow_no_arch_indep_uploads \
            and 'all' not in changes.architectures \
+           and 'experimental' not in changes.distributions \
            and changes.source.package_list.has_arch_indep_packages():
             raise Reject('Uploads not including architecture-independent packages are not allowed.')
 
            and changes.source.package_list.has_arch_indep_packages():
             raise Reject('Uploads not including architecture-independent packages are not allowed.')