summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJürg Billeter <j@bitron.ch>2020-04-22 12:20:16 +0200
committerbst-marge-bot <marge-bot@buildstream.build>2020-04-27 08:32:32 +0000
commit9ce3da0ab8b6a2998b2565864e8234680976f198 (patch)
treecbcc979a58f92a9918e82dd46483ae99040c83bc
parent047549f45ee9670798f2c32822d7429a819964a1 (diff)
downloadbuildstream-9ce3da0ab8b6a2998b2565864e8234680976f198.tar.gz
storage: Add Directory.rename() method
-rw-r--r--src/buildstream/storage/_casbaseddirectory.py11
-rw-r--r--src/buildstream/storage/_filebaseddirectory.py11
-rw-r--r--src/buildstream/storage/directory.py10
3 files changed, 32 insertions, 0 deletions
diff --git a/src/buildstream/storage/_casbaseddirectory.py b/src/buildstream/storage/_casbaseddirectory.py
index e20c1e73a..c83918e4d 100644
--- a/src/buildstream/storage/_casbaseddirectory.py
+++ b/src/buildstream/storage/_casbaseddirectory.py
@@ -319,6 +319,17 @@ class CasBasedDirectory(Directory):
del self.index[name]
self.__invalidate_digest()
+ def rename(self, src, dest):
+ srcdir = self.descend(*src[:-1])
+ entry = srcdir._entry_from_path(src[-1])
+
+ destdir = self.descend(*dest[:-1])
+ self.__validate_path_component(dest[-1])
+
+ srcdir.remove(src[-1], recursive=True)
+ entry.name = dest[-1]
+ destdir._add_entry(entry)
+
def descend(self, *paths, create=False, follow_symlinks=False):
"""Descend one or more levels of directory hierarchy and return a new
Directory object for that directory.
diff --git a/src/buildstream/storage/_filebaseddirectory.py b/src/buildstream/storage/_filebaseddirectory.py
index 60d63d567..12312299d 100644
--- a/src/buildstream/storage/_filebaseddirectory.py
+++ b/src/buildstream/storage/_filebaseddirectory.py
@@ -312,6 +312,17 @@ class FileBasedDirectory(Directory):
else:
os.unlink(newpath)
+ def rename(self, src, dest):
+ # Use descend() to avoid following symlinks (potentially escaping the sandbox)
+ srcdir = self.descend(*src[:-1])
+ destdir = self.descend(*dest[:-1])
+ srcpath = os.path.join(srcdir.external_directory, src[-1])
+ destpath = os.path.join(destdir.external_directory, dest[-1])
+
+ if destdir.exists(dest[-1]):
+ destdir.remove(dest[-1])
+ os.rename(srcpath, destpath)
+
def __iter__(self):
yield from os.listdir(self.external_directory)
diff --git a/src/buildstream/storage/directory.py b/src/buildstream/storage/directory.py
index 2b3a85be3..f9ea4044a 100644
--- a/src/buildstream/storage/directory.py
+++ b/src/buildstream/storage/directory.py
@@ -306,6 +306,16 @@ class Directory:
"""
raise NotImplementedError()
+ def rename(self, src: List[str], dest: List[str]):
+ """ Rename a file, symlink or directory. If destination path exists
+ already and is a file or empty directory, it will be replaced.
+
+ Args:
+ *src: Source path components.
+ *dest: Destination path components.
+ """
+ raise NotImplementedError()
+
def _create_empty_file(self, *paths):
with self.open_file(*paths, mode="w"):
pass