[PATCH] bisect: ability to check revision with command
Sune Foldager
cryo at cyanite.org
Sat Oct 11 04:35:25 CDT 2008
It's "its exit status" and not "it's exit status" :-)
-- Sune
On 10/10/2008, at 17.58, Alexander Solovyov <piranha at piranha.org.ua>
wrote:
> # HG changeset patch
> # User Alexander Solovyov <piranha at piranha.org.ua>
> # Date 1223647094 -10800
> # Node ID 0bfd347f3c9dec484406f634ae95e4a90a841781
> # Parent c29d3f4ed967fc758541ce2e5018f1eb7cae87c8
> bisect: ability to check revision with command
>
> diff --git a/mercurial/commands.py b/mercurial/commands.py
> --- a/mercurial/commands.py
> +++ b/mercurial/commands.py
> @@ -260,7 +260,7 @@
> ui.status(_('(use "backout --merge" '
> 'if you want to auto-merge)\n'))
>
> -def bisect(ui, repo, rev=None, extra=None,
> +def bisect(ui, repo, rev=None, extra=None, command=None,
> reset=None, good=None, bad=None, skip=None,
> noupdate=None):
> """subdivision search of changesets
>
> @@ -275,67 +275,12 @@
>
> As a shortcut, you can also use the revision argument to mark a
> revision as good or bad without checking it out first.
> +
> + If you supply a command it will be used for automatic
> bisection. It's
> + exit status will be used as flag to mark revision as bad or
> good (good
> + in case of 0 and bad in any other case).
> """
> - # backward compatibility
> - if rev in "good bad reset init".split():
> - ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
> - cmd, rev, extra = rev, extra, None
> - if cmd == "good":
> - good = True
> - elif cmd == "bad":
> - bad = True
> - else:
> - reset = True
> - elif extra or good + bad + skip + reset > 1:
> - raise util.Abort(_('incompatible arguments'))
> -
> - if reset:
> - p = repo.join("bisect.state")
> - if os.path.exists(p):
> - os.unlink(p)
> - return
> -
> - # load state
> - state = {'good': [], 'bad': [], 'skip': []}
> - if os.path.exists(repo.join("bisect.state")):
> - for l in repo.opener("bisect.state"):
> - kind, node = l[:-1].split()
> - node = repo.lookup(node)
> - if kind not in state:
> - raise util.Abort(_("unknown bisect kind %s") % kind)
> - state[kind].append(node)
> -
> - # update state
> - node = repo.lookup(rev or '.')
> - if good:
> - state['good'].append(node)
> - elif bad:
> - state['bad'].append(node)
> - elif skip:
> - state['skip'].append(node)
> -
> - # save state
> - f = repo.opener("bisect.state", "w", atomictemp=True)
> - wlock = repo.wlock()
> - try:
> - for kind in state:
> - for node in state[kind]:
> - f.write("%s %s\n" % (kind, hex(node)))
> - f.rename()
> - finally:
> - del wlock
> -
> - if not state['good'] or not state['bad']:
> - if (good or bad or skip or reset):
> - return
> - if not state['good']:
> - raise util.Abort(_('cannot bisect (no known good
> revisions)'))
> - else:
> - raise util.Abort(_('cannot bisect (no known bad
> revisions)'))
> -
> - # actually bisect
> - nodes, changesets, good = hbisect.bisect(repo.changelog, state)
> - if changesets == 0:
> + def print_result(nodes, good):
> displayer = cmdutil.show_changeset(ui, repo, {})
> transition = (good and "good" or "bad")
> if len(nodes) == 1:
> @@ -348,6 +293,74 @@
> "%s revision could be any of:\n") % transition)
> for n in nodes:
> displayer.show(changenode=n)
> +
> + def check_state(state, interactive=True):
> + if not state['good'] or not state['bad']:
> + if (good or bad or skip or reset) and interactive:
> + return
> + if not state['good']:
> + raise util.Abort(_('cannot bisect (no known good
> revisions)'))
> + else:
> + raise util.Abort(_('cannot bisect (no known bad
> revisions)'))
> + return True
> +
> + # backward compatibility
> + if rev in "good bad reset init".split():
> + ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
> + cmd, rev, extra = rev, extra, None
> + if cmd == "good":
> + good = True
> + elif cmd == "bad":
> + bad = True
> + else:
> + reset = True
> + elif extra or good + bad + skip + reset + bool(command) > 1:
> + raise util.Abort(_('incompatible arguments'))
> +
> + if reset:
> + p = repo.join("bisect.state")
> + if os.path.exists(p):
> + os.unlink(p)
> + return
> +
> + state = hbisect.load_state(repo)
> +
> + if command:
> + changesets = 1
> + while changesets:
> + # check state
> + status = bool(list(os.popen3(command)[2]))
> + node = repo.lookup(rev or '.')
> + transition = (status and 'bad' or 'good')
> + state[transition].append(node)
> + ui.note(_('Changeset %s: %s\n') % (short(node),
> transition))
> + check_state(state, interactive=False)
> + # bisect
> + nodes, changesets, good =
> hbisect.bisect(repo.changelog, state)
> + # update to next check
> + cmdutil.bail_if_changed(repo)
> + hg.clean(repo, nodes[0], show_stats=False)
> + hbisect.save_state(repo, state)
> + return print_result(nodes, not status)
> +
> + # update state
> + node = repo.lookup(rev or '.')
> + if good:
> + state['good'].append(node)
> + elif bad:
> + state['bad'].append(node)
> + elif skip:
> + state['skip'].append(node)
> +
> + hbisect.save_state(repo, state)
> +
> + if not check_state(state):
> + return
> +
> + # actually bisect
> + nodes, changesets, good = hbisect.bisect(repo.changelog, state)
> + if changesets == 0:
> + print_result(nodes, good)
> else:
> assert len(nodes) == 1 # only a single node can be tested next
> node = nodes[0]
> @@ -2986,8 +2999,9 @@
> ('g', 'good', False, _('mark changeset good')),
> ('b', 'bad', False, _('mark changeset bad')),
> ('s', 'skip', False, _('skip testing changeset')),
> + ('c', 'command', '', _('Use command to check changeset
> state')),
> ('U', 'noupdate', False, _('do not update to target'))],
> - _("hg bisect [-gbsr] [REV]")),
> + _("hg bisect [-gbsr] [REV] [-c COMMAND]")),
> "branch":
> (branch,
> [('f', 'force', None,
> diff --git a/mercurial/hbisect.py b/mercurial/hbisect.py
> --- a/mercurial/hbisect.py
> +++ b/mercurial/hbisect.py
> @@ -7,8 +7,9 @@
> # This software may be used and distributed according to the terms
> # of the GNU General Public License, incorporated herein by reference.
>
> +import os
> from i18n import _
> -from node import short
> +from node import short, hex
> import util
>
> def bisect(changelog, state):
> @@ -116,3 +117,28 @@
> best_node = changelog.node(best_rev)
>
> return ([best_node], tot, good)
> +
> +
> +def load_state(repo):
> + state = {'good': [], 'bad': [], 'skip': []}
> + if os.path.exists(repo.join("bisect.state")):
> + for l in repo.opener("bisect.state"):
> + kind, node = l[:-1].split()
> + node = repo.lookup(node)
> + if kind not in state:
> + raise util.Abort(_("unknown bisect kind %s") % kind)
> + state[kind].append(node)
> + return state
> +
> +
> +def save_state(repo, state):
> + f = repo.opener("bisect.state", "w", atomictemp=True)
> + wlock = repo.wlock()
> + try:
> + for kind in state:
> + for node in state[kind]:
> + f.write("%s %s\n" % (kind, hex(node)))
> + f.rename()
> + finally:
> + del wlock
> +
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
More information about the Mercurial-devel
mailing list