+def try_or_reject(function):
+ """Try to call function or reject the upload if that fails
+ """
+ def wrapper(directory, upload, *args, **kwargs):
+ try:
+ return function(directory, upload, *args, **kwargs)
+ except Exception as e:
+ try:
+ reason = "There was an uncaught exception when processing your upload:\n{0}\nAny original reject reason follows below.".format(traceback.format_exc())
+ upload.rollback()
+ return real_reject(directory, upload, reason=reason)
+ except Exception as e:
+ reason = "In addition there was an exception when rejecting the package:\n{0}\nPrevious reasons:\n{1}".format(traceback.format_exc(), reason)
+ upload.rollback()
+ return real_reject(directory, upload, reason=reason, notify=False)
+
+ return wrapper
+
+def subst_for_upload(upload):
+ cnf = Config()
+
+ changes = upload.changes
+ control = upload.changes.changes
+
+ if upload.final_suites is None or len(upload.final_suites) == 0:
+ suite_name = '(unknown)'
+ else:
+ suite_names = []
+ for suite in upload.final_suites:
+ if suite.policy_queue:
+ suite_names.append("{0}->{1}".format(suite.suite_name, suite.policy_queue.queue_name))
+ else:
+ suite_names.append(suite.suite_name)
+ suite_name = ','.join(suite_names)
+
+ maintainer_field = control.get('Maintainer', cnf['Dinstall::MyEmailAddress'])
+ changed_by_field = control.get('Changed-By', maintainer_field)
+ maintainer = fix_maintainer(changed_by_field)
+ if upload.changes.source is not None:
+ addresses = utils.mail_addresses_for_upload(maintainer_field, changed_by_field, changes.primary_fingerprint)
+ else:
+ addresses = utils.mail_addresses_for_upload(maintainer_field, maintainer_field, changes.primary_fingerprint)
+
+ bcc = 'X-DAK: dak process-upload'
+ if 'Dinstall::Bcc' in cnf:
+ bcc = '{0}\nBcc: {1}'.format(bcc, cnf['Dinstall::Bcc'])
+
+ subst = {
+ '__DISTRO__': cnf['Dinstall::MyDistribution'],
+ '__ADMIN_ADDRESS__': cnf['Dinstall::MyAdminAddress'],
+
+ '__CHANGES_FILENAME__': upload.changes.filename,
+
+ '__SOURCE__': control.get('Source', '(unknown)'),
+ '__ARCHITECTURE__': control.get('Architecture', '(unknown)'),
+ '__VERSION__': control.get('Version', '(unknown)'),
+
+ '__SUITE__': suite_name,
+
+ '__DAK_ADDRESS__': cnf['Dinstall::MyEmailAddress'],
+ '__MAINTAINER_FROM__': maintainer[1],
+ '__MAINTAINER_TO__': ", ".join(addresses),
+ '__MAINTAINER__': changed_by_field,
+ '__BCC__': bcc,
+
+ '__BUG_SERVER__': cnf.get('Dinstall::BugServer'),
+
+ '__FILE_CONTENTS__': open(upload.changes.path, 'r').read(),
+ }
+
+ override_maintainer = cnf.get('Dinstall::OverrideMaintainer')
+ if override_maintainer:
+ subst['__MAINTAINER_TO__'] = subst['__MAINTAINER_FROM__'] = override_maintainer
+
+ return subst
+
+@try_or_reject
+def accept(directory, upload):
+ cnf = Config()
+
+ Logger.log(['ACCEPT', upload.changes.filename])
+
+ upload.install()
+
+ accepted_to_real_suite = False
+ for suite in upload.final_suites:
+ accepted_to_real_suite = accepted_to_real_suite or suite.policy_queue is None
+
+ sourceful_upload = 'source' in upload.changes.architectures
+
+ control = upload.changes.changes
+ if sourceful_upload and not Options['No-Action']:
+ urgency = control.get('Urgency')
+ if urgency not in cnf.value_list('Urgency::Valid'):
+ urgency = cnf['Urgency::Default']
+ UrgencyLog().log(control['Source'], control['Version'], urgency)
+
+ # send mail to maintainer
+ subst = subst_for_upload(upload)
+ message = utils.TemplateSubst(subst, os.path.join(cnf['Dir::Templates'], 'process-unchecked.accepted'))
+ utils.send_mail(message)
+
+ # send mail to announce lists and tracking server
+ if accepted_to_real_suite and sourceful_upload:
+ subst = subst_for_upload(upload)
+ announce = set()
+ for suite in upload.final_suites:
+ if suite.policy_queue is not None:
+ continue
+ announce.update(suite.announce or [])
+ announce_address = ", ".join(announce)
+
+ tracking = cnf.get('Dinstall::TrackingServer')
+ if tracking and 'source' in upload.changes.architectures:
+ announce_address = '{0}\nBcc: {1}@{2}'.format(announce_address, control['Source'], tracking)
+
+ subst['__ANNOUNCE_LIST_ADDRESS__'] = announce_address
+
+ message = utils.TemplateSubst(subst, os.path.join(cnf['Dir::Templates'], 'process-unchecked.announce'))
+ utils.send_mail(message)
+
+ # Only close bugs for uploads that were not redirected to a policy queue.
+ # process-policy will close bugs for those once they are accepted.
+ subst = subst_for_upload(upload)
+ if accepted_to_real_suite and cnf.find_b('Dinstall::CloseBugs') and sourceful_upload:
+ for bugnum in upload.changes.closed_bugs:
+ subst['__BUG_NUMBER__'] = str(bugnum)
+
+ message = utils.TemplateSubst(subst, os.path.join(cnf['Dir::Templates'], 'process-unchecked.bug-close'))
+ utils.send_mail(message)
+
+ del subst['__BUG_NUMBER__']
+
+ # Move .changes to done, but only for uploads that were accepted to a
+ # real suite. process-policy will handle this for uploads to queues.
+ if accepted_to_real_suite:
+ src = os.path.join(upload.directory, upload.changes.filename)
+
+ now = datetime.datetime.now()
+ donedir = os.path.join(cnf['Dir::Done'], now.strftime('%Y/%m/%d'))
+ dst = os.path.join(donedir, upload.changes.filename)
+ dst = utils.find_next_free(dst)
+
+ upload.transaction.fs.copy(src, dst, mode=0o644)
+
+ SummaryStats().accept_count += 1
+ SummaryStats().accept_bytes += upload.changes.bytes
+
+@try_or_reject
+def accept_to_new(directory, upload):
+ cnf = Config()
+
+ Logger.log(['ACCEPT-TO-NEW', upload.changes.filename])