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))
98 upload.pkg.remove_known_changes(session=session)
108 ################################################################################
110 def indiv_sg_compare (a, b):
111 """Sort by source name, source, version, 'have source', and
112 finally by filename."""
113 # Sort by source version
114 q = apt_pkg.VersionCompare(a["version"], b["version"])
118 # Sort by 'have source'
119 a_has_source = a["architecture"].get("source")
120 b_has_source = b["architecture"].get("source")
121 if a_has_source and not b_has_source:
123 elif b_has_source and not a_has_source:
126 return cmp(a["filename"], b["filename"])
128 ############################################################
130 def sg_compare (a, b):
133 """Sort by have note, source already in database and time of oldest upload."""
135 a_note_state = a["note_state"]
136 b_note_state = b["note_state"]
137 if a_note_state < b_note_state:
139 elif a_note_state > b_note_state:
141 # Sort by source already in database (descending)
142 source_in_database = cmp(a["source_in_database"], b["source_in_database"])
143 if source_in_database:
144 return -source_in_database
146 # Sort by time of oldest upload
147 return cmp(a["oldest"], b["oldest"])
149 def sort_changes(changes_files, session):
150 """Sort into source groups, then sort each source group by version,
151 have source, filename. Finally, sort the source groups by have
152 note, time of oldest upload of each source upload."""
153 if len(changes_files) == 1:
158 # Read in all the .changes files
159 for filename in changes_files:
162 u.pkg.changes_file = filename
163 u.load_changes(filename)
165 cache[filename] = copy.copy(u.pkg.changes)
166 cache[filename]["filename"] = filename
168 sorted_list.append(filename)
170 # Divide the .changes into per-source groups
172 for filename in cache.keys():
173 source = cache[filename]["source"]
174 if not per_source.has_key(source):
175 per_source[source] = {}
176 per_source[source]["list"] = []
177 per_source[source]["list"].append(cache[filename])
178 # Determine oldest time and have note status for each source group
179 for source in per_source.keys():
180 q = session.query(DBSource).filter_by(source = source).all()
181 per_source[source]["source_in_database"] = len(q)>0
182 source_list = per_source[source]["list"]
183 first = source_list[0]
184 oldest = os.stat(first["filename"])[stat.ST_MTIME]
186 for d in per_source[source]["list"]:
187 mtime = os.stat(d["filename"])[stat.ST_MTIME]
190 have_note += has_new_comment(d["source"], d["version"], session)
191 per_source[source]["oldest"] = oldest
193 per_source[source]["note_state"] = 0; # none
194 elif have_note < len(source_list):
195 per_source[source]["note_state"] = 1; # some
197 per_source[source]["note_state"] = 2; # all
198 per_source[source]["list"].sort(indiv_sg_compare)
199 per_source_items = per_source.items()
200 per_source_items.sort(sg_compare)
201 for i in per_source_items:
202 for j in i[1]["list"]:
203 sorted_list.append(j["filename"])
206 ################################################################################
208 class Section_Completer:
209 def __init__ (self, session):
212 for s, in session.query(Section.section):
213 self.sections.append(s)
215 def complete(self, text, state):
219 for word in self.sections:
221 self.matches.append(word)
223 return self.matches[state]
227 ############################################################
229 class Priority_Completer:
230 def __init__ (self, session):
233 for p, in session.query(Priority.priority):
234 self.priorities.append(p)
236 def complete(self, text, state):
240 for word in self.priorities:
242 self.matches.append(word)
244 return self.matches[state]
248 ################################################################################
250 def print_new (new, upload, indexed, file=sys.stdout):
254 for pkg in new.keys():
256 section = new[pkg]["section"]
257 priority = new[pkg]["priority"]
258 if new[pkg]["section id"] == -1:
261 if new[pkg]["priority id"] == -1:
265 line = "(%s): %-20s %-20s %-20s" % (index, pkg, priority, section)
267 line = "%-20s %-20s %-20s" % (pkg, priority, section)
268 line = line.strip()+'\n'
270 notes = get_new_comments(upload.pkg.changes.get("source"))
272 print "\nAuthor: %s\nVersion: %s\nTimestamp: %s\n\n%s" \
273 % (note.author, note.version, note.notedate, note.comment)
275 return broken, len(notes) > 0
277 ################################################################################
279 def index_range (index):
283 return "1-%s" % (index)
285 ################################################################################
286 ################################################################################
288 def edit_new (new, upload):
289 # Write the current data to a temporary file
290 (fd, temp_filename) = utils.temp_filename()
291 temp_file = os.fdopen(fd, 'w')
292 print_new (new, upload, indexed=0, file=temp_file)
294 # Spawn an editor on that file
295 editor = os.environ.get("EDITOR","vi")
296 result = os.system("%s %s" % (editor, temp_filename))
298 utils.fubar ("%s invocation failed for %s." % (editor, temp_filename), result)
299 # Read the edited data back in
300 temp_file = utils.open_file(temp_filename)
301 lines = temp_file.readlines()
303 os.unlink(temp_filename)
310 # Pad the list if necessary
311 s[len(s):3] = [None] * (3-len(s))
312 (pkg, priority, section) = s[:3]
313 if not new.has_key(pkg):
314 utils.warn("Ignoring unknown package '%s'" % (pkg))
316 # Strip off any invalid markers, print_new will readd them.
317 if section.endswith("[!]"):
318 section = section[:-3]
319 if priority.endswith("[!]"):
320 priority = priority[:-3]
321 for f in new[pkg]["files"]:
322 upload.pkg.files[f]["section"] = section
323 upload.pkg.files[f]["priority"] = priority
324 new[pkg]["section"] = section
325 new[pkg]["priority"] = priority
327 ################################################################################
329 def edit_index (new, upload, index):
330 priority = new[index]["priority"]
331 section = new[index]["section"]
332 ftype = new[index]["type"]
335 print "\t".join([index, priority, section])
339 prompt = "[B]oth, Priority, Section, Done ? "
341 prompt = "[S]ection, Done ? "
342 edit_priority = edit_section = 0
344 while prompt.find(answer) == -1:
345 answer = utils.our_raw_input(prompt)
346 m = re_default_answer.match(prompt)
349 answer = answer[:1].upper()
356 edit_priority = edit_section = 1
362 readline.set_completer(Priorities.complete)
364 while not got_priority:
365 new_priority = utils.our_raw_input("New priority: ").strip()
366 if new_priority not in Priorities.priorities:
367 print "E: '%s' is not a valid priority, try again." % (new_priority)
370 priority = new_priority
374 readline.set_completer(Sections.complete)
376 while not got_section:
377 new_section = utils.our_raw_input("New section: ").strip()
378 if new_section not in Sections.sections:
379 print "E: '%s' is not a valid section, try again." % (new_section)
382 section = new_section
384 # Reset the readline completer
385 readline.set_completer(None)
387 for f in new[index]["files"]:
388 upload.pkg.files[f]["section"] = section
389 upload.pkg.files[f]["priority"] = priority
390 new[index]["priority"] = priority
391 new[index]["section"] = section
394 ################################################################################
396 def edit_overrides (new, upload, session):
400 print_new (new, upload, indexed=1)
407 prompt = "(%s) edit override <n>, Editor, Done ? " % (index_range(index))
410 while not got_answer:
411 answer = utils.our_raw_input(prompt)
412 if not answer.isdigit():
413 answer = answer[:1].upper()
414 if answer == "E" or answer == "D":
416 elif re_isanum.match (answer):
418 if (answer < 1) or (answer > index):
419 print "%s is not a valid index (%s). Please retry." % (answer, index_range(index))
424 edit_new(new, upload)
428 edit_index (new, upload, new_index[answer])
432 ################################################################################
434 def edit_note(note, upload, session):
435 # Write the current data to a temporary file
436 (fd, temp_filename) = utils.temp_filename()
437 editor = os.environ.get("EDITOR","vi")
440 os.system("%s %s" % (editor, temp_filename))
441 temp_file = utils.open_file(temp_filename)
442 newnote = temp_file.read().rstrip()
445 print utils.prefix_multi_line_string(newnote," ")
446 prompt = "[D]one, Edit, Abandon, Quit ?"
448 while prompt.find(answer) == -1:
449 answer = utils.our_raw_input(prompt)
450 m = re_default_answer.search(prompt)
453 answer = answer[:1].upper()
454 os.unlink(temp_filename)
461 comment = NewComment()
462 comment.package = upload.pkg.changes["source"]
463 comment.version = upload.pkg.changes["version"]
464 comment.comment = newnote
465 comment.author = utils.whoami()
466 comment.trainee = bool(Options["Trainee"])
470 ################################################################################
472 def check_pkg (upload):
474 less_fd = os.popen("less -R -", 'w', 0)
475 stdout_fd = sys.stdout
478 changes = utils.parse_changes (upload.pkg.changes_file)
479 examine_package.display_changes(changes['distribution'], upload.pkg.changes_file)
480 files = upload.pkg.files
481 for f in files.keys():
482 if files[f].has_key("new"):
483 ftype = files[f]["type"]
485 examine_package.check_deb(changes['distribution'], f)
487 examine_package.check_dsc(changes['distribution'], f)
489 examine_package.output_package_relations()
490 sys.stdout = stdout_fd
492 if e.errno == errno.EPIPE:
493 utils.warn("[examine_package] Caught EPIPE; skipping.")
497 except KeyboardInterrupt:
498 utils.warn("[examine_package] Caught C-c; skipping.")
501 ################################################################################
503 ## FIXME: horribly Debian specific
505 def do_bxa_notification(upload):
506 files = upload.pkg.files
508 for f in files.keys():
509 if files[f]["type"] == "deb":
510 control = apt_pkg.ParseSection(apt_inst.debExtractControl(utils.open_file(f)))
512 summary += "Package: %s\n" % (control.Find("Package"))
513 summary += "Description: %s\n" % (control.Find("Description"))
514 upload.Subst["__BINARY_DESCRIPTIONS__"] = summary
515 bxa_mail = utils.TemplateSubst(upload.Subst,Config()["Dir::Templates"]+"/process-new.bxa_notification")
516 utils.send_mail(bxa_mail)
518 ################################################################################
520 def add_overrides (new, upload, session):
521 changes = upload.pkg.changes
522 files = upload.pkg.files
523 srcpkg = changes.get("source")
525 for suite in changes["suite"].keys():
526 suite_id = get_suite(suite).suite_id
527 for pkg in new.keys():
528 component_id = get_component(new[pkg]["component"]).component_id
529 type_id = get_override_type(new[pkg]["type"]).overridetype_id
530 priority_id = new[pkg]["priority id"]
531 section_id = new[pkg]["section id"]
532 Logger.log(["%s overrides" % (srcpkg), suite, new[pkg]["component"], new[pkg]["type"], new[pkg]["priority"], new[pkg]["section"]])
533 session.execute("INSERT INTO override (suite, component, type, package, priority, section, maintainer) VALUES (:sid, :cid, :tid, :pkg, :pid, :sectid, '')",
534 { 'sid': suite_id, 'cid': component_id, 'tid':type_id, 'pkg': pkg, 'pid': priority_id, 'sectid': section_id})
535 for f in new[pkg]["files"]:
536 if files[f].has_key("new"):
542 if Config().FindB("Dinstall::BXANotify"):
543 do_bxa_notification(upload)
545 ################################################################################
547 def prod_maintainer (note, upload):
549 # Here we prepare an editor and get them ready to prod...
550 (fd, temp_filename) = utils.temp_filename()
551 temp_file = os.fdopen(fd, 'w')
554 temp_file.write(line)
556 editor = os.environ.get("EDITOR","vi")
559 os.system("%s %s" % (editor, temp_filename))
560 temp_fh = utils.open_file(temp_filename)
561 prod_message = "".join(temp_fh.readlines())
563 print "Prod message:"
564 print utils.prefix_multi_line_string(prod_message," ",include_blank_lines=1)
565 prompt = "[P]rod, Edit, Abandon, Quit ?"
567 while prompt.find(answer) == -1:
568 answer = utils.our_raw_input(prompt)
569 m = re_default_answer.search(prompt)
572 answer = answer[:1].upper()
573 os.unlink(temp_filename)
579 # Otherwise, do the proding...
580 user_email_address = utils.whoami() + " <%s>" % (
581 cnf["Dinstall::MyAdminAddress"])
585 Subst["__FROM_ADDRESS__"] = user_email_address
586 Subst["__PROD_MESSAGE__"] = prod_message
587 Subst["__CC__"] = "Cc: " + cnf["Dinstall::MyEmailAddress"]
589 prod_mail_message = utils.TemplateSubst(
590 Subst,cnf["Dir::Templates"]+"/process-new.prod")
592 # Send the prod mail if appropriate
593 if not cnf["Dinstall::Options::No-Mail"]:
594 utils.send_mail(prod_mail_message)
596 print "Sent proding message"
598 ################################################################################
600 def do_new(upload, session):
602 files = upload.pkg.files
603 upload.check_files(not Options["No-Action"])
604 changes = upload.pkg.changes
607 # Check for a valid distribution
608 upload.check_distributions()
610 # Make a copy of distribution we can happily trample on
611 changes["suite"] = copy.copy(changes["distribution"])
613 # Fix up the list of target suites
614 for suite in changes["suite"].keys():
615 override = cnf.Find("Suite::%s::OverrideSuite" % (suite))
617 (olderr, newerr) = (get_suite(suite, session) == None,
618 get_suite(override, session) == None)
620 (oinv, newinv) = ("", "")
621 if olderr: oinv = "invalid "
622 if newerr: ninv = "invalid "
623 print "warning: overriding %ssuite %s to %ssuite %s" % (
624 oinv, suite, ninv, override)
625 del changes["suite"][suite]
626 changes["suite"][override] = 1
628 # The main NEW processing loop
631 # Find out what's new
632 new = determine_new(changes, files)
638 if Options["No-Action"] or Options["Automatic"]:
641 (broken, note) = print_new(new, upload, indexed=0)
644 if not broken and not note:
645 prompt = "Add overrides, "
647 print "W: [!] marked entries must be fixed before package can be processed."
649 print "W: note must be removed before package can be processed."
650 prompt += "RemOve all notes, Remove note, "
652 prompt += "Edit overrides, Check, Manual reject, Note edit, Prod, [S]kip, Quit ?"
654 while prompt.find(answer) == -1:
655 answer = utils.our_raw_input(prompt)
656 m = re_default_answer.search(prompt)
659 answer = answer[:1].upper()
661 if answer in ( 'A', 'E', 'M', 'O', 'R' ) and Options["Trainee"]:
662 utils.warn("Trainees can't do that")
665 if answer == 'A' and not Options["Trainee"]:
668 done = add_overrides (new, upload, session)
669 do_accept(upload, session)
670 Logger.log(["NEW ACCEPT: %s" % (upload.pkg.changes_file)])
671 except CantGetLockError:
672 print "Hello? Operator! Give me the number for 911!"
673 print "Dinstall in the locked area, cant process packages, come back later"
676 elif answer == 'E' and not Options["Trainee"]:
677 new = edit_overrides (new, upload, session)
678 elif answer == 'M' and not Options["Trainee"]:
679 aborted = upload.do_reject(manual=1,
680 reject_message=Options["Manual-Reject"],
681 note=get_new_comments(changes.get("source", ""), session=session))
683 upload.pkg.remove_known_changes(session=session)
684 Logger.log(["NEW REJECT: %s" % (upload.pkg.changes_file)])
687 edit_note(get_new_comments(changes.get("source", ""), session=session),
689 elif answer == 'P' and not Options["Trainee"]:
690 prod_maintainer(get_new_comments(changes.get("source", ""), session=session),
692 Logger.log(["NEW PROD: %s" % (upload.pkg.changes_file)])
693 elif answer == 'R' and not Options["Trainee"]:
694 confirm = utils.our_raw_input("Really clear note (y/N)? ").lower()
696 for c in get_new_comments(changes.get("source", ""), changes.get("version", ""), session=session):
699 elif answer == 'O' and not Options["Trainee"]:
700 confirm = utils.our_raw_input("Really clear all notes (y/N)? ").lower()
702 for c in get_new_comments(changes.get("source", ""), session=session):
712 ################################################################################
713 ################################################################################
714 ################################################################################
716 def usage (exit_code=0):
717 print """Usage: dak process-new [OPTION]... [CHANGES]...
718 -a, --automatic automatic run
719 -h, --help show this help and exit.
720 -m, --manual-reject=MSG manual reject with `msg'
721 -n, --no-action don't do anything
722 -t, --trainee FTP Trainee mode
723 -V, --version display the version number and exit"""
726 ################################################################################
728 def do_byhand(upload, session):
731 files = upload.pkg.files
735 for f in files.keys():
736 if files[f]["type"] == "byhand":
737 if os.path.exists(f):
738 print "W: %s still present; please process byhand components and try again." % (f)
744 if Options["No-Action"]:
747 if Options["Automatic"] and not Options["No-Action"]:
749 prompt = "[A]ccept, Manual reject, Skip, Quit ?"
751 prompt = "Manual reject, [S]kip, Quit ?"
753 while prompt.find(answer) == -1:
754 answer = utils.our_raw_input(prompt)
755 m = re_default_answer.search(prompt)
758 answer = answer[:1].upper()
766 Logger.log(["BYHAND ACCEPT: %s" % (upload.pkg.changes_file)])
767 except CantGetLockError:
768 print "Hello? Operator! Give me the number for 911!"
769 print "Dinstall in the locked area, cant process packages, come back later"
771 Logger.log(["BYHAND REJECT: %s" % (upload.pkg.changes_file)])
772 upload.do_reject(manual=1, reject_message=Options["Manual-Reject"])
773 upload.pkg.remove_known_changes(session=session)
781 ################################################################################
783 def check_daily_lock():
785 Raises CantGetLockError if the dinstall daily.lock exists.
790 os.open(cnf["Process-New::DinstallLockFile"],
791 os.O_RDONLY | os.O_CREAT | os.O_EXCL)
793 if e.errno == errno.EEXIST or e.errno == errno.EACCES:
794 raise CantGetLockError
796 os.unlink(cnf["Process-New::DinstallLockFile"])
799 @contextlib.contextmanager
800 def lock_package(package):
802 Lock C{package} so that noone else jumps in processing it.
804 @type package: string
805 @param package: source package name to lock
808 path = os.path.join(Config()["Process-New::LockDir"], package)
810 fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_RDONLY)
812 if e.errno == errno.EEXIST or e.errno == errno.EACCES:
813 user = pwd.getpwuid(os.stat(path)[stat.ST_UID])[4].split(',')[0].replace('.', '')
814 raise AlreadyLockedError, user
821 class clean_holding(object):
822 def __init__(self,pkg):
828 def __exit__(self, type, value, traceback):
831 for f in self.pkg.files.keys():
832 if os.path.exists(os.path.join(h.holding_dir, f)):
833 os.unlink(os.path.join(h.holding_dir, f))
837 def changes_to_newstage(upload, session):
838 """move a changes file to newstage"""
839 new = get_policy_queue('new', session );
840 newstage = get_policy_queue('newstage', session );
842 chg = session.query(DBChange).filter_by(changesname=os.path.basename(upload.pkg.changes_file)).one()
843 chg.approved_for = newstage.policy_queue_id
846 # update the changes_pending_files row
848 utils.move(os.path.join(new.path, f.filename), newstage.path, perms=int(newstage.perms, 8))
850 utils.move(os.path.join(new.path, upload.pkg.changes_file), newstage.path, perms=int(newstage.perms, 8))
851 chg.in_queue = newstage
854 def _accept(upload, session):
855 if Options["No-Action"]:
857 (summary, short_summary) = upload.build_summaries()
858 # upload.accept(summary, short_summary, targetqueue)
860 changes_to_newstage(upload, session)
862 def do_accept(upload, session):
865 if not Options["No-Action"]:
866 (summary, short_summary) = upload.build_summaries()
868 if cnf.FindB("Dinstall::SecurityQueueHandling"):
869 upload.dump_vars(cnf["Dir::Queue::Embargoed"])
870 upload.move_to_queue(get_policy_queue('embargoed'))
871 upload.queue_build("embargoed", cnf["Dir::Queue::Embargoed"])
872 # Check for override disparities
873 upload.Subst["__SUMMARY__"] = summary
875 # Just a normal upload, accept it...
876 _accept(upload, session)
878 def do_pkg(changes_file, session):
879 new_queue = get_policy_queue('new', session );
881 u.pkg.changes_file = changes_file
882 (u.pkg.changes["fingerprint"], rejects) = utils.check_signature(changes_file)
883 u.load_changes(changes_file)
884 u.pkg.directory = new_queue.path
887 origchanges = os.path.abspath(u.pkg.changes_file)
890 bcc = "X-DAK: dak process-new"
891 if cnf.has_key("Dinstall::Bcc"):
892 u.Subst["__BCC__"] = bcc + "\nBcc: %s" % (cnf["Dinstall::Bcc"])
894 u.Subst["__BCC__"] = bcc
897 for deb_filename, f in files.items():
898 if deb_filename.endswith(".udeb") or deb_filename.endswith(".deb"):
899 u.binary_file_checks(deb_filename, session)
900 u.check_binary_against_db(deb_filename, session)
902 u.source_file_checks(deb_filename, session)
903 u.check_source_against_db(deb_filename, session)
905 u.pkg.changes["suite"] = copy.copy(u.pkg.changes["distribution"])
908 with lock_package(u.pkg.changes["source"]):
909 with clean_holding(u.pkg):
910 if not recheck(u, session):
913 # FIXME: This does need byhand checks added!
914 new = determine_new(u.pkg.changes, files)
920 do_accept(u, session)
921 except CantGetLockError:
922 print "Hello? Operator! Give me the number for 911!"
923 print "Dinstall in the locked area, cant process packages, come back later"
924 # (new, byhand) = check_status(files)
929 # do_byhand(u, session)
930 # (new, byhand) = check_status(files)
932 # if not new and not byhand:
936 # except CantGetLockError:
937 # print "Hello? Operator! Give me the number for 911!"
938 # print "Dinstall in the locked area, cant process packages, come back later"
939 except AlreadyLockedError, e:
940 print "Seems to be locked by %s already, skipping..." % (e)
942 ################################################################################
945 accept_count = SummaryStats().accept_count
946 accept_bytes = SummaryStats().accept_bytes
952 sys.stderr.write("Accepted %d package %s, %s.\n" % (accept_count, sets, utils.size_type(int(accept_bytes))))
953 Logger.log(["total",accept_count,accept_bytes])
955 if not Options["No-Action"] and not Options["Trainee"]:
958 ################################################################################
961 global Options, Logger, Sections, Priorities
964 session = DBConn().session()
966 Arguments = [('a',"automatic","Process-New::Options::Automatic"),
967 ('h',"help","Process-New::Options::Help"),
968 ('m',"manual-reject","Process-New::Options::Manual-Reject", "HasArg"),
969 ('t',"trainee","Process-New::Options::Trainee"),
970 ('n',"no-action","Process-New::Options::No-Action")]
972 for i in ["automatic", "help", "manual-reject", "no-action", "version", "trainee"]:
973 if not cnf.has_key("Process-New::Options::%s" % (i)):
974 cnf["Process-New::Options::%s" % (i)] = ""
976 changes_files = apt_pkg.ParseCommandLine(cnf.Cnf,Arguments,sys.argv)
977 if len(changes_files) == 0:
978 new_queue = get_policy_queue('new', session );
979 changes_files = utils.get_changes_files(new_queue.path)
981 Options = cnf.SubTree("Process-New::Options")
986 if not Options["No-Action"]:
988 Logger = daklog.Logger(cnf, "process-new")
989 except CantOpenError, e:
990 Options["Trainee"] = "True"
992 Sections = Section_Completer(session)
993 Priorities = Priority_Completer(session)
994 readline.parse_and_bind("tab: complete")
996 if len(changes_files) > 1:
997 sys.stderr.write("Sorting changes...\n")
998 changes_files = sort_changes(changes_files, session)
1000 # Kill me now? **FIXME**
1001 cnf["Dinstall::Options::No-Mail"] = ""
1003 for changes_file in changes_files:
1004 changes_file = utils.validate_changes_file_arg(changes_file, 0)
1005 if not changes_file:
1007 print "\n" + changes_file
1009 do_pkg (changes_file, session)
1013 ################################################################################
1015 if __name__ == '__main__':