2 # vim:set et ts=4 sw=4:
4 """ Handles NEW and BYHAND packages """
5 # Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 James Troup <james@nocrew.org>
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 ################################################################################
23 # 23:12|<aj> I will not hush!
25 # 23:12|<aj> Where there is injustice in the world, I shall be there!
26 # 23:13|<aj> I shall not be silenced!
27 # 23:13|<aj> The world shall know!
28 # 23:13|<aj> The world *must* know!
29 # 23:13|<elmo> oh dear, he's gone back to powerpuff girls... ;-)
30 # 23:13|<aj> yay powerpuff girls!!
31 # 23:13|<aj> buttercup's my favourite, who's yours?
32 # 23:14|<aj> you're backing away from the keyboard right now aren't you?
33 # 23:14|<aj> *AREN'T YOU*?!
34 # 23:15|<aj> I will not be treated like this.
35 # 23:15|<aj> I shall have my revenge.
36 # 23:15|<aj> I SHALL!!!
38 ################################################################################
40 import copy, errno, os, readline, stat, sys, time
41 import apt_pkg, apt_inst
42 import examine_package
43 from daklib import database
44 from daklib import logging
45 from daklib import queue
46 from daklib import utils
47 from daklib.regexes import re_no_epoch, re_default_answer, re_isanum
61 ################################################################################
62 ################################################################################
63 ################################################################################
65 def reject (str, prefix="Rejected: "):
68 reject_message += prefix + str + "\n"
72 files = Upload.pkg.files
75 for f in files.keys():
76 # The .orig.tar.gz can disappear out from under us is it's a
77 # duplicate of one in the archive.
78 if not files.has_key(f):
80 # Check that the source still exists
81 if files[f]["type"] == "deb":
82 source_version = files[f]["source version"]
83 source_package = files[f]["source package"]
84 if not Upload.pkg.changes["architecture"].has_key("source") \
85 and not Upload.source_exists(source_package, source_version, Upload.pkg.changes["distribution"].keys()):
86 source_epochless_version = re_no_epoch.sub('', source_version)
87 dsc_filename = "%s_%s.dsc" % (source_package, source_epochless_version)
89 for q in ["Accepted", "Embargoed", "Unembargoed"]:
90 if Cnf.has_key("Dir::Queue::%s" % (q)):
91 if os.path.exists(Cnf["Dir::Queue::%s" % (q)] + '/' + dsc_filename):
94 reject("no source found for %s %s (%s)." % (source_package, source_version, f))
96 # Version and file overwrite checks
97 if files[f]["type"] == "deb":
98 reject(Upload.check_binary_against_db(f), "")
99 elif files[f]["type"] == "dsc":
100 reject(Upload.check_source_against_db(f), "")
101 (reject_msg, is_in_incoming) = Upload.check_dsc_against_db(f)
102 reject(reject_msg, "")
104 if reject_message.find("Rejected") != -1:
106 if Options["No-Action"] or Options["Automatic"]:
109 print "REJECT\n" + reject_message,
110 prompt = "[R]eject, Skip, Quit ?"
112 while prompt.find(answer) == -1:
113 answer = utils.our_raw_input(prompt)
114 m = re_default_answer.match(prompt)
117 answer = answer[:1].upper()
120 Upload.do_reject(0, reject_message)
121 os.unlink(Upload.pkg.changes_file[:-8]+".dak")
131 ################################################################################
133 def indiv_sg_compare (a, b):
134 """Sort by source name, source, version, 'have source', and
135 finally by filename."""
136 # Sort by source version
137 q = apt_pkg.VersionCompare(a["version"], b["version"])
141 # Sort by 'have source'
142 a_has_source = a["architecture"].get("source")
143 b_has_source = b["architecture"].get("source")
144 if a_has_source and not b_has_source:
146 elif b_has_source and not a_has_source:
149 return cmp(a["filename"], b["filename"])
151 ############################################################
153 def sg_compare (a, b):
156 """Sort by have note, source already in database and time of oldest upload."""
158 a_note_state = a["note_state"]
159 b_note_state = b["note_state"]
160 if a_note_state < b_note_state:
162 elif a_note_state > b_note_state:
164 # Sort by source already in database (descending)
165 source_in_database = cmp(a["source_in_database"], b["source_in_database"])
166 if source_in_database:
167 return -source_in_database
169 # Sort by time of oldest upload
170 return cmp(a["oldest"], b["oldest"])
172 def sort_changes(changes_files):
173 """Sort into source groups, then sort each source group by version,
174 have source, filename. Finally, sort the source groups by have
175 note, time of oldest upload of each source upload."""
176 if len(changes_files) == 1:
181 # Read in all the .changes files
182 for filename in changes_files:
184 Upload.pkg.changes_file = filename
187 cache[filename] = copy.copy(Upload.pkg.changes)
188 cache[filename]["filename"] = filename
190 sorted_list.append(filename)
192 # Divide the .changes into per-source groups
194 for filename in cache.keys():
195 source = cache[filename]["source"]
196 if not per_source.has_key(source):
197 per_source[source] = {}
198 per_source[source]["list"] = []
199 per_source[source]["list"].append(cache[filename])
200 # Determine oldest time and have note status for each source group
201 for source in per_source.keys():
202 q = projectB.query("SELECT 1 FROM source WHERE source = '%s'" % source)
204 per_source[source]["source_in_database"] = len(ql)>0
205 source_list = per_source[source]["list"]
206 first = source_list[0]
207 oldest = os.stat(first["filename"])[stat.ST_MTIME]
209 for d in per_source[source]["list"]:
210 mtime = os.stat(d["filename"])[stat.ST_MTIME]
213 have_note += (d.has_key("process-new note"))
214 per_source[source]["oldest"] = oldest
216 per_source[source]["note_state"] = 0; # none
217 elif have_note < len(source_list):
218 per_source[source]["note_state"] = 1; # some
220 per_source[source]["note_state"] = 2; # all
221 per_source[source]["list"].sort(indiv_sg_compare)
222 per_source_items = per_source.items()
223 per_source_items.sort(sg_compare)
224 for i in per_source_items:
225 for j in i[1]["list"]:
226 sorted_list.append(j["filename"])
229 ################################################################################
231 class Section_Completer:
235 q = projectB.query("SELECT section FROM section")
236 for i in q.getresult():
237 self.sections.append(i[0])
239 def complete(self, text, state):
243 for word in self.sections:
245 self.matches.append(word)
247 return self.matches[state]
251 ############################################################
253 class Priority_Completer:
257 q = projectB.query("SELECT priority FROM priority")
258 for i in q.getresult():
259 self.priorities.append(i[0])
261 def complete(self, text, state):
265 for word in self.priorities:
267 self.matches.append(word)
269 return self.matches[state]
273 ################################################################################
275 def print_new (new, indexed, file=sys.stdout):
276 queue.check_valid(new)
279 for pkg in new.keys():
281 section = new[pkg]["section"]
282 priority = new[pkg]["priority"]
283 if new[pkg]["section id"] == -1:
286 if new[pkg]["priority id"] == -1:
290 line = "(%s): %-20s %-20s %-20s" % (index, pkg, priority, section)
292 line = "%-20s %-20s %-20s" % (pkg, priority, section)
293 line = line.strip()+'\n'
295 note = Upload.pkg.changes.get("process-new note")
302 ################################################################################
304 def index_range (index):
308 return "1-%s" % (index)
310 ################################################################################
311 ################################################################################
314 # Write the current data to a temporary file
315 (fd, temp_filename) = utils.temp_filename()
316 temp_file = os.fdopen(fd, 'w')
317 print_new (new, 0, temp_file)
319 # Spawn an editor on that file
320 editor = os.environ.get("EDITOR","vi")
321 result = os.system("%s %s" % (editor, temp_filename))
323 utils.fubar ("%s invocation failed for %s." % (editor, temp_filename), result)
324 # Read the edited data back in
325 temp_file = utils.open_file(temp_filename)
326 lines = temp_file.readlines()
328 os.unlink(temp_filename)
335 # Pad the list if necessary
336 s[len(s):3] = [None] * (3-len(s))
337 (pkg, priority, section) = s[:3]
338 if not new.has_key(pkg):
339 utils.warn("Ignoring unknown package '%s'" % (pkg))
341 # Strip off any invalid markers, print_new will readd them.
342 if section.endswith("[!]"):
343 section = section[:-3]
344 if priority.endswith("[!]"):
345 priority = priority[:-3]
346 for f in new[pkg]["files"]:
347 Upload.pkg.files[f]["section"] = section
348 Upload.pkg.files[f]["priority"] = priority
349 new[pkg]["section"] = section
350 new[pkg]["priority"] = priority
352 ################################################################################
354 def edit_index (new, index):
355 priority = new[index]["priority"]
356 section = new[index]["section"]
357 ftype = new[index]["type"]
360 print "\t".join([index, priority, section])
364 prompt = "[B]oth, Priority, Section, Done ? "
366 prompt = "[S]ection, Done ? "
367 edit_priority = edit_section = 0
369 while prompt.find(answer) == -1:
370 answer = utils.our_raw_input(prompt)
371 m = re_default_answer.match(prompt)
374 answer = answer[:1].upper()
381 edit_priority = edit_section = 1
387 readline.set_completer(Priorities.complete)
389 while not got_priority:
390 new_priority = utils.our_raw_input("New priority: ").strip()
391 if new_priority not in Priorities.priorities:
392 print "E: '%s' is not a valid priority, try again." % (new_priority)
395 priority = new_priority
399 readline.set_completer(Sections.complete)
401 while not got_section:
402 new_section = utils.our_raw_input("New section: ").strip()
403 if new_section not in Sections.sections:
404 print "E: '%s' is not a valid section, try again." % (new_section)
407 section = new_section
409 # Reset the readline completer
410 readline.set_completer(None)
412 for f in new[index]["files"]:
413 Upload.pkg.files[f]["section"] = section
414 Upload.pkg.files[f]["priority"] = priority
415 new[index]["priority"] = priority
416 new[index]["section"] = section
419 ################################################################################
421 def edit_overrides (new):
432 prompt = "(%s) edit override <n>, Editor, Done ? " % (index_range(index))
435 while not got_answer:
436 answer = utils.our_raw_input(prompt)
437 if not answer.isdigit():
438 answer = answer[:1].upper()
439 if answer == "E" or answer == "D":
441 elif re_isanum.match (answer):
443 if (answer < 1) or (answer > index):
444 print "%s is not a valid index (%s). Please retry." % (answer, index_range(index))
453 edit_index (new, new_index[answer])
457 ################################################################################
460 # Write the current data to a temporary file
461 (fd, temp_filename) = utils.temp_filename()
462 temp_file = os.fdopen(fd, 'w')
463 temp_file.write(note)
465 editor = os.environ.get("EDITOR","vi")
468 os.system("%s %s" % (editor, temp_filename))
469 temp_file = utils.open_file(temp_filename)
470 note = temp_file.read().rstrip()
473 print utils.prefix_multi_line_string(note," ")
474 prompt = "[D]one, Edit, Abandon, Quit ?"
476 while prompt.find(answer) == -1:
477 answer = utils.our_raw_input(prompt)
478 m = re_default_answer.search(prompt)
481 answer = answer[:1].upper()
482 os.unlink(temp_filename)
488 Upload.pkg.changes["process-new note"] = note
489 Upload.dump_vars(Cnf["Dir::Queue::New"])
491 ################################################################################
495 less_fd = os.popen("less -R -", 'w', 0)
496 stdout_fd = sys.stdout
499 changes = utils.parse_changes (Upload.pkg.changes_file)
500 examine_package.display_changes(changes['distribution'], Upload.pkg.changes_file)
501 files = Upload.pkg.files
502 for f in files.keys():
503 if files[f].has_key("new"):
504 ftype = files[f]["type"]
506 examine_package.check_deb(changes['distribution'], f)
508 examine_package.check_dsc(changes['distribution'], f)
510 sys.stdout = stdout_fd
512 if e.errno == errno.EPIPE:
513 utils.warn("[examine_package] Caught EPIPE; skipping.")
517 except KeyboardInterrupt:
518 utils.warn("[examine_package] Caught C-c; skipping.")
521 ################################################################################
523 ## FIXME: horribly Debian specific
525 def do_bxa_notification():
526 files = Upload.pkg.files
528 for f in files.keys():
529 if files[f]["type"] == "deb":
530 control = apt_pkg.ParseSection(apt_inst.debExtractControl(utils.open_file(f)))
532 summary += "Package: %s\n" % (control.Find("Package"))
533 summary += "Description: %s\n" % (control.Find("Description"))
534 Upload.Subst["__BINARY_DESCRIPTIONS__"] = summary
535 bxa_mail = utils.TemplateSubst(Upload.Subst,Cnf["Dir::Templates"]+"/process-new.bxa_notification")
536 utils.send_mail(bxa_mail)
538 ################################################################################
540 def add_overrides (new):
541 changes = Upload.pkg.changes
542 files = Upload.pkg.files
544 projectB.query("BEGIN WORK")
545 for suite in changes["suite"].keys():
546 suite_id = database.get_suite_id(suite)
547 for pkg in new.keys():
548 component_id = database.get_component_id(new[pkg]["component"])
549 type_id = database.get_override_type_id(new[pkg]["type"])
550 priority_id = new[pkg]["priority id"]
551 section_id = new[pkg]["section id"]
552 projectB.query("INSERT INTO override (suite, component, type, package, priority, section, maintainer) VALUES (%s, %s, %s, '%s', %s, %s, '')" % (suite_id, component_id, type_id, pkg, priority_id, section_id))
553 for f in new[pkg]["files"]:
554 if files[f].has_key("new"):
558 projectB.query("COMMIT WORK")
560 if Cnf.FindB("Dinstall::BXANotify"):
561 do_bxa_notification()
563 ################################################################################
565 def prod_maintainer ():
566 # Here we prepare an editor and get them ready to prod...
567 (fd, temp_filename) = utils.temp_filename()
568 editor = os.environ.get("EDITOR","vi")
571 os.system("%s %s" % (editor, temp_filename))
573 prod_message = "".join(f.readlines())
575 print "Prod message:"
576 print utils.prefix_multi_line_string(prod_message," ",include_blank_lines=1)
577 prompt = "[P]rod, Edit, Abandon, Quit ?"
579 while prompt.find(answer) == -1:
580 answer = utils.our_raw_input(prompt)
581 m = re_default_answer.search(prompt)
584 answer = answer[:1].upper()
585 os.unlink(temp_filename)
591 # Otherwise, do the proding...
592 user_email_address = utils.whoami() + " <%s>" % (
593 Cnf["Dinstall::MyAdminAddress"])
597 Subst["__FROM_ADDRESS__"] = user_email_address
598 Subst["__PROD_MESSAGE__"] = prod_message
599 Subst["__CC__"] = "Cc: " + Cnf["Dinstall::MyEmailAddress"]
601 prod_mail_message = utils.TemplateSubst(
602 Subst,Cnf["Dir::Templates"]+"/process-new.prod")
604 # Send the prod mail if appropriate
605 if not Cnf["Dinstall::Options::No-Mail"]:
606 utils.send_mail(prod_mail_message)
608 print "Sent proding message"
610 ################################################################################
614 files = Upload.pkg.files
615 changes = Upload.pkg.changes
617 # Make a copy of distribution we can happily trample on
618 changes["suite"] = copy.copy(changes["distribution"])
620 # Fix up the list of target suites
621 for suite in changes["suite"].keys():
622 override = Cnf.Find("Suite::%s::OverrideSuite" % (suite))
624 (olderr, newerr) = (database.get_suite_id(suite) == -1,
625 database.get_suite_id(override) == -1)
627 (oinv, newinv) = ("", "")
628 if olderr: oinv = "invalid "
629 if newerr: ninv = "invalid "
630 print "warning: overriding %ssuite %s to %ssuite %s" % (
631 oinv, suite, ninv, override)
632 del changes["suite"][suite]
633 changes["suite"][override] = 1
635 for suite in changes["suite"].keys():
636 suite_id = database.get_suite_id(suite)
638 utils.fubar("%s has invalid suite '%s' (possibly overriden). say wha?" % (changes, suite))
640 # The main NEW processing loop
643 # Find out what's new
644 new = queue.determine_new(changes, files, projectB)
650 if Options["No-Action"] or Options["Automatic"]:
653 (broken, note) = print_new(new, 0)
656 if not broken and not note:
657 prompt = "Add overrides, "
659 print "W: [!] marked entries must be fixed before package can be processed."
661 print "W: note must be removed before package can be processed."
662 prompt += "Remove note, "
664 prompt += "Edit overrides, Check, Manual reject, Note edit, Prod, [S]kip, Quit ?"
666 while prompt.find(answer) == -1:
667 answer = utils.our_raw_input(prompt)
668 m = re_default_answer.search(prompt)
671 answer = answer[:1].upper()
674 done = add_overrides (new)
678 new = edit_overrides (new)
680 aborted = Upload.do_reject(1, Options["Manual-Reject"])
682 os.unlink(Upload.pkg.changes_file[:-8]+".dak")
685 edit_note(changes.get("process-new note", ""))
689 confirm = utils.our_raw_input("Really clear note (y/N)? ").lower()
691 del changes["process-new note"]
698 ################################################################################
699 ################################################################################
700 ################################################################################
702 def usage (exit_code=0):
703 print """Usage: dak process-new [OPTION]... [CHANGES]...
704 -a, --automatic automatic run
705 -h, --help show this help and exit.
706 -C, --comments-dir=DIR use DIR as comments-dir, for [o-]p-u-new
707 -m, --manual-reject=MSG manual reject with `msg'
708 -n, --no-action don't do anything
709 -V, --version display the version number and exit"""
712 ################################################################################
715 global Cnf, Options, Logger, Upload, projectB, Sections, Priorities
717 Cnf = utils.get_conf()
719 Arguments = [('a',"automatic","Process-New::Options::Automatic"),
720 ('h',"help","Process-New::Options::Help"),
721 ('C',"comments-dir","Process-New::Options::Comments-Dir", "HasArg"),
722 ('m',"manual-reject","Process-New::Options::Manual-Reject", "HasArg"),
723 ('n',"no-action","Process-New::Options::No-Action")]
725 for i in ["automatic", "help", "manual-reject", "no-action", "version", "comments-dir"]:
726 if not Cnf.has_key("Process-New::Options::%s" % (i)):
727 Cnf["Process-New::Options::%s" % (i)] = ""
729 changes_files = apt_pkg.ParseCommandLine(Cnf,Arguments,sys.argv)
730 Options = Cnf.SubTree("Process-New::Options")
735 Upload = queue.Upload(Cnf)
737 if not Options["No-Action"]:
738 Logger = Upload.Logger = logging.Logger(Cnf, "process-new")
740 projectB = Upload.projectB
742 Sections = Section_Completer()
743 Priorities = Priority_Completer()
744 readline.parse_and_bind("tab: complete")
748 ################################################################################
753 files = Upload.pkg.files
757 for f in files.keys():
758 if files[f]["type"] == "byhand":
759 if os.path.exists(f):
760 print "W: %s still present; please process byhand components and try again." % (f)
766 if Options["No-Action"]:
769 if Options["Automatic"] and not Options["No-Action"]:
771 prompt = "[A]ccept, Manual reject, Skip, Quit ?"
773 prompt = "Manual reject, [S]kip, Quit ?"
775 while prompt.find(answer) == -1:
776 answer = utils.our_raw_input(prompt)
777 m = re_default_answer.search(prompt)
780 answer = answer[:1].upper()
787 Upload.do_reject(1, Options["Manual-Reject"])
788 os.unlink(Upload.pkg.changes_file[:-8]+".dak")
796 ################################################################################
798 def get_accept_lock():
802 os.open(Cnf["Process-New::AcceptedLockFile"], os.O_RDONLY | os.O_CREAT | os.O_EXCL)
805 if e.errno == errno.EACCES or e.errno == errno.EEXIST:
808 utils.fubar("Couldn't obtain lock; assuming 'dak process-unchecked' is already running.")
810 print("Unable to get accepted lock (try %d of 10)" % retry)
815 def move_to_dir (dest, perms=0660, changesperms=0664):
816 utils.move (Upload.pkg.changes_file, dest, perms=changesperms)
817 file_keys = Upload.pkg.files.keys()
819 utils.move (f, dest, perms=perms)
821 def is_source_in_queue_dir(qdir):
822 entries = [ x for x in os.listdir(qdir) if x.startswith(Upload.pkg.changes["source"])
823 and x.endswith(".changes") ]
824 for entry in entries:
826 u = queue.Upload(Cnf)
827 u.pkg.changes_file = os.path.join(qdir, entry)
829 if not u.pkg.changes["architecture"].has_key("source"):
830 # another binary upload, ignore
832 if Upload.pkg.changes["version"] != u.pkg.changes["version"]:
833 # another version, ignore
839 def move_to_holding(suite, queue_dir):
840 print "Moving to %s holding area." % (suite.upper(),)
841 if Options["No-Action"]:
843 Logger.log(["Moving to %s" % (suite,), Upload.pkg.changes_file])
844 Upload.dump_vars(queue_dir)
845 move_to_dir(queue_dir)
846 os.unlink(Upload.pkg.changes_file[:-8]+".dak")
849 if Options["No-Action"]:
851 (summary, short_summary) = Upload.build_summaries()
852 Upload.accept(summary, short_summary)
853 os.unlink(Upload.pkg.changes_file[:-8]+".dak")
855 def do_accept_stableupdate(suite, q):
856 queue_dir = Cnf["Dir::Queue::%s" % (q,)]
857 if not Upload.pkg.changes["architecture"].has_key("source"):
858 # It is not a sourceful upload. So its source may be either in p-u
859 # holding, in new, in accepted or already installed.
860 if is_source_in_queue_dir(queue_dir):
861 # It's in p-u holding, so move it there.
862 print "Binary-only upload, source in %s." % (q,)
863 move_to_holding(suite, queue_dir)
864 elif Upload.source_exists(Upload.pkg.changes["source"],
865 Upload.pkg.changes["version"]):
866 # dak tells us that there is source available. At time of
867 # writing this means that it is installed, so put it into
869 print "Binary-only upload, source installed."
871 elif is_source_in_queue_dir(Cnf["Dir::Queue::Accepted"]):
872 # The source is in accepted, the binary cleared NEW: accept it.
873 print "Binary-only upload, source in accepted."
875 elif is_source_in_queue_dir(Cnf["Dir::Queue::New"]):
876 # It's in NEW. We expect the source to land in p-u holding
878 print "Binary-only upload, source in new."
879 move_to_holding(suite, queue_dir)
881 # No case applicable. Bail out. Return will cause the upload
884 print "Stable update failed. Source not found."
887 # We are handling a sourceful upload. Move to accepted if currently
888 # in p-u holding and to p-u holding otherwise.
889 if is_source_in_queue_dir(queue_dir):
890 print "Sourceful upload in %s, accepting." % (q,)
893 move_to_holding(suite, queue_dir)
897 if not Options["No-Action"]:
899 (summary, short_summary) = Upload.build_summaries()
901 if Cnf.FindB("Dinstall::SecurityQueueHandling"):
902 Upload.dump_vars(Cnf["Dir::Queue::Embargoed"])
903 move_to_dir(Cnf["Dir::Queue::Embargoed"])
904 Upload.queue_build("embargoed", Cnf["Dir::Queue::Embargoed"])
905 # Check for override disparities
906 Upload.Subst["__SUMMARY__"] = summary
908 # Stable updates need to be copied to proposed-updates holding
909 # area instead of accepted. Sourceful uploads need to go
910 # to it directly, binaries only if the source has not yet been
912 for suite, q in [("proposed-updates", "ProposedUpdates"),
913 ("oldstable-proposed-updates", "OldProposedUpdates")]:
914 if not Upload.pkg.changes["distribution"].has_key(suite):
916 return do_accept_stableupdate(suite, q)
917 # Just a normal upload, accept it...
920 if not Options["No-Action"]:
921 os.unlink(Cnf["Process-New::AcceptedLockFile"])
923 def check_status(files):
925 for f in files.keys():
926 if files[f]["type"] == "byhand":
928 elif files[f].has_key("new"):
932 def do_pkg(changes_file):
933 Upload.pkg.changes_file = changes_file
936 Upload.update_subst()
937 files = Upload.pkg.files
942 (new, byhand) = check_status(files)
948 (new, byhand) = check_status(files)
950 if not new and not byhand:
953 ################################################################################
956 accept_count = Upload.accept_count
957 accept_bytes = Upload.accept_bytes
963 sys.stderr.write("Accepted %d package %s, %s.\n" % (accept_count, sets, utils.size_type(int(accept_bytes))))
964 Logger.log(["total",accept_count,accept_bytes])
966 if not Options["No-Action"]:
969 ################################################################################
971 def do_comments(dir, opref, npref, line, fn):
972 for comm in [ x for x in os.listdir(dir) if x.startswith(opref) ]:
973 lines = open("%s/%s" % (dir, comm)).readlines()
974 if len(lines) == 0 or lines[0] != line + "\n": continue
975 changes_files = [ x for x in os.listdir(".") if x.startswith(comm[7:]+"_")
976 and x.endswith(".changes") ]
977 changes_files = sort_changes(changes_files)
978 for f in changes_files:
979 f = utils.validate_changes_file_arg(f, 0)
982 fn(f, "".join(lines[1:]))
984 if opref != npref and not Options["No-Action"]:
985 newcomm = npref + comm[len(opref):]
986 os.rename("%s/%s" % (dir, comm), "%s/%s" % (dir, newcomm))
988 ################################################################################
990 def comment_accept(changes_file, comments):
991 Upload.pkg.changes_file = changes_file
994 Upload.update_subst()
995 files = Upload.pkg.files
998 return # dak wants to REJECT, crap
1000 (new, byhand) = check_status(files)
1001 if not new and not byhand:
1004 ################################################################################
1006 def comment_reject(changes_file, comments):
1007 Upload.pkg.changes_file = changes_file
1009 Upload.update_vars()
1010 Upload.update_subst()
1013 pass # dak has its own reasons to reject as well, which is fine
1016 print "REJECT\n" + reject_message,
1017 if not Options["No-Action"]:
1018 Upload.do_reject(0, reject_message)
1019 os.unlink(Upload.pkg.changes_file[:-8]+".dak")
1021 ################################################################################
1024 changes_files = init()
1025 if len(changes_files) > 50:
1026 sys.stderr.write("Sorting changes...\n")
1027 changes_files = sort_changes(changes_files)
1029 # Kill me now? **FIXME**
1030 Cnf["Dinstall::Options::No-Mail"] = ""
1031 bcc = "X-DAK: dak process-new\nX-Katie: lisa $Revision: 1.31 $"
1032 if Cnf.has_key("Dinstall::Bcc"):
1033 Upload.Subst["__BCC__"] = bcc + "\nBcc: %s" % (Cnf["Dinstall::Bcc"])
1035 Upload.Subst["__BCC__"] = bcc
1037 commentsdir = Cnf.get("Process-New::Options::Comments-Dir","")
1039 if changes_files != []:
1040 sys.stderr.write("Can't specify any changes files if working with comments-dir")
1042 do_comments(commentsdir, "ACCEPT.", "ACCEPTED.", "OK", comment_accept)
1043 do_comments(commentsdir, "REJECT.", "REJECTED.", "NOTOK", comment_reject)
1045 for changes_file in changes_files:
1046 changes_file = utils.validate_changes_file_arg(changes_file, 0)
1047 if not changes_file:
1049 print "\n" + changes_file
1050 do_pkg (changes_file)
1054 ################################################################################
1056 if __name__ == '__main__':