diff --git a/src/main/java/com/google/devtools/build/lib/query2/query/output/BUILD b/src/main/java/com/google/devtools/build/lib/query2/query/output/BUILD index 6e0365179dc7cb..861d484caf0f9e 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/query/output/BUILD +++ b/src/main/java/com/google/devtools/build/lib/query2/query/output/BUILD @@ -35,5 +35,6 @@ java_library( "//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/query/output/JSONProtoOutputFormatter.java b/src/main/java/com/google/devtools/build/lib/query2/query/output/JSONProtoOutputFormatter.java new file mode 100644 index 00000000000000..83ecb50354c1b2 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/query2/query/output/JSONProtoOutputFormatter.java @@ -0,0 +1,50 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.google.devtools.build.lib.query2.query.output; + +import com.google.devtools.build.lib.cmdline.RepositoryMapping; +import com.google.devtools.build.lib.packages.Target; +import com.google.devtools.build.lib.query2.engine.OutputFormatterCallback; +import com.google.protobuf.util.JsonFormat; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; + +/** + * An output formatter that outputs a protocol buffer json representation of a query result and + * outputs the json to the output print stream. + */ +public class JSONProtoOutputFormatter extends ProtoOutputFormatter { + @Override + public String getName() { + return "jsonproto"; + } + + private final JsonFormat.Printer jsonPrinter = JsonFormat.printer(); + + @Override + public OutputFormatterCallback createPostFactoStreamCallback( + final OutputStream out, final QueryOptions options, RepositoryMapping mainRepoMapping) { + return new OutputFormatterCallback() { + @Override + public void processOutput(Iterable partialResult) + throws IOException, InterruptedException { + for (Target target : partialResult) { + out.write( + jsonPrinter.print(toTargetProtoBuffer(target)).getBytes(StandardCharsets.UTF_8)); + } + } + }; + } +} diff --git a/src/main/java/com/google/devtools/build/lib/query2/query/output/OutputFormatters.java b/src/main/java/com/google/devtools/build/lib/query2/query/output/OutputFormatters.java index 752cc6520e49aa..41268a365a7977 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/query/output/OutputFormatters.java +++ b/src/main/java/com/google/devtools/build/lib/query2/query/output/OutputFormatters.java @@ -37,6 +37,7 @@ public static ImmutableList getDefaultFormatters() { new PackageOutputFormatter(), new LocationOutputFormatter(), new GraphOutputFormatter(), + new JSONProtoOutputFormatter(), new XmlOutputFormatter(), new ProtoOutputFormatter(), new StreamedProtoOutputFormatter()); diff --git a/src/main/java/com/google/devtools/build/lib/query2/query/output/QueryOptions.java b/src/main/java/com/google/devtools/build/lib/query2/query/output/QueryOptions.java index 185f1f067e82d1..87f036b6d987f1 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/query/output/QueryOptions.java +++ b/src/main/java/com/google/devtools/build/lib/query2/query/output/QueryOptions.java @@ -39,8 +39,9 @@ public OrderOutputConverter() { documentationCategory = OptionDocumentationCategory.QUERY, effectTags = {OptionEffectTag.TERMINAL_OUTPUT}, help = - "The format in which the query results should be printed. Allowed values for query are: " - + "build, graph, label, label_kind, location, maxrank, minrank, package, proto, xml.") + "The format in which the query results should be printed. Allowed values for query are:" + + " build, graph, jsonproto, label, label_kind, location, maxrank, minrank, package," + + " proto, xml.") public String outputFormat; @Option( diff --git a/src/test/shell/integration/bazel_query_test.sh b/src/test/shell/integration/bazel_query_test.sh index 5e2285691148cb..5dcd144c3b3222 100755 --- a/src/test/shell/integration/bazel_query_test.sh +++ b/src/test/shell/integration/bazel_query_test.sh @@ -668,7 +668,7 @@ genquery(name='q', opts = ["--output=blargh"],) EOF - local expected_error_msg="in genquery rule //starfruit:q: Invalid output format 'blargh'. Valid values are: label, label_kind, build, minrank, maxrank, package, location, graph, xml, proto" + local expected_error_msg="in genquery rule //starfruit:q: Invalid output format 'blargh'. Valid values are: label, label_kind, build, minrank, maxrank, package, location, graph, jsonproto, xml, proto" bazel build //starfruit:q >& $TEST_log && fail "Expected failure" expect_log "$expected_error_msg" } @@ -1064,4 +1064,61 @@ EOF expect_log "//${package}:hint" } +function test_same_pkg_direct_rdeps_loads_only_inputs_packages() { + mkdir -p "pkg1" + mkdir -p "pkg2" + mkdir -p "pkg3" + + cat > "pkg1/BUILD" < "pkg2/BUILD" < "pkg3/BUILD" <& $TEST_log \ + || fail "Expected success" + + expect_log "Loading package: pkg1" + expect_log "Loading package: pkg3" + # For graphless query mode, pkg2 should not be loaded because + # same_pkg_direct_rdeps only cares about the targets in the same package + # as its inputs. + expect_not_log "Loading package: pkg2" + # the result of "same_pkg_direct_rdeps(//pkg1:t2+//pkg3:t5)" + expect_log "//pkg1:t1" + expect_log "//pkg3:t4" +} + +function test_basic_query_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 + bazel query --output=jsonproto --noimplicit_deps "//$pkg:bar" > output 2> "$TEST_log" \ + || fail "Expected success" + cat output >> "$TEST_log" + + # Verify that the appropriate attributes were included. + assert_contains "\"ruleClass\": \"genrule\"" output + assert_contains "\"name\": \"//$pkg:bar\"" output + assert_contains "\"ruleInput\": \[\"//$pkg:dummy.txt\"\]" output + assert_contains "\"ruleOutput\": \[\"//$pkg:bar_out.txt\"\]" output + assert_contains "echo unused" output +} + run_suite "${PRODUCT_NAME} query tests"