Patchwork [01,of,13] exchange: extract pull function from localrepo

login
register
mail settings
Submitter Pierre-Yves David
Date Feb. 12, 2014, 1:34 a.m.
Message ID <164d38007b414b136c75.1392168855@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/3600/
State Accepted
Commit 6b4c789d618d5a9682730461ba07f370502ced09
Headers show

Comments

Pierre-Yves David - Feb. 12, 2014, 1:34 a.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@logilab.fr>
# Date 1391127169 28800
#      Thu Jan 30 16:12:49 2014 -0800
# Node ID 164d38007b414b136c75e20595dc2163ca7c8a53
# Parent  a2c08adbb86ed8e65897ce35ec97ee947f26d2dd
exchange: extract pull function from localrepo

The localrepo class if far too big. Push and pull logic are extracted and
reworked to better fit with the fact we exchange more than bundle now.

This changeset extract the pulh code. later changeset will slowly slice it into
smaller brick.

The localrepo.pull method is kept for now to limit impact on user code. But it
will be ultimately removed, now that the public API is hold by peer.

Patch

diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -4,11 +4,11 @@ 
 #
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
 from i18n import _
-from node import hex
+from node import hex, nullid
 import errno
 import util, scmutil, changegroup
 import discovery, phases, obsolete, bookmarks
 
 
@@ -311,5 +311,91 @@  def _pushbookmark(pushop):
             continue
         if remote.pushkey('bookmarks', b, dcid, scid):
             ui.status(_("updating bookmark %s\n") % b)
         else:
             ui.warn(_('updating bookmark %s failed!\n') % b)
+
+
+def pull(repo, remote, heads=None, force=False):
+    if remote.local():
+        missing = set(remote.requirements) - repo.supported
+        if missing:
+            msg = _("required features are not"
+                    " supported in the destination:"
+                    " %s") % (', '.join(sorted(missing)))
+            raise util.Abort(msg)
+
+    # don't open transaction for nothing or you break future useful
+    # rollback call
+    tr = None
+    trname = 'pull\n' + util.hidepassword(remote.url())
+    lock = repo.lock()
+    try:
+        tmp = discovery.findcommonincoming(repo.unfiltered(), remote,
+                                           heads=heads, force=force)
+        common, fetch, rheads = tmp
+        if not fetch:
+            repo.ui.status(_("no changes found\n"))
+            result = 0
+        else:
+            tr = repo.transaction(trname)
+            if heads is None and list(common) == [nullid]:
+                repo.ui.status(_("requesting all changes\n"))
+            elif heads is None and remote.capable('changegroupsubset'):
+                # issue1320, avoid a race if remote changed after discovery
+                heads = rheads
+
+            if remote.capable('getbundle'):
+                # TODO: get bundlecaps from remote
+                cg = remote.getbundle('pull', common=common,
+                                      heads=heads or rheads)
+            elif heads is None:
+                cg = remote.changegroup(fetch, 'pull')
+            elif not remote.capable('changegroupsubset'):
+                raise util.Abort(_("partial pull cannot be done because "
+                                       "other repository doesn't support "
+                                       "changegroupsubset."))
+            else:
+                cg = remote.changegroupsubset(fetch, heads, 'pull')
+            result = repo.addchangegroup(cg, 'pull', remote.url())
+
+        # compute target subset
+        if heads is None:
+            # We pulled every thing possible
+            # sync on everything common
+            subset = common + rheads
+        else:
+            # We pulled a specific subset
+            # sync on this subset
+            subset = heads
+
+        # Get remote phases data from remote
+        remotephases = remote.listkeys('phases')
+        publishing = bool(remotephases.get('publishing', False))
+        if remotephases and not publishing:
+            # remote is new and unpublishing
+            pheads, _dr = phases.analyzeremotephases(repo, subset,
+                                                     remotephases)
+            phases.advanceboundary(repo, phases.public, pheads)
+            phases.advanceboundary(repo, phases.draft, subset)
+        else:
+            # Remote is old or publishing all common changesets
+            # should be seen as public
+            phases.advanceboundary(repo, phases.public, subset)
+
+        def gettransaction():
+            if tr is None:
+                return repo.transaction(trname)
+            return tr
+
+        obstr = obsolete.syncpull(repo, remote, gettransaction)
+        if obstr is not None:
+            tr = obstr
+
+        if tr is not None:
+            tr.close()
+    finally:
+        if tr is not None:
+            tr.release()
+        lock.release()
+
+    return result
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -1657,93 +1657,11 @@  class localrepository(object):
             r.append(l)
 
         return r
 
     def pull(self, remote, heads=None, force=False):
-        if remote.local():
-            missing = set(remote.requirements) - self.supported
-            if missing:
-                msg = _("required features are not"
-                        " supported in the destination:"
-                        " %s") % (', '.join(sorted(missing)))
-                raise util.Abort(msg)
-
-        # don't open transaction for nothing or you break future useful
-        # rollback call
-        tr = None
-        trname = 'pull\n' + util.hidepassword(remote.url())
-        lock = self.lock()
-        try:
-            tmp = discovery.findcommonincoming(self.unfiltered(), remote,
-                                               heads=heads, force=force)
-            common, fetch, rheads = tmp
-            if not fetch:
-                self.ui.status(_("no changes found\n"))
-                result = 0
-            else:
-                tr = self.transaction(trname)
-                if heads is None and list(common) == [nullid]:
-                    self.ui.status(_("requesting all changes\n"))
-                elif heads is None and remote.capable('changegroupsubset'):
-                    # issue1320, avoid a race if remote changed after discovery
-                    heads = rheads
-
-                if remote.capable('getbundle'):
-                    # TODO: get bundlecaps from remote
-                    cg = remote.getbundle('pull', common=common,
-                                          heads=heads or rheads)
-                elif heads is None:
-                    cg = remote.changegroup(fetch, 'pull')
-                elif not remote.capable('changegroupsubset'):
-                    raise util.Abort(_("partial pull cannot be done because "
-                                           "other repository doesn't support "
-                                           "changegroupsubset."))
-                else:
-                    cg = remote.changegroupsubset(fetch, heads, 'pull')
-                result = self.addchangegroup(cg, 'pull', remote.url())
-
-            # compute target subset
-            if heads is None:
-                # We pulled every thing possible
-                # sync on everything common
-                subset = common + rheads
-            else:
-                # We pulled a specific subset
-                # sync on this subset
-                subset = heads
-
-            # Get remote phases data from remote
-            remotephases = remote.listkeys('phases')
-            publishing = bool(remotephases.get('publishing', False))
-            if remotephases and not publishing:
-                # remote is new and unpublishing
-                pheads, _dr = phases.analyzeremotephases(self, subset,
-                                                         remotephases)
-                phases.advanceboundary(self, phases.public, pheads)
-                phases.advanceboundary(self, phases.draft, subset)
-            else:
-                # Remote is old or publishing all common changesets
-                # should be seen as public
-                phases.advanceboundary(self, phases.public, subset)
-
-            def gettransaction():
-                if tr is None:
-                    return self.transaction(trname)
-                return tr
-
-            obstr = obsolete.syncpull(self, remote, gettransaction)
-            if obstr is not None:
-                tr = obstr
-
-            if tr is not None:
-                tr.close()
-        finally:
-            if tr is not None:
-                tr.release()
-            lock.release()
-
-        return result
+        return exchange.pull (self, remote, heads, force)
 
     def checkpush(self, force, revs):
         """Extensions can override this function if additional checks have
         to be performed before pushing, or call it if they override push
         command.