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 # Fix up the list of target suites
615 for suite in changes["suite"].keys():
616 override = cnf.Find("Suite::%s::OverrideSuite" % (suite))
618 (olderr, newerr) = (get_suite(suite, session) == None,
619 get_suite(override, session) == None)
621 (oinv, newinv) = ("", "")
622 if olderr: oinv = "invalid "
623 if newerr: ninv = "invalid "
624 print "warning: overriding %ssuite %s to %ssuite %s" % (
625 oinv, suite, ninv, override)
626 del changes["suite"][suite]
627 changes["suite"][override] = 1
629 # The main NEW processing loop
632 # Find out what's new
633 new = determine_new(changes, files)
639 if Options["No-Action"] or Options["Automatic"]:
642 (broken, note) = print_new(new, upload, indexed=0)
645 if not broken and not note:
646 prompt = "Add overrides, "
648 print "W: [!] marked entries must be fixed before package can be processed."
650 print "W: note must be removed before package can be processed."
651 prompt += "RemOve all notes, Remove note, "
653 prompt += "Edit overrides, Check, Manual reject, Note edit, Prod, [S]kip, Quit ?"
655 while prompt.find(answer) == -1:
656 answer = utils.our_raw_input(prompt)
657 m = re_default_answer.search(prompt)
660 answer = answer[:1].upper()
662 if answer in ( 'A', 'E', 'M', 'O', 'R' ) and Options["Trainee"]:
663 utils.warn("Trainees can't do that")
666 if answer == 'A' and not Options["Trainee"]:
669 done = add_overrides (new, upload, session)
670 do_accept(upload, session)
671 Logger.log(["NEW ACCEPT: %s" % (upload.pkg.changes_file)])
672 except CantGetLockError:
673 print "Hello? Operator! Give me the number for 911!"
674 print "Dinstall in the locked area, cant process packages, come back later"
677 elif answer == 'E' and not Options["Trainee"]:
678 new = edit_overrides (new, upload, session)
679 elif answer == 'M' and not Options["Trainee"]:
680 aborted = upload.do_reject(manual=1,
681 reject_message=Options["Manual-Reject"],
682 note=get_new_comments(changes.get("source", ""), session=session))
684 upload.pkg.remove_known_changes(session=session)
686 Logger.log(["NEW REJECT: %s" % (upload.pkg.changes_file)])
689 edit_note(get_new_comments(changes.get("source", ""), session=session),
691 elif answer == 'P' and not Options["Trainee"]:
692 prod_maintainer(get_new_comments(changes.get("source", ""), session=session),
694 Logger.log(["NEW PROD: %s" % (upload.pkg.changes_file)])
695 elif answer == 'R' and not Options["Trainee"]:
696 confirm = utils.our_raw_input("Really clear note (y/N)? ").lower()
698 for c in get_new_comments(changes.get("source", ""), changes.get("version", ""), session=session):
701 elif answer == 'O' and not Options["Trainee"]:
702 confirm = utils.our_raw_input("Really clear all notes (y/N)? ").lower()
704 for c in get_new_comments(changes.get("source", ""), session=session):
714 ################################################################################
715 ################################################################################
716 ################################################################################
718 def usage (exit_code=0):
719 print """Usage: dak process-new [OPTION]... [CHANGES]...
720 -a, --automatic automatic run
721 -h, --help show this help and exit.
722 -m, --manual-reject=MSG manual reject with `msg'
723 -n, --no-action don't do anything
724 -t, --trainee FTP Trainee mode
725 -V, --version display the version number and exit"""
728 ################################################################################
730 def do_byhand(upload, session):
733 files = upload.pkg.files
737 for f in files.keys():
738 if files[f]["type"] == "byhand":
739 if os.path.exists(f):
740 print "W: %s still present; please process byhand components and try again." % (f)
746 if Options["No-Action"]:
749 if Options["Automatic"] and not Options["No-Action"]:
751 prompt = "[A]ccept, Manual reject, Skip, Quit ?"
753 prompt = "Manual reject, [S]kip, Quit ?"
755 while prompt.find(answer) == -1:
756 answer = utils.our_raw_input(prompt)
757 m = re_default_answer.search(prompt)
760 answer = answer[:1].upper()
768 Logger.log(["BYHAND ACCEPT: %s" % (upload.pkg.changes_file)])
769 except CantGetLockError:
770 print "Hello? Operator! Give me the number for 911!"
771 print "Dinstall in the locked area, cant process packages, come back later"
773 Logger.log(["BYHAND REJECT: %s" % (upload.pkg.changes_file)])
774 upload.do_reject(manual=1, reject_message=Options["Manual-Reject"])
775 upload.pkg.remove_known_changes(session=session)
784 ################################################################################
786 def check_daily_lock():
788 Raises CantGetLockError if the dinstall daily.lock exists.
793 os.open(cnf["Process-New::DinstallLockFile"],
794 os.O_RDONLY | os.O_CREAT | os.O_EXCL)
796 if e.errno == errno.EEXIST or e.errno == errno.EACCES:
797 raise CantGetLockError
799 os.unlink(cnf["Process-New::DinstallLockFile"])
802 @contextlib.contextmanager
803 def lock_package(package):
805 Lock C{package} so that noone else jumps in processing it.
807 @type package: string
808 @param package: source package name to lock
811 path = os.path.join(Config()["Process-New::LockDir"], package)
813 fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_RDONLY)
815 if e.errno == errno.EEXIST or e.errno == errno.EACCES:
816 user = pwd.getpwuid(os.stat(path)[stat.ST_UID])[4].split(',')[0].replace('.', '')
817 raise AlreadyLockedError, user
824 class clean_holding(object):
825 def __init__(self,pkg):
831 def __exit__(self, type, value, traceback):
834 for f in self.pkg.files.keys():
835 if os.path.exists(os.path.join(h.holding_dir, f)):
836 os.unlink(os.path.join(h.holding_dir, f))
840 def changes_to_newstage(upload, session):
841 """move a changes file to newstage"""
842 new = get_policy_queue('new', session );
843 newstage = get_policy_queue('newstage', session );
845 chg = session.query(DBChange).filter_by(changesname=os.path.basename(upload.pkg.changes_file)).one()
846 chg.approved_for = newstage.policy_queue_id
849 # update the changes_pending_files row
851 utils.move(os.path.join(new.path, f.filename), newstage.path, perms=int(newstage.perms, 8))
853 utils.move(os.path.join(new.path, upload.pkg.changes_file), newstage.path, perms=int(newstage.perms, 8))
854 chg.in_queue = newstage
857 def _accept(upload, session):
858 if Options["No-Action"]:
860 (summary, short_summary) = upload.build_summaries()
861 # upload.accept(summary, short_summary, targetqueue)
863 changes_to_newstage(upload, session)
865 def do_accept(upload, session):
868 if not Options["No-Action"]:
869 (summary, short_summary) = upload.build_summaries()
871 if cnf.FindB("Dinstall::SecurityQueueHandling"):
872 upload.dump_vars(cnf["Dir::Queue::Embargoed"])
873 upload.move_to_queue(get_policy_queue('embargoed'))
874 upload.queue_build("embargoed", cnf["Dir::Queue::Embargoed"])
875 # Check for override disparities
876 upload.Subst["__SUMMARY__"] = summary
878 # Just a normal upload, accept it...
879 _accept(upload, session)
881 def do_pkg(changes_file, session):
882 new_queue = get_policy_queue('new', session );
884 u.pkg.changes_file = changes_file
885 (u.pkg.changes["fingerprint"], rejects) = utils.check_signature(changes_file)
886 u.load_changes(changes_file)
887 u.pkg.directory = new_queue.path
890 origchanges = os.path.abspath(u.pkg.changes_file)
893 bcc = "X-DAK: dak process-new"
894 if cnf.has_key("Dinstall::Bcc"):
895 u.Subst["__BCC__"] = bcc + "\nBcc: %s" % (cnf["Dinstall::Bcc"])
897 u.Subst["__BCC__"] = bcc
900 for deb_filename, f in files.items():
901 if deb_filename.endswith(".udeb") or deb_filename.endswith(".deb"):
902 u.binary_file_checks(deb_filename, session)
903 u.check_binary_against_db(deb_filename, session)
905 u.source_file_checks(deb_filename, session)
906 u.check_source_against_db(deb_filename, session)
908 u.pkg.changes["suite"] = copy.copy(u.pkg.changes["distribution"])
911 with lock_package(u.pkg.changes["source"]):
912 with clean_holding(u.pkg):
913 if not recheck(u, session):
916 # FIXME: This does need byhand checks added!
917 new = determine_new(u.pkg.changes, files)
923 do_accept(u, session)
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 # (new, byhand) = check_status(files)
932 # do_byhand(u, session)
933 # (new, byhand) = check_status(files)
935 # if not new and not byhand:
939 # except CantGetLockError:
940 # print "Hello? Operator! Give me the number for 911!"
941 # print "Dinstall in the locked area, cant process packages, come back later"
942 except AlreadyLockedError, e:
943 print "Seems to be locked by %s already, skipping..." % (e)
945 ################################################################################
948 accept_count = SummaryStats().accept_count
949 accept_bytes = SummaryStats().accept_bytes
955 sys.stderr.write("Accepted %d package %s, %s.\n" % (accept_count, sets, utils.size_type(int(accept_bytes))))
956 Logger.log(["total",accept_count,accept_bytes])
958 if not Options["No-Action"] and not Options["Trainee"]:
961 ################################################################################
964 global Options, Logger, Sections, Priorities
967 session = DBConn().session()
969 Arguments = [('a',"automatic","Process-New::Options::Automatic"),
970 ('h',"help","Process-New::Options::Help"),
971 ('m',"manual-reject","Process-New::Options::Manual-Reject", "HasArg"),
972 ('t',"trainee","Process-New::Options::Trainee"),
973 ('n',"no-action","Process-New::Options::No-Action")]
975 for i in ["automatic", "help", "manual-reject", "no-action", "version", "trainee"]:
976 if not cnf.has_key("Process-New::Options::%s" % (i)):
977 cnf["Process-New::Options::%s" % (i)] = ""
979 changes_files = apt_pkg.ParseCommandLine(cnf.Cnf,Arguments,sys.argv)
980 if len(changes_files) == 0:
981 new_queue = get_policy_queue('new', session );
982 changes_files = utils.get_changes_files(new_queue.path)
984 Options = cnf.SubTree("Process-New::Options")
989 if not Options["No-Action"]:
991 Logger = daklog.Logger(cnf, "process-new")
992 except CantOpenError, e:
993 Options["Trainee"] = "True"
995 Sections = Section_Completer(session)
996 Priorities = Priority_Completer(session)
997 readline.parse_and_bind("tab: complete")
999 if len(changes_files) > 1:
1000 sys.stderr.write("Sorting changes...\n")
1001 changes_files = sort_changes(changes_files, session)
1003 # Kill me now? **FIXME**
1004 cnf["Dinstall::Options::No-Mail"] = ""
1006 for changes_file in changes_files:
1007 changes_file = utils.validate_changes_file_arg(changes_file, 0)
1008 if not changes_file:
1010 print "\n" + changes_file
1012 do_pkg (changes_file, session)
1016 ################################################################################
1018 if __name__ == '__main__':