sapling/remotefilelog/shallowrepo.py

104 lines
4.2 KiB
Python
Raw Normal View History

# shallowrepo.py - shallow repository that uses remote filelogs
2013-05-18 05:08:53 +04:00
#
# Copyright 2013 Facebook, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from mercurial.node import hex, nullid, bin
2013-05-18 05:08:53 +04:00
from mercurial.i18n import _
from mercurial import localrepo, context, util, match
2013-08-30 22:09:19 +04:00
from mercurial.extensions import wrapfunction
2013-09-09 22:44:08 +04:00
import remotefilelog, remotefilectx, fileserverclient, shallowbundle, os
requirement = "remotefilelog"
def wraprepo(repo):
class shallowrepository(repo.__class__):
@util.propertycache
def name(self):
return self.ui.config('remotefilelog', 'reponame', '')
def file(self, f):
if f[0] == '/':
f = f[1:]
if self.shallowmatch(f):
return remotefilelog.remotefilelog(self.sopener, f, self)
else:
return super(shallowrepository, self).file(f)
def filectx(self, path, changeid=None, fileid=None):
if self.shallowmatch(path):
return remotefilectx.remotefilectx(self, path, changeid, fileid)
else:
return super(shallowrepository, self).filectx(path, changeid, fileid)
def pull(self, remote, *args, **kwargs):
# Hook into the callstream/getbundle to insert bundle capabilities
# during a pull.
def remotecallstream(orig, command, **opts):
if command == 'getbundle' and 'remotefilelog' in remote._capabilities():
bundlecaps = opts.get('bundlecaps')
if bundlecaps:
bundlecaps = [bundlecaps]
else:
bundlecaps = []
bundlecaps.append('remotefilelog')
if self.includepattern:
bundlecaps.append("includepattern=" + '\0'.join(self.includepattern))
if self.excludepattern:
bundlecaps.append("excludepattern=" + '\0'.join(self.excludepattern))
opts['bundlecaps'] = ','.join(bundlecaps)
return orig(command, **opts)
def localgetbundle(orig, source, heads=None, common=None, bundlecaps=None):
if not bundlecaps:
bundlecaps = []
bundlecaps.append('remotefilelog')
return orig(source, heads=heads, common=common, bundlecaps=bundlecaps)
if hasattr(remote, '_callstream'):
wrapfunction(remote, '_callstream', remotecallstream)
2013-12-13 00:34:39 +04:00
elif hasattr(remote, 'getbundle'):
wrapfunction(remote, 'getbundle', localgetbundle)
return super(shallowrepository, self).pull(remote, *args, **kwargs)
2013-09-09 22:44:08 +04:00
2013-08-30 22:09:19 +04:00
# Wrap dirstate.status here so we can prefetch all file nodes in
# the lookup set before localrepo.status uses them.
def status(orig, match, subrepos, ignored, clean, unknown):
lookup, modified, added, removed, deleted, unknown, ignored, \
clean = orig(match, subrepos, ignored, clean, unknown)
if lookup:
files = []
parents = repo.parents()
2013-08-30 22:09:19 +04:00
for fname in lookup:
for ctx in parents:
if fname in ctx:
fnode = ctx.filenode(fname)
files.append((fname, hex(fnode)))
2013-08-30 22:09:19 +04:00
repo.fileservice.prefetch(files)
2013-08-30 22:09:19 +04:00
return (lookup, modified, added, removed, deleted, unknown, \
ignored, clean)
wrapfunction(repo.dirstate, 'status', status)
repo.__class__ = shallowrepository
repo.shallowmatch = match.always(repo.root, '')
repo.fileservice = fileserverclient.fileserverclient(repo)
repo.includepattern = repo.ui.configlist("remotefilelog", "includepattern", None)
repo.excludepattern = repo.ui.configlist("remotefilelog", "excludepattern", None)
if repo.includepattern or repo.excludepattern:
repo.shallowmatch = match.match(repo.root, '', None,
repo.includepattern, repo.excludepattern)
localpath = os.path.join(repo.sopener.vfs.base, 'data')
if not os.path.exists(localpath):
os.makedirs(localpath)