Skip to content

Commit 9eef9d5

Browse files
benjaminpulfjack
authored andcommitted
Transform roots along with paths during output deletion.
4009b17 resolved output paths but not the related roots. Fixes bazelbuild#12678. Closes bazelbuild#12634. PiperOrigin-RevId: 346975821
1 parent c478122 commit 9eef9d5

File tree

5 files changed

+49
-13
lines changed

5 files changed

+49
-13
lines changed

src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -362,10 +362,23 @@ protected void deleteOutputs(
362362
}
363363

364364
for (Artifact output : getOutputs()) {
365-
deleteOutput(pathResolver.toPath(output), output.getRoot());
365+
deleteOutput(output, pathResolver);
366366
}
367367
}
368368

369+
/**
370+
* Remove an output artifact.
371+
*
372+
* <p>If the path refers to a directory, recursively removes the contents of the directory.
373+
*
374+
* @param output artifact to remove
375+
*/
376+
protected static void deleteOutput(Artifact output, ArtifactPathResolver pathResolver)
377+
throws IOException {
378+
deleteOutput(
379+
pathResolver.toPath(output), pathResolver.transformRoot(output.getRoot().getRoot()));
380+
}
381+
369382
/**
370383
* Helper method to remove an output file.
371384
*
@@ -375,23 +388,22 @@ protected void deleteOutputs(
375388
* @param root the root containing the output. This is used to check that we don't delete
376389
* arbitrary files in the file system.
377390
*/
378-
public static void deleteOutput(Path path, @Nullable ArtifactRoot root) throws IOException {
391+
public static void deleteOutput(Path path, @Nullable Root root) throws IOException {
379392
try {
380393
// Optimize for the common case: output artifacts are files.
381394
path.delete();
382395
} catch (IOException e) {
383396
// Handle a couple of scenarios where the output can still be deleted, but make sure we're not
384397
// deleting random files on the filesystem.
385398
if (root == null) {
386-
throw new IOException(e);
399+
throw new IOException("null root", e);
387400
}
388-
Root outputRoot = root.getRoot();
389-
if (!outputRoot.contains(path)) {
390-
throw new IOException(e);
401+
if (!root.contains(path)) {
402+
throw new IOException(String.format("%s not under %s", path, root), e);
391403
}
392404

393405
Path parentDir = path.getParentDirectory();
394-
if (!parentDir.isWritable() && outputRoot.contains(parentDir)) {
406+
if (!parentDir.isWritable() && root.contains(parentDir)) {
395407
// Retry deleting after making the parent writable.
396408
parentDir.setWritable(true);
397409
deleteOutput(path, root);

src/main/java/com/google/devtools/build/lib/actions/ArtifactPathResolver.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,7 @@ public interface ArtifactPathResolver {
3737
*/
3838
Path convertPath(Path path);
3939

40-
/**
41-
* @return a resolved Rooth corresponding to the given Root.
42-
*/
40+
/** @return a resolved {@link Root} corresponding to the given Root. */
4341
Root transformRoot(Root root);
4442

4543
ArtifactPathResolver IDENTITY = new IdentityResolver(null);

src/main/java/com/google/devtools/build/lib/bazel/BazelWorkspaceStatusModule.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ public void prepare(
161161
// The default implementation of this method deletes all output files; override it to keep
162162
// the old stableStatus around. This way we can reuse the existing file (preserving its mtime)
163163
// if the contents haven't changed.
164-
deleteOutput(pathResolver.toPath(volatileStatus), volatileStatus.getRoot());
164+
deleteOutput(volatileStatus, pathResolver);
165165
}
166166

167167
@Override

src/main/java/com/google/devtools/build/lib/includescanning/SpawnIncludeScanner.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,11 @@ public Collection<Inclusion> extractInclusions(
295295
Path output = getIncludesOutput(file, actionExecutionContext.getPathResolver(), fileType,
296296
placeNextToFile);
297297
if (!inMemoryOutput) {
298-
AbstractAction.deleteOutput(output, placeNextToFile ? file.getRoot() : null);
298+
AbstractAction.deleteOutput(
299+
output,
300+
placeNextToFile
301+
? actionExecutionContext.getPathResolver().transformRoot(file.getRoot().getRoot())
302+
: null);
299303
if (!placeNextToFile) {
300304
output.getParentDirectory().createDirectoryAndParents();
301305
}
@@ -409,7 +413,11 @@ public ListenableFuture<Collection<Inclusion>> extractInclusionsAsync(
409413
getIncludesOutput(
410414
file, actionExecutionContext.getPathResolver(), fileType, placeNextToFile);
411415
if (!inMemoryOutput) {
412-
AbstractAction.deleteOutput(output, placeNextToFile ? file.getRoot() : null);
416+
AbstractAction.deleteOutput(
417+
output,
418+
placeNextToFile
419+
? actionExecutionContext.getPathResolver().transformRoot(file.getRoot().getRoot())
420+
: null);
413421
if (!placeNextToFile) {
414422
output.getParentDirectory().createDirectoryAndParents();
415423
}

src/test/shell/bazel/remote/remote_execution_test.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1667,6 +1667,24 @@ function test_download_toplevel_no_remote_execution() {
16671667
|| fail "Failed to run bazel build --remote_download_toplevel"
16681668
}
16691669

1670+
function test_download_toplevel_can_delete_directory_outputs() {
1671+
cat > BUILD <<'EOF'
1672+
genrule(
1673+
name = 'g',
1674+
outs = ['out'],
1675+
cmd = "touch $@",
1676+
)
1677+
EOF
1678+
bazel build
1679+
mkdir $(bazel info bazel-genfiles)/out
1680+
touch $(bazel info bazel-genfiles)/out/f
1681+
bazel build \
1682+
--remote_download_toplevel \
1683+
--remote_executor=grpc://localhost:${worker_port} \
1684+
//:g \
1685+
|| fail "should have worked"
1686+
}
1687+
16701688
function test_tag_no_remote_cache() {
16711689
mkdir -p a
16721690
cat > a/BUILD <<'EOF'

0 commit comments

Comments
 (0)