79 while parts: |
79 while parts: |
80 prefix = os.sep.join(parts) |
80 prefix = os.sep.join(parts) |
81 normprefix = os.sep.join(normparts) |
81 normprefix = os.sep.join(normparts) |
82 if normprefix in self.auditeddir: |
82 if normprefix in self.auditeddir: |
83 break |
83 break |
84 curpath = os.path.join(self.root, prefix) |
84 self._checkfs(prefix, path) |
85 try: |
|
86 st = os.lstat(curpath) |
|
87 except OSError as err: |
|
88 # EINVAL can be raised as invalid path syntax under win32. |
|
89 # They must be ignored for patterns can be checked too. |
|
90 if err.errno not in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL): |
|
91 raise |
|
92 else: |
|
93 if stat.S_ISLNK(st.st_mode): |
|
94 raise error.Abort( |
|
95 _('path %r traverses symbolic link %r') |
|
96 % (path, prefix)) |
|
97 elif (stat.S_ISDIR(st.st_mode) and |
|
98 os.path.isdir(os.path.join(curpath, '.hg'))): |
|
99 if not self.callback or not self.callback(curpath): |
|
100 raise error.Abort(_("path '%s' is inside nested " |
|
101 "repo %r") |
|
102 % (path, prefix)) |
|
103 prefixes.append(normprefix) |
85 prefixes.append(normprefix) |
104 parts.pop() |
86 parts.pop() |
105 normparts.pop() |
87 normparts.pop() |
106 |
88 |
107 self.audited.add(normpath) |
89 self.audited.add(normpath) |
108 # only add prefixes to the cache after checking everything: we don't |
90 # only add prefixes to the cache after checking everything: we don't |
109 # want to add "foo/bar/baz" before checking if there's a "foo/.hg" |
91 # want to add "foo/bar/baz" before checking if there's a "foo/.hg" |
110 self.auditeddir.update(prefixes) |
92 self.auditeddir.update(prefixes) |
|
93 |
|
94 def _checkfs(self, prefix, path): |
|
95 """raise exception if a file system backed check fails""" |
|
96 curpath = os.path.join(self.root, prefix) |
|
97 try: |
|
98 st = os.lstat(curpath) |
|
99 except OSError as err: |
|
100 # EINVAL can be raised as invalid path syntax under win32. |
|
101 # They must be ignored for patterns can be checked too. |
|
102 if err.errno not in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL): |
|
103 raise |
|
104 else: |
|
105 if stat.S_ISLNK(st.st_mode): |
|
106 raise error.Abort( |
|
107 _('path %r traverses symbolic link %r') |
|
108 % (path, prefix)) |
|
109 elif (stat.S_ISDIR(st.st_mode) and |
|
110 os.path.isdir(os.path.join(curpath, '.hg'))): |
|
111 if not self.callback or not self.callback(curpath): |
|
112 raise error.Abort(_("path '%s' is inside nested " |
|
113 "repo %r") % (path, prefix)) |
111 |
114 |
112 def check(self, path): |
115 def check(self, path): |
113 try: |
116 try: |
114 self(path) |
117 self(path) |
115 return True |
118 return True |