3 # Edit and then check the release managers transition file for correctness
4 # and outdated transitions
5 # Copyright (C) 2008 Joerg Jaspert <joerg@debian.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 # <elmo> if klecker.d.o died, I swear to god, I'm going to migrate to gentoo.
25 ################################################################################
27 import os, pg, sys, time
29 import daklib.database
38 ################################################################################
41 global Cnf, Options, projectB
45 Cnf = daklib.utils.get_conf()
47 Arguments = [('h',"help","Edit-Transitions::Options::Help"),
48 ('e',"edit","Edit-Transitions::Options::Edit"),
49 ('c',"check","Edit-Transitions::Options::check"),
50 ('n',"no-action","Edit-Transitions::Options::No-Action")]
52 for i in ["help", "no-action", "edit", "check"]:
53 if not Cnf.has_key("Edit-Transitions::Options::%s" % (i)):
54 Cnf["Edit-Transitions::Options::%s" % (i)] = ""
56 apt_pkg.ParseCommandLine(Cnf, Arguments, sys.argv)
58 Options = Cnf.SubTree("Edit-Transitions::Options")
60 projectB = pg.connect(Cnf["DB::Name"], Cnf["DB::Host"], int(Cnf["DB::Port"]))
61 daklib.database.init(Cnf, projectB)
66 ################################################################################
68 def usage (exit_code=0):
69 print """Usage: edit_transitions [OPTION]...
70 Check the release managers transition file for correctness and outdated transitions
71 -h, --help show this help and exit.
72 -e, --edit edit the transitions file
73 -c, --check check the transitions file, remove outdated entries
74 -n, --no-action don't do anything
76 Called without an option this tool will check the transition file for outdated
77 transitions and remove them."""
80 ################################################################################
82 def lock_file(lockfile):
86 lock_fd = os.open(lockfile, os.O_RDONLY | os.O_CREAT | os.O_EXCL)
89 if errno.errorcode[e.errno] == 'EACCES' or errno.errorcode[e.errno] == 'EEXIST':
92 daklib.utils.fubar("Couldn't obtain lock for %s." % (lockfile) )
94 print("Unable to get lock for %s (try %d of 10)" % (lockfile, retry) )
100 ################################################################################
102 def edit_transitions():
103 trans_file = Cnf["Dinstall::Reject::ReleaseTransitions"]
105 tempfile = "./%s.transition.tmp" % (os.getpid() )
107 lockfile="/tmp/transitions.lock"
110 daklib.utils.copy(trans_file, tempfile)
112 editor = os.environ.get("EDITOR", "vi")
115 result = os.system("%s %s" % (editor, tempfile))
119 daklib.utils.fubar("%s invocation failed for %s, not removing tempfile." % (editor, tempfile))
121 # Now try to load the new file
122 test = load_transitions(tempfile)
127 prompt = "Broken edit: [E]dit again, Drop changes?"
129 while prompt.find(answer) == -1:
130 answer = daklib.utils.our_raw_input(prompt)
133 answer = answer[:1].upper()
140 print "OK, discarding changes"
143 # No problems in loading the new file, jump out of the while loop
146 # We seem to be done and also have a working file. Copy over.
147 # We are not using daklib.utils.copy here, as we use sudo to get this file copied, to
148 # limit the rights needed to edit transitions
149 os.spawnl(os.P_WAIT, "/usr/bin/sudo", "/usr/bin/sudo", "-u", "dak", "-H",
150 "cp", tempfile, trans_file)
155 # Before we finish print out transition info again
156 print "\n\n------------------------------------------------------------------------"
157 print "Edit done, file saved, currently defined transitions:\n"
158 transitions = load_transitions(Cnf["Dinstall::Reject::ReleaseTransitions"])
159 transition_info(transitions)
161 ################################################################################
163 def load_transitions(trans_file):
164 # Parse the yaml file
165 sourcefile = file(trans_file, 'r')
166 sourcecontent = sourcefile.read()
168 trans = syck.load(sourcecontent)
169 except syck.error, msg:
170 # Someone fucked it up
171 print "ERROR: %s" % (msg)
175 ################################################################################
177 def print_info(trans, source, expected, rm, reason, packages):
179 Looking at transition: %s
184 Blocked Packages (total: %d): %s
185 """ % (trans, source, expected, rm, reason, len(packages), ", ".join(packages))
188 ################################################################################
190 def transition_info(transitions):
191 for trans in transitions:
192 t = transitions[trans]
196 # Will be None if nothing is in testing.
197 current = daklib.database.get_suite_version(source, "testing")
199 print_info(trans, source, expected, t["rm"], t["reason"], t["packages"])
202 # No package in testing
203 print "Transition source %s not in testing, transition still ongoing." % (source)
205 compare = apt_pkg.VersionCompare(current, expected)
206 print "Apt compare says: %s" % (compare)
208 # This is still valid, the current version in database is older than
209 # the new version we wait for
210 print "This transition is still ongoing, we currently have version %s" % (current)
212 print "This transition is over, the target package reached testing, should be removed"
213 print "%s wanted version: %s, has %s" % (source, expected, current)
214 print "-------------------------------------------------------------------------"
216 ################################################################################
218 def check_transitions(transitions):
221 # Now look through all defined transitions
222 for trans in transitions:
223 t = transitions[trans]
227 # Will be None if nothing is in testing.
228 current = daklib.database.get_suite_version(source, "testing")
230 print_info(trans, source, expected, t["rm"], t["reason"], t["packages"])
233 # No package in testing
234 print "Transition source %s not in testing, transition still ongoing." % (source)
236 compare = apt_pkg.VersionCompare(current, expected)
238 # This is still valid, the current version in database is older than
239 # the new version we wait for
240 print "This transition is still ongoing, we currently have version %s" % (current)
242 print "REMOVE: This transition is over, the target package reached testing. REMOVE"
243 print "%s wanted version: %s, has %s" % (source, expected, current)
244 to_remove.append(trans)
246 print "-------------------------------------------------------------------------"
249 prompt = "Removing: "
250 for remove in to_remove:
254 prompt += " Commit Changes? (y/N)"
257 if Options["no-action"]:
260 answer = daklib.utils.our_raw_input(prompt).lower()
266 print "Not committing changes"
270 for remove in to_remove:
271 del transitions[remove]
273 lockfile="/tmp/transitions.lock"
275 tempfile = "./%s.transition.tmp" % (os.getpid() )
277 destfile = file(tempfile, 'w')
278 syck.dump(transitions, destfile)
281 os.spawnl(os.P_WAIT, "/usr/bin/sudo", "/usr/bin/sudo", "-u", "dak", "-H",
282 "cp", tempfile, Cnf["Dinstall::Reject::ReleaseTransitions"])
288 print "WTF are you typing?"
291 ################################################################################
298 # Only check if there is a file defined (and existant) with checks. It's a little bit
299 # specific to Debian, not much use for others, so return early there.
300 if not Cnf.has_key("Dinstall::Reject::ReleaseTransitions") or not os.path.exists("%s" % (Cnf["Dinstall::Reject::ReleaseTransitions"])):
301 daklib.utils.warn("Dinstall::Reject::ReleaseTransitions not defined or file %s not existant." %
302 (Cnf["Dinstall::Reject::ReleaseTransitions"]))
305 # Parse the yaml file
306 transitions = load_transitions(Cnf["Dinstall::Reject::ReleaseTransitions"])
307 if transitions == None:
308 # Something very broken with the transitions, exit
309 daklib.utils.warn("Not doing any work, someone fucked up the transitions file outside our control")
313 # Output information about the currently defined transitions.
314 print "Currently defined transitions:"
315 transition_info(transitions)
316 daklib.utils.our_raw_input("Press enter to continue...")
318 # Lets edit the transitions file
320 elif Options["check"]:
321 # Check and remove outdated transitions
322 check_transitions(transitions)
324 # Output information about the currently defined transitions.
325 transition_info(transitions)
327 # Nothing requested, doing nothing besides the above display of the transitions
331 ################################################################################
333 if __name__ == '__main__':