diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py --- a/mercurial/bundle2.py +++ b/mercurial/bundle2.py @@ -1599,6 +1599,14 @@ phasedata = phases.binaryencode(headsbyphase) bundler.newpart('phase-heads', data=phasedata) + if opts.get('bookmarks', False): + # From exchange._pushb2bookmarkspart + data = [] + for book, new in repo._bookmarks.items(): + data.append((book, new)) + checkdata = bookmarks.binaryencode(data) + bundler.newpart('bookmarks', data=checkdata) + def addparttagsfnodescache(repo, bundler, outgoing): # we include the tags fnode cache for the bundle changeset # (as an optional parts) diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -1267,6 +1267,8 @@ contentopts['obsolescence'] = True if repo.ui.configbool('experimental', 'bundle-phases'): contentopts['phases'] = True + if repo.ui.configbool('experimental', 'bundle-bookmarks'): + contentopts['bookmarks'] = True bundle2.writenewbundle(ui, repo, 'bundle', fname, bversion, outgoing, contentopts, compression=bcompression, compopts=compopts) @@ -5406,7 +5408,7 @@ """ fnames = (fname1,) + fnames - with repo.lock(): + with repo.wlock(), repo.lock(): for fname in fnames: f = hg.openpath(ui, fname) gen = exchange.readbundle(ui, f, fname) diff --git a/mercurial/configitems.py b/mercurial/configitems.py --- a/mercurial/configitems.py +++ b/mercurial/configitems.py @@ -419,6 +419,9 @@ coreconfigitem('experimental', 'archivemetatemplate', default=dynamicdefault, ) +coreconfigitem('experimental', 'bundle-bookmarks', + default=False, +) coreconfigitem('experimental', 'bundle-phases', default=False, ) diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py --- a/mercurial/debugcommands.py +++ b/mercurial/debugcommands.py @@ -33,6 +33,7 @@ short, ) from . import ( + bookmarks, bundle2, changegroup, cmdutil, @@ -326,6 +327,14 @@ ui.write(indent_string) ui.write('%s %s\n' % (hex(head), phases.phasenames[phase])) +def _debugbookmarks(ui, data, indent=0): + """display version and markers contained in 'data'""" + indent_string = ' ' * indent + bm = bookmarks.binarydecode(data) + for bookmark in sorted(bm): + ui.write(indent_string) + ui.write('%s: %s\n' % (bookmark[0], bookmark[1])) + def _quasirepr(thing): if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)): return '{%s}' % ( @@ -353,6 +362,9 @@ if part.type == 'phase-heads': if not ui.quiet: _debugphaseheads(ui, part, indent=4) + if part.type == 'bookmarks': + if not ui.quiet: + _debugbookmarks(ui, part, indent=4) @command('debugbundle', [('a', 'all', None, _('show all details')), diff --git a/tests/test-bundle-bookmarks.t b/tests/test-bundle-bookmarks.t new file mode 100644 --- /dev/null +++ b/tests/test-bundle-bookmarks.t @@ -0,0 +1,116 @@ + $ cat >> $HGRCPATH < [experimental] + > bundle-bookmarks=yes + > [extensions] + > strip= + > drawdag=$TESTDIR/drawdag.py + > EOF + +Set up repo with linear history + $ hg init linear + $ cd linear + $ hg debugdrawdag <<'EOF' + > E + > | + > D + > | + > C + > | + > B + > | + > A + > EOF + $ hg bookmarks -r A "A1" + $ hg bookmarks -r D "D1" + $ hg bookmarks -r D "D2" + $ hg log -G -T '{desc} {bookmarks}\n' + o E + | + o D D1 D2 + | + o C + | + o B + | + o A A1 + +Bookmarks are restored when unbundling + $ hg bundle --all bundle + 5 changesets found + $ hg debugbundle bundle + Stream params: {Compression: BZ} + changegroup -- {nbchanges: 5, version: 02} + 426bada5c67598ca65036d57d9e4b64b0c1ce7a0 + 112478962961147124edd43549aedd1a335e44bf + 26805aba1e600a82e93661149f2313866a221a7b + f585351a92f85104bff7c284233c338b10eb1df7 + 9bc730a19041f9ec7cb33c626e811aa233efb18c + bookmarks -- {} + A1: Bk\xad\xa5\xc6u\x98\xcae\x03mW\xd9\xe4\xb6K\x0c\x1c\xe7\xa0 (esc) + D1: \xf5\x855\x1a\x92\xf8Q\x04\xbf\xf7\xc2\x84#<3\x8b\x10\xeb\x1d\xf7 (esc) + D2: \xf5\x855\x1a\x92\xf8Q\x04\xbf\xf7\xc2\x84#<3\x8b\x10\xeb\x1d\xf7 (esc) + $ hg strip --no-backup C + $ hg unbundle -q bundle + $ hg log -G -T '{desc} {bookmarks}\n' + o E + | + o D D1 D2 + | + o C + | + o B + | + o A A1 + +Bookmarks doesn't conflict with local bookmarks + + $ hg bookmarks -d A1 + $ hg bookmarks -r A "A2" + $ hg unbundle -q bundle + $ hg log -G -T '{desc} {bookmarks}\n' + o E + | + o D D1 D2 + | + o C + | + o B + | + o A A1 A2 + +Test bookmarks divergence + + $ hg bundle --all bundle + 5 changesets found + $ hg strip --no-backup C + +Create soem divergence + $ hg up B + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ touch F + $ hg add F + $ hg commit -m "F" + $ hg bookmarks -f -r "desc(F)" D1 + + $ hg log -G -T '{desc} {bookmarks}\n' + @ F D1 + | + o B D2 + | + o A A1 A2 + + + $ hg unbundle -q bundle + $ hg log -G -T '{desc} {bookmarks}\n' + o E + | + o D D1 D2 + | + o C + | + | @ F + |/ + o B + | + o A A1 A2 +