Add make_executable to aquery results
Android converts bazel actions to a ninja build graph by querying the
actions with aquery, but was always outputting non-executable FileWrite
files because the executable bit was not included in the aquery results.
RELNOTES: Added whether or not a FileWrite action's output is executable to the aquery results
PiperOrigin-RevId: 559485729
Change-Id: Id3ac9d77c884bd92645b40be48f774898664dac8
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/actions/AbstractFileWriteAction.java b/src/main/java/com/google/devtools/build/lib/analysis/actions/AbstractFileWriteAction.java
index a0da40e..a6bf082 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/actions/AbstractFileWriteAction.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/actions/AbstractFileWriteAction.java
@@ -113,5 +113,7 @@
*/
public interface FileContentsProvider {
String getFileContents(@Nullable EventHandler eventHandler) throws IOException;
+
+ public boolean makeExecutable();
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphTextOutputFormatterCallback.java b/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphTextOutputFormatterCallback.java
index 99609af..a659fbb 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphTextOutputFormatterCallback.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphTextOutputFormatterCallback.java
@@ -317,14 +317,17 @@
stringBuilder.append(" ]\n");
}
- if (options.includeFileWriteContents
- && action instanceof AbstractFileWriteAction.FileContentsProvider) {
- String contents =
- ((AbstractFileWriteAction.FileContentsProvider) action).getFileContents(eventHandler);
- stringBuilder
- .append(" FileWriteContents: [")
- .append(Base64.getEncoder().encodeToString(contents.getBytes(UTF_8)))
- .append("]\n");
+ if (action instanceof AbstractFileWriteAction.FileContentsProvider) {
+ AbstractFileWriteAction.FileContentsProvider fileAction =
+ (AbstractFileWriteAction.FileContentsProvider) action;
+ stringBuilder.append(String.format(" IsExecutable: %b\n", fileAction.makeExecutable()));
+ if (options.includeFileWriteContents) {
+ String contents = fileAction.getFileContents(eventHandler);
+ stringBuilder
+ .append(" FileWriteContents: [")
+ .append(Base64.getEncoder().encodeToString(contents.getBytes(UTF_8)))
+ .append("]\n");
+ }
}
if (action instanceof UnresolvedSymlinkAction) {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/v2/ActionGraphDump.java b/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/v2/ActionGraphDump.java
index 0dc5c0b..9f247f5 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/v2/ActionGraphDump.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/v2/ActionGraphDump.java
@@ -195,13 +195,17 @@
actionBuilder.addAllArguments(commandAction.getArguments());
}
- if (includeFileWriteContents
- && action instanceof AbstractFileWriteAction.FileContentsProvider) {
- String contents =
- ((AbstractFileWriteAction.FileContentsProvider) action).getFileContents(eventHandler);
- actionBuilder.setFileContents(contents);
+ if (action instanceof AbstractFileWriteAction.FileContentsProvider) {
+ actionBuilder.setIsExecutable(
+ ((AbstractFileWriteAction.FileContentsProvider) action).makeExecutable());
+ if (includeFileWriteContents) {
+ String contents =
+ ((AbstractFileWriteAction.FileContentsProvider) action).getFileContents(eventHandler);
+ actionBuilder.setFileContents(contents);
+ }
}
+
if (action instanceof UnresolvedSymlinkAction) {
actionBuilder.setUnresolvedSymlinkTarget(
((UnresolvedSymlinkAction) action).getTarget().toString());
diff --git a/src/main/protobuf/analysis_v2.proto b/src/main/protobuf/analysis_v2.proto
index cfe4d76..20fa8e7 100644
--- a/src/main/protobuf/analysis_v2.proto
+++ b/src/main/protobuf/analysis_v2.proto
@@ -113,13 +113,17 @@
// to.
repeated KeyValuePair substitutions = 16;
- // The contents of the file for the actions.write() action
+ // The contents of the file for the ctx.actions.write() action
// (guarded by the --include_file_write_contents flag).
string file_contents = 17;
// The target of the symlink created by UnresolvedSymlink actions.
// For regular Symlink actions, the target is represented as an input.
string unresolved_symlink_target = 18;
+
+ // If FileWrite actions should make their output executable.
+ // (ctx.actions.write(is_executable=True))
+ bool is_executable = 19;
}
// Represents a single target (without configuration information) that is
diff --git a/src/test/shell/integration/aquery_test.sh b/src/test/shell/integration/aquery_test.sh
index 1fa9009..70fc640 100755
--- a/src/test/shell/integration/aquery_test.sh
+++ b/src/test/shell/integration/aquery_test.sh
@@ -1703,11 +1703,54 @@
assert_contains "Mnemonic: FileWrite" output
# FileWrite contents is base64-encoded 'hello world'
assert_contains "FileWriteContents: \[aGVsbG8gd29ybGQ=\]" output
+ assert_contains "^ *IsExecutable: false" output
bazel aquery --output=textproto --include_file_write_contents "//$pkg:bar" > output 2> "$TEST_log" \
|| fail "Expected success"
cat output >> "$TEST_log"
assert_contains 'file_contents: "hello world"' output
+ assert_not_contains "^is_executable: true" output
+}
+
+function test_file_write_is_executable() {
+ local pkg="${FUNCNAME[0]}"
+ mkdir -p "$pkg" || fail "mkdir -p $pkg"
+ touch "$pkg/foo.sh"
+ cat > "$pkg/write_executable_file.bzl" <<'EOF'
+def _impl(ctx):
+ out = ctx.actions.declare_symlink(ctx.label.name)
+ ctx.actions.write(
+ output = out,
+ content = "Hello",
+ is_executable = True,
+ )
+ return [
+ DefaultInfo(files = depset([out]))
+ ]
+write_executable_file = rule(
+ implementation = _impl,
+ attrs = {
+ "path": attr.string(),
+ },
+)
+EOF
+ cat > "$pkg/BUILD" <<'EOF'
+load(":write_executable_file.bzl", "write_executable_file")
+write_executable_file(
+ name = "foo",
+ path = "bar/baz.txt",
+)
+EOF
+ bazel aquery --output=textproto \
+ "//$pkg:foo" >output 2> "$TEST_log" || fail "Expected success"
+ cat output >> "$TEST_log"
+ assert_contains "^is_executable: true" output
+
+ bazel aquery --output=text "//$pkg:foo" | \
+ sed -nr '/Mnemonic: FileWrite/,/^ *$/p' >output \
+ 2> "$TEST_log" || fail "Expected success"
+ cat output >> "$TEST_log"
+ assert_contains "^ *IsExecutable: true" output
}
function test_source_symlink_manifest() {