# HG changeset patch # User Matt Harbison , Pierre-Yves David # Date 1677189951 -3600 # Node ID 197204dba8a22a79b025f678c4f9cd6944759199 # Parent 21f876895dfef4281a55b915a488977e81d3e2f2 bundlerepo: apply phase data stored in the bundle instead of assuming `draft` The phase information contained in the changegroup part and the explicit `phase-heads` part are now taken in account. Initial changes and test by Matt Harbison, code rework by Pierre-Yves David. diff -r 21f876895dfe -r 197204dba8a2 mercurial/bundlerepo.py --- a/mercurial/bundlerepo.py Thu Feb 23 19:07:58 2023 +0100 +++ b/mercurial/bundlerepo.py Thu Feb 23 23:05:51 2023 +0100 @@ -302,7 +302,9 @@ cgpart = None for part in bundle.iterparts(seekable=True): - if part.type == b'changegroup': + if part.type == b'phase-heads': + self._handle_bundle2_phase_part(bundle, part) + elif part.type == b'changegroup': if cgpart: raise NotImplementedError( b"can't process multiple changegroups" @@ -346,6 +348,17 @@ def _handle_bundle2_cg_part(self, bundle, part): assert part.type == b'changegroup' cgstream = part + targetphase = part.params.get(b'targetphase') + try: + targetphase = int(targetphase) + except TypeError: + pass + if targetphase is None: + targetphase = phases.draft + if targetphase not in phases.allphases: + m = _(b'unsupported targetphase: %d') + m %= targetphase + raise error.Abort(m) version = part.params.get(b'version', b'01') legalcgvers = changegroup.supportedincomingversions(self) if version not in legalcgvers: @@ -360,10 +373,17 @@ phases.retractboundary( self, None, - phases.draft, + targetphase, [ctx.node() for ctx in self[self.firstnewrev :]], ) + def _handle_bundle2_phase_part(self, bundle, part): + assert part.type == b'phase-heads' + + unfi = self.unfiltered() + headsbyphase = phases.binarydecode(part) + phases.updatephases(unfi, lambda: None, headsbyphase) + def _writetempbundle(self, readfn, suffix, header=b''): """Write a temporary file to disk""" fdtemp, temp = self.vfs.mkstemp(prefix=b"hg-bundle-", suffix=suffix) diff -r 21f876895dfe -r 197204dba8a2 tests/test-bundle-phases.t --- a/tests/test-bundle-phases.t Thu Feb 23 19:07:58 2023 +0100 +++ b/tests/test-bundle-phases.t Thu Feb 23 23:05:51 2023 +0100 @@ -33,7 +33,6 @@ | o A public -Phases are restored when unbundling $ hg bundle --base B -r E bundle 3 changesets found $ hg debugbundle bundle @@ -46,6 +45,57 @@ phase-heads -- {} (mandatory: True) 26805aba1e600a82e93661149f2313866a221a7b draft $ hg strip --no-backup C + +Phases show on incoming, and are also restored when pulling. Secret commits +aren't incoming or pulled, following usual incoming/pull semantics. + + $ hg log -R bundle -r 'bundle()^+bundle()' -G -T '{desc} {phase}\n' + o E secret + | + o D secret + | + o C draft + | + o B draft + | + ~ + + $ hg incoming bundle -G -T '{desc} {phase}\n' + comparing with bundle + searching for changes + o C draft + + $ hg pull bundle + pulling from bundle + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + new changesets 26805aba1e60 (1 drafts) + (run 'hg update' to get a working copy) + $ hg log -G -T '{desc} {phase}\n' + o C draft + | + o B draft + | + o A public + + $ hg log -R bundle -r 'bundle()^+bundle()' -G -T '{desc} {phase}\n' + o E secret + | + o D secret + | + o C draft + | + o B draft + | + ~ + + $ hg rollback --config ui.rollback=1 + repository tip rolled back to revision 1 (undo pull) + +Phases are restored when unbundling $ hg unbundle -q bundle $ rm bundle $ hg log -G -T '{desc} {phase}\n' @@ -64,7 +114,27 @@ 5 changesets found $ hg strip --no-backup A $ hg unbundle -q bundle - $ rm bundle + $ hg log -G -T '{desc} {phase}\n' + o E secret + | + o D secret + | + o C draft + | + o B draft + | + o A public + + $ hg init empty + $ hg -R empty pull bundle + pulling from bundle + requesting all changes + adding changesets + adding manifests + adding file changes + added 3 changesets with 3 changes to 3 files + new changesets 426bada5c675:26805aba1e60 (2 drafts) + (run 'hg update' to get a working copy) $ hg log -G -T '{desc} {phase}\n' o E secret | @@ -76,8 +146,74 @@ | o A public + +Public repo commits take precedence over phases in the bundle + $ hg phase --public E + $ hg incoming bundle -G -T '{desc} {phase}\n' + comparing with bundle + searching for changes + no changes found + $ hg log -R bundle -r 'bundle()^+bundle()' -G -T '{desc} {phase}\n' + o E public + | + o D public + | + o C public + | + o B public + | + o A public + + $ hg pull bundle + pulling from bundle + searching for changes + no changes found + $ hg log -G -T '{desc} {phase}\n' + o E public + | + o D public + | + o C public + | + o B public + | + o A public + + $ rm bundle + +A bundle with public phases that are not public in the repo will show as public +with `hg log`, but will remain not public in the plain repo. + + $ hg bundle --base B -r E bundle + 3 changesets found + $ hg phase --force --draft -r C + + $ hg log -R bundle -G -T '{desc} {phase}\n' + o E public + | + o D public + | + o C public + | + o B public + | + o A public + + $ hg log -G -T '{desc} {phase}\n' + o E draft + | + o D draft + | + o C draft + | + o B public + | + o A public + + $ hg phase --public -r E + $ rm bundle + Completely public history can be restored - $ hg phase --public E $ hg bundle -a bundle 5 changesets found $ hg strip --no-backup A