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

login
register
mail settings
Submitter Pierre-Yves David
Date April 17, 2013, 3:58 p.m.
Message ID <4f01e4913967eb0961f0.1366214317@crater1.logilab.fr>
Download mbox | patch
Permalink /patch/1387/
State Deferred, archived
Headers show

Comments

Pierre-Yves David - April 17, 2013, 3:58 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@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.

Patch

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.