queue.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. # vim:set et sw=4:
  2. """
  3. Queue utility functions for dak
  4. @contact: Debian FTP Master <ftpmaster@debian.org>
  5. @copyright: 2001 - 2006 James Troup <james@nocrew.org>
  6. @copyright: 2009, 2010 Joerg Jaspert <joerg@debian.org>
  7. @license: GNU General Public License version 2 or later
  8. """
  9. # This program is free software; you can redistribute it and/or modify
  10. # it under the terms of the GNU General Public License as published by
  11. # the Free Software Foundation; either version 2 of the License, or
  12. # (at your option) any later version.
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU General Public License for more details.
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program; if not, write to the Free Software
  19. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. ###############################################################################
  21. from . import utils
  22. from .regexes import *
  23. from .config import Config
  24. from .dbconn import *
  25. ################################################################################
  26. def check_valid(overrides: list[dict], session) -> bool:
  27. """Check if section and priority for new overrides exist in database.
  28. Additionally does sanity checks:
  29. - debian-installer packages have to be udeb (or source)
  30. - non debian-installer packages cannot be udeb
  31. :param overrides: list of overrides to check. The overrides need
  32. to be given in form of a dict with the following keys:
  33. - package: package name
  34. - priority
  35. - section
  36. - component
  37. - type: type of requested override ('dsc', 'deb' or 'udeb')
  38. All values are strings.
  39. :return: :const:`True` if all overrides are valid, :const:`False` if there is any
  40. invalid override.
  41. """
  42. all_valid = True
  43. for o in overrides:
  44. o['valid'] = True
  45. if session.query(Priority).filter_by(priority=o['priority']).first() is None:
  46. o['valid'] = False
  47. if session.query(Section).filter_by(section=o['section']).first() is None:
  48. o['valid'] = False
  49. if get_mapped_component(o['component'], session) is None:
  50. o['valid'] = False
  51. if o['type'] not in ('dsc', 'deb', 'udeb'):
  52. raise Exception('Unknown override type {0}'.format(o['type']))
  53. if o['type'] == 'udeb' and o['section'].split('/', 1)[-1] != 'debian-installer':
  54. o['valid'] = False
  55. if o['section'].split('/', 1)[-1] == 'debian-installer' and o['type'] not in ('dsc', 'udeb'):
  56. o['valid'] = False
  57. all_valid = all_valid and o['valid']
  58. return all_valid
  59. ###############################################################################
  60. def prod_maintainer(notes, upload: PolicyQueueUpload, session, trainee=False):
  61. cnf = Config()
  62. changes = upload.changes
  63. whitelists = [upload.target_suite.mail_whitelist]
  64. # Here we prepare an editor and get them ready to prod...
  65. prod_message = "\n\n=====\n\n".join([note.comment for note in notes])
  66. answer = 'E'
  67. while answer == 'E':
  68. prod_message = utils.call_editor(prod_message)
  69. print("Prod message:")
  70. print(utils.prefix_multi_line_string(prod_message, " ", include_blank_lines=True))
  71. prompt = "[P]rod, Edit, Abandon, Quit ?"
  72. answer = "XXX"
  73. while prompt.find(answer) == -1:
  74. answer = utils.input_or_exit(prompt)
  75. m = re_default_answer.search(prompt)
  76. if answer == "":
  77. answer = m.group(1)
  78. answer = answer[:1].upper()
  79. if answer == 'A':
  80. return
  81. elif answer == 'Q':
  82. return 0
  83. # Otherwise, do the proding...
  84. user_email_address = utils.whoami() + " <%s>" % (
  85. cnf["Dinstall::MyAdminAddress"])
  86. changed_by = changes.changedby or changes.maintainer
  87. maintainer = changes.maintainer
  88. maintainer_to = utils.mail_addresses_for_upload(maintainer, changed_by, changes.fingerprint)
  89. Subst = {
  90. '__SOURCE__': upload.changes.source,
  91. '__VERSION__': upload.changes.version,
  92. '__ARCHITECTURE__': upload.changes.architecture,
  93. '__CHANGES_FILENAME__': upload.changes.changesname,
  94. '__MAINTAINER_TO__': ", ".join(maintainer_to),
  95. }
  96. Subst["__FROM_ADDRESS__"] = user_email_address
  97. Subst["__PROD_MESSAGE__"] = prod_message
  98. Subst["__CC__"] = "Cc: " + cnf["Dinstall::MyEmailAddress"]
  99. prod_mail_message = utils.TemplateSubst(
  100. Subst, cnf["Dir::Templates"] + "/process-new.prod")
  101. # Send the prod mail
  102. utils.send_mail(prod_mail_message, whitelists=whitelists)
  103. print("Sent prodding message")
  104. answer = utils.input_or_exit("Store prod message as note? (Y/n)?").lower()
  105. if answer != "n":
  106. comment = NewComment()
  107. comment.policy_queue = upload.policy_queue
  108. comment.package = upload.changes.source
  109. comment.version = upload.changes.version
  110. comment.comment = prod_mail_message
  111. comment.author = utils.whoami()
  112. comment.trainee = trainee
  113. session.add(comment)
  114. session.commit()
  115. ################################################################################
  116. def edit_note(note, upload, session, trainee=False):
  117. newnote = ""
  118. answer = 'E'
  119. while answer == 'E':
  120. newnote = utils.call_editor(newnote).rstrip()
  121. print("New Note:")
  122. print(utils.prefix_multi_line_string(newnote, " "))
  123. empty_note = not newnote.strip()
  124. if empty_note:
  125. prompt = "Done, Edit, [A]bandon, Quit ?"
  126. else:
  127. prompt = "[D]one, Edit, Abandon, Quit ?"
  128. answer = "XXX"
  129. while prompt.find(answer) == -1:
  130. answer = utils.input_or_exit(prompt)
  131. m = re_default_answer.search(prompt)
  132. if answer == "":
  133. answer = m.group(1)
  134. answer = answer[:1].upper()
  135. if answer == 'A':
  136. return
  137. elif answer == 'Q':
  138. return 0
  139. comment = NewComment()
  140. comment.policy_queue = upload.policy_queue
  141. comment.package = upload.changes.source
  142. comment.version = upload.changes.version
  143. comment.comment = newnote
  144. comment.author = utils.whoami()
  145. comment.trainee = trainee
  146. session.add(comment)
  147. session.commit()
  148. ###############################################################################
  149. def get_suite_version_by_source(source: str, session) -> list[tuple[str, str]]:
  150. 'returns a list of tuples (suite_name, version) for source package'
  151. q = session.query(Suite.suite_name, DBSource.version). \
  152. join(Suite.sources).filter_by(source=source)
  153. return q.all()
  154. def get_suite_version_by_package(package: str, arch_string: str, session) -> list[tuple[str, str]]:
  155. '''
  156. returns a list of tuples (suite_name, version) for binary package and
  157. arch_string
  158. '''
  159. return session.query(Suite.suite_name, DBBinary.version). \
  160. join(Suite.binaries).filter_by(package=package). \
  161. join(DBBinary.architecture). \
  162. filter(Architecture.arch_string.in_([arch_string, 'all'])).all()