def _doUpload(self, type, version, policy, archive, distribution_name, suite, logger, notify): """Upload a given version. Raises an error if the version couldn't be found or the upload was rejected. Build a upload policy with the given name and override it with archive, distribution_name and suite if passed. Return the corresponding `NascentUpload` object. """ changesfile_path = self._getChangefilePathForVersion(version, type) assert changesfile_path is not None, ( "Could not find a %s upload for version %s." % (type, version)) if archive is not None: policy.archive = archive policy.distro = getUtility(IDistributionSet).getByName( distribution_name) if suite is not None: policy.setDistroSeriesAndPocket(suite) upload = NascentUpload.from_changesfile_path( changesfile_path, policy, logger) upload.process() return upload
def makeNascentUpload(self, spph, maintainer, maintainer_address, changer, changer_address): """Create a `NascentUpload` for `spph`.""" changes = self.makeChangesFile( spph, maintainer, maintainer_address, changer, changer_address) upload = NascentUpload( changes, FakeUploadPolicy(spph), DevNullLogger()) upload.queue_root = upload._createQueueEntry() das = self.factory.makeDistroArchSeries( distroseries=spph.distroseries) bpb = self.factory.makeBinaryPackageBuild( source_package_release=spph.sourcepackagerelease, archive=spph.archive, distroarchseries=das, pocket=spph.pocket, sourcepackagename=spph.sourcepackagename) upload.queue_root.addBuild(bpb) return upload
def _doUpload(self, type, version, policy, archive, distribution_name, suite, logger, notify): """Upload a given version. Raises an error if the version couldn't be found or the upload was rejected. Build a upload policy with the given name and override it with archive, distribution_name and suite if passed. Return the corresponding `NascentUpload` object. """ changesfile_path = self._getChangefilePathForVersion(version, type) assert changesfile_path is not None, ( "Could not find a %s upload for version %s." % (type, version)) if archive is not None: policy.archive = archive policy.distro = getUtility(IDistributionSet).getByName( distribution_name) if suite is not None: policy.setDistroSeriesAndPocket(suite) upload = NascentUpload.from_changesfile_path(changesfile_path, policy, logger) upload.process() return upload
def makeNascentUpload(self, spph, maintainer, maintainer_address, changer, changer_address): """Create a `NascentUpload` for `spph`.""" changes = self.makeChangesFile(spph, maintainer, maintainer_address, changer, changer_address) upload = NascentUpload(changes, FakeUploadPolicy(spph), DevNullLogger()) upload.queue_root = upload._createQueueEntry() das = self.factory.makeDistroArchSeries(distroseries=spph.distroseries) bpb = self.factory.makeBinaryPackageBuild( source_package_release=spph.sourcepackagerelease, archive=spph.archive, distroarchseries=das, pocket=spph.pocket, sourcepackagename=spph.sourcepackagename) upload.queue_root.addBuild(bpb) return upload
def uploadTestData(self, version): upload = NascentUpload.from_changesfile_path( datadir("dist-upgrader/dist-upgrader_%s_all.changes" % version), self.anything_policy, self.logger) upload.process() self.assertFalse(upload.is_rejected) self.assertTrue(upload.do_accept()) self.assertFalse(upload.rejection_message) return upload
def uploadTestData(self, version): upload = NascentUpload.from_changesfile_path( datadir("ddtp-tarball/translations-main_%s_all.changes" % version), self.anything_policy, self.logger ) upload.process() self.assertFalse(upload.is_rejected) self.assertTrue(upload.do_accept()) self.assertFalse(upload.rejection_message) return upload
def uploadToPPA(self): # Setup PPA owner and archive self.name16 = getUtility(IPersonSet).getByName('name16') name16_archive = self.factory.makeArchive( distribution=self.breezy_autotest.distribution, owner=self.name16, name="ppa") policy = self.absolutely_anything_policy policy.archive = name16_archive upload = NascentUpload.from_changesfile_path( datadir("rosetta-translations/%s" % self.source_changes_file), policy, self.logger) upload.process() self.assertFalse(upload.is_rejected) self.assertTrue(upload.do_accept()) self.assertEqual(upload.queue_root.status, PackageUploadStatus.DONE) spph = self.name16.archive.getPublishedSources(name="pmount").one() self.assertIsNotNone(spph) transaction.commit() policy.accepted_type = ArchiveUploadType.BINARY_ONLY bin_upload = NascentUpload.from_changesfile_path( datadir("rosetta-translations/%s" % self.bin_changes_file), policy, self.logger) bin_upload.process() self.assertFalse(bin_upload.is_rejected) self.assertTrue(bin_upload.do_accept()) self.assertEqual(bin_upload.queue_root.status, PackageUploadStatus.ACCEPTED) bin_upload.queue_root.realiseUpload() self.assertEqual(bin_upload.queue_root.status, PackageUploadStatus.DONE) self.assertEqual(bin_upload.queue_root.builds[0].build.status.name, "FULLYBUILT") transaction.commit() return upload, spph, bin_upload
def uploadTestData(self): upload = NascentUpload.from_changesfile_path( datadir("debian-installer/" "debian-installer_20070214ubuntu1_i386.changes"), self.anything_policy, self.logger) upload.process() self.assertFalse(upload.is_rejected) self.assertTrue(upload.do_accept()) self.assertFalse(upload.rejection_message) return upload
def uploadTestData(self): upload = NascentUpload.from_changesfile_path( datadir( "debian-installer/" "debian-installer_20070214ubuntu1_i386.changes"), self.anything_policy, self.logger) upload.process() self.assertFalse(upload.is_rejected) self.assertTrue(upload.do_accept()) self.assertFalse(upload.rejection_message) return upload
def test_hash_mismatch_rejects(self): # A hash mismatch for any uploaded file will cause the upload to # be rejected. policy = getPolicy(name="sync", distro="ubuntu", distroseries="hoary") policy.accepted_type = ArchiveUploadType.BINARY_ONLY upload = NascentUpload.from_changesfile_path( datadir("suite/badhash_1.0-1/badhash_1.0-1_i386.changes"), policy, DevNullLogger()) upload.process() self.assertTrue(upload.is_rejected) self.assertEqual( 'File badhash_1.0-1_i386.deb mentioned in the changes has a SHA1 ' 'mismatch. 2ca33cf32a45852c62b465aaf9063fb7deb31725 != ' '91556113ad38eb35d2fe03d27ae646e0ed487a3d', upload.rejection_message)
def test_hash_mismatch_rejects(self): # A hash mismatch for any uploaded file will cause the upload to # be rejected. policy = getPolicy(name="sync", distro="ubuntu", distroseries="hoary") policy.accepted_type = ArchiveUploadType.BINARY_ONLY upload = NascentUpload.from_changesfile_path( datadir("suite/badhash_1.0-1/badhash_1.0-1_i386.changes"), policy, DevNullLogger() ) upload.process() self.assertTrue(upload.is_rejected) self.assertEqual( "File badhash_1.0-1_i386.deb mentioned in the changes has a SHA1 " "mismatch. 2ca33cf32a45852c62b465aaf9063fb7deb31725 != " "91556113ad38eb35d2fe03d27ae646e0ed487a3d", upload.rejection_message, )
def test_ppa_publishing_location(self): # A PPA dist-upgrader upload is published to the right place. archive = self.factory.makeArchive(distribution=self.ubuntutest) self.anything_policy.archive = archive ppa_upload = self.uploadTestData("20060302.0120") ppa_upload = NascentUpload.from_changesfile_path( datadir("dist-upgrader/dist-upgrader_20060302.0120_all.changes"), self.anything_policy, self.logger) ppa_upload.process() self.assertTrue(ppa_upload.do_accept()) transaction.commit() ppa_upload.queue_root.realiseUpload(self.logger) ppa_root = config.personalpackagearchive.root ppa_dir = os.path.join(ppa_root, archive.owner.name, archive.name) target_dir = os.path.join( ppa_dir, "ubuntutest/dists/breezy-autotest/main/dist-upgrader-all") self.assertContentEqual( ["20060302.0120", "current"], os.listdir(target_dir))
def test_ppa_publishing_location(self): # A PPA dist-upgrader upload is published to the right place. archive = self.factory.makeArchive(distribution=self.ubuntutest) self.anything_policy.archive = archive ppa_upload = self.uploadTestData("20060302.0120") ppa_upload = NascentUpload.from_changesfile_path( datadir("dist-upgrader/dist-upgrader_20060302.0120_all.changes"), self.anything_policy, self.logger) ppa_upload.process() self.assertTrue(ppa_upload.do_accept()) transaction.commit() ppa_upload.queue_root.realiseUpload(self.logger) ppa_root = config.personalpackagearchive.root ppa_dir = os.path.join(ppa_root, archive.owner.name, archive.name) target_dir = os.path.join( ppa_dir, "ubuntutest/dists/breezy-autotest/main/dist-upgrader-all") self.assertContentEqual(["20060302.0120", "current"], os.listdir(target_dir))
def uploadTestData(self, name=None, version=None): if name is None: name = self.package_name if version is None: version = self.version spph = self.getPubSource(sourcename=name, version=version, distroseries=self.breezy_autotest, status=PackagePublishingStatus.PUBLISHED) self.spr = spph.sourcepackagerelease upload = NascentUpload.from_changesfile_path( datadir("rosetta-translations/%s" % self.bin_changes_file), self.absolutely_anything_policy, self.logger) upload.process() self.assertFalse(upload.is_rejected) self.assertTrue(upload.do_accept()) self.assertFalse(upload.rejection_message) # Accepting the queue entry because there's no ancestry, so not # auto-accepted upload.queue_root.setAccepted() return upload
def test_rejects_misspelled_changesfile_name(self): upload = NascentUpload.from_changesfile_path( datadir("dist-upgrader/dist-upgrader_20060302.0120.changes"), self.absolutely_anything_policy, self.logger) self.assertRaises(EarlyReturnUploadError, upload.process)
class TestMatchDDEBs(TestCase): """Tests that NascentUpload correctly links DEBs to their DDEBs. Also verifies detection of DDEB-related error cases. """ layer = LaunchpadZopelessLayer def setUp(self): super(TestMatchDDEBs, self).setUp() self.changes = FakeChangesFile() self.upload = NascentUpload(self.changes, None, DevNullLogger()) def addFile(self, filename, comp_and_section='main/devel', priority='extra'): """Add a file of the right type to the upload.""" package, cls = determine_file_class_and_name(filename) file = cls(filename, None, 100, comp_and_section, priority, package, '666', self.changes, None, self.upload.logger) self.changes.files.append(file) return file def assertMatchDDEBErrors(self, error_list): self.assertEqual(error_list, [str(e) for e in self.upload._matchDDEBs()]) def testNoLinksWithNoBinaries(self): # No links will be made if there are no binaries whatsoever. self.addFile('something_1.0.diff.gz') self.assertMatchDDEBErrors([]) def testNoLinksWithJustDEBs(self): # No links will be made if there are no DDEBs. self.addFile('blah_1.0_all.deb') self.addFile('libblah_1.0_i386.deb') self.assertMatchDDEBErrors([]) for file in self.changes.files: self.assertIs(None, file.ddeb_file) def testLinksMatchingDDEBs(self): # DDEBs will be linked to their matching DEBs. self.addFile('blah_1.0_all.deb') self.addFile('libblah_1.0_i386.deb') self.addFile('libblah-dbgsym_1.0_i386.ddeb') self.addFile('libfooble_1.0_i386.udeb') self.addFile('libfooble-dbgsym_1.0_i386.ddeb') self.assertMatchDDEBErrors([]) self.assertIs(None, self.changes.files[0].ddeb_file) self.assertIs(self.changes.files[2], self.changes.files[1].ddeb_file) self.assertIs(self.changes.files[1], self.changes.files[2].deb_file) self.assertIs(None, self.changes.files[2].ddeb_file) def testDuplicateDDEBsCauseErrors(self): # An error will be raised if a DEB has more than one matching # DDEB. self.addFile('libblah_1.0_i386.deb') self.addFile('libblah-dbgsym_1.0_i386.ddeb') self.addFile('libblah-dbgsym_1.0_i386.ddeb') self.assertMatchDDEBErrors( ['Duplicated debug packages: libblah-dbgsym 666 (i386)']) def testMismatchedDDEBsCauseErrors(self): # An error will be raised if a DDEB has no matching DEB. self.addFile('libblah_1.0_i386.deb') self.addFile('libblah-dbgsym_1.0_amd64.ddeb') self.assertMatchDDEBErrors( ['Orphaned debug packages: libblah-dbgsym 666 (amd64)'])
def setUp(self): super(TestMatchDDEBs, self).setUp() self.changes = FakeChangesFile() self.upload = NascentUpload(self.changes, None, DevNullLogger())
class TestMatchDDEBs(TestCase): """Tests that NascentUpload correctly links DEBs to their DDEBs. Also verifies detection of DDEB-related error cases. """ layer = LaunchpadZopelessLayer def setUp(self): super(TestMatchDDEBs, self).setUp() self.changes = FakeChangesFile() self.upload = NascentUpload(self.changes, None, DevNullLogger()) def addFile(self, filename, comp_and_section="main/devel", priority="extra"): """Add a file of the right type to the upload.""" package, cls = determine_file_class_and_name(filename) file = cls( filename, None, 100, comp_and_section, priority, package, "666", self.changes, None, self.upload.logger ) self.changes.files.append(file) return file def assertMatchDDEBErrors(self, error_list): self.assertEquals(error_list, [str(e) for e in self.upload._matchDDEBs()]) def testNoLinksWithNoBinaries(self): # No links will be made if there are no binaries whatsoever. self.addFile("something_1.0.diff.gz") self.assertMatchDDEBErrors([]) def testNoLinksWithJustDEBs(self): # No links will be made if there are no DDEBs. self.addFile("blah_1.0_all.deb") self.addFile("libblah_1.0_i386.deb") self.assertMatchDDEBErrors([]) for file in self.changes.files: self.assertIs(None, file.ddeb_file) def testLinksMatchingDDEBs(self): # DDEBs will be linked to their matching DEBs. self.addFile("blah_1.0_all.deb") self.addFile("libblah_1.0_i386.deb") self.addFile("libblah-dbgsym_1.0_i386.ddeb") self.addFile("libfooble_1.0_i386.udeb") self.addFile("libfooble-dbgsym_1.0_i386.ddeb") self.assertMatchDDEBErrors([]) self.assertIs(None, self.changes.files[0].ddeb_file) self.assertIs(self.changes.files[2], self.changes.files[1].ddeb_file) self.assertIs(self.changes.files[1], self.changes.files[2].deb_file) self.assertIs(None, self.changes.files[2].ddeb_file) def testDuplicateDDEBsCauseErrors(self): # An error will be raised if a DEB has more than one matching # DDEB. self.addFile("libblah_1.0_i386.deb") self.addFile("libblah-dbgsym_1.0_i386.ddeb") self.addFile("libblah-dbgsym_1.0_i386.ddeb") self.assertMatchDDEBErrors(["Duplicated debug packages: libblah-dbgsym 666 (i386)"]) def testMismatchedDDEBsCauseErrors(self): # An error will be raised if a DDEB has no matching DEB. self.addFile("libblah_1.0_i386.deb") self.addFile("libblah-dbgsym_1.0_amd64.ddeb") self.assertMatchDDEBErrors(["Orphaned debug packages: libblah-dbgsym 666 (amd64)"])
def getUploadForBinary(upload_path): """Return a NascentUpload object for binaries.""" policy = getPolicy(name='sync', distro='ubuntu', distroseries='hoary') policy.accepted_type = ArchiveUploadType.BINARY_ONLY return NascentUpload.from_changesfile_path( datadir(upload_path), policy, DevNullLogger())
def getPPAUploadForSource(upload_path, ppa): """Return a NascentUpload object for a PPA source.""" policy = getPolicy(name='insecure', distro='ubuntu', distroseries='hoary') policy.archive = ppa return NascentUpload.from_changesfile_path( datadir(upload_path), policy, DevNullLogger())
def getUploadForSource(upload_path): """Return a NascentUpload object for a source.""" policy = getPolicy(name='sync', distro='ubuntu', distroseries='hoary') return NascentUpload.from_changesfile_path( datadir(upload_path), policy, DevNullLogger())
def test_rejects_misspelled_changesfile_name(self): upload = NascentUpload.from_changesfile_path( datadir("ddtp-tarball/translations-main_20060728.changes"), self.absolutely_anything_policy, self.logger) self.assertRaises(EarlyReturnUploadError, upload.process)
def test_rejects_misspelled_changesfile_name(self): upload = NascentUpload.from_changesfile_path( datadir("ddtp-tarball/translations-main_20060728.changes"), self.absolutely_anything_policy, self.logger ) self.assertRaises(EarlyReturnUploadError, upload.process)
def processChangesFile(self, changes_file, logger=None): """Process a single changes file. This is done by obtaining the appropriate upload policy (according to command-line options and the value in the .distro file beside the upload, if present), creating a NascentUpload object and calling its process method. We obtain the context for this processing from the relative path, within the upload folder, of this changes file. This influences our creation both of upload policy and the NascentUpload object. See nascentupload.py for the gory details. Returns a value from UploadStatusEnum, or re-raises an exception from NascentUpload. :param changes_file: filename of the changes file to process. :param logger: logger to use for processing. :return: an `UploadStatusEnum` value """ if logger is None: logger = self.processor.log # Calculate the distribution from the path within the upload # Reject the upload since we could not process the path, # Store the exception information as a rejection message. relative_path = os.path.dirname(changes_file) upload_path_error = None try: (distribution, suite_name, archive) = parse_upload_path(relative_path) except UploadPathError as e: # pick some defaults to create the NascentUpload() object. # We will be rejecting the upload so it doesn matter much. distribution = getUtility(IDistributionSet)['ubuntu'] suite_name = None archive = distribution.main_archive upload_path_error = UPLOAD_PATH_ERROR_TEMPLATE % (dict( upload_path=relative_path, path_error=str(e), extra_info=("Please update your dput/dupload configuration " "and then re-upload."))) except PPAUploadPathError as e: # Again, pick some defaults but leave a hint for the rejection # emailer that it was a PPA failure. distribution = getUtility(IDistributionSet)['ubuntu'] suite_name = None # XXX cprov 20071212: using the first available PPA is not exactly # fine because it can confuse the code that sends rejection # messages if it relies only on archive.purpose (which should be # enough). On the other hand if we set an arbitrary owner it # will break nascentupload ACL calculations. archive = distribution.getAllPPAs()[0] upload_path_error = UPLOAD_PATH_ERROR_TEMPLATE % (dict( upload_path=relative_path, path_error=str(e), extra_info=( "Please check the documentation at " "https://help.launchpad.net/Packaging/PPA#Uploading " "and update your configuration."))) logger.debug("Finding fresh policy") policy = self._getPolicyForDistro(distribution) policy.archive = archive # DistroSeries overriding respect the following precedence: # 1. process-upload.py command-line option (-r), # 2. upload path, # 3. changesfile 'Distribution' field. if suite_name is not None: policy.setDistroSeriesAndPocket(suite_name) # The path we want for NascentUpload is the path to the folder # containing the changes file (and the other files referenced by it). changesfile_path = os.path.join(self.upload_path, changes_file) try: upload = NascentUpload.from_changesfile_path( changesfile_path, policy, self.processor.log) except UploadError as e: # We failed to parse the changes file, so we have no key or # Changed-By to notify of the rejection. Just log it and # move on. # XXX wgrant 2011-09-29 bug=499438: With some refactoring we # could do better here: if we have a signature then we have # somebody to email, even if the rest of the file is # corrupt. logger.info("Failed to parse changes file '%s': %s" % (os.path.join(self.upload_path, changes_file), str(e))) return UploadStatusEnum.REJECTED # Reject source upload to buildd upload paths. first_path = relative_path.split(os.path.sep)[0] if (first_path.isdigit() and policy.name != BuildDaemonUploadPolicy.name): error_message = ("Invalid upload path (%s) for this policy (%s)" % (relative_path, policy.name)) upload.reject(error_message) logger.error(error_message) # Reject upload with path processing errors. if upload_path_error is not None: upload.reject(upload_path_error) # Store processed NascentUpload instance, mostly used for tests. self.processor.last_processed_upload = upload try: logger.info("Processing upload %s" % upload.changes.filename) result = UploadStatusEnum.ACCEPTED try: self._processUpload(upload) except UploadPolicyError as e: upload.reject("UploadPolicyError escaped upload.process: " "%s " % e) logger.debug("UploadPolicyError escaped upload.process", exc_info=True) except (KeyboardInterrupt, SystemExit): raise except EarlyReturnUploadError: # An error occurred that prevented further error collection, # add this fact to the list of errors. upload.reject( "Further error processing not possible because of " "a critical previous error.") except Exception as e: # In case of unexpected unhandled exception, we'll # *try* to reject the upload. This may fail and cause # a further exception, depending on the state of the # nascentupload objects. In that case, we've lost nothing, # the new exception will be handled by the caller just like # the one we caught would have been, by failing the upload # with no email. logger.exception("Unhandled exception processing upload") upload.reject("Unhandled exception processing upload: %s" % e) # XXX julian 2007-05-25 bug=29744: # When bug #29744 is fixed (zopeless mails should only be sent # when transaction is committed) this will cause any emails sent # sent by do_reject to be lost. notify = True if self.processor.dry_run or self.processor.no_mails: notify = False if upload.is_rejected: result = UploadStatusEnum.REJECTED upload.do_reject(notify) self.processor.ztm.abort() else: successful = self._acceptUpload(upload, notify) if not successful: result = UploadStatusEnum.REJECTED logger.info( "Rejection during accept. Aborting partial accept.") self.processor.ztm.abort() if upload.is_rejected: logger.info("Upload was rejected:") for msg in upload.rejections: logger.info("\t%s" % msg) if self.processor.dry_run: logger.info("Dry run, aborting transaction.") self.processor.ztm.abort() else: logger.info( "Committing the transaction and any mails associated " "with this upload.") self.processor.ztm.commit() except: self.processor.ztm.abort() raise return result
def processChangesFile(self, changes_file, logger=None): """Process a single changes file. This is done by obtaining the appropriate upload policy (according to command-line options and the value in the .distro file beside the upload, if present), creating a NascentUpload object and calling its process method. We obtain the context for this processing from the relative path, within the upload folder, of this changes file. This influences our creation both of upload policy and the NascentUpload object. See nascentupload.py for the gory details. Returns a value from UploadStatusEnum, or re-raises an exception from NascentUpload. :param changes_file: filename of the changes file to process. :param logger: logger to use for processing. :return: an `UploadStatusEnum` value """ if logger is None: logger = self.processor.log # Calculate the distribution from the path within the upload # Reject the upload since we could not process the path, # Store the exception information as a rejection message. relative_path = os.path.dirname(changes_file) upload_path_error = None try: (distribution, suite_name, archive) = parse_upload_path(relative_path) except UploadPathError as e: # pick some defaults to create the NascentUpload() object. # We will be rejecting the upload so it doesn matter much. distribution = getUtility(IDistributionSet)['ubuntu'] suite_name = None archive = distribution.main_archive upload_path_error = UPLOAD_PATH_ERROR_TEMPLATE % ( dict(upload_path=relative_path, path_error=str(e), extra_info=( "Please update your dput/dupload configuration " "and then re-upload."))) except PPAUploadPathError as e: # Again, pick some defaults but leave a hint for the rejection # emailer that it was a PPA failure. distribution = getUtility(IDistributionSet)['ubuntu'] suite_name = None # XXX cprov 20071212: using the first available PPA is not exactly # fine because it can confuse the code that sends rejection # messages if it relies only on archive.purpose (which should be # enough). On the other hand if we set an arbitrary owner it # will break nascentupload ACL calculations. archive = distribution.getAllPPAs()[0] upload_path_error = UPLOAD_PATH_ERROR_TEMPLATE % ( dict(upload_path=relative_path, path_error=str(e), extra_info=( "Please check the documentation at " "https://help.launchpad.net/Packaging/PPA#Uploading " "and update your configuration."))) logger.debug("Finding fresh policy") policy = self._getPolicyForDistro(distribution) policy.archive = archive # DistroSeries overriding respect the following precedence: # 1. process-upload.py command-line option (-r), # 2. upload path, # 3. changesfile 'Distribution' field. if suite_name is not None: policy.setDistroSeriesAndPocket(suite_name) # The path we want for NascentUpload is the path to the folder # containing the changes file (and the other files referenced by it). changesfile_path = os.path.join(self.upload_path, changes_file) try: upload = NascentUpload.from_changesfile_path( changesfile_path, policy, self.processor.log) except UploadError as e: # We failed to parse the changes file, so we have no key or # Changed-By to notify of the rejection. Just log it and # move on. # XXX wgrant 2011-09-29 bug=499438: With some refactoring we # could do better here: if we have a signature then we have # somebody to email, even if the rest of the file is # corrupt. logger.info( "Failed to parse changes file '%s': %s" % ( os.path.join(self.upload_path, changes_file), str(e))) return UploadStatusEnum.REJECTED # Reject source upload to buildd upload paths. first_path = relative_path.split(os.path.sep)[0] if (first_path.isdigit() and policy.name != BuildDaemonUploadPolicy.name): error_message = ( "Invalid upload path (%s) for this policy (%s)" % (relative_path, policy.name)) upload.reject(error_message) logger.error(error_message) # Reject upload with path processing errors. if upload_path_error is not None: upload.reject(upload_path_error) # Store processed NascentUpload instance, mostly used for tests. self.processor.last_processed_upload = upload try: logger.info("Processing upload %s" % upload.changes.filename) result = UploadStatusEnum.ACCEPTED try: self._processUpload(upload) except UploadPolicyError as e: upload.reject("UploadPolicyError escaped upload.process: " "%s " % e) logger.debug( "UploadPolicyError escaped upload.process", exc_info=True) except (KeyboardInterrupt, SystemExit): raise except EarlyReturnUploadError: # An error occurred that prevented further error collection, # add this fact to the list of errors. upload.reject( "Further error processing not possible because of " "a critical previous error.") except Exception as e: # In case of unexpected unhandled exception, we'll # *try* to reject the upload. This may fail and cause # a further exception, depending on the state of the # nascentupload objects. In that case, we've lost nothing, # the new exception will be handled by the caller just like # the one we caught would have been, by failing the upload # with no email. logger.exception("Unhandled exception processing upload") upload.reject("Unhandled exception processing upload: %s" % e) # XXX julian 2007-05-25 bug=29744: # When bug #29744 is fixed (zopeless mails should only be sent # when transaction is committed) this will cause any emails sent # sent by do_reject to be lost. notify = True if self.processor.dry_run or self.processor.no_mails: notify = False if upload.is_rejected: result = UploadStatusEnum.REJECTED upload.do_reject(notify) self.processor.ztm.abort() else: successful = self._acceptUpload(upload, notify) if not successful: result = UploadStatusEnum.REJECTED logger.info( "Rejection during accept. Aborting partial accept.") self.processor.ztm.abort() if upload.is_rejected: logger.info("Upload was rejected:") for msg in upload.rejections: logger.info("\t%s" % msg) if self.processor.dry_run: logger.info("Dry run, aborting transaction.") self.processor.ztm.abort() else: logger.info( "Committing the transaction and any mails associated " "with this upload.") self.processor.ztm.commit() except: self.processor.ztm.abort() raise return result