diff --git a/hgext/narrow/narrowrepo.py b/hgext/narrow/narrowrepo.py --- a/hgext/narrow/narrowrepo.py +++ b/hgext/narrow/narrowrepo.py @@ -19,8 +19,8 @@ def wraprepo(repo): 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 diff --git a/mercurial/bundlerepo.py b/mercurial/bundlerepo.py --- a/mercurial/bundlerepo.py +++ b/mercurial/bundlerepo.py @@ -484,8 +484,8 @@ class bundlerepository: 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 diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -5405,6 +5405,12 @@ def postincoming(ui, repo, modheads, opt _(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 @@ def pull(ui, repo, *sources, **opts): 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 @@ def pull(ui, repo, *sources, **opts): 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 = {} diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -65,10 +65,10 @@ release = lock.release 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 @@ def repository( 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 @@ def peer(uiorrepo, opts, path, create=Fa create, intents=intents, createopts=createopts, + remotehidden=remotehidden, ) _setup_repo_or_peer(rui, peer) else: @@ -274,7 +283,7 @@ def peer(uiorrepo, opts, path, create=Fa intents=intents, createopts=createopts, ) - peer = repo.peer(path=peer_path) + peer = repo.peer(path=peer_path, remotehidden=remotehidden) return peer diff --git a/mercurial/httppeer.py b/mercurial/httppeer.py --- a/mercurial/httppeer.py +++ b/mercurial/httppeer.py @@ -381,8 +381,17 @@ def parsev1commandresponse(ui, baseurl, 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 @@ def performhandshake(ui, url, opener, re 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 @@ def _make_peer(ui, path, opener=None, re 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 @@ def make_peer(ui, path, create, intents= _(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: diff --git a/mercurial/interfaces/repository.py b/mercurial/interfaces/repository.py --- a/mercurial/interfaces/repository.py +++ b/mercurial/interfaces/repository.py @@ -388,7 +388,7 @@ class peer: limitedarguments = False - def __init__(self, ui, path=None): + def __init__(self, ui, path=None, remotehidden=False): self.ui = ui self.path = path diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -307,8 +307,18 @@ class localcommandexecutor: 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 @@ class locallegacypeer(localpeer): """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 @@ class localrepository: 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 diff --git a/mercurial/sshpeer.py b/mercurial/sshpeer.py --- a/mercurial/sshpeer.py +++ b/mercurial/sshpeer.py @@ -372,7 +372,16 @@ def _performhandshake(ui, stdin, stdout, 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 @@ class sshv1peer(wireprotov1peer.wirepeer ``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 @@ class sshv1peer(wireprotov1peer.wirepeer 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 @@ def _make_peer(ui, path, proc, stdin, st stderr, caps, autoreadstderr=autoreadstderr, + remotehidden=remotehidden, ) else: _cleanuppipes(ui, stdout, stdin, stderr, warn=None) @@ -606,7 +632,9 @@ def _make_peer(ui, path, proc, stdin, st ) -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 @@ def make_peer(ui, path, create, intents= 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. diff --git a/mercurial/statichttprepo.py b/mercurial/statichttprepo.py --- a/mercurial/statichttprepo.py +++ b/mercurial/statichttprepo.py @@ -237,8 +237,8 @@ class statichttprepository( 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 @@ class statichttprepository( 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 + ) diff --git a/mercurial/unionrepo.py b/mercurial/unionrepo.py --- a/mercurial/unionrepo.py +++ b/mercurial/unionrepo.py @@ -270,8 +270,8 @@ class unionrepository: 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 diff --git a/tests/notcapable b/tests/notcapable --- a/tests/notcapable +++ b/tests/notcapable @@ -15,10 +15,10 @@ def wrapcapable(orig, self, name, *args, 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 diff --git a/tests/test-completion.t b/tests/test-completion.t --- a/tests/test-completion.t +++ b/tests/test-completion.t @@ -366,7 +366,7 @@ Show all commands + options 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