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();
}