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)
109 ################################################################################
111 def indiv_sg_compare (a, b):
112 """Sort by source name, source, version, 'have source', and
113 finally by filename."""
114 # Sort by source version
115 q = apt_pkg.VersionCompare(a["version"], b["version"])
119 # Sort by 'have source'
120 a_has_source = a["architecture"].get("source")
121 b_has_source = b["architecture"].get("source")
122 if a_has_source and not b_has_source:
124 elif b_has_source and not a_has_source:
127 return cmp(a["filename"], b["filename"])
129 ############################################################
131 def sg_compare (a, b):
134 """Sort by have note, source already in database and time of oldest upload."""
136 a_note_state = a["note_state"]
137 b_note_state = b["note_state"]
138 if a_note_state < b_note_state:
140 elif a_note_state > b_note_state:
142 # Sort by source already in database (descending)
143 source_in_database = cmp(a["source_in_database"], b["source_in_database"])
144 if source_in_database:
145 return -source_in_database
147 # Sort by time of oldest upload
148 return cmp(a["oldest"], b["oldest"])
150 def sort_changes(changes_files, session):
151 """Sort into source groups, then sort each source group by version,
152 have source, filename. Finally, sort the source groups by have
153 note, time of oldest upload of each source upload."""
154 if len(changes_files) == 1:
159 # Read in all the .changes files
160 for filename in changes_files:
163 u.pkg.changes_file = filename
164 u.load_changes(filename)
166 cache[filename] = copy.copy(u.pkg.changes)
167 cache[filename]["filename"] = filename
169 sorted_list.append(filename)
171 # Divide the .changes into per-source groups
173 for filename in cache.keys():
174 source = cache[filename]["source"]
175 if not per_source.has_key(source):
176 per_source[source] = {}
177 per_source[source]["list"] = []
178 per_source[source]["list"].append(cache[filename])
179 # Determine oldest time and have note status for each source group
180 for source in per_source.keys():
181 q = session.query(DBSource).filter_by(source = source).all()
182 per_source[source]["source_in_database"] = len(q)>0
183 source_list = per_source[source]["list"]
184 first = source_list[0]
185 oldest = os.stat(first["filename"])[stat.ST_MTIME]
187 for d in per_source[source]["list"]:
188 mtime = os.stat(d["filename"])[stat.ST_MTIME]
191 have_note += has_new_comment(d["source"], d["version"], session)
192 per_source[source]["oldest"] = oldest
194 per_source[source]["note_state"] = 0; # none
195 elif have_note < len(source_list):
196 per_source[source]["note_state"] = 1; # some
198 per_source[source]["note_state"] = 2; # all
199 per_source[source]["list"].sort(indiv_sg_compare)
200 per_source_items = per_source.items()
201 per_source_items.sort(sg_compare)
202 for i in per_source_items:
203 for j in i[1]["list"]:
204 sorted_list.append(j["filename"])
207 ################################################################################
209 class Section_Completer:
210 def __init__ (self, session):
213 for s, in session.query(Section.section):
214 self.sections.append(s)
216 def complete(self, text, state):
220 for word in self.sections:
222 self.matches.append(word)
224 return self.matches[state]
228 ############################################################
230 class Priority_Completer:
231 def __init__ (self, session):
234 for p, in session.query(Priority.priority):
235 self.priorities.append(p)
237 def complete(self, text, state):
241 for word in self.priorities:
243 self.matches.append(word)
245 return self.matches[state]
249 ################################################################################
251 def print_new (new, upload, indexed, file=sys.stdout):
255 for pkg in new.keys():
257 section = new[pkg]["section"]
258 priority = new[pkg]["priority"]
259 if new[pkg]["section id"] == -1:
262 if new[pkg]["priority id"] == -1:
266 line = "(%s): %-20s %-20s %-20s" % (index, pkg, priority, section)
268 line = "%-20s %-20s %-20s" % (pkg, priority, section)
269 line = line.strip()+'\n'
271 notes = get_new_comments(upload.pkg.changes.get("source"))
273 print "\nAuthor: %s\nVersion: %s\nTimestamp: %s\n\n%s" \
274 % (note.author, note.version, note.notedate, note.comment)
276 return broken, len(notes) > 0
278 ################################################################################
280 def index_range (index):
284 return "1-%s" % (index)
286 ################################################################################
287 ################################################################################
289 def edit_new (new, upload):
290 # Write the current data to a temporary file
291 (fd, temp_filename) = utils.temp_filename()
292 temp_file = os.fdopen(fd, 'w')
293 print_new (new, upload, indexed=0, file=temp_file)
295 # Spawn an editor on that file
296 editor = os.environ.get("EDITOR","vi")
297 result = os.system("%s %s" % (editor, temp_filename))
299 utils.fubar ("%s invocation failed for %s." % (editor, temp_filename), result)
300 # Read the edited data back in
301 temp_file = utils.open_file(temp_filename)
302 lines = temp_file.readlines()
304 os.unlink(temp_filename)
311 # Pad the list if necessary
312 s[len(s):3] = [None] * (3-len(s))
313 (pkg, priority, section) = s[:3]
314 if not new.has_key(pkg):
315 utils.warn("Ignoring unknown package '%s'" % (pkg))
317 # Strip off any invalid markers, print_new will readd them.
318 if section.endswith("[!]"):
319 section = section[:-3]
320 if priority.endswith("[!]"):
321 priority = priority[:-3]
322 for f in new[pkg]["files"]:
323 upload.pkg.files[f]["section"] = section
324 upload.pkg.files[f]["priority"] = priority
325 new[pkg]["section"] = section
326 new[pkg]["priority"] = priority
328 ################################################################################
330 def edit_index (new, upload, index):
331 priority = new[index]["priority"]
332 section = new[index]["section"]
333 ftype = new[index]["type"]
336 print "\t".join([index, priority, section])
340 prompt = "[B]oth, Priority, Section, Done ? "
342 prompt = "[S]ection, Done ? "
343 edit_priority = edit_section = 0
345 while prompt.find(answer) == -1:
346 answer = utils.our_raw_input(prompt)
347 m = re_default_answer.match(prompt)
350 answer = answer[:1].upper()
357 edit_priority = edit_section = 1
363 readline.set_completer(Priorities.complete)
365 while not got_priority:
366 new_priority = utils.our_raw_input("New priority: ").strip()
367 if new_priority not in Priorities.priorities:
368 print "E: '%s' is not a valid priority, try again." % (new_priority)
371 priority = new_priority
375 readline.set_completer(Sections.complete)
377 while not got_section:
378 new_section = utils.our_raw_input("New section: ").strip()
379 if new_section not in Sections.sections:
380 print "E: '%s' is not a valid section, try again." % (new_section)
383 section = new_section
385 # Reset the readline completer
386 readline.set_completer(None)
388 for f in new[index]["files"]:
389 upload.pkg.files[f]["section"] = section
390 upload.pkg.files[f]["priority"] = priority
391 new[index]["priority"] = priority
392 new[index]["section"] = section
395 ################################################################################
397 def edit_overrides (new, upload, session):
401 print_new (new, upload, indexed=1)
408 prompt = "(%s) edit override <n>, Editor, Done ? " % (index_range(index))
411 while not got_answer:
412 answer = utils.our_raw_input(prompt)
413 if not answer.isdigit():
414 answer = answer[:1].upper()
415 if answer == "E" or answer == "D":
417 elif re_isanum.match (answer):
419 if (answer < 1) or (answer > index):
420 print "%s is not a valid index (%s). Please retry." % (answer, index_range(index))
425 edit_new(new, upload)
429 edit_index (new, upload, new_index[answer])
433 ################################################################################
435 def edit_note(note, upload, session):
436 # Write the current data to a temporary file
437 (fd, temp_filename) = utils.temp_filename()
438 editor = os.environ.get("EDITOR","vi")
441 os.system("%s %s" % (editor, temp_filename))
442 temp_file = utils.open_file(temp_filename)
443 newnote = temp_file.read().rstrip()
446 print utils.prefix_multi_line_string(newnote," ")
447 prompt = "[D]one, Edit, Abandon, Quit ?"
449 while prompt.find(answer) == -1:
450 answer = utils.our_raw_input(prompt)
451 m = re_default_answer.search(prompt)
454 answer = answer[:1].upper()
455 os.unlink(temp_filename)
462 comment = NewComment()
463 comment.package = upload.pkg.changes["source"]
464 comment.version = upload.pkg.changes["version"]
465 comment.comment = newnote
466 comment.author = utils.whoami()
467 comment.trainee = bool(Options["Trainee"])
471 ################################################################################
473 def check_pkg (upload):
475 less_fd = os.popen("less -R -", 'w', 0)
476 stdout_fd = sys.stdout
479 changes = utils.parse_changes (upload.pkg.changes_file)
480 examine_package.display_changes(changes['distribution'], upload.pkg.changes_file)
481 files = upload.pkg.files
482 for f in files.keys():
483 if files[f].has_key("new"):
484 ftype = files[f]["type"]
486 examine_package.check_deb(changes['distribution'], f)
488 examine_package.check_dsc(changes['distribution'], f)
490 examine_package.output_package_relations()
491 sys.stdout = stdout_fd
493 if e.errno == errno.EPIPE:
494 utils.warn("[examine_package] Caught EPIPE; skipping.")
498 except KeyboardInterrupt:
499 utils.warn("[examine_package] Caught C-c; skipping.")
502 ################################################################################
504 ## FIXME: horribly Debian specific
506 def do_bxa_notification(upload):
507 files = upload.pkg.files
509 for f in files.keys():
510 if files[f]["type"] == "deb":
511 control = apt_pkg.ParseSection(apt_inst.debExtractControl(utils.open_file(f)))
513 summary += "Package: %s\n" % (control.Find("Package"))
514 summary += "Description: %s\n" % (control.Find("Description"))
515 upload.Subst["__BINARY_DESCRIPTIONS__"] = summary
516 bxa_mail = utils.TemplateSubst(upload.Subst,Config()["Dir::Templates"]+"/process-new.bxa_notification")
517 utils.send_mail(bxa_mail)
519 ################################################################################
521 def add_overrides (new, upload, session):
522 changes = upload.pkg.changes
523 files = upload.pkg.files
524 srcpkg = changes.get("source")
526 for suite in changes["suite"].keys():
527 suite_id = get_suite(suite).suite_id
528 for pkg in new.keys():
529 component_id = get_component(new[pkg]["component"]).component_id
530 type_id = get_override_type(new[pkg]["type"]).overridetype_id
531 priority_id = new[pkg]["priority id"]
532 section_id = new[pkg]["section id"]
533 Logger.log(["%s overrides" % (srcpkg), suite, new[pkg]["component"], new[pkg]["type"], new[pkg]["priority"], new[pkg]["section"]])
534 session.execute("INSERT INTO override (suite, component, type, package, priority, section, maintainer) VALUES (:sid, :cid, :tid, :pkg, :pid, :sectid, '')",
535 { 'sid': suite_id, 'cid': component_id, 'tid':type_id, 'pkg': pkg, 'pid': priority_id, 'sectid': section_id})
536 for f in new[pkg]["files"]:
537 if files[f].has_key("new"):
543 if Config().FindB("Dinstall::BXANotify"):
544 do_bxa_notification(upload)
546 ################################################################################
548 def prod_maintainer (note, upload):
550 # Here we prepare an editor and get them ready to prod...
551 (fd, temp_filename) = utils.temp_filename()
552 temp_file = os.fdopen(fd, 'w')
555 temp_file.write(line)
557 editor = os.environ.get("EDITOR","vi")
560 os.system("%s %s" % (editor, temp_filename))
561 temp_fh = utils.open_file(temp_filename)
562 prod_message = "".join(temp_fh.readlines())
564 print "Prod message:"
565 print utils.prefix_multi_line_string(prod_message," ",include_blank_lines=1)
566 prompt = "[P]rod, Edit, Abandon, Quit ?"
568 while prompt.find(answer) == -1:
569 answer = utils.our_raw_input(prompt)
570 m = re_default_answer.search(prompt)
573 answer = answer[:1].upper()
574 os.unlink(temp_filename)
580 # Otherwise, do the proding...
581 user_email_address = utils.whoami() + " <%s>" % (
582 cnf["Dinstall::MyAdminAddress"])
586 Subst["__FROM_ADDRESS__"] = user_email_address
587 Subst["__PROD_MESSAGE__"] = prod_message
588 Subst["__CC__"] = "Cc: " + cnf["Dinstall::MyEmailAddress"]
590 prod_mail_message = utils.TemplateSubst(
591 Subst,cnf["Dir::Templates"]+"/process-new.prod")
593 # Send the prod mail if appropriate
594 if not cnf["Dinstall::Options::No-Mail"]:
595 utils.send_mail(prod_mail_message)
597 print "Sent proding message"
599 ################################################################################
601 def do_new(upload, session):
603 files = upload.pkg.files
604 upload.check_files(not Options["No-Action"])
605 changes = upload.pkg.changes
608 # Check for a valid distribution
609 upload.check_distributions()
611 # Make a copy of distribution we can happily trample on
612 changes["suite"] = copy.copy(changes["distribution"])
614 # The main NEW processing loop
617 # Find out what's new
618 new = determine_new(changes, files)
624 if Options["No-Action"] or Options["Automatic"]:
627 (broken, note) = print_new(new, upload, indexed=0)
630 if not broken and not note:
631 prompt = "Add overrides, "
633 print "W: [!] marked entries must be fixed before package can be processed."
635 print "W: note must be removed before package can be processed."
636 prompt += "RemOve all notes, Remove note, "
638 prompt += "Edit overrides, Check, Manual reject, Note edit, Prod, [S]kip, Quit ?"
640 while prompt.find(answer) == -1:
641 answer = utils.our_raw_input(prompt)
642 m = re_default_answer.search(prompt)
645 answer = answer[:1].upper()
647 if answer in ( 'A', 'E', 'M', 'O', 'R' ) and Options["Trainee"]:
648 utils.warn("Trainees can't do that")
651 if answer == 'A' and not Options["Trainee"]:
654 done = add_overrides (new, upload, session)
655 do_accept(upload, session)
656 Logger.log(["NEW ACCEPT: %s" % (upload.pkg.changes_file)])
657 except CantGetLockError:
658 print "Hello? Operator! Give me the number for 911!"
659 print "Dinstall in the locked area, cant process packages, come back later"
662 elif answer == 'E' and not Options["Trainee"]:
663 new = edit_overrides (new, upload, session)
664 elif answer == 'M' and not Options["Trainee"]:
665 aborted = upload.do_reject(manual=1,
666 reject_message=Options["Manual-Reject"],
667 notes=get_new_comments(changes.get("source", ""), session=session))
669 upload.pkg.remove_known_changes(session=session)
671 Logger.log(["NEW REJECT: %s" % (upload.pkg.changes_file)])
674 edit_note(get_new_comments(changes.get("source", ""), session=session),
676 elif answer == 'P' and not Options["Trainee"]:
677 prod_maintainer(get_new_comments(changes.get("source", ""), session=session),
679 Logger.log(["NEW PROD: %s" % (upload.pkg.changes_file)])
680 elif answer == 'R' and not Options["Trainee"]:
681 confirm = utils.our_raw_input("Really clear note (y/N)? ").lower()
683 for c in get_new_comments(changes.get("source", ""), changes.get("version", ""), session=session):
686 elif answer == 'O' and not Options["Trainee"]:
687 confirm = utils.our_raw_input("Really clear all notes (y/N)? ").lower()
689 for c in get_new_comments(changes.get("source", ""), session=session):
699 ################################################################################
700 ################################################################################
701 ################################################################################
703 def usage (exit_code=0):
704 print """Usage: dak process-new [OPTION]... [CHANGES]...
705 -a, --automatic automatic run
706 -h, --help show this help and exit.
707 -m, --manual-reject=MSG manual reject with `msg'
708 -n, --no-action don't do anything
709 -t, --trainee FTP Trainee mode
710 -V, --version display the version number and exit"""
713 ################################################################################
715 def do_byhand(upload, session):
718 files = upload.pkg.files
722 for f in files.keys():
723 if files[f]["type"] == "byhand":
724 if os.path.exists(f):
725 print "W: %s still present; please process byhand components and try again." % (f)
731 if Options["No-Action"]:
734 if Options["Automatic"] and not Options["No-Action"]:
736 prompt = "[A]ccept, Manual reject, Skip, Quit ?"
738 prompt = "Manual reject, [S]kip, Quit ?"
740 while prompt.find(answer) == -1:
741 answer = utils.our_raw_input(prompt)
742 m = re_default_answer.search(prompt)
745 answer = answer[:1].upper()
753 Logger.log(["BYHAND ACCEPT: %s" % (upload.pkg.changes_file)])
754 except CantGetLockError:
755 print "Hello? Operator! Give me the number for 911!"
756 print "Dinstall in the locked area, cant process packages, come back later"
758 Logger.log(["BYHAND REJECT: %s" % (upload.pkg.changes_file)])
759 upload.do_reject(manual=1, reject_message=Options["Manual-Reject"])
760 upload.pkg.remove_known_changes(session=session)
769 ################################################################################
771 def check_daily_lock():
773 Raises CantGetLockError if the dinstall daily.lock exists.
778 os.open(cnf["Process-New::DinstallLockFile"],
779 os.O_RDONLY | os.O_CREAT | os.O_EXCL)
781 if e.errno == errno.EEXIST or e.errno == errno.EACCES:
782 raise CantGetLockError
784 os.unlink(cnf["Process-New::DinstallLockFile"])
787 @contextlib.contextmanager
788 def lock_package(package):
790 Lock C{package} so that noone else jumps in processing it.
792 @type package: string
793 @param package: source package name to lock
796 path = os.path.join(Config()["Process-New::LockDir"], package)
798 fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_RDONLY)
800 if e.errno == errno.EEXIST or e.errno == errno.EACCES:
801 user = pwd.getpwuid(os.stat(path)[stat.ST_UID])[4].split(',')[0].replace('.', '')
802 raise AlreadyLockedError, user
809 class clean_holding(object):
810 def __init__(self,pkg):
816 def __exit__(self, type, value, traceback):
819 for f in self.pkg.files.keys():
820 if os.path.exists(os.path.join(h.holding_dir, f)):
821 os.unlink(os.path.join(h.holding_dir, f))
825 def changes_to_newstage(upload, session):
826 """move a changes file to newstage"""
827 new = get_policy_queue('new', session );
828 newstage = get_policy_queue('newstage', session );
830 chg = session.query(DBChange).filter_by(changesname=os.path.basename(upload.pkg.changes_file)).one()
831 chg.approved_for = newstage.policy_queue_id
834 # update the changes_pending_files row
836 utils.move(os.path.join(new.path, f.filename), newstage.path, perms=int(newstage.perms, 8))
838 utils.move(os.path.join(new.path, upload.pkg.changes_file), newstage.path, perms=int(newstage.perms, 8))
839 chg.in_queue = newstage
842 def _accept(upload, session):
843 if Options["No-Action"]:
845 (summary, short_summary) = upload.build_summaries()
846 # upload.accept(summary, short_summary, targetqueue)
848 changes_to_newstage(upload, session)
850 def do_accept(upload, session):
853 if not Options["No-Action"]:
854 (summary, short_summary) = upload.build_summaries()
856 if cnf.FindB("Dinstall::SecurityQueueHandling"):
857 upload.dump_vars(cnf["Dir::Queue::Embargoed"])
858 upload.move_to_queue(get_policy_queue('embargoed'))
859 upload.queue_build("embargoed", cnf["Dir::Queue::Embargoed"])
860 # Check for override disparities
861 upload.Subst["__SUMMARY__"] = summary
863 # Just a normal upload, accept it...
864 _accept(upload, session)
866 def do_pkg(changes_file, session):
867 new_queue = get_policy_queue('new', session );
869 u.pkg.changes_file = changes_file
870 (u.pkg.changes["fingerprint"], rejects) = utils.check_signature(changes_file)
871 u.load_changes(changes_file)
872 u.pkg.directory = new_queue.path
875 origchanges = os.path.abspath(u.pkg.changes_file)
878 bcc = "X-DAK: dak process-new"
879 if cnf.has_key("Dinstall::Bcc"):
880 u.Subst["__BCC__"] = bcc + "\nBcc: %s" % (cnf["Dinstall::Bcc"])
882 u.Subst["__BCC__"] = bcc
885 for deb_filename, f in files.items():
886 if deb_filename.endswith(".udeb") or deb_filename.endswith(".deb"):
887 u.binary_file_checks(deb_filename, session)
888 u.check_binary_against_db(deb_filename, session)
890 u.source_file_checks(deb_filename, session)
891 u.check_source_against_db(deb_filename, session)
893 u.pkg.changes["suite"] = copy.copy(u.pkg.changes["distribution"])
896 with lock_package(u.pkg.changes["source"]):
897 with clean_holding(u.pkg):
898 if not recheck(u, session):
901 # FIXME: This does need byhand checks added!
902 new = determine_new(u.pkg.changes, files)
908 do_accept(u, session)
909 except CantGetLockError:
910 print "Hello? Operator! Give me the number for 911!"
911 print "Dinstall in the locked area, cant process packages, come back later"
912 # (new, byhand) = check_status(files)
917 # do_byhand(u, session)
918 # (new, byhand) = check_status(files)
920 # if not new and not byhand:
924 # except CantGetLockError:
925 # print "Hello? Operator! Give me the number for 911!"
926 # print "Dinstall in the locked area, cant process packages, come back later"
927 except AlreadyLockedError, e:
928 print "Seems to be locked by %s already, skipping..." % (e)
930 ################################################################################
933 accept_count = SummaryStats().accept_count
934 accept_bytes = SummaryStats().accept_bytes
940 sys.stderr.write("Accepted %d package %s, %s.\n" % (accept_count, sets, utils.size_type(int(accept_bytes))))
941 Logger.log(["total",accept_count,accept_bytes])
943 if not Options["No-Action"] and not Options["Trainee"]:
946 ################################################################################
949 global Options, Logger, Sections, Priorities
952 session = DBConn().session()
954 Arguments = [('a',"automatic","Process-New::Options::Automatic"),
955 ('h',"help","Process-New::Options::Help"),
956 ('m',"manual-reject","Process-New::Options::Manual-Reject", "HasArg"),
957 ('t',"trainee","Process-New::Options::Trainee"),
958 ('n',"no-action","Process-New::Options::No-Action")]
960 for i in ["automatic", "help", "manual-reject", "no-action", "version", "trainee"]:
961 if not cnf.has_key("Process-New::Options::%s" % (i)):
962 cnf["Process-New::Options::%s" % (i)] = ""
964 changes_files = apt_pkg.ParseCommandLine(cnf.Cnf,Arguments,sys.argv)
965 if len(changes_files) == 0:
966 new_queue = get_policy_queue('new', session );
967 changes_files = utils.get_changes_files(new_queue.path)
969 Options = cnf.SubTree("Process-New::Options")
974 if not Options["No-Action"]:
976 Logger = daklog.Logger(cnf, "process-new")
977 except CantOpenError, e:
978 Options["Trainee"] = "True"
980 Sections = Section_Completer(session)
981 Priorities = Priority_Completer(session)
982 readline.parse_and_bind("tab: complete")
984 if len(changes_files) > 1:
985 sys.stderr.write("Sorting changes...\n")
986 changes_files = sort_changes(changes_files, session)
988 # Kill me now? **FIXME**
989 cnf["Dinstall::Options::No-Mail"] = ""
991 for changes_file in changes_files:
992 changes_file = utils.validate_changes_file_arg(changes_file, 0)
995 print "\n" + changes_file
997 do_pkg (changes_file, session)
1001 ################################################################################
1003 if __name__ == '__main__':