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
60 ################################################################################
61 ################################################################################
62 ################################################################################
64 def reject (str, prefix="Rejected: "):
67 reject_message += prefix + str + "\n"
71 files = Upload.pkg.files
74 for f in files.keys():
75 # The .orig.tar.gz can disappear out from under us is it's a
76 # duplicate of one in the archive.
77 if not files.has_key(f):
79 # Check that the source still exists
80 if files[f]["type"] == "deb":
81 source_version = files[f]["source version"]
82 source_package = files[f]["source package"]
83 if not Upload.pkg.changes["architecture"].has_key("source") \
84 and not Upload.source_exists(source_package, source_version, Upload.pkg.changes["distribution"].keys()):
85 source_epochless_version = utils.re_no_epoch.sub('', source_version)
86 dsc_filename = "%s_%s.dsc" % (source_package, source_epochless_version)
88 for q in ["Accepted", "Embargoed", "Unembargoed"]:
89 if Cnf.has_key("Dir::Queue::%s" % (q)):
90 if os.path.exists(Cnf["Dir::Queue::%s" % (q)] + '/' + dsc_filename):
93 reject("no source found for %s %s (%s)." % (source_package, source_version, f))
95 # Version and file overwrite checks
96 if files[f]["type"] == "deb":
97 reject(Upload.check_binary_against_db(f), "")
98 elif files[f]["type"] == "dsc":
99 reject(Upload.check_source_against_db(f), "")
100 (reject_msg, is_in_incoming) = Upload.check_dsc_against_db(f)
101 reject(reject_msg, "")
103 if reject_message.find("Rejected") != -1:
105 if Options["No-Action"] or Options["Automatic"]:
108 print "REJECT\n" + reject_message,
109 prompt = "[R]eject, Skip, Quit ?"
111 while prompt.find(answer) == -1:
112 answer = utils.our_raw_input(prompt)
113 m = queue.re_default_answer.match(prompt)
116 answer = answer[:1].upper()
119 Upload.do_reject(0, reject_message)
120 os.unlink(Upload.pkg.changes_file[:-8]+".dak")
130 ################################################################################
132 def indiv_sg_compare (a, b):
133 """Sort by source name, source, version, 'have source', and
134 finally by filename."""
135 # Sort by source version
136 q = apt_pkg.VersionCompare(a["version"], b["version"])
140 # Sort by 'have source'
141 a_has_source = a["architecture"].get("source")
142 b_has_source = b["architecture"].get("source")
143 if a_has_source and not b_has_source:
145 elif b_has_source and not a_has_source:
148 return cmp(a["filename"], b["filename"])
150 ############################################################
152 def sg_compare (a, b):
155 """Sort by have note, source already in database and time of oldest upload."""
157 a_note_state = a["note_state"]
158 b_note_state = b["note_state"]
159 if a_note_state < b_note_state:
161 elif a_note_state > b_note_state:
163 # Sort by source already in database (descending)
164 source_in_database = cmp(a["source_in_database"], b["source_in_database"])
165 if source_in_database:
166 return -source_in_database
168 # Sort by time of oldest upload
169 return cmp(a["oldest"], b["oldest"])
171 def sort_changes(changes_files):
172 """Sort into source groups, then sort each source group by version,
173 have source, filename. Finally, sort the source groups by have
174 note, time of oldest upload of each source upload."""
175 if len(changes_files) == 1:
180 # Read in all the .changes files
181 for filename in changes_files:
183 Upload.pkg.changes_file = filename
186 cache[filename] = copy.copy(Upload.pkg.changes)
187 cache[filename]["filename"] = filename
189 sorted_list.append(filename)
191 # Divide the .changes into per-source groups
193 for filename in cache.keys():
194 source = cache[filename]["source"]
195 if not per_source.has_key(source):
196 per_source[source] = {}
197 per_source[source]["list"] = []
198 per_source[source]["list"].append(cache[filename])
199 # Determine oldest time and have note status for each source group
200 for source in per_source.keys():
201 q = projectB.query("SELECT 1 FROM source WHERE source = '%s'" % source)
203 per_source[source]["source_in_database"] = len(ql)>0
204 source_list = per_source[source]["list"]
205 first = source_list[0]
206 oldest = os.stat(first["filename"])[stat.ST_MTIME]
208 for d in per_source[source]["list"]:
209 mtime = os.stat(d["filename"])[stat.ST_MTIME]
212 have_note += (d.has_key("process-new note"))
213 per_source[source]["oldest"] = oldest
215 per_source[source]["note_state"] = 0; # none
216 elif have_note < len(source_list):
217 per_source[source]["note_state"] = 1; # some
219 per_source[source]["note_state"] = 2; # all
220 per_source[source]["list"].sort(indiv_sg_compare)
221 per_source_items = per_source.items()
222 per_source_items.sort(sg_compare)
223 for i in per_source_items:
224 for j in i[1]["list"]:
225 sorted_list.append(j["filename"])
228 ################################################################################
230 class Section_Completer:
234 q = projectB.query("SELECT section FROM section")
235 for i in q.getresult():
236 self.sections.append(i[0])
238 def complete(self, text, state):
242 for word in self.sections:
244 self.matches.append(word)
246 return self.matches[state]
250 ############################################################
252 class Priority_Completer:
256 q = projectB.query("SELECT priority FROM priority")
257 for i in q.getresult():
258 self.priorities.append(i[0])
260 def complete(self, text, state):
264 for word in self.priorities:
266 self.matches.append(word)
268 return self.matches[state]
272 ################################################################################
274 def print_new (new, indexed, file=sys.stdout):
275 queue.check_valid(new)
278 for pkg in new.keys():
280 section = new[pkg]["section"]
281 priority = new[pkg]["priority"]
282 if new[pkg]["section id"] == -1:
285 if new[pkg]["priority id"] == -1:
289 line = "(%s): %-20s %-20s %-20s" % (index, pkg, priority, section)
291 line = "%-20s %-20s %-20s" % (pkg, priority, section)
292 line = line.strip()+'\n'
294 note = Upload.pkg.changes.get("process-new note")
301 ################################################################################
303 def index_range (index):
307 return "1-%s" % (index)
309 ################################################################################
310 ################################################################################
313 # Write the current data to a temporary file
314 (fd, temp_filename) = utils.temp_filename()
315 temp_file = os.fdopen(fd, 'w')
316 print_new (new, 0, temp_file)
318 # Spawn an editor on that file
319 editor = os.environ.get("EDITOR","vi")
320 result = os.system("%s %s" % (editor, temp_filename))
322 utils.fubar ("%s invocation failed for %s." % (editor, temp_filename), result)
323 # Read the edited data back in
324 temp_file = utils.open_file(temp_filename)
325 lines = temp_file.readlines()
327 os.unlink(temp_filename)
334 # Pad the list if necessary
335 s[len(s):3] = [None] * (3-len(s))
336 (pkg, priority, section) = s[:3]
337 if not new.has_key(pkg):
338 utils.warn("Ignoring unknown package '%s'" % (pkg))
340 # Strip off any invalid markers, print_new will readd them.
341 if section.endswith("[!]"):
342 section = section[:-3]
343 if priority.endswith("[!]"):
344 priority = priority[:-3]
345 for f in new[pkg]["files"]:
346 Upload.pkg.files[f]["section"] = section
347 Upload.pkg.files[f]["priority"] = priority
348 new[pkg]["section"] = section
349 new[pkg]["priority"] = priority
351 ################################################################################
353 def edit_index (new, index):
354 priority = new[index]["priority"]
355 section = new[index]["section"]
356 ftype = new[index]["type"]
359 print "\t".join([index, priority, section])
363 prompt = "[B]oth, Priority, Section, Done ? "
365 prompt = "[S]ection, Done ? "
366 edit_priority = edit_section = 0
368 while prompt.find(answer) == -1:
369 answer = utils.our_raw_input(prompt)
370 m = queue.re_default_answer.match(prompt)
373 answer = answer[:1].upper()
380 edit_priority = edit_section = 1
386 readline.set_completer(Priorities.complete)
388 while not got_priority:
389 new_priority = utils.our_raw_input("New priority: ").strip()
390 if new_priority not in Priorities.priorities:
391 print "E: '%s' is not a valid priority, try again." % (new_priority)
394 priority = new_priority
398 readline.set_completer(Sections.complete)
400 while not got_section:
401 new_section = utils.our_raw_input("New section: ").strip()
402 if new_section not in Sections.sections:
403 print "E: '%s' is not a valid section, try again." % (new_section)
406 section = new_section
408 # Reset the readline completer
409 readline.set_completer(None)
411 for f in new[index]["files"]:
412 Upload.pkg.files[f]["section"] = section
413 Upload.pkg.files[f]["priority"] = priority
414 new[index]["priority"] = priority
415 new[index]["section"] = section
418 ################################################################################
420 def edit_overrides (new):
431 prompt = "(%s) edit override <n>, Editor, Done ? " % (index_range(index))
434 while not got_answer:
435 answer = utils.our_raw_input(prompt)
436 if not answer.isdigit():
437 answer = answer[:1].upper()
438 if answer == "E" or answer == "D":
440 elif queue.re_isanum.match (answer):
442 if (answer < 1) or (answer > index):
443 print "%s is not a valid index (%s). Please retry." % (answer, index_range(index))
452 edit_index (new, new_index[answer])
456 ################################################################################
459 # Write the current data to a temporary file
460 (fd, temp_filename) = utils.temp_filename()
461 temp_file = os.fdopen(temp_filename, 'w')
462 temp_file.write(note)
464 editor = os.environ.get("EDITOR","vi")
467 os.system("%s %s" % (editor, temp_filename))
468 temp_file = utils.open_file(temp_filename)
469 note = temp_file.read().rstrip()
472 print utils.prefix_multi_line_string(note," ")
473 prompt = "[D]one, Edit, Abandon, Quit ?"
475 while prompt.find(answer) == -1:
476 answer = utils.our_raw_input(prompt)
477 m = queue.re_default_answer.search(prompt)
480 answer = answer[:1].upper()
481 os.unlink(temp_filename)
487 Upload.pkg.changes["process-new note"] = note
488 Upload.dump_vars(Cnf["Dir::Queue::New"])
490 ################################################################################
494 less_fd = os.popen("less -R -", 'w', 0)
495 stdout_fd = sys.stdout
498 changes = utils.parse_changes (Upload.pkg.changes_file)
499 examine_package.display_changes(changes['distribution'], Upload.pkg.changes_file)
500 files = Upload.pkg.files
501 for f in files.keys():
502 if files[f].has_key("new"):
503 ftype = files[f]["type"]
505 examine_package.check_deb(changes['distribution'], f)
507 examine_package.check_dsc(changes['distribution'], f)
509 sys.stdout = stdout_fd
511 if e.errno == errno.EPIPE:
512 utils.warn("[examine_package] Caught EPIPE; skipping.")
516 except KeyboardInterrupt:
517 utils.warn("[examine_package] Caught C-c; skipping.")
520 ################################################################################
522 ## FIXME: horribly Debian specific
524 def do_bxa_notification():
525 files = Upload.pkg.files
527 for f in files.keys():
528 if files[f]["type"] == "deb":
529 control = apt_pkg.ParseSection(apt_inst.debExtractControl(utils.open_file(f)))
531 summary += "Package: %s\n" % (control.Find("Package"))
532 summary += "Description: %s\n" % (control.Find("Description"))
533 Upload.Subst["__BINARY_DESCRIPTIONS__"] = summary
534 bxa_mail = utils.TemplateSubst(Upload.Subst,Cnf["Dir::Templates"]+"/process-new.bxa_notification")
535 utils.send_mail(bxa_mail)
537 ################################################################################
539 def add_overrides (new):
540 changes = Upload.pkg.changes
541 files = Upload.pkg.files
543 projectB.query("BEGIN WORK")
544 for suite in changes["suite"].keys():
545 suite_id = database.get_suite_id(suite)
546 for pkg in new.keys():
547 component_id = database.get_component_id(new[pkg]["component"])
548 type_id = database.get_override_type_id(new[pkg]["type"])
549 priority_id = new[pkg]["priority id"]
550 section_id = new[pkg]["section id"]
551 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))
552 for f in new[pkg]["files"]:
553 if files[f].has_key("new"):
557 projectB.query("COMMIT WORK")
559 if Cnf.FindB("Dinstall::BXANotify"):
560 do_bxa_notification()
562 ################################################################################
564 def prod_maintainer ():
565 # Here we prepare an editor and get them ready to prod...
566 (fd, temp_filename) = utils.temp_filename()
567 editor = os.environ.get("EDITOR","vi")
570 os.system("%s %s" % (editor, temp_filename))
572 prod_message = "".join(f.readlines())
574 print "Prod message:"
575 print utils.prefix_multi_line_string(prod_message," ",include_blank_lines=1)
576 prompt = "[P]rod, Edit, Abandon, Quit ?"
578 while prompt.find(answer) == -1:
579 answer = utils.our_raw_input(prompt)
580 m = queue.re_default_answer.search(prompt)
583 answer = answer[:1].upper()
584 os.unlink(temp_filename)
590 # Otherwise, do the proding...
591 user_email_address = utils.whoami() + " <%s>" % (
592 Cnf["Dinstall::MyAdminAddress"])
596 Subst["__FROM_ADDRESS__"] = user_email_address
597 Subst["__PROD_MESSAGE__"] = prod_message
598 Subst["__CC__"] = "Cc: " + Cnf["Dinstall::MyEmailAddress"]
600 prod_mail_message = utils.TemplateSubst(
601 Subst,Cnf["Dir::Templates"]+"/process-new.prod")
603 # Send the prod mail if appropriate
604 if not Cnf["Dinstall::Options::No-Mail"]:
605 utils.send_mail(prod_mail_message)
607 print "Sent proding message"
609 ################################################################################
613 files = Upload.pkg.files
614 changes = Upload.pkg.changes
616 # Make a copy of distribution we can happily trample on
617 changes["suite"] = copy.copy(changes["distribution"])
619 # Fix up the list of target suites
620 for suite in changes["suite"].keys():
621 override = Cnf.Find("Suite::%s::OverrideSuite" % (suite))
623 (olderr, newerr) = (database.get_suite_id(suite) == -1,
624 database.get_suite_id(override) == -1)
626 (oinv, newinv) = ("", "")
627 if olderr: oinv = "invalid "
628 if newerr: ninv = "invalid "
629 print "warning: overriding %ssuite %s to %ssuite %s" % (
630 oinv, suite, ninv, override)
631 del changes["suite"][suite]
632 changes["suite"][override] = 1
634 for suite in changes["suite"].keys():
635 suite_id = database.get_suite_id(suite)
637 utils.fubar("%s has invalid suite '%s' (possibly overriden). say wha?" % (changes, suite))
639 # The main NEW processing loop
642 # Find out what's new
643 new = queue.determine_new(changes, files, projectB)
649 if Options["No-Action"] or Options["Automatic"]:
652 (broken, note) = print_new(new, 0)
655 if not broken and not note:
656 prompt = "Add overrides, "
658 print "W: [!] marked entries must be fixed before package can be processed."
660 print "W: note must be removed before package can be processed."
661 prompt += "Remove note, "
663 prompt += "Edit overrides, Check, Manual reject, Note edit, Prod, [S]kip, Quit ?"
665 while prompt.find(answer) == -1:
666 answer = utils.our_raw_input(prompt)
667 m = queue.re_default_answer.search(prompt)
670 answer = answer[:1].upper()
673 done = add_overrides (new)
677 new = edit_overrides (new)
679 aborted = Upload.do_reject(1, Options["Manual-Reject"])
681 os.unlink(Upload.pkg.changes_file[:-8]+".dak")
684 edit_note(changes.get("process-new note", ""))
688 confirm = utils.our_raw_input("Really clear note (y/N)? ").lower()
690 del changes["process-new note"]
697 ################################################################################
698 ################################################################################
699 ################################################################################
701 def usage (exit_code=0):
702 print """Usage: dak process-new [OPTION]... [CHANGES]...
703 -a, --automatic automatic run
704 -h, --help show this help and exit.
705 -C, --comments-dir=DIR use DIR as comments-dir, for [o-]p-u-new
706 -m, --manual-reject=MSG manual reject with `msg'
707 -n, --no-action don't do anything
708 -V, --version display the version number and exit"""
711 ################################################################################
714 global Cnf, Options, Logger, Upload, projectB, Sections, Priorities
716 Cnf = utils.get_conf()
718 Arguments = [('a',"automatic","Process-New::Options::Automatic"),
719 ('h',"help","Process-New::Options::Help"),
720 ('C',"comments-dir","Process-New::Options::Comments-Dir", "HasArg"),
721 ('m',"manual-reject","Process-New::Options::Manual-Reject", "HasArg"),
722 ('n',"no-action","Process-New::Options::No-Action")]
724 for i in ["automatic", "help", "manual-reject", "no-action", "version", "comments-dir"]:
725 if not Cnf.has_key("Process-New::Options::%s" % (i)):
726 Cnf["Process-New::Options::%s" % (i)] = ""
728 changes_files = apt_pkg.ParseCommandLine(Cnf,Arguments,sys.argv)
729 Options = Cnf.SubTree("Process-New::Options")
734 Upload = queue.Upload(Cnf)
736 if not Options["No-Action"]:
737 Logger = Upload.Logger = logging.Logger(Cnf, "process-new")
739 projectB = Upload.projectB
741 Sections = Section_Completer()
742 Priorities = Priority_Completer()
743 readline.parse_and_bind("tab: complete")
747 ################################################################################
752 files = Upload.pkg.files
756 for f in files.keys():
757 if files[f]["type"] == "byhand":
758 if os.path.exists(f):
759 print "W: %s still present; please process byhand components and try again." % (f)
765 if Options["No-Action"]:
768 if Options["Automatic"] and not Options["No-Action"]:
770 prompt = "[A]ccept, Manual reject, Skip, Quit ?"
772 prompt = "Manual reject, [S]kip, Quit ?"
774 while prompt.find(answer) == -1:
775 answer = utils.our_raw_input(prompt)
776 m = queue.re_default_answer.search(prompt)
779 answer = answer[:1].upper()
786 Upload.do_reject(1, Options["Manual-Reject"])
787 os.unlink(Upload.pkg.changes_file[:-8]+".dak")
795 ################################################################################
797 def get_accept_lock():
801 os.open(Cnf["Process-New::AcceptedLockFile"], os.O_RDONLY | os.O_CREAT | os.O_EXCL)
804 if e.errno == errno.EACCES or e.errno == errno.EEXIST:
807 utils.fubar("Couldn't obtain lock; assuming 'dak process-unchecked' is already running.")
809 print("Unable to get accepted lock (try %d of 10)" % retry)
814 def move_to_dir (dest, perms=0660, changesperms=0664):
815 utils.move (Upload.pkg.changes_file, dest, perms=changesperms)
816 file_keys = Upload.pkg.files.keys()
818 utils.move (f, dest, perms=perms)
820 def is_source_in_queue_dir(qdir):
821 entries = [ x for x in os.listdir(qdir) if x.startswith(Upload.pkg.changes["source"])
822 and x.endswith(".changes") ]
823 for entry in entries:
825 u = queue.Upload(Cnf)
826 u.pkg.changes_file = os.path.join(qdir, entry)
828 if not u.pkg.changes["architecture"].has_key("source"):
829 # another binary upload, ignore
831 if Upload.pkg.changes["version"] != u.pkg.changes["version"]:
832 # another version, ignore
838 def move_to_holding(suite, queue_dir):
839 print "Moving to %s holding area." % (suite.upper(),)
840 if Options["No-Action"]:
842 Logger.log(["Moving to %s" % (suite,), Upload.pkg.changes_file])
843 Upload.dump_vars(queue_dir)
844 move_to_dir(queue_dir)
845 os.unlink(Upload.pkg.changes_file[:-8]+".dak")
848 if Options["No-Action"]:
850 (summary, short_summary) = Upload.build_summaries()
851 Upload.accept(summary, short_summary)
852 os.unlink(Upload.pkg.changes_file[:-8]+".dak")
854 def do_accept_stableupdate(suite, q):
855 queue_dir = Cnf["Dir::Queue::%s" % (q,)]
856 if not Upload.pkg.changes["architecture"].has_key("source"):
857 # It is not a sourceful upload. So its source may be either in p-u
858 # holding, in new, in accepted or already installed.
859 if is_source_in_queue_dir(queue_dir):
860 # It's in p-u holding, so move it there.
861 print "Binary-only upload, source in %s." % (q,)
862 move_to_holding(suite, queue_dir)
863 elif Upload.source_exists(Upload.pkg.changes["source"],
864 Upload.pkg.changes["version"]):
865 # dak tells us that there is source available. At time of
866 # writing this means that it is installed, so put it into
868 print "Binary-only upload, source installed."
870 elif is_source_in_queue_dir(Cnf["Dir::Queue::Accepted"]):
871 # The source is in accepted, the binary cleared NEW: accept it.
872 print "Binary-only upload, source in accepted."
874 elif is_source_in_queue_dir(Cnf["Dir::Queue::New"]):
875 # It's in NEW. We expect the source to land in p-u holding
877 print "Binary-only upload, source in new."
878 move_to_holding(suite, queue_dir)
880 # No case applicable. Bail out. Return will cause the upload
883 print "Stable update failed. Source not found."
886 # We are handling a sourceful upload. Move to accepted if currently
887 # in p-u holding and to p-u holding otherwise.
888 if is_source_in_queue_dir(queue_dir):
889 print "Sourceful upload in %s, accepting." % (q,)
892 move_to_holding(suite, queue_dir)
896 if not Options["No-Action"]:
898 (summary, short_summary) = Upload.build_summaries()
900 if Cnf.FindB("Dinstall::SecurityQueueHandling"):
901 Upload.dump_vars(Cnf["Dir::Queue::Embargoed"])
902 move_to_dir(Cnf["Dir::Queue::Embargoed"])
903 Upload.queue_build("embargoed", Cnf["Dir::Queue::Embargoed"])
904 # Check for override disparities
905 Upload.Subst["__SUMMARY__"] = summary
907 # Stable updates need to be copied to proposed-updates holding
908 # area instead of accepted. Sourceful uploads need to go
909 # to it directly, binaries only if the source has not yet been
911 for suite, q in [("proposed-updates", "ProposedUpdates"),
912 ("oldstable-proposed-updates", "OldProposedUpdates")]:
913 if not Upload.pkg.changes["distribution"].has_key(suite):
915 return do_accept_stableupdate(suite, q)
916 # Just a normal upload, accept it...
919 if not Options["No-Action"]:
920 os.unlink(Cnf["Process-New::AcceptedLockFile"])
922 def check_status(files):
924 for f in files.keys():
925 if files[f]["type"] == "byhand":
927 elif files[f].has_key("new"):
931 def do_pkg(changes_file):
932 Upload.pkg.changes_file = changes_file
935 Upload.update_subst()
936 files = Upload.pkg.files
941 (new, byhand) = check_status(files)
947 (new, byhand) = check_status(files)
949 if not new and not byhand:
952 ################################################################################
955 accept_count = Upload.accept_count
956 accept_bytes = Upload.accept_bytes
962 sys.stderr.write("Accepted %d package %s, %s.\n" % (accept_count, sets, utils.size_type(int(accept_bytes))))
963 Logger.log(["total",accept_count,accept_bytes])
965 if not Options["No-Action"]:
968 ################################################################################
970 def do_comments(dir, opref, npref, line, fn):
971 for comm in [ x for x in os.listdir(dir) if x.startswith(opref) ]:
972 lines = open("%s/%s" % (dir, comm)).readlines()
973 if len(lines) == 0 or lines[0] != line + "\n": continue
974 changes_files = [ x for x in os.listdir(".") if x.startswith(comm[7:]+"_")
975 and x.endswith(".changes") ]
976 changes_files = sort_changes(changes_files)
977 for f in changes_files:
978 f = utils.validate_changes_file_arg(f, 0)
981 fn(f, "".join(lines[1:]))
983 if opref != npref and not Options["No-Action"]:
984 newcomm = npref + comm[len(opref):]
985 os.rename("%s/%s" % (dir, comm), "%s/%s" % (dir, newcomm))
987 ################################################################################
989 def comment_accept(changes_file, comments):
990 Upload.pkg.changes_file = changes_file
993 Upload.update_subst()
994 files = Upload.pkg.files
997 return # dak wants to REJECT, crap
999 (new, byhand) = check_status(files)
1000 if not new and not byhand:
1003 ################################################################################
1005 def comment_reject(changes_file, comments):
1006 Upload.pkg.changes_file = changes_file
1008 Upload.update_vars()
1009 Upload.update_subst()
1012 pass # dak has its own reasons to reject as well, which is fine
1015 print "REJECT\n" + reject_message,
1016 if not Options["No-Action"]:
1017 Upload.do_reject(0, reject_message)
1018 os.unlink(Upload.pkg.changes_file[:-8]+".dak")
1020 ################################################################################
1023 changes_files = init()
1024 if len(changes_files) > 50:
1025 sys.stderr.write("Sorting changes...\n")
1026 changes_files = sort_changes(changes_files)
1028 # Kill me now? **FIXME**
1029 Cnf["Dinstall::Options::No-Mail"] = ""
1030 bcc = "X-DAK: dak process-new\nX-Katie: lisa $Revision: 1.31 $"
1031 if Cnf.has_key("Dinstall::Bcc"):
1032 Upload.Subst["__BCC__"] = bcc + "\nBcc: %s" % (Cnf["Dinstall::Bcc"])
1034 Upload.Subst["__BCC__"] = bcc
1036 commentsdir = Cnf.get("Process-New::Options::Comments-Dir","")
1038 if changes_files != []:
1039 sys.stderr.write("Can't specify any changes files if working with comments-dir")
1041 do_comments(commentsdir, "ACCEPT.", "ACCEPTED.", "OK", comment_accept)
1042 do_comments(commentsdir, "REJECT.", "REJECTED.", "NOTOK", comment_reject)
1044 for changes_file in changes_files:
1045 changes_file = utils.validate_changes_file_arg(changes_file, 0)
1046 if not changes_file:
1048 print "\n" + changes_file
1049 do_pkg (changes_file)
1053 ################################################################################
1055 if __name__ == '__main__':