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, re_package
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 # STU: I'm not sure, but I don't thin kthis is necessary any longer: upload.recheck(session)
81 if len(upload.rejects) > 0:
83 if Options["No-Action"] or Options["Automatic"] or Options["Trainee"]:
86 print "REJECT\n%s" % '\n'.join(upload.rejects)
87 prompt = "[R]eject, Skip, Quit ?"
89 while prompt.find(answer) == -1:
90 answer = utils.our_raw_input(prompt)
91 m = re_default_answer.match(prompt)
94 answer = answer[:1].upper()
97 upload.do_reject(manual=0, reject_message='\n'.join(upload.rejects))
107 ################################################################################
109 def indiv_sg_compare (a, b):
110 """Sort by source name, source, version, 'have source', and
111 finally by filename."""
112 # Sort by source version
113 q = apt_pkg.VersionCompare(a["version"], b["version"])
117 # Sort by 'have source'
118 a_has_source = a["architecture"].get("source")
119 b_has_source = b["architecture"].get("source")
120 if a_has_source and not b_has_source:
122 elif b_has_source and not a_has_source:
125 return cmp(a["filename"], b["filename"])
127 ############################################################
129 def sg_compare (a, b):
132 """Sort by have note, source already in database and time of oldest upload."""
134 a_note_state = a["note_state"]
135 b_note_state = b["note_state"]
136 if a_note_state < b_note_state:
138 elif a_note_state > b_note_state:
140 # Sort by source already in database (descending)
141 source_in_database = cmp(a["source_in_database"], b["source_in_database"])
142 if source_in_database:
143 return -source_in_database
145 # Sort by time of oldest upload
146 return cmp(a["oldest"], b["oldest"])
148 def sort_changes(changes_files, session):
149 """Sort into source groups, then sort each source group by version,
150 have source, filename. Finally, sort the source groups by have
151 note, time of oldest upload of each source upload."""
152 if len(changes_files) == 1:
157 # Read in all the .changes files
158 for filename in changes_files:
161 u.pkg.changes_file = filename
162 u.load_changes(filename)
164 cache[filename] = copy.copy(u.pkg.changes)
165 cache[filename]["filename"] = filename
167 sorted_list.append(filename)
169 # Divide the .changes into per-source groups
171 for filename in cache.keys():
172 source = cache[filename]["source"]
173 if not per_source.has_key(source):
174 per_source[source] = {}
175 per_source[source]["list"] = []
176 per_source[source]["list"].append(cache[filename])
177 # Determine oldest time and have note status for each source group
178 for source in per_source.keys():
179 q = session.query(DBSource).filter_by(source = source).all()
180 per_source[source]["source_in_database"] = len(q)>0
181 source_list = per_source[source]["list"]
182 first = source_list[0]
183 oldest = os.stat(first["filename"])[stat.ST_MTIME]
185 for d in per_source[source]["list"]:
186 mtime = os.stat(d["filename"])[stat.ST_MTIME]
189 have_note += has_new_comment(d["source"], d["version"], session)
190 per_source[source]["oldest"] = oldest
192 per_source[source]["note_state"] = 0; # none
193 elif have_note < len(source_list):
194 per_source[source]["note_state"] = 1; # some
196 per_source[source]["note_state"] = 2; # all
197 per_source[source]["list"].sort(indiv_sg_compare)
198 per_source_items = per_source.items()
199 per_source_items.sort(sg_compare)
200 for i in per_source_items:
201 for j in i[1]["list"]:
202 sorted_list.append(j["filename"])
205 ################################################################################
207 class Section_Completer:
208 def __init__ (self, session):
211 for s, in session.query(Section.section):
212 self.sections.append(s)
214 def complete(self, text, state):
218 for word in self.sections:
220 self.matches.append(word)
222 return self.matches[state]
226 ############################################################
228 class Priority_Completer:
229 def __init__ (self, session):
232 for p, in session.query(Priority.priority):
233 self.priorities.append(p)
235 def complete(self, text, state):
239 for word in self.priorities:
241 self.matches.append(word)
243 return self.matches[state]
247 ################################################################################
249 def print_new (new, upload, indexed, file=sys.stdout):
253 for pkg in new.keys():
255 section = new[pkg]["section"]
256 priority = new[pkg]["priority"]
257 if new[pkg]["section id"] == -1:
260 if new[pkg]["priority id"] == -1:
264 line = "(%s): %-20s %-20s %-20s" % (index, pkg, priority, section)
266 line = "%-20s %-20s %-20s" % (pkg, priority, section)
267 line = line.strip()+'\n'
269 notes = get_new_comments(upload.pkg.changes.get("source"))
271 print "\nAuthor: %s\nVersion: %s\nTimestamp: %s\n\n%s" \
272 % (note.author, note.version, note.notedate, note.comment)
274 return broken, len(notes) > 0
276 ################################################################################
278 def index_range (index):
282 return "1-%s" % (index)
284 ################################################################################
285 ################################################################################
287 def edit_new (new, upload):
288 # Write the current data to a temporary file
289 (fd, temp_filename) = utils.temp_filename()
290 temp_file = os.fdopen(fd, 'w')
291 print_new (new, upload, indexed=0, file=temp_file)
293 # Spawn an editor on that file
294 editor = os.environ.get("EDITOR","vi")
295 result = os.system("%s %s" % (editor, temp_filename))
297 utils.fubar ("%s invocation failed for %s." % (editor, temp_filename), result)
298 # Read the edited data back in
299 temp_file = utils.open_file(temp_filename)
300 lines = temp_file.readlines()
302 os.unlink(temp_filename)
309 # Pad the list if necessary
310 s[len(s):3] = [None] * (3-len(s))
311 (pkg, priority, section) = s[:3]
312 if not new.has_key(pkg):
313 utils.warn("Ignoring unknown package '%s'" % (pkg))
315 # Strip off any invalid markers, print_new will readd them.
316 if section.endswith("[!]"):
317 section = section[:-3]
318 if priority.endswith("[!]"):
319 priority = priority[:-3]
320 for f in new[pkg]["files"]:
321 upload.pkg.files[f]["section"] = section
322 upload.pkg.files[f]["priority"] = priority
323 new[pkg]["section"] = section
324 new[pkg]["priority"] = priority
326 ################################################################################
328 def edit_index (new, upload, index):
329 priority = new[index]["priority"]
330 section = new[index]["section"]
331 ftype = new[index]["type"]
334 print "\t".join([index, priority, section])
338 prompt = "[B]oth, Priority, Section, Done ? "
340 prompt = "[S]ection, Done ? "
341 edit_priority = edit_section = 0
343 while prompt.find(answer) == -1:
344 answer = utils.our_raw_input(prompt)
345 m = re_default_answer.match(prompt)
348 answer = answer[:1].upper()
355 edit_priority = edit_section = 1
361 readline.set_completer(Priorities.complete)
363 while not got_priority:
364 new_priority = utils.our_raw_input("New priority: ").strip()
365 if new_priority not in Priorities.priorities:
366 print "E: '%s' is not a valid priority, try again." % (new_priority)
369 priority = new_priority
373 readline.set_completer(Sections.complete)
375 while not got_section:
376 new_section = utils.our_raw_input("New section: ").strip()
377 if new_section not in Sections.sections:
378 print "E: '%s' is not a valid section, try again." % (new_section)
381 section = new_section
383 # Reset the readline completer
384 readline.set_completer(None)
386 for f in new[index]["files"]:
387 upload.pkg.files[f]["section"] = section
388 upload.pkg.files[f]["priority"] = priority
389 new[index]["priority"] = priority
390 new[index]["section"] = section
393 ################################################################################
395 def edit_overrides (new, upload, session):
399 print_new (new, upload, indexed=1)
406 prompt = "(%s) edit override <n>, Editor, Done ? " % (index_range(index))
409 while not got_answer:
410 answer = utils.our_raw_input(prompt)
411 if not answer.isdigit():
412 answer = answer[:1].upper()
413 if answer == "E" or answer == "D":
415 elif re_isanum.match (answer):
417 if (answer < 1) or (answer > index):
418 print "%s is not a valid index (%s). Please retry." % (answer, index_range(index))
423 edit_new(new, upload)
427 edit_index (new, upload, new_index[answer])
431 ################################################################################
433 def edit_note(note, upload, session):
434 # Write the current data to a temporary file
435 (fd, temp_filename) = utils.temp_filename()
436 editor = os.environ.get("EDITOR","vi")
439 os.system("%s %s" % (editor, temp_filename))
440 temp_file = utils.open_file(temp_filename)
441 newnote = temp_file.read().rstrip()
444 print utils.prefix_multi_line_string(newnote," ")
445 prompt = "[D]one, Edit, Abandon, Quit ?"
447 while prompt.find(answer) == -1:
448 answer = utils.our_raw_input(prompt)
449 m = re_default_answer.search(prompt)
452 answer = answer[:1].upper()
453 os.unlink(temp_filename)
460 comment = NewComment()
461 comment.package = upload.pkg.changes["source"]
462 comment.version = upload.pkg.changes["version"]
463 comment.comment = newnote
464 comment.author = utils.whoami()
465 comment.trainee = bool(Options["Trainee"])
469 ################################################################################
471 def check_pkg (upload):
473 less_fd = os.popen("less -R -", 'w', 0)
474 stdout_fd = sys.stdout
477 changes = utils.parse_changes (upload.pkg.changes_file)
478 examine_package.display_changes(changes['distribution'], upload.pkg.changes_file)
479 files = upload.pkg.files
480 for f in files.keys():
481 if files[f].has_key("new"):
482 ftype = files[f]["type"]
484 examine_package.check_deb(changes['distribution'], f)
486 examine_package.check_dsc(changes['distribution'], f)
488 examine_package.output_package_relations()
489 sys.stdout = stdout_fd
491 if e.errno == errno.EPIPE:
492 utils.warn("[examine_package] Caught EPIPE; skipping.")
496 except KeyboardInterrupt:
497 utils.warn("[examine_package] Caught C-c; skipping.")
500 ################################################################################
502 ## FIXME: horribly Debian specific
504 def do_bxa_notification(upload):
505 files = upload.pkg.files
507 for f in files.keys():
508 if files[f]["type"] == "deb":
509 control = apt_pkg.ParseSection(apt_inst.debExtractControl(utils.open_file(f)))
511 summary += "Package: %s\n" % (control.Find("Package"))
512 summary += "Description: %s\n" % (control.Find("Description"))
513 upload.Subst["__BINARY_DESCRIPTIONS__"] = summary
514 bxa_mail = utils.TemplateSubst(upload.Subst,Config()["Dir::Templates"]+"/process-new.bxa_notification")
515 utils.send_mail(bxa_mail)
517 ################################################################################
519 def add_overrides (new, upload, session):
520 changes = upload.pkg.changes
521 files = upload.pkg.files
522 srcpkg = changes.get("source")
524 for suite in changes["suite"].keys():
525 suite_id = get_suite(suite).suite_id
526 for pkg in new.keys():
527 component_id = get_component(new[pkg]["component"]).component_id
528 type_id = get_override_type(new[pkg]["type"]).overridetype_id
529 priority_id = new[pkg]["priority id"]
530 section_id = new[pkg]["section id"]
531 Logger.log(["%s overrides" % (srcpkg), suite, new[pkg]["component"], new[pkg]["type"], new[pkg]["priority"], new[pkg]["section"]])
532 session.execute("INSERT INTO override (suite, component, type, package, priority, section, maintainer) VALUES (:sid, :cid, :tid, :pkg, :pid, :sectid, '')",
533 { 'sid': suite_id, 'cid': component_id, 'tid':type_id, 'pkg': pkg, 'pid': priority_id, 'sectid': section_id})
534 for f in new[pkg]["files"]:
535 if files[f].has_key("new"):
541 if Config().FindB("Dinstall::BXANotify"):
542 do_bxa_notification(upload)
544 ################################################################################
546 def prod_maintainer (note, upload):
548 # Here we prepare an editor and get them ready to prod...
549 (fd, temp_filename) = utils.temp_filename()
550 temp_file = os.fdopen(fd, 'w')
553 temp_file.write(line)
555 editor = os.environ.get("EDITOR","vi")
558 os.system("%s %s" % (editor, temp_filename))
559 temp_fh = utils.open_file(temp_filename)
560 prod_message = "".join(temp_fh.readlines())
562 print "Prod message:"
563 print utils.prefix_multi_line_string(prod_message," ",include_blank_lines=1)
564 prompt = "[P]rod, Edit, Abandon, Quit ?"
566 while prompt.find(answer) == -1:
567 answer = utils.our_raw_input(prompt)
568 m = re_default_answer.search(prompt)
571 answer = answer[:1].upper()
572 os.unlink(temp_filename)
578 # Otherwise, do the proding...
579 user_email_address = utils.whoami() + " <%s>" % (
580 cnf["Dinstall::MyAdminAddress"])
584 Subst["__FROM_ADDRESS__"] = user_email_address
585 Subst["__PROD_MESSAGE__"] = prod_message
586 Subst["__CC__"] = "Cc: " + cnf["Dinstall::MyEmailAddress"]
588 prod_mail_message = utils.TemplateSubst(
589 Subst,cnf["Dir::Templates"]+"/process-new.prod")
591 # Send the prod mail if appropriate
592 if not cnf["Dinstall::Options::No-Mail"]:
593 utils.send_mail(prod_mail_message)
595 print "Sent proding message"
597 ################################################################################
599 def do_new(upload, session):
601 files = upload.pkg.files
602 upload.check_files(not Options["No-Action"])
603 changes = upload.pkg.changes
606 # Check for a valid distribution
607 upload.check_distributions()
609 # Make a copy of distribution we can happily trample on
610 changes["suite"] = copy.copy(changes["distribution"])
612 # Fix up the list of target suites
613 for suite in changes["suite"].keys():
614 override = cnf.Find("Suite::%s::OverrideSuite" % (suite))
616 (olderr, newerr) = (get_suite(suite, session) == None,
617 get_suite(override, session) == None)
619 (oinv, newinv) = ("", "")
620 if olderr: oinv = "invalid "
621 if newerr: ninv = "invalid "
622 print "warning: overriding %ssuite %s to %ssuite %s" % (
623 oinv, suite, ninv, override)
624 del changes["suite"][suite]
625 changes["suite"][override] = 1
627 # The main NEW processing loop
630 # Find out what's new
631 new = determine_new(changes, files)
637 if Options["No-Action"] or Options["Automatic"]:
640 (broken, note) = print_new(new, upload, indexed=0)
643 if not broken and not note:
644 prompt = "Add overrides, "
646 print "W: [!] marked entries must be fixed before package can be processed."
648 print "W: note must be removed before package can be processed."
649 prompt += "RemOve all notes, Remove note, "
651 prompt += "Edit overrides, Check, Manual reject, Note edit, Prod, [S]kip, Quit ?"
653 while prompt.find(answer) == -1:
654 answer = utils.our_raw_input(prompt)
655 m = re_default_answer.search(prompt)
658 answer = answer[:1].upper()
660 if answer in ( 'A', 'E', 'M', 'O', 'R' ) and Options["Trainee"]:
661 utils.warn("Trainees can't do that")
664 if answer == 'A' and not Options["Trainee"]:
667 done = add_overrides (new, upload, session)
668 do_accept(upload, session)
669 Logger.log(["NEW ACCEPT: %s" % (upload.pkg.changes_file)])
670 except CantGetLockError:
671 print "Hello? Operator! Give me the number for 911!"
672 print "Dinstall in the locked area, cant process packages, come back later"
675 elif answer == 'E' and not Options["Trainee"]:
676 new = edit_overrides (new, upload, session)
677 elif answer == 'M' and not Options["Trainee"]:
678 upload.pkg.remove_known_changes()
679 aborted = upload.do_reject(manual=1,
680 reject_message=Options["Manual-Reject"],
681 note=get_new_comments(changes.get("source", ""), session=session))
683 Logger.log(["NEW REJECT: %s" % (upload.pkg.changes_file)])
686 edit_note(get_new_comments(changes.get("source", ""), session=session),
688 elif answer == 'P' and not Options["Trainee"]:
689 prod_maintainer(get_new_comments(changes.get("source", ""), session=session),
691 Logger.log(["NEW PROD: %s" % (upload.pkg.changes_file)])
692 elif answer == 'R' and not Options["Trainee"]:
693 confirm = utils.our_raw_input("Really clear note (y/N)? ").lower()
695 for c in get_new_comments(changes.get("source", ""), changes.get("version", ""), session=session):
698 elif answer == 'O' and not Options["Trainee"]:
699 confirm = utils.our_raw_input("Really clear all notes (y/N)? ").lower()
701 for c in get_new_comments(changes.get("source", ""), session=session):
711 ################################################################################
712 ################################################################################
713 ################################################################################
715 def usage (exit_code=0):
716 print """Usage: dak process-new [OPTION]... [CHANGES]...
717 -a, --automatic automatic run
718 -h, --help show this help and exit.
719 -m, --manual-reject=MSG manual reject with `msg'
720 -n, --no-action don't do anything
721 -t, --trainee FTP Trainee mode
722 -V, --version display the version number and exit"""
725 ################################################################################
727 def do_byhand(upload, session):
730 files = upload.pkg.files
734 for f in files.keys():
735 if files[f]["type"] == "byhand":
736 if os.path.exists(f):
737 print "W: %s still present; please process byhand components and try again." % (f)
743 if Options["No-Action"]:
746 if Options["Automatic"] and not Options["No-Action"]:
748 prompt = "[A]ccept, Manual reject, Skip, Quit ?"
750 prompt = "Manual reject, [S]kip, Quit ?"
752 while prompt.find(answer) == -1:
753 answer = utils.our_raw_input(prompt)
754 m = re_default_answer.search(prompt)
757 answer = answer[:1].upper()
765 Logger.log(["BYHAND ACCEPT: %s" % (upload.pkg.changes_file)])
766 except CantGetLockError:
767 print "Hello? Operator! Give me the number for 911!"
768 print "Dinstall in the locked area, cant process packages, come back later"
770 Logger.log(["BYHAND REJECT: %s" % (upload.pkg.changes_file)])
771 upload.do_reject(manual=1, reject_message=Options["Manual-Reject"])
779 ################################################################################
781 def check_daily_lock():
783 Raises CantGetLockError if the dinstall daily.lock exists.
788 os.open(cnf["Process-New::DinstallLockFile"],
789 os.O_RDONLY | os.O_CREAT | os.O_EXCL)
791 if e.errno == errno.EEXIST or e.errno == errno.EACCES:
792 raise CantGetLockError
794 os.unlink(cnf["Process-New::DinstallLockFile"])
797 @contextlib.contextmanager
798 def lock_package(package):
800 Lock C{package} so that noone else jumps in processing it.
802 @type package: string
803 @param package: source package name to lock
806 path = os.path.join(Config()["Process-New::LockDir"], package)
808 fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_RDONLY)
810 if e.errno == errno.EEXIST or e.errno == errno.EACCES:
811 user = pwd.getpwuid(os.stat(path)[stat.ST_UID])[4].split(',')[0].replace('.', '')
812 raise AlreadyLockedError, user
819 class clean_holding(object):
820 def __init__(self,pkg):
826 def __exit__(self, type, value, traceback):
829 for f in self.pkg.files.keys():
830 if os.path.exists(os.path.join(h.holding_dir, f)):
831 os.unlink(os.path.join(h.holding_dir, f))
835 def changes_to_newstage(upload, session):
836 """move a changes file to newstage"""
837 new = get_policy_queue('new', session );
838 newstage = get_policy_queue('newstage', session );
840 chg = session.query(DBChange).filter_by(changesname=os.path.basename(upload.pkg.changes_file)).one()
841 chg.approved_for = newstage.policy_queue_id
844 # update the changes_pending_files row
846 utils.move(os.path.join(new.path, f.filename), newstage.path, perms=int(newstage.perms, 8))
848 utils.move(os.path.join(new.path, upload.pkg.changes_file), newstage.path, perms=int(newstage.perms, 8))
849 chg.in_queue = newstage
852 def _accept(upload, session):
853 if Options["No-Action"]:
855 (summary, short_summary) = upload.build_summaries()
856 # upload.accept(summary, short_summary, targetqueue)
858 changes_to_newstage(upload, session)
860 def do_accept(upload, session):
863 if not Options["No-Action"]:
864 (summary, short_summary) = upload.build_summaries()
866 if cnf.FindB("Dinstall::SecurityQueueHandling"):
867 upload.dump_vars(cnf["Dir::Queue::Embargoed"])
868 upload.move_to_queue(get_policy_queue('embargoed'))
869 upload.queue_build("embargoed", cnf["Dir::Queue::Embargoed"])
870 # Check for override disparities
871 upload.Subst["__SUMMARY__"] = summary
873 # Just a normal upload, accept it...
874 _accept(upload, session)
876 def do_pkg(changes_file, session):
877 new_queue = get_policy_queue('new', session );
879 u.pkg.changes_file = changes_file
880 (u.pkg.changes["fingerprint"], rejects) = utils.check_signature(changes_file)
881 u.load_changes(changes_file)
882 u.pkg.directory = new_queue.path
885 origchanges = os.path.abspath(u.pkg.changes_file)
888 bcc = "X-DAK: dak process-new"
889 if cnf.has_key("Dinstall::Bcc"):
890 u.Subst["__BCC__"] = bcc + "\nBcc: %s" % (cnf["Dinstall::Bcc"])
892 u.Subst["__BCC__"] = bcc
895 for deb_filename, f in files.items():
896 if deb_filename.endswith(".udeb") or deb_filename.endswith(".deb"):
897 u.binary_file_checks(deb_filename, session)
898 u.check_binary_against_db(deb_filename, session)
900 u.source_file_checks(deb_filename, session)
901 u.check_source_against_db(deb_filename, session)
903 u.pkg.changes["suite"] = copy.copy(u.pkg.changes["distribution"])
906 with lock_package(u.pkg.changes["source"]):
907 with clean_holding(u.pkg):
908 if not recheck(u, session):
911 # FIXME: This does need byhand checks added!
912 new = determine_new(u.pkg.changes, files)
918 do_accept(u, session)
919 except CantGetLockError:
920 print "Hello? Operator! Give me the number for 911!"
921 print "Dinstall in the locked area, cant process packages, come back later"
922 # (new, byhand) = check_status(files)
927 # do_byhand(u, session)
928 # (new, byhand) = check_status(files)
930 # if not new and not byhand:
934 # except CantGetLockError:
935 # print "Hello? Operator! Give me the number for 911!"
936 # print "Dinstall in the locked area, cant process packages, come back later"
937 except AlreadyLockedError, e:
938 print "Seems to be locked by %s already, skipping..." % (e)
940 ################################################################################
943 accept_count = SummaryStats().accept_count
944 accept_bytes = SummaryStats().accept_bytes
950 sys.stderr.write("Accepted %d package %s, %s.\n" % (accept_count, sets, utils.size_type(int(accept_bytes))))
951 Logger.log(["total",accept_count,accept_bytes])
953 if not Options["No-Action"] and not Options["Trainee"]:
956 ################################################################################
959 global Options, Logger, Sections, Priorities
962 session = DBConn().session()
964 Arguments = [('a',"automatic","Process-New::Options::Automatic"),
965 ('h',"help","Process-New::Options::Help"),
966 ('m',"manual-reject","Process-New::Options::Manual-Reject", "HasArg"),
967 ('t',"trainee","Process-New::Options::Trainee"),
968 ('n',"no-action","Process-New::Options::No-Action")]
970 for i in ["automatic", "help", "manual-reject", "no-action", "version", "trainee"]:
971 if not cnf.has_key("Process-New::Options::%s" % (i)):
972 cnf["Process-New::Options::%s" % (i)] = ""
974 changes_files = apt_pkg.ParseCommandLine(cnf.Cnf,Arguments,sys.argv)
975 if len(changes_files) == 0:
976 new_queue = get_policy_queue('new', session );
977 changes_files = utils.get_changes_files(new_queue.path)
979 Options = cnf.SubTree("Process-New::Options")
984 if not Options["No-Action"]:
986 Logger = daklog.Logger(cnf, "process-new")
987 except CantOpenError, e:
988 Options["Trainee"] = "True"
990 Sections = Section_Completer(session)
991 Priorities = Priority_Completer(session)
992 readline.parse_and_bind("tab: complete")
994 if len(changes_files) > 1:
995 sys.stderr.write("Sorting changes...\n")
996 changes_files = sort_changes(changes_files, session)
998 # Kill me now? **FIXME**
999 cnf["Dinstall::Options::No-Mail"] = ""
1001 for changes_file in changes_files:
1002 changes_file = utils.validate_changes_file_arg(changes_file, 0)
1003 if not changes_file:
1005 print "\n" + changes_file
1007 do_pkg (changes_file, session)
1011 ################################################################################
1013 if __name__ == '__main__':