D264: exchange: drop support for lock-based unbundling (BC)

indygreg (Gregory Szorc) phabricator at mercurial-scm.org
Tue Aug 8 03:24:13 UTC 2017


indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Locking over the wire protocol and the "addchangegroup" wire
  protocol command has been deprecated since https://phab.mercurial-scm.org/rHGe8c4f3d3df8c461d4868268c3faeda9639a9a902, which was
  first part of Mercurial 0.9.1.
  
  Support for handling these commands from sshserver was dropped in
  https://phab.mercurial-scm.org/rHG9f6e0e7ef82884e3ec66455dac7312820c2b35ce in 2015, effectively locking out pre 0.9.1 clients
  from new servers.
  
  However, client-side code for calling lock and addchangegroup is
  still present in exchange.py and the various peer classes to
  facilitate pushing to pre 0.9.1 servers.
  
  The lock-based pushing mechanism is extremely brittle. 0.9.1 was
  released in July 2006 and I highly doubt anyone is still running
  such an ancient version of Mercurial on a server. I'm about to
  refactor the peer API and I don't think it is worth keeping
  support for this ancient protocol feature. So, this commit removes
  client support for the lock-based pushing mechanism. This means
  modern clients will no longer be able to push to pre 0.9.1 servers.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D264

AFFECTED FILES
  mercurial/exchange.py
  mercurial/httppeer.py
  mercurial/localrepo.py
  mercurial/sshpeer.py

CHANGE DETAILS

diff --git a/mercurial/sshpeer.py b/mercurial/sshpeer.py
--- a/mercurial/sshpeer.py
+++ b/mercurial/sshpeer.py
@@ -17,21 +17,6 @@
     wireproto,
 )
 
-class remotelock(object):
-    def __init__(self, repo):
-        self.repo = repo
-    def release(self):
-        self.repo.unlock()
-        self.repo = None
-    def __enter__(self):
-        return self
-    def __exit__(self, exc_type, exc_val, exc_tb):
-        if self.repo:
-            self.release()
-    def __del__(self):
-        if self.repo:
-            self.release()
-
 def _serverquote(s):
     if not s:
         return s
@@ -337,33 +322,4 @@
             self.pipeo.flush()
         self.readerr()
 
-    def lock(self):
-        self._call("lock")
-        return remotelock(self)
-
-    def unlock(self):
-        self._call("unlock")
-
-    def addchangegroup(self, cg, source, url, lock=None):
-        '''Send a changegroup to the remote server.  Return an integer
-        similar to unbundle(). DEPRECATED, since it requires locking the
-        remote.'''
-        d = self._call("addchangegroup")
-        if d:
-            self._abort(error.RepoError(_("push refused: %s") % d))
-        for d in iter(lambda: cg.read(4096), ''):
-            self.pipeo.write(d)
-            self.readerr()
-
-        self.pipeo.flush()
-
-        self.readerr()
-        r = self._recv()
-        if not r:
-            return 1
-        try:
-            return int(r)
-        except ValueError:
-            self._abort(error.ResponseError(_("unexpected response:"), r))
-
 instance = sshpeer
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -237,9 +237,6 @@
         except error.PushRaced as exc:
             raise error.ResponseError(_('push failed:'), str(exc))
 
-    def lock(self):
-        return self._repo.lock()
-
     def pushkey(self, namespace, key, old, new):
         return self._repo.pushkey(namespace, key, old, new)
 
diff --git a/mercurial/httppeer.py b/mercurial/httppeer.py
--- a/mercurial/httppeer.py
+++ b/mercurial/httppeer.py
@@ -132,9 +132,6 @@
                           (' '.join(self.caps or ['none'])))
         return self.caps
 
-    def lock(self):
-        raise error.Abort(_('operation not supported over http'))
-
     def _callstream(self, cmd, _compressible=False, **args):
         if cmd == 'pushkey':
             args['data'] = ''
diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -433,16 +433,13 @@
                     " %s") % (', '.join(sorted(missing)))
             raise error.Abort(msg)
 
-    # there are two ways to push to remote repo:
-    #
-    # addchangegroup assumes local user can lock remote
-    # repo (local filesystem, old ssh servers).
-    #
-    # unbundle assumes local user cannot lock remote repo (new ssh
-    # servers, http servers).
-
     if not pushop.remote.canpush():
         raise error.Abort(_("destination does not support push"))
+
+    if not pushop.remote.capable('unbundle'):
+        raise error.Abort(_('cannot push: destination does not support the '
+                            'unbundle wire protocol command'))
+
     # get local lock as we might write phase data
     localwlock = locallock = None
     try:
@@ -468,21 +465,14 @@
                                                   'push-response',
                                                   pushop.remote.url())
         pushop.repo.checkpush(pushop)
-        lock = None
-        unbundle = pushop.remote.capable('unbundle')
-        if not unbundle:
-            lock = pushop.remote.lock()
-        try:
-            _pushdiscovery(pushop)
-            if not _forcebundle1(pushop):
-                _pushbundle2(pushop)
-            _pushchangeset(pushop)
-            _pushsyncphase(pushop)
-            _pushobsolete(pushop)
-            _pushbookmark(pushop)
-        finally:
-            if lock is not None:
-                lock.release()
+        _pushdiscovery(pushop)
+        if not _forcebundle1(pushop):
+            _pushbundle2(pushop)
+        _pushchangeset(pushop)
+        _pushsyncphase(pushop)
+        _pushobsolete(pushop)
+        _pushbookmark(pushop)
+
         if pushop.trmanager:
             pushop.trmanager.close()
     finally:
@@ -948,9 +938,12 @@
     pushop.stepsdone.add('changesets')
     if not _pushcheckoutgoing(pushop):
         return
+
+    # Should have verified this in push().
+    assert pushop.remote.capable('unbundle')
+
     pushop.repo.prepushoutgoinghooks(pushop)
     outgoing = pushop.outgoing
-    unbundle = pushop.remote.capable('unbundle')
     # TODO: get bundlecaps from remote
     bundlecaps = None
     # create a changegroup from local
@@ -969,24 +962,18 @@
                                         bundlecaps=bundlecaps)
 
     # apply changegroup to remote
-    if unbundle:
-        # local repo finds heads on server, finds out what
-        # revs it must push. once revs transferred, if server
-        # finds it has different heads (someone else won
-        # commit/push race), server aborts.
-        if pushop.force:
-            remoteheads = ['force']
-        else:
-            remoteheads = pushop.remoteheads
-        # ssh: return remote's addchangegroup()
-        # http: return remote's addchangegroup() or 0 for error
-        pushop.cgresult = pushop.remote.unbundle(cg, remoteheads,
-                                            pushop.repo.url())
+    # local repo finds heads on server, finds out what
+    # revs it must push. once revs transferred, if server
+    # finds it has different heads (someone else won
+    # commit/push race), server aborts.
+    if pushop.force:
+        remoteheads = ['force']
     else:
-        # we return an integer indicating remote head count
-        # change
-        pushop.cgresult = pushop.remote.addchangegroup(cg, 'push',
-                                                       pushop.repo.url())
+        remoteheads = pushop.remoteheads
+    # ssh: return remote's addchangegroup()
+    # http: return remote's addchangegroup() or 0 for error
+    pushop.cgresult = pushop.remote.unbundle(cg, remoteheads,
+                                        pushop.repo.url())
 
 def _pushsyncphase(pushop):
     """synchronise phase information locally and remotely"""



To: indygreg, #hg-reviewers
Cc: mercurial-devel


More information about the Mercurial-devel mailing list