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.
--- 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