103 |
102 |
104 _setupclone(ui) |
103 _setupclone(ui) |
105 _setuplog(ui) |
104 _setuplog(ui) |
106 _setupadd(ui) |
105 _setupadd(ui) |
107 _setupdirstate(ui) |
106 _setupdirstate(ui) |
108 |
|
109 def reposetup(ui, repo): |
|
110 if not util.safehasattr(repo, 'dirstate'): |
|
111 return |
|
112 |
|
113 if 'dirstate' in repo._filecache: |
|
114 repo.dirstate.repo = repo |
|
115 |
107 |
116 def replacefilecache(cls, propname, replacement): |
108 def replacefilecache(cls, propname, replacement): |
117 """Replace a filecache property with a new class. This allows changing the |
109 """Replace a filecache property with a new class. This allows changing the |
118 cache invalidation condition.""" |
110 cache invalidation condition.""" |
119 origcls = cls |
111 origcls = cls |
198 def _setupdirstate(ui): |
190 def _setupdirstate(ui): |
199 """Modify the dirstate to prevent stat'ing excluded files, |
191 """Modify the dirstate to prevent stat'ing excluded files, |
200 and to prevent modifications to files outside the checkout. |
192 and to prevent modifications to files outside the checkout. |
201 """ |
193 """ |
202 |
194 |
203 def _dirstate(orig, repo): |
|
204 dirstate = orig(repo) |
|
205 dirstate.repo = repo |
|
206 return dirstate |
|
207 extensions.wrapfunction( |
|
208 localrepo.localrepository.dirstate, 'func', _dirstate) |
|
209 |
|
210 # The atrocity below is needed to wrap dirstate._ignore. It is a cached |
195 # The atrocity below is needed to wrap dirstate._ignore. It is a cached |
211 # property, which means normal function wrapping doesn't work. |
196 # property, which means normal function wrapping doesn't work. |
212 class ignorewrapper(object): |
197 class ignorewrapper(object): |
213 def __init__(self, orig): |
198 def __init__(self, orig): |
214 self.orig = orig |
199 self.orig = orig |
215 self.origignore = None |
200 self.origignore = None |
216 self.func = None |
201 self.func = None |
217 self.sparsematch = None |
202 self.sparsematch = None |
218 |
203 |
219 def __get__(self, obj, type=None): |
204 def __get__(self, obj, type=None): |
220 repo = obj.repo |
|
221 origignore = self.orig.__get__(obj) |
205 origignore = self.orig.__get__(obj) |
222 |
206 |
223 sparsematch = sparse.matcher(repo) |
207 sparsematch = obj._sparsematcher |
224 if sparsematch.always(): |
208 if sparsematch.always(): |
225 return origignore |
209 return origignore |
226 |
210 |
227 if self.sparsematch != sparsematch or self.origignore != origignore: |
211 if self.sparsematch != sparsematch or self.origignore != origignore: |
228 self.func = matchmod.unionmatcher([ |
212 self.func = matchmod.unionmatcher([ |
239 |
223 |
240 replacefilecache(dirstate.dirstate, '_ignore', ignorewrapper) |
224 replacefilecache(dirstate.dirstate, '_ignore', ignorewrapper) |
241 |
225 |
242 # dirstate.rebuild should not add non-matching files |
226 # dirstate.rebuild should not add non-matching files |
243 def _rebuild(orig, self, parent, allfiles, changedfiles=None): |
227 def _rebuild(orig, self, parent, allfiles, changedfiles=None): |
244 matcher = sparse.matcher(self.repo) |
228 matcher = self._sparsematcher |
245 if not matcher.always(): |
229 if not matcher.always(): |
246 allfiles = allfiles.matches(matcher) |
230 allfiles = allfiles.matches(matcher) |
247 if changedfiles: |
231 if changedfiles: |
248 changedfiles = [f for f in changedfiles if matcher(f)] |
232 changedfiles = [f for f in changedfiles if matcher(f)] |
249 |
233 |
260 editfuncs = ['normal', 'add', 'normallookup', 'copy', 'remove', 'merge'] |
244 editfuncs = ['normal', 'add', 'normallookup', 'copy', 'remove', 'merge'] |
261 hint = _('include file with `hg debugsparse --include <pattern>` or use ' + |
245 hint = _('include file with `hg debugsparse --include <pattern>` or use ' + |
262 '`hg add -s <file>` to include file directory while adding') |
246 '`hg add -s <file>` to include file directory while adding') |
263 for func in editfuncs: |
247 for func in editfuncs: |
264 def _wrapper(orig, self, *args): |
248 def _wrapper(orig, self, *args): |
265 repo = self.repo |
249 sparsematch = self._sparsematcher |
266 sparsematch = sparse.matcher(repo) |
|
267 if not sparsematch.always(): |
250 if not sparsematch.always(): |
268 for f in args: |
251 for f in args: |
269 if (f is not None and not sparsematch(f) and |
252 if (f is not None and not sparsematch(f) and |
270 f not in self): |
253 f not in self): |
271 raise error.Abort(_("cannot add '%s' - it is outside " |
254 raise error.Abort(_("cannot add '%s' - it is outside " |