[PATCH 1 of 2 V2] share: implement shared bookmark functionality

Ryan McElroy rm at fb.com
Tue Dec 2 21:39:44 UTC 2014


# HG changeset patch
# User Ryan McElroy <rmcelroy at fb.com>
# Date 1417078134 28800
#      Thu Nov 27 00:48:54 2014 -0800
# Node ID 5fc6fc3b954321f2aed07d7270f560e7c4c867be
# Parent  c4f7d3fbe855041951dfccb40b05031def426a2b
share: implement shared bookmark functionality

The hg.share function now creates a bookmarks.shared file in the destination
repository with contents pointing to the source repository with which the
destination should share bookmarks.

This enables bookmarks to be shared between shared repositories by extending
the bookmarks.bmstore methods that read and write bookmarks to take into account
a bookmarks.shared file that can point to another repository.

diff --git a/hgext/share.py b/hgext/share.py
--- a/hgext/share.py
+++ b/hgext/share.py
@@ -6,7 +6,9 @@
 '''share a common history between several working directories'''
 
 from mercurial.i18n import _
-from mercurial import cmdutil, hg, util
+from mercurial import cmdutil, hg, util, extensions, bookmarks
+from mercurial.hg import repository, parseurl
+import errno
 
 cmdtable = {}
 command = cmdutil.command(cmdtable)
@@ -20,7 +22,7 @@ def share(ui, source, dest=None, noupdat
     """create a new shared repository
 
     Initialize a new repository and working directory that shares its
-    history with another repository.
+    history and bookmarks with another repository.
 
     .. note::
 
@@ -67,3 +69,45 @@ def unshare(ui, repo):
 
     # update store, spath, sopener and sjoin of repo
     repo.unfiltered().__init__(repo.baseui, repo.root)
+
+def extsetup(ui):
+    extensions.wrapfunction(bookmarks.bmstore, 'getbkfile', getbkfile)
+    extensions.wrapfunction(bookmarks.bmstore, 'recordchange', recordchange)
+    extensions.wrapfunction(bookmarks.bmstore, 'write', write)
+
+def getsrcrepo(repo):
+    srcrepo = None
+    try:
+        source = repo.vfs.read('bookmarks.shared')
+        srcurl, branches = parseurl(source)
+        srcrepo = repository(repo.ui, srcurl)
+    except IOError, inst:
+        if inst.errno != errno.ENOENT:
+            raise
+    return srcrepo
+
+def getbkfile(orig, self, repo):
+    repo = getsrcrepo(repo) or repo
+    return orig(self, repo)
+
+def recordchange(orig, self, tr):
+    tr.addfilegenerator('bookmarks', ('bookmarks',), self._write)
+    orig(self, tr)
+    _write(self)
+
+def write(orig, self):
+    # First write a bookmarks file in case we ever unshare
+    orig(self)
+    _write(self)
+
+def _write(self):
+    repo = getsrcrepo(self._repo) or self._repo
+
+    wlock = repo.wlock()
+    try:
+        f = repo.vfs('bookmarks', 'w', atomictemp=True)
+        self._write(f)
+        f.close()
+
+    finally:
+        wlock.release()
diff --git a/mercurial/hg.py b/mercurial/hg.py
--- a/mercurial/hg.py
+++ b/mercurial/hg.py
@@ -225,6 +225,18 @@ def share(ui, source, dest=None, update=
                 continue
         _update(r, uprev)
 
+    bookpath = srcrepo.wvfs.base
+    # follow shared repo to source
+    try:
+        bookpath = srcrepo.vfs.read('bookmarks.shared')
+        ui.debug('bookmark path changed to %s' % bookpath)
+    except IOError, inst:
+        ui.debug('bookmkar path left as %s' % bookpath)
+        if inst.errno != errno.ENOENT:
+            raise
+
+    destvfs.write('bookmarks.shared', bookpath)
+
 def copystore(ui, srcrepo, destpath):
     '''copy files from store of srcrepo in destpath
 
diff --git a/tests/test-share.t b/tests/test-share.t
--- a/tests/test-share.t
+++ b/tests/test-share.t
@@ -128,6 +128,114 @@ check that a change does not propagate
 
   $ cd ..
 
+
+test sharing bookmarks
+
+  $ hg share repo1 repo3
+  updating working directory
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ cd repo1
+  $ hg bookmark bm1
+  $ hg bookmarks
+   * bm1                       2:c2e0ac586386
+  $ cd ../repo2
+  $ hg book bm2
+  $ hg bookmarks
+     bm1                       2:c2e0ac586386
+   * bm2                       3:0e6e70d1d5f1
+  $ cd ../repo3
+  $ hg bookmarks
+     bm1                       2:c2e0ac586386
+  $ hg book bm3
+  $ hg bookmarks
+     bm1                       2:c2e0ac586386
+   * bm3                       2:c2e0ac586386
+  $ cd ../repo1
+  $ hg bookmarks
+   * bm1                       2:c2e0ac586386
+     bm3                       2:c2e0ac586386
+
+test that commits work
+
+  $ echo 'shared bookmarks' > a
+  $ hg commit -m 'testing shared bookmarks'
+  $ hg bookmarks
+   * bm1                       3:b87954705719
+     bm3                       2:c2e0ac586386
+  $ cd ../repo3
+  $ hg bookmarks
+     bm1                       3:b87954705719
+   * bm3                       2:c2e0ac586386
+  $ echo 'more shared bookmarks' > a
+  $ hg commit -m 'testing shared bookmarks'
+  created new head
+  $ hg bookmarks
+     bm1                       3:b87954705719
+   * bm3                       4:62f4ded848e4
+  $ cd ../repo1
+  $ hg bookmarks
+   * bm1                       3:b87954705719
+     bm3                       4:62f4ded848e4
+  $ cd ..
+
+test pushing bookmarks works
+
+  $ hg clone repo3 repo4
+  updating to branch default
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ cd repo4
+  $ hg boo bm4
+  $ echo foo > b
+  $ hg commit -m 'foo in b'
+  $ hg boo
+     bm1                       3:b87954705719
+     bm3                       4:62f4ded848e4
+   * bm4                       5:92793bfc8cad
+  $ hg push -B bm4
+  pushing to $TESTTMP/repo3 (glob)
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  exporting bookmark bm4
+  $ cd ../repo1
+  $ hg bookmarks
+   * bm1                       3:b87954705719
+     bm3                       4:62f4ded848e4
+     bm4                       5:92793bfc8cad
+  $ cd ../repo3
+  $ hg bookmarks
+     bm1                       3:b87954705719
+   * bm3                       4:62f4ded848e4
+     bm4                       5:92793bfc8cad
+  $ cd ..
+
+test behavior when sharing a shared repo
+
+  $ hg share repo3 repo5
+  updating working directory
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ cd repo5
+  $ hg book
+     bm1                       3:b87954705719
+     bm3                       4:62f4ded848e4
+     bm4                       5:92793bfc8cad
+  $ cd ..
+
+test what happens when an active bookmark is deleted
+
+  $ cd repo1
+  $ hg boo -d bm3
+  $ hg boo
+   * bm1                       3:b87954705719
+     bm4                       5:92793bfc8cad
+  $ cd ../repo3
+  $ hg boo
+     bm1                       3:b87954705719
+     bm4                       5:92793bfc8cad
+
+
 Explicitly kill daemons to let the test exit on Windows
 
   $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS


More information about the Mercurial-devel mailing list