# HG changeset patch # User Pierre-Yves David # Date 1327090873 -3600 # Node ID 5653f2d166eab6cc67495535af8c4b82d940da39 # Parent 5a14f48d6b9a5822c8d6d1be66b904cc8788a107 push: prevent moving phases outside of the pushed subset diff -r 5a14f48d6b9a -r 5653f2d166ea mercurial/localrepo.py --- a/mercurial/localrepo.py Fri Jan 20 19:41:18 2012 +0100 +++ b/mercurial/localrepo.py Fri Jan 20 21:21:13 2012 +0100 @@ -1554,21 +1554,29 @@ clend = len(self.changelog) added = [self.changelog.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 - subset = common + added pheads, _dr = phases.analyzeremotephases(self, subset, remotephases) phases.advanceboundary(self, phases.public, pheads) - phases.advanceboundary(self, phases.draft, common + added) + 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, common + added) + phases.advanceboundary(self, phases.public, subset) finally: lock.release() @@ -1652,11 +1660,35 @@ # we return an integer indicating remote head count change ret = remote.addchangegroup(cg, 'push', self.url()) - cheads = outgoing.commonheads[:] if ret: - # push succeed, synchonize common + pushed - # this is a no-op if there was nothing to push - cheads += outgoing.missingheads + # push succeed, synchonize target of the push + cheads = outgoing.missingheads + elif revs is None: + # All out push fails. synchronize all common + cheads = outgoing.commonheads + else: + # I want cheads = heads(::missingheads and ::commonheads) + # (missingheads is revs with secret changeset filtered out) + # + # This can be expressed as: + # cheads = ( (missingheads and ::commonheads) + # + (commonheads and ::missingheads))" + # ) + # + # while trying to push we already computed the following: + # common = (::commonheads) + # missing = ((commonheads::missingheads) - commonheads) + # + # We can pick: + # * missingheads part of comon (::commonheads) + common = set(outgoing.common) + cheads = [n for node in revs if n in common] + # and + # * commonheads parents on missing + rvset = repo.revset('%ln and parents(roots(%ln))', + outgoing.commonheads, + outgoing.missing) + cheads.extend(c.node() for c in rvset) # even when we don't push, exchanging phase data is useful remotephases = remote.listkeys('phases') if not remotephases: # old server or public only repo diff -r 5a14f48d6b9a -r 5653f2d166ea tests/test-hook.t --- a/tests/test-hook.t Fri Jan 20 19:41:18 2012 +0100 +++ b/tests/test-hook.t Fri Jan 20 21:21:13 2012 +0100 @@ -179,7 +179,6 @@ 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 @@ -193,7 +192,7 @@ pulling from ../a listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'} no changes found - listkeys hook: HG_NAMESPACE=phases HG_VALUES={'539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10': '1', 'publishing': 'True'} + listkeys hook: HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'} listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'} importing bookmark bar $ cd ../a @@ -207,7 +206,7 @@ pushing to ../a searching for changes no changes found - listkeys hook: HG_NAMESPACE=phases HG_VALUES={'539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10': '1', 'publishing': 'True'} + listkeys hook: HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '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 diff -r 5a14f48d6b9a -r 5653f2d166ea tests/test-phases-exchange.t --- a/tests/test-phases-exchange.t Fri Jan 20 19:41:18 2012 +0100 +++ b/tests/test-phases-exchange.t Fri Jan 20 21:21:13 2012 +0100 @@ -238,10 +238,10 @@ adding file changes added 1 changesets with 1 changes to 1 files (run 'hg update' to get a working copy) - $ hgph + $ hgph # f54f1bb90ff3 stay draft, not ancestor of -r o 4 public a-D - b555f63b6063 | - | o 3 public b-A - f54f1bb90ff3 + | o 3 draft b-A - f54f1bb90ff3 | | o | 2 public a-C - 54acac6f23ab |/ @@ -262,7 +262,7 @@ | | o 4 public a-D - b555f63b6063 | | - o | 3 public b-A - f54f1bb90ff3 + o | 3 draft b-A - f54f1bb90ff3 | | | o 2 public a-C - 54acac6f23ab |/ @@ -288,7 +288,7 @@ | | | o 3 public a-C - 54acac6f23ab | | - o | 2 public b-A - f54f1bb90ff3 + o | 2 draft b-A - f54f1bb90ff3 |/ o 1 public a-B - 548a3d25dbf0 | @@ -497,20 +497,21 @@ $ cd ../mu - $ hgph # d6bcb4f74035 and 145e75495359 changed because common is too smart + $ hgph # again f54f1bb90ff3, d6bcb4f74035 and 145e75495359 stay draft, + > # not ancestor of -r o 8 draft a-F - b740e3e5c05d | o 7 draft a-E - e9f537e46dea | - | o 6 public n-B - 145e75495359 + | o 6 draft n-B - 145e75495359 | | - | o 5 public n-A - d6bcb4f74035 + | o 5 draft n-A - d6bcb4f74035 | | o | 4 public a-D - b555f63b6063 | | o | 3 public a-C - 54acac6f23ab | | - | o 2 public b-A - f54f1bb90ff3 + | o 2 draft b-A - f54f1bb90ff3 |/ o 1 public a-B - 548a3d25dbf0 | @@ -526,20 +527,21 @@ 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 + $ hgph # again f54f1bb90ff3, d6bcb4f74035 and 145e75495359 stay draft, + > # not ancestor of -r o 8 public a-F - b740e3e5c05d | o 7 public a-E - e9f537e46dea | - | o 6 public n-B - 145e75495359 + | o 6 draft n-B - 145e75495359 | | - | o 5 public n-A - d6bcb4f74035 + | o 5 draft n-A - d6bcb4f74035 | | o | 4 public a-D - b555f63b6063 | | o | 3 public a-C - 54acac6f23ab | | - | o 2 public b-A - f54f1bb90ff3 + | o 2 draft b-A - f54f1bb90ff3 |/ o 1 public a-B - 548a3d25dbf0 | @@ -569,7 +571,7 @@ o 0 public a-A - 054250a37db4 $ cd ../alpha - $ hgph # e9f537e46dea and b740e3e5c05d should have been sync to 0 + $ hgph @ 10 draft a-H - 967b449fbc94 | | o 9 draft a-G - 3e27b6f1eee1 @@ -627,14 +629,14 @@ $ cd ../mu $ hgph # d6bcb4f74035 should have changed phase - > # again d6bcb4f74035 and 145e75495359 changed because common was too smart + > # 145e75495359 is still draft. not ancestor of -r o 9 draft a-H - 967b449fbc94 | | o 8 public a-F - b740e3e5c05d | | | o 7 public a-E - e9f537e46dea | | - +---o 6 public n-B - 145e75495359 + +---o 6 draft n-B - 145e75495359 | | o | 5 public n-A - d6bcb4f74035 | |