Skip to content

Commit ee32eff

Browse files
authored
[6.2.0] Allows --query_file to be used for cquery and aquery too. (bazelbuild#17823)
Fixes bazelbuild#12924. RELNOTES[NEW]: The aquery and cquery commands now respect the --query_file flag just like the query command. PiperOrigin-RevId: 487689456 Change-Id: Ia2c9d85e88fdf769a823eaf7b6585a77d654ae70
1 parent a87b8e0 commit ee32eff

File tree

9 files changed

+137
-58
lines changed

9 files changed

+137
-58
lines changed

src/main/java/com/google/devtools/build/lib/query2/common/CommonQueryOptions.java

+10
Original file line numberDiff line numberDiff line change
@@ -326,4 +326,14 @@ public AspectResolutionModeConverter() {
326326
+ "will be merged together and their labels concatenated. This option is only "
327327
+ "applicable to --output=graph.")
328328
public boolean graphFactored;
329+
330+
@Option(
331+
name = "query_file",
332+
defaultValue = "",
333+
documentationCategory = OptionDocumentationCategory.QUERY,
334+
effectTags = {OptionEffectTag.CHANGES_INPUTS},
335+
help =
336+
"If set, query will read the query from the file named here, rather than on the command "
337+
+ "line. It is an error to specify a file here as well as a command-line query.")
338+
public String queryFile;
329339
}

src/main/java/com/google/devtools/build/lib/query2/query/output/QueryOptions.java

-11
Original file line numberDiff line numberDiff line change
@@ -167,17 +167,6 @@ public enum OrderOutput {
167167
)
168168
public boolean strictTestSuite;
169169

170-
@Option(
171-
name = "query_file",
172-
defaultValue = "",
173-
documentationCategory = OptionDocumentationCategory.QUERY,
174-
effectTags = {OptionEffectTag.CHANGES_INPUTS},
175-
help =
176-
"If set, query will read the query from the file named here, rather than on the command "
177-
+ "line. It is an error to specify a file here as well as a command-line query."
178-
)
179-
public String queryFile;
180-
181170
@Option(
182171
name = "experimental_graphless_query",
183172
defaultValue = "auto",

src/main/java/com/google/devtools/build/lib/runtime/commands/AqueryCommand.java

+5-8
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
// limitations under the License.
1414
package com.google.devtools.build.lib.runtime.commands;
1515

16-
import com.google.common.base.Joiner;
1716
import com.google.common.base.Strings;
1817
import com.google.common.collect.ImmutableList;
1918
import com.google.common.collect.ImmutableMap;
@@ -101,15 +100,13 @@ public BlazeCommandResult exec(CommandEnvironment env, OptionsParsingResult opti
101100
InterruptedFailureDetails.detailedExitCode(errorMessage));
102101
}
103102

104-
// When querying for the state of Skyframe, it's possible to omit the query expression.
105-
if (options.getResidue().isEmpty() && !queryCurrentSkyframeState) {
106-
String message =
107-
"Missing query expression. Use the 'help aquery' command for syntax and help.";
108-
env.getReporter().handle(Event.error(message));
109-
return createFailureResult(message, Code.COMMAND_LINE_EXPRESSION_MISSING);
103+
String query = null;
104+
try {
105+
query = QueryOptionHelper.readQuery(aqueryOptions, options, env, queryCurrentSkyframeState);
106+
} catch (QueryException e) {
107+
return BlazeCommandResult.failureDetail(e.getFailureDetail());
110108
}
111109

112-
String query = Joiner.on(' ').join(options.getResidue());
113110
ImmutableMap<String, QueryFunction> functions = getFunctionsMap(env);
114111

115112
// Query expression might be null in the case of --skyframe_state.

src/main/java/com/google/devtools/build/lib/runtime/commands/BUILD

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ java_library(
6565
"//src/main/java/com/google/devtools/build/lib/profiler/memory:allocationtracker",
6666
"//src/main/java/com/google/devtools/build/lib/query2",
6767
"//src/main/java/com/google/devtools/build/lib/query2/common:abstract-blaze-query-env",
68+
"//src/main/java/com/google/devtools/build/lib/query2/common:options",
6869
"//src/main/java/com/google/devtools/build/lib/query2/common:universe-scope",
6970
"//src/main/java/com/google/devtools/build/lib/query2/engine",
7071
"//src/main/java/com/google/devtools/build/lib/query2/query/output",

src/main/java/com/google/devtools/build/lib/runtime/commands/CqueryCommand.java

+9-7
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
// limitations under the License.
1414
package com.google.devtools.build.lib.runtime.commands;
1515

16-
import com.google.common.base.Joiner;
1716
import com.google.common.collect.ImmutableList;
1817
import com.google.devtools.build.lib.analysis.config.CoreOptions.IncludeConfigFragmentsEnum;
1918
import com.google.devtools.build.lib.buildtool.BuildRequest;
@@ -27,6 +26,7 @@
2726
import com.google.devtools.build.lib.query2.cquery.ConfiguredTargetQueryEnvironment;
2827
import com.google.devtools.build.lib.query2.cquery.CqueryOptions;
2928
import com.google.devtools.build.lib.query2.engine.QueryEnvironment.QueryFunction;
29+
import com.google.devtools.build.lib.query2.engine.QueryException;
3030
import com.google.devtools.build.lib.query2.engine.QueryExpression;
3131
import com.google.devtools.build.lib.query2.engine.QueryParser;
3232
import com.google.devtools.build.lib.query2.engine.QuerySyntaxException;
@@ -133,13 +133,15 @@ public BlazeCommandResult exec(CommandEnvironment env, OptionsParsingResult opti
133133
InterruptedFailureDetails.detailedExitCode(errorMessage));
134134
}
135135

136-
if (options.getResidue().isEmpty()) {
137-
String message =
138-
"Missing query expression. Use the 'help cquery' command for syntax and help.";
139-
env.getReporter().handle(Event.error(message));
140-
return createFailureResult(message, Code.COMMAND_LINE_EXPRESSION_MISSING);
136+
String query = null;
137+
try {
138+
query =
139+
QueryOptionHelper.readQuery(
140+
options.getOptions(CqueryOptions.class), options, env, /* allowEmptyQuery= */ false);
141+
} catch (QueryException e) {
142+
return BlazeCommandResult.failureDetail(e.getFailureDetail());
141143
}
142-
String query = Joiner.on(' ').join(options.getResidue());
144+
143145
HashMap<String, QueryFunction> functions = new HashMap<>();
144146
for (QueryFunction queryFunction : ConfiguredTargetQueryEnvironment.FUNCTIONS) {
145147
functions.put(queryFunction.getName(), queryFunction);

src/main/java/com/google/devtools/build/lib/runtime/commands/QueryEnvironmentBasedCommand.java

+6-32
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
import static com.google.devtools.build.lib.packages.Rule.ALL_LABELS;
1717

18-
import com.google.common.base.Joiner;
1918
import com.google.common.collect.ImmutableList;
2019
import com.google.devtools.build.lib.analysis.NoBuildEvent;
2120
import com.google.devtools.build.lib.analysis.NoBuildRequestFinishedEvent;
@@ -32,6 +31,7 @@
3231
import com.google.devtools.build.lib.query2.engine.QueryEnvironment;
3332
import com.google.devtools.build.lib.query2.engine.QueryEnvironment.Setting;
3433
import com.google.devtools.build.lib.query2.engine.QueryEvalResult;
34+
import com.google.devtools.build.lib.query2.engine.QueryException;
3535
import com.google.devtools.build.lib.query2.query.output.OutputFormatter;
3636
import com.google.devtools.build.lib.query2.query.output.OutputFormatters;
3737
import com.google.devtools.build.lib.query2.query.output.QueryOptions;
@@ -57,13 +57,9 @@
5757
import com.google.devtools.build.lib.util.Either;
5858
import com.google.devtools.build.lib.util.ExitCode;
5959
import com.google.devtools.build.lib.util.InterruptedFailureDetails;
60-
import com.google.devtools.build.lib.vfs.FileSystemUtils;
61-
import com.google.devtools.build.lib.vfs.Path;
6260
import com.google.devtools.build.skyframe.WalkableGraph;
6361
import com.google.devtools.common.options.OptionsParsingResult;
6462
import com.google.devtools.common.options.TriState;
65-
import java.io.IOException;
66-
import java.nio.charset.StandardCharsets;
6763
import java.util.Set;
6864
import java.util.function.Function;
6965

@@ -125,33 +121,11 @@ private BlazeCommandResult execInternal(CommandEnvironment env, OptionsParsingRe
125121
return BlazeCommandResult.detailedExitCode(e.getDetailedExitCode());
126122
}
127123

128-
String query;
129-
if (!options.getResidue().isEmpty()) {
130-
if (!queryOptions.queryFile.isEmpty()) {
131-
return reportAndCreateFailureResult(
132-
env,
133-
"Command-line query and --query_file cannot both be specified",
134-
Query.Code.QUERY_FILE_WITH_COMMAND_LINE_EXPRESSION);
135-
}
136-
query = Joiner.on(' ').join(options.getResidue());
137-
} else if (!queryOptions.queryFile.isEmpty()) {
138-
// Works for absolute or relative query file.
139-
Path residuePath = env.getWorkingDirectory().getRelative(queryOptions.queryFile);
140-
try {
141-
query = new String(FileSystemUtils.readContent(residuePath), StandardCharsets.UTF_8);
142-
} catch (IOException e) {
143-
return reportAndCreateFailureResult(
144-
env,
145-
"I/O error reading from " + residuePath.getPathString(),
146-
Query.Code.QUERY_FILE_READ_FAILURE);
147-
}
148-
} else {
149-
return reportAndCreateFailureResult(
150-
env,
151-
String.format(
152-
"missing query expression. Type '%s help query' for syntax and help",
153-
runtime.getProductName()),
154-
Query.Code.COMMAND_LINE_EXPRESSION_MISSING);
124+
String query = null;
125+
try {
126+
query = QueryOptionHelper.readQuery(queryOptions, options, env, /* allowEmptyQuery =*/ false);
127+
} catch (QueryException e) {
128+
return BlazeCommandResult.failureDetail(e.getFailureDetail());
155129
}
156130

157131
Iterable<OutputFormatter> formatters = runtime.getQueryOutputFormatters();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Copyright 2022 The Bazel Authors. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.package com.google.devtools.build.lib.runtime.commands;
14+
package com.google.devtools.build.lib.runtime.commands;
15+
16+
import static java.nio.charset.StandardCharsets.UTF_8;
17+
18+
import com.google.common.base.Joiner;
19+
import com.google.devtools.build.lib.query2.common.CommonQueryOptions;
20+
import com.google.devtools.build.lib.query2.engine.QueryException;
21+
import com.google.devtools.build.lib.runtime.CommandEnvironment;
22+
import com.google.devtools.build.lib.server.FailureDetails.Query;
23+
import com.google.devtools.build.lib.vfs.FileSystemUtils;
24+
import com.google.devtools.build.lib.vfs.Path;
25+
import com.google.devtools.common.options.OptionsParsingResult;
26+
import java.io.IOException;
27+
28+
/**
29+
* Reads the query for query, cquery and aquery using the --query_file option or from the residue of
30+
* the command line.
31+
*/
32+
public final class QueryOptionHelper {
33+
34+
public static String readQuery(
35+
CommonQueryOptions queryOptions,
36+
OptionsParsingResult options,
37+
CommandEnvironment env,
38+
boolean allowEmptyQuery)
39+
throws QueryException {
40+
String query = "";
41+
if (!options.getResidue().isEmpty()) {
42+
if (!queryOptions.queryFile.isEmpty()) {
43+
throw new QueryException(
44+
"Command-line query and --query_file cannot both be specified",
45+
Query.Code.QUERY_FILE_WITH_COMMAND_LINE_EXPRESSION);
46+
}
47+
query = Joiner.on(' ').join(options.getResidue());
48+
} else if (!queryOptions.queryFile.isEmpty()) {
49+
// Works for absolute or relative query file.
50+
Path residuePath = env.getWorkingDirectory().getRelative(queryOptions.queryFile);
51+
try {
52+
query = new String(FileSystemUtils.readContent(residuePath), UTF_8);
53+
} catch (IOException unused) {
54+
throw new QueryException(
55+
"I/O error reading from " + residuePath.getPathString(),
56+
Query.Code.QUERY_FILE_READ_FAILURE);
57+
}
58+
} else {
59+
// When querying for the state of Skyframe, it's possible to omit the query expression.
60+
if (!allowEmptyQuery) {
61+
throw new QueryException(
62+
String.format(
63+
"missing query expression. Type '%s help query' for syntax and help",
64+
env.getRuntime().getProductName()),
65+
Query.Code.COMMAND_LINE_EXPRESSION_MISSING);
66+
}
67+
}
68+
return query;
69+
}
70+
71+
private QueryOptionHelper() {}
72+
}

src/test/shell/integration/aquery_test.sh

+19
Original file line numberDiff line numberDiff line change
@@ -1665,6 +1665,25 @@ EOF
16651665
fi
16661666
}
16671667

1668+
function test_does_not_fail_horribly_with_file() {
1669+
rm -rf peach
1670+
mkdir -p peach
1671+
cat > "peach/BUILD" <<'EOF'
1672+
genrule(
1673+
name = "bar",
1674+
srcs = ["dummy.txt"],
1675+
outs = ["bar_out.txt"],
1676+
cmd = "echo unused > bar_out.txt",
1677+
)
1678+
EOF
1679+
1680+
echo "//peach:bar" > query_file
1681+
bazel aquery --query_file=query_file > $TEST_log
1682+
1683+
expect_log "Target: //peach:bar" "look in $TEST_log"
1684+
expect_log "ActionKey:"
1685+
}
1686+
16681687
function test_cpp_compile_action_env() {
16691688
local pkg="${FUNCNAME[0]}"
16701689
mkdir -p "$pkg"

src/test/shell/integration/configured_query_test.sh

+15
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,21 @@ EOF
14611461
expect_not_log "QueryException"
14621462
}
14631463

1464+
function test_does_not_fail_horribly_with_file() {
1465+
rm -rf peach
1466+
mkdir -p peach
1467+
cat > peach/BUILD <<EOF
1468+
sh_library(name='brighton', deps=[':harken'])
1469+
sh_library(name='harken')
1470+
EOF
1471+
1472+
echo "deps(//peach:brighton)" > query_file
1473+
bazel cquery --query_file=query_file > $TEST_log
1474+
1475+
expect_log "//peach:brighton"
1476+
expect_log "//peach:harken"
1477+
}
1478+
14641479
function test_files_include_source_files() {
14651480
local -r pkg=$FUNCNAME
14661481
mkdir -p $pkg

0 commit comments

Comments
 (0)