diff --git a/hgext/remotenames.py b/hgext/remotenames.py --- a/hgext/remotenames.py +++ b/hgext/remotenames.py @@ -43,6 +43,10 @@ templateutil, ) +from mercurial.utils import ( + stringutil, +) + if pycompat.ispy3: import collections.abc mutablemapping = collections.abc.MutableMapping @@ -343,34 +347,91 @@ return templateutil.compatlist(context, mapping, 'remotebranch', remotebranches, plural='remotebranches') -def _revsetutil(repo, subset, x, rtypes): +def _revsetutil(repo, subset, x, rtypes, args): """utility function to return a set of revs based on the rtypes""" revs = set() cl = repo.changelog + literals, matchers = args + # whether arguments were passed or not + argspassed = bool(literals or matchers) for rtype in rtypes: if rtype in repo.names: ns = repo.names[rtype] for name in ns.listnames(repo): - revs.update(ns.nodes(repo, name)) + if argspassed: + if name in literals: + revs.update(ns.nodes(repo, name)) + continue + for matcher in matchers: + if matcher(name): + revs.update(ns.nodes(repo, name)) + break + else: + revs.update(ns.nodes(repo, name)) results = (cl.rev(n) for n in revs if cl.hasnode(n)) return subset & smartset.baseset(sorted(results)) -@revsetpredicate('remotenames()') +def _parseargs(x): + """parses the argument passed in revsets + + returns (literals, matchers) where, + literals is a set of literals passed by user + matchers is a list of matcher objects for patterns passed by user + """ + + # set of paths passed as literals + literals = set() + # list of matcher to match the patterns passed as names + matchers = [] + + if not x: + return literals, matchers + + args = set() + lx = revsetlang.getlist(x) + err = _('the argument must be a string') + for entry in lx: + args.add(revsetlang.getstring(entry, err)) + for p in args: + kind, pattern, matcher = stringutil.stringmatcher(p) + if kind == 'literal': + literals.add(pattern) + else: + matchers.append(matcher) + return literals, matchers + +@revsetpredicate('remotenames([name, ...])') def remotenamesrevset(repo, subset, x): - """All changesets which have a remotename on them.""" - revsetlang.getargs(x, 0, 0, _("remotenames takes no arguments")) - return _revsetutil(repo, subset, x, ('remotebookmarks', 'remotebranches')) + """All changesets which have a remotename on them. If paths are specified, + remotenames of those remote paths are only considered. + + Pattern matching is supported for `name`. See :hg:`help revisions.patterns`. + """ -@revsetpredicate('remotebranches()') + args = _parseargs(x) + return _revsetutil(repo, subset, x, ('remotebookmarks', 'remotebranches'), + args) + +@revsetpredicate('remotebranches([name, ...])') def remotebranchesrevset(repo, subset, x): - """All changesets which are branch heads on remotes.""" - revsetlang.getargs(x, 0, 0, _("remotebranches takes no arguments")) - return _revsetutil(repo, subset, x, ('remotebranches',)) + """All changesets which are branch heads on remotes. If paths are specified, + only those remotes paths are considered. + + Pattern matching is supported for `name`. See :hg:`help revisions.patterns`. + """ + + args = _parseargs(x) + return _revsetutil(repo, subset, x, ('remotebranches',), args) -@revsetpredicate('remotebookmarks()') +@revsetpredicate('remotebookmarks([name, ...])') def remotebmarksrevset(repo, subset, x): - """All changesets which have bookmarks on remotes.""" - revsetlang.getargs(x, 0, 0, _("remotebookmarks takes no arguments")) - return _revsetutil(repo, subset, x, ('remotebookmarks',)) + """All changesets which have bookmarks on remotes. If paths are specified, + only those remote paths are considered. + + Pattern matching is supported for `name`. See :hg:`help revisions.patterns`. + """ + + args = _parseargs(x) + return _revsetutil(repo, subset, x, ('remotebookmarks',), args) diff --git a/tests/test-logexchange.t b/tests/test-logexchange.t --- a/tests/test-logexchange.t +++ b/tests/test-logexchange.t @@ -291,6 +291,7 @@ ~ Updating to revision using hoisted name +--------------------------------------- Deleting local bookmark to make sure we update to hoisted name only @@ -395,3 +396,187 @@ default/bar 6:87d6d6676308 default/foo 8:3e1487808078 * foo 8:3e1487808078 + +Testing the names argument to remotenames, remotebranches and remotebookmarks revsets +-------------------------------------------------------------------------------------- + + $ cd .. + $ hg clone ssh://user@dummy/server client2 + requesting all changes + adding changesets + adding manifests + adding file changes + added 9 changesets with 9 changes to 9 files (+1 heads) + new changesets 18d04c59bb5d:3e1487808078 + updating to branch default + 8 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd server2 + $ hg up wat + 6 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo foo > watwat + $ hg ci -Aqm "added watwat" + $ hg bookmark bar + abort: bookmark 'bar' already exists (use -f to force) + [255] + $ hg up ec24 + 3 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ echo i > i + $ hg ci -Aqm "added i" + + $ cd ../client2 + $ echo "[paths]" >> .hg/hgrc + $ echo "server2 = $TESTTMP/server2" >> .hg/hgrc + $ hg pull server2 + pulling from $TESTTMP/server2 + searching for changes + adding changesets + adding manifests + adding file changes + added 2 changesets with 2 changes to 2 files + new changesets f34adec73c21:bf433e48adea + (run 'hg update' to get a working copy) + + $ hg log -Gr 'remotenames()' -T '{rev}:{node|short} {desc}\n({remotebranches}) [{remotebookmarks}]\n\n' + o 10:bf433e48adea added i + | (server2/default) [] + | + | o 9:f34adec73c21 added watwat + | | (server2/wat) [] + | | + | o 8:3e1487808078 added bar + | : (default/wat) [default/foo] + | : + @ : 7:ec2426147f0e Added h + | : (default/default) [] + | : + o : 6:87d6d6676308 Added g + :/ () [default/bar server2/bar] + : + o 3:62615734edd5 Added d + | () [server2/foo] + ~ + +Testing for a single remote name which exists + + $ hg log -r 'remotebranches("default/wat")' -GT "{rev}:{node|short} {remotebranches}\n" + o 8:3e1487808078 default/wat + | + ~ + + $ hg log -r 'remotebookmarks("server2/foo")' -GT "{rev}:{node|short} {remotebookmarks}\n" + o 3:62615734edd5 server2/foo + | + ~ + + $ hg log -r 'remotenames("re:default")' -GT "{rev}:{node|short} {remotenames}\n" + o 10:bf433e48adea server2/default + | + | o 8:3e1487808078 default/foo default/wat + | | + | ~ + @ 7:ec2426147f0e default/default + | + o 6:87d6d6676308 default/bar server2/bar + | + ~ + +Testing for a single name which does not exists + + $ hg log -r 'remotebranches(def)' -GT "{rev}:{node|short} {remotenames}\n" + + $ hg log -r 'remotebookmarks("server3")' -GT "{rev}:{node|short} {remotenames}\n" + + $ hg log -r 'remotenames("server3")' -GT "{rev}:{node|short} {remotenames}\n" + +Testing for multiple names where all of them exists + + $ hg log -r 'remotenames("re:default", "re:server2")' -GT "{rev}:{node|short} {remotenames}\n" + o 10:bf433e48adea server2/default + | + | o 9:f34adec73c21 server2/wat + | | + | o 8:3e1487808078 default/foo default/wat + | : + @ : 7:ec2426147f0e default/default + | : + o : 6:87d6d6676308 default/bar server2/bar + :/ + o 3:62615734edd5 server2/foo + | + ~ + + $ hg log -r 'remotebranches("default/wat", "server2/wat")' -GT "{rev}:{node|short} {remotebranches}\n" + o 9:f34adec73c21 server2/wat + | + o 8:3e1487808078 default/wat + | + ~ + + $ hg log -r 'remotebookmarks("default/foo", "server2/foo")' -GT "{rev}:{node|short} {remotebookmarks}\n" + o 8:3e1487808078 default/foo + : + o 3:62615734edd5 server2/foo + | + ~ + +Testing for multipe names where some exists and some not + + $ hg log -r 'remotenames(def, "re:server2")' -GT "{rev}:{node|short} {remotenames}\n" + o 10:bf433e48adea server2/default + : + : o 9:f34adec73c21 server2/wat + : : + o : 6:87d6d6676308 default/bar server2/bar + :/ + o 3:62615734edd5 server2/foo + | + ~ + + $ hg log -r 'remotebranches("default/default", server)' -GT "{rev}:{node|short} {remotebranches}\n" + @ 7:ec2426147f0e default/default + | + ~ + + $ hg log -r 'remotebookmarks("default/foo", serv)' -GT "{rev}:{node|short} {remotebookmarks}\n" + o 8:3e1487808078 default/foo + | + ~ + +Where multiple names specified and None of them exists + + $ hg log -r 'remotenames(def, serv2)' -GT "{rev}:{node|short} {remotenames}\n" + + $ hg log -r 'remotebranches(defu, server)' -GT "{rev}:{node|short} {remotebranches}\n" + + $ hg log -r 'remotebookmarks(delt, serv)' -GT "{rev}:{node|short} {remotebookmarks}\n" + +Testing pattern matching + + $ hg log -r 'remotenames("re:def")' -GT "{rev}:{node|short} {remotenames}\n" + o 10:bf433e48adea server2/default + | + | o 8:3e1487808078 default/foo default/wat + | | + | ~ + @ 7:ec2426147f0e default/default + | + o 6:87d6d6676308 default/bar server2/bar + | + ~ + + $ hg log -r 'remotebranches("re:ser.*2")' -GT "{rev}:{node|short} {remotebranches}\n" + o 10:bf433e48adea server2/default + | + ~ + o 9:f34adec73c21 server2/wat + | + ~ + + $ hg log -r 'remotebookmarks("re:def", "re:.*2")' -GT "{rev}:{node|short} {remotebookmarks}\n" + o 8:3e1487808078 default/foo + : + : o 6:87d6d6676308 default/bar server2/bar + :/ + o 3:62615734edd5 server2/foo + | + ~