]> git.decadent.org.uk Git - dak.git/blobdiff - daklib/queue.py
Don't shadow "dir" builtin.
[dak.git] / daklib / queue.py
index 7e93448cd45199cc1af1cde5f23cf0fe3cb7181a..8e8421f122658ebf2c2d59046bda0527a76162df 100755 (executable)
@@ -273,19 +273,20 @@ class Upload(object):
         self.pkg.reset()
 
     def package_info(self):
-        msg = ''
-
-        if len(self.rejects) > 0:
-            msg += "Reject Reasons:\n"
-            msg += "\n".join(self.rejects)
+        """
+        Format various messages from this Upload to send to the maintainer.
+        """
 
-        if len(self.warnings) > 0:
-            msg += "Warnings:\n"
-            msg += "\n".join(self.warnings)
+        msgs = (
+            ('Reject Reasons', self.rejects),
+            ('Warnings', self.warnings),
+            ('Notes', self.notes),
+        )
 
-        if len(self.notes) > 0:
-            msg += "Notes:\n"
-            msg += "\n".join(self.notes)
+        msg = ''
+        for title, messages in msgs:
+            if messages:
+                msg += '\n\n%s:\n%s' % (title, '\n'.join(messages))
 
         return msg
 
@@ -407,7 +408,7 @@ class Upload(object):
                    fix_maintainer (self.pkg.changes["maintainer"])
         except ParseMaintError, msg:
             self.rejects.append("%s: Maintainer field ('%s') failed to parse: %s" \
-                   % (filename, changes["maintainer"], msg))
+                   % (filename, self.pkg.changes["maintainer"], msg))
 
         # ...likewise for the Changed-By: field if it exists.
         try:
@@ -438,9 +439,8 @@ class Upload(object):
         # Check there isn't already a changes file of the same name in one
         # of the queue directories.
         base_filename = os.path.basename(filename)
-        for d in [ "Accepted", "Byhand", "Done", "New", "ProposedUpdates", "OldProposedUpdates" ]:
-            if os.path.exists(os.path.join(Cnf["Dir::Queue::%s" % (d) ], base_filename)):
-                self.rejects.append("%s: a file with this name already exists in the %s directory." % (base_filename, d))
+        if get_knownchange(base_filename):
+            self.rejects.append("%s: a file with this name already exists." % (base_filename))
 
         # Check the .changes is non-empty
         if not self.pkg.files:
@@ -755,7 +755,7 @@ class Upload(object):
 
         # Validate the component
         if not get_component(entry["component"], session):
-            self.rejects.append("file '%s' has unknown component '%s'." % (f, component))
+            self.rejects.append("file '%s' has unknown component '%s'." % (f, entry["component"]))
             return
 
         # See if the package is NEW
@@ -770,7 +770,7 @@ class Upload(object):
         location = cnf["Dir::Pool"]
         l = get_location(location, entry["component"], archive, session)
         if l is None:
-            self.rejects.append("[INTERNAL ERROR] couldn't determine location (Component: %s, Archive: %s)" % (component, archive))
+            self.rejects.append("[INTERNAL ERROR] couldn't determine location (Component: %s, Archive: %s)" % (entry["component"], archive))
             entry["location id"] = -1
         else:
             entry["location id"] = l.location_id
@@ -1036,8 +1036,8 @@ class Upload(object):
                 if not os.path.exists(src):
                     return
                 ftype = m.group(3)
-                if re_is_orig_source.match(f) and pkg.orig_files.has_key(f) and \
-                   pkg.orig_files[f].has_key("path"):
+                if re_is_orig_source.match(f) and self.pkg.orig_files.has_key(f) and \
+                   self.pkg.orig_files[f].has_key("path"):
                     continue
                 dest = os.path.join(os.getcwd(), f)
                 os.symlink(src, dest)
@@ -1182,7 +1182,98 @@ class Upload(object):
         self.ensure_hashes()
 
     ###########################################################################
+
+    def ensure_orig(self, target_dir='.', session=None):
+        """
+        Ensures that all orig files mentioned in the changes file are present
+        in target_dir. If they do not exist, they are symlinked into place.
+
+        An list containing the symlinks that were created are returned (so they
+        can be removed).
+        """
+
+        symlinked = []
+        cnf = Config()
+
+        for filename, entry in self.pkg.dsc_files.iteritems():
+            if not re_is_orig_source.match(filename):
+                # File is not an orig; ignore
+                continue
+
+            if os.path.exists(filename):
+                # File exists, no need to continue
+                continue
+
+            def symlink_if_valid(path):
+                f = utils.open_file(path)
+                md5sum = apt_pkg.md5sum(f)
+                f.close()
+
+                fingerprint = (os.stat(path)[stat.ST_SIZE], md5sum)
+                expected = (int(entry['size']), entry['md5sum'])
+
+                if fingerprint != expected:
+                    return False
+
+                dest = os.path.join(target_dir, filename)
+
+                os.symlink(path, dest)
+                symlinked.append(dest)
+
+                return True
+
+            session_ = session
+            if session is None:
+                session_ = DBConn().session()
+
+            found = False
+
+            # Look in the pool
+            for poolfile in get_poolfile_like_name('/%s' % filename, session_):
+                poolfile_path = os.path.join(
+                    poolfile.location.path, poolfile.filename
+                )
+
+                if symlink_if_valid(poolfile_path):
+                    found = True
+                    break
+
+            if session is None:
+                session_.close()
+
+            if found:
+                continue
+
+            # Look in some other queues for the file
+            queues = ('Accepted', 'New', 'Byhand', 'ProposedUpdates',
+                'OldProposedUpdates', 'Embargoed', 'Unembargoed')
+
+            for queue in queues:
+                if not cnf.get('Dir::Queue::%s' % queue):
+                    continue
+
+                queuefile_path = os.path.join(
+                    cnf['Dir::Queue::%s' % queue], filename
+                )
+
+                if not os.path.exists(queuefile_path):
+                    # Does not exist in this queue
+                    continue
+
+                if symlink_if_valid(queuefile_path):
+                    break
+
+        return symlinked
+
+    ###########################################################################
+
     def check_lintian(self):
+        cnf = Config()
+
+        # Don't reject binary uploads
+        if not self.pkg.changes['architecture'].has_key('source'):
+            return
+
         # Only check some distributions
         valid_dist = False
         for dist in ('unstable', 'experimental'):
@@ -1193,11 +1284,11 @@ class Upload(object):
         if not valid_dist:
             return
 
-        cnf = Config()
         tagfile = cnf.get("Dinstall::LintianTags")
         if tagfile is None:
             # We don't have a tagfile, so just don't do anything.
             return
+
         # Parse the yaml file
         sourcefile = file(tagfile, 'r')
         sourcecontent = sourcefile.read()
@@ -1208,6 +1299,9 @@ class Upload(object):
             utils.fubar("Can not read the lintian tags file %s, YAML error: %s." % (tagfile, msg))
             return
 
+        # Try and find all orig mentioned in the .dsc
+        symlinked = self.ensure_orig()
+
         # Now setup the input file for lintian. lintian wants "one tag per line" only,
         # so put it together like it. We put all types of tags in one file and then sort
         # through lintians output later to see if its a fatal tag we detected, or not.
@@ -1227,8 +1321,12 @@ class Upload(object):
         # to then parse it.
         command = "lintian --show-overrides --tags-from-file %s %s" % (temp_filename, self.pkg.changes_file)
         (result, output) = commands.getstatusoutput(command)
-        # We are done with lintian, remove our tempfile
+
+        # We are done with lintian, remove our tempfile and any symlinks we created
         os.unlink(temp_filename)
+        for symlink in symlinked:
+            os.unlink(symlink)
+
         if (result == 2):
             utils.warn("lintian failed for %s [return code: %s]." % (self.pkg.changes_file, result))
             utils.warn(utils.prefix_multi_line_string(output, " [possible output:] "))
@@ -1236,6 +1334,10 @@ class Upload(object):
         if len(output) == 0:
             return
 
+        def log(*txt):
+            if self.logger:
+                self.logger.log([self.pkg.changes_file, "check_lintian"] + list(txt))
+
         # We have output of lintian, this package isn't clean. Lets parse it and see if we
         # are having a victim for a reject.
         # W: tzdata: binary-without-manpage usr/sbin/tzconfig
@@ -1262,12 +1364,16 @@ class Upload(object):
                 elif etag in lintiantags['error']:
                     # The tag is overriden - but is not allowed to be
                     self.rejects.append("%s: Overriden tag %s found, but this tag may not be overwritten." % (epackage, etag))
+                    log("ftpmaster does not allow tag to be overridable", etag)
             else:
                 # Tag is known, it is not overriden, direct reject.
                 self.rejects.append("%s: Found lintian output: '%s %s', automatically rejected package." % (epackage, etag, etext))
                 # Now tell if they *might* override it.
                 if etag in lintiantags['warning']:
+                    log("auto rejecting", "overridable", etag)
                     self.rejects.append("%s: If you have a good reason, you may override this lintian tag." % (epackage))
+                else:
+                    log("auto rejecting", "not overridable", etag)
 
     ###########################################################################
     def check_urgency(self):
@@ -1459,10 +1565,10 @@ class Upload(object):
         rej = False
         for f in self.pkg.files.keys():
             if self.pkg.files[f].has_key("byhand"):
-                self.rejects.append("%s may not upload BYHAND file %s" % (uid, f))
+                self.rejects.append("%s may not upload BYHAND file %s" % (fpr.uid.uid, f))
                 rej = True
             if self.pkg.files[f].has_key("new"):
-                self.rejects.append("%s may not upload NEW file %s" % (uid, f))
+                self.rejects.append("%s may not upload NEW file %s" % (fpr.uid.uid, f))
                 rej = True
 
         if rej:
@@ -1872,14 +1978,14 @@ distribution."""
 
     ###########################################################################
 
-    def remove(self, dir=None):
+    def remove(self, from_dir=None):
         """
         Used (for instance) in p-u to remove the package from unchecked
         """
-        if dir is None:
+        if from_dir is None:
             os.chdir(self.pkg.directory)
         else:
-            os.chdir(dir)
+            os.chdir(from_dir)
 
         for f in self.pkg.files.keys():
             os.unlink(f)