scmutil: add utility fn to return repo object with user passed revs unhidden
authorPulkit Goyal <7895pulkit@gmail.com>
Fri, 15 Dec 2017 04:31:29 +0530
changeset 35496 8bb90cc4668e
parent 35495 07fdac1d5c66
child 35497 b378a3d840ab
scmutil: add utility fn to return repo object with user passed revs unhidden There has been a need for accessing hidden changesets by default without passing --hidden. This is currently done using the directaccess extension but is bit hacky. This patch adds a utility function to return a repo object having user passed revisions unhidden. This functionality will live behind a config option and won't be the default behaviour. There is also a config option added by this patch which tells whether we want to unhide only those revisions whose hashes are passed or should we consider revisions numbers also. Differential Revision: https://phab.mercurial-scm.org/D1733
mercurial/configitems.py
mercurial/scmutil.py
--- a/mercurial/configitems.py	Mon Dec 18 17:50:02 2017 +0530
+++ b/mercurial/configitems.py	Fri Dec 15 04:31:29 2017 +0530
@@ -452,6 +452,12 @@
 coreconfigitem('experimental', 'crecordtest',
     default=None,
 )
+coreconfigitem('experimental', 'directaccess',
+    default=False,
+)
+coreconfigitem('experimental', 'directaccess.revnums',
+    default=False,
+)
 coreconfigitem('experimental', 'editortmpinhg',
     default=False,
 )
--- a/mercurial/scmutil.py	Mon Dec 18 17:50:02 2017 +0530
+++ b/mercurial/scmutil.py	Fri Dec 15 04:31:29 2017 +0530
@@ -1305,3 +1305,79 @@
     before it is used, whether or not the convert extension was formally loaded.
     """
     return sink
+
+def unhidehashlikerevs(repo, specs, hiddentype):
+    """parse the user specs and unhide changesets whose hash or revision number
+    is passed.
+
+    hiddentype can be: 1) 'warn': warn while unhiding changesets
+                       2) 'nowarn': don't warn while unhiding changesets
+
+    returns a repo object with the required changesets unhidden
+    """
+    if not repo.filtername or not repo.ui.configbool('experimental',
+                                                     'directaccess'):
+        return repo
+
+    if not repo.filtername.startswith('visible'):
+        return repo
+
+    symbols = set()
+    for spec in specs:
+        try:
+            tree = revsetlang.parse(spec)
+        except error.ParseError: # will be reported by scmutil.revrange()
+            continue
+
+        symbols.update(revsetlang.gethashlikesymbols(tree))
+
+    if not symbols:
+        return repo
+
+    revs = _getrevsfromsymbols(repo, symbols)
+
+    if not revs:
+        return repo
+
+    if hiddentype == 'warn':
+        unfi = repo.unfiltered()
+        revstr = ", ".join([pycompat.bytestr(unfi[l]) for l in revs])
+        repo.ui.warn(_("warning: accessing hidden changesets for write "
+                       "operation: %s\n") % revstr)
+
+    return repo.filtered('visible-hidden', revs)
+
+def _getrevsfromsymbols(repo, symbols):
+    """parse the list of symbols and returns a set of revision numbers of hidden
+    changesets present in symbols"""
+    revs = set()
+    unfi = repo.unfiltered()
+    unficl = unfi.changelog
+    cl = repo.changelog
+    tiprev = len(unficl)
+    pmatch = unficl._partialmatch
+    allowrevnums = repo.ui.configbool('experimental', 'directaccess.revnums')
+    for s in symbols:
+        try:
+            n = int(s)
+            if n <= tiprev:
+                if not allowrevnums:
+                    continue
+                else:
+                    if n not in cl:
+                        revs.add(n)
+                    continue
+        except ValueError:
+            pass
+
+        try:
+            s = pmatch(s)
+        except error.LookupError:
+            s = None
+
+        if s is not None:
+            rev = unficl.rev(s)
+            if rev not in cl:
+                revs.add(rev)
+
+    return revs