Show More
@@ -382,7 +382,7 b' def overridewalk(orig, self, match, subr' | |||
|
382 | 382 | visit.update(f for f in copymap |
|
383 | 383 | if f not in results and matchfn(f)) |
|
384 | 384 | |
|
385 | audit = pathutil.pathauditor(self._root).check | |
|
385 | audit = pathutil.pathauditor(self._root, cached=True).check | |
|
386 | 386 | auditpass = [f for f in visit if audit(f)] |
|
387 | 387 | auditpass.sort() |
|
388 | 388 | auditfail = visit.difference(auditpass) |
@@ -3538,7 +3538,7 b' def _performrevert(repo, parents, ctx, a' | |||
|
3538 | 3538 | pass |
|
3539 | 3539 | repo.dirstate.remove(f) |
|
3540 | 3540 | |
|
3541 | audit_path = pathutil.pathauditor(repo.root) | |
|
3541 | audit_path = pathutil.pathauditor(repo.root, cached=True) | |
|
3542 | 3542 | for f in actions['forget'][0]: |
|
3543 | 3543 | if interactive: |
|
3544 | 3544 | choice = repo.ui.promptchoice( |
@@ -1153,7 +1153,7 b' class dirstate(object):' | |||
|
1153 | 1153 | # that wasn't ignored, and everything that matched was stat'ed |
|
1154 | 1154 | # and is already in results. |
|
1155 | 1155 | # The rest must thus be ignored or under a symlink. |
|
1156 | audit_path = pathutil.pathauditor(self._root) | |
|
1156 | audit_path = pathutil.pathauditor(self._root, cached=True) | |
|
1157 | 1157 | |
|
1158 | 1158 | for nf in iter(visit): |
|
1159 | 1159 | # If a stat for the same file was already added with a |
@@ -339,11 +339,11 b' class localrepository(object):' | |||
|
339 | 339 | # only used when writing this comment: basectx.match |
|
340 | 340 | self.auditor = pathutil.pathauditor(self.root, self._checknested) |
|
341 | 341 | self.nofsauditor = pathutil.pathauditor(self.root, self._checknested, |
|
342 | realfs=False) | |
|
342 | realfs=False, cached=True) | |
|
343 | 343 | self.baseui = baseui |
|
344 | 344 | self.ui = baseui.copy() |
|
345 | 345 | self.ui.copy = baseui.copy # prevent copying repo configuration |
|
346 | self.vfs = vfsmod.vfs(self.path) | |
|
346 | self.vfs = vfsmod.vfs(self.path, cacheaudited=True) | |
|
347 | 347 | if (self.ui.configbool('devel', 'all-warnings') or |
|
348 | 348 | self.ui.configbool('devel', 'check-locks')): |
|
349 | 349 | self.vfs.audit = self._getvfsward(self.vfs.audit) |
@@ -426,12 +426,13 b' class localrepository(object):' | |||
|
426 | 426 | '"sparse" extensions to access')) |
|
427 | 427 | |
|
428 | 428 | self.store = store.store( |
|
429 |
|
|
|
429 | self.requirements, self.sharedpath, | |
|
430 | lambda base: vfsmod.vfs(base, cacheaudited=True)) | |
|
430 | 431 | self.spath = self.store.path |
|
431 | 432 | self.svfs = self.store.vfs |
|
432 | 433 | self.sjoin = self.store.join |
|
433 | 434 | self.vfs.createmode = self.store.createmode |
|
434 | self.cachevfs = vfsmod.vfs(cachepath) | |
|
435 | self.cachevfs = vfsmod.vfs(cachepath, cacheaudited=True) | |
|
435 | 436 | self.cachevfs.createmode = self.store.createmode |
|
436 | 437 | if (self.ui.configbool('devel', 'all-warnings') or |
|
437 | 438 | self.ui.configbool('devel', 'check-locks')): |
@@ -33,13 +33,18 b' class pathauditor(object):' | |||
|
33 | 33 | The file system checks are only done when 'realfs' is set to True (the |
|
34 | 34 | default). They should be disable then we are auditing path for operation on |
|
35 | 35 | stored history. |
|
36 | ||
|
37 | If 'cached' is set to True, audited paths and sub-directories are cached. | |
|
38 | Be careful to not keep the cache of unmanaged directories for long because | |
|
39 | audited paths may be replaced with symlinks. | |
|
36 | 40 | ''' |
|
37 | 41 | |
|
38 | def __init__(self, root, callback=None, realfs=True): | |
|
42 | def __init__(self, root, callback=None, realfs=True, cached=False): | |
|
39 | 43 | self.audited = set() |
|
40 | 44 | self.auditeddir = set() |
|
41 | 45 | self.root = root |
|
42 | 46 | self._realfs = realfs |
|
47 | self._cached = cached | |
|
43 | 48 | self.callback = callback |
|
44 | 49 | if os.path.lexists(root) and not util.fscasesensitive(root): |
|
45 | 50 | self.normcase = util.normcase |
@@ -96,10 +101,11 b' class pathauditor(object):' | |||
|
96 | 101 | self._checkfs(prefix, path) |
|
97 | 102 | prefixes.append(normprefix) |
|
98 | 103 | |
|
99 | self.audited.add(normpath) | |
|
100 | # only add prefixes to the cache after checking everything: we don't | |
|
101 | # want to add "foo/bar/baz" before checking if there's a "foo/.hg" | |
|
102 | self.auditeddir.update(prefixes) | |
|
104 | if self._cached: | |
|
105 | self.audited.add(normpath) | |
|
106 | # only add prefixes to the cache after checking everything: we don't | |
|
107 | # want to add "foo/bar/baz" before checking if there's a "foo/.hg" | |
|
108 | self.auditeddir.update(prefixes) | |
|
103 | 109 | |
|
104 | 110 | def _checkfs(self, prefix, path): |
|
105 | 111 | """raise exception if a file system backed check fails""" |
@@ -738,7 +738,7 b' def _interestingfiles(repo, matcher):' | |||
|
738 | 738 | This is different from dirstate.status because it doesn't care about |
|
739 | 739 | whether files are modified or clean.''' |
|
740 | 740 | added, unknown, deleted, removed, forgotten = [], [], [], [], [] |
|
741 | audit_path = pathutil.pathauditor(repo.root) | |
|
741 | audit_path = pathutil.pathauditor(repo.root, cached=True) | |
|
742 | 742 | |
|
743 | 743 | ctx = repo[None] |
|
744 | 744 | dirstate = repo.dirstate |
@@ -295,8 +295,13 b' class vfs(abstractvfs):' | |||
|
295 | 295 | |
|
296 | 296 | This class is used to hide the details of COW semantics and |
|
297 | 297 | remote file access from higher level code. |
|
298 | ||
|
299 | 'cacheaudited' should be enabled only if (a) vfs object is short-lived, or | |
|
300 | (b) the base directory is managed by hg and considered sort-of append-only. | |
|
301 | See pathutil.pathauditor() for details. | |
|
298 | 302 | ''' |
|
299 |
def __init__(self, base, audit=True, expandpath=False, |
|
|
303 | def __init__(self, base, audit=True, cacheaudited=False, expandpath=False, | |
|
304 | realpath=False): | |
|
300 | 305 | if expandpath: |
|
301 | 306 | base = util.expandpath(base) |
|
302 | 307 | if realpath: |
@@ -304,7 +309,7 b' class vfs(abstractvfs):' | |||
|
304 | 309 | self.base = base |
|
305 | 310 | self._audit = audit |
|
306 | 311 | if audit: |
|
307 | self.audit = pathutil.pathauditor(self.base) | |
|
312 | self.audit = pathutil.pathauditor(self.base, cached=cacheaudited) | |
|
308 | 313 | else: |
|
309 | 314 | self.audit = (lambda path, mode=None: True) |
|
310 | 315 | self.createmode = None |
@@ -169,9 +169,9 b' and the rebase should fail (issue5628)' | |||
|
169 | 169 | $ hg up -qC 2 |
|
170 | 170 | $ hg rebase -s 2 -d 1 --config extensions.rebase= |
|
171 | 171 | rebasing 2:e73c21d6b244 "file a/poisoned" (tip) |
|
172 | saved backup bundle to * (glob) | |
|
172 | abort: path 'a/poisoned' traverses symbolic link 'a' | |
|
173 | [255] | |
|
173 | 174 | $ ls ../merge-symlink-out |
|
174 | poisoned | |
|
175 | 175 | |
|
176 | 176 | $ cd .. |
|
177 | 177 | |
@@ -211,10 +211,9 b' audited first by calculateupdates(), whe' | |||
|
211 | 211 | |
|
212 | 212 | $ hg up -qC null |
|
213 | 213 | $ hg up 1 |
|
214 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
214 | abort: path 'a/b' traverses symbolic link 'a' | |
|
215 | [255] | |
|
215 | 216 | $ ls ../update-symlink-out |
|
216 | b | |
|
217 | $ rm ../update-symlink-out/b | |
|
218 | 217 | |
|
219 | 218 | try branch update replacing directory with symlink, and its content: the |
|
220 | 219 | path 'a' is audited as a directory first, which should be audited again as |
@@ -223,9 +222,9 b' a symlink.' | |||
|
223 | 222 | $ rm -f a |
|
224 | 223 | $ hg up -qC 2 |
|
225 | 224 | $ hg up 1 |
|
226 | 2 files updated, 0 files merged, 1 files removed, 0 files unresolved | |
|
225 | abort: path 'a/b' traverses symbolic link 'a' | |
|
226 | [255] | |
|
227 | 227 | $ ls ../update-symlink-out |
|
228 | b | |
|
229 | 228 | |
|
230 | 229 | $ cd .. |
|
231 | 230 |
@@ -953,10 +953,9 b' and the merge should fail (issue5628)' | |||
|
953 | 953 | *** runcommand up -qC 2 |
|
954 | 954 | *** runcommand up -qC 1 |
|
955 | 955 | *** runcommand merge 2 |
|
956 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
957 | (branch merge, don't forget to commit) | |
|
956 | abort: path 'a/poisoned' traverses symbolic link 'a' | |
|
957 | [255] | |
|
958 | 958 | $ ls ../merge-symlink-out |
|
959 | poisoned | |
|
960 | 959 | |
|
961 | 960 | cache of repo.auditor should be discarded, so matcher would never traverse |
|
962 | 961 | symlinks: |
@@ -980,7 +979,8 b' symlinks:' | |||
|
980 | 979 | *** runcommand up -qC 0 |
|
981 | 980 | *** runcommand up -qC 1 |
|
982 | 981 | *** runcommand files a/poisoned |
|
983 | [1] | |
|
982 | abort: path 'a/poisoned' traverses symbolic link 'a' | |
|
983 | [255] | |
|
984 | 984 | |
|
985 | 985 | $ cd .. |
|
986 | 986 |
General Comments 0
You need to be logged in to leave comments.
Login now