Update Command to implement DescribableExecutionUnit.
PiperOrigin-RevId: 398330385
diff --git a/src/main/java/com/google/devtools/build/lib/shell/BUILD b/src/main/java/com/google/devtools/build/lib/shell/BUILD
index 985c866..9f27331 100644
--- a/src/main/java/com/google/devtools/build/lib/shell/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/shell/BUILD
@@ -17,6 +17,7 @@
name = "shell",
srcs = glob(["*.java"]),
deps = [
+ "//src/main/java/com/google/devtools/build/lib/util:describable_execution_unit",
"//src/main/java/com/google/devtools/build/lib/vfs",
"//src/main/protobuf:execution_statistics_java_proto",
"//third_party:auto_value",
diff --git a/src/main/java/com/google/devtools/build/lib/shell/Command.java b/src/main/java/com/google/devtools/build/lib/shell/Command.java
index 83c3915..7ca600c 100644
--- a/src/main/java/com/google/devtools/build/lib/shell/Command.java
+++ b/src/main/java/com/google/devtools/build/lib/shell/Command.java
@@ -16,16 +16,17 @@
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.flogger.GoogleLogger;
import com.google.common.flogger.LazyArgs;
import com.google.common.io.ByteStreams;
import com.google.devtools.build.lib.shell.Consumers.OutErrConsumers;
+import com.google.devtools.build.lib.util.DescribableExecutionUnit;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.Duration;
-import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
@@ -122,7 +123,7 @@
* lookup, output redirection, pipelines, etc) are needed, call it directly without using a shell,
* as in the {@code du(1)} example above.
*/
-public final class Command {
+public final class Command implements DescribableExecutionUnit {
private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();
@@ -206,13 +207,15 @@
}
/** Returns the raw command line elements to be executed */
- public String[] getCommandLineElements() {
- final List<String> elements = subprocessBuilder.getArgv();
- return elements.toArray(new String[elements.size()]);
+ @Override
+ public ImmutableList<String> getArguments() {
+ return subprocessBuilder.getArgv();
}
/** Returns an (unmodifiable) {@link Map} view of command's environment variables or null. */
- @Nullable public Map<String, String> getEnvironmentVariables() {
+ @Override
+ @Nullable
+ public ImmutableMap<String, String> getEnvironment() {
return subprocessBuilder.getEnv();
}
diff --git a/src/main/java/com/google/devtools/build/lib/util/CommandUtils.java b/src/main/java/com/google/devtools/build/lib/util/CommandUtils.java
index 7082cbc..3bec531 100644
--- a/src/main/java/com/google/devtools/build/lib/util/CommandUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/util/CommandUtils.java
@@ -19,9 +19,6 @@
import com.google.devtools.build.lib.shell.Command;
import com.google.devtools.build.lib.shell.CommandException;
import com.google.devtools.build.lib.shell.CommandResult;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Map;
/**
* Utility methods relating to the {@link Command} class.
@@ -31,16 +28,6 @@
private CommandUtils() {} // Prevent instantiation.
@VisibleForTesting
- static Collection<String> commandLine(Command command) {
- return Arrays.asList(command.getCommandLineElements());
- }
-
- @VisibleForTesting
- static Map<String, String> env(Command command) {
- return command.getEnvironmentVariables();
- }
-
- @VisibleForTesting
static String cwd(Command command) {
return command.getWorkingDirectory() == null ? null : command.getWorkingDirectory().getPath();
}
@@ -48,22 +35,15 @@
/**
* Construct an error message that describes a failed command invocation.
* Currently this returns a message of the form "foo failed: error executing
- * command /dir/foo bar baz".
- */
- public static String describeCommandFailure(boolean verbose, Command command) {
- return CommandFailureUtils.describeCommandFailure(
- verbose, commandLine(command), env(command), cwd(command), null);
- }
-
- /**
- * Construct an error message that describes a failed command invocation.
- * Currently this returns a message of the form "foo failed: error executing
* command /dir/foo bar baz: exception message", with the
* command's stdout and stderr output appended if available.
*/
public static String describeCommandFailure(boolean verbose, CommandException exception) {
- String message = describeCommandFailure(verbose, exception.getCommand()) + ": "
- + exception.getMessage();
+ Command command = exception.getCommand();
+ String message =
+ CommandFailureUtils.describeCommandFailure(verbose, cwd(command), command)
+ + ": "
+ + exception.getMessage();
if (exception instanceof AbnormalTerminationException) {
CommandResult result = ((AbnormalTerminationException) exception).getResult();
try {
diff --git a/src/test/java/com/google/devtools/build/lib/exec/SymlinkTreeHelperTest.java b/src/test/java/com/google/devtools/build/lib/exec/SymlinkTreeHelperTest.java
index 8bb5fa8..a15756c 100644
--- a/src/test/java/com/google/devtools/build/lib/exec/SymlinkTreeHelperTest.java
+++ b/src/test/java/com/google/devtools/build/lib/exec/SymlinkTreeHelperTest.java
@@ -45,13 +45,13 @@
Command command =
new SymlinkTreeHelper(inputManifestPath, execRoot.getRelative("output/MANIFEST"), false)
.createCommand(execRoot, binTools, ImmutableMap.of());
- assertThat(command.getEnvironmentVariables()).isEmpty();
+ assertThat(command.getEnvironment()).isEmpty();
assertThat(command.getWorkingDirectory()).isEqualTo(execRoot.getPathFile());
- String[] commandLine = command.getCommandLineElements();
- assertThat(commandLine).hasLength(3);
- assertThat(commandLine[0]).endsWith(SymlinkTreeHelper.BUILD_RUNFILES);
- assertThat(commandLine[1]).isEqualTo("input_manifest");
- assertThat(commandLine[2]).isEqualTo("output/MANIFEST");
+ ImmutableList<String> commandLine = command.getArguments();
+ assertThat(commandLine).hasSize(3);
+ assertThat(commandLine.get(0)).endsWith(SymlinkTreeHelper.BUILD_RUNFILES);
+ assertThat(commandLine.get(1)).isEqualTo("input_manifest");
+ assertThat(commandLine.get(2)).isEqualTo("output/MANIFEST");
}
@Test
diff --git a/src/test/java/com/google/devtools/build/lib/shell/CommandTest.java b/src/test/java/com/google/devtools/build/lib/shell/CommandTest.java
index 0543e07..7091291 100644
--- a/src/test/java/com/google/devtools/build/lib/shell/CommandTest.java
+++ b/src/test/java/com/google/devtools/build/lib/shell/CommandTest.java
@@ -15,7 +15,6 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
-import static com.google.devtools.build.lib.shell.TestUtil.assertArrayEquals;
import static org.junit.Assert.assertThrows;
import com.google.common.collect.ImmutableMap;
@@ -71,9 +70,9 @@
Map<String, String> env = Collections.singletonMap("foo", "bar");
String[] commandArgs = new String[] { "command" };
Command command = new Command(commandArgs, env, workingDir);
- assertArrayEquals(commandArgs, command.getCommandLineElements());
+ assertThat(command.getArguments()).containsExactlyElementsIn(commandArgs);
for (String key : env.keySet()) {
- assertThat(command.getEnvironmentVariables()).containsEntry(key, env.get(key));
+ assertThat(command.getEnvironment()).containsEntry(key, env.get(key));
}
assertThat(command.getWorkingDirectory()).isEqualTo(workingDir);
}
@@ -403,7 +402,7 @@
private static void checkCommandElements(CommandException e,
String... expected) {
- assertArrayEquals(expected, e.getCommand().getCommandLineElements());
+ assertThat(e.getCommand().getArguments()).containsExactlyElementsIn(expected);
}
private static void checkATE(final AbnormalTerminationException ate) {
@@ -423,7 +422,7 @@
Command command = new Command(new String[]{"relative/path/to/binary"},
ImmutableMap.<String, String>of(),
new File("/working/directory"));
- assertThat(command.getCommandLineElements()[0])
+ assertThat(command.getArguments().get(0))
.isEqualTo("/working/directory/relative/path/to/binary");
}
}
diff --git a/src/test/java/com/google/devtools/build/lib/util/CommandBuilderTest.java b/src/test/java/com/google/devtools/build/lib/util/CommandBuilderTest.java
index 18293c8..a3f5b0b 100644
--- a/src/test/java/com/google/devtools/build/lib/util/CommandBuilderTest.java
+++ b/src/test/java/com/google/devtools/build/lib/util/CommandBuilderTest.java
@@ -17,7 +17,6 @@
import static org.junit.Assert.assertThrows;
import com.google.common.collect.ImmutableList;
-import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -37,10 +36,7 @@
}
private void assertArgv(CommandBuilder builder, String... expected) {
- assertThat(builder.build().getCommandLineElements())
- .asList()
- .containsExactlyElementsIn(Arrays.asList(expected))
- .inOrder();
+ assertThat(builder.build().getArguments()).containsExactlyElementsIn(expected).inOrder();
}
private void assertWinCmdArgv(CommandBuilder builder, String expected) {
diff --git a/src/test/java/com/google/devtools/build/lib/util/CommandUtilsTest.java b/src/test/java/com/google/devtools/build/lib/util/CommandUtilsTest.java
index 52ae6ec..8693b98 100644
--- a/src/test/java/com/google/devtools/build/lib/util/CommandUtilsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/util/CommandUtilsTest.java
@@ -28,8 +28,7 @@
@RunWith(JUnit4.class)
public class CommandUtilsTest {
- @Test
- public void longCommand() throws Exception {
+ private static Command buildLongCommand() {
String[] args = new String[40];
args[0] = "this_command_will_not_be_found";
for (int i = 1; i < args.length; i++) {
@@ -39,35 +38,33 @@
env.put("PATH", "/usr/bin:/bin:/sbin");
env.put("FOO", "foo");
File directory = new File("/tmp");
- CommandException exception =
- assertThrows(CommandException.class, () -> new Command(args, env, directory).execute());
- Command command1 = exception.getCommand();
+ return new Command(args, env, directory);
+ }
+
+ @Test
+ public void longCommand() throws Exception {
+ Command command = buildLongCommand();
String message =
- CommandFailureUtils.describeCommandError(
- false,
- CommandUtils.commandLine(command1),
- CommandUtils.env(command1),
- CommandUtils.cwd(command1),
- null);
- Command command = exception.getCommand();
- String verboseMessage =
- CommandFailureUtils.describeCommandError(
- true,
- CommandUtils.commandLine(command),
- CommandUtils.env(command),
- CommandUtils.cwd(command),
- null);
+ CommandFailureUtils.describeCommandFailure(false, CommandUtils.cwd(command), command);
assertThat(message)
.isEqualTo(
- "error executing command this_command_will_not_be_found arg1 "
+ "this_command_will_not_be_found failed: "
+ + "error executing command this_command_will_not_be_found arg1 "
+ "arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 arg10 "
+ "arg11 arg12 arg13 arg14 arg15 arg16 arg17 arg18 "
+ "arg19 arg20 arg21 arg22 arg23 arg24 arg25 arg26 "
+ "arg27 arg28 arg29 arg30 "
+ "... (remaining 9 arguments skipped)");
+ }
+
+ @Test
+ public void longCommand_verbose() throws Exception {
+ Command command = buildLongCommand();
+ String verboseMessage =
+ CommandFailureUtils.describeCommandFailure(true, CommandUtils.cwd(command), command);
assertThat(verboseMessage)
.isEqualTo(
- "error executing command \n"
+ "this_command_will_not_be_found failed: error executing command \n"
+ " (cd /tmp && \\\n"
+ " exec env - \\\n"
+ " FOO=foo \\\n"