205 dirs.add(dirname) |
201 dirs.add(dirname) |
206 sparse.updateconfig(repo, opts, include=list(dirs)) |
202 sparse.updateconfig(repo, opts, include=list(dirs)) |
207 return orig(ui, repo, *pats, **opts) |
203 return orig(ui, repo, *pats, **opts) |
208 |
204 |
209 extensions.wrapcommand(commands.table, b'add', _add) |
205 extensions.wrapcommand(commands.table, b'add', _add) |
210 |
|
211 |
|
212 def _setupdirstate(ui): |
|
213 """Modify the dirstate to prevent stat'ing excluded files, |
|
214 and to prevent modifications to files outside the checkout. |
|
215 """ |
|
216 |
|
217 def walk(orig, self, match, subrepos, unknown, ignored, full=True): |
|
218 # hack to not exclude explicitly-specified paths so that they can |
|
219 # be warned later on e.g. dirstate.add() |
|
220 em = matchmod.exact(match.files()) |
|
221 sm = matchmod.unionmatcher([self._sparsematcher, em]) |
|
222 match = matchmod.intersectmatchers(match, sm) |
|
223 return orig(self, match, subrepos, unknown, ignored, full) |
|
224 |
|
225 extensions.wrapfunction(dirstate.dirstate, b'walk', walk) |
|
226 |
|
227 # dirstate.rebuild should not add non-matching files |
|
228 def _rebuild(orig, self, parent, allfiles, changedfiles=None): |
|
229 matcher = self._sparsematcher |
|
230 if not matcher.always(): |
|
231 allfiles = [f for f in allfiles if matcher(f)] |
|
232 if changedfiles: |
|
233 changedfiles = [f for f in changedfiles if matcher(f)] |
|
234 |
|
235 if changedfiles is not None: |
|
236 # In _rebuild, these files will be deleted from the dirstate |
|
237 # when they are not found to be in allfiles |
|
238 dirstatefilestoremove = {f for f in self if not matcher(f)} |
|
239 changedfiles = dirstatefilestoremove.union(changedfiles) |
|
240 |
|
241 return orig(self, parent, allfiles, changedfiles) |
|
242 |
|
243 extensions.wrapfunction(dirstate.dirstate, b'rebuild', _rebuild) |
|
244 |
|
245 # Prevent adding files that are outside the sparse checkout |
|
246 editfuncs = [ |
|
247 b'set_tracked', |
|
248 b'set_untracked', |
|
249 b'copy', |
|
250 ] |
|
251 hint = _( |
|
252 b'include file with `hg debugsparse --include <pattern>` or use ' |
|
253 + b'`hg add -s <file>` to include file directory while adding' |
|
254 ) |
|
255 for func in editfuncs: |
|
256 |
|
257 def _wrapper(orig, self, *args, **kwargs): |
|
258 sparsematch = self._sparsematcher |
|
259 if not sparsematch.always(): |
|
260 for f in args: |
|
261 if f is not None and not sparsematch(f) and f not in self: |
|
262 raise error.Abort( |
|
263 _( |
|
264 b"cannot add '%s' - it is outside " |
|
265 b"the sparse checkout" |
|
266 ) |
|
267 % f, |
|
268 hint=hint, |
|
269 ) |
|
270 return orig(self, *args, **kwargs) |
|
271 |
|
272 extensions.wrapfunction(dirstate.dirstate, func, _wrapper) |
|
273 |
206 |
274 |
207 |
275 @command( |
208 @command( |
276 b'debugsparse', |
209 b'debugsparse', |
277 [ |
210 [ |
396 ) |
329 ) |
397 count = sum([updateconfig, bool(action)]) |
330 count = sum([updateconfig, bool(action)]) |
398 if count > 1: |
331 if count > 1: |
399 raise error.Abort(_(b"too many flags specified")) |
332 raise error.Abort(_(b"too many flags specified")) |
400 |
333 |
|
334 # enable sparse on repo even if the requirements is missing. |
|
335 repo._has_sparse = True |
|
336 |
401 if count == 0: |
337 if count == 0: |
402 if repo.vfs.exists(b'sparse'): |
338 if repo.vfs.exists(b'sparse'): |
403 ui.status(repo.vfs.read(b"sparse") + b"\n") |
339 ui.status(repo.vfs.read(b"sparse") + b"\n") |
404 temporaryincludes = sparse.readtemporaryincludes(repo) |
340 temporaryincludes = sparse.readtemporaryincludes(repo) |
405 if temporaryincludes: |
341 if temporaryincludes: |