# HG changeset patch # User Dan Villiom Podlaski Christiansen # Date 1486991124 -3600 # Node ID 23080c03a604737b7d32cb789b7526bbec125e08 # Parent bbdd712e9adb2affe5a065dda8f5e6433ebac6d1 share: add --relative flag to store a relative path to the source Storing a relative path the source repository is useful when exporting repositories over the network or when they're located on external drives where the mountpoint isn't always fixed. Currently, Mercurial interprets paths in `.hg/shared` relative to $PWD. I suspect this is very much unintentional, and you have to manually edit `.hg/shared` in order to trigger this behaviour. However, on the off chance that someone might rely on it, I added a new capability called 'relshared'. In addition, this makes earlier versions of Mercurial fail with a graceful error. I should note that I haven't tested this patch on Windows. diff -r bbdd712e9adb -r 23080c03a604 hgext/share.py --- a/hgext/share.py Wed Feb 15 11:49:12 2017 -0800 +++ b/hgext/share.py Mon Feb 13 14:05:24 2017 +0100 @@ -65,10 +65,14 @@ @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 @@ """ return hg.share(ui, source, dest=dest, update=not noupdate, - bookmarks=bookmarks) + bookmarks=bookmarks, relative=relative) @command('unshare', [], '') def unshare(ui, repo): diff -r bbdd712e9adb -r 23080c03a604 mercurial/help/internals/requirements.txt --- a/mercurial/help/internals/requirements.txt Wed Feb 15 11:49:12 2017 -0800 +++ b/mercurial/help/internals/requirements.txt Mon Feb 13 14:05:24 2017 +0100 @@ -55,6 +55,17 @@ 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 -r bbdd712e9adb -r 23080c03a604 mercurial/hg.py --- a/mercurial/hg.py Wed Feb 15 11:49:12 2017 -0800 +++ b/mercurial/hg.py Mon Feb 13 14:05:24 2017 +0100 @@ -195,7 +195,8 @@ 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 @@ 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 -r bbdd712e9adb -r 23080c03a604 mercurial/localrepo.py --- a/mercurial/localrepo.py Wed Feb 15 11:49:12 2017 -0800 +++ b/mercurial/localrepo.py Mon Feb 13 14:05:24 2017 +0100 @@ -244,7 +244,7 @@ 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 @@ 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 -r bbdd712e9adb -r 23080c03a604 tests/test-share.t --- a/tests/test-share.t Wed Feb 15 11:49:12 2017 -0800 +++ b/tests/test-share.t Mon Feb 13 14:05:24 2017 +0100 @@ -358,6 +358,41 @@ 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