diff --git a/src/main/java/com/google/devtools/build/lib/actions/PathMapper.java b/src/main/java/com/google/devtools/build/lib/actions/PathMapper.java
index 1d006ed7678737..0e7dcc546dd531 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/PathMapper.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/PathMapper.java
@@ -33,7 +33,15 @@
* part (e.g. "k8-fastbuild") from exec paths to allow for cross-configuration cache hits.
*/
public interface PathMapper {
- /** Returns the exec path with the path mapping applied. */
+ /**
+ * Returns the exec path with the path mapping applied.
+ *
+ *
Path mappers may return paths with different roots for two paths that have the same root
+ * (e.g., they may map an artifact at {@code bazel-out/k8-fastbuild/bin/pkg/foo} to {@code
+ * bazel-out//bin/pkg/foo}). Paths of artifacts that should share the same
+ * parent directory, such as runfiles or tree artifact files, should thus be derived from the
+ * mapped path of their parent.
+ */
PathFragment map(PathFragment execPath);
/** Returns the exec path of the input with the path mapping applied. */
@@ -80,6 +88,17 @@ default boolean isNoop() {
return this == NOOP;
}
+ /**
+ * Returns an opaque object whose equality class should encode all information that goes into the
+ * behavior of the {@link #map(PathFragment)} function of this path mapper. This is used as a key
+ * for in-memory caches.
+ *
+ * The default implementation returns the {@link Class} of the path mapper.
+ */
+ default Object cacheKey() {
+ return this.getClass();
+ }
+
/** A {@link PathMapper} that doesn't change paths. */
PathMapper NOOP = execPath -> execPath;
}
diff --git a/src/main/java/com/google/devtools/build/lib/exec/SpawnInputExpander.java b/src/main/java/com/google/devtools/build/lib/exec/SpawnInputExpander.java
index 7ee6986efe5392..16d3359d4cef71 100644
--- a/src/main/java/com/google/devtools/build/lib/exec/SpawnInputExpander.java
+++ b/src/main/java/com/google/devtools/build/lib/exec/SpawnInputExpander.java
@@ -33,6 +33,7 @@
import com.google.devtools.build.lib.actions.FilesetOutputSymlink;
import com.google.devtools.build.lib.actions.ForbiddenActionInputException;
import com.google.devtools.build.lib.actions.InputMetadataProvider;
+import com.google.devtools.build.lib.actions.PathMapper;
import com.google.devtools.build.lib.actions.RunfilesSupplier;
import com.google.devtools.build.lib.actions.Spawn;
import com.google.devtools.build.lib.actions.cache.VirtualActionInput;
@@ -125,6 +126,7 @@ void addRunfilesToInputs(
RunfilesSupplier runfilesSupplier,
InputMetadataProvider actionFileCache,
ArtifactExpander artifactExpander,
+ PathMapper pathMapper,
PathFragment baseDirectory)
throws IOException, ForbiddenActionInputException {
Map> rootsAndMappings =
@@ -145,6 +147,7 @@ void addRunfilesToInputs(
? null
: artifactExpander.getArchivedTreeArtifact((SpecialArtifact) localArtifact);
if (archivedTreeArtifact != null) {
+ // TODO(bazel-team): Add path mapping support for archived tree artifacts.
addMapping(inputMap, location, localArtifact, baseDirectory);
} else {
List expandedInputs =
@@ -153,11 +156,12 @@ void addRunfilesToInputs(
artifactExpander,
/* keepEmptyTreeArtifacts= */ false);
for (ActionInput input : expandedInputs) {
- addMapping(
- inputMap,
- location.getRelative(((TreeFileArtifact) input).getParentRelativePath()),
- input,
- baseDirectory);
+ addMapping(
+ inputMap,
+ mapForRunfiles(pathMapper, root, location)
+ .getRelative(((TreeFileArtifact) input).getParentRelativePath()),
+ input,
+ baseDirectory);
}
}
} else if (localArtifact.isFileset()) {
@@ -167,15 +171,21 @@ void addRunfilesToInputs(
} catch (MissingExpansionException e) {
throw new IllegalStateException(e);
}
+ // TODO(bazel-team): Add path mapping support for filesets.
addFilesetManifest(location, localArtifact, filesetLinks, inputMap, baseDirectory);
} else {
if (strict) {
failIfDirectory(actionFileCache, localArtifact);
}
- addMapping(inputMap, location, localArtifact, baseDirectory);
+ addMapping(
+ inputMap, mapForRunfiles(pathMapper, root, location), localArtifact, baseDirectory);
}
} else {
- addMapping(inputMap, location, VirtualActionInput.EMPTY_MARKER, baseDirectory);
+ addMapping(
+ inputMap,
+ mapForRunfiles(pathMapper, root, location),
+ VirtualActionInput.EMPTY_MARKER,
+ baseDirectory);
}
}
}
@@ -186,11 +196,12 @@ public Map addRunfilesToInputs(
RunfilesSupplier runfilesSupplier,
InputMetadataProvider actionFileCache,
ArtifactExpander artifactExpander,
+ PathMapper pathMapper,
PathFragment baseDirectory)
throws IOException, ForbiddenActionInputException {
Map inputMap = new HashMap<>();
addRunfilesToInputs(
- inputMap, runfilesSupplier, actionFileCache, artifactExpander, baseDirectory);
+ inputMap, runfilesSupplier, actionFileCache, artifactExpander, pathMapper, baseDirectory);
return inputMap;
}
@@ -235,6 +246,7 @@ void addFilesetManifest(
value == null
? VirtualActionInput.EMPTY_MARKER
: ActionInputHelper.fromPath(execRoot.getRelative(value).asFragment());
+ // TODO(bazel-team): Add path mapping support for filesets.
addMapping(inputMappings, mapping.getKey(), artifact, baseDirectory);
}
}
@@ -243,6 +255,7 @@ private static void addInputs(
Map inputMap,
NestedSet extends ActionInput> inputFiles,
ArtifactExpander artifactExpander,
+ PathMapper pathMapper,
PathFragment baseDirectory) {
// Actions that accept TreeArtifacts as inputs generally expect the directory corresponding
// to the artifact to be created, even if it is empty. We explicitly keep empty TreeArtifacts
@@ -251,7 +264,17 @@ private static void addInputs(
ActionInputHelper.expandArtifacts(
inputFiles, artifactExpander, /* keepEmptyTreeArtifacts= */ true);
for (ActionInput input : inputs) {
- addMapping(inputMap, input.getExecPath(), input, baseDirectory);
+ if (input instanceof TreeFileArtifact) {
+ addMapping(
+ inputMap,
+ pathMapper
+ .map(((TreeFileArtifact) input).getParent().getExecPath())
+ .getRelative(((TreeFileArtifact) input).getParentRelativePath()),
+ input,
+ baseDirectory);
+ } else {
+ addMapping(inputMap, pathMapper.map(input.getExecPath()), input, baseDirectory);
+ }
}
}
@@ -273,17 +296,37 @@ public SortedMap getInputMapping(
InputMetadataProvider actionInputFileCache)
throws IOException, ForbiddenActionInputException {
TreeMap inputMap = new TreeMap<>();
- addInputs(inputMap, spawn.getInputFiles(), artifactExpander, baseDirectory);
+ addInputs(
+ inputMap, spawn.getInputFiles(), artifactExpander, spawn.getPathMapper(), baseDirectory);
addRunfilesToInputs(
inputMap,
spawn.getRunfilesSupplier(),
actionInputFileCache,
artifactExpander,
+ spawn.getPathMapper(),
baseDirectory);
addFilesetManifests(spawn.getFilesetMappings(), inputMap, baseDirectory);
return inputMap;
}
+ private static PathFragment mapForRunfiles(
+ PathMapper pathMapper, PathFragment runfilesDir, PathFragment execPath) {
+ if (pathMapper.isNoop()) {
+ return execPath;
+ }
+ String runfilesDirName = runfilesDir.getBaseName();
+ Preconditions.checkArgument(runfilesDirName.endsWith(".runfiles"));
+ // Derive the path of the executable, apply the path mapping to it and then rederive the path
+ // of the runfiles dir.
+ PathFragment executable =
+ runfilesDir.replaceName(
+ runfilesDirName.substring(0, runfilesDirName.length() - ".runfiles".length()));
+ return pathMapper
+ .map(executable)
+ .replaceName(runfilesDirName)
+ .getRelative(execPath.relativeTo(runfilesDir));
+ }
+
/** The interface for accessing part of the input hierarchy. */
public interface InputWalker {
@@ -326,19 +369,25 @@ public void walkInputs(
InputMetadataProvider actionInputFileCache,
InputVisitor visitor)
throws IOException, ForbiddenActionInputException {
- walkNestedSetInputs(baseDirectory, spawn.getInputFiles(), artifactExpander, visitor);
+ walkNestedSetInputs(
+ baseDirectory, spawn.getInputFiles(), artifactExpander, spawn.getPathMapper(), visitor);
RunfilesSupplier runfilesSupplier = spawn.getRunfilesSupplier();
visitor.visit(
// Cache key for the sub-mapping containing the runfiles inputs for this spawn.
- ImmutableList.of(runfilesSupplier, baseDirectory),
+ ImmutableList.of(runfilesSupplier, baseDirectory, spawn.getPathMapper().cacheKey()),
new InputWalker() {
@Override
public SortedMap getLeavesInputMapping()
throws IOException, ForbiddenActionInputException {
TreeMap inputMap = new TreeMap<>();
addRunfilesToInputs(
- inputMap, runfilesSupplier, actionInputFileCache, artifactExpander, baseDirectory);
+ inputMap,
+ runfilesSupplier,
+ actionInputFileCache,
+ artifactExpander,
+ spawn.getPathMapper(),
+ baseDirectory);
return inputMap;
}
});
@@ -348,7 +397,7 @@ public SortedMap getLeavesInputMapping()
// improved runtime.
visitor.visit(
// Cache key for the sub-mapping containing the fileset inputs for this spawn.
- ImmutableList.of(filesetMappings, baseDirectory),
+ ImmutableList.of(filesetMappings, baseDirectory, spawn.getPathMapper().cacheKey()),
new InputWalker() {
@Override
public SortedMap getLeavesInputMapping()
@@ -365,11 +414,12 @@ private void walkNestedSetInputs(
PathFragment baseDirectory,
NestedSet extends ActionInput> someInputFiles,
ArtifactExpander artifactExpander,
+ PathMapper pathMapper,
InputVisitor visitor)
throws IOException, ForbiddenActionInputException {
visitor.visit(
// Cache key for the sub-mapping containing the files in this nested set.
- ImmutableList.of(someInputFiles.toNode(), baseDirectory),
+ ImmutableList.of(someInputFiles.toNode(), baseDirectory, pathMapper.cacheKey()),
new InputWalker() {
@Override
public SortedMap getLeavesInputMapping() {
@@ -384,6 +434,7 @@ public SortedMap getLeavesInputMapping() {
inputMap,
NestedSetBuilder.wrap(someInputFiles.getOrder(), leaves),
artifactExpander,
+ pathMapper,
baseDirectory);
return inputMap;
}
@@ -394,11 +445,16 @@ public void visitNonLeaves(InputVisitor childVisitor)
for (ActionInput input : someInputFiles.getLeaves()) {
if (isTreeArtifact(input)) {
walkTreeInputs(
- baseDirectory, (SpecialArtifact) input, artifactExpander, childVisitor);
+ baseDirectory,
+ (SpecialArtifact) input,
+ artifactExpander,
+ pathMapper,
+ childVisitor);
}
}
for (NestedSet extends ActionInput> subInputs : someInputFiles.getNonLeaves()) {
- walkNestedSetInputs(baseDirectory, subInputs, artifactExpander, childVisitor);
+ walkNestedSetInputs(
+ baseDirectory, subInputs, artifactExpander, pathMapper, childVisitor);
}
}
});
@@ -409,11 +465,12 @@ private void walkTreeInputs(
PathFragment baseDirectory,
SpecialArtifact tree,
ArtifactExpander artifactExpander,
+ PathMapper pathMapper,
InputVisitor visitor)
throws IOException, ForbiddenActionInputException {
visitor.visit(
// Cache key for the sub-mapping containing the files in this tree artifact.
- ImmutableList.of(tree, baseDirectory),
+ ImmutableList.of(tree, baseDirectory, pathMapper.cacheKey()),
new InputWalker() {
@Override
public SortedMap getLeavesInputMapping() {
@@ -422,6 +479,7 @@ public SortedMap getLeavesInputMapping() {
inputMap,
NestedSetBuilder.create(Order.STABLE_ORDER, tree),
artifactExpander,
+ pathMapper,
baseDirectory);
return inputMap;
}
diff --git a/src/test/java/com/google/devtools/build/lib/exec/SpawnInputExpanderTest.java b/src/test/java/com/google/devtools/build/lib/exec/SpawnInputExpanderTest.java
index f1ffe6e5b00dec..e55beea7fd9eda 100644
--- a/src/test/java/com/google/devtools/build/lib/exec/SpawnInputExpanderTest.java
+++ b/src/test/java/com/google/devtools/build/lib/exec/SpawnInputExpanderTest.java
@@ -17,6 +17,7 @@
import static com.google.devtools.build.lib.actions.FilesetManifest.RelativeSymlinkBehavior.ERROR;
import static com.google.devtools.build.lib.actions.FilesetManifest.RelativeSymlinkBehavior.IGNORE;
import static com.google.devtools.build.lib.actions.FilesetManifest.RelativeSymlinkBehavior.RESOLVE;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.fail;
@@ -37,6 +38,7 @@
import com.google.devtools.build.lib.actions.FilesetManifest;
import com.google.devtools.build.lib.actions.FilesetOutputSymlink;
import com.google.devtools.build.lib.actions.ForbiddenActionInputException;
+import com.google.devtools.build.lib.actions.PathMapper;
import com.google.devtools.build.lib.actions.RunfilesSupplier;
import com.google.devtools.build.lib.actions.Spawn;
import com.google.devtools.build.lib.actions.cache.VirtualActionInput;
@@ -82,7 +84,12 @@ public void testEmptyRunfiles() throws Exception {
RunfilesSupplier supplier = EmptyRunfilesSupplier.INSTANCE;
FakeActionInputFileCache mockCache = new FakeActionInputFileCache();
expander.addRunfilesToInputs(
- inputMappings, supplier, mockCache, NO_ARTIFACT_EXPANDER, PathFragment.EMPTY_FRAGMENT);
+ inputMappings,
+ supplier,
+ mockCache,
+ NO_ARTIFACT_EXPANDER,
+ PathMapper.NOOP,
+ PathFragment.EMPTY_FRAGMENT);
assertThat(inputMappings).isEmpty();
}
@@ -101,7 +108,12 @@ public void testRunfilesSingleFile() throws Exception {
FileArtifactValue.createForNormalFile(FAKE_DIGEST, /*proxy=*/ null, /*size=*/ 0L));
expander.addRunfilesToInputs(
- inputMappings, supplier, mockCache, NO_ARTIFACT_EXPANDER, PathFragment.EMPTY_FRAGMENT);
+ inputMappings,
+ supplier,
+ mockCache,
+ NO_ARTIFACT_EXPANDER,
+ PathMapper.NOOP,
+ PathFragment.EMPTY_FRAGMENT);
assertThat(inputMappings).hasSize(1);
assertThat(inputMappings)
.containsEntry(PathFragment.create("runfiles/workspace/dir/file"), artifact);
@@ -136,7 +148,12 @@ public ImmutableList getFileset(Artifact artifact) {
};
expander.addRunfilesToInputs(
- inputMappings, supplier, mockCache, filesetExpander, PathFragment.EMPTY_FRAGMENT);
+ inputMappings,
+ supplier,
+ mockCache,
+ filesetExpander,
+ PathMapper.NOOP,
+ PathFragment.EMPTY_FRAGMENT);
assertThat(inputMappings).hasSize(1);
assertThat(inputMappings)
.containsEntry(
@@ -165,6 +182,7 @@ public void testRunfilesDirectoryStrict() {
supplier,
mockCache,
NO_ARTIFACT_EXPANDER,
+ PathMapper.NOOP,
PathFragment.EMPTY_FRAGMENT));
assertThat(expected).hasMessageThat().isEqualTo("Not a file: dir/file");
}
@@ -183,7 +201,12 @@ public void testRunfilesDirectoryNonStrict() throws Exception {
expander = new SpawnInputExpander(execRoot, /*strict=*/ false);
expander.addRunfilesToInputs(
- inputMappings, supplier, mockCache, NO_ARTIFACT_EXPANDER, PathFragment.EMPTY_FRAGMENT);
+ inputMappings,
+ supplier,
+ mockCache,
+ NO_ARTIFACT_EXPANDER,
+ PathMapper.NOOP,
+ PathFragment.EMPTY_FRAGMENT);
assertThat(inputMappings).hasSize(1);
assertThat(inputMappings)
.containsEntry(PathFragment.create("runfiles/workspace/dir/file"), artifact);
@@ -212,7 +235,12 @@ public void testRunfilesTwoFiles() throws Exception {
FileArtifactValue.createForNormalFile(FAKE_DIGEST, /*proxy=*/ null, /*size=*/ 12L));
expander.addRunfilesToInputs(
- inputMappings, supplier, mockCache, NO_ARTIFACT_EXPANDER, PathFragment.EMPTY_FRAGMENT);
+ inputMappings,
+ supplier,
+ mockCache,
+ NO_ARTIFACT_EXPANDER,
+ PathMapper.NOOP,
+ PathFragment.EMPTY_FRAGMENT);
assertThat(inputMappings).hasSize(2);
assertThat(inputMappings)
.containsEntry(PathFragment.create("runfiles/workspace/dir/file"), artifact1);
@@ -220,6 +248,45 @@ public void testRunfilesTwoFiles() throws Exception {
.containsEntry(PathFragment.create("runfiles/workspace/dir/baz"), artifact2);
}
+ @Test
+ public void testRunfilesTwoFiles_pathMapped() throws Exception {
+ Artifact artifact1 =
+ ActionsTestUtil.createArtifact(
+ ArtifactRoot.asSourceRoot(Root.fromPath(fs.getPath("/root"))),
+ fs.getPath("/root/dir/file"));
+ Artifact artifact2 =
+ ActionsTestUtil.createArtifact(
+ ArtifactRoot.asSourceRoot(Root.fromPath(fs.getPath("/root"))),
+ fs.getPath("/root/dir/baz"));
+ Runfiles runfiles =
+ new Runfiles.Builder("workspace").addArtifact(artifact1).addArtifact(artifact2).build();
+ RunfilesSupplier supplier =
+ AnalysisTestUtil.createRunfilesSupplier(
+ PathFragment.create("bazel-out/k8-opt/bin/foo.runfiles"), runfiles);
+ FakeActionInputFileCache mockCache = new FakeActionInputFileCache();
+ mockCache.put(
+ artifact1,
+ FileArtifactValue.createForNormalFile(FAKE_DIGEST, /* proxy= */ null, /* size= */ 1L));
+ mockCache.put(
+ artifact2,
+ FileArtifactValue.createForNormalFile(FAKE_DIGEST, /* proxy= */ null, /* size= */ 12L));
+
+ expander.addRunfilesToInputs(
+ inputMappings,
+ supplier,
+ mockCache,
+ NO_ARTIFACT_EXPANDER,
+ execPath -> PathFragment.create(execPath.getPathString().replace("k8-opt/", "")),
+ PathFragment.EMPTY_FRAGMENT);
+ assertThat(inputMappings).hasSize(2);
+ assertThat(inputMappings)
+ .containsEntry(
+ PathFragment.create("bazel-out/bin/foo.runfiles/workspace/dir/file"), artifact1);
+ assertThat(inputMappings)
+ .containsEntry(
+ PathFragment.create("bazel-out/bin/foo.runfiles/workspace/dir/baz"), artifact2);
+ }
+
@Test
public void testRunfilesSymlink() throws Exception {
Artifact artifact =
@@ -238,7 +305,12 @@ public void testRunfilesSymlink() throws Exception {
FileArtifactValue.createForNormalFile(FAKE_DIGEST, /*proxy=*/ null, /*size=*/ 1L));
expander.addRunfilesToInputs(
- inputMappings, supplier, mockCache, NO_ARTIFACT_EXPANDER, PathFragment.EMPTY_FRAGMENT);
+ inputMappings,
+ supplier,
+ mockCache,
+ NO_ARTIFACT_EXPANDER,
+ PathMapper.NOOP,
+ PathFragment.EMPTY_FRAGMENT);
assertThat(inputMappings).hasSize(1);
assertThat(inputMappings)
.containsEntry(PathFragment.create("runfiles/workspace/symlink"), artifact);
@@ -262,7 +334,12 @@ public void testRunfilesRootSymlink() throws Exception {
FileArtifactValue.createForNormalFile(FAKE_DIGEST, /*proxy=*/ null, /*size=*/ 1L));
expander.addRunfilesToInputs(
- inputMappings, supplier, mockCache, NO_ARTIFACT_EXPANDER, PathFragment.EMPTY_FRAGMENT);
+ inputMappings,
+ supplier,
+ mockCache,
+ NO_ARTIFACT_EXPANDER,
+ PathMapper.NOOP,
+ PathFragment.EMPTY_FRAGMENT);
assertThat(inputMappings).hasSize(2);
assertThat(inputMappings).containsEntry(PathFragment.create("runfiles/symlink"), artifact);
// If there's no other entry, Runfiles adds an empty file in the workspace to make sure the
@@ -295,7 +372,12 @@ public void testRunfilesWithTreeArtifacts() throws Exception {
fakeCache.put(file2, FileArtifactValue.createForTesting(file2));
expander.addRunfilesToInputs(
- inputMappings, supplier, fakeCache, artifactExpander, PathFragment.EMPTY_FRAGMENT);
+ inputMappings,
+ supplier,
+ fakeCache,
+ artifactExpander,
+ PathMapper.NOOP,
+ PathFragment.EMPTY_FRAGMENT);
assertThat(inputMappings).hasSize(2);
assertThat(inputMappings)
.containsEntry(PathFragment.create("runfiles/workspace/treeArtifact/file1"), file1);
@@ -303,6 +385,64 @@ public void testRunfilesWithTreeArtifacts() throws Exception {
.containsEntry(PathFragment.create("runfiles/workspace/treeArtifact/file2"), file2);
}
+ @Test
+ public void testRunfilesWithTreeArtifacts_pathMapped() throws Exception {
+ SpecialArtifact treeArtifact = createTreeArtifact("treeArtifact");
+ assertThat(treeArtifact.isTreeArtifact()).isTrue();
+ TreeFileArtifact file1 = TreeFileArtifact.createTreeOutput(treeArtifact, "file1");
+ TreeFileArtifact file2 = TreeFileArtifact.createTreeOutput(treeArtifact, "file2");
+ FileSystemUtils.writeContentAsLatin1(file1.getPath(), "foo");
+ FileSystemUtils.writeContentAsLatin1(file2.getPath(), "bar");
+
+ Runfiles runfiles = new Runfiles.Builder("workspace").addArtifact(treeArtifact).build();
+ ArtifactExpander artifactExpander =
+ (Artifact artifact, Collection super Artifact> output) -> {
+ if (artifact.equals(treeArtifact)) {
+ output.addAll(Arrays.asList(file1, file2));
+ }
+ };
+ RunfilesSupplier supplier =
+ AnalysisTestUtil.createRunfilesSupplier(
+ PathFragment.create("bazel-out/k8-opt/bin/foo.runfiles"), runfiles);
+ FakeActionInputFileCache fakeCache = new FakeActionInputFileCache();
+ fakeCache.put(file1, FileArtifactValue.createForTesting(file1));
+ fakeCache.put(file2, FileArtifactValue.createForTesting(file2));
+
+ PathMapper pathMapper =
+ execPath -> {
+ // Replace the config segment "k8-opt" in "bazel-bin/k8-opt/bin" with a hash of the full
+ // path to verify that the new paths are constructed by appending the child paths to the
+ // mapped parent path, not by mapping the child paths directly.
+ PathFragment runfilesPath = execPath.subFragment(3);
+ String runfilesPathHash =
+ DigestHashFunction.SHA256
+ .getHashFunction()
+ .hashString(runfilesPath.getPathString(), UTF_8)
+ .toString();
+ return execPath
+ .subFragment(0, 1)
+ .getRelative(runfilesPathHash.substring(0, 8))
+ .getRelative(execPath.subFragment(2));
+ };
+
+ expander.addRunfilesToInputs(
+ inputMappings,
+ supplier,
+ fakeCache,
+ artifactExpander,
+ pathMapper,
+ PathFragment.EMPTY_FRAGMENT);
+ assertThat(inputMappings).hasSize(2);
+ assertThat(inputMappings)
+ .containsEntry(
+ PathFragment.create("bazel-out/2c26b46b/bin/foo.runfiles/workspace/treeArtifact/file1"),
+ file1);
+ assertThat(inputMappings)
+ .containsEntry(
+ PathFragment.create("bazel-out/2c26b46b/bin/foo.runfiles/workspace/treeArtifact/file2"),
+ file2);
+ }
+
@Test
public void testRunfilesWithArchivedTreeArtifacts() throws Exception {
SpecialArtifact treeArtifact = createTreeArtifact("treeArtifact");
@@ -335,6 +475,7 @@ public ArchivedTreeArtifact getArchivedTreeArtifact(SpecialArtifact treeArtifact
supplier,
new FakeActionInputFileCache(),
artifactExpander,
+ PathMapper.NOOP,
PathFragment.EMPTY_FRAGMENT);
assertThat(inputMappings).hasSize(1);
assertThat(inputMappings)
@@ -367,7 +508,12 @@ public void testRunfilesWithTreeArtifactsInSymlinks() throws Exception {
fakeCache.put(file2, FileArtifactValue.createForTesting(file2));
expander.addRunfilesToInputs(
- inputMappings, supplier, fakeCache, artifactExpander, PathFragment.EMPTY_FRAGMENT);
+ inputMappings,
+ supplier,
+ fakeCache,
+ artifactExpander,
+ PathMapper.NOOP,
+ PathFragment.EMPTY_FRAGMENT);
assertThat(inputMappings).hasSize(2);
assertThat(inputMappings)
.containsEntry(PathFragment.create("runfiles/workspace/symlink/file1"), file1);
diff --git a/src/test/java/com/google/devtools/build/lib/exec/util/SpawnBuilder.java b/src/test/java/com/google/devtools/build/lib/exec/util/SpawnBuilder.java
index 294ba3396ac4a6..0a8b407d64124a 100644
--- a/src/test/java/com/google/devtools/build/lib/exec/util/SpawnBuilder.java
+++ b/src/test/java/com/google/devtools/build/lib/exec/util/SpawnBuilder.java
@@ -61,7 +61,7 @@ public final class SpawnBuilder {
private RunfilesSupplier runfilesSupplier = EmptyRunfilesSupplier.INSTANCE;
private ResourceSet resourceSet = ResourceSet.ZERO;
- private PathMapper pathMapper;
+ private PathMapper pathMapper = PathMapper.NOOP;
private boolean builtForToolConfiguration;
/**
diff --git a/src/test/java/com/google/devtools/build/lib/remote/RemoteExecutionServiceTest.java b/src/test/java/com/google/devtools/build/lib/remote/RemoteExecutionServiceTest.java
index 3780956a765056..d8fb493413f87e 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/RemoteExecutionServiceTest.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/RemoteExecutionServiceTest.java
@@ -67,6 +67,7 @@
import com.google.devtools.build.lib.actions.ArtifactRoot.RootType;
import com.google.devtools.build.lib.actions.EmptyRunfilesSupplier;
import com.google.devtools.build.lib.actions.ExecutionRequirements;
+import com.google.devtools.build.lib.actions.PathMapper;
import com.google.devtools.build.lib.actions.ResourceSet;
import com.google.devtools.build.lib.actions.SimpleSpawn;
import com.google.devtools.build.lib.actions.Spawn;
@@ -2081,12 +2082,21 @@ public void buildMerkleTree_withMemoization_works() throws Exception {
verify(service, times(6)).uncachedBuildMerkleTreeVisitor(any(), any(), any());
assertThat(service.getMerkleTreeCache().asMap().keySet())
.containsExactly(
- ImmutableList.of(ImmutableMap.of(), PathFragment.EMPTY_FRAGMENT), // fileset mapping
- ImmutableList.of(EmptyRunfilesSupplier.INSTANCE, PathFragment.EMPTY_FRAGMENT),
- ImmutableList.of(tree, PathFragment.EMPTY_FRAGMENT),
- ImmutableList.of(nodeRoot1.toNode(), PathFragment.EMPTY_FRAGMENT),
- ImmutableList.of(nodeFoo1.toNode(), PathFragment.EMPTY_FRAGMENT),
- ImmutableList.of(nodeBar.toNode(), PathFragment.EMPTY_FRAGMENT));
+ ImmutableList.of(
+ ImmutableMap.of(),
+ PathFragment.EMPTY_FRAGMENT,
+ PathMapper.NOOP.getClass()), // fileset mapping
+ ImmutableList.of(
+ EmptyRunfilesSupplier.INSTANCE,
+ PathFragment.EMPTY_FRAGMENT,
+ PathMapper.NOOP.getClass()),
+ ImmutableList.of(tree, PathFragment.EMPTY_FRAGMENT, PathMapper.NOOP.getClass()),
+ ImmutableList.of(
+ nodeRoot1.toNode(), PathFragment.EMPTY_FRAGMENT, PathMapper.NOOP.getClass()),
+ ImmutableList.of(
+ nodeFoo1.toNode(), PathFragment.EMPTY_FRAGMENT, PathMapper.NOOP.getClass()),
+ ImmutableList.of(
+ nodeBar.toNode(), PathFragment.EMPTY_FRAGMENT, PathMapper.NOOP.getClass()));
// act second time
service.buildRemoteAction(spawn2, context2);
@@ -2095,14 +2105,25 @@ public void buildMerkleTree_withMemoization_works() throws Exception {
verify(service, times(6 + 2)).uncachedBuildMerkleTreeVisitor(any(), any(), any());
assertThat(service.getMerkleTreeCache().asMap().keySet())
.containsExactly(
- ImmutableList.of(ImmutableMap.of(), PathFragment.EMPTY_FRAGMENT), // fileset mapping
- ImmutableList.of(EmptyRunfilesSupplier.INSTANCE, PathFragment.EMPTY_FRAGMENT),
- ImmutableList.of(tree, PathFragment.EMPTY_FRAGMENT),
- ImmutableList.of(nodeRoot1.toNode(), PathFragment.EMPTY_FRAGMENT),
- ImmutableList.of(nodeRoot2.toNode(), PathFragment.EMPTY_FRAGMENT),
- ImmutableList.of(nodeFoo1.toNode(), PathFragment.EMPTY_FRAGMENT),
- ImmutableList.of(nodeFoo2.toNode(), PathFragment.EMPTY_FRAGMENT),
- ImmutableList.of(nodeBar.toNode(), PathFragment.EMPTY_FRAGMENT));
+ ImmutableList.of(
+ ImmutableMap.of(),
+ PathFragment.EMPTY_FRAGMENT,
+ PathMapper.NOOP.getClass()), // fileset mapping
+ ImmutableList.of(
+ EmptyRunfilesSupplier.INSTANCE,
+ PathFragment.EMPTY_FRAGMENT,
+ PathMapper.NOOP.getClass()),
+ ImmutableList.of(tree, PathFragment.EMPTY_FRAGMENT, PathMapper.NOOP.getClass()),
+ ImmutableList.of(
+ nodeRoot1.toNode(), PathFragment.EMPTY_FRAGMENT, PathMapper.NOOP.getClass()),
+ ImmutableList.of(
+ nodeRoot2.toNode(), PathFragment.EMPTY_FRAGMENT, PathMapper.NOOP.getClass()),
+ ImmutableList.of(
+ nodeFoo1.toNode(), PathFragment.EMPTY_FRAGMENT, PathMapper.NOOP.getClass()),
+ ImmutableList.of(
+ nodeFoo2.toNode(), PathFragment.EMPTY_FRAGMENT, PathMapper.NOOP.getClass()),
+ ImmutableList.of(
+ nodeBar.toNode(), PathFragment.EMPTY_FRAGMENT, PathMapper.NOOP.getClass()));
}
@Test