Remove error code for archived artifacts feature used when discarding orphaned
artifacts.
Change the method exposing information about archived artifact to include the
`ArchivedTreeArtifact` itself rather than just a boolean if it's present.
Add a `remove` method to `TreeArtifactValue.MultiBuilder` to allow deleting
tree artifacts from the builder after adding entries for them.
PiperOrigin-RevId: 333207607
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TreeArtifactValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/TreeArtifactValue.java
index 093b840..e02e068 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TreeArtifactValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TreeArtifactValue.java
@@ -99,6 +99,17 @@
}
/**
+ * Removes all of collected data for a given tree artifact.
+ *
+ * <p>No-op if there is no data for a given tree artifact.
+ */
+ public MultiBuilder remove(SpecialArtifact treeArtifact) {
+ checkArgument(treeArtifact.isTreeArtifact(), "Not a tree artifact: %s", treeArtifact);
+ map.remove(treeArtifact);
+ return this;
+ }
+
+ /**
* For each unique parent seen by this builder, passes the aggregated metadata to {@link
* TreeArtifactInjector#injectTree}.
*/
@@ -189,8 +200,11 @@
}
@VisibleForTesting
- public boolean hasArchivedArtifactForTesting() {
- return archivedRepresentation != null;
+ @Nullable
+ public ArchivedTreeArtifact getArchivedArtifactForTesting() {
+ return archivedRepresentation != null
+ ? archivedRepresentation.archivedTreeFileArtifact()
+ : null;
}
ImmutableMap<TreeFileArtifact, FileArtifactValue> getChildValues() {
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/TreeArtifactValueTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/TreeArtifactValueTest.java
index 5634913..e8bea2c 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/TreeArtifactValueTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/TreeArtifactValueTest.java
@@ -574,6 +574,79 @@
.build());
}
+ @Test
+ public void multiBuilder_doesNotInjectRemovedValue() {
+ TreeArtifactValue.MultiBuilder builder = TreeArtifactValue.newMultiBuilder();
+ SpecialArtifact parent1 = createTreeArtifact("bin/tree1");
+ TreeFileArtifact parent1Child = TreeFileArtifact.createTreeOutput(parent1, "child");
+ FileArtifactValue parent1ChildMetadata = metadataWithId(1);
+ SpecialArtifact parent2 = createTreeArtifact("bin/tree2");
+ TreeFileArtifact parent2Child = TreeFileArtifact.createTreeOutput(parent2, "child");
+ FileArtifactValue parent2ChildMetadata = metadataWithId(2);
+ Map<SpecialArtifact, TreeArtifactValue> results = new HashMap<>();
+
+ builder
+ .putChild(parent1Child, parent1ChildMetadata)
+ .putChild(parent2Child, parent2ChildMetadata)
+ .remove(parent1)
+ .injectTo(results::put);
+
+ assertThat(results)
+ .containsExactly(
+ parent2,
+ TreeArtifactValue.newBuilder(parent2)
+ .putChild(parent2Child, parent2ChildMetadata)
+ .build());
+ }
+
+ @Test
+ public void multiBuilder_removeMissingTree_doesNothing() {
+ TreeArtifactValue.MultiBuilder builder = TreeArtifactValue.newMultiBuilder();
+ SpecialArtifact missingTree = createTreeArtifact("bin/tree");
+ Map<SpecialArtifact, TreeArtifactValue> results = new HashMap<>();
+
+ builder.remove(missingTree).injectTo(results::put);
+
+ assertThat(results).isEmpty();
+ }
+
+ @Test
+ public void multiBuilder_removeNotATreeArtifact_fails() {
+ TreeArtifactValue.MultiBuilder builder = TreeArtifactValue.newMultiBuilder();
+ SpecialArtifact notATreeArtifact =
+ new SpecialArtifact(
+ root,
+ root.getExecPath().getRelative("bin/artifact"),
+ ActionsTestUtil.NULL_ARTIFACT_OWNER,
+ SpecialArtifactType.FILESET);
+
+ assertThrows(IllegalArgumentException.class, () -> builder.remove(notATreeArtifact));
+ }
+
+ @Test
+ public void multiBuilder_removeAndRecreateValue_injectsValueAfterRemove() {
+ TreeArtifactValue.MultiBuilder builder = TreeArtifactValue.newMultiBuilder();
+ SpecialArtifact parent = createTreeArtifact("bin/tree");
+ TreeFileArtifact child1 = TreeFileArtifact.createTreeOutput(parent, "child1");
+ FileArtifactValue child1Metadata = metadataWithId(1);
+ ArchivedTreeArtifact archivedArtifact = createArchivedTreeArtifact(parent);
+ FileArtifactValue archivedArtifactMetadata = metadataWithId(2);
+ TreeFileArtifact child2 = TreeFileArtifact.createTreeOutput(parent, "child2");
+ FileArtifactValue child2Metadata = metadataWithId(3);
+ Map<SpecialArtifact, TreeArtifactValue> results = new HashMap<>();
+
+ builder
+ .putChild(child1, child1Metadata)
+ .setArchivedRepresentation(archivedArtifact, archivedArtifactMetadata)
+ .remove(parent)
+ .putChild(child2, child2Metadata)
+ .injectTo(results::put);
+
+ assertThat(results)
+ .containsExactly(
+ parent, TreeArtifactValue.newBuilder(parent).putChild(child2, child2Metadata).build());
+ }
+
private static ArchivedTreeArtifact createArchivedTreeArtifact(SpecialArtifact specialArtifact) {
return ArchivedTreeArtifact.create(specialArtifact, BIN_PATH);
}