Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/pathutil.py @ 49964:445b4d819e9a
pathauditor: no need to normcase the paths
The only thing normed paths are used is the key of the caching sets,
so the only change of behavior will be that the checks will be repeated
for paths that differ by case.
If anything, it seems correct for the check to be repeated, in case
that actually affects semantics, but the main reasoning is simplifying
the code and making it a bit faster.
It looks like the code originally comes from commit [081e795c60e0]:
it looks like that commit tried to get rid of the existing norming,
but presumably did this overly cautiously, preserving it for the
cache keys, even though it was pointless even then.
author | Arseniy Alekseyev <aalekseyev@janestreet.com> |
---|---|
date | Fri, 06 Jan 2023 16:27:31 +0000 |
parents | 44deb5a164dc |
children | 1b701d425c37 |
comparison
equal
deleted
inserted
replaced
49963:44deb5a164dc | 49964:445b4d819e9a |
---|---|
70 # type: (bytes, Optional[Any]) -> None | 70 # type: (bytes, Optional[Any]) -> None |
71 """Check the relative path. | 71 """Check the relative path. |
72 path may contain a pattern (e.g. foodir/**.txt)""" | 72 path may contain a pattern (e.g. foodir/**.txt)""" |
73 | 73 |
74 path = util.localpath(path) | 74 path = util.localpath(path) |
75 normpath = self.normcase(path) | 75 if path in self.audited: |
76 if normpath in self.audited: | |
77 return | 76 return |
78 # AIX ignores "/" at end of path, others raise EISDIR. | 77 # AIX ignores "/" at end of path, others raise EISDIR. |
79 if util.endswithsep(path): | 78 if util.endswithsep(path): |
80 raise error.InputError( | 79 raise error.InputError( |
81 _(b"path ends in directory separator: %s") % path | 80 _(b"path ends in directory separator: %s") % path |
107 raise error.InputError( | 106 raise error.InputError( |
108 _(b"path '%s' is inside nested repo %r") | 107 _(b"path '%s' is inside nested repo %r") |
109 % (path, pycompat.bytestr(base)) | 108 % (path, pycompat.bytestr(base)) |
110 ) | 109 ) |
111 | 110 |
112 normparts = util.splitpath(normpath) | |
113 assert len(parts) == len(normparts) | |
114 | |
115 parts.pop() | 111 parts.pop() |
116 normparts.pop() | |
117 # It's important that we check the path parts starting from the root. | 112 # It's important that we check the path parts starting from the root. |
118 # We don't want to add "foo/bar/baz" to auditeddir before checking if | 113 # We don't want to add "foo/bar/baz" to auditeddir before checking if |
119 # there's a "foo/.hg" directory. This also means we won't accidentally | 114 # there's a "foo/.hg" directory. This also means we won't accidentally |
120 # traverse a symlink into some other filesystem (which is potentially | 115 # traverse a symlink into some other filesystem (which is potentially |
121 # expensive to access). | 116 # expensive to access). |
122 for i in range(len(parts)): | 117 for i in range(len(parts)): |
123 prefix = pycompat.ossep.join(parts[: i + 1]) | 118 prefix = pycompat.ossep.join(parts[: i + 1]) |
124 normprefix = pycompat.ossep.join(normparts[: i + 1]) | 119 if prefix in self.auditeddir: |
125 if normprefix in self.auditeddir: | |
126 continue | 120 continue |
127 if self._realfs: | 121 if self._realfs: |
128 self._checkfs(prefix, path) | 122 self._checkfs(prefix, path) |
129 if self._cached: | 123 if self._cached: |
130 self.auditeddir.add(normprefix) | 124 self.auditeddir.add(prefix) |
131 | 125 |
132 if self._cached: | 126 if self._cached: |
133 self.audited.add(normpath) | 127 self.audited.add(path) |
134 | 128 |
135 def _checkfs(self, prefix, path): | 129 def _checkfs(self, prefix, path): |
136 # type: (bytes, bytes) -> None | 130 # type: (bytes, bytes) -> None |
137 """raise exception if a file system backed check fails""" | 131 """raise exception if a file system backed check fails""" |
138 curpath = os.path.join(self.root, prefix) | 132 curpath = os.path.join(self.root, prefix) |