summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJürg Billeter <j@bitron.ch>2020-03-03 15:43:11 +0100
committerJürg Billeter <j@bitron.ch>2020-03-10 15:46:04 +0000
commitdd1a4554417a0e1b4f57827a0af1918ec05323ba (patch)
tree510ef972fb22805d95303e0e64747dfe847977ae
parent7ff10230c634078d440eb7ff0e05155e956644f3 (diff)
downloadbuildstream-dd1a4554417a0e1b4f57827a0af1918ec05323ba.tar.gz
_filebaseddirectory.py: Support follow_symlinks in descend()
-rw-r--r--src/buildstream/storage/_filebaseddirectory.py39
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