summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim MacArthur <jim.macarthur@codethink.co.uk>2018-10-23 17:57:16 +0100
committerJim MacArthur <jim.macarthur@codethink.co.uk>2018-10-23 17:57:16 +0100
commita8c76395365fa51ec0068fa1bc736554cd1bb3f6 (patch)
tree4a39140ced1b1c37b5992b54c386984351997b7c
parente1b047ef61cd3727355915868f6cd546b6a4205f (diff)
downloadbuildstream-a8c76395365fa51ec0068fa1bc736554cd1bb3f6.tar.gz
casbaseddirectory: Various fixes.
-rw-r--r--buildstream/storage/_casbaseddirectory.py44
1 files changed, 41 insertions, 3 deletions
diff --git a/buildstream/storage/_casbaseddirectory.py b/buildstream/storage/_casbaseddirectory.py
index cc28fbd98..1a078b225 100644
--- a/buildstream/storage/_casbaseddirectory.py
+++ b/buildstream/storage/_casbaseddirectory.py
@@ -288,9 +288,12 @@ class CasBasedDirectory(Directory):
return entry.descend(subdirectory_spec[1:], create)
else:
# May be a symlink
+ target = self._resolve(subdirectory_spec[0])
+ if isinstance(target, CasBasedDirectory):
+ return target
error = "Cannot descend into {}, which is a '{}' in the directory {}"
raise VirtualDirectoryError(error.format(subdirectory_spec[0],
- type(entry).__name__,
+ type(self.index[subdirectory_spec[0]].pb_object).__name__,
self))
else:
if create:
@@ -328,6 +331,7 @@ class CasBasedDirectory(Directory):
return self.index[name].buildstream_object
# OK then, it's a symlink
symlink = self._find_pb2_entry(name)
+ assert isinstance(symlink, remote_execution_pb2.SymlinkNode)
absolute = symlink.target.startswith(CasBasedDirectory._pb2_absolute_path_prefix)
if absolute:
root = self.find_root()
@@ -344,6 +348,16 @@ class CasBasedDirectory(Directory):
directory = directory.descend(c, create=True)
return directory
+ def _is_followable(self, name):
+ """ Returns true if this is a directory or symlink to a valid directory. """
+ if name not in self.index:
+ return False
+ if isinstance(self.index[name].buildstream_object, Directory):
+ return True
+ target = self._resolve(name)
+ print("Is {} followable? Resolved to {}".format(name, target))
+ return isinstance(target, CasBasedDirectory) or target is None
+
def _resolve_symlink(self, node):
"""Same as _resolve_symlink_or_directory but takes a SymlinkNode.
"""
@@ -476,7 +490,13 @@ class CasBasedDirectory(Directory):
""" _import_directory_recursively and _import_files_from_directory will be called alternately
as a directory tree is descended. """
if directory_name in self.index:
- subdir = self._resolve_symlink_or_directory(directory_name)
+ if self._is_followable(directory_name):
+ subdir = self._resolve_symlink_or_directory(directory_name)
+ else:
+ print("Overwriting unfollowable thing {}".format(directory_name))
+ self.delete_entry(directory_name)
+ subdir = self._add_directory(directory_name)
+ # TODO: Add this to the list of overwritten things.
else:
subdir = self._add_directory(directory_name)
new_path_prefix = os.path.join(path_prefix, directory_name)
@@ -607,6 +627,12 @@ class CasBasedDirectory(Directory):
if dirname not in processed_directories:
# Now strip off the first directory name and import files recursively.
subcomponents = CasBasedDirectory.files_in_subdir(files, dirname)
+ # We will fail at this point if there is a file or symlink to file called 'dirname'.
+ if dirname in self.index:
+ x = self._resolve(dirname)
+ if isinstance(x, remote_execution_pb2.FileNode):
+ self.delete_entry(dirname)
+ result.overwritten.append(f)
self.create_directory(dirname)
print("Creating destination in {}: {}".format(self, dirname))
dest_subdir = self._resolve_symlink_or_directory(dirname)
@@ -688,6 +714,18 @@ class CasBasedDirectory(Directory):
print("Extracted all files from source directory '{}': {}".format(source_directory, files))
return self._partial_import_cas_into_cas(source_directory, list(files))
+ def _describe(self, thing):
+ # Describes protocol buffer objects
+ if isinstance(thing, remote_execution_pb2.DirectoryNode):
+ return "directory called {}".format(thing.name)
+ elif isinstance(thing, remote_execution_pb2.SymlinkNode):
+ return "symlink called {} pointing to {}".format(thing.name, thing.target)
+ elif isinstance(thing, remote_execution_pb2.FileNode):
+ return "file called {}".format(thing.name)
+ else:
+ return "strange thing"
+
+
def showdiff(self, other):
print("Diffing {} and {}:".format(self, other))
@@ -701,7 +739,7 @@ class CasBasedDirectory(Directory):
return False
item2 = l2[index]
if item1.name != item2.name:
- print("Items do not match: {} in l1, {} in l2".format(item1.name, item2.name))
+ print("Items do not match: {}, a {} in l1, vs {}, a {} in l2".format(item1.name, self._describe(item1), item2.name, self._describe(item2)))
return False
index += 1
if index != len(l2):