##// END OF EJS Templates
sync
cin -
r15:a8aa61eea9d1 default
parent child
Show More
@@ -1,13 +1,13
1 package org.implab.gradle.common.dsl;
1 package org.implab.gradle.common.dsl;
2
2
3
3
4 import org.gradle.api.provider.ListProperty;
4 import org.gradle.api.provider.ListProperty;
5
5
6 public interface CommandSpec {
6 public interface TaskCommandSpecMixin {
7 ListProperty<String> getCommandLine();
7 ListProperty<String> getCommandLine();
8
8
9 void commandLine(Object arg0, Object... args);
9 void commandLine(Object arg0, Object... args);
10
10
11 void args(Object arg0, Object... args);
11 void args(Object arg0, Object... args);
12
12
13 }
13 }
@@ -1,48 +1,52
1 package org.implab.gradle.common.dsl;
1 package org.implab.gradle.common.dsl;
2
2
3 import java.util.HashMap;
3 import java.util.HashMap;
4 import java.util.Map;
4 import java.util.Map;
5
5
6 import org.gradle.api.Action;
6 import org.gradle.api.Action;
7 import org.gradle.api.file.DirectoryProperty;
7 import org.gradle.api.file.DirectoryProperty;
8 import org.gradle.api.provider.MapProperty;
8 import org.gradle.api.provider.MapProperty;
9 import org.gradle.api.provider.Property;
9 import org.implab.gradle.common.utils.Closures;
10 import org.implab.gradle.common.utils.Closures;
10 import org.implab.gradle.common.utils.Values;
11 import org.implab.gradle.common.utils.Values;
11
12
12 import groovy.lang.Closure;
13 import groovy.lang.Closure;
13
14
14 /**
15 /**
15 * Configuration properties of the execution shell. This object specifies a
16 * Configuration properties of the execution shell. This object specifies a
16 * working directory and environment variables for the processes started within
17 * working directory and environment variables for the processes started within
17 * this shell.
18 * this shell.
18 */
19 */
19 public interface EnvironmentSpec {
20 public interface TaskEnvSpecMixin {
21
22 /** Inherit environment from current process */
23 Property<Boolean> getInheritEnvironment();
20
24
21 /** Working directory */
25 /** Working directory */
22 DirectoryProperty getWorkingDirectory();
26 DirectoryProperty getWorkingDirectory();
23
27
24 /** Environment variables */
28 /** Environment variables */
25 MapProperty<String, String> getEnvironment();
29 MapProperty<String, String> getEnvironment();
26
30
27 /**
31 /**
28 * Configures the environment variable using the specified action. The
32 * Configures the environment variable using the specified action. The
29 * action is called when the value is calculated;
33 * action is called when the value is calculated;
30 */
34 */
31 default void env(Action<Map<String, Object>> configure) {
35 default void env(Action<Map<String, Object>> configure) {
32 var provider = getEnvironment()
36 var provider = getEnvironment()
33 .orElse(Map.of())
37 .orElse(Map.of())
34 .map((base) -> {
38 .map((base) -> {
35 var props = new HashMap<String, Object>(base);
39 var props = new HashMap<String, Object>(base);
36
40
37 configure.execute(props);
41 configure.execute(props);
38
42
39 return Values.mapValues(props, Values::toString);
43 return Values.mapValues(props, Values::toString);
40 });
44 });
41
45
42 getEnvironment().set(provider);
46 getEnvironment().set(provider);
43 }
47 }
44
48
45 default void env(Closure<?> configure) {
49 default void env(Closure<?> configure) {
46 env(Closures.action(configure));
50 env(Closures.action(configure));
47 }
51 }
48 }
52 }
@@ -1,12 +1,12
1 package org.implab.gradle.common.dsl;
1 package org.implab.gradle.common.dsl;
2
2
3 import org.eclipse.jdt.annotation.NonNullByDefault;
3 import org.eclipse.jdt.annotation.NonNullByDefault;
4
4
5 @NonNullByDefault
5 @NonNullByDefault
6 public interface PipeSpec {
6 public interface TaskPipeSpecMixin {
7 RedirectToSpec getStdout();
7 RedirectToSpec getStdout();
8
8
9 RedirectToSpec getStderr();
9 RedirectToSpec getStderr();
10
10
11 RedirectFromSpec getStdin();
11 RedirectFromSpec getStdin();
12 }
12 }
@@ -1,110 +1,115
1 package org.implab.gradle.common.tasks;
1 package org.implab.gradle.common.tasks;
2
2
3 import java.io.IOException;
3 import java.io.IOException;
4 import java.util.Map;
4 import java.util.Map;
5 import java.util.concurrent.ExecutionException;
5 import java.util.concurrent.ExecutionException;
6 import java.util.stream.Stream;
6 import java.util.stream.Stream;
7
7
8 import org.gradle.api.DefaultTask;
8 import org.gradle.api.DefaultTask;
9 import org.gradle.api.file.DirectoryProperty;
9 import org.gradle.api.file.DirectoryProperty;
10 import org.gradle.api.provider.ListProperty;
10 import org.gradle.api.provider.ListProperty;
11 import org.gradle.api.provider.MapProperty;
11 import org.gradle.api.provider.MapProperty;
12 import org.gradle.api.provider.Property;
12 import org.gradle.api.tasks.Internal;
13 import org.gradle.api.tasks.Internal;
13 import org.gradle.api.tasks.TaskAction;
14 import org.gradle.api.tasks.TaskAction;
14 import org.implab.gradle.common.dsl.CommandSpec;
15 import org.implab.gradle.common.dsl.TaskCommandSpecMixin;
15 import org.implab.gradle.common.dsl.PipeSpec;
16 import org.implab.gradle.common.dsl.TaskPipeSpecMixin;
16 import org.implab.gradle.common.dsl.RedirectFromSpec;
17 import org.implab.gradle.common.dsl.RedirectFromSpec;
17 import org.implab.gradle.common.dsl.RedirectToSpec;
18 import org.implab.gradle.common.dsl.RedirectToSpec;
18 import org.implab.gradle.common.dsl.EnvironmentSpec;
19 import org.implab.gradle.common.dsl.TaskEnvSpecMixin;
19 import org.implab.gradle.common.exec.ExecBuilder;
20 import org.implab.gradle.common.exec.ExecBuilder;
20 import org.implab.gradle.common.utils.ObjectsMixin;
21 import org.implab.gradle.common.utils.ObjectsMixin;
21 import org.implab.gradle.common.utils.Strings;
22 import org.implab.gradle.common.utils.Strings;
22 import org.implab.gradle.common.utils.ThrowingConsumer;
23 import org.implab.gradle.common.utils.ThrowingConsumer;
23
24
24 public abstract class ShellExecTask
25 public abstract class ShellExecTask
25 extends DefaultTask
26 extends DefaultTask
26 implements CommandSpec, PipeSpec, EnvironmentSpec, ObjectsMixin {
27 implements TaskCommandSpecMixin, TaskPipeSpecMixin, TaskEnvSpecMixin, ObjectsMixin {
27
28
28 private final RedirectToSpec redirectStderr = new RedirectToSpec();
29 private final RedirectToSpec redirectStderr = new RedirectToSpec();
29
30
30 private final RedirectToSpec redirectStdout = new RedirectToSpec();
31 private final RedirectToSpec redirectStdout = new RedirectToSpec();
31
32
32 private final RedirectFromSpec redirectStdin = new RedirectFromSpec();
33 private final RedirectFromSpec redirectStdin = new RedirectFromSpec();
33
34
34 @Internal
35 @Internal
35 @Override
36 @Override
37 public abstract Property<Boolean> getInheritEnvironment();
38
39 @Internal
40 @Override
36 public abstract DirectoryProperty getWorkingDirectory();
41 public abstract DirectoryProperty getWorkingDirectory();
37
42
38 @Internal
43 @Internal
39 @Override
44 @Override
40 public abstract MapProperty<String, String> getEnvironment();
45 public abstract MapProperty<String, String> getEnvironment();
41
46
42 @Internal
47 @Internal
43 @Override
48 @Override
44 public abstract ListProperty<String> getCommandLine();
49 public abstract ListProperty<String> getCommandLine();
45
50
46 /**
51 /**
47 * STDIN redirection, if not specified, no input will be passed to the command
52 * STDIN redirection, if not specified, no input will be passed to the command
48 */
53 */
49 @Internal
54 @Internal
50 @Override
55 @Override
51 public RedirectFromSpec getStdin() {
56 public RedirectFromSpec getStdin() {
52 return redirectStdin;
57 return redirectStdin;
53 }
58 }
54
59
55 /**
60 /**
56 * STDOUT redirection, if not specified, redirected to logger::info
61 * STDOUT redirection, if not specified, redirected to logger::info
57 */
62 */
58 @Internal
63 @Internal
59 @Override
64 @Override
60 public RedirectToSpec getStdout() {
65 public RedirectToSpec getStdout() {
61 return redirectStdout;
66 return redirectStdout;
62 }
67 }
63
68
64 /**
69 /**
65 * STDERR redirection, if not specified, redirected to logger::error
70 * STDERR redirection, if not specified, redirected to logger::error
66 */
71 */
67 @Internal
72 @Internal
68 @Override
73 @Override
69 public RedirectToSpec getStderr() {
74 public RedirectToSpec getStderr() {
70 return redirectStderr;
75 return redirectStderr;
71 }
76 }
72
77
73 @Override
78 @Override
74 public void commandLine(Object arg0, Object... args) {
79 public void commandLine(Object arg0, Object... args) {
75 getCommandLine().set(provider(() -> Stream.concat(
80 getCommandLine().set(provider(() -> Stream.concat(
76 Stream.of(arg0),
81 Stream.of(arg0),
77 Stream.of(args))
82 Stream.of(args))
78 .map(Strings::asString).toList()));
83 .map(Strings::asString).toList()));
79
84
80 }
85 }
81
86
82 @Override
87 @Override
83 public void args(Object arg0, Object... args) {
88 public void args(Object arg0, Object... args) {
84 getCommandLine().addAll(provider(() -> Stream.concat(
89 getCommandLine().addAll(provider(() -> Stream.concat(
85 Stream.of(arg0),
90 Stream.of(arg0),
86 Stream.of(args))
91 Stream.of(args))
87 .map(Strings::asString).toList()));
92 .map(Strings::asString).toList()));
88 }
93 }
89
94
90 protected abstract ExecBuilder execBuilder();
95 protected abstract ExecBuilder execBuilder();
91
96
92 @TaskAction
97 @TaskAction
93 public final void run() throws IOException, InterruptedException, ExecutionException {
98 public final void run() throws IOException, InterruptedException, ExecutionException {
94 var execBuilder = execBuilder();
99 var execBuilder = execBuilder();
95 execBuilder.workingDirectory(getWorkingDirectory().get().getAsFile());
100 execBuilder.workingDirectory(getWorkingDirectory().get().getAsFile());
96 execBuilder.environment(getEnvironment().getOrElse(Map.of()));
101 execBuilder.environment(getEnvironment().getOrElse(Map.of()));
97 execBuilder.commandLine(getCommandLine().get());
102 execBuilder.commandLine(getCommandLine().get());
98
103
99 getStdout().getRedirection().ifPresent(execBuilder::stdout);
104 getStdout().getRedirection().ifPresent(execBuilder::stdout);
100 getStderr().getRedirection().ifPresent(execBuilder::stderr);
105 getStderr().getRedirection().ifPresent(execBuilder::stderr);
101 getStdin().getRedirection().ifPresent(execBuilder::stdin);
106 getStdin().getRedirection().ifPresent(execBuilder::stdin);
102
107
103 execBuilder.exec().thenAccept(ThrowingConsumer.guard(this::checkRetCode)).join();
108 execBuilder.exec().thenAccept(ThrowingConsumer.guard(this::checkRetCode)).join();
104 }
109 }
105
110
106 protected void checkRetCode(Integer code) throws IOException {
111 protected void checkRetCode(Integer code) throws IOException {
107 throw new IOException(String.format("The process is terminated with code %s", code));
112 throw new IOException(String.format("The process is terminated with code %s", code));
108 }
113 }
109
114
110 }
115 }
@@ -1,24 +1,21
1 package org.implab.gradle.common.utils;
1 package org.implab.gradle.common.utils;
2
2
3 import groovy.lang.Closure;
3 import groovy.lang.Closure;
4
4
5 import org.eclipse.jdt.annotation.NonNullByDefault;
5 import org.eclipse.jdt.annotation.NonNullByDefault;
6 import org.gradle.api.Action;
6 import org.gradle.api.Action;
7
7
8 @NonNullByDefault
8 @NonNullByDefault
9 public final class Closures {
9 public final class Closures {
10 private Closures() {
10 private Closures() {
11 }
11 }
12
12
13 public static <T> Action<T> action(Closure<?> closure) {
13 public static <T> Action<T> action(Closure<?> closure) {
14 return arg -> {
14 return arg -> apply(closure, arg);
15 closure.setDelegate(arg);
16 closure.call(arg);
17 };
18 }
15 }
19
16
20 public static void apply(Closure<?> action, Object target) {
17 public static void apply(Closure<?> action, Object target) {
21 action.setDelegate(target);
18 action.setDelegate(target);
22 action.call(target);
19 action.call(target);
23 }
20 }
24 }
21 }
@@ -1,89 +1,93
1 package org.implab.gradle.common.utils;
1 package org.implab.gradle.common.utils;
2
2
3 import java.util.Iterator;
3 import java.util.Iterator;
4 import java.util.Map;
4 import java.util.Map;
5 import java.util.Spliterators;
5 import java.util.Spliterators;
6 import java.util.Map.Entry;
6 import java.util.Map.Entry;
7 import java.util.Optional;
7 import java.util.Optional;
8 import java.util.function.Function;
8 import java.util.function.Function;
9 import java.util.function.Supplier;
9 import java.util.function.Supplier;
10 import java.util.stream.Collectors;
10 import java.util.stream.Collectors;
11 import java.util.stream.Stream;
11 import java.util.stream.Stream;
12 import java.util.stream.StreamSupport;
12 import java.util.stream.StreamSupport;
13
13
14 import org.gradle.api.provider.Provider;
14 import org.gradle.api.provider.Provider;
15
15
16 public final class Values {
16 public final class Values {
17
17
18 private Values() {
18 private Values() {
19 }
19 }
20
20
21 /**
21 /**
22 * Converts values in the specified map
22 * Converts values in the specified map
23 *
23 *
24 * @param <K>
24 * @param <K>
25 * @param <V>
25 * @param <V>
26 * @param <U>
26 * @param <U>
27 * @param map
27 * @param map
28 * @param mapper
28 * @param mapper
29 * @return
29 * @return
30 */
30 */
31 public static <K, V, U> Map<K, U> mapValues(Map<K, V> map, Function<V, U> mapper) {
31 public static <K, V, U> Map<K, U> mapValues(Map<K, V> map, Function<V, U> mapper) {
32 Function<Entry<K, V>, V> getter = Entry::getValue;
32 Function<Entry<K, V>, V> getter = Entry::getValue;
33
33
34 return map.entrySet().stream()
34 return map.entrySet().stream()
35 .collect(Collectors.toMap(Entry::getKey, getter.andThen(mapper)));
35 .collect(Collectors.toMap(Entry::getKey, getter.andThen(mapper)));
36 }
36 }
37
37
38 /**
38 /**
39 * Converts the supplied value to a string.
39 * Converts the supplied value to a string.
40 */
40 */
41 public static String toString(Object value) {
41 public static String toString(Object value) {
42 if (value == null) {
42 if (value == null) {
43 return null;
43 return null;
44 } else if (value instanceof String string) {
44 } else if (value instanceof String string) {
45 return string;
45 return string;
46 } else if (value instanceof Provider<?> provider) {
46 } else if (value instanceof Provider<?> provider) {
47 return toString(provider.getOrNull());
47 return toString(provider.getOrNull());
48 } else if (value instanceof Supplier<?> supplier) {
48 } else if (value instanceof Supplier<?> supplier) {
49 return toString(supplier.get());
49 return toString(supplier.get());
50 } else {
50 } else {
51 return value.toString();
51 return value.toString();
52 }
52 }
53 }
53 }
54
54
55 public static <T> Stream<T> stream(Iterator<T> remaining) {
55 public static <T> Stream<T> stream(Iterator<T> remaining) {
56 return StreamSupport.stream(
56 return StreamSupport.stream(
57 Spliterators.spliteratorUnknownSize(remaining, 0),
57 Spliterators.spliteratorUnknownSize(remaining, 0),
58 false);
58 false);
59 }
59 }
60
60
61 public static <T> Optional<T> take(Iterator<T> iterator) {
61 public static <T> Optional<T> take(Iterator<T> iterator) {
62 return iterator.hasNext() ? Optional.of(iterator.next()) : Optional.empty();
62 return iterator.hasNext() ? Optional.of(iterator.next()) : Optional.empty();
63 }
63 }
64
64
65 public static <T> Iterable<T> iterable(T[] values) {
65 public static <T> Iterable<T> iterable(T[] values) {
66 return () -> new ArrayIterator<>(values);
66 return () -> new ArrayIterator<>(values);
67 }
67 }
68
68
69 public static <T> Optional<T> optional(Provider<T> provider) {
70 return provider.isPresent() ? Optional.of(provider.get()) : Optional.empty();
71 }
72
69 private static class ArrayIterator<T> implements Iterator<T> {
73 private static class ArrayIterator<T> implements Iterator<T> {
70 private final T[] data;
74 private final T[] data;
71
75
72 private int pos = 0;
76 private int pos = 0;
73
77
74 ArrayIterator(T[] data) {
78 ArrayIterator(T[] data) {
75 this.data = data;
79 this.data = data;
76 }
80 }
77
81
78 @Override
82 @Override
79 public boolean hasNext() {
83 public boolean hasNext() {
80 return pos < data.length;
84 return pos < data.length;
81 }
85 }
82
86
83 @Override
87 @Override
84 public T next() {
88 public T next() {
85 return data[pos++];
89 return data[pos++];
86 }
90 }
87 }
91 }
88
92
89 }
93 }
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now