summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJürg Billeter <j@bitron.ch>2018-07-10 16:08:03 +0200
committerJürg Billeter <j@bitron.ch>2018-07-17 07:56:40 +0200
commita3bdfc1882b576fbe205bd92fb75978669f4cc9d (patch)
tree0d3eaf818498dede603ef866b2fc5a3ff761635d
parentf13bef568127757098f02395a01becacd51b006b (diff)
downloadbuildstream-a3bdfc1882b576fbe205bd92fb75978669f4cc9d.tar.gz
_artifactcache/cascache.py: Add prune() method
-rw-r--r--buildstream/_artifactcache/cascache.py45
1 files changed, 45 insertions, 0 deletions
diff --git a/buildstream/_artifactcache/cascache.py b/buildstream/_artifactcache/cascache.py
index 55b35c758..d1d975c8f 100644
--- a/buildstream/_artifactcache/cascache.py
+++ b/buildstream/_artifactcache/cascache.py
@@ -222,6 +222,36 @@ class CASCache(ArtifactCache):
except FileNotFoundError as e:
raise ArtifactError("Attempt to access unavailable artifact: {}".format(e)) from e
+ # prune():
+ #
+ # Prune unreachable objects from the repo.
+ #
+ def prune(self):
+ ref_heads = os.path.join(self.casdir, 'refs', 'heads')
+
+ pruned = 0
+ reachable = set()
+
+ # Check which objects are reachable
+ for root, _, files in os.walk(ref_heads):
+ for filename in files:
+ ref_path = os.path.join(root, filename)
+ ref = os.path.relpath(ref_path, ref_heads)
+
+ tree = self.resolve_ref(ref)
+ self._reachable_refs_dir(reachable, tree)
+
+ # Prune unreachable objects
+ for root, _, files in os.walk(os.path.join(self.casdir, 'objects')):
+ for filename in files:
+ objhash = os.path.basename(root) + filename
+ if objhash not in reachable:
+ obj_path = os.path.join(root, filename)
+ pruned += os.stat(obj_path).st_size
+ os.unlink(obj_path)
+
+ return pruned
+
################################################
# Local Private Methods #
################################################
@@ -346,3 +376,18 @@ class CASCache(ArtifactCache):
path=os.path.join(path, dir_a.directories[a].name))
a += 1
b += 1
+
+ def _reachable_refs_dir(self, reachable, tree):
+ if tree.hash in reachable:
+ return
+
+ directory = remote_execution_pb2.Directory()
+
+ with open(self.objpath(tree), 'rb') as f:
+ directory.ParseFromString(f.read())
+
+ for filenode in directory.files:
+ reachable.add(filenode.digest.hash)
+
+ for dirnode in directory.directories:
+ self._reachable_refs_dir(reachable, dirnode.digest)