Mercurial > public > mercurial-scm > hg
comparison mercurial/vfs.py @ 47809:98c3fa6a3ac2 stable
vfs: always use / as file separator (issue6546)
Various part of vfs already enforce `/` usage and using `\` confuse the encoded
vfs. So we simply use `/` all the time.
Differential Revision: https://phab.mercurial-scm.org/D11260
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Thu, 05 Aug 2021 12:53:44 +0200 |
parents | 9ab54aa56982 |
children | 6000f5b25c9b |
comparison
equal
deleted
inserted
replaced
47808:23921bc857b5 | 47809:98c3fa6a3ac2 |
---|---|
48 | 48 |
49 | 49 |
50 class abstractvfs(object): | 50 class abstractvfs(object): |
51 """Abstract base class; cannot be instantiated""" | 51 """Abstract base class; cannot be instantiated""" |
52 | 52 |
53 # default directory separator for vfs | |
54 # | |
55 # Other vfs code always use `/` and this works fine because python file API | |
56 # abstract the use of `/` and make it work transparently. For consistency | |
57 # vfs will always use `/` when joining. This avoid some confusion in | |
58 # encoded vfs (see issue6546) | |
59 _dir_sep = b'/' | |
60 | |
53 def __init__(self, *args, **kwargs): | 61 def __init__(self, *args, **kwargs): |
54 '''Prevent instantiation; don't call this from subclasses.''' | 62 '''Prevent instantiation; don't call this from subclasses.''' |
55 raise NotImplementedError('attempted instantiating ' + str(type(self))) | 63 raise NotImplementedError('attempted instantiating ' + str(type(self))) |
56 | 64 |
57 def __call__(self, path, mode=b'rb', **kwargs): | 65 def __call__(self, path, mode=b'rb', **kwargs): |
150 except OSError: | 158 except OSError: |
151 return False | 159 return False |
152 mode = st.st_mode | 160 mode = st.st_mode |
153 return stat.S_ISREG(mode) or stat.S_ISLNK(mode) | 161 return stat.S_ISREG(mode) or stat.S_ISLNK(mode) |
154 | 162 |
163 def _join(self, *paths): | |
164 root_idx = 0 | |
165 for idx, p in enumerate(paths): | |
166 if os.path.isabs(p) or p.startswith(self._dir_sep): | |
167 root_idx = idx | |
168 if root_idx != 0: | |
169 paths = paths[root_idx:] | |
170 paths = [p for p in paths if p] | |
171 return self._dir_sep.join(paths) | |
172 | |
155 def reljoin(self, *paths): | 173 def reljoin(self, *paths): |
156 """join various elements of a path together (as os.path.join would do) | 174 """join various elements of a path together (as os.path.join would do) |
157 | 175 |
158 The vfs base is not injected so that path stay relative. This exists | 176 The vfs base is not injected so that path stay relative. This exists |
159 to allow handling of strange encoding if needed.""" | 177 to allow handling of strange encoding if needed.""" |
160 return os.path.join(*paths) | 178 return self._join(*paths) |
161 | 179 |
162 def split(self, path): | 180 def split(self, path): |
163 """split top-most element of a path (as os.path.split would do) | 181 """split top-most element of a path (as os.path.split would do) |
164 | 182 |
165 This exists to allow handling of strange encoding if needed.""" | 183 This exists to allow handling of strange encoding if needed.""" |
526 else: | 544 else: |
527 self.write(dst, src) | 545 self.write(dst, src) |
528 | 546 |
529 def join(self, path, *insidef): | 547 def join(self, path, *insidef): |
530 if path: | 548 if path: |
531 return os.path.join(self.base, path, *insidef) | 549 parts = [self.base, path] |
550 parts.extend(insidef) | |
551 return self._join(*parts) | |
532 else: | 552 else: |
533 return self.base | 553 return self.base |
534 | 554 |
535 | 555 |
536 opener = vfs | 556 opener = vfs |