pull: add --remote-hidden option and pass it through peer creation
authorManuel Jacob <me@manueljacob.de>
Thu, 04 Apr 2019 18:07:30 +0200
changeset 50440 3a2df812e1c7
parent 50439 4077d6222cf1
child 50441 b15b6e2c3309
pull: add --remote-hidden option and pass it through peer creation This option will allow to pull changesets that are hidden on the remote. This is useful when looking into a changeset’s evolution history, resolving evolution instability or mirroring a repository. The option is best effort and will only affect the pull when it can. The option will be ignored when it cannot be honored. Support for each type of peer is yet to be implemented. They currently all warn about lack of support. The warning code will get removed as peers gain support for this option. The option is still experimental, so we will have freedom to update the UI or implementation before it graduates out of experimental. Based on a changeset by Pierre-Yves David, which added the option.
hgext/narrow/narrowrepo.py
mercurial/bundlerepo.py
mercurial/commands.py
mercurial/hg.py
mercurial/httppeer.py
mercurial/interfaces/repository.py
mercurial/localrepo.py
mercurial/sshpeer.py
mercurial/statichttprepo.py
mercurial/unionrepo.py
tests/notcapable
tests/test-completion.t
--- a/hgext/narrow/narrowrepo.py	Sat Apr 13 01:17:56 2019 +0200
+++ b/hgext/narrow/narrowrepo.py	Thu Apr 04 18:07:30 2019 +0200
@@ -19,8 +19,8 @@
             dirstate = super(narrowrepository, self)._makedirstate()
             return narrowdirstate.wrapdirstate(self, dirstate)
 
-        def peer(self, path=None):
-            peer = super(narrowrepository, self).peer(path=path)
+        def peer(self, *args, **kwds):
+            peer = super(narrowrepository, self).peer(*args, **kwds)
             peer._caps.add(wireprototypes.NARROWCAP)
             peer._caps.add(wireprototypes.ELLIPSESCAP)
             return peer
--- a/mercurial/bundlerepo.py	Sat Apr 13 01:17:56 2019 +0200
+++ b/mercurial/bundlerepo.py	Thu Apr 04 18:07:30 2019 +0200
@@ -484,8 +484,8 @@
     def cancopy(self):
         return False
 
-    def peer(self, path=None):
-        return bundlepeer(self, path=path)
+    def peer(self, path=None, remotehidden=False):
+        return bundlepeer(self, path=path, remotehidden=remotehidden)
 
     def getcwd(self):
         return encoding.getcwd()  # always outside the repo
--- a/mercurial/commands.py	Sat Apr 13 01:17:56 2019 +0200
+++ b/mercurial/commands.py	Thu Apr 04 18:07:30 2019 +0200
@@ -5405,6 +5405,12 @@
             _(b'a specific branch you would like to pull'),
             _(b'BRANCH'),
         ),
+        (
+            b'',
+            b'remote-hidden',
+            False,
+            _(b"include changesets hidden on the remote (EXPERIMENTAL)"),
+        ),
     ]
     + remoteopts,
     _(b'[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]...'),
@@ -5442,6 +5448,14 @@
     Specifying bookmark as ``.`` is equivalent to specifying the active
     bookmark's name.
 
+    .. container:: verbose
+
+        One can use the `--remote-hidden` flag to pull changesets
+        hidden on the remote. This flag is "best effort", and will only
+        work if the server supports the feature and is configured to
+        allow the user to access hidden changesets. This option is
+        experimental and backwards compatibility is not garanteed.
+
     Returns 0 on success, 1 if an update had unresolved files.
     """
 
@@ -5456,12 +5470,16 @@
     for path in urlutil.get_pull_paths(repo, ui, sources):
         ui.status(_(b'pulling from %s\n') % urlutil.hidepassword(path.loc))
         ui.flush()
-        other = hg.peer(repo, opts, path)
+        other = hg.peer(repo, opts, path, remotehidden=opts[b'remote_hidden'])
         update_conflict = None
         try:
             branches = (path.branch, opts.get(b'branch', []))
             revs, checkout = hg.addbranchrevs(
-                repo, other, branches, opts.get(b'rev')
+                repo,
+                other,
+                branches,
+                opts.get(b'rev'),
+                remotehidden=opts[b'remote_hidden'],
             )
 
             pullopargs = {}
--- a/mercurial/hg.py	Sat Apr 13 01:17:56 2019 +0200
+++ b/mercurial/hg.py	Thu Apr 04 18:07:30 2019 +0200
@@ -65,10 +65,10 @@
 sharedbookmarks = b'bookmarks'
 
 
-def addbranchrevs(lrepo, other, branches, revs):
+def addbranchrevs(lrepo, other, branches, revs, remotehidden=False):
     if util.safehasattr(other, 'peer'):
         # a courtesy to callers using a localrepo for other
-        peer = other.peer()
+        peer = other.peer(remotehidden=remotehidden)
     else:
         peer = other
     hashbranch, branches = branches
@@ -242,7 +242,15 @@
     return repo.filtered(b'visible')
 
 
-def peer(uiorrepo, opts, path, create=False, intents=None, createopts=None):
+def peer(
+    uiorrepo,
+    opts,
+    path,
+    create=False,
+    intents=None,
+    createopts=None,
+    remotehidden=False,
+):
     '''return a repository peer for the specified path'''
     ui = getattr(uiorrepo, 'ui', uiorrepo)
     rui = remoteui(uiorrepo, opts)
@@ -260,6 +268,7 @@
             create,
             intents=intents,
             createopts=createopts,
+            remotehidden=remotehidden,
         )
         _setup_repo_or_peer(rui, peer)
     else:
@@ -274,7 +283,7 @@
             intents=intents,
             createopts=createopts,
         )
-        peer = repo.peer(path=peer_path)
+        peer = repo.peer(path=peer_path, remotehidden=remotehidden)
     return peer
 
 
--- a/mercurial/httppeer.py	Sat Apr 13 01:17:56 2019 +0200
+++ b/mercurial/httppeer.py	Thu Apr 04 18:07:30 2019 +0200
@@ -381,8 +381,17 @@
 
 
 class httppeer(wireprotov1peer.wirepeer):
-    def __init__(self, ui, path, url, opener, requestbuilder, caps):
-        super().__init__(ui, path=path)
+    def __init__(
+        self, ui, path, url, opener, requestbuilder, caps, remotehidden=False
+    ):
+        super().__init__(ui, path=path, remotehidden=remotehidden)
+        if remotehidden:
+            msg = _(
+                b"ignoring `--remote-hidden` request\n"
+                b"(access to hidden changeset for http peers not "
+                b"supported yet)\n"
+            )
+            ui.warn(msg)
         self._url = url
         self._caps = caps
         self.limitedarguments = caps is not None and b'httppostargs' not in caps
@@ -592,7 +601,9 @@
     return respurl, info
 
 
-def _make_peer(ui, path, opener=None, requestbuilder=urlreq.request):
+def _make_peer(
+    ui, path, opener=None, requestbuilder=urlreq.request, remotehidden=False
+):
     """Construct an appropriate HTTP peer instance.
 
     ``opener`` is an ``url.opener`` that should be used to establish
@@ -615,11 +626,19 @@
     respurl, info = performhandshake(ui, url, opener, requestbuilder)
 
     return httppeer(
-        ui, path, respurl, opener, requestbuilder, info[b'v1capabilities']
+        ui,
+        path,
+        respurl,
+        opener,
+        requestbuilder,
+        info[b'v1capabilities'],
+        remotehidden=remotehidden,
     )
 
 
-def make_peer(ui, path, create, intents=None, createopts=None):
+def make_peer(
+    ui, path, create, intents=None, createopts=None, remotehidden=False
+):
     if create:
         raise error.Abort(_(b'cannot create new http repository'))
     try:
@@ -628,7 +647,7 @@
                 _(b'Python support for SSL and HTTPS is not installed')
             )
 
-        inst = _make_peer(ui, path)
+        inst = _make_peer(ui, path, remotehidden=remotehidden)
 
         return inst
     except error.RepoError as httpexception:
--- a/mercurial/interfaces/repository.py	Sat Apr 13 01:17:56 2019 +0200
+++ b/mercurial/interfaces/repository.py	Thu Apr 04 18:07:30 2019 +0200
@@ -388,7 +388,7 @@
 
     limitedarguments = False
 
-    def __init__(self, ui, path=None):
+    def __init__(self, ui, path=None, remotehidden=False):
         self.ui = ui
         self.path = path
 
--- a/mercurial/localrepo.py	Sat Apr 13 01:17:56 2019 +0200
+++ b/mercurial/localrepo.py	Thu Apr 04 18:07:30 2019 +0200
@@ -307,8 +307,18 @@
 class localpeer(repository.peer):
     '''peer for a local repo; reflects only the most recent API'''
 
-    def __init__(self, repo, caps=None, path=None):
-        super(localpeer, self).__init__(repo.ui, path=path)
+    def __init__(self, repo, caps=None, path=None, remotehidden=False):
+        super(localpeer, self).__init__(
+            repo.ui, path=path, remotehidden=remotehidden
+        )
+
+        if remotehidden:
+            msg = _(
+                b"ignoring `--remote-hidden` request\n"
+                b"(access to hidden changeset for %r not "
+                b"supported yet)\n"
+            ) % type(self)
+            self.ui.warn(msg)
 
         if caps is None:
             caps = moderncaps.copy()
@@ -455,8 +465,10 @@
     """peer extension which implements legacy methods too; used for tests with
     restricted capabilities"""
 
-    def __init__(self, repo, path=None):
-        super(locallegacypeer, self).__init__(repo, caps=legacycaps, path=path)
+    def __init__(self, repo, path=None, remotehidden=False):
+        super(locallegacypeer, self).__init__(
+            repo, caps=legacycaps, path=path, remotehidden=remotehidden
+        )
 
     # Begin of baselegacywirecommands interface.
 
@@ -1657,8 +1669,10 @@
                 parts.pop()
         return False
 
-    def peer(self, path=None):
-        return localpeer(self, path=path)  # not cached to avoid reference cycle
+    def peer(self, path=None, remotehidden=False):
+        return localpeer(
+            self, path=path, remotehidden=remotehidden
+        )  # not cached to avoid reference cycle
 
     def unfiltered(self):
         """Return unfiltered version of the repository
--- a/mercurial/sshpeer.py	Sat Apr 13 01:17:56 2019 +0200
+++ b/mercurial/sshpeer.py	Thu Apr 04 18:07:30 2019 +0200
@@ -372,7 +372,16 @@
 
 class sshv1peer(wireprotov1peer.wirepeer):
     def __init__(
-        self, ui, path, proc, stdin, stdout, stderr, caps, autoreadstderr=True
+        self,
+        ui,
+        path,
+        proc,
+        stdin,
+        stdout,
+        stderr,
+        caps,
+        autoreadstderr=True,
+        remotehidden=False,
     ):
         """Create a peer from an existing SSH connection.
 
@@ -383,7 +392,14 @@
         ``autoreadstderr`` denotes whether to automatically read from
         stderr and to forward its output.
         """
-        super().__init__(ui, path=path)
+        super().__init__(ui, path=path, remotehidden=remotehidden)
+        if remotehidden:
+            msg = _(
+                b"ignoring `--remote-hidden` request\n"
+                b"(access to hidden changeset for ssh peers not supported "
+                b"yet)\n"
+            )
+            ui.warn(msg)
         # self._subprocess is unused. Keeping a handle on the process
         # holds a reference and prevents it from being garbage collected.
         self._subprocess = proc
@@ -568,7 +584,16 @@
             self._readerr()
 
 
-def _make_peer(ui, path, proc, stdin, stdout, stderr, autoreadstderr=True):
+def _make_peer(
+    ui,
+    path,
+    proc,
+    stdin,
+    stdout,
+    stderr,
+    autoreadstderr=True,
+    remotehidden=False,
+):
     """Make a peer instance from existing pipes.
 
     ``path`` and ``proc`` are stored on the eventual peer instance and may
@@ -598,6 +623,7 @@
             stderr,
             caps,
             autoreadstderr=autoreadstderr,
+            remotehidden=remotehidden,
         )
     else:
         _cleanuppipes(ui, stdout, stdin, stderr, warn=None)
@@ -606,7 +632,9 @@
         )
 
 
-def make_peer(ui, path, create, intents=None, createopts=None):
+def make_peer(
+    ui, path, create, intents=None, createopts=None, remotehidden=False
+):
     """Create an SSH peer.
 
     The returned object conforms to the ``wireprotov1peer.wirepeer`` interface.
@@ -658,7 +686,9 @@
         ui, sshcmd, args, remotecmd, remotepath, sshenv
     )
 
-    peer = _make_peer(ui, path, proc, stdin, stdout, stderr)
+    peer = _make_peer(
+        ui, path, proc, stdin, stdout, stderr, remotehidden=remotehidden
+    )
 
     # Finally, if supported by the server, notify it about our own
     # capabilities.
--- a/mercurial/statichttprepo.py	Sat Apr 13 01:17:56 2019 +0200
+++ b/mercurial/statichttprepo.py	Thu Apr 04 18:07:30 2019 +0200
@@ -237,8 +237,8 @@
     def local(self):
         return False
 
-    def peer(self, path=None):
-        return statichttppeer(self, path=path)
+    def peer(self, path=None, remotehidden=False):
+        return statichttppeer(self, path=path, remotehidden=remotehidden)
 
     def wlock(self, wait=True):
         raise error.LockUnavailable(
@@ -260,8 +260,12 @@
         pass  # statichttprepository are read only
 
 
-def make_peer(ui, path, create, intents=None, createopts=None):
+def make_peer(
+    ui, path, create, intents=None, createopts=None, remotehidden=False
+):
     if create:
         raise error.Abort(_(b'cannot create new static-http repository'))
     url = path.loc[7:]
-    return statichttprepository(ui, url).peer(path=path)
+    return statichttprepository(ui, url).peer(
+        path=path, remotehidden=remotehidden
+    )
--- a/mercurial/unionrepo.py	Sat Apr 13 01:17:56 2019 +0200
+++ b/mercurial/unionrepo.py	Thu Apr 04 18:07:30 2019 +0200
@@ -270,8 +270,8 @@
     def cancopy(self):
         return False
 
-    def peer(self, path=None):
-        return unionpeer(self, path=None)
+    def peer(self, path=None, remotehidden=False):
+        return unionpeer(self, path=None, remotehidden=remotehidden)
 
     def getcwd(self):
         return encoding.getcwd()  # always outside the repo
--- a/tests/notcapable	Sat Apr 13 01:17:56 2019 +0200
+++ b/tests/notcapable	Thu Apr 04 18:07:30 2019 +0200
@@ -15,10 +15,10 @@
     if name in b'$CAP'.split(b' '):
         return False
     return orig(self, name, *args, **kwargs)
-def wrappeer(orig, self, path=None):
+def wrappeer(orig, self, *args, **kwargs):
     # Since we're disabling some newer features, we need to make sure local
     # repos add in the legacy features again.
-    return localrepo.locallegacypeer(self, path=path)
+    return localrepo.locallegacypeer(self, *args, **kwargs)
 EOF
 
 echo '[extensions]' >> $HGRCPATH
--- a/tests/test-completion.t	Sat Apr 13 01:17:56 2019 +0200
+++ b/tests/test-completion.t	Thu Apr 04 18:07:30 2019 +0200
@@ -366,7 +366,7 @@
   parents: rev, style, template
   paths: template
   phase: public, draft, secret, force, rev
-  pull: update, force, confirm, rev, bookmark, branch, ssh, remotecmd, insecure
+  pull: update, force, confirm, rev, bookmark, branch, remote-hidden, ssh, remotecmd, insecure
   purge: abort-on-err, all, ignored, dirs, files, print, print0, confirm, include, exclude
   push: force, rev, bookmark, all-bookmarks, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
   recover: verify