comparison hgext/hbisect.py @ 5732:2060cad9fabd

bisect: simplify state handling and init - use a single bisect.state file - unify init and reset (delete the state) - move write into good/bad
author Matt Mackall <mpm@selenic.com>
date Thu, 27 Dec 2007 23:55:39 -0600
parents 19691160d7f5
children 47ec288456bb
comparison
equal deleted inserted replaced
5731:19691160d7f5 5732:2060cad9fabd
12 12
13 class bisect(object): 13 class bisect(object):
14 """dichotomic search in the DAG of changesets""" 14 """dichotomic search in the DAG of changesets"""
15 def __init__(self, ui, repo): 15 def __init__(self, ui, repo):
16 self.repo = repo 16 self.repo = repo
17 self.path = repo.join("bisect")
18 self.opener = util.opener(self.path)
19 self.ui = ui 17 self.ui = ui
20 self.goodnodes = [] 18 self.goodnodes = []
21 self.badnode = None 19 self.badnode = None
22 self.good_path = "good" 20
23 self.bad_path = "bad" 21 p = self.repo.join("bisect.state")
24 self.is_reset = False 22 if os.path.exists(p):
25 23 for l in self.repo.opener("bisect.state"):
26 if os.path.exists(os.path.join(self.path, self.good_path)): 24 type, node = l[:-1].split()
27 self.goodnodes = self.opener(self.good_path).read().splitlines() 25 node = self.repo.lookup(node)
28 self.goodnodes = [hg.bin(x) for x in self.goodnodes] 26 if type == "good":
29 if os.path.exists(os.path.join(self.path, self.bad_path)): 27 self.goodnodes.append(node)
30 r = self.opener(self.bad_path).read().splitlines() 28 elif type == "bad":
31 if r: 29 self.badnode = node
32 self.badnode = hg.bin(r.pop(0))
33 30
34 def write(self): 31 def write(self):
35 if self.is_reset: 32 f = self.repo.opener("bisect.state", "w")
36 return 33 for n in self.goodnodes:
37 if not os.path.isdir(self.path): 34 f.write("good %s\n" % hg.hex(n))
38 os.mkdir(self.path)
39 f = self.opener(self.good_path, "w")
40 f.write("\n".join([hg.hex(r) for r in self.goodnodes]))
41 if len(self.goodnodes) > 0:
42 f.write("\n")
43 f = self.opener(self.bad_path, "w")
44 if self.badnode: 35 if self.badnode:
45 f.write(hg.hex(self.badnode) + "\n") 36 f.write("bad %s\n" % hg.hex(self.badnode))
46 37
47 def init(self): 38 def init(self):
48 """start a new bisection""" 39 """start a new bisection"""
49 if os.path.isdir(self.path): 40 p = self.repo.join("bisect.state")
50 raise util.Abort(_("bisect directory already exists\n")) 41 if os.path.exists(p):
51 os.mkdir(self.path) 42 os.unlink(p)
52 return 0
53
54 def reset(self):
55 """finish a bisection"""
56 if os.path.isdir(self.path):
57 sl = [os.path.join(self.path, p)
58 for p in [self.bad_path, self.good_path]]
59 for s in sl:
60 if os.path.exists(s):
61 os.unlink(s)
62 os.rmdir(self.path)
63 # Not sure about this
64 #self.ui.write("Going back to tip\n")
65 #self.repo.update(self.repo.changelog.tip())
66 self.is_reset = True
67 return 0
68 43
69 def bisect(self): 44 def bisect(self):
70 cl = self.repo.changelog 45 cl = self.repo.changelog
71 clparents = cl.parentrevs 46 clparents = cl.parentrevs
72 bad = self.badnode 47 bad = self.badnode
156 return hg.clean(self.repo, node) 131 return hg.clean(self.repo, node)
157 132
158 def good(self, rev=None): 133 def good(self, rev=None):
159 """mark revision as good and update to the next revision to test""" 134 """mark revision as good and update to the next revision to test"""
160 self.goodnodes.append(self.repo.lookup(rev or '.')) 135 self.goodnodes.append(self.repo.lookup(rev or '.'))
136 self.write()
161 if self.badnode: 137 if self.badnode:
162 return self.next() 138 return self.next()
163 139
164 def bad(self, rev=None): 140 def bad(self, rev=None):
165 """mark revision as bad and update to the next revision to test""" 141 """mark revision as bad and update to the next revision to test"""
166 self.badnode = self.repo.lookup(rev or '.') 142 self.badnode = self.repo.lookup(rev or '.')
143 self.write()
167 if self.goodnodes: 144 if self.goodnodes:
168 self.next() 145 self.next()
169 146
170 def bisect_run(ui, repo, cmd=None, *args): 147 def bisect_run(ui, repo, cmd=None, *args):
171 """Subdivision search of changesets 148 """Subdivision search of changesets
205 bisectcmdtable = { 182 bisectcmdtable = {
206 "init": (b.init, 0, _("hg bisect init")), 183 "init": (b.init, 0, _("hg bisect init")),
207 "bad": (b.bad, 1, _("hg bisect bad [<rev>]")), 184 "bad": (b.bad, 1, _("hg bisect bad [<rev>]")),
208 "good": (b.good, 1, _("hg bisect good [<rev>]")), 185 "good": (b.good, 1, _("hg bisect good [<rev>]")),
209 "next": (b.next, 0, _("hg bisect next")), 186 "next": (b.next, 0, _("hg bisect next")),
210 "reset": (b.reset, 0, _("hg bisect reset")),
211 "help": (help_, 1, _("hg bisect help [<subcommand>]")), 187 "help": (help_, 1, _("hg bisect help [<subcommand>]")),
212 } 188 }
189
190 if cmd == "reset":
191 cmd = "init"
213 192
214 if not bisectcmdtable.has_key(cmd): 193 if not bisectcmdtable.has_key(cmd):
215 ui.warn(_("bisect: Unknown sub-command\n")) 194 ui.warn(_("bisect: Unknown sub-command\n"))
216 return help_() 195 return help_()
217 if len(args) > bisectcmdtable[cmd][1]: 196 if len(args) > bisectcmdtable[cmd][1]:
218 ui.warn(_("bisect: Too many arguments\n")) 197 ui.warn(_("bisect: Too many arguments\n"))
219 return help_() 198 return help_()
220 ret = bisectcmdtable[cmd][0](*args) 199 ret = bisectcmdtable[cmd][0](*args)
221 b.write()
222 return ret 200 return ret
223 201
224 cmdtable = { 202 cmdtable = {
225 "bisect": (bisect_run, [], _("hg bisect [help|init|reset|next|good|bad]")), 203 "bisect": (bisect_run, [], _("hg bisect [help|init|reset|next|good|bad]")),
226 #"bisect-test": (test, [], "hg bisect-test rev"), 204 #"bisect-test": (test, [], "hg bisect-test rev"),