diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/buildstream/storage/_filebaseddirectory.py | 39 |
1 files changed, 31 insertions, 8 deletions
diff --git a/src/buildstream/storage/_filebaseddirectory.py b/src/buildstream/storage/_filebaseddirectory.py index 07efa4598..f14b3de1d 100644 --- a/src/buildstream/storage/_filebaseddirectory.py +++ b/src/buildstream/storage/_filebaseddirectory.py @@ -44,15 +44,13 @@ from .._exceptions import ImplError class FileBasedDirectory(Directory): - def __init__(self, external_directory=None): + def __init__(self, external_directory=None, *, parent=None): self.external_directory = external_directory + self.parent = parent def descend(self, *paths, create=False, follow_symlinks=False): """ See superclass Directory for arguments """ - if follow_symlinks: - ImplError("FileBasedDirectory.Decend dose not implement follow_symlinks=True") - current_dir = self for path in paths: @@ -60,21 +58,38 @@ class FileBasedDirectory(Directory): if not path: continue + if path == ".": + continue + if path == "..": + if current_dir.parent is not None: + current_dir = current_dir.parent + # In POSIX /.. == / so just stay at the root dir + continue + new_path = os.path.join(current_dir.external_directory, path) try: st = os.lstat(new_path) - if not stat.S_ISDIR(st.st_mode): + if stat.S_ISDIR(st.st_mode): + current_dir = FileBasedDirectory(new_path, parent=current_dir) + elif follow_symlinks and stat.S_ISLNK(st.st_mode): + linklocation = os.readlink(new_path) + newpaths = linklocation.split(os.path.sep) + if os.path.isabs(linklocation): + current_dir = current_dir._find_root().descend(*newpaths, follow_symlinks=True) + else: + current_dir = current_dir.descend(*newpaths, follow_symlinks=True) + else: raise VirtualDirectoryError( - "Cannot descend into '{}': '{}' is not a directory".format(path, new_path) + "Cannot descend into '{}': '{}' is not a directory".format(path, new_path), + reason="not-a-directory", ) except FileNotFoundError: if create: os.mkdir(new_path) + current_dir = FileBasedDirectory(new_path, parent=current_dir) else: raise VirtualDirectoryError("Cannot descend into '{}': '{}' does not exist".format(path, new_path)) - current_dir = FileBasedDirectory(new_path) - return current_dir def import_files( @@ -228,6 +243,14 @@ class FileBasedDirectory(Directory): object refers to. """ return self.external_directory + def _find_root(self): + """ Finds the root of this directory tree by following 'parent' until there is + no parent. """ + if self.parent: + return self.parent._find_root() + else: + return self + def _get_filetype(self, name=None): path = self.external_directory |