Add "jsonproto" option to aquery/cquery --output flag. Closes #10421 Closes #10426. PiperOrigin-RevId: 286370369
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD index 1b2c39e..c1ed327 100644 --- a/src/main/java/com/google/devtools/build/lib/BUILD +++ b/src/main/java/com/google/devtools/build/lib/BUILD
@@ -685,6 +685,7 @@ "//third_party:guava", "//third_party:jsr305", "//third_party/protobuf:protobuf_java", + "//third_party/protobuf:protobuf_java_util", "@remoteapis//:build_bazel_remote_execution_v2_remote_execution_java_proto", ], )
diff --git a/src/main/java/com/google/devtools/build/lib/query2/BUILD b/src/main/java/com/google/devtools/build/lib/query2/BUILD index 63d5a91..3a43ae3 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/BUILD +++ b/src/main/java/com/google/devtools/build/lib/query2/BUILD
@@ -53,6 +53,7 @@ "//third_party:guava", "//third_party:jsr305", "//third_party/protobuf:protobuf_java", + "//third_party/protobuf:protobuf_java_util", ], )
diff --git a/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphProtoOutputFormatterCallback.java b/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphProtoOutputFormatterCallback.java index ee4158b..9283a24 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphProtoOutputFormatterCallback.java +++ b/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphProtoOutputFormatterCallback.java
@@ -25,6 +25,7 @@ import com.google.devtools.build.lib.skyframe.SkyframeExecutor; import com.google.devtools.build.lib.skyframe.actiongraph.ActionGraphDump; import com.google.protobuf.TextFormat; +import com.google.protobuf.util.JsonFormat; import java.io.IOException; import java.io.OutputStream; @@ -34,7 +35,8 @@ /** Defines the types of proto output this class can handle. */ public enum OutputType { BINARY("proto"), - TEXT("textproto"); + TEXT("textproto"), + JSON("jsonproto"); private final String formatName; @@ -50,6 +52,7 @@ private final OutputType outputType; private final ActionGraphDump actionGraphDump; private final AqueryActionFilter actionFilters; + private final JsonFormat.Printer jsonPrinter = JsonFormat.printer(); ActionGraphProtoOutputFormatterCallback( ExtendedEventHandler eventHandler, @@ -110,6 +113,10 @@ case TEXT: TextFormat.print(actionGraphContainer, printStream); break; + case JSON: + jsonPrinter.appendTo(actionGraphContainer, printStream); + printStream.println(); + break; default: throw new IllegalStateException("Unknown outputType " + outputType.formatName()); }
diff --git a/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphQueryEnvironment.java index 5e0e91e..00d7772 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphQueryEnvironment.java +++ b/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphQueryEnvironment.java
@@ -178,6 +178,14 @@ accessor, StreamedOutputHandler.OutputType.TEXT, actionFilters), + new ActionGraphProtoV2OutputFormatterCallback( + eventHandler, + aqueryOptions, + out, + skyframeExecutor, + accessor, + StreamedOutputHandler.OutputType.JSON, + actionFilters), new ActionGraphTextOutputFormatterCallback( eventHandler, aqueryOptions, out, skyframeExecutor, accessor, actionFilters)) : ImmutableList.of( @@ -197,6 +205,14 @@ accessor, OutputType.TEXT, actionFilters), + new ActionGraphProtoOutputFormatterCallback( + eventHandler, + aqueryOptions, + out, + skyframeExecutor, + accessor, + OutputType.JSON, + actionFilters), new ActionGraphTextOutputFormatterCallback( eventHandler, aqueryOptions, out, skyframeExecutor, accessor, actionFilters)); }
diff --git a/src/main/java/com/google/devtools/build/lib/query2/aquery/AqueryOptions.java b/src/main/java/com/google/devtools/build/lib/query2/aquery/AqueryOptions.java index da45a89..d0ed617 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/aquery/AqueryOptions.java +++ b/src/main/java/com/google/devtools/build/lib/query2/aquery/AqueryOptions.java
@@ -28,7 +28,7 @@ effectTags = {OptionEffectTag.TERMINAL_OUTPUT}, help = "The format in which the aquery results should be printed. Allowed values for aquery " - + "are: text, textproto, proto.") + + "are: text, textproto, proto, jsonproto.") public String outputFormat; @Option(
diff --git a/src/main/java/com/google/devtools/build/lib/query2/cquery/ConfiguredTargetQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/cquery/ConfiguredTargetQueryEnvironment.java index e6d82f7..5b05015 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/cquery/ConfiguredTargetQueryEnvironment.java +++ b/src/main/java/com/google/devtools/build/lib/query2/cquery/ConfiguredTargetQueryEnvironment.java
@@ -193,6 +193,14 @@ accessor, aspectResolver, OutputType.TEXT), + new ProtoOutputFormatterCallback( + eventHandler, + cqueryOptions, + out, + skyframeExecutor, + accessor, + aspectResolver, + OutputType.JSON), new BuildOutputFormatterCallback( eventHandler, cqueryOptions, out, skyframeExecutor, accessor)); }
diff --git a/src/main/java/com/google/devtools/build/lib/query2/cquery/CqueryOptions.java b/src/main/java/com/google/devtools/build/lib/query2/cquery/CqueryOptions.java index 11884c2..2de9e3a 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/cquery/CqueryOptions.java +++ b/src/main/java/com/google/devtools/build/lib/query2/cquery/CqueryOptions.java
@@ -45,8 +45,8 @@ effectTags = {OptionEffectTag.TERMINAL_OUTPUT}, help = "The format in which the cquery results should be printed. Allowed values for cquery " - + "are: label, textproto, transitions, proto. If you select 'transitions', you also " - + "have to specify the --transitions=(lite|full) option.") + + "are: label, textproto, transitions, proto, jsonproto. If you select " + + "'transitions', you also have to specify the --transitions=(lite|full) option.") public String outputFormat; @Option(
diff --git a/src/main/java/com/google/devtools/build/lib/query2/cquery/ProtoOutputFormatterCallback.java b/src/main/java/com/google/devtools/build/lib/query2/cquery/ProtoOutputFormatterCallback.java index 10eaf03..cc79c8b 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/cquery/ProtoOutputFormatterCallback.java +++ b/src/main/java/com/google/devtools/build/lib/query2/cquery/ProtoOutputFormatterCallback.java
@@ -35,6 +35,7 @@ import com.google.devtools.build.lib.skyframe.SkyframeExecutor; import com.google.protobuf.Message; import com.google.protobuf.TextFormat; +import com.google.protobuf.util.JsonFormat; import java.io.IOException; import java.io.OutputStream; import java.util.Map; @@ -45,7 +46,8 @@ /** Defines the types of proto output this class can handle. */ public enum OutputType { BINARY("proto"), - TEXT("textproto"); + TEXT("textproto"), + JSON("jsonproto"); private final String formatName; @@ -60,6 +62,7 @@ private final OutputType outputType; private final AspectResolver resolver; + private final JsonFormat.Printer jsonPrinter = JsonFormat.printer(); private AnalysisProtos.CqueryResult.Builder protoResult; @@ -108,6 +111,10 @@ case TEXT: TextFormat.print(message, printStream); break; + case JSON: + jsonPrinter.appendTo(message, printStream); + printStream.append('\n'); + break; default: throw new IllegalStateException("Unknown outputType " + outputType.formatName()); }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/v2/StreamedOutputHandler.java b/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/v2/StreamedOutputHandler.java index b857b6e..6412f03 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/v2/StreamedOutputHandler.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/v2/StreamedOutputHandler.java
@@ -16,6 +16,7 @@ import com.google.devtools.build.lib.analysis.AnalysisProtosV2.ActionGraphComponent; import com.google.devtools.build.lib.analysis.AnalysisProtosV2.ActionGraphContainer; import com.google.protobuf.CodedOutputStream; +import com.google.protobuf.util.JsonFormat; import java.io.IOException; import java.io.PrintStream; @@ -24,7 +25,8 @@ /** Defines the types of proto output this class can handle. */ public enum OutputType { BINARY("proto"), - TEXT("textproto"); + TEXT("textproto"), + JSON("jsonproto"); private final String formatName; @@ -40,6 +42,7 @@ private final OutputType outputType; private final CodedOutputStream outputStream; private final PrintStream printStream; + private final JsonFormat.Printer jsonPrinter = JsonFormat.printer(); public StreamedOutputHandler( OutputType outputType, CodedOutputStream outputStream, PrintStream printStream) { @@ -62,6 +65,10 @@ case TEXT: printStream.print(wrapperActionGraphComponent(message)); break; + case JSON: + jsonPrinter.appendTo(message, printStream); + printStream.println(); + break; } } @@ -76,6 +83,7 @@ outputStream.flush(); break; case TEXT: + case JSON: printStream.flush(); printStream.close(); break;
diff --git a/src/test/shell/integration/aquery_test.sh b/src/test/shell/integration/aquery_test.sh index 30425c1..e57d63e 100755 --- a/src/test/shell/integration/aquery_test.sh +++ b/src/test/shell/integration/aquery_test.sh
@@ -132,7 +132,6 @@ assert_not_contains "echo unused" output } - function test_aquery_include_artifacts() { local pkg="${FUNCNAME[0]}" mkdir -p "$pkg" || fail "mkdir -p $pkg" @@ -187,6 +186,32 @@ assert_not_contains "echo unused" output } +function test_aquery_jsonproto() { + local pkg="${FUNCNAME[0]}" + mkdir -p "$pkg" || fail "mkdir -p $pkg" + cat > "$pkg/BUILD" <<'EOF' +genrule( + name = "bar", + srcs = ["dummy.txt"], + outs = ["bar_out.txt"], + cmd = "echo unused > $(OUTS)", +) +EOF + echo "hello aquery" > "$pkg/in.txt" + + bazel aquery --output=jsonproto "//$pkg:bar" > output 2> "$TEST_log" \ + || fail "Expected success" + cat output >> "$TEST_log" + assert_contains "\"execPath\": \"$pkg/dummy.txt\"" output + assert_contains "\"mnemonic\": \"Genrule\"" output + assert_contains "\"mnemonic\": \".*-fastbuild\"" output + assert_contains "echo unused" output + + bazel aquery --output=jsonproto --noinclude_commandline "//$pkg:bar" > output \ + 2> "$TEST_log" || fail "Expected success" + assert_not_contains "echo unused" output +} + function test_aquery_skylark_env() { local pkg="${FUNCNAME[0]}" mkdir -p "$pkg" || fail "mkdir -p $pkg" @@ -1113,4 +1138,33 @@ assert_contains "mnemonic: \".*-fastbuild\"" output assert_contains "echo unused" output } + +function test_basic_aquery_jsonproto_v2() { + local pkg="${FUNCNAME[0]}" + mkdir -p "$pkg" || fail "mkdir -p $pkg" + cat > "$pkg/BUILD" <<'EOF' +genrule( + name = "bar", + srcs = ["dummy.txt"], + outs = ["bar_out.txt"], + cmd = "echo unused > $(OUTS)", +) +EOF + bazel aquery --incompatible_proto_output_v2 --output=jsonproto "//$pkg:bar" > output 2> "$TEST_log" \ + || fail "Expected success" + cat output >> "$TEST_log" + + # Verify than ids come in integers instead of strings. + assert_contains "\"id\": 1," output + assert_not_contains "\"id\": \"1\"" output + + # Verify that paths are broken down to path fragments. + assert_contains "\"pathFragment\": {" output + + # Verify that the appropriate action was included. + assert_contains "\"label\": \"dummy.txt\"" output + assert_contains "\"mnemonic\": \"Genrule\"" output + assert_contains "\"mnemonic\": \".*-fastbuild\"" output + assert_contains "echo unused" output +} run_suite "${PRODUCT_NAME} action graph query tests"