diff --git a/common/src/main/java/org/implab/gradle/common/exec/CommandBuilder.java b/common/src/main/java/org/implab/gradle/common/exec/CommandBuilder.java --- a/common/src/main/java/org/implab/gradle/common/exec/CommandBuilder.java +++ b/common/src/main/java/org/implab/gradle/common/exec/CommandBuilder.java @@ -5,26 +5,54 @@ import java.util.stream.Stream; import org.eclipse.jdt.annotation.NonNullByDefault; import org.implab.gradle.common.utils.Values; +/** Command builder interface, used to specify the executable and parameters */ @NonNullByDefault public interface CommandBuilder { + /** Sets the executable, the parameters are left intact. */ CommandBuilder executable(String executable); + /** Sets the specified executable and parameters, old executable and parameters + * are discarded. + */ default CommandBuilder commandLine(String executable, String... args) { return executable(executable) .arguments(args); } - default CommandBuilder arg(String arg0, String... args) { + /** Sets the specified executable and parameters, old executable and parameters + * are discarded. + * + * @param command The command line. Must contain at least one element (executable). + * + */ + default CommandBuilder commandLine(Iterable command) { + var iterator = command.iterator(); + + // set executable + executable(Values.take(iterator).orElseThrow()); + // cleat arguments + arguments(); + // set new arguments + while (iterator.hasNext()) + addArguments(iterator.next()); + + return this; + } + + /** Adds the specified arguments to this builder */ + default CommandBuilder addArguments(String arg0, String... args) { return arguments(() -> Stream .concat(Stream.of(arg0), Stream.of(args)) .iterator()); } + /** Replaces arguments in the builder with the specified one. */ default CommandBuilder arguments(String... args) { return arguments(Values.iterable(args)); } + /** Replaces arguments in the builder with the specified one. */ CommandBuilder arguments(Iterable args); default CommandBuilder from(CommandSpec commandSpec) { diff --git a/common/src/main/java/org/implab/gradle/common/exec/ExecBuilder.java b/common/src/main/java/org/implab/gradle/common/exec/ExecBuilder.java --- a/common/src/main/java/org/implab/gradle/common/exec/ExecBuilder.java +++ b/common/src/main/java/org/implab/gradle/common/exec/ExecBuilder.java @@ -53,17 +53,8 @@ public abstract class ExecBuilder implem return this; } - public ExecBuilder commandLine(Iterable cmd) { - requireNonNull(cmd, "cmd can't be null"); - - this.arguments.clear(); - for (var arg : cmd) - this.arguments.add(arg); - return this; - } - @Override - public ExecBuilder arg(String arg0, String... args) { + public ExecBuilder addArguments(String arg0, String... args) { requireNonNull(arg0, "arg0 parameter can't be null"); arguments.add(arg0); diff --git a/common/src/main/java/org/implab/gradle/common/utils/Values.java b/common/src/main/java/org/implab/gradle/common/utils/Values.java --- a/common/src/main/java/org/implab/gradle/common/utils/Values.java +++ b/common/src/main/java/org/implab/gradle/common/utils/Values.java @@ -2,10 +2,15 @@ package org.implab.gradle.common.utils; import java.util.Iterator; import java.util.Map; +import java.util.Spliterator; +import java.util.Spliterators; import java.util.Map.Entry; +import java.util.Optional; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; import org.gradle.api.provider.Provider; @@ -46,6 +51,16 @@ public final class Values { } } + public static Stream stream(Iterator remaining) { + var spliterator = Spliterators.spliteratorUnknownSize(remaining, 0); + + return StreamSupport.stream(spliterator, false); + } + + public static Optional take(Iterator iterator) { + return iterator.hasNext() ? Optional.of(iterator.next()) : Optional.empty(); + } + public static Iterable iterable(T[] values) { return () -> new ArrayIterator<>(values); }