[PATCH 6 of 6 phases exchange V2] phases: exchange phase boundaries on push

pierre-yves.david at logilab.fr pierre-yves.david at logilab.fr
Thu Dec 15 05:05:51 CST 2011


# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at logilab.fr>
# Date 1323945901 -3600
# Node ID 6869a4c510c3eafbe00e58a2b7aac3f214b48cf1
# Parent  ef72c0f1e19778a47976e7cb4b827d379653ecfd
phases: exchange phase boundaries on push

For now phase sync is tried even if push fails with some know pathological
case. The exact behavior is to be discussed and implemented later.

diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -1585,10 +1585,12 @@ class localrepository(repo.repository):
             locallock = self.lock()
             try:
                 cg, remote_heads, fut = discovery.prepush(self, remote, force,
                                                            revs, newbranch)
                 ret = remote_heads
+                # create a callback for addchangegroup.
+                # If will be used branch of the conditionnal too.
                 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
@@ -1599,13 +1601,45 @@ class localrepository(repo.repository):
                         # 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())
-                # if we don't push, the common data is already useful
-                # everything exchange is public for now
-                phases.advanceboundary(self, 0, fut)
+
+                # even when we don't push, exchanging phase data is useful
+                remotephases = remote.listkeys('phases')
+                if not remotephases: # old server or public only repo
+                    phases.advanceboundary(self, 0, fut)
+                    # don't push any phase data as there is nothing to push
+                else:
+                    ana = phases.analyzeremotephases(self, fut, remotephases)
+                    rheads, rroots = ana
+                    ### Apply remote phase on local
+                    if remotephases.get('publishing', False):
+                        phases.advanceboundary(self, 0, fut)
+                    else: # publish = False
+                        for phase, rpheads in enumerate(rheads):
+                            phases.advanceboundary(self, phase, rpheads)
+                    ### Apply local phase on remote
+                    #
+                    # XXX If push failed we should use strict common and not
+                    # future to avoir pushing phase data on unknown changeset.
+                    # This is to done later.
+                    futctx = [self[n] for n in fut if n != nullid]
+                    for phase in phases.trackedphases[::-1]:
+                        prevphase = phase -1
+                        # get all candidate for head in previous phase
+                        inprev = [ctx for ctx in futctx
+                                      if ctx.phase() == prevphase]
+                        for newremotehead in  self.set('heads(%ld & (%ln::))',
+                                              inprev, rroots[phase]):
+                            r = remote.pushkey('phases',
+                                               newremotehead.hex(),
+                                               str(phase), str(prevphase))
+                            if not r:
+                                self.ui.warn(_('updating phase of %s'
+                                               'to %s failed!\n')
+                                                % (newremotehead, prevphase))
             finally:
                 locallock.release()
         finally:
             if lock is not None:
                 lock.release()
diff --git a/tests/test-hook.t b/tests/test-hook.t
--- a/tests/test-hook.t
+++ b/tests/test-hook.t
@@ -177,10 +177,11 @@ pushkey hook
   $ hg bookmark -r null foo
   $ hg push -B foo ../a
   pushing to ../a
   searching for changes
   no changes found
+  pushkey hook: HG_KEY=07f3376c1e655977439df2a814e3cc14b27abac2 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1 HG_RET=1 
   exporting bookmark foo
   pushkey hook: HG_KEY=foo HG_NAMESPACE=bookmarks HG_NEW=0000000000000000000000000000000000000000 HG_RET=1 
   $ cd ../a
 
 listkeys hook
@@ -190,11 +191,11 @@ listkeys hook
   $ cd ../b
   $ hg pull -B bar ../a
   pulling from ../a
   listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'} 
   no changes found
-  listkeys hook: HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'} 
+  listkeys hook: HG_NAMESPACE=phases HG_VALUES={'539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10': '1', 'publishing': 'True'} 
   listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'} 
   importing bookmark bar
   $ cd ../a
 
 test that prepushkey can prevent incoming keys
@@ -204,10 +205,11 @@ test that prepushkey can prevent incomin
   $ hg bookmark -r null baz
   $ hg push -B baz ../a
   pushing to ../a
   searching for changes
   no changes found
+  listkeys hook: HG_NAMESPACE=phases HG_VALUES={'539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10': '1', 'publishing': 'True'} 
   listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'} 
   listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'} 
   exporting bookmark baz
   prepushkey.forbid hook: HG_KEY=baz HG_NAMESPACE=bookmarks HG_NEW=0000000000000000000000000000000000000000 
   abort: prepushkey hook exited with status 1
diff --git a/tests/test-phases-exchange.t b/tests/test-phases-exchange.t
--- a/tests/test-phases-exchange.t
+++ b/tests/test-phases-exchange.t
@@ -268,5 +268,218 @@ pulling back into original repo
   3 0 b-A - f54f1bb90ff3
   2 0 a-C - 54acac6f23ab
   1 0 a-B - 548a3d25dbf0
   0 0 a-A - 054250a37db4
   $ cd ..
+
+Push
+````
+
+initial setup
+
+  $ cd alpha
+  $ hg glog
+  o  changeset:   6:145e75495359
+  |  tag:         tip
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     n-B
+  |
+  o  changeset:   5:d6bcb4f74035
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     n-A
+  |
+  o  changeset:   4:f54f1bb90ff3
+  |  parent:      1:548a3d25dbf0
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     b-A
+  |
+  | @  changeset:   3:b555f63b6063
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     a-D
+  | |
+  | o  changeset:   2:54acac6f23ab
+  |/   user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     a-C
+  |
+  o  changeset:   1:548a3d25dbf0
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     a-B
+  |
+  o  changeset:   0:054250a37db4
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     a-A
+  
+  $ mkcommit a-E
+  $ mkcommit a-F
+  $ mkcommit a-G
+  $ hg up d6bcb4f74035 -q
+  $ mkcommit a-H
+  created new head
+  $ hgph
+  10 1 a-H - 967b449fbc94
+  9 1 a-G - 3e27b6f1eee1
+  8 1 a-F - b740e3e5c05d
+  7 1 a-E - e9f537e46dea
+  6 0 n-B - 145e75495359
+  5 0 n-A - d6bcb4f74035
+  4 0 b-A - f54f1bb90ff3
+  3 0 a-D - b555f63b6063
+  2 0 a-C - 54acac6f23ab
+  1 0 a-B - 548a3d25dbf0
+  0 0 a-A - 054250a37db4
+
+Pushing to Publish=False (unknown changeset)
+
+  $ hg push ../mu -r b740e3e5c05d # a-F
+  pushing to ../mu
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 2 changes to 2 files
+  $ hgph
+  10 1 a-H - 967b449fbc94
+  9 1 a-G - 3e27b6f1eee1
+  8 1 a-F - b740e3e5c05d
+  7 1 a-E - e9f537e46dea
+  6 0 n-B - 145e75495359
+  5 0 n-A - d6bcb4f74035
+  4 0 b-A - f54f1bb90ff3
+  3 0 a-D - b555f63b6063
+  2 0 a-C - 54acac6f23ab
+  1 0 a-B - 548a3d25dbf0
+  0 0 a-A - 054250a37db4
+
+  $ cd ../mu
+  $ hgph # d6bcb4f74035 and 145e75495359 changed because common is too smart
+  8 1 a-F - b740e3e5c05d
+  7 1 a-E - e9f537e46dea
+  6 0 n-B - 145e75495359
+  5 0 n-A - d6bcb4f74035
+  4 0 a-D - b555f63b6063
+  3 0 a-C - 54acac6f23ab
+  2 0 b-A - f54f1bb90ff3
+  1 0 a-B - 548a3d25dbf0
+  0 0 a-A - 054250a37db4
+
+Pushing to Publish=True (unknown changeset)
+
+  $ hg push ../beta -r b740e3e5c05d
+  pushing to ../beta
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 2 changes to 2 files
+  $ hgph # again d6bcb4f74035 and 145e75495359 changed because common is too smart
+  8 0 a-F - b740e3e5c05d
+  7 0 a-E - e9f537e46dea
+  6 0 n-B - 145e75495359
+  5 0 n-A - d6bcb4f74035
+  4 0 a-D - b555f63b6063
+  3 0 a-C - 54acac6f23ab
+  2 0 b-A - f54f1bb90ff3
+  1 0 a-B - 548a3d25dbf0
+  0 0 a-A - 054250a37db4
+
+Pushing to Publish=True (common changeset)
+
+  $ cd ../beta
+  $ hg push ../alpha
+  pushing to ../alpha
+  searching for changes
+  no changes found
+  $ hgph
+  6 0 a-F - b740e3e5c05d
+  5 0 a-E - e9f537e46dea
+  4 0 a-D - b555f63b6063
+  3 0 a-C - 54acac6f23ab
+  2 0 b-A - f54f1bb90ff3
+  1 0 a-B - 548a3d25dbf0
+  0 0 a-A - 054250a37db4
+  $ cd ../alpha
+  $ hgph # e9f537e46dea and b740e3e5c05d should have been sync to 0
+  10 1 a-H - 967b449fbc94
+  9 1 a-G - 3e27b6f1eee1
+  8 0 a-F - b740e3e5c05d
+  7 0 a-E - e9f537e46dea
+  6 0 n-B - 145e75495359
+  5 0 n-A - d6bcb4f74035
+  4 0 b-A - f54f1bb90ff3
+  3 0 a-D - b555f63b6063
+  2 0 a-C - 54acac6f23ab
+  1 0 a-B - 548a3d25dbf0
+  0 0 a-A - 054250a37db4
+
+Pushing to Publish=False (common changeset that change phase + unknown one)
+
+  $ hg push ../mu -r 967b449fbc94 -f
+  pushing to ../mu
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files (+1 heads)
+  $ hgph
+  10 1 a-H - 967b449fbc94
+  9 1 a-G - 3e27b6f1eee1
+  8 0 a-F - b740e3e5c05d
+  7 0 a-E - e9f537e46dea
+  6 0 n-B - 145e75495359
+  5 0 n-A - d6bcb4f74035
+  4 0 b-A - f54f1bb90ff3
+  3 0 a-D - b555f63b6063
+  2 0 a-C - 54acac6f23ab
+  1 0 a-B - 548a3d25dbf0
+  0 0 a-A - 054250a37db4
+  $ cd ../mu
+  $ hgph # d6bcb4f74035 should have changed phase
+  >      # again d6bcb4f74035 and 145e75495359 changed because common was too smart
+  9 1 a-H - 967b449fbc94
+  8 0 a-F - b740e3e5c05d
+  7 0 a-E - e9f537e46dea
+  6 0 n-B - 145e75495359
+  5 0 n-A - d6bcb4f74035
+  4 0 a-D - b555f63b6063
+  3 0 a-C - 54acac6f23ab
+  2 0 b-A - f54f1bb90ff3
+  1 0 a-B - 548a3d25dbf0
+  0 0 a-A - 054250a37db4
+
+
+Pushing to Publish=True (common changeset from publish=False)
+
+  $ hg push ../alpha
+  pushing to ../alpha
+  searching for changes
+  no changes found
+  $ hgph
+  9 0 a-H - 967b449fbc94
+  8 0 a-F - b740e3e5c05d
+  7 0 a-E - e9f537e46dea
+  6 0 n-B - 145e75495359
+  5 0 n-A - d6bcb4f74035
+  4 0 a-D - b555f63b6063
+  3 0 a-C - 54acac6f23ab
+  2 0 b-A - f54f1bb90ff3
+  1 0 a-B - 548a3d25dbf0
+  0 0 a-A - 054250a37db4
+  $ hgph -R ../alpha # a-H should have been synced to 0
+  10 0 a-H - 967b449fbc94
+  9 1 a-G - 3e27b6f1eee1
+  8 0 a-F - b740e3e5c05d
+  7 0 a-E - e9f537e46dea
+  6 0 n-B - 145e75495359
+  5 0 n-A - d6bcb4f74035
+  4 0 b-A - f54f1bb90ff3
+  3 0 a-D - b555f63b6063
+  2 0 a-C - 54acac6f23ab
+  1 0 a-B - 548a3d25dbf0
+  0 0 a-A - 054250a37db4
+
diff --git a/tests/test-push-http.t b/tests/test-push-http.t
--- a/tests/test-push-http.t
+++ b/tests/test-push-http.t
@@ -26,10 +26,12 @@ expect ssl error
 
   $ req
   pushing to http://localhost:$HGPORT/
   searching for changes
   remote: ssl required
+  remote: ssl required
+  updating phase of ba677d0156c1to 0 failed!
   % serve errors
 
 expect authorization error
 
   $ echo '[web]' > .hg/hgrc


More information about the Mercurial-devel mailing list