Further improve error message.
RELNOTES: None
PiperOrigin-RevId: 269829330
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/RunCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/RunCommand.java
index 73136dd..12b400b 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/RunCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/RunCommand.java
@@ -15,9 +15,11 @@
package com.google.devtools.build.lib.runtime.commands;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.devtools.build.lib.actions.Artifact;
@@ -147,11 +149,6 @@
private static final class NoShellFoundException extends Exception {}
@VisibleForTesting
- public static final String SINGLE_TARGET_MESSAGE =
- "Only a single target can be run. Do not use target patterns that expand to more than one "
- + "target, or a test_suite that expands to more than one test";
-
- @VisibleForTesting
public static final String NO_TARGET_MESSAGE = "No targets found to run";
public static final String MULTIPLE_TESTS_MESSAGE =
@@ -172,9 +169,13 @@
@VisibleForTesting // productionVisibility = Visibility.PRIVATE
protected BuildResult processRequest(final CommandEnvironment env, BuildRequest request) {
- return new BuildTool(env).processRequest(request,
- (Collection<Target> targets, boolean keepGoing) ->
- RunCommand.this.validateTargets(env.getReporter(), targets, keepGoing));
+ List<String> targetPatternStrings = request.getTargets();
+ return new BuildTool(env)
+ .processRequest(
+ request,
+ (Collection<Target> targets, boolean keepGoing) ->
+ RunCommand.this.validateTargets(
+ env.getReporter(), targetPatternStrings, targets, keepGoing));
}
@Override
@@ -317,7 +318,12 @@
if (targetsBuilt != null) {
int maxTargets = runUnder != null && runUnder.getLabel() != null ? 2 : 1;
if (targetsBuilt.size() > maxTargets) {
- env.getReporter().handle(Event.error(SINGLE_TARGET_MESSAGE));
+ env.getReporter()
+ .handle(
+ Event.error(
+ makeErrorMessageForNotHavingASingleTarget(
+ targetString,
+ Iterables.transform(targetsBuilt, ct -> ct.getLabel().toString()))));
return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
for (ConfiguredTarget target : targetsBuilt) {
@@ -335,7 +341,12 @@
} else if (targetToRun == null) {
targetToRun = target;
} else {
- env.getReporter().handle(Event.error(SINGLE_TARGET_MESSAGE));
+ env.getReporter()
+ .handle(
+ Event.error(
+ makeErrorMessageForNotHavingASingleTarget(
+ targetString,
+ Iterables.transform(targetsBuilt, ct -> ct.getLabel().toString()))));
return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
}
@@ -617,7 +628,11 @@
// Make sure we are building exactly 1 binary target.
// If keepGoing, we'll build all the targets even if they are non-binary.
- private void validateTargets(Reporter reporter, Collection<Target> targets, boolean keepGoing)
+ private void validateTargets(
+ Reporter reporter,
+ List<String> targetPatternStrings,
+ Collection<Target> targets,
+ boolean keepGoing)
throws LoadingFailedException {
Target targetToRun = null;
Target runUnderTarget = null;
@@ -625,7 +640,12 @@
boolean singleTargetWarningWasOutput = false;
int maxTargets = currentRunUnder != null && currentRunUnder.getLabel() != null ? 2 : 1;
if (targets.size() > maxTargets) {
- warningOrException(reporter, SINGLE_TARGET_MESSAGE, keepGoing);
+ warningOrException(
+ reporter,
+ makeErrorMessageForNotHavingASingleTarget(
+ targetPatternStrings.get(0),
+ Iterables.transform(targets, t -> t.getLabel().toString())),
+ keepGoing);
singleTargetWarningWasOutput = true;
}
for (Target target : targets) {
@@ -642,7 +662,12 @@
targetToRun = target;
} else {
if (!singleTargetWarningWasOutput) {
- warningOrException(reporter, SINGLE_TARGET_MESSAGE, keepGoing);
+ warningOrException(
+ reporter,
+ makeErrorMessageForNotHavingASingleTarget(
+ targetPatternStrings.get(0),
+ Iterables.transform(targets, t -> t.getLabel().toString())),
+ keepGoing);
}
return;
}
@@ -764,4 +789,19 @@
Rule rule = (Rule) target;
return rule.getRuleClass().equals("alias") || rule.getRuleClass().equals("bind");
}
+
+ private String makeErrorMessageForNotHavingASingleTarget(
+ String targetPatternString, Iterable<String> expandedTargetNames) {
+ final int maxNumExpandedTargetsToIncludeInErrorMessage = 5;
+ boolean truncateTargetNameList = Iterables.size(expandedTargetNames) > 5;
+ Iterable<String> targetNamesToIncludeInErrorMessage =
+ truncateTargetNameList
+ ? Iterables.limit(expandedTargetNames, maxNumExpandedTargetsToIncludeInErrorMessage)
+ : expandedTargetNames;
+ return String.format(
+ "Only a single target can be run. Your target pattern %s expanded to the targets %s%s",
+ targetPatternString,
+ Joiner.on(", ").join(ImmutableSortedSet.copyOf(targetNamesToIncludeInErrorMessage)),
+ truncateTargetNameList ? "[TRUNCATED]" : "");
+ }
}