diff options
author | Kristina Chodorow <kchodorow@google.com> | 2017-03-15 17:12:38 +0000 |
---|---|---|
committer | Yun Peng <pcloudy@google.com> | 2017-03-16 08:35:57 +0000 |
commit | cb81292b95c903bf25c0266f8959cdb978d2b89a (patch) | |
tree | d4118dc199b511b766fa59edf2f9b836ba8a30fb /src/main/java/com/google/devtools/build/lib | |
parent | d1f0d6e57286e0987b680aaf956226585ea965a9 (diff) |
Print repository context's execute output
RELNOTES: Repository context's execute() function can print stdout/stderr while running. To enable, pass quiet=False.
--
PiperOrigin-RevId: 150206218
MOS_MIGRATED_REVID=150206218
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib')
3 files changed, 70 insertions, 44 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD index 7843d3143a..8be69a6b48 100644 --- a/src/main/java/com/google/devtools/build/lib/BUILD +++ b/src/main/java/com/google/devtools/build/lib/BUILD @@ -715,6 +715,7 @@ java_library( ":util", "//src/java_tools/singlejar/java/com/google/devtools/build/zip", "//src/main/java/com/google/devtools/build/lib:build-base", + "//src/main/java/com/google/devtools/build/lib:io", "//src/main/java/com/google/devtools/build/lib:packages-internal", "//src/main/java/com/google/devtools/build/lib:shell", "//src/main/java/com/google/devtools/build/lib:skylarkinterface", diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkExecutionResult.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkExecutionResult.java index b049fa8369..1d5f70c088 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkExecutionResult.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkExecutionResult.java @@ -19,14 +19,17 @@ import com.google.devtools.build.lib.shell.BadExitStatusException; 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 com.google.devtools.build.lib.shell.TimeoutKillableObserver; import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable; import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory; import com.google.devtools.build.lib.syntax.EvalException; import com.google.devtools.build.lib.util.Preconditions; +import com.google.devtools.build.lib.util.io.DelegatingOutErr; +import com.google.devtools.build.lib.util.io.OutErr; +import com.google.devtools.build.lib.util.io.RecordingOutErr; import java.io.File; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -55,15 +58,6 @@ final class SkylarkExecutionResult { this.stderr = stderr; } - private SkylarkExecutionResult(CommandResult result) { - // TODO(dmarting): if a lot of data is sent to stdout, this will use all the memory and - // Bazel will crash. Maybe we should use custom output streams that throw an appropriate - // exception when reaching a specific size. - this.stdout = new String(result.getStdout(), StandardCharsets.UTF_8); - this.stderr = new String(result.getStderr(), StandardCharsets.UTF_8); - this.returnCode = result.getTerminationStatus().getExitCode(); - } - @SkylarkCallable( name = "return_code", structField = true, @@ -112,6 +106,7 @@ final class SkylarkExecutionResult { private final Map<String, String> envBuilder = Maps.newLinkedHashMap(); private long timeout = -1; private boolean executed = false; + private boolean quiet; private Builder(Map<String, String> environment) { envBuilder.putAll(environment); @@ -166,6 +161,11 @@ final class SkylarkExecutionResult { return this; } + Builder setQuiet(boolean quiet) { + this.quiet = quiet; + return this; + } + /** * Execute the command specified by {@link #addArguments(Iterable)}. */ @@ -176,16 +176,32 @@ final class SkylarkExecutionResult { Preconditions.checkNotNull(directory, "Directory must be set before calling execute()."); executed = true; + DelegatingOutErr delegator = new DelegatingOutErr(); + RecordingOutErr recorder = new RecordingOutErr(); + // TODO(dmarting): if a lot of data is sent to stdout, this will use all the memory and + // Bazel will crash. Maybe we should use custom output streams that throw an appropriate + // exception when reaching a specific size. + delegator.addSink(recorder); + if (!quiet) { + delegator.addSink(OutErr.create(System.out, System.err)); + } try { String[] argsArray = new String[args.size()]; for (int i = 0; i < args.size(); i++) { argsArray[i] = args.get(i); } Command command = new Command(argsArray, envBuilder, directory); - CommandResult result = command.execute(new byte[]{}, timeout, false); - return new SkylarkExecutionResult(result); + CommandResult result = command.execute( + new byte[]{}, new TimeoutKillableObserver(timeout), + delegator.getOutputStream(), delegator.getErrorStream()); + return new SkylarkExecutionResult( + result.getTerminationStatus().getExitCode(), + recorder.outAsLatin1(), + recorder.errAsLatin1()); } catch (BadExitStatusException e) { - return new SkylarkExecutionResult(e.getResult()); + return new SkylarkExecutionResult( + e.getResult().getTerminationStatus().getExitCode(), recorder.outAsLatin1(), + recorder.errAsLatin1()); } catch (CommandException e) { // 256 is outside of the standard range for exit code on Unixes. We are not guaranteed that // on all system it would be outside of the standard range. diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java index 60f23eb627..deff590162 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java @@ -361,39 +361,47 @@ public class SkylarkRepositoryContext { } @SkylarkCallable( - name = "execute", - doc = - "Executes the command given by the list of arguments. The execution time of the command" - + " is limited by <code>timeout</code> (in seconds, default 600 seconds). This method" - + " returns an <code>exec_result</code> structure containing the output of the" - + " command. The <code>environment</code> map can be used to override some environment" - + " variables to be passed to the process.", - parameters = { - @Param( - name = "arguments", - type = SkylarkList.class, - doc = - "List of arguments, the first element should be the path to the program to " - + "execute." - ), - @Param( - name = "timeout", - type = Integer.class, - named = true, - defaultValue = "600", - doc = "maximum duration of the command in seconds (default is 600 seconds)." - ), - @Param( - name = "environment", - type = SkylarkDict.class, - defaultValue = "{}", - named = true, - doc = "force some environment variables to be set to be passed to the process." - ), - } + name = "execute", + doc = + "Executes the command given by the list of arguments. The execution time of the command" + + " is limited by <code>timeout</code> (in seconds, default 600 seconds). This method" + + " returns an <code>exec_result</code> structure containing the output of the" + + " command. The <code>environment</code> map can be used to override some" + + " environment variables to be passed to the process.", + parameters = { + @Param( + name = "arguments", + type = SkylarkList.class, + doc = + "List of arguments, the first element should be the path to the program to " + + "execute." + ), + @Param( + name = "timeout", + type = Integer.class, + named = true, + defaultValue = "600", + doc = "maximum duration of the command in seconds (default is 600 seconds)." + ), + @Param( + name = "environment", + type = SkylarkDict.class, + defaultValue = "{}", + named = true, + doc = "force some environment variables to be set to be passed to the process." + ), + @Param( + name = "quiet", + type = Boolean.class, + defaultValue = "True", + named = true, + doc = "If stdout and stderr should be printed to the terminal." + ), + } ) public SkylarkExecutionResult execute( - SkylarkList<Object> arguments, Integer timeout, SkylarkDict<String, String> environment) + SkylarkList<Object> arguments, Integer timeout, SkylarkDict<String, String> environment, + boolean quiet) throws EvalException, RepositoryFunctionException { createDirectory(outputDirectory); return SkylarkExecutionResult.builder(osObject.getEnvironmentVariables()) @@ -401,6 +409,7 @@ public class SkylarkRepositoryContext { .setDirectory(outputDirectory.getPathFile()) .addEnvironmentVariables(environment) .setTimeout(timeout.longValue() * 1000) + .setQuiet(quiet) .execute(); } |