mirror of
https://github.com/facebook/sapling.git
synced 2024-10-05 14:28:17 +03:00
bisect: support lazy evaluation for 'skip' option
Summary: Currently, the 'skip' option is too slow when users want to use it to bisect on a file or folder like below: sl bisect --skip "!( file('path:foo') & file('path:bar') )" Since it tries to eval the skip revset upfront, which takes a long time for current `file` implementation. This diff make it lazy evaluated. Reviewed By: muirdm Differential Revision: D46643574 fbshipit-source-id: c063fbea2bc0703772e07d5167adc8fbf989a68f
This commit is contained in:
parent
38c190a35a
commit
a7e82b1613
@ -1174,16 +1174,34 @@ the sparse profile from the known %s changeset %s\n"
|
||||
|
||||
|
||||
def _update_state(repo, state, rev, good, bad, skip):
|
||||
if rev:
|
||||
nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
|
||||
else:
|
||||
nodes = [repo.lookup(".")]
|
||||
def get_nodes(rev):
|
||||
nodes = (
|
||||
[repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
|
||||
if rev
|
||||
else [repo.lookup(".")]
|
||||
)
|
||||
return nodes
|
||||
|
||||
def get_revs(rev):
|
||||
"""lazy evaluate `rev` revset expression if it is large.
|
||||
|
||||
This is only used for 'skip' status now.
|
||||
"""
|
||||
revs = scmutil.revrange(repo, [rev or "."])
|
||||
fastlen = revs.fastlen()
|
||||
# revset check is slower than nodes check, so avoid revset expr for small revsets.
|
||||
# for example, user might just want to skip a single commit.
|
||||
if fastlen is not None and fastlen < 10:
|
||||
return list(repo.changelog.tonodes(revs))
|
||||
else:
|
||||
return [f"revset:{rev}"]
|
||||
|
||||
if good:
|
||||
state["good"] += nodes
|
||||
state["good"] += get_nodes(rev)
|
||||
elif bad:
|
||||
state["bad"] += nodes
|
||||
state["bad"] += get_nodes(rev)
|
||||
elif skip:
|
||||
state["skip"] += nodes
|
||||
state["skip"] += get_revs(rev)
|
||||
|
||||
|
||||
@command(
|
||||
|
@ -37,7 +37,7 @@ def bisect(repo, state):
|
||||
|
||||
changelog = repo.changelog
|
||||
clparents = changelog.parentrevs
|
||||
skip = set([changelog.rev(n) for n in state["skip"]])
|
||||
skip = _state_to_revs(repo, state, "skip")
|
||||
|
||||
def buildancestors(bad, good):
|
||||
badrev = min([changelog.rev(n) for n in bad])
|
||||
@ -219,6 +219,22 @@ def checkstate(state) -> bool:
|
||||
raise error.Abort(_("cannot bisect (no known bad revisions)"))
|
||||
|
||||
|
||||
def _state_to_revs(repo, state, kind):
|
||||
items = state[kind]
|
||||
nodes = []
|
||||
revset_exprs = []
|
||||
|
||||
for item in items:
|
||||
if isinstance(item, bytes):
|
||||
nodes.append(item)
|
||||
elif item.startswith("revset:"):
|
||||
revset_exprs.append(item[7:])
|
||||
else:
|
||||
raise error.Abort(_("invalid node: %s, kind: %s") % (item, kind))
|
||||
|
||||
return repo.revs("%ln or %lr", nodes, revset_exprs)
|
||||
|
||||
|
||||
def get(repo, status):
|
||||
"""
|
||||
Return a list of revision(s) that match the given status:
|
||||
@ -233,7 +249,7 @@ def get(repo, status):
|
||||
"""
|
||||
state = load_state(repo)
|
||||
if status in ("good", "bad", "skip", "current"):
|
||||
return list(map(repo.changelog.rev, state[status]))
|
||||
return list(_state_to_revs(repo, state, status))
|
||||
else:
|
||||
# In the following sets, we do *not* call 'bisect()' with more
|
||||
# than one level of recursion, because that can be very, very
|
||||
|
@ -18,18 +18,7 @@
|
||||
|
||||
$ hg bisect -s "! (file('path:E') or file('path:M'))"
|
||||
$ cat .hg/bisect.state
|
||||
skip 426bada5c67598ca65036d57d9e4b64b0c1ce7a0
|
||||
skip 112478962961147124edd43549aedd1a335e44bf
|
||||
skip 26805aba1e600a82e93661149f2313866a221a7b
|
||||
skip f585351a92f85104bff7c284233c338b10eb1df7
|
||||
skip a194cadd16930608adaa649035ad4c16930cbd0f
|
||||
skip 43195508e3bb704c08d24c40375bdd826789dd72
|
||||
skip a31451c3c1debad52cf22ef2aebfc88c75dc899a
|
||||
skip 47eb959e86339c47666b6d1e12c7a9ea534aea1c
|
||||
skip 08eb06eada62c63c386dde447d379684d2a0156d
|
||||
skip fb35f87c67da3431b7514753fc516ec66a60be78
|
||||
skip 652ea04869f63d6b6ce47da40f4fb76e01516a98
|
||||
skip 71d6430ccd823b5187025bfdedc0ac6d8c0f7e34
|
||||
skip revset:! (file('path:E') or file('path:M'))
|
||||
|
||||
$ hg bisect -g $A
|
||||
$ hg bisect -b $N
|
||||
|
@ -246,10 +246,10 @@
|
||||
good b5bd63375ab9a290419f2024b7f4ee9ea7ce90a8
|
||||
good ed2d2f24b11c368fa8aa0da9f4e1db580abade59
|
||||
good 58c80a7c8a4025a94cedaf7b4a4e3124e8909a96
|
||||
skip 9d7d07bc967ca98ad0600c24953fd289ad5fa991
|
||||
skip ce8f0998e922c179e80819d5066fbe46e2998784
|
||||
skip e7fa0811edb063f6319531f0d0a865882138e180
|
||||
skip a2e6ea4973e9196ddd3386493b0c214b41fd97d3
|
||||
skip e7fa0811edb063f6319531f0d0a865882138e180
|
||||
skip ce8f0998e922c179e80819d5066fbe46e2998784
|
||||
skip 9d7d07bc967ca98ad0600c24953fd289ad5fa991
|
||||
|
||||
# bisect reverse test
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user