[PATCH 11 of 16] push: extract outgoing computation and validation in its own method

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


# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at logilab.fr>
# Date 1366213905 -7200
#      Wed Apr 17 17:51:45 2013 +0200
# Node ID 74fe7f2c9abe580306ed39c0968fa87188a9bbaa
# Parent  bdd829b196108ee5099021f0a4c7b56c7a3af078
push: extract outgoing computation and validation in its own method

Another step toward god function diet.

diff --git a/mercurial/exchangeutil.py b/mercurial/exchangeutil.py
--- a/mercurial/exchangeutil.py
+++ b/mercurial/exchangeutil.py
@@ -21,10 +21,13 @@ class pushoperation(object):
         self.remote = remote
         self.force = force
         self.revs = revs
         self.newbranch = newbranch
 
+        self._outgoing = None    # discovery.outgoing object
+        self._remoteheads = None # know remote head before the push
+
     def perform(self):
         '''Push outgoing changesets (limited by revs) from the current
         repository to remote. Return an integer:
           - None means nothing to push
           - 0 means HTTP error
@@ -50,81 +53,50 @@ class pushoperation(object):
             lock = None
             unbundle = remote.capable('unbundle')
             if not unbundle:
                 lock = remote.lock()
             try:
-                # discovery
-                fci = discovery.findcommonincoming
-                commoninc = fci(unfi, remote, force=self.force)
-                common, inc, remoteheads = commoninc
-                fco = discovery.findcommonoutgoing
-                outgoing = fco(unfi, remote, onlyheads=self.revs,
-                               commoninc=commoninc, force=self.force)
+                self._outgoing, self._remoteheads = self._processoutgoing()
 
-                if not outgoing.missing:
+                if not self._outgoing.missing:
                     # nothing to push
-                    scmutil.nochangesfound(unfi.ui, unfi, outgoing.excluded)
+                    scmutil.nochangesfound(unfi.ui, unfi,
+                                           self._outgoing.excluded)
                     ret = None
                 else:
-                    # something to push
-                    if not self.force:
-                        # if self.obsstore == False --> no obsolete
-                        # then, save the iteration
-                        if unfi.obsstore:
-                            # this message are here for 80 char limit reason
-                            mso = _("push includes obsolete changeset: %s!")
-                            mst = "push includes %s changeset: %s!"
-                            # plain versions for i18n tool to detect them
-                            _("push includes unstable changeset: %s!")
-                            _("push includes bumped changeset: %s!")
-                            _("push includes divergent changeset: %s!")
-                            # If we are to push if there is at least one
-                            # obsolete or unstable changeset in missing, at
-                            # least one of the missinghead will be obsolete or
-                            # unstable. So checking heads only is ok
-                            for node in outgoing.missingheads:
-                                ctx = unfi[node]
-                                if ctx.obsolete():
-                                    raise util.Abort(mso % ctx)
-                                elif ctx.troubled():
-                                    raise util.Abort(_(mst)
-                                                     % (ctx.troubles()[0],
-                                                        ctx))
-                        discovery.checkheads(unfi, remote, outgoing,
-                                             remoteheads, self.newbranch,
-                                             bool(inc))
-
                     # create a changegroup from local
-                    if self.revs is None and not outgoing.excluded:
+                    if self.revs is None and not self._outgoing.excluded:
                         # push everything,
                         # use the fast path, no race possible on push
-                        cg = repo._changegroup(outgoing.missing, 'push')
+                        cg = repo._changegroup(self._outgoing.missing, 'push')
                     else:
-                        cg = repo.getlocalbundle('push', outgoing)
+                        cg = repo.getlocalbundle('push', self._outgoing)
 
                     # 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 self.force:
                             remoteheads = ['force']
+                        else:
+                            remoteheads = self._remoteheads
                         # ssh: return remote's addchangegroup()
                         # http: return remote's addchangegroup() or 0 for error
                         ret = remote.unbundle(cg, remoteheads, 'push')
                     else:
                         # we return an integer indicating remote head count
                         # change
                         ret = remote.addchangegroup(cg, 'push', repo.url())
 
                 if ret:
                     # push succeed, synchronize target of the push
-                    cheads = outgoing.missingheads
+                    cheads = self._outgoing.missingheads
                 elif self.revs is None:
                     # All out push fails. synchronize all common
-                    cheads = outgoing.commonheads
+                    cheads = self._outgoing.commonheads
                 else:
                     # I want cheads = heads(::missingheads and ::commonheads)
                     # (missingheads is revs with secret changeset filtered out)
                     #
                     # This can be expressed as:
@@ -136,17 +108,17 @@ class pushoperation(object):
                     #     common = (::commonheads)
                     #     missing = ((commonheads::missingheads) - commonheads)
                     #
                     # We can pick:
                     # * missingheads part of common (::commonheads)
-                    common = set(outgoing.common)
+                    common = set(self._outgoing.common)
                     cheads = [node for node in self.revs if node in common]
                     # and
                     # * commonheads parents on missing
                     revset = unfi.set('%ln and parents(roots(%ln))',
-                                     outgoing.commonheads,
-                                     outgoing.missing)
+                                     self._outgoing.commonheads,
+                                     self._outgoing.missing)
                     cheads.extend(c.node() for c in revset)
                 # even when we don't push, exchanging phase data is useful
                 remotephases = remote.listkeys('phases')
                 if (repo.ui.configbool('ui', '_usedassubrepo', False)
                     and remotephases    # server supports phases
@@ -196,10 +168,51 @@ class pushoperation(object):
         finally:
             locallock.release()
         self._pushbookmarks()
         return ret
 
+    def _processoutgoing(self):
+        """call discovery to find outgoing changeset and validate it content
+        """
+        unfi = self.repo.unfiltered()
+        fci = discovery.findcommonincoming
+        commoninc = fci(unfi, self.remote, force=self.force)
+        common, inc, remoteheads = commoninc
+        fco = discovery.findcommonoutgoing
+        outgoing = fco(unfi, self.remote, onlyheads=self.revs,
+                       commoninc=commoninc, force=self.force)
+        if (not self.force) and outgoing.missing:
+            # something to push, validate it
+            #
+            # if self.obsstore == False --> no obsolete
+            # then, save the iteration
+            if unfi.obsstore:
+                # this message are here for 80 char limit reason
+                mso = _("push includes obsolete changeset: %s!")
+                mst = "push includes %s changeset: %s!"
+                # plain versions for i18n tool to detect them
+                _("push includes unstable changeset: %s!")
+                _("push includes bumped changeset: %s!")
+                _("push includes divergent changeset: %s!")
+                # If we are to push if there is at least one
+                # obsolete or unstable changeset in missing, at
+                # least one of the missinghead will be obsolete or
+                # unstable. So checking heads only is ok
+                for node in outgoing.missingheads:
+                    ctx = unfi[node]
+                    if ctx.obsolete():
+                        raise util.Abort(mso % ctx)
+                    elif ctx.troubled():
+                        raise util.Abort(_(mst)
+                                         % (ctx.troubles()[0],
+                                            ctx))
+            discovery.checkheads(unfi, self.remote, outgoing,
+                                 remoteheads, self.newbranch, bool(inc))
+        return outgoing, remoteheads
+
+
+
     def _pushobsolescence(self):
         """Send local obsolescence marker to remote"""
         self.repo.ui.debug('try to push obsolete markers to remote\n')
         if (obsolete._enabled and self.repo.obsstore and
             'obsolete' in self.remote.listkeys('namespaces')):


More information about the Mercurial-devel mailing list