diff --git a/hgext/largefiles/overrides.py b/hgext/largefiles/overrides.py --- a/hgext/largefiles/overrides.py +++ b/hgext/largefiles/overrides.py @@ -1479,3 +1479,14 @@ def upgraderequirements(orig, repo): if 'largefiles' in repo.requirements: reqs.add('largefiles') return reqs + +_lfscheme = 'largefile://' +def openlargefile(orig, ui, url_, data=None): + if url_.startswith(_lfscheme): + if data: + msg = "cannot use data on a 'largefile://' url" + raise error.ProgrammingError(msg) + lfid = url_[len(_lfscheme):] + return storefactory.getlfile(ui, lfid) + else: + return orig(ui, url_, data=data) diff --git a/hgext/largefiles/remotestore.py b/hgext/largefiles/remotestore.py --- a/hgext/largefiles/remotestore.py +++ b/hgext/largefiles/remotestore.py @@ -27,7 +27,9 @@ class remotestore(basestore.basestore): '''a largefile store accessed over a network''' def __init__(self, ui, repo, url): super(remotestore, self).__init__(ui, repo, url) - self._lstore = localstore.localstore(self.ui, self.repo, self.repo) + self._lstore = None + if repo is not None: + self._lstore = localstore.localstore(self.ui, self.repo, self.repo) def put(self, source, hash): if self.sendfile(source, hash): diff --git a/hgext/largefiles/storefactory.py b/hgext/largefiles/storefactory.py --- a/hgext/largefiles/storefactory.py +++ b/hgext/largefiles/storefactory.py @@ -22,8 +22,9 @@ from . import ( # During clone this function is passed the src's ui object # but it needs the dest's ui object so it can read out of # the config file. Use repo.ui instead. -def openstore(repo, remote=None, put=False): - ui = repo.ui +def openstore(repo=None, remote=None, put=False, ui=None): + if ui is None: + ui = repo.ui if not remote: lfpullsource = getattr(repo, 'lfpullsource', None) @@ -37,12 +38,16 @@ def openstore(repo, remote=None, put=Fal # ui.expandpath() leaves 'default-push' and 'default' alone if # they cannot be expanded: fallback to the empty string, # meaning the current directory. - if path == 'default-push' or path == 'default': + if repo is None: + path = ui.expandpath('default') + path, _branches = hg.parseurl(path) + remote = hg.peer(repo or ui, {}, path) + elif path == 'default-push' or path == 'default': path = '' remote = repo else: path, _branches = hg.parseurl(path) - remote = hg.peer(repo, {}, path) + remote = hg.peer(repo or ui, {}, path) # The path could be a scheme so use Mercurial's normal functionality # to resolve the scheme to a repository and use its path @@ -76,3 +81,6 @@ def openstore(repo, remote=None, put=Fal } _scheme_re = re.compile(r'^([a-zA-Z0-9+-.]+)://') + +def getlfile(ui, hash): + return util.chunkbuffer(openstore(ui=ui)._get(hash)) diff --git a/hgext/largefiles/uisetup.py b/hgext/largefiles/uisetup.py --- a/hgext/largefiles/uisetup.py +++ b/hgext/largefiles/uisetup.py @@ -31,6 +31,7 @@ from mercurial import ( sshpeer, subrepo, upgrade, + url, wireproto, ) @@ -160,6 +161,9 @@ def uisetup(ui): extensions.wrapfunction(scmutil, 'marktouched', overrides.scmutilmarktouched) + extensions.wrapfunction(url, 'open', + overrides.openlargefile) + # create the new wireproto commands ... wireproto.commands['putlfile'] = (proto.putlfile, 'sha') wireproto.commands['getlfile'] = (proto.getlfile, 'sha') diff --git a/tests/test-url-download.t b/tests/test-url-download.t --- a/tests/test-url-download.t +++ b/tests/test-url-download.t @@ -34,3 +34,21 @@ Check other kind of compatible url $ hg debugdownload ./null.txt 1 0000000000000000000000000000000000000000 +Test largefile URL +------------------ + + $ cat << EOF >> $HGRCPATH + > [extensions] + > largefiles= + > EOF + + $ killdaemons.py + $ rm -f error.log hg1.pid + $ hg serve -R server -p $HGPORT -d --pid-file=hg1.pid -E error.log + $ cat hg1.pid >> $DAEMON_PIDS + + $ hg -R server debuglfput null.txt + a57b57b39ee4dc3da1e03526596007f480ecdbe8 + + $ hg --traceback debugdownload "largefile://a57b57b39ee4dc3da1e03526596007f480ecdbe8" --config paths.default=http://localhost:$HGPORT/ + 1 0000000000000000000000000000000000000000