diff --git a/mercurial/configitems.py b/mercurial/configitems.py --- a/mercurial/configitems.py +++ b/mercurial/configitems.py @@ -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, ) diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py --- a/mercurial/scmutil.py +++ b/mercurial/scmutil.py @@ -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