Patchwork [1,of,2] remotenames: add names argument to remotenames revset

login
register
mail settings
Submitter Augie Fackler
Date Oct. 5, 2018, 2:39 a.m.
Message ID <6638bd3f061b89b3b0bf.1538707163@imladris.local>
Download mbox | patch
Permalink /patch/35478/
State Accepted
Headers show

Comments

Augie Fackler - Oct. 5, 2018, 2:39 a.m.
# HG changeset patch
# User Pulkit Goyal <7895pulkit@gmail.com>
# Date 1531345329 -19800
#      Thu Jul 12 03:12:09 2018 +0530
# Node ID 6638bd3f061b89b3b0bf432799da79e1fee5eb62
# Parent  91f7402537a0ffd278dd7809f698dc28a955c901
remotenames: add names argument to remotenames revset

This patch adds names argument to the revsets provided by the remotenames
extension. The revsets are remotenames(), remotebranches() and
remotebookmarks(). names can be a single names, list of names or can be empty too
which means it's an optional argument.

If names is/are passed, changesets which have those remotenames will be
returned.
If names are not passed, changesets from all the remotenames are shown.

Passing an invalid remotename does not throw error.

The name argument also supports pattern matching.

Tests are added for the argument in tests/test-logexchange.t

Differential Revision: https://phab.mercurial-scm.org/D3639

Patch

diff --git a/hgext/remotenames.py b/hgext/remotenames.py
--- a/hgext/remotenames.py
+++ b/hgext/remotenames.py
@@ -43,6 +43,10 @@  from mercurial import (
     templateutil,
 )
 
+from mercurial.utils import (
+    stringutil,
+)
+
 if pycompat.ispy3:
     import collections.abc
     mutablemapping = collections.abc.MutableMapping
@@ -343,34 +347,91 @@  def remotebrancheskw(context, mapping):
     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`.
+    """
+
+    args = _parseargs(x)
+    return _revsetutil(repo, subset, x, ('remotebookmarks', 'remotebranches'),
+                       args)
 
-@revsetpredicate('remotebranches()')
+@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`.
+    """
 
-@revsetpredicate('remotebookmarks()')
+    args = _parseargs(x)
+    return _revsetutil(repo, subset, x, ('remotebranches',), args)
+
+@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
@@ -289,6 +289,7 @@  Testing the revsets provided by remotena
   ~
 
 Updating to revision using hoisted name
+---------------------------------------
 
 Deleting local bookmark to make sure we update to hoisted name only
 
@@ -393,3 +394,187 @@  After the push, default/foo should move 
      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
+  |
+  ~