2 # vim:set et ts=4 sw=4:
4 """ Handles NEW and BYHAND packages
6 @contact: Debian FTP Master <ftpmaster@debian.org>
7 @copyright: 2001, 2002, 2003, 2004, 2005, 2006 James Troup <james@nocrew.org>
8 @copyright: 2009 Joerg Jaspert <joerg@debian.org>
9 @copyright: 2009 Frank Lichtenheld <djpig@debian.org>
10 @license: GNU General Public License version 2 or later
12 # This program is free software; you can redistribute it and/or modify
13 # it under the terms of the GNU General Public License as published by
14 # the Free Software Foundation; either version 2 of the License, or
15 # (at your option) any later version.
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # GNU General Public License for more details.
22 # You should have received a copy of the GNU General Public License
23 # along with this program; if not, write to the Free Software
24 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 ################################################################################
28 # 23:12|<aj> I will not hush!
30 # 23:12|<aj> Where there is injustice in the world, I shall be there!
31 # 23:13|<aj> I shall not be silenced!
32 # 23:13|<aj> The world shall know!
33 # 23:13|<aj> The world *must* know!
34 # 23:13|<elmo> oh dear, he's gone back to powerpuff girls... ;-)
35 # 23:13|<aj> yay powerpuff girls!!
36 # 23:13|<aj> buttercup's my favourite, who's yours?
37 # 23:14|<aj> you're backing away from the keyboard right now aren't you?
38 # 23:14|<aj> *AREN'T YOU*?!
39 # 23:15|<aj> I will not be treated like this.
40 # 23:15|<aj> I shall have my revenge.
41 # 23:15|<aj> I SHALL!!!
43 ################################################################################
45 from __future__ import with_statement
56 import apt_pkg, apt_inst
57 import examine_package
59 from daklib.dbconn import *
60 from daklib.queue import *
61 from daklib import daklog
62 from daklib import utils
63 from daklib.regexes import re_no_epoch, re_default_answer, re_isanum
64 from daklib.dak_exceptions import CantOpenError, AlreadyLockedError, CantGetLockError
65 from daklib.summarystats import SummaryStats
66 from daklib.config import Config
75 ################################################################################
76 ################################################################################
77 ################################################################################
79 def recheck(upload, session):
80 files = upload.pkg.files
83 for f in files.keys():
84 # The .orig.tar.gz can disappear out from under us is it's a
85 # duplicate of one in the archive.
86 if not files.has_key(f):
88 # Check that the source still exists
89 if files[f]["type"] == "deb":
90 source_version = files[f]["source version"]
91 source_package = files[f]["source package"]
92 if not upload.pkg.changes["architecture"].has_key("source") \
93 and not upload.source_exists(source_package, source_version, upload.pkg.changes["distribution"].keys()):
94 source_epochless_version = re_no_epoch.sub('', source_version)
95 dsc_filename = "%s_%s.dsc" % (source_package, source_epochless_version)
97 for q in ["Accepted", "Embargoed", "Unembargoed", "Newstage"]:
98 if cnf.has_key("Dir::Queue::%s" % (q)):
99 if os.path.exists(cnf["Dir::Queue::%s" % (q)] + '/' + dsc_filename):
102 upload.rejects.append("no source found for %s %s (%s)." % (source_package, source_version, f))
104 # Version and file overwrite checks
105 if files[f]["type"] == "deb":
106 upload.check_binary_against_db(f, session)
107 elif files[f]["type"] == "dsc":
108 upload.check_source_against_db(f, session)
109 upload.check_dsc_against_db(f, session)
111 if len(upload.rejects) > 0:
113 if Options["No-Action"] or Options["Automatic"] or Options["Trainee"]:
116 print "REJECT\n%s" % '\n'.join(upload.rejects)
117 prompt = "[R]eject, Skip, Quit ?"
119 while prompt.find(answer) == -1:
120 answer = utils.our_raw_input(prompt)
121 m = re_default_answer.match(prompt)
124 answer = answer[:1].upper()
127 upload.do_reject(manual=0, reject_message='\n'.join(upload.rejects))
128 os.unlink(upload.pkg.changes_file[:-8]+".dak")
138 ################################################################################
140 def indiv_sg_compare (a, b):
141 """Sort by source name, source, version, 'have source', and
142 finally by filename."""
143 # Sort by source version
144 q = apt_pkg.VersionCompare(a["version"], b["version"])
148 # Sort by 'have source'
149 a_has_source = a["architecture"].get("source")
150 b_has_source = b["architecture"].get("source")
151 if a_has_source and not b_has_source:
153 elif b_has_source and not a_has_source:
156 return cmp(a["filename"], b["filename"])
158 ############################################################
160 def sg_compare (a, b):
163 """Sort by have note, source already in database and time of oldest upload."""
165 a_note_state = a["note_state"]
166 b_note_state = b["note_state"]
167 if a_note_state < b_note_state:
169 elif a_note_state > b_note_state:
171 # Sort by source already in database (descending)
172 source_in_database = cmp(a["source_in_database"], b["source_in_database"])
173 if source_in_database:
174 return -source_in_database
176 # Sort by time of oldest upload
177 return cmp(a["oldest"], b["oldest"])
179 def sort_changes(changes_files, session):
180 """Sort into source groups, then sort each source group by version,
181 have source, filename. Finally, sort the source groups by have
182 note, time of oldest upload of each source upload."""
183 if len(changes_files) == 1:
188 # Read in all the .changes files
189 for filename in changes_files:
192 u.pkg.load_dot_dak(filename)
194 cache[filename] = copy.copy(u.pkg.changes)
195 cache[filename]["filename"] = filename
197 sorted_list.append(filename)
199 # Divide the .changes into per-source groups
201 for filename in cache.keys():
202 source = cache[filename]["source"]
203 if not per_source.has_key(source):
204 per_source[source] = {}
205 per_source[source]["list"] = []
206 per_source[source]["list"].append(cache[filename])
207 # Determine oldest time and have note status for each source group
208 for source in per_source.keys():
209 q = session.query(DBSource).filter_by(source = source).all()
210 per_source[source]["source_in_database"] = len(q)>0
211 source_list = per_source[source]["list"]
212 first = source_list[0]
213 oldest = os.stat(first["filename"])[stat.ST_MTIME]
215 for d in per_source[source]["list"]:
216 mtime = os.stat(d["filename"])[stat.ST_MTIME]
219 have_note += has_new_comment(d["source"], d["version"], session)
220 per_source[source]["oldest"] = oldest
222 per_source[source]["note_state"] = 0; # none
223 elif have_note < len(source_list):
224 per_source[source]["note_state"] = 1; # some
226 per_source[source]["note_state"] = 2; # all
227 per_source[source]["list"].sort(indiv_sg_compare)
228 per_source_items = per_source.items()
229 per_source_items.sort(sg_compare)
230 for i in per_source_items:
231 for j in i[1]["list"]:
232 sorted_list.append(j["filename"])
235 ################################################################################
237 class Section_Completer:
238 def __init__ (self, session):
241 for s, in session.query(Section.section):
242 self.sections.append(s)
244 def complete(self, text, state):
248 for word in self.sections:
250 self.matches.append(word)
252 return self.matches[state]
256 ############################################################
258 class Priority_Completer:
259 def __init__ (self, session):
262 for p, in session.query(Priority.priority):
263 self.priorities.append(p)
265 def complete(self, text, state):
269 for word in self.priorities:
271 self.matches.append(word)
273 return self.matches[state]
277 ################################################################################
279 def print_new (new, upload, indexed, file=sys.stdout):
283 for pkg in new.keys():
285 section = new[pkg]["section"]
286 priority = new[pkg]["priority"]
287 if new[pkg]["section id"] == -1:
290 if new[pkg]["priority id"] == -1:
294 line = "(%s): %-20s %-20s %-20s" % (index, pkg, priority, section)
296 line = "%-20s %-20s %-20s" % (pkg, priority, section)
297 line = line.strip()+'\n'
299 notes = get_new_comments(upload.pkg.changes.get("source"))
301 print "\nAuthor: %s\nVersion: %s\nTimestamp: %s\n\n%s" \
302 % (note.author, note.version, note.notedate, note.comment)
304 return broken, len(notes) > 0
306 ################################################################################
308 def index_range (index):
312 return "1-%s" % (index)
314 ################################################################################
315 ################################################################################
317 def edit_new (new, upload):
318 # Write the current data to a temporary file
319 (fd, temp_filename) = utils.temp_filename()
320 temp_file = os.fdopen(fd, 'w')
321 print_new (new, upload, indexed=0, file=temp_file)
323 # Spawn an editor on that file
324 editor = os.environ.get("EDITOR","vi")
325 result = os.system("%s %s" % (editor, temp_filename))
327 utils.fubar ("%s invocation failed for %s." % (editor, temp_filename), result)
328 # Read the edited data back in
329 temp_file = utils.open_file(temp_filename)
330 lines = temp_file.readlines()
332 os.unlink(temp_filename)
339 # Pad the list if necessary
340 s[len(s):3] = [None] * (3-len(s))
341 (pkg, priority, section) = s[:3]
342 if not new.has_key(pkg):
343 utils.warn("Ignoring unknown package '%s'" % (pkg))
345 # Strip off any invalid markers, print_new will readd them.
346 if section.endswith("[!]"):
347 section = section[:-3]
348 if priority.endswith("[!]"):
349 priority = priority[:-3]
350 for f in new[pkg]["files"]:
351 upload.pkg.files[f]["section"] = section
352 upload.pkg.files[f]["priority"] = priority
353 new[pkg]["section"] = section
354 new[pkg]["priority"] = priority
356 ################################################################################
358 def edit_index (new, upload, index):
359 priority = new[index]["priority"]
360 section = new[index]["section"]
361 ftype = new[index]["type"]
364 print "\t".join([index, priority, section])
368 prompt = "[B]oth, Priority, Section, Done ? "
370 prompt = "[S]ection, Done ? "
371 edit_priority = edit_section = 0
373 while prompt.find(answer) == -1:
374 answer = utils.our_raw_input(prompt)
375 m = re_default_answer.match(prompt)
378 answer = answer[:1].upper()
385 edit_priority = edit_section = 1
391 readline.set_completer(Priorities.complete)
393 while not got_priority:
394 new_priority = utils.our_raw_input("New priority: ").strip()
395 if new_priority not in Priorities.priorities:
396 print "E: '%s' is not a valid priority, try again." % (new_priority)
399 priority = new_priority
403 readline.set_completer(Sections.complete)
405 while not got_section:
406 new_section = utils.our_raw_input("New section: ").strip()
407 if new_section not in Sections.sections:
408 print "E: '%s' is not a valid section, try again." % (new_section)
411 section = new_section
413 # Reset the readline completer
414 readline.set_completer(None)
416 for f in new[index]["files"]:
417 upload.pkg.files[f]["section"] = section
418 upload.pkg.files[f]["priority"] = priority
419 new[index]["priority"] = priority
420 new[index]["section"] = section
423 ################################################################################
425 def edit_overrides (new, upload, session):
429 print_new (new, upload, indexed=1)
436 prompt = "(%s) edit override <n>, Editor, Done ? " % (index_range(index))
439 while not got_answer:
440 answer = utils.our_raw_input(prompt)
441 if not answer.isdigit():
442 answer = answer[:1].upper()
443 if answer == "E" or answer == "D":
445 elif re_isanum.match (answer):
447 if (answer < 1) or (answer > index):
448 print "%s is not a valid index (%s). Please retry." % (answer, index_range(index))
453 edit_new(new, upload)
457 edit_index (new, upload, new_index[answer])
461 ################################################################################
463 def edit_note(note, upload, session):
464 # Write the current data to a temporary file
465 (fd, temp_filename) = utils.temp_filename()
466 editor = os.environ.get("EDITOR","vi")
469 os.system("%s %s" % (editor, temp_filename))
470 temp_file = utils.open_file(temp_filename)
471 newnote = temp_file.read().rstrip()
474 print utils.prefix_multi_line_string(newnote," ")
475 prompt = "[D]one, Edit, Abandon, Quit ?"
477 while prompt.find(answer) == -1:
478 answer = utils.our_raw_input(prompt)
479 m = re_default_answer.search(prompt)
482 answer = answer[:1].upper()
483 os.unlink(temp_filename)
490 comment = NewComment()
491 comment.package = upload.pkg.changes["source"]
492 comment.version = upload.pkg.changes["version"]
493 comment.comment = newnote
494 comment.author = utils.whoami()
495 comment.trainee = bool(Options["Trainee"])
499 ################################################################################
501 def check_pkg (upload):
503 less_fd = os.popen("less -R -", 'w', 0)
504 stdout_fd = sys.stdout
507 changes = utils.parse_changes (upload.pkg.changes_file)
508 examine_package.display_changes(changes['distribution'], upload.pkg.changes_file)
509 files = upload.pkg.files
510 for f in files.keys():
511 if files[f].has_key("new"):
512 ftype = files[f]["type"]
514 examine_package.check_deb(changes['distribution'], f)
516 examine_package.check_dsc(changes['distribution'], f)
518 examine_package.output_package_relations()
519 sys.stdout = stdout_fd
521 if e.errno == errno.EPIPE:
522 utils.warn("[examine_package] Caught EPIPE; skipping.")
526 except KeyboardInterrupt:
527 utils.warn("[examine_package] Caught C-c; skipping.")
530 ################################################################################
532 ## FIXME: horribly Debian specific
534 def do_bxa_notification(upload):
535 files = upload.pkg.files
537 for f in files.keys():
538 if files[f]["type"] == "deb":
539 control = apt_pkg.ParseSection(apt_inst.debExtractControl(utils.open_file(f)))
541 summary += "Package: %s\n" % (control.Find("Package"))
542 summary += "Description: %s\n" % (control.Find("Description"))
543 upload.Subst["__BINARY_DESCRIPTIONS__"] = summary
544 bxa_mail = utils.TemplateSubst(upload.Subst,Config()["Dir::Templates"]+"/process-new.bxa_notification")
545 utils.send_mail(bxa_mail)
547 ################################################################################
549 def add_overrides (new, upload, session):
550 changes = upload.pkg.changes
551 files = upload.pkg.files
552 srcpkg = changes.get("source")
554 for suite in changes["suite"].keys():
555 suite_id = get_suite(suite).suite_id
556 for pkg in new.keys():
557 component_id = get_component(new[pkg]["component"]).component_id
558 type_id = get_override_type(new[pkg]["type"]).overridetype_id
559 priority_id = new[pkg]["priority id"]
560 section_id = new[pkg]["section id"]
561 Logger.log(["%s overrides" % (srcpkg), suite, new[pkg]["component"], new[pkg]["type"], new[pkg]["priority"], new[pkg]["section"]])
562 session.execute("INSERT INTO override (suite, component, type, package, priority, section, maintainer) VALUES (:sid, :cid, :tid, :pkg, :pid, :sectid, '')",
563 { 'sid': suite_id, 'cid': component_id, 'tid':type_id, 'pkg': pkg, 'pid': priority_id, 'sectid': section_id})
564 for f in new[pkg]["files"]:
565 if files[f].has_key("new"):
571 if Config().FindB("Dinstall::BXANotify"):
572 do_bxa_notification(upload)
574 ################################################################################
576 def prod_maintainer (note, upload):
578 # Here we prepare an editor and get them ready to prod...
579 (fd, temp_filename) = utils.temp_filename()
580 temp_file = os.fdopen(fd, 'w')
583 temp_file.write(line)
585 editor = os.environ.get("EDITOR","vi")
588 os.system("%s %s" % (editor, temp_filename))
589 temp_fh = utils.open_file(temp_filename)
590 prod_message = "".join(temp_fh.readlines())
592 print "Prod message:"
593 print utils.prefix_multi_line_string(prod_message," ",include_blank_lines=1)
594 prompt = "[P]rod, Edit, Abandon, Quit ?"
596 while prompt.find(answer) == -1:
597 answer = utils.our_raw_input(prompt)
598 m = re_default_answer.search(prompt)
601 answer = answer[:1].upper()
602 os.unlink(temp_filename)
608 # Otherwise, do the proding...
609 user_email_address = utils.whoami() + " <%s>" % (
610 cnf["Dinstall::MyAdminAddress"])
614 Subst["__FROM_ADDRESS__"] = user_email_address
615 Subst["__PROD_MESSAGE__"] = prod_message
616 Subst["__CC__"] = "Cc: " + cnf["Dinstall::MyEmailAddress"]
618 prod_mail_message = utils.TemplateSubst(
619 Subst,cnf["Dir::Templates"]+"/process-new.prod")
621 # Send the prod mail if appropriate
622 if not cnf["Dinstall::Options::No-Mail"]:
623 utils.send_mail(prod_mail_message)
625 print "Sent proding message"
627 ################################################################################
629 def do_new(upload, session):
631 files = upload.pkg.files
632 changes = upload.pkg.changes
635 # Make a copy of distribution we can happily trample on
636 changes["suite"] = copy.copy(changes["distribution"])
638 # Fix up the list of target suites
639 for suite in changes["suite"].keys():
640 override = cnf.Find("Suite::%s::OverrideSuite" % (suite))
642 (olderr, newerr) = (get_suite(suite, session) == None,
643 get_suite(override, session) == None)
645 (oinv, newinv) = ("", "")
646 if olderr: oinv = "invalid "
647 if newerr: ninv = "invalid "
648 print "warning: overriding %ssuite %s to %ssuite %s" % (
649 oinv, suite, ninv, override)
650 del changes["suite"][suite]
651 changes["suite"][override] = 1
653 for suite in changes["suite"].keys():
654 if get_suite(suite, session) is None:
655 utils.fubar("%s has invalid suite '%s' (possibly overriden). say wha?" % (changes, suite))
657 # The main NEW processing loop
660 # Find out what's new
661 new = determine_new(changes, files)
667 if Options["No-Action"] or Options["Automatic"]:
670 (broken, note) = print_new(new, upload, indexed=0)
673 if not broken and not note:
674 prompt = "Add overrides, "
676 print "W: [!] marked entries must be fixed before package can be processed."
678 print "W: note must be removed before package can be processed."
679 prompt += "RemOve all notes, Remove note, "
681 prompt += "Edit overrides, Check, Manual reject, Note edit, Prod, [S]kip, Quit ?"
683 while prompt.find(answer) == -1:
684 answer = utils.our_raw_input(prompt)
685 m = re_default_answer.search(prompt)
688 answer = answer[:1].upper()
690 if answer in ( 'A', 'E', 'M', 'O', 'R' ) and Options["Trainee"]:
691 utils.warn("Trainees can't do that")
694 if answer == 'A' and not Options["Trainee"]:
697 done = add_overrides (new, upload, session)
698 Logger.log(["NEW ACCEPT: %s" % (upload.pkg.changes_file)])
699 except CantGetLockError:
700 print "Hello? Operator! Give me the number for 911!"
701 print "Dinstall in the locked area, cant process packages, come back later"
704 elif answer == 'E' and not Options["Trainee"]:
705 new = edit_overrides (new, upload, session)
706 elif answer == 'M' and not Options["Trainee"]:
707 aborted = upload.do_reject(manual=1,
708 reject_message=Options["Manual-Reject"],
709 note=get_new_comments(changes.get("source", ""), session=session))
711 Logger.log(["NEW REJECT: %s" % (upload.pkg.changes_file)])
712 os.unlink(upload.pkg.changes_file[:-8]+".dak")
715 edit_note(get_new_comments(changes.get("source", ""), session=session),
717 elif answer == 'P' and not Options["Trainee"]:
718 prod_maintainer(get_new_comments(changes.get("source", ""), session=session),
720 Logger.log(["NEW PROD: %s" % (upload.pkg.changes_file)])
721 elif answer == 'R' and not Options["Trainee"]:
722 confirm = utils.our_raw_input("Really clear note (y/N)? ").lower()
724 for c in get_new_comments(changes.get("source", ""), changes.get("version", ""), session=session):
727 elif answer == 'O' and not Options["Trainee"]:
728 confirm = utils.our_raw_input("Really clear all notes (y/N)? ").lower()
730 for c in get_new_comments(changes.get("source", ""), session=session):
740 ################################################################################
741 ################################################################################
742 ################################################################################
744 def usage (exit_code=0):
745 print """Usage: dak process-new [OPTION]... [CHANGES]...
746 -a, --automatic automatic run
747 -h, --help show this help and exit.
748 -C, --comments-dir=DIR use DIR as comments-dir, for [o-]p-u-new
749 -m, --manual-reject=MSG manual reject with `msg'
750 -n, --no-action don't do anything
751 -t, --trainee FTP Trainee mode
752 -V, --version display the version number and exit"""
755 ################################################################################
757 def do_byhand(upload, session):
760 files = upload.pkg.files
764 for f in files.keys():
765 if files[f]["type"] == "byhand":
766 if os.path.exists(f):
767 print "W: %s still present; please process byhand components and try again." % (f)
773 if Options["No-Action"]:
776 if Options["Automatic"] and not Options["No-Action"]:
778 prompt = "[A]ccept, Manual reject, Skip, Quit ?"
780 prompt = "Manual reject, [S]kip, Quit ?"
782 while prompt.find(answer) == -1:
783 answer = utils.our_raw_input(prompt)
784 m = re_default_answer.search(prompt)
787 answer = answer[:1].upper()
795 Logger.log(["BYHAND ACCEPT: %s" % (upload.pkg.changes_file)])
796 except CantGetLockError:
797 print "Hello? Operator! Give me the number for 911!"
798 print "Dinstall in the locked area, cant process packages, come back later"
800 Logger.log(["BYHAND REJECT: %s" % (upload.pkg.changes_file)])
801 upload.do_reject(manual=1, reject_message=Options["Manual-Reject"])
802 os.unlink(upload.pkg.changes_file[:-8]+".dak")
810 ################################################################################
812 def check_daily_lock():
814 Raises CantGetLockError if the dinstall daily.lock exists.
819 os.open(cnf["Process-New::DinstallLockFile"],
820 os.O_RDONLY | os.O_CREAT | os.O_EXCL)
822 if e.errno == errno.EEXIST or e.errno == errno.EACCES:
823 raise CantGetLockError
825 os.unlink(cnf["Process-New::DinstallLockFile"])
828 @contextlib.contextmanager
829 def lock_package(package):
831 Lock C{package} so that noone else jumps in processing it.
833 @type package: string
834 @param package: source package name to lock
837 path = os.path.join(Config()["Process-New::LockDir"], package)
839 fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_RDONLY)
841 if e.errno == errno.EEXIST or e.errno == errno.EACCES:
842 user = pwd.getpwuid(os.stat(path)[stat.ST_UID])[4].split(',')[0].replace('.', '')
843 raise AlreadyLockedError, user
850 # def move_to_dir (upload, dest, perms=0660, changesperms=0664):
851 # utils.move (upload.pkg.changes_file, dest, perms=changesperms)
852 # file_keys = upload.pkg.files.keys()
853 # for f in file_keys:
854 # utils.move (f, dest, perms=perms)
856 # def is_source_in_queue_dir(qdir):
857 # entries = [ x for x in os.listdir(qdir) if x.startswith(Upload.pkg.changes["source"])
858 # and x.endswith(".changes") ]
859 # for entry in entries:
861 # u = queue.Upload(Cnf)
862 # u.pkg.changes_file = os.path.join(qdir, entry)
864 # if not u.pkg.changes["architecture"].has_key("source"):
865 # # another binary upload, ignore
867 # if Upload.pkg.changes["version"] != u.pkg.changes["version"]:
868 # # another version, ignore
874 # def move_to_holding(suite, queue_dir):
875 # print "Moving to %s holding area." % (suite.upper(),)
876 # if Options["No-Action"]:
878 # Logger.log(["Moving to %s" % (suite,), Upload.pkg.changes_file])
879 # Upload.dump_vars(queue_dir)
880 # move_to_dir(queue_dir, perms=0664)
881 # os.unlink(Upload.pkg.changes_file[:-8]+".dak")
884 if Options["No-Action"]:
886 (summary, short_summary) = upload.build_summaries()
887 upload.accept(summary, short_summary, targetdir=Config()["Dir::Queue::Newstage"])
888 os.unlink(upload.pkg.changes_file[:-8]+".dak")
890 # def do_accept_stableupdate(upload,suite, q):
892 # queue_dir = cnf["Dir::Queue::%s" % (q,)]
893 # if not upload.pkg.changes["architecture"].has_key("source"):
894 # # It is not a sourceful upload. So its source may be either in p-u
895 # # holding, in new, in accepted or already installed.
896 # if is_source_in_queue_dir(queue_dir):
897 # # It's in p-u holding, so move it there.
898 # print "Binary-only upload, source in %s." % (q,)
899 # move_to_holding(suite, queue_dir)
900 # elif Upload.source_exists(Upload.pkg.changes["source"],
901 # Upload.pkg.changes["version"]):
902 # # dak tells us that there is source available. At time of
903 # # writing this means that it is installed, so put it into
905 # print "Binary-only upload, source installed."
906 # Logger.log([utils.getusername(), "PUNEW ACCEPT: %s" % (Upload.pkg.changes_file)])
908 # elif is_source_in_queue_dir(Cnf["Dir::Queue::Accepted"]):
909 # # The source is in accepted, the binary cleared NEW: accept it.
910 # print "Binary-only upload, source in accepted."
911 # Logger.log([utils.getusername(), "PUNEW ACCEPT: %s" % (Upload.pkg.changes_file)])
913 # elif is_source_in_queue_dir(Cnf["Dir::Queue::New"]):
914 # # It's in NEW. We expect the source to land in p-u holding
916 # print "Binary-only upload, source in new."
917 # move_to_holding(suite, queue_dir)
918 # elif is_source_in_queue_dir(Cnf["Dir::Queue::Newstage"]):
919 # # It's in newstage. Accept into the holding area
920 # print "Binary-only upload, source in newstage."
921 # Logger.log([utils.getusername(), "PUNEW ACCEPT: %s" % (Upload.pkg.changes_file)])
924 # # No case applicable. Bail out. Return will cause the upload
927 # print "Stable update failed. Source not found."
930 # # We are handling a sourceful upload. Move to accepted if currently
931 # # in p-u holding and to p-u holding otherwise.
932 # if is_source_in_queue_dir(queue_dir):
933 # print "Sourceful upload in %s, accepting." % (q,)
936 # move_to_holding(suite, queue_dir)
938 def do_accept(upload):
941 if not Options["No-Action"]:
942 (summary, short_summary) = upload.build_summaries()
943 # if cnf.FindB("Dinstall::SecurityQueueHandling"):
944 # upload.dump_vars(cnf["Dir::Queue::Embargoed"])
945 # move_to_dir(cnf["Dir::Queue::Embargoed"])
946 # upload.queue_build("embargoed", cnf["Dir::Queue::Embargoed"])
947 # # Check for override disparities
948 # upload.Subst["__SUMMARY__"] = summary
950 # Stable updates need to be copied to proposed-updates holding
951 # area instead of accepted. Sourceful uploads need to go
952 # to it directly, binaries only if the source has not yet been
954 for suite, q in [("proposed-updates", "ProposedUpdates"),
955 ("oldstable-proposed-updates", "OldProposedUpdates")]:
956 if not upload.pkg.changes["distribution"].has_key(suite):
958 utils.fubar("stable accept not supported yet")
959 # return do_accept_stableupdate(suite, q)
960 # Just a normal upload, accept it...
963 def check_status(files):
965 for f in files.keys():
966 if files[f]["type"] == "byhand":
968 elif files[f].has_key("new"):
972 def do_pkg(changes_file, session):
974 u.pkg.load_dot_dak(changes_file)
978 bcc = "X-DAK: dak process-new"
979 if cnf.has_key("Dinstall::Bcc"):
980 u.Subst["__BCC__"] = bcc + "\nBcc: %s" % (cnf["Dinstall::Bcc"])
982 u.Subst["__BCC__"] = bcc
987 with lock_package(u.pkg.changes["source"]):
988 if not recheck(u, session):
991 (new, byhand) = check_status(files)
996 do_byhand(u, session)
997 (new, byhand) = check_status(files)
999 if not new and not byhand:
1003 except CantGetLockError:
1004 print "Hello? Operator! Give me the number for 911!"
1005 print "Dinstall in the locked area, cant process packages, come back later"
1006 except AlreadyLockedError, e:
1007 print "Seems to be locked by %s already, skipping..." % (e)
1009 ################################################################################
1012 accept_count = SummaryStats().accept_count
1013 accept_bytes = SummaryStats().accept_bytes
1017 if accept_count > 1:
1019 sys.stderr.write("Accepted %d package %s, %s.\n" % (accept_count, sets, utils.size_type(int(accept_bytes))))
1020 Logger.log(["total",accept_count,accept_bytes])
1022 if not Options["No-Action"] and not Options["Trainee"]:
1025 ################################################################################
1027 # def do_comments(dir, opref, npref, line, fn):
1028 # for comm in [ x for x in os.listdir(dir) if x.startswith(opref) ]:
1029 # lines = open("%s/%s" % (dir, comm)).readlines()
1030 # if len(lines) == 0 or lines[0] != line + "\n": continue
1031 # changes_files = [ x for x in os.listdir(".") if x.startswith(comm[7:]+"_")
1032 # and x.endswith(".changes") ]
1033 # changes_files = sort_changes(changes_files)
1034 # for f in changes_files:
1035 # f = utils.validate_changes_file_arg(f, 0)
1036 # if not f: continue
1038 # fn(f, "".join(lines[1:]))
1040 # if opref != npref and not Options["No-Action"]:
1041 # newcomm = npref + comm[len(opref):]
1042 # os.rename("%s/%s" % (dir, comm), "%s/%s" % (dir, newcomm))
1044 # ################################################################################
1046 # def comment_accept(changes_file, comments):
1047 # Upload.pkg.changes_file = changes_file
1048 # Upload.init_vars()
1049 # Upload.update_vars()
1050 # Upload.update_subst()
1051 # files = Upload.pkg.files
1054 # return # dak wants to REJECT, crap
1056 # (new, byhand) = check_status(files)
1057 # if not new and not byhand:
1060 # ################################################################################
1062 # def comment_reject(changes_file, comments):
1063 # Upload.pkg.changes_file = changes_file
1064 # Upload.init_vars()
1065 # Upload.update_vars()
1066 # Upload.update_subst()
1069 # pass # dak has its own reasons to reject as well, which is fine
1072 # print "REJECT\n" + reject_message,
1073 # if not Options["No-Action"]:
1074 # Upload.do_reject(0, reject_message)
1075 # os.unlink(Upload.pkg.changes_file[:-8]+".dak")
1077 ################################################################################
1080 global Options, Logger, Sections, Priorities
1083 session = DBConn().session()
1085 Arguments = [('a',"automatic","Process-New::Options::Automatic"),
1086 ('h',"help","Process-New::Options::Help"),
1087 ('C',"comments-dir","Process-New::Options::Comments-Dir", "HasArg"),
1088 ('m',"manual-reject","Process-New::Options::Manual-Reject", "HasArg"),
1089 ('t',"trainee","Process-New::Options::Trainee"),
1090 ('n',"no-action","Process-New::Options::No-Action")]
1092 for i in ["automatic", "help", "manual-reject", "no-action", "version", "comments-dir", "trainee"]:
1093 if not cnf.has_key("Process-New::Options::%s" % (i)):
1094 cnf["Process-New::Options::%s" % (i)] = ""
1096 changes_files = apt_pkg.ParseCommandLine(cnf.Cnf,Arguments,sys.argv)
1097 if len(changes_files) == 0 and not cnf.get("Process-New::Options::Comments-Dir",""):
1098 changes_files = utils.get_changes_files(cnf["Dir::Queue::New"])
1100 Options = cnf.SubTree("Process-New::Options")
1105 if not Options["No-Action"]:
1107 Logger = daklog.Logger(cnf, "process-new")
1108 except CantOpenError, e:
1109 Options["Trainee"] = "True"
1111 Sections = Section_Completer(session)
1112 Priorities = Priority_Completer(session)
1113 readline.parse_and_bind("tab: complete")
1115 if len(changes_files) > 1:
1116 sys.stderr.write("Sorting changes...\n")
1117 changes_files = sort_changes(changes_files, session)
1119 # Kill me now? **FIXME**
1120 cnf["Dinstall::Options::No-Mail"] = ""
1122 # commentsdir = cnf.get("Process-New::Options::Comments-Dir","")
1124 # if changes_files != []:
1125 # sys.stderr.write("Can't specify any changes files if working with comments-dir")
1127 # do_comments(commentsdir, "ACCEPT.", "ACCEPTED.", "OK", comment_accept)
1128 # do_comments(commentsdir, "REJECT.", "REJECTED.", "NOTOK", comment_reject)
1131 for changes_file in changes_files:
1132 changes_file = utils.validate_changes_file_arg(changes_file, 0)
1133 if not changes_file:
1135 print "\n" + changes_file
1137 do_pkg (changes_file, session)
1141 ################################################################################
1143 if __name__ == '__main__':