changeset 15485:fa47291b3f1f

phases: mark content pushed as public in local repo on push
author Pierre-Yves David <pierre-yves.david@ens-lyon.org>
date Fri, 11 Nov 2011 00:21:17 +0100
parents a44446ff9ad8
children 1eefa4451c56
files mercurial/discovery.py mercurial/localrepo.py tests/test-phases-exchange.t
diffstat 3 files changed, 68 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/discovery.py	Fri Nov 11 00:19:00 2011 +0100
+++ b/mercurial/discovery.py	Fri Nov 11 00:21:17 2011 +0100
@@ -67,14 +67,18 @@
     on circumstances:
 
     If we are not going to push anything, return a tuple (None,
-    outgoing) where outgoing is 0 if there are no outgoing
+    outgoing, common) where outgoing is 0 if there are no outgoing
     changesets and 1 if there are, but we refuse to push them
-    (e.g. would create new remote heads).
+    (e.g. would create new remote heads). The third element "common"
+    is the list of heads of the common set between local and remote.
 
-    Otherwise, return a tuple (changegroup, remoteheads), where
-    changegroup is a readable file-like object whose read() returns
-    successive changegroup chunks ready to be sent over the wire and
-    remoteheads is the list of remote heads.'''
+    Otherwise, return a tuple (changegroup, remoteheads, futureheads),
+    where changegroup is a readable file-like object whose read()
+    returns successive changegroup chunks ready to be sent over the
+    wire, remoteheads is the list of remote heads and futureheads is
+    the list of heads of the common set between local and remote to
+    be after push completion.
+    '''
     commoninc = findcommonincoming(repo, remote, force=force)
     common, revs = findcommonoutgoing(repo, remote, onlyheads=revs,
                                       commoninc=commoninc, force=force)
@@ -85,7 +89,7 @@
 
     if not outg:
         repo.ui.status(_("no changes found\n"))
-        return None, 1
+        return None, 1, common
 
     if not force and remoteheads != [nullid]:
         if remote.capable('branchmap'):
@@ -189,4 +193,10 @@
         cg = repo._changegroup(outg, 'push')
     else:
         cg = repo.getbundle('push', heads=revs, common=common)
-    return cg, remoteheads
+    # no need to compute outg ancestor. All node in outg have either:
+    # - parents in outg
+    # - parents in common
+    # - nullid parent
+    rset = repo.set('heads(%ln + %ln)', common, outg)
+    futureheads = [ctx.node() for ctx in rset]
+    return cg, remoteheads, futureheads
--- a/mercurial/localrepo.py	Fri Nov 11 00:19:00 2011 +0100
+++ b/mercurial/localrepo.py	Fri Nov 11 00:21:17 2011 +0100
@@ -1554,24 +1554,32 @@
         if not unbundle:
             lock = remote.lock()
         try:
-            cg, remote_heads = discovery.prepush(self, remote, force, revs,
-                                                 newbranch)
-            ret = remote_heads
-            if cg is not None:
-                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 force:
-                        remote_heads = ['force']
-                    # ssh: return remote's addchangegroup()
-                    # http: return remote's addchangegroup() or 0 for error
-                    ret = remote.unbundle(cg, remote_heads, 'push')
-                else:
-                    # we return an integer indicating remote head count change
-                    ret = remote.addchangegroup(cg, 'push', self.url(),
-                                                lock=lock)
+            # get local lock as we might write phase data
+            locallock = self.lock()
+            try:
+                cg, remote_heads, fut = discovery.prepush(self, remote, force,
+                                                           revs, newbranch)
+                ret = remote_heads
+                if cg is not None:
+                    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 force:
+                            remote_heads = ['force']
+                        # ssh: return remote's addchangegroup()
+                        # http: return remote's addchangegroup() or 0 for error
+                        ret = remote.unbundle(cg, remote_heads, 'push')
+                    else:
+                        # we return an integer indicating remote head count change
+                        ret = remote.addchangegroup(cg, 'push', self.url(),
+                                                    lock=lock)
+                # if we don't push, the common data is already useful
+                # everything exchange is public for now
+                phases.advanceboundary(self, 0, fut)
+            finally:
+                locallock.release()
         finally:
             if lock is not None:
                 lock.release()
--- a/tests/test-phases-exchange.t	Fri Nov 11 00:19:00 2011 +0100
+++ b/tests/test-phases-exchange.t	Fri Nov 11 00:21:17 2011 +0100
@@ -30,6 +30,12 @@
   adding manifests
   adding file changes
   added 2 changesets with 2 changes to 2 files
+  $ hgph
+  3 1 a-D
+  2 1 a-C
+  1 0 a-B
+  0 0 a-A
+
   $ cd ../beta
   $ hgph
   1 0 a-B
@@ -55,4 +61,22 @@
   1 0 a-B
   0 0 a-A
 
+pull did not updated ../alpha state.
+push from alpha to beta should update phase even if nothing is transfered
 
+  $ cd ../alpha
+  $ hgph # not updated by remote pull
+  3 1 a-D
+  2 1 a-C
+  1 0 a-B
+  0 0 a-A
+  $ hg push ../beta
+  pushing to ../beta
+  searching for changes
+  no changes found
+  $ hgph
+  3 0 a-D
+  2 0 a-C
+  1 0 a-B
+  0 0 a-A
+