##// END OF EJS Templates
pathauditor: disable cache of audited paths by default (issue5628)...
Yuya Nishihara -
r33705:20bac46f stable
parent child Browse files
Show More
@@ -394,7 +394,7 b' def overridewalk(orig, self, match, subr'
394 visit.update(f for f in copymap
394 visit.update(f for f in copymap
395 if f not in results and matchfn(f))
395 if f not in results and matchfn(f))
396
396
397 audit = pathutil.pathauditor(self._root).check
397 audit = pathutil.pathauditor(self._root, cached=True).check
398 auditpass = [f for f in visit if audit(f)]
398 auditpass = [f for f in visit if audit(f)]
399 auditpass.sort()
399 auditpass.sort()
400 auditfail = visit.difference(auditpass)
400 auditfail = visit.difference(auditpass)
@@ -3218,7 +3218,7 b' def _performrevert(repo, parents, ctx, a'
3218 pass
3218 pass
3219 repo.dirstate.remove(f)
3219 repo.dirstate.remove(f)
3220
3220
3221 audit_path = pathutil.pathauditor(repo.root)
3221 audit_path = pathutil.pathauditor(repo.root, cached=True)
3222 for f in actions['forget'][0]:
3222 for f in actions['forget'][0]:
3223 if interactive:
3223 if interactive:
3224 choice = repo.ui.promptchoice(
3224 choice = repo.ui.promptchoice(
@@ -1089,7 +1089,7 b' class dirstate(object):'
1089 # that wasn't ignored, and everything that matched was stat'ed
1089 # that wasn't ignored, and everything that matched was stat'ed
1090 # and is already in results.
1090 # and is already in results.
1091 # The rest must thus be ignored or under a symlink.
1091 # The rest must thus be ignored or under a symlink.
1092 audit_path = pathutil.pathauditor(self._root)
1092 audit_path = pathutil.pathauditor(self._root, cached=True)
1093
1093
1094 for nf in iter(visit):
1094 for nf in iter(visit):
1095 # If a stat for the same file was already added with a
1095 # If a stat for the same file was already added with a
@@ -273,8 +273,8 b' class localrepository(object):'
273 self.origroot = path
273 self.origroot = path
274 self.auditor = pathutil.pathauditor(self.root, self._checknested)
274 self.auditor = pathutil.pathauditor(self.root, self._checknested)
275 self.nofsauditor = pathutil.pathauditor(self.root, self._checknested,
275 self.nofsauditor = pathutil.pathauditor(self.root, self._checknested,
276 realfs=False)
276 realfs=False, cached=True)
277 self.vfs = vfsmod.vfs(self.path)
277 self.vfs = vfsmod.vfs(self.path, cacheaudited=True)
278 self.baseui = baseui
278 self.baseui = baseui
279 self.ui = baseui.copy()
279 self.ui = baseui.copy()
280 self.ui.copy = baseui.copy # prevent copying repo configuration
280 self.ui.copy = baseui.copy # prevent copying repo configuration
@@ -350,7 +350,8 b' class localrepository(object):'
350 raise
350 raise
351
351
352 self.store = store.store(
352 self.store = store.store(
353 self.requirements, self.sharedpath, vfsmod.vfs)
353 self.requirements, self.sharedpath,
354 lambda base: vfsmod.vfs(base, cacheaudited=True))
354 self.spath = self.store.path
355 self.spath = self.store.path
355 self.svfs = self.store.vfs
356 self.svfs = self.store.vfs
356 self.sjoin = self.store.join
357 self.sjoin = self.store.join
@@ -33,13 +33,18 b' class pathauditor(object):'
33 The file system checks are only done when 'realfs' is set to True (the
33 The file system checks are only done when 'realfs' is set to True (the
34 default). They should be disable then we are auditing path for operation on
34 default). They should be disable then we are auditing path for operation on
35 stored history.
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 self.audited = set()
43 self.audited = set()
40 self.auditeddir = set()
44 self.auditeddir = set()
41 self.root = root
45 self.root = root
42 self._realfs = realfs
46 self._realfs = realfs
47 self._cached = cached
43 self.callback = callback
48 self.callback = callback
44 if os.path.lexists(root) and not util.fscasesensitive(root):
49 if os.path.lexists(root) and not util.fscasesensitive(root):
45 self.normcase = util.normcase
50 self.normcase = util.normcase
@@ -96,10 +101,11 b' class pathauditor(object):'
96 self._checkfs(prefix, path)
101 self._checkfs(prefix, path)
97 prefixes.append(normprefix)
102 prefixes.append(normprefix)
98
103
99 self.audited.add(normpath)
104 if self._cached:
100 # only add prefixes to the cache after checking everything: we don't
105 self.audited.add(normpath)
101 # want to add "foo/bar/baz" before checking if there's a "foo/.hg"
106 # only add prefixes to the cache after checking everything: we don't
102 self.auditeddir.update(prefixes)
107 # want to add "foo/bar/baz" before checking if there's a "foo/.hg"
108 self.auditeddir.update(prefixes)
103
109
104 def _checkfs(self, prefix, path):
110 def _checkfs(self, prefix, path):
105 """raise exception if a file system backed check fails"""
111 """raise exception if a file system backed check fails"""
@@ -667,7 +667,7 b' def _interestingfiles(repo, matcher):'
667 This is different from dirstate.status because it doesn't care about
667 This is different from dirstate.status because it doesn't care about
668 whether files are modified or clean.'''
668 whether files are modified or clean.'''
669 added, unknown, deleted, removed, forgotten = [], [], [], [], []
669 added, unknown, deleted, removed, forgotten = [], [], [], [], []
670 audit_path = pathutil.pathauditor(repo.root)
670 audit_path = pathutil.pathauditor(repo.root, cached=True)
671
671
672 ctx = repo[None]
672 ctx = repo[None]
673 dirstate = repo.dirstate
673 dirstate = repo.dirstate
@@ -276,13 +276,19 b' class vfs(abstractvfs):'
276
276
277 This class is used to hide the details of COW semantics and
277 This class is used to hide the details of COW semantics and
278 remote file access from higher level code.
278 remote file access from higher level code.
279
280 'cacheaudited' should be enabled only if (a) vfs object is short-lived, or
281 (b) the base directory is managed by hg and considered sort-of append-only.
282 See pathutil.pathauditor() for details.
279 '''
283 '''
280 def __init__(self, base, audit=True, expandpath=False, realpath=False):
284 def __init__(self, base, audit=True, cacheaudited=False, expandpath=False,
285 realpath=False):
281 if expandpath:
286 if expandpath:
282 base = util.expandpath(base)
287 base = util.expandpath(base)
283 if realpath:
288 if realpath:
284 base = os.path.realpath(base)
289 base = os.path.realpath(base)
285 self.base = base
290 self.base = base
291 self._cacheaudited = cacheaudited
286 self.mustaudit = audit
292 self.mustaudit = audit
287 self.createmode = None
293 self.createmode = None
288 self._trustnlink = None
294 self._trustnlink = None
@@ -295,7 +301,8 b' class vfs(abstractvfs):'
295 def mustaudit(self, onoff):
301 def mustaudit(self, onoff):
296 self._audit = onoff
302 self._audit = onoff
297 if onoff:
303 if onoff:
298 self.audit = pathutil.pathauditor(self.base)
304 self.audit = pathutil.pathauditor(
305 self.base, cached=self._cacheaudited)
299 else:
306 else:
300 self.audit = util.always
307 self.audit = util.always
301
308
@@ -169,9 +169,9 b' and the rebase should fail (issue5628)'
169 $ hg up -qC 2
169 $ hg up -qC 2
170 $ hg rebase -s 2 -d 1 --config extensions.rebase=
170 $ hg rebase -s 2 -d 1 --config extensions.rebase=
171 rebasing 2:e73c21d6b244 "file a/poisoned" (tip)
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 $ ls ../merge-symlink-out
174 $ ls ../merge-symlink-out
174 poisoned
175
175
176 $ cd ..
176 $ cd ..
177
177
@@ -211,10 +211,9 b' audited first by calculateupdates(), whe'
211
211
212 $ hg up -qC null
212 $ hg up -qC null
213 $ hg up 1
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 $ ls ../update-symlink-out
216 $ ls ../update-symlink-out
216 b
217 $ rm ../update-symlink-out/b
218
217
219 try branch update replacing directory with symlink, and its content: the
218 try branch update replacing directory with symlink, and its content: the
220 path 'a' is audited as a directory first, which should be audited again as
219 path 'a' is audited as a directory first, which should be audited again as
@@ -223,9 +222,9 b' a symlink.'
223 $ rm -f a
222 $ rm -f a
224 $ hg up -qC 2
223 $ hg up -qC 2
225 $ hg up 1
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 $ ls ../update-symlink-out
227 $ ls ../update-symlink-out
228 b
229
228
230 $ cd ..
229 $ cd ..
231
230
@@ -956,10 +956,9 b' and the merge should fail (issue5628)'
956 *** runcommand up -qC 2
956 *** runcommand up -qC 2
957 *** runcommand up -qC 1
957 *** runcommand up -qC 1
958 *** runcommand merge 2
958 *** runcommand merge 2
959 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
959 abort: path 'a/poisoned' traverses symbolic link 'a'
960 (branch merge, don't forget to commit)
960 [255]
961 $ ls ../merge-symlink-out
961 $ ls ../merge-symlink-out
962 poisoned
963
962
964 cache of repo.auditor should be discarded, so matcher would never traverse
963 cache of repo.auditor should be discarded, so matcher would never traverse
965 symlinks:
964 symlinks:
@@ -983,7 +982,8 b' symlinks:'
983 *** runcommand up -qC 0
982 *** runcommand up -qC 0
984 *** runcommand up -qC 1
983 *** runcommand up -qC 1
985 *** runcommand files a/poisoned
984 *** runcommand files a/poisoned
986 [1]
985 abort: path 'a/poisoned' traverses symbolic link 'a'
986 [255]
987
987
988 $ cd ..
988 $ cd ..
989
989
General Comments 0
You need to be logged in to leave comments. Login now