# HG changeset patch # User cin # Date 2024-06-24 15:38:09 # Node ID 4ba61464d214de1f48be57f4b012defc37c6572b # Parent 364cf786438689556cc1c7b6e09b96d951c8fdc1 Refactoring exec classes diff --git a/common/src/main/java/org/implab/gradle/common/dsl/ProcessSpec.java b/common/src/main/java/org/implab/gradle/common/dsl/ProcessSpec.java --- a/common/src/main/java/org/implab/gradle/common/dsl/ProcessSpec.java +++ b/common/src/main/java/org/implab/gradle/common/dsl/ProcessSpec.java @@ -5,7 +5,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import org.implab.gradle.common.exec.Executor; +import org.implab.gradle.common.exec.ExecBuilder; import org.implab.gradle.common.exec.RedirectFrom; import org.implab.gradle.common.exec.RedirectTo; @@ -63,7 +63,7 @@ public class ProcessSpec { return this; } - public void accept(Executor executor) { + public void accept(ExecBuilder executor) { command.forEach(executor::argument); executor.directory(directory); if (inputRedirect != null) diff --git a/common/src/main/java/org/implab/gradle/common/exec/Executor.java b/common/src/main/java/org/implab/gradle/common/exec/ExecBuilder.java rename from common/src/main/java/org/implab/gradle/common/exec/Executor.java rename to common/src/main/java/org/implab/gradle/common/exec/ExecBuilder.java --- a/common/src/main/java/org/implab/gradle/common/exec/Executor.java +++ b/common/src/main/java/org/implab/gradle/common/exec/ExecBuilder.java @@ -2,24 +2,60 @@ package org.implab.gradle.common.exec; import java.util.concurrent.CompletableFuture; +import org.eclipse.jdt.annotation.NonNullByDefault; + import java.io.File; import java.io.IOException; -/** Interface for a command line execution. */ -public interface Executor { +/** Command line builder */ +@NonNullByDefault +public interface ExecBuilder { + + /** Sets command line, clears previous one if any */ + void command(String cmd, String... args); + + /** Adds an argument to the command line */ void argument(String arg); + /** Sets the working directory */ void directory(File directory); + /** + * Sets the environment value. The value cannot be null. + * + * @param envVar The name of the environment variable + * @param value The value to set, + */ + void setEnvironment(String envVar, String value); + + void unsetEnvironment(String envVar); + + /** + * Sets redirection for the stdin, {@link RedirectFrom} will be applied + * every time the process is started. + * + *

If redirection + */ void stdin(RedirectFrom from); + /** + * Sets redirection for the stdout, {@link RedirectTo} will be applied + * every time the process is started. + */ void stdout(RedirectTo out); + /** + * Sets redirection for the stderr, {@link RedirectTo} will be applied + * every time the process is started. + */ void stderr(RedirectTo err); - + + /** + * Creates and starts new process and returns {@link CompletableFuture}. The + * process may be a remote process, or a shell process or etc. + * @return + * @throws IOException + */ CompletableFuture start() throws IOException; - public static Executor system() { - return new SystemExec(); - } } diff --git a/common/src/main/java/org/implab/gradle/common/exec/ExecShell.java b/common/src/main/java/org/implab/gradle/common/exec/ExecShell.java new file mode 100644 --- /dev/null +++ b/common/src/main/java/org/implab/gradle/common/exec/ExecShell.java @@ -0,0 +1,16 @@ +package org.implab.gradle.common.exec; + +/** Shell used to start processes */ +public interface ExecShell { + + /** Creates new process builder {@link ExecBuilder} */ + ExecBuilder builder(); + + /** + * Creates default process execution "shell" which will execute processes + * directly. + */ + static ExecShell system() { + return () -> new SystemExecBuilder(); + } +} diff --git a/common/src/main/java/org/implab/gradle/common/exec/RedirectFrom.java b/common/src/main/java/org/implab/gradle/common/exec/RedirectFrom.java --- a/common/src/main/java/org/implab/gradle/common/exec/RedirectFrom.java +++ b/common/src/main/java/org/implab/gradle/common/exec/RedirectFrom.java @@ -6,6 +6,10 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.concurrent.CompletableFuture; +/** Describes how to redirect input streams. This interface is used to configure + * lazy redirection. {@link #redirect(OutputStream)} is called when the process + * is started. + */ public interface RedirectFrom { CompletableFuture redirect(OutputStream to); diff --git a/common/src/main/java/org/implab/gradle/common/exec/SystemExec.java b/common/src/main/java/org/implab/gradle/common/exec/SystemExecBuilder.java rename from common/src/main/java/org/implab/gradle/common/exec/SystemExec.java rename to common/src/main/java/org/implab/gradle/common/exec/SystemExecBuilder.java --- a/common/src/main/java/org/implab/gradle/common/exec/SystemExec.java +++ b/common/src/main/java/org/implab/gradle/common/exec/SystemExecBuilder.java @@ -6,7 +6,7 @@ import java.lang.ProcessBuilder.Redirect import java.util.ArrayList; import java.util.concurrent.CompletableFuture; -class SystemExec implements Executor { +class SystemExecBuilder implements ExecBuilder { private final ProcessBuilder builder = new ProcessBuilder(); @@ -48,22 +48,22 @@ class SystemExec implements Executor { .thenApply(t -> proc.exitValue()); } - public void command(String... args) { - builder.command(args); - } - + @Override public void directory(File workingDir) { builder.directory(workingDir); } + @Override public void stderr(RedirectTo to) { errorRedirect = to; } + @Override public void stdin(RedirectFrom from) { inputRedirect = from; } + @Override public void stdout(RedirectTo to) { outputRedirect = to; } @@ -73,4 +73,26 @@ class SystemExec implements Executor { builder.command().add(arg); } + @Override + public void setEnvironment(String envVar, String value) { + builder.environment().put(envVar, value); + + } + + @Override + public void unsetEnvironment(String envVar) { + builder.environment().remove(envVar); + } + + @Override + public void command(String cmd, String... args) { + var commandLine = new ArrayList(); + + commandLine.add(cmd); + for (var arg : args) + commandLine.add(arg); + + builder.command(commandLine); + } + } diff --git a/common/src/main/java/org/implab/gradle/common/tasks/ExternalTask.java b/common/src/main/java/org/implab/gradle/common/tasks/ExternalTask.java --- a/common/src/main/java/org/implab/gradle/common/tasks/ExternalTask.java +++ b/common/src/main/java/org/implab/gradle/common/tasks/ExternalTask.java @@ -6,7 +6,7 @@ import java.util.concurrent.ExecutionExc import org.gradle.api.DefaultTask; import org.implab.gradle.common.dsl.ProcessSpec; -import org.implab.gradle.common.exec.Executor; +import org.implab.gradle.common.exec.ExecBuilder; import org.implab.gradle.common.exec.RedirectFrom; import org.implab.gradle.common.exec.RedirectTo; @@ -100,5 +100,5 @@ public abstract class ExternalTask exten return executor.start().get() == code; } - protected abstract Executor exec(); + protected abstract ExecBuilder exec(); }