diff --git a/hgext/share.py b/hgext/share.py --- a/hgext/share.py +++ b/hgext/share.py @@ -65,10 +65,14 @@ testedwith = 'ships-with-hg-core' @command('share', [('U', 'noupdate', None, _('do not create a working directory')), - ('B', 'bookmarks', None, _('also share bookmarks'))], + ('B', 'bookmarks', None, _('also share bookmarks')), + ('', 'relative', None, _('point to source using a relative path ' + '(EXPERIMENTAL)')), + ], _('[-U] [-B] SOURCE [DEST]'), norepo=True) -def share(ui, source, dest=None, noupdate=False, bookmarks=False): +def share(ui, source, dest=None, noupdate=False, bookmarks=False, + relative=False): """create a new shared repository Initialize a new repository and working directory that shares its @@ -87,7 +91,7 @@ def share(ui, source, dest=None, noupdat """ return hg.share(ui, source, dest=dest, update=not noupdate, - bookmarks=bookmarks) + bookmarks=bookmarks, relative=relative) @command('unshare', [], '') def unshare(ui, repo): diff --git a/mercurial/help/internals/requirements.txt b/mercurial/help/internals/requirements.txt --- a/mercurial/help/internals/requirements.txt +++ b/mercurial/help/internals/requirements.txt @@ -55,6 +55,17 @@ This requirement is set when a repositor The requirement was added in Mercurial 1.3 (released July 2009). +relshared +========= + +Derivative of ``shared``; the location of the store is relative to the +store of this repository. + +This requirement is set when a repository is created via :hg:`share` +using the ``--relative`` option. + +The requirement was added in Mercurial 4.2 (released May 2017). + dotencode ========= diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -195,7 +195,8 @@ def defaultdest(source): return '' return os.path.basename(os.path.normpath(path)) -def share(ui, source, dest=None, update=True, bookmarks=True, defaultpath=None): +def share(ui, source, dest=None, update=True, bookmarks=True, defaultpath=None, + relative=False): '''create a shared repository''' if not islocal(source): @@ -235,7 +236,16 @@ def share(ui, source, dest=None, update= if inst.errno != errno.ENOENT: raise - requirements += 'shared\n' + if relative: + try: + sharedpath = os.path.relpath(sharedpath, destvfs.base) + requirements += 'relshared\n' + except IOError as e: + raise error.Abort(_('cannot calculate relative path'), + hint=str(e)) + else: + requirements += 'shared\n' + destvfs.write('requires', requirements) destvfs.write('sharedpath', sharedpath) diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -244,7 +244,7 @@ class localrepository(object): supportedformats = set(('revlogv1', 'generaldelta', 'treemanifest', 'manifestv2')) _basesupported = supportedformats | set(('store', 'fncache', 'shared', - 'dotencode')) + 'relshared', 'dotencode')) openerreqs = set(('revlogv1', 'generaldelta', 'treemanifest', 'manifestv2')) filtername = None @@ -325,8 +325,11 @@ class localrepository(object): self.sharedpath = self.path try: - vfs = scmutil.vfs(self.vfs.read("sharedpath").rstrip('\n'), - realpath=True) + sharedpath = self.vfs.read("sharedpath").rstrip('\n') + if 'relshared' in self.requirements: + sharedpath = self.vfs.join(sharedpath) + vfs = scmutil.vfs(sharedpath, realpath=True) + s = vfs.base if not vfs.exists(): raise error.RepoError( diff --git a/tests/test-share.t b/tests/test-share.t --- a/tests/test-share.t +++ b/tests/test-share.t @@ -358,6 +358,41 @@ verify bookmark behavior after unshare bm4 5:92793bfc8cad $ cd .. +test shared clones using relative paths work + + $ mkdir thisdir + $ hg init thisdir/orig + $ hg share -U thisdir/orig thisdir/abs + $ hg share -U --relative thisdir/abs thisdir/rel + $ cat thisdir/rel/.hg/sharedpath + ../../orig/.hg (no-eol) + $ grep shared thisdir/*/.hg/requires + thisdir/abs/.hg/requires:shared + thisdir/rel/.hg/requires:shared + thisdir/rel/.hg/requires:relshared + +test that relative shared paths aren't relative to $PWD + + $ cd thisdir + $ hg -R rel root + $TESTTMP/thisdir/rel + $ cd .. + +now test that relative paths really are relative, survive across +renames and changes of PWD + + $ hg -R thisdir/abs root + $TESTTMP/thisdir/abs + $ hg -R thisdir/rel root + $TESTTMP/thisdir/rel + $ mv thisdir thatdir + $ hg -R thatdir/abs root + abort: .hg/sharedpath points to nonexistent directory $TESTTMP/thisdir/orig/.hg! + [255] + $ hg -R thatdir/rel root + $TESTTMP/thatdir/rel + $ rm -r thatdir + Explicitly kill daemons to let the test exit on Windows $ killdaemons.py