##// END OF EJS Templates
narrow: only wrap dirstate functions once, instead of per-reposetup...
Kyle Lippincott -
r38142:1cba4974 default
parent child Browse files
Show More
@@ -28,7 +28,6 b' from . import ('
28 narrowchangegroup,
28 narrowchangegroup,
29 narrowcommands,
29 narrowcommands,
30 narrowcopies,
30 narrowcopies,
31 narrowdirstate,
32 narrowpatch,
31 narrowpatch,
33 narrowrepo,
32 narrowrepo,
34 narrowrevlog,
33 narrowrevlog,
@@ -72,10 +71,9 b' def reposetup(ui, repo):'
72 if not repo.local():
71 if not repo.local():
73 return
72 return
74
73
75 narrowrepo.wraprepo(repo)
76 if changegroup.NARROW_REQUIREMENT in repo.requirements:
74 if changegroup.NARROW_REQUIREMENT in repo.requirements:
75 narrowrepo.wraprepo(repo)
77 narrowcopies.setup(repo)
76 narrowcopies.setup(repo)
78 narrowdirstate.setup(repo)
79 narrowpatch.setup(repo)
77 narrowpatch.setup(repo)
80 narrowwirepeer.reposetup(repo)
78 narrowwirepeer.reposetup(repo)
81
79
@@ -9,74 +9,91 b' from __future__ import absolute_import'
9
9
10 from mercurial.i18n import _
10 from mercurial.i18n import _
11 from mercurial import (
11 from mercurial import (
12 dirstate,
13 error,
12 error,
14 extensions,
15 match as matchmod,
13 match as matchmod,
16 narrowspec,
14 narrowspec,
17 util as hgutil,
15 util as hgutil,
18 )
16 )
19
17
20 def setup(repo):
18 def wrapdirstate(repo, dirstate):
21 """Add narrow spec dirstate ignore, block changes outside narrow spec."""
19 """Add narrow spec dirstate ignore, block changes outside narrow spec."""
22
20
23 def walk(orig, self, match, subrepos, unknown, ignored, full=True,
21 def _editfunc(fn):
24 narrowonly=True):
22 def _wrapper(self, *args):
25 if narrowonly:
26 # hack to not exclude explicitly-specified paths so that they can
27 # be warned later on e.g. dirstate.add()
28 em = matchmod.exact(match._root, match._cwd, match.files())
29 nm = matchmod.unionmatcher([repo.narrowmatch(), em])
30 match = matchmod.intersectmatchers(match, nm)
31 return orig(self, match, subrepos, unknown, ignored, full)
32
33 extensions.wrapfunction(dirstate.dirstate, 'walk', walk)
34
35 # Prevent adding files that are outside the sparse checkout
36 editfuncs = ['normal', 'add', 'normallookup', 'copy', 'remove', 'merge']
37 for func in editfuncs:
38 def _wrapper(orig, self, *args):
39 dirstate = repo.dirstate
23 dirstate = repo.dirstate
40 narrowmatch = repo.narrowmatch()
24 narrowmatch = repo.narrowmatch()
41 for f in args:
25 for f in args:
42 if f is not None and not narrowmatch(f) and f not in dirstate:
26 if f is not None and not narrowmatch(f) and f not in dirstate:
43 raise error.Abort(_("cannot track '%s' - it is outside " +
27 raise error.Abort(_("cannot track '%s' - it is outside " +
44 "the narrow clone") % f)
28 "the narrow clone") % f)
45 return orig(self, *args)
29 return fn(self, *args)
46 extensions.wrapfunction(dirstate.dirstate, func, _wrapper)
30 return _wrapper
47
48 def filterrebuild(orig, self, parent, allfiles, changedfiles=None):
49 if changedfiles is None:
50 # Rebuilding entire dirstate, let's filter allfiles to match the
51 # narrowspec.
52 allfiles = [f for f in allfiles if repo.narrowmatch()(f)]
53 orig(self, parent, allfiles, changedfiles)
54
55 extensions.wrapfunction(dirstate.dirstate, 'rebuild', filterrebuild)
56
31
57 def _narrowbackupname(backupname):
32 def _narrowbackupname(backupname):
58 assert 'dirstate' in backupname
33 assert 'dirstate' in backupname
59 return backupname.replace('dirstate', narrowspec.FILENAME)
34 return backupname.replace('dirstate', narrowspec.FILENAME)
60
35
61 def restorebackup(orig, self, tr, backupname):
36 class narrowdirstate(dirstate.__class__):
62 self._opener.rename(_narrowbackupname(backupname), narrowspec.FILENAME,
37 def walk(self, match, subrepos, unknown, ignored, full=True,
63 checkambig=True)
38 narrowonly=True):
64 orig(self, tr, backupname)
39 if narrowonly:
40 # hack to not exclude explicitly-specified paths so that they
41 # can be warned later on e.g. dirstate.add()
42 em = matchmod.exact(match._root, match._cwd, match.files())
43 nm = matchmod.unionmatcher([repo.narrowmatch(), em])
44 match = matchmod.intersectmatchers(match, nm)
45 return super(narrowdirstate, self).walk(match, subrepos, unknown,
46 ignored, full)
65
47
66 extensions.wrapfunction(dirstate.dirstate, 'restorebackup', restorebackup)
48 # Prevent adding/editing/copying/deleting files that are outside the
49 # sparse checkout
50 @_editfunc
51 def normal(self, *args):
52 return super(narrowdirstate, self).normal(*args)
67
53
68 def savebackup(orig, self, tr, backupname):
54 @_editfunc
69 orig(self, tr, backupname)
55 def add(self, *args):
56 return super(narrowdirstate, self).add(*args)
57
58 @_editfunc
59 def normallookup(self, *args):
60 return super(narrowdirstate, self).normallookup(*args)
61
62 @_editfunc
63 def copy(self, *args):
64 return super(narrowdirstate, self).copy(*args)
70
65
71 narrowbackupname = _narrowbackupname(backupname)
66 @_editfunc
72 self._opener.tryunlink(narrowbackupname)
67 def remove(self, *args):
73 hgutil.copyfile(self._opener.join(narrowspec.FILENAME),
68 return super(narrowdirstate, self).remove(*args)
74 self._opener.join(narrowbackupname), hardlink=True)
69
70 @_editfunc
71 def merge(self, *args):
72 return super(narrowdirstate, self).merge(*args)
73
74 def rebuild(self, parent, allfiles, changedfiles=None):
75 if changedfiles is None:
76 # Rebuilding entire dirstate, let's filter allfiles to match the
77 # narrowspec.
78 allfiles = [f for f in allfiles if repo.narrowmatch()(f)]
79 super(narrowdirstate, self).rebuild(parent, allfiles, changedfiles)
75
80
76 extensions.wrapfunction(dirstate.dirstate, 'savebackup', savebackup)
81 def restorebackup(self, tr, backupname):
82 self._opener.rename(_narrowbackupname(backupname),
83 narrowspec.FILENAME, checkambig=True)
84 super(narrowdirstate, self).restorebackup(tr, backupname)
85
86 def savebackup(self, tr, backupname):
87 super(narrowdirstate, self).savebackup(tr, backupname)
77
88
78 def clearbackup(orig, self, tr, backupname):
89 narrowbackupname = _narrowbackupname(backupname)
79 orig(self, tr, backupname)
90 self._opener.tryunlink(narrowbackupname)
80 self._opener.unlink(_narrowbackupname(backupname))
91 hgutil.copyfile(self._opener.join(narrowspec.FILENAME),
92 self._opener.join(narrowbackupname), hardlink=True)
81
93
82 extensions.wrapfunction(dirstate.dirstate, 'clearbackup', clearbackup)
94 def clearbackup(self, tr, backupname):
95 super(narrowdirstate, self).clearbackup(tr, backupname)
96 self._opener.unlink(_narrowbackupname(backupname))
97
98 dirstate.__class__ = narrowdirstate
99 return dirstate
@@ -15,6 +15,7 b' from mercurial import ('
15 )
15 )
16
16
17 from . import (
17 from . import (
18 narrowdirstate,
18 narrowrevlog,
19 narrowrevlog,
19 )
20 )
20
21
@@ -62,4 +63,8 b' def wraprepo(repo):'
62 return scmutil.status(modified, added, removed, deleted, unknown,
63 return scmutil.status(modified, added, removed, deleted, unknown,
63 ignored, clean)
64 ignored, clean)
64
65
66 def _makedirstate(self):
67 dirstate = super(narrowrepository, self)._makedirstate()
68 return narrowdirstate.wrapdirstate(self, dirstate)
69
65 repo.__class__ = narrowrepository
70 repo.__class__ = narrowrepository
@@ -778,6 +778,9 b' class localrepository(object):'
778
778
779 @repofilecache('dirstate')
779 @repofilecache('dirstate')
780 def dirstate(self):
780 def dirstate(self):
781 return self._makedirstate()
782
783 def _makedirstate(self):
781 sparsematchfn = lambda: sparse.matcher(self)
784 sparsematchfn = lambda: sparse.matcher(self)
782
785
783 return dirstate.dirstate(self.vfs, self.ui, self.root,
786 return dirstate.dirstate(self.vfs, self.ui, self.root,
@@ -72,29 +72,31 b' have this method available in narrowhg p'
72 > for f in repo[b'.'].manifest().walk(added):
72 > for f in repo[b'.'].manifest().walk(added):
73 > repo.dirstate.normallookup(f)
73 > repo.dirstate.normallookup(f)
74 >
74 >
75 > def makeds(ui, repo):
75 > def wrapds(ui, repo, ds):
76 > def wrapds(orig, self):
76 > class expandingdirstate(ds.__class__):
77 > ds = orig(self)
77 > @hgutil.propertycache
78 > class expandingdirstate(ds.__class__):
78 > def _map(self):
79 > @hgutil.propertycache
79 > ret = super(expandingdirstate, self)._map
80 > def _map(self):
80 > with repo.wlock(), repo.lock(), repo.transaction(
81 > ret = super(expandingdirstate, self)._map
81 > b'expandnarrowspec'):
82 > with repo.wlock(), repo.lock(), repo.transaction(
82 > expandnarrowspec(ui, repo,
83 > b'expandnarrowspec'):
83 > encoding.environ.get(b'DIRSTATEINCLUDES'))
84 > expandnarrowspec(ui, repo,
84 > return ret
85 > encoding.environ.get(b'DIRSTATEINCLUDES'))
85 > ds.__class__ = expandingdirstate
86 > return ret
86 > return ds
87 > ds.__class__ = expandingdirstate
88 > return ds
89 > return wrapds
90 >
87 >
91 > def reposetup(ui, repo):
88 > def reposetup(ui, repo):
92 > extensions.wrapfilecache(localrepo.localrepository, b'dirstate',
89 > class expandingrepo(repo.__class__):
93 > makeds(ui, repo))
90 > def _makedirstate(self):
94 > def overridepatch(orig, *args, **kwargs):
91 > dirstate = super(expandingrepo, self)._makedirstate()
92 > return wrapds(ui, repo, dirstate)
93 > repo.__class__ = expandingrepo
94 >
95 > def extsetup(unused_ui):
96 > def overridepatch(orig, ui, repo, *args, **kwargs):
95 > with repo.wlock():
97 > with repo.wlock():
96 > expandnarrowspec(ui, repo, encoding.environ.get(b'PATCHINCLUDES'))
98 > expandnarrowspec(ui, repo, encoding.environ.get(b'PATCHINCLUDES'))
97 > return orig(*args, **kwargs)
99 > return orig(ui, repo, *args, **kwargs)
98 >
100 >
99 > extensions.wrapfunction(patch, b'patch', overridepatch)
101 > extensions.wrapfunction(patch, b'patch', overridepatch)
100 > EOF
102 > EOF
General Comments 0
You need to be logged in to leave comments. Login now