[PATCH 02 of 16] exchangeutil: extract pull function from localrepo

pierre-yves.david at logilab.fr pierre-yves.david at logilab.fr
Wed Apr 17 10:58:37 CDT 2013


# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at logilab.fr>
# Date 1366194524 -7200
#      Wed Apr 17 12:28:44 2013 +0200
# Node ID 4f01e4913967eb0961f07f7d77e026dbac5a439c
# Parent  8c78d95ab62f3edc06871132a1011109d3b2c3ce
exchangeutil: extract pull function from localrepo

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

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.

diff --git a/mercurial/exchangeutil.py b/mercurial/exchangeutil.py
--- a/mercurial/exchangeutil.py
+++ b/mercurial/exchangeutil.py
@@ -4,12 +4,12 @@
 #
 # 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
-import util, scmutil
+from node import hex, nullid
+import util, scmutil, base85
 import discovery, phases, obsolete, bookmarks
 
 
 def push(repo, remote, force=False, revs=None, newbranch=False):
     '''Push outgoing changesets (limited by revs) from the current
@@ -210,5 +210,91 @@ def push(repo, remote, force=False, revs
                     else:
                         repo.ui.warn(_('updating bookmark %s'
                                        ' failed!\n') % k)
 
     return ret
+
+def pull(repo, remote, heads=None, force=False):
+    # 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, remote, heads=heads,
+                                           force=force)
+        common, fetch, rheads = tmp
+        if not fetch:
+            repo.ui.status(_("no changes found\n"))
+            added = []
+            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'):
+                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')
+            # we use unfiltered changelog here because hidden revision must
+            # be taken in account for phase synchronization. They may
+            # becomes public and becomes visible again.
+            cl = repo.unfiltered().changelog
+            clstart = len(cl)
+            result = repo.addchangegroup(cg, 'pull', remote.url())
+            clend = len(cl)
+            added = [cl.node(r) for r in xrange(clstart, clend)]
+
+        # compute target subset
+        if heads is None:
+            # We pulled every thing possible
+            # sync on everything common
+            subset = common + added
+        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)
+
+        if obsolete._enabled:
+            repo.ui.debug('fetching remote obsolete markers\n')
+            remoteobs = remote.listkeys('obsolete')
+            if 'dump0' in remoteobs:
+                if tr is None:
+                    tr = repo.transaction(trname)
+                for key in sorted(remoteobs, reverse=True):
+                    if key.startswith('dump'):
+                        data = base85.b85decode(remoteobs[key])
+                        repo.obsstore.mergemarkers(tr, data)
+                repo.invalidatevolatilesets()
+        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
@@ -6,11 +6,11 @@
 # GNU General Public License version 2 or any later version.
 from node import hex, nullid, short
 from i18n import _
 import peer, changegroup, subrepo, discovery, pushkey, obsolete, repoview
 import changelog, dirstate, filelog, manifest, context, bookmarks, phases
-import lock, transaction, store, encoding, base85, exchangeutil
+import lock, transaction, store, encoding, exchangeutil
 import scmutil, util, extensions, hook, error, revset
 import match as matchmod
 import merge as mergemod
 import tags as tagsmod
 from lock import release
@@ -1650,94 +1650,11 @@ class localrepository(object):
             r.append(l)
 
         return r
 
     def pull(self, remote, heads=None, force=False):
-        # 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, remote, heads=heads,
-                                               force=force)
-            common, fetch, rheads = tmp
-            if not fetch:
-                self.ui.status(_("no changes found\n"))
-                added = []
-                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'):
-                    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')
-                # we use unfiltered changelog here because hidden revision must
-                # be taken in account for phase synchronization. They may
-                # becomes public and becomes visible again.
-                cl = self.unfiltered().changelog
-                clstart = len(cl)
-                result = self.addchangegroup(cg, 'pull', remote.url())
-                clend = len(cl)
-                added = [cl.node(r) for r in xrange(clstart, clend)]
-
-            # compute target subset
-            if heads is None:
-                # We pulled every thing possible
-                # sync on everything common
-                subset = common + added
-            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)
-
-            if obsolete._enabled:
-                self.ui.debug('fetching remote obsolete markers\n')
-                remoteobs = remote.listkeys('obsolete')
-                if 'dump0' in remoteobs:
-                    if tr is None:
-                        tr = self.transaction(trname)
-                    for key in sorted(remoteobs, reverse=True):
-                        if key.startswith('dump'):
-                            data = base85.b85decode(remoteobs[key])
-                            self.obsstore.mergemarkers(tr, data)
-                    self.invalidatevolatilesets()
-            if tr is not None:
-                tr.close()
-        finally:
-            if tr is not None:
-                tr.release()
-            lock.release()
-
-        return result
+        return exchangeutil.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.


More information about the Mercurial-devel mailing list