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" + upload.rejects.join("\n"),
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=upload.rejects.join("\n"))
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([utils.getusername(), "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([utils.getusername(), "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([utils.getusername(), "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 -m, --manual-reject=MSG manual reject with `msg'
749 -n, --no-action don't do anything
750 -t, --trainee FTP Trainee mode
751 -V, --version display the version number and exit"""
754 ################################################################################
756 def do_byhand(upload, session):
759 files = upload.pkg.files
763 for f in files.keys():
764 if files[f]["type"] == "byhand":
765 if os.path.exists(f):
766 print "W: %s still present; please process byhand components and try again." % (f)
772 if Options["No-Action"]:
775 if Options["Automatic"] and not Options["No-Action"]:
777 prompt = "[A]ccept, Manual reject, Skip, Quit ?"
779 prompt = "Manual reject, [S]kip, Quit ?"
781 while prompt.find(answer) == -1:
782 answer = utils.our_raw_input(prompt)
783 m = re_default_answer.search(prompt)
786 answer = answer[:1].upper()
794 Logger.log([utils.getusername(), "BYHAND ACCEPT: %s" % (upload.pkg.changes_file)])
795 except CantGetLockError:
796 print "Hello? Operator! Give me the number for 911!"
797 print "Dinstall in the locked area, cant process packages, come back later"
799 Logger.log([utils.getusername(), "BYHAND REJECT: %s" % (upload.pkg.changes_file)])
800 upload.do_reject(manual=1, reject_message=Options["Manual-Reject"])
801 os.unlink(upload.pkg.changes_file[:-8]+".dak")
809 ################################################################################
811 def check_daily_lock():
813 Raises CantGetLockError if the dinstall daily.lock exists.
818 os.open(cnf["Process-New::DinstallLockFile"],
819 os.O_RDONLY | os.O_CREAT | os.O_EXCL)
821 if e.errno == errno.EEXIST or e.errno == errno.EACCES:
822 raise CantGetLockError
824 os.unlink(cnf["Process-New::DinstallLockFile"])
827 @contextlib.contextmanager
828 def lock_package(package):
830 Lock C{package} so that noone else jumps in processing it.
832 @type package: string
833 @param package: source package name to lock
836 path = os.path.join(Config()["Process-New::LockDir"], package)
838 fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_RDONLY)
840 if e.errno == errno.EEXIST or e.errno == errno.EACCES:
841 user = pwd.getpwuid(os.stat(path)[stat.ST_UID])[4].split(',')[0].replace('.', '')
842 raise AlreadyLockedError, user
850 if Options["No-Action"]:
852 (summary, short_summary) = upload.build_summaries()
853 upload.accept(summary, short_summary, targetdir=Config()["Dir::Queue::Newstage"])
854 os.unlink(upload.pkg.changes_file[:-8]+".dak")
856 def do_accept(upload):
859 if not Options["No-Action"]:
860 (summary, short_summary) = upload.build_summaries()
862 if cnf.FindB("Dinstall::SecurityQueueHandling"):
863 upload.dump_vars(cnf["Dir::Queue::Embargoed"])
864 upload.move_to_dir(cnf["Dir::Queue::Embargoed"])
865 upload.queue_build("embargoed", cnf["Dir::Queue::Embargoed"])
866 # Check for override disparities
867 upload.Subst["__SUMMARY__"] = summary
869 # Just a normal upload, accept it...
872 def check_status(files):
874 for f in files.keys():
875 if files[f]["type"] == "byhand":
877 elif files[f].has_key("new"):
881 def do_pkg(changes_file, session):
883 u.pkg.load_dot_dak(changes_file)
887 bcc = "X-DAK: dak process-new\nX-Katie: lisa $Revision: 1.31 $"
888 if cnf.has_key("Dinstall::Bcc"):
889 u.Subst["__BCC__"] = bcc + "\nBcc: %s" % (cnf["Dinstall::Bcc"])
891 u.Subst["__BCC__"] = bcc
896 with lock_package(u.pkg.changes["source"]):
897 if not recheck(u, session):
900 (new, byhand) = check_status(files)
905 do_byhand(u, session)
906 (new, byhand) = check_status(files)
908 if not new and not byhand:
912 except CantGetLockError:
913 print "Hello? Operator! Give me the number for 911!"
914 print "Dinstall in the locked area, cant process packages, come back later"
915 except AlreadyLockedError, e:
916 print "Seems to be locked by %s already, skipping..." % (e)
918 ################################################################################
921 accept_count = SummaryStats().accept_count
922 accept_bytes = SummaryStats().accept_bytes
928 sys.stderr.write("Accepted %d package %s, %s.\n" % (accept_count, sets, utils.size_type(int(accept_bytes))))
929 Logger.log([utils.getusername(), "total",accept_count,accept_bytes])
931 if not Options["No-Action"] and not Options["Trainee"]:
934 ################################################################################
937 global Options, Logger, Sections, Priorities
940 session = DBConn().session()
942 Arguments = [('a',"automatic","Process-New::Options::Automatic"),
943 ('h',"help","Process-New::Options::Help"),
944 ('m',"manual-reject","Process-New::Options::Manual-Reject", "HasArg"),
945 ('t',"trainee","Process-New::Options::Trainee"),
946 ('n',"no-action","Process-New::Options::No-Action")]
948 for i in ["automatic", "help", "manual-reject", "no-action", "version", "trainee"]:
949 if not cnf.has_key("Process-New::Options::%s" % (i)):
950 cnf["Process-New::Options::%s" % (i)] = ""
952 changes_files = apt_pkg.ParseCommandLine(cnf.Cnf,Arguments,sys.argv)
953 if len(changes_files) == 0:
954 changes_files = utils.get_changes_files(cnf["Dir::Queue::New"])
956 Options = cnf.SubTree("Process-New::Options")
961 if not Options["No-Action"]:
963 Logger = daklog.Logger(cnf, "process-new")
964 except CantOpenError, e:
965 Options["Trainee"] = "True"
967 Sections = Section_Completer(session)
968 Priorities = Priority_Completer(session)
969 readline.parse_and_bind("tab: complete")
971 if len(changes_files) > 1:
972 sys.stderr.write("Sorting changes...\n")
973 changes_files = sort_changes(changes_files, session)
975 # Kill me now? **FIXME**
976 cnf["Dinstall::Options::No-Mail"] = ""
978 for changes_file in changes_files:
979 changes_file = utils.validate_changes_file_arg(changes_file, 0)
982 print "\n" + changes_file
984 do_pkg (changes_file, session)
988 ################################################################################
990 if __name__ == '__main__':