9 from i18n import _ |
9 from i18n import _ |
10 import os, re, sys, urllib |
10 import os, re, sys, urllib |
11 import hg, util, revlog, bundlerepo, extensions |
11 import hg, util, revlog, bundlerepo, extensions |
12 import difflib, patch, time, help, mdiff, tempfile |
12 import difflib, patch, time, help, mdiff, tempfile |
13 import errno, version, socket |
13 import errno, version, socket |
14 import archival, changegroup, cmdutil, hgweb.server, sshserver |
14 import archival, changegroup, cmdutil, hgweb.server, sshserver, hbisect |
15 |
15 |
16 # Commands start here, listed alphabetically |
16 # Commands start here, listed alphabetically |
17 |
17 |
18 def add(ui, repo, *pats, **opts): |
18 def add(ui, repo, *pats, **opts): |
19 """add the specified files on the next commit |
19 """add the specified files on the next commit |
243 else: |
243 else: |
244 ui.status(_('the backout changeset is a new head - ' |
244 ui.status(_('the backout changeset is a new head - ' |
245 'do not forget to merge\n')) |
245 'do not forget to merge\n')) |
246 ui.status(_('(use "backout --merge" ' |
246 ui.status(_('(use "backout --merge" ' |
247 'if you want to auto-merge)\n')) |
247 'if you want to auto-merge)\n')) |
|
248 |
|
249 def bisect(ui, repo, rev=None, extra=None, |
|
250 reset=None, good=None, bad=None, skip=None, noupdate=None): |
|
251 """subdivision search of changesets |
|
252 |
|
253 This command helps to find changesets which introduce problems. |
|
254 To use, mark the earliest changeset you know exhibits the problem |
|
255 as bad, then mark the latest changeset which is free from the |
|
256 problem as good. Bisect will update your working directory to a |
|
257 revision for testing. Once you have performed tests, mark the |
|
258 working directory as bad or good and bisect will either update to |
|
259 another candidate changeset or announce that it has found the bad |
|
260 revision. |
|
261 |
|
262 Note: bisect expects bad revisions to be descendants of good |
|
263 revisions. If you are looking for the point at which a problem was |
|
264 fixed, then make the problem-free state \"bad\" and the |
|
265 problematic state \"good.\" |
|
266 """ |
|
267 # backward compatibility |
|
268 if rev in "good bad reset init".split(): |
|
269 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n")) |
|
270 cmd, rev, extra = rev, extra, None |
|
271 if cmd == "good": |
|
272 good = True |
|
273 elif cmd == "bad": |
|
274 bad = True |
|
275 else: |
|
276 reset = True |
|
277 elif extra or good + bad + skip + reset > 1: |
|
278 raise util.Abort("Incompatible arguments") |
|
279 |
|
280 if reset: |
|
281 p = repo.join("bisect.state") |
|
282 if os.path.exists(p): |
|
283 os.unlink(p) |
|
284 return |
|
285 |
|
286 # load state |
|
287 state = {'good': [], 'bad': [], 'skip': []} |
|
288 if os.path.exists(repo.join("bisect.state")): |
|
289 for l in repo.opener("bisect.state"): |
|
290 kind, node = l[:-1].split() |
|
291 node = repo.lookup(node) |
|
292 if kind not in state: |
|
293 raise util.Abort(_("unknown bisect kind %s") % kind) |
|
294 state[kind].append(node) |
|
295 |
|
296 # update state |
|
297 node = repo.lookup(rev or '.') |
|
298 if good: |
|
299 state['good'].append(node) |
|
300 elif bad: |
|
301 state['bad'].append(node) |
|
302 elif skip: |
|
303 state['skip'].append(node) |
|
304 |
|
305 # save state |
|
306 f = repo.opener("bisect.state", "w", atomictemp=True) |
|
307 wlock = repo.wlock() |
|
308 try: |
|
309 for kind in state: |
|
310 for node in state[kind]: |
|
311 f.write("%s %s\n" % (kind, hg.hex(node))) |
|
312 f.rename() |
|
313 finally: |
|
314 del wlock |
|
315 |
|
316 if not state['good'] or not state['bad']: |
|
317 return |
|
318 |
|
319 # actually bisect |
|
320 node, changesets = hbisect.bisect(repo.changelog, state) |
|
321 if changesets == 0: |
|
322 ui.write(_("The first bad revision is:\n")) |
|
323 displayer = cmdutil.show_changeset(ui, repo, {}) |
|
324 displayer.show(changenode=node) |
|
325 elif node is not None: |
|
326 # compute the approximate number of remaining tests |
|
327 tests, size = 0, 2 |
|
328 while size <= changesets: |
|
329 tests, size = tests + 1, size * 2 |
|
330 rev = repo.changelog.rev(node) |
|
331 ui.write(_("Testing changeset %s:%s " |
|
332 "(%s changesets remaining, ~%s tests)\n") |
|
333 % (rev, hg.short(node), changesets, tests)) |
|
334 if not noupdate: |
|
335 cmdutil.bail_if_changed(repo) |
|
336 return hg.clean(repo, node) |
248 |
337 |
249 def branch(ui, repo, label=None, **opts): |
338 def branch(ui, repo, label=None, **opts): |
250 """set or show the current branch name |
339 """set or show the current branch name |
251 |
340 |
252 With no argument, show the current branch name. With one argument, |
341 With no argument, show the current branch name. With one argument, |
2656 _('merge with old dirstate parent after backout')), |
2745 _('merge with old dirstate parent after backout')), |
2657 ('', 'parent', '', _('parent to choose when backing out merge')), |
2746 ('', 'parent', '', _('parent to choose when backing out merge')), |
2658 ('r', 'rev', '', _('revision to backout')), |
2747 ('r', 'rev', '', _('revision to backout')), |
2659 ] + walkopts + commitopts + commitopts2, |
2748 ] + walkopts + commitopts + commitopts2, |
2660 _('hg backout [OPTION]... [-r] REV')), |
2749 _('hg backout [OPTION]... [-r] REV')), |
|
2750 "bisect": (bisect, |
|
2751 [('r', 'reset', False, _('reset bisect state')), |
|
2752 ('g', 'good', False, _('mark changeset good')), |
|
2753 ('b', 'bad', False, _('mark changeset bad')), |
|
2754 ('s', 'skip', False, _('skip testing changeset')), |
|
2755 ('U', 'noupdate', False, _('do not update to target'))], |
|
2756 _("hg bisect [-gbsr] [REV]")), |
2661 "branch": |
2757 "branch": |
2662 (branch, |
2758 (branch, |
2663 [('f', 'force', None, |
2759 [('f', 'force', None, |
2664 _('set branch name even if it shadows an existing branch'))], |
2760 _('set branch name even if it shadows an existing branch'))], |
2665 _('hg branch [NAME]')), |
2761 _('hg branch [NAME]')), |