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 @license: GNU General Public License version 2 or later
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2 of the License, or
13 # (at your option) any later version.
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License
21 # along with this program; if not, write to the Free Software
22 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 ################################################################################
26 # 23:12|<aj> I will not hush!
28 # 23:12|<aj> Where there is injustice in the world, I shall be there!
29 # 23:13|<aj> I shall not be silenced!
30 # 23:13|<aj> The world shall know!
31 # 23:13|<aj> The world *must* know!
32 # 23:13|<elmo> oh dear, he's gone back to powerpuff girls... ;-)
33 # 23:13|<aj> yay powerpuff girls!!
34 # 23:13|<aj> buttercup's my favourite, who's yours?
35 # 23:14|<aj> you're backing away from the keyboard right now aren't you?
36 # 23:14|<aj> *AREN'T YOU*?!
37 # 23:15|<aj> I will not be treated like this.
38 # 23:15|<aj> I shall have my revenge.
39 # 23:15|<aj> I SHALL!!!
41 ################################################################################
50 import apt_pkg, apt_inst
51 import examine_package
52 from daklib import database
53 from daklib import logging
54 from daklib import queue
55 from daklib import utils
56 from daklib.regexes import re_no_epoch, re_default_answer, re_isanum
59 Cnf = None #: Configuration, apt_pkg.Configuration
62 projectB = None #: database connection, pgobject
70 ################################################################################
71 ################################################################################
72 ################################################################################
74 def reject (str, prefix="Rejected: "):
77 reject_message += prefix + str + "\n"
81 files = Upload.pkg.files
84 for f in files.keys():
85 # The .orig.tar.gz can disappear out from under us is it's a
86 # duplicate of one in the archive.
87 if not files.has_key(f):
89 # Check that the source still exists
90 if files[f]["type"] == "deb":
91 source_version = files[f]["source version"]
92 source_package = files[f]["source package"]
93 if not Upload.pkg.changes["architecture"].has_key("source") \
94 and not Upload.source_exists(source_package, source_version, Upload.pkg.changes["distribution"].keys()):
95 source_epochless_version = re_no_epoch.sub('', source_version)
96 dsc_filename = "%s_%s.dsc" % (source_package, source_epochless_version)
98 for q in ["Accepted", "Embargoed", "Unembargoed"]:
99 if Cnf.has_key("Dir::Queue::%s" % (q)):
100 if os.path.exists(Cnf["Dir::Queue::%s" % (q)] + '/' + dsc_filename):
103 reject("no source found for %s %s (%s)." % (source_package, source_version, f))
105 # Version and file overwrite checks
106 if files[f]["type"] == "deb":
107 reject(Upload.check_binary_against_db(f), "")
108 elif files[f]["type"] == "dsc":
109 reject(Upload.check_source_against_db(f), "")
110 (reject_msg, is_in_incoming) = Upload.check_dsc_against_db(f)
111 reject(reject_msg, "")
113 if reject_message.find("Rejected") != -1:
115 if Options["No-Action"] or Options["Automatic"]:
118 print "REJECT\n" + reject_message,
119 prompt = "[R]eject, Skip, Quit ?"
121 while prompt.find(answer) == -1:
122 answer = utils.our_raw_input(prompt)
123 m = re_default_answer.match(prompt)
126 answer = answer[:1].upper()
129 Upload.do_reject(0, reject_message)
130 os.unlink(Upload.pkg.changes_file[:-8]+".dak")
140 ################################################################################
142 def indiv_sg_compare (a, b):
143 """Sort by source name, source, version, 'have source', and
144 finally by filename."""
145 # Sort by source version
146 q = apt_pkg.VersionCompare(a["version"], b["version"])
150 # Sort by 'have source'
151 a_has_source = a["architecture"].get("source")
152 b_has_source = b["architecture"].get("source")
153 if a_has_source and not b_has_source:
155 elif b_has_source and not a_has_source:
158 return cmp(a["filename"], b["filename"])
160 ############################################################
162 def sg_compare (a, b):
165 """Sort by have note, source already in database and time of oldest upload."""
167 a_note_state = a["note_state"]
168 b_note_state = b["note_state"]
169 if a_note_state < b_note_state:
171 elif a_note_state > b_note_state:
173 # Sort by source already in database (descending)
174 source_in_database = cmp(a["source_in_database"], b["source_in_database"])
175 if source_in_database:
176 return -source_in_database
178 # Sort by time of oldest upload
179 return cmp(a["oldest"], b["oldest"])
181 def sort_changes(changes_files):
182 """Sort into source groups, then sort each source group by version,
183 have source, filename. Finally, sort the source groups by have
184 note, time of oldest upload of each source upload."""
185 if len(changes_files) == 1:
190 # Read in all the .changes files
191 for filename in changes_files:
193 Upload.pkg.changes_file = filename
196 cache[filename] = copy.copy(Upload.pkg.changes)
197 cache[filename]["filename"] = filename
199 sorted_list.append(filename)
201 # Divide the .changes into per-source groups
203 for filename in cache.keys():
204 source = cache[filename]["source"]
205 if not per_source.has_key(source):
206 per_source[source] = {}
207 per_source[source]["list"] = []
208 per_source[source]["list"].append(cache[filename])
209 # Determine oldest time and have note status for each source group
210 for source in per_source.keys():
211 q = projectB.query("SELECT 1 FROM source WHERE source = '%s'" % source)
213 per_source[source]["source_in_database"] = len(ql)>0
214 source_list = per_source[source]["list"]
215 first = source_list[0]
216 oldest = os.stat(first["filename"])[stat.ST_MTIME]
218 for d in per_source[source]["list"]:
219 mtime = os.stat(d["filename"])[stat.ST_MTIME]
222 have_note += (d.has_key("process-new note"))
223 per_source[source]["oldest"] = oldest
225 per_source[source]["note_state"] = 0; # none
226 elif have_note < len(source_list):
227 per_source[source]["note_state"] = 1; # some
229 per_source[source]["note_state"] = 2; # all
230 per_source[source]["list"].sort(indiv_sg_compare)
231 per_source_items = per_source.items()
232 per_source_items.sort(sg_compare)
233 for i in per_source_items:
234 for j in i[1]["list"]:
235 sorted_list.append(j["filename"])
238 ################################################################################
240 class Section_Completer:
244 q = projectB.query("SELECT section FROM section")
245 for i in q.getresult():
246 self.sections.append(i[0])
248 def complete(self, text, state):
252 for word in self.sections:
254 self.matches.append(word)
256 return self.matches[state]
260 ############################################################
262 class Priority_Completer:
266 q = projectB.query("SELECT priority FROM priority")
267 for i in q.getresult():
268 self.priorities.append(i[0])
270 def complete(self, text, state):
274 for word in self.priorities:
276 self.matches.append(word)
278 return self.matches[state]
282 ################################################################################
284 def print_new (new, indexed, file=sys.stdout):
285 queue.check_valid(new)
288 for pkg in new.keys():
290 section = new[pkg]["section"]
291 priority = new[pkg]["priority"]
292 if new[pkg]["section id"] == -1:
295 if new[pkg]["priority id"] == -1:
299 line = "(%s): %-20s %-20s %-20s" % (index, pkg, priority, section)
301 line = "%-20s %-20s %-20s" % (pkg, priority, section)
302 line = line.strip()+'\n'
304 note = Upload.pkg.changes.get("process-new note")
311 ################################################################################
313 def index_range (index):
317 return "1-%s" % (index)
319 ################################################################################
320 ################################################################################
323 # Write the current data to a temporary file
324 (fd, temp_filename) = utils.temp_filename()
325 temp_file = os.fdopen(fd, 'w')
326 print_new (new, 0, temp_file)
328 # Spawn an editor on that file
329 editor = os.environ.get("EDITOR","vi")
330 result = os.system("%s %s" % (editor, temp_filename))
332 utils.fubar ("%s invocation failed for %s." % (editor, temp_filename), result)
333 # Read the edited data back in
334 temp_file = utils.open_file(temp_filename)
335 lines = temp_file.readlines()
337 os.unlink(temp_filename)
344 # Pad the list if necessary
345 s[len(s):3] = [None] * (3-len(s))
346 (pkg, priority, section) = s[:3]
347 if not new.has_key(pkg):
348 utils.warn("Ignoring unknown package '%s'" % (pkg))
350 # Strip off any invalid markers, print_new will readd them.
351 if section.endswith("[!]"):
352 section = section[:-3]
353 if priority.endswith("[!]"):
354 priority = priority[:-3]
355 for f in new[pkg]["files"]:
356 Upload.pkg.files[f]["section"] = section
357 Upload.pkg.files[f]["priority"] = priority
358 new[pkg]["section"] = section
359 new[pkg]["priority"] = priority
361 ################################################################################
363 def edit_index (new, index):
364 priority = new[index]["priority"]
365 section = new[index]["section"]
366 ftype = new[index]["type"]
369 print "\t".join([index, priority, section])
373 prompt = "[B]oth, Priority, Section, Done ? "
375 prompt = "[S]ection, Done ? "
376 edit_priority = edit_section = 0
378 while prompt.find(answer) == -1:
379 answer = utils.our_raw_input(prompt)
380 m = re_default_answer.match(prompt)
383 answer = answer[:1].upper()
390 edit_priority = edit_section = 1
396 readline.set_completer(Priorities.complete)
398 while not got_priority:
399 new_priority = utils.our_raw_input("New priority: ").strip()
400 if new_priority not in Priorities.priorities:
401 print "E: '%s' is not a valid priority, try again." % (new_priority)
404 priority = new_priority
408 readline.set_completer(Sections.complete)
410 while not got_section:
411 new_section = utils.our_raw_input("New section: ").strip()
412 if new_section not in Sections.sections:
413 print "E: '%s' is not a valid section, try again." % (new_section)
416 section = new_section
418 # Reset the readline completer
419 readline.set_completer(None)
421 for f in new[index]["files"]:
422 Upload.pkg.files[f]["section"] = section
423 Upload.pkg.files[f]["priority"] = priority
424 new[index]["priority"] = priority
425 new[index]["section"] = section
428 ################################################################################
430 def edit_overrides (new):
441 prompt = "(%s) edit override <n>, Editor, Done ? " % (index_range(index))
444 while not got_answer:
445 answer = utils.our_raw_input(prompt)
446 if not answer.isdigit():
447 answer = answer[:1].upper()
448 if answer == "E" or answer == "D":
450 elif re_isanum.match (answer):
452 if (answer < 1) or (answer > index):
453 print "%s is not a valid index (%s). Please retry." % (answer, index_range(index))
462 edit_index (new, new_index[answer])
466 ################################################################################
469 # Write the current data to a temporary file
470 (fd, temp_filename) = utils.temp_filename()
471 temp_file = os.fdopen(fd, 'w')
472 temp_file.write(note)
474 editor = os.environ.get("EDITOR","vi")
477 os.system("%s %s" % (editor, temp_filename))
478 temp_file = utils.open_file(temp_filename)
479 note = temp_file.read().rstrip()
482 print utils.prefix_multi_line_string(note," ")
483 prompt = "[D]one, Edit, Abandon, Quit ?"
485 while prompt.find(answer) == -1:
486 answer = utils.our_raw_input(prompt)
487 m = re_default_answer.search(prompt)
490 answer = answer[:1].upper()
491 os.unlink(temp_filename)
497 Upload.pkg.changes["process-new note"] = note
498 Upload.dump_vars(Cnf["Dir::Queue::New"])
500 ################################################################################
504 less_fd = os.popen("less -R -", 'w', 0)
505 stdout_fd = sys.stdout
508 changes = utils.parse_changes (Upload.pkg.changes_file)
509 examine_package.display_changes(changes['distribution'], Upload.pkg.changes_file)
510 files = Upload.pkg.files
511 for f in files.keys():
512 if files[f].has_key("new"):
513 ftype = files[f]["type"]
515 examine_package.check_deb(changes['distribution'], f)
517 examine_package.check_dsc(changes['distribution'], f)
519 examine_package.output_package_relations()
520 sys.stdout = stdout_fd
522 if e.errno == errno.EPIPE:
523 utils.warn("[examine_package] Caught EPIPE; skipping.")
527 except KeyboardInterrupt:
528 utils.warn("[examine_package] Caught C-c; skipping.")
531 ################################################################################
533 ## FIXME: horribly Debian specific
535 def do_bxa_notification():
536 files = Upload.pkg.files
538 for f in files.keys():
539 if files[f]["type"] == "deb":
540 control = apt_pkg.ParseSection(apt_inst.debExtractControl(utils.open_file(f)))
542 summary += "Package: %s\n" % (control.Find("Package"))
543 summary += "Description: %s\n" % (control.Find("Description"))
544 Upload.Subst["__BINARY_DESCRIPTIONS__"] = summary
545 bxa_mail = utils.TemplateSubst(Upload.Subst,Cnf["Dir::Templates"]+"/process-new.bxa_notification")
546 utils.send_mail(bxa_mail)
548 ################################################################################
550 def add_overrides (new):
551 changes = Upload.pkg.changes
552 files = Upload.pkg.files
554 projectB.query("BEGIN WORK")
555 for suite in changes["suite"].keys():
556 suite_id = database.get_suite_id(suite)
557 for pkg in new.keys():
558 component_id = database.get_component_id(new[pkg]["component"])
559 type_id = database.get_override_type_id(new[pkg]["type"])
560 priority_id = new[pkg]["priority id"]
561 section_id = new[pkg]["section id"]
562 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))
563 for f in new[pkg]["files"]:
564 if files[f].has_key("new"):
568 projectB.query("COMMIT WORK")
570 if Cnf.FindB("Dinstall::BXANotify"):
571 do_bxa_notification()
573 ################################################################################
575 def prod_maintainer ():
576 # Here we prepare an editor and get them ready to prod...
577 (fd, temp_filename) = utils.temp_filename()
578 editor = os.environ.get("EDITOR","vi")
581 os.system("%s %s" % (editor, temp_filename))
583 prod_message = "".join(f.readlines())
585 print "Prod message:"
586 print utils.prefix_multi_line_string(prod_message," ",include_blank_lines=1)
587 prompt = "[P]rod, Edit, Abandon, Quit ?"
589 while prompt.find(answer) == -1:
590 answer = utils.our_raw_input(prompt)
591 m = re_default_answer.search(prompt)
594 answer = answer[:1].upper()
595 os.unlink(temp_filename)
601 # Otherwise, do the proding...
602 user_email_address = utils.whoami() + " <%s>" % (
603 Cnf["Dinstall::MyAdminAddress"])
607 Subst["__FROM_ADDRESS__"] = user_email_address
608 Subst["__PROD_MESSAGE__"] = prod_message
609 Subst["__CC__"] = "Cc: " + Cnf["Dinstall::MyEmailAddress"]
611 prod_mail_message = utils.TemplateSubst(
612 Subst,Cnf["Dir::Templates"]+"/process-new.prod")
614 # Send the prod mail if appropriate
615 if not Cnf["Dinstall::Options::No-Mail"]:
616 utils.send_mail(prod_mail_message)
618 print "Sent proding message"
620 ################################################################################
624 files = Upload.pkg.files
625 changes = Upload.pkg.changes
627 # Make a copy of distribution we can happily trample on
628 changes["suite"] = copy.copy(changes["distribution"])
630 # Fix up the list of target suites
631 for suite in changes["suite"].keys():
632 override = Cnf.Find("Suite::%s::OverrideSuite" % (suite))
634 (olderr, newerr) = (database.get_suite_id(suite) == -1,
635 database.get_suite_id(override) == -1)
637 (oinv, newinv) = ("", "")
638 if olderr: oinv = "invalid "
639 if newerr: ninv = "invalid "
640 print "warning: overriding %ssuite %s to %ssuite %s" % (
641 oinv, suite, ninv, override)
642 del changes["suite"][suite]
643 changes["suite"][override] = 1
645 for suite in changes["suite"].keys():
646 suite_id = database.get_suite_id(suite)
648 utils.fubar("%s has invalid suite '%s' (possibly overriden). say wha?" % (changes, suite))
650 # The main NEW processing loop
653 # Find out what's new
654 new = queue.determine_new(changes, files, projectB)
660 if Options["No-Action"] or Options["Automatic"]:
663 (broken, note) = print_new(new, 0)
666 if not broken and not note:
667 prompt = "Add overrides, "
669 print "W: [!] marked entries must be fixed before package can be processed."
671 print "W: note must be removed before package can be processed."
672 prompt += "Remove note, "
674 prompt += "Edit overrides, Check, Manual reject, Note edit, Prod, [S]kip, Quit ?"
676 while prompt.find(answer) == -1:
677 answer = utils.our_raw_input(prompt)
678 m = re_default_answer.search(prompt)
681 answer = answer[:1].upper()
684 done = add_overrides (new)
688 new = edit_overrides (new)
690 aborted = Upload.do_reject(1, Options["Manual-Reject"])
692 os.unlink(Upload.pkg.changes_file[:-8]+".dak")
695 edit_note(changes.get("process-new note", ""))
699 confirm = utils.our_raw_input("Really clear note (y/N)? ").lower()
701 del changes["process-new note"]
708 ################################################################################
709 ################################################################################
710 ################################################################################
712 def usage (exit_code=0):
713 print """Usage: dak process-new [OPTION]... [CHANGES]...
714 -a, --automatic automatic run
715 -h, --help show this help and exit.
716 -C, --comments-dir=DIR use DIR as comments-dir, for [o-]p-u-new
717 -m, --manual-reject=MSG manual reject with `msg'
718 -n, --no-action don't do anything
719 -V, --version display the version number and exit"""
722 ################################################################################
725 global Cnf, Options, Logger, Upload, projectB, Sections, Priorities
727 Cnf = utils.get_conf()
729 Arguments = [('a',"automatic","Process-New::Options::Automatic"),
730 ('h',"help","Process-New::Options::Help"),
731 ('C',"comments-dir","Process-New::Options::Comments-Dir", "HasArg"),
732 ('m',"manual-reject","Process-New::Options::Manual-Reject", "HasArg"),
733 ('n',"no-action","Process-New::Options::No-Action")]
735 for i in ["automatic", "help", "manual-reject", "no-action", "version", "comments-dir"]:
736 if not Cnf.has_key("Process-New::Options::%s" % (i)):
737 Cnf["Process-New::Options::%s" % (i)] = ""
739 changes_files = apt_pkg.ParseCommandLine(Cnf,Arguments,sys.argv)
740 if len(changes_files) == 0 and not Cnf.get("Process-New::Options::Comments-Dir",""):
741 changes_files = utils.get_changes_files(Cnf["Dir::Queue::New"])
743 Options = Cnf.SubTree("Process-New::Options")
748 Upload = queue.Upload(Cnf)
750 if not Options["No-Action"]:
751 Logger = Upload.Logger = logging.Logger(Cnf, "process-new")
753 projectB = Upload.projectB
755 Sections = Section_Completer()
756 Priorities = Priority_Completer()
757 readline.parse_and_bind("tab: complete")
761 ################################################################################
766 files = Upload.pkg.files
770 for f in files.keys():
771 if files[f]["type"] == "byhand":
772 if os.path.exists(f):
773 print "W: %s still present; please process byhand components and try again." % (f)
779 if Options["No-Action"]:
782 if Options["Automatic"] and not Options["No-Action"]:
784 prompt = "[A]ccept, Manual reject, Skip, Quit ?"
786 prompt = "Manual reject, [S]kip, Quit ?"
788 while prompt.find(answer) == -1:
789 answer = utils.our_raw_input(prompt)
790 m = re_default_answer.search(prompt)
793 answer = answer[:1].upper()
800 Upload.do_reject(1, Options["Manual-Reject"])
801 os.unlink(Upload.pkg.changes_file[:-8]+".dak")
809 ################################################################################
811 def get_accept_lock():
815 os.open(Cnf["Process-New::AcceptedLockFile"], os.O_RDONLY | os.O_CREAT | os.O_EXCL)
818 if e.errno == errno.EACCES or e.errno == errno.EEXIST:
821 utils.fubar("Couldn't obtain lock; assuming 'dak process-unchecked' is already running.")
823 print("Unable to get accepted lock (try %d of 10)" % retry)
828 def move_to_dir (dest, perms=0660, changesperms=0664):
829 utils.move (Upload.pkg.changes_file, dest, perms=changesperms)
830 file_keys = Upload.pkg.files.keys()
832 utils.move (f, dest, perms=perms)
834 def is_source_in_queue_dir(qdir):
835 entries = [ x for x in os.listdir(qdir) if x.startswith(Upload.pkg.changes["source"])
836 and x.endswith(".changes") ]
837 for entry in entries:
839 u = queue.Upload(Cnf)
840 u.pkg.changes_file = os.path.join(qdir, entry)
842 if not u.pkg.changes["architecture"].has_key("source"):
843 # another binary upload, ignore
845 if Upload.pkg.changes["version"] != u.pkg.changes["version"]:
846 # another version, ignore
852 def move_to_holding(suite, queue_dir):
853 print "Moving to %s holding area." % (suite.upper(),)
854 if Options["No-Action"]:
856 Logger.log(["Moving to %s" % (suite,), Upload.pkg.changes_file])
857 Upload.dump_vars(queue_dir)
858 move_to_dir(queue_dir, perms=0664)
859 os.unlink(Upload.pkg.changes_file[:-8]+".dak")
862 if Options["No-Action"]:
864 (summary, short_summary) = Upload.build_summaries()
865 Upload.accept(summary, short_summary)
866 os.unlink(Upload.pkg.changes_file[:-8]+".dak")
868 def do_accept_stableupdate(suite, q):
869 queue_dir = Cnf["Dir::Queue::%s" % (q,)]
870 if not Upload.pkg.changes["architecture"].has_key("source"):
871 # It is not a sourceful upload. So its source may be either in p-u
872 # holding, in new, in accepted or already installed.
873 if is_source_in_queue_dir(queue_dir):
874 # It's in p-u holding, so move it there.
875 print "Binary-only upload, source in %s." % (q,)
876 move_to_holding(suite, queue_dir)
877 elif Upload.source_exists(Upload.pkg.changes["source"],
878 Upload.pkg.changes["version"]):
879 # dak tells us that there is source available. At time of
880 # writing this means that it is installed, so put it into
882 print "Binary-only upload, source installed."
884 elif is_source_in_queue_dir(Cnf["Dir::Queue::Accepted"]):
885 # The source is in accepted, the binary cleared NEW: accept it.
886 print "Binary-only upload, source in accepted."
888 elif is_source_in_queue_dir(Cnf["Dir::Queue::New"]):
889 # It's in NEW. We expect the source to land in p-u holding
891 print "Binary-only upload, source in new."
892 move_to_holding(suite, queue_dir)
894 # No case applicable. Bail out. Return will cause the upload
897 print "Stable update failed. Source not found."
900 # We are handling a sourceful upload. Move to accepted if currently
901 # in p-u holding and to p-u holding otherwise.
902 if is_source_in_queue_dir(queue_dir):
903 print "Sourceful upload in %s, accepting." % (q,)
906 move_to_holding(suite, queue_dir)
910 if not Options["No-Action"]:
912 (summary, short_summary) = Upload.build_summaries()
914 if Cnf.FindB("Dinstall::SecurityQueueHandling"):
915 Upload.dump_vars(Cnf["Dir::Queue::Embargoed"])
916 move_to_dir(Cnf["Dir::Queue::Embargoed"])
917 Upload.queue_build("embargoed", Cnf["Dir::Queue::Embargoed"])
918 # Check for override disparities
919 Upload.Subst["__SUMMARY__"] = summary
921 # Stable updates need to be copied to proposed-updates holding
922 # area instead of accepted. Sourceful uploads need to go
923 # to it directly, binaries only if the source has not yet been
925 for suite, q in [("proposed-updates", "ProposedUpdates"),
926 ("oldstable-proposed-updates", "OldProposedUpdates")]:
927 if not Upload.pkg.changes["distribution"].has_key(suite):
929 return do_accept_stableupdate(suite, q)
930 # Just a normal upload, accept it...
933 if not Options["No-Action"]:
934 os.unlink(Cnf["Process-New::AcceptedLockFile"])
936 def check_status(files):
938 for f in files.keys():
939 if files[f]["type"] == "byhand":
941 elif files[f].has_key("new"):
945 def do_pkg(changes_file):
946 Upload.pkg.changes_file = changes_file
949 Upload.update_subst()
950 files = Upload.pkg.files
955 (new, byhand) = check_status(files)
961 (new, byhand) = check_status(files)
963 if not new and not byhand:
966 ################################################################################
969 accept_count = Upload.accept_count
970 accept_bytes = Upload.accept_bytes
976 sys.stderr.write("Accepted %d package %s, %s.\n" % (accept_count, sets, utils.size_type(int(accept_bytes))))
977 Logger.log(["total",accept_count,accept_bytes])
979 if not Options["No-Action"]:
982 ################################################################################
984 def do_comments(dir, opref, npref, line, fn):
985 for comm in [ x for x in os.listdir(dir) if x.startswith(opref) ]:
986 lines = open("%s/%s" % (dir, comm)).readlines()
987 if len(lines) == 0 or lines[0] != line + "\n": continue
988 changes_files = [ x for x in os.listdir(".") if x.startswith(comm[7:]+"_")
989 and x.endswith(".changes") ]
990 changes_files = sort_changes(changes_files)
991 for f in changes_files:
992 f = utils.validate_changes_file_arg(f, 0)
995 fn(f, "".join(lines[1:]))
997 if opref != npref and not Options["No-Action"]:
998 newcomm = npref + comm[len(opref):]
999 os.rename("%s/%s" % (dir, comm), "%s/%s" % (dir, newcomm))
1001 ################################################################################
1003 def comment_accept(changes_file, comments):
1004 Upload.pkg.changes_file = changes_file
1006 Upload.update_vars()
1007 Upload.update_subst()
1008 files = Upload.pkg.files
1011 return # dak wants to REJECT, crap
1013 (new, byhand) = check_status(files)
1014 if not new and not byhand:
1017 ################################################################################
1019 def comment_reject(changes_file, comments):
1020 Upload.pkg.changes_file = changes_file
1022 Upload.update_vars()
1023 Upload.update_subst()
1026 pass # dak has its own reasons to reject as well, which is fine
1029 print "REJECT\n" + reject_message,
1030 if not Options["No-Action"]:
1031 Upload.do_reject(0, reject_message)
1032 os.unlink(Upload.pkg.changes_file[:-8]+".dak")
1034 ################################################################################
1037 changes_files = init()
1038 if len(changes_files) > 50:
1039 sys.stderr.write("Sorting changes...\n")
1040 changes_files = sort_changes(changes_files)
1042 # Kill me now? **FIXME**
1043 Cnf["Dinstall::Options::No-Mail"] = ""
1044 bcc = "X-DAK: dak process-new\nX-Katie: lisa $Revision: 1.31 $"
1045 if Cnf.has_key("Dinstall::Bcc"):
1046 Upload.Subst["__BCC__"] = bcc + "\nBcc: %s" % (Cnf["Dinstall::Bcc"])
1048 Upload.Subst["__BCC__"] = bcc
1050 commentsdir = Cnf.get("Process-New::Options::Comments-Dir","")
1052 if changes_files != []:
1053 sys.stderr.write("Can't specify any changes files if working with comments-dir")
1055 do_comments(commentsdir, "ACCEPT.", "ACCEPTED.", "OK", comment_accept)
1056 do_comments(commentsdir, "REJECT.", "REJECTED.", "NOTOK", comment_reject)
1058 for changes_file in changes_files:
1059 changes_file = utils.validate_changes_file_arg(changes_file, 0)
1060 if not changes_file:
1062 print "\n" + changes_file
1063 do_pkg (changes_file)
1067 ################################################################################
1069 if __name__ == '__main__':