comparison mercurial/scmutil.py @ 38842:503f936489dd

lookup: add option to disambiguate prefix within revset When resolving a nodeid prefix that is not unique within the repo and the user has configured a revset that they want to disambiguate within, we now try to look up within that revset before we fail. If there is a unique match within the revset, we use that. This is of course most effective at allowing a short prefix if the revset contains few nodes. For most of our internal users at Google, "not public()" is sufficiently small that a hex digit or two is enough. The implementation is currently pretty slow, but good enough for small revsets (which is the expected use case). The scan in the revset is linear. We may want to use a prefix tree if we want to allow users to use a larger revset. Credit for the idea goes to Kyle Lippincott. Differential Revision: https://phab.mercurial-scm.org/D4037
author Martin von Zweigbergk <martinvonz@google.com>
date Wed, 28 Mar 2018 09:36:02 -0700
parents df0873ab5c14
children 6f7c9527030b
comparison
equal deleted inserted replaced
38841:df0873ab5c14 38842:503f936489dd
435 else: 435 else:
436 hexfunc = short 436 hexfunc = short
437 return '%d:%s' % (rev, hexfunc(node)) 437 return '%d:%s' % (rev, hexfunc(node))
438 438
439 def resolvehexnodeidprefix(repo, prefix): 439 def resolvehexnodeidprefix(repo, prefix):
440 # Uses unfiltered repo because it's faster when prefix is ambiguous/ 440 try:
441 # This matches the shortesthexnodeidprefix() function below. 441 # Uses unfiltered repo because it's faster when prefix is ambiguous/
442 node = repo.unfiltered().changelog._partialmatch(prefix) 442 # This matches the shortesthexnodeidprefix() function below.
443 node = repo.unfiltered().changelog._partialmatch(prefix)
444 except error.AmbiguousPrefixLookupError:
445 revset = repo.ui.config('experimental', 'revisions.disambiguatewithin')
446 if revset:
447 # Clear config to avoid infinite recursion
448 configoverrides = {('experimental',
449 'revisions.disambiguatewithin'): None}
450 with repo.ui.configoverride(configoverrides):
451 revs = repo.anyrevs([revset], user=True)
452 matches = []
453 for rev in revs:
454 node = repo.changelog.node(rev)
455 if hex(node).startswith(prefix):
456 matches.append(node)
457 if len(matches) == 1:
458 return matches[0]
459 raise
443 if node is None: 460 if node is None:
444 return 461 return
445 repo.changelog.rev(node) # make sure node isn't filtered 462 repo.changelog.rev(node) # make sure node isn't filtered
446 return node 463 return node
447 464