diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -670,11 +670,14 @@ ('s', 'skip', False, _('skip testing changeset')), ('e', 'extend', False, _('extend the bisect range')), ('c', 'command', '', _('use command to check changeset state'), _('CMD')), - ('U', 'noupdate', False, _('do not update to target'))], + ('U', 'noupdate', False, _('do not update to target')), + ('', 'abort', False, + _('abort bisect and update to the original changeset')), + ], _("[-gbsr] [-U] [-c CMD] [REV]")) def bisect(ui, repo, rev=None, extra=None, command=None, reset=None, good=None, bad=None, skip=None, extend=None, - noupdate=None): + noupdate=None, abort=None): """subdivision search of changesets This command helps to find changesets which introduce problems. To @@ -770,6 +773,7 @@ raise error.Abort(_('incompatible arguments')) incompatibles = { + '--abort': abort, '--bad': bad, '--command': bool(command), '--extend': extend, @@ -788,8 +792,26 @@ hbisect.resetstate(repo) return + firsttime = not hbisect.stateexists(repo) state = hbisect.load_state(repo) + if abort: + if firsttime: + raise error.Abort(_('not bisect in progress')) + cmdutil.checkunfinished(repo) + cmdutil.bailifchanged(repo) + if not state['original']: + ui.warn(_('warning: not updating since bisect state did not ' + 'include original changeset\n')) + else: + node = state['original'][0] + hg.clean(repo, node, show_stats=False) + hbisect.resetstate(repo) + return + + if firsttime: + state['original'] = [repo['.'].node()] + # update state if good or bad or skip: if rev: diff --git a/mercurial/hbisect.py b/mercurial/hbisect.py --- a/mercurial/hbisect.py +++ b/mercurial/hbisect.py @@ -154,7 +154,7 @@ return None def load_state(repo): - state = {'current': [], 'good': [], 'bad': [], 'skip': []} + state = {'current': [], 'good': [], 'bad': [], 'skip': [], 'original': []} for l in repo.vfs.tryreadlines("bisect.state"): kind, node = l[:-1].split() node = repo.lookup(node) @@ -163,7 +163,6 @@ state[kind].append(node) return state - def save_state(repo, state): f = repo.vfs("bisect.state", "w", atomictemp=True) with repo.wlock(): @@ -172,6 +171,10 @@ f.write("%s %s\n" % (kind, hex(node))) f.close() +def stateexists(repo): + """return True if bisect state exists, False otherwise""" + return repo.vfs.exists("bisect.state") + def resetstate(repo): """remove any bisect state from the repository""" if repo.vfs.exists("bisect.state"): diff --git a/tests/test-bisect-abort.t b/tests/test-bisect-abort.t new file mode 100644 --- /dev/null +++ b/tests/test-bisect-abort.t @@ -0,0 +1,36 @@ + $ cat >> $HGRCPATH < [extensions] + > drawdag=$TESTDIR/drawdag.py + > EOF + + $ hg init + $ hg debugdrawdag <<'EOS' + > D + > | + > C + > | + > B + > | + > A + > EOS + + $ hg update -q C + $ hg bisect --abort + abort: not bisect in progress + [255] + + $ hg bisect --good D + $ hg bisect --bad A + Testing changeset 1:112478962961 (3 changesets remaining, ~1 tests) + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + + $ echo 1 >> A + $ hg bisect --abort + abort: uncommitted changes + [255] + + $ hg update -q -C . + $ hg bisect --abort + + $ hg log -r . -T '{desc}\n' + C