Mercurial > hg
comparison mercurial/pathutil.py @ 49890:1b701d425c37
merge: short-circuit the _checkfs loop upon getting ENOENT
This reduces the number of [lstat] calls when updating from rev(-1) to
a rev with lots of files by a factor of several: for path foo/bar/baz/quux.txt
without this patch we're lstatting:
foo
foo/bar
foo/bar/baz
foo/bar/baz/quux.txt
and with this patch:
foo
foo/bar/baz/quux.txt
author | Arseniy Alekseyev <aalekseyev@janestreet.com> |
---|---|
date | Wed, 04 Jan 2023 16:48:32 +0000 |
parents | 445b4d819e9a |
children | 76d1e9f229fe |
comparison
equal
deleted
inserted
replaced
49889:3aa8e569478a | 49890:1b701d425c37 |
---|---|
117 for i in range(len(parts)): | 117 for i in range(len(parts)): |
118 prefix = pycompat.ossep.join(parts[: i + 1]) | 118 prefix = pycompat.ossep.join(parts[: i + 1]) |
119 if prefix in self.auditeddir: | 119 if prefix in self.auditeddir: |
120 continue | 120 continue |
121 if self._realfs: | 121 if self._realfs: |
122 self._checkfs(prefix, path) | 122 res = self._checkfs_exists(prefix, path) |
123 if self._cached: | 123 if self._cached: |
124 self.auditeddir.add(prefix) | 124 self.auditeddir.add(prefix) |
125 if not res: | |
126 break | |
125 | 127 |
126 if self._cached: | 128 if self._cached: |
127 self.audited.add(path) | 129 self.audited.add(path) |
128 | 130 |
129 def _checkfs(self, prefix, path): | 131 def _checkfs_exists(self, prefix, path): |
130 # type: (bytes, bytes) -> None | 132 # type: (bytes, bytes) -> bool |
131 """raise exception if a file system backed check fails""" | 133 """raise exception if a file system backed check fails. |
134 | |
135 Return a bool that indicates that the directory (or file) exists.""" | |
132 curpath = os.path.join(self.root, prefix) | 136 curpath = os.path.join(self.root, prefix) |
133 try: | 137 try: |
134 st = os.lstat(curpath) | 138 st = os.lstat(curpath) |
135 except OSError as err: | 139 except OSError as err: |
140 if err.errno == errno.ENOENT: | |
141 return False | |
136 # EINVAL can be raised as invalid path syntax under win32. | 142 # EINVAL can be raised as invalid path syntax under win32. |
137 # They must be ignored for patterns can be checked too. | 143 # They must be ignored for patterns can be checked too. |
138 if err.errno not in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL): | 144 if err.errno not in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL): |
139 raise | 145 raise |
140 else: | 146 else: |
148 os.path.join(curpath, b'.hg') | 154 os.path.join(curpath, b'.hg') |
149 ): | 155 ): |
150 if not self.callback or not self.callback(curpath): | 156 if not self.callback or not self.callback(curpath): |
151 msg = _(b"path '%s' is inside nested repo %r") | 157 msg = _(b"path '%s' is inside nested repo %r") |
152 raise error.Abort(msg % (path, pycompat.bytestr(prefix))) | 158 raise error.Abort(msg % (path, pycompat.bytestr(prefix))) |
159 return True | |
153 | 160 |
154 def check(self, path): | 161 def check(self, path): |
155 # type: (bytes) -> bool | 162 # type: (bytes) -> bool |
156 try: | 163 try: |
157 self(path) | 164 self(path) |