Patchwork [07,of,16] exchangeutil: turn pull into an object

login
register
mail settings
Submitter Pierre-Yves David
Date April 17, 2013, 3:58 p.m.
Message ID <e98361603d55211f03b4.1366214322@crater1.logilab.fr>
Download mbox | patch
Permalink /patch/1396/
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 1366206025 -7200
#      Wed Apr 17 15:40:25 2013 +0200
# Node ID e98361603d55211f03b4a2a6aa8af2f92d9661b5
# Parent  ebab1a6407d1d19dd84a4ad7721c5dbfcad31b68
exchangeutil: turn pull into an object

This move toward a small state-full, one-shot object where each step are isolated.
Smaller function are easier to maintains and wrap.

Patch

diff --git a/mercurial/exchangeutil.py b/mercurial/exchangeutil.py
--- a/mercurial/exchangeutil.py
+++ b/mercurial/exchangeutil.py
@@ -234,90 +234,92 @@  class pushoperation(object):
                         else:
                             repo.ui.warn(_('updating bookmark %s'
                                            ' failed!\n') % k)
 
 
-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
+class pulloperation(object):
 
-            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."))
+    def perform(self, 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:
-                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)]
+                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
 
-        # 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
+                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)]
 
-        # 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)
+            # 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
 
-        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()
+            # 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)
 
-    return result
+            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
@@ -1650,11 +1650,12 @@  class localrepository(object):
             r.append(l)
 
         return r
 
     def pull(self, remote, heads=None, force=False):
-        return exchangeutil.pull (self, remote, heads, force)
+        pull = exchangeutil.pulloperation()
+        return pull.perform(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.