Patchwork D1143: revset: update visibility exceptions with hidden commits from the tree

login
register
mail settings
Submitter phabricator
Date Nov. 2, 2017, 6:05 p.m.
Message ID <e4488a5eb729c85afc44994bd436d3e9@localhost.localdomain>
Download mbox | patch
Permalink /patch/25354/
State Not Applicable
Headers show

Comments

phabricator - Nov. 2, 2017, 6:05 p.m.
pulkit updated this revision to Diff 3205.
pulkit edited the summary of this revision.
pulkit retitled this revision from "revset: update repo.pinnedrevs with hidden commits from the tree" to "revset: update visibility exceptions with hidden commits from the tree".

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D1143?vs=2905&id=3205

REVISION DETAIL
  https://phab.mercurial-scm.org/D1143

AFFECTED FILES
  mercurial/revset.py

CHANGE DETAILS




To: pulkit, #hg-reviewers, indygreg
Cc: indygreg, dlax, mercurial-devel

Patch

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -22,6 +22,7 @@ 
     obsutil,
     pathutil,
     phases,
+    pycompat,
     registrar,
     repoview,
     revsetlang,
@@ -2195,6 +2196,10 @@ 
     tree = revsetlang.analyze(tree)
     tree = revsetlang.optimize(tree)
     posttreebuilthook(tree, repo)
+    # add revs to visibility exceptions if hashes of hidden revs is passed and
+    # accessing hidden commmits is allowed
+    if repo and repo.filtername in ('visible-hidden', 'visible-warnhidden'):
+        _updateexceptions(tree, repo)
     return makematcher(tree)
 
 def makematcher(tree):
@@ -2223,3 +2228,71 @@ 
 
 # tell hggettext to extract docstrings from these functions:
 i18nfunctions = symbols.values()
+
+hashre = util.re.compile('[0-9a-fA-F]{1,40}')
+_listtuple = ('symbol', '_list')
+
+def _ishashsymbol(symbol, maxrev):
+    """ returns true if symbol looks like a hash """
+
+    try:
+        n = int(symbol)
+        if n <= maxrev:
+            # It's a rev number
+            return False
+    except ValueError:
+        pass
+    return hashre.match(symbol)
+
+def gethashsymbols(tree, maxrev):
+    """
+    returns the list of symbols of the tree that look like hashes
+    for example for the revset 3::abe3ff it will return ('abe3ff')
+    """
+
+    if not tree:
+        return []
+
+    results = []
+    if len(tree) in (2, 3) and tree[0] == "symbol":
+        results.append(tree[1])
+    elif tree[0] == "func" and tree[1] == _listtuple:
+        # the optimiser will group sequence of hash request
+        results += tree[2][1].split('\0')
+    elif len(tree) >= 2:
+        for subtree in tree[1:]:
+            results += gethashsymbols(subtree, maxrev)
+        # return directly, we don't need to filter symbols again
+        return results
+    return [s for s in results if _ishashsymbol(s, maxrev)]
+
+def _updateexceptions(tree, repo):
+    """
+    extracts the symbols that looks like hashes and add them to
+    visibility exceptions set for accessing hidden hashes
+    """
+
+    hiddenset = set()
+    unfi = repo.unfiltered()
+    unficl = unfi.changelog
+    cl = repo.changelog
+    symbols = gethashsymbols(tree, len(unficl))
+    pmatch = unficl._partialmatch
+    for revnode in symbols:
+        try:
+            revnode = pmatch(revnode)
+        except error.LookupError:
+            revnode = None
+        if revnode is not None:
+            rev = unficl.rev(revnode)
+            if rev not in cl:
+                hiddenset.add(rev)
+
+    if hiddenset:
+        if repo.filtername == 'visible-warnhidden':
+            hsets = _(",").join([pycompat.bytestr(unfi[l]) for l in hiddenset])
+            repo.ui.warn(_("warning: accessing hidden changesets for write "
+                           "operation: %s\n") % hsets)
+
+        repo.addvisibilityexceptions(hiddenset)
+        repo.invalidatevolatilesets()