Skip to content

Commit

Permalink
[6.5.0] Fix tree file materialized as symlink to another file when bu…
Browse files Browse the repository at this point in the history
…ilding without the bytes. (#20409)

This is the same bug as #19143, except that the fix in 3a48457 missed
the case where the symlink occurs inside an output directory.

Fixes #20408.
  • Loading branch information
tjgq authored Dec 7, 2023
1 parent 50b61e3 commit 9433840
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1100,7 +1100,7 @@ public InMemoryOutput downloadOutputs(RemoteAction action, RemoteActionResult re
ImmutableList.Builder<ListenableFuture<FileMetadata>> downloadsBuilder =
ImmutableList.builder();

boolean downloadOutputs = shouldDownloadOutputsFor(result);
boolean downloadOutputs = shouldDownloadOutputsFor(result, metadata);

// Download into temporary paths, then move everything at the end.
// This avoids holding the output lock while downloading, which would prevent the local branch
Expand Down Expand Up @@ -1251,13 +1251,13 @@ public InMemoryOutput downloadOutputs(RemoteAction action, RemoteActionResult re
return null;
}

private boolean shouldDownloadOutputsFor(RemoteActionResult result) {
private boolean shouldDownloadOutputsFor(RemoteActionResult result,
ActionResultMetadata metadata) {
if (remoteOptions.remoteOutputsMode.downloadAllOutputs()) {
return true;
}
// An output materialized as a symlink might point to one of the other outputs.
if (!result.getOutputSymlinks().isEmpty() || !result.getOutputFileSymlinks().isEmpty()
|| !result.getOutputDirectorySymlinks().isEmpty()) {
if (resultHasSymlinks(result, metadata)) {
return true;
}
// In case the action failed, download all outputs. It might be helpful for debugging and there
Expand All @@ -1268,6 +1268,18 @@ private boolean shouldDownloadOutputsFor(RemoteActionResult result) {
return false;
}

private boolean resultHasSymlinks(RemoteActionResult result, ActionResultMetadata metadata) {
if (!metadata.symlinks().isEmpty()) {
return true;
}
for (Entry<Path, DirectoryMetadata> entry : metadata.directories()) {
if (!entry.getValue().symlinks().isEmpty()) {
return true;
}
}
return false;
}

private ImmutableList<ListenableFuture<FileMetadata>> buildFilesToDownload(
RemoteActionExecutionContext context,
ProgressStatusListener progressStatusListener,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -713,13 +713,39 @@ public void downloadTopLevel_genruleSymlinkToOutput() throws Exception {

// Delete target, re-download it
getOutputPath("foo").delete();

buildTarget("//:gen");

assertSymlink("foo-link", PathFragment.create("foo"));
assertValidOutputFile("foo-link", "hello\n");
}

@Test
public void downloadTopLevel_treeContainingSymlink() throws Exception {
// Disable test on Windows.
assumeFalse(OS.getCurrent() == OS.WINDOWS);

setDownloadToplevel();
write("tree.bzl", "def _impl(ctx):",
" d = ctx.actions.declare_directory(ctx.label.name)",
" ctx.actions.run_shell(",
" outputs = [d],",
" command = 'cd {} && echo hello > file.txt && ln -s file.txt sym.txt'.format(d.path),",
" )",
" return DefaultInfo(files = depset([d]))",
"tree = rule(_impl)");
write(
"BUILD",
"load('tree.bzl', 'tree')",
"tree(",
" name = 'tree',",
")");

buildTarget("//:tree");

assertSymlink("tree/sym.txt", PathFragment.create("file.txt"));
assertValidOutputFile("tree/sym.txt", "hello\n");
}

protected void assertSymlink(String binRelativeLinkPath, PathFragment targetPath)
throws Exception {
Path output = getOutputPath(binRelativeLinkPath);
Expand Down

0 comments on commit 9433840

Please sign in to comment.