# HG changeset patch # User cin # Date 2025-07-04 10:20:37 # Node ID 0e291927620c14942a6d20b55d21c2329e5fb399 # Parent a8aa61eea9d13d78586db9502055c3111ea08d4e Changed TaskEnvSpecMixin , Fixed bug in ExtraProps extension when updating extra pros of objects. diff --git a/common/build.gradle b/common/build.gradle --- a/common/build.gradle +++ b/common/build.gradle @@ -6,7 +6,7 @@ plugins { java { withJavadocJar() withSourcesJar() - toolchain { + toolchain { languageVersion = JavaLanguageVersion.of(17) } } diff --git a/common/src/main/java/org/implab/gradle/common/dsl/TaskEnvSpecMixin.java b/common/src/main/java/org/implab/gradle/common/dsl/TaskEnvSpecMixin.java --- a/common/src/main/java/org/implab/gradle/common/dsl/TaskEnvSpecMixin.java +++ b/common/src/main/java/org/implab/gradle/common/dsl/TaskEnvSpecMixin.java @@ -7,6 +7,7 @@ import org.gradle.api.Action; import org.gradle.api.file.DirectoryProperty; import org.gradle.api.provider.MapProperty; import org.gradle.api.provider.Property; +import org.gradle.api.provider.Provider; import org.implab.gradle.common.utils.Closures; import org.implab.gradle.common.utils.Values; @@ -31,19 +32,13 @@ public interface TaskEnvSpecMixin { /** * Configures the environment variable using the specified action. The * action is called when the value is calculated; + * + *

+ * The configuration action is called immediately. To support lazy evaluation, + * properties may be assigned to providers. */ - default void env(Action> configure) { - var provider = getEnvironment() - .orElse(Map.of()) - .map((base) -> { - var props = new HashMap(base); - - configure.execute(props); - - return Values.mapValues(props, Values::toString); - }); - - getEnvironment().set(provider); + default void env(Action> configure) { + Values.configureMap(getEnvironment(), configure, Object.class, Values::toString); } default void env(Closure configure) { diff --git a/common/src/main/java/org/implab/gradle/common/utils/ExtraProps.java b/common/src/main/java/org/implab/gradle/common/utils/ExtraProps.java --- a/common/src/main/java/org/implab/gradle/common/utils/ExtraProps.java +++ b/common/src/main/java/org/implab/gradle/common/utils/ExtraProps.java @@ -1,16 +1,25 @@ package org.implab.gradle.common.utils; -import java.util.Map; +import java.util.Optional; +import java.util.Set; import org.gradle.api.plugins.ExtensionAware; -public class ExtraProps { +public interface ExtraProps { + + Set keys(); + + boolean has(String name); + + Optional get(String name, Class clazz); - public static Map of(Object target) { - if (target instanceof ExtensionAware ext) - return ext.getExtensions().getExtraProperties().getProperties(); - else - return Map.of(); + void put(String name, Object value); + + void remove(String name); + + public static ExtraProps of(Object target) { + return target instanceof ExtensionAware ext + ? new ExtraPropsExtension(ext.getExtensions().getExtraProperties()) + : new ExtraPropsNone(); } - } diff --git a/common/src/main/java/org/implab/gradle/common/utils/ExtraPropsExtension.java b/common/src/main/java/org/implab/gradle/common/utils/ExtraPropsExtension.java new file mode 100644 --- /dev/null +++ b/common/src/main/java/org/implab/gradle/common/utils/ExtraPropsExtension.java @@ -0,0 +1,43 @@ +package org.implab.gradle.common.utils; + +import java.util.Optional; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.gradle.api.plugins.ExtraPropertiesExtension; + +@NonNullByDefault +class ExtraPropsExtension implements ExtraProps { + + private final ExtraPropertiesExtension ext; + + public ExtraPropsExtension(ExtraPropertiesExtension ext) { + this.ext = ext; + } + + @Override + public Set keys() { + return ext.getProperties().keySet(); + } + + @Override + public boolean has(String name) { + return ext.has(name); + } + + @Override + public Optional get(String name, Class clazz) { + return Optional.ofNullable(ext.get(name)).map(clazz::cast); + } + + @Override + public void put(String name, Object value) { + ext.set(name, value); + } + + @Override + public void remove(String name) { + ext.set(name, null); + } + +} diff --git a/common/src/main/java/org/implab/gradle/common/utils/ExtraPropsNone.java b/common/src/main/java/org/implab/gradle/common/utils/ExtraPropsNone.java new file mode 100644 --- /dev/null +++ b/common/src/main/java/org/implab/gradle/common/utils/ExtraPropsNone.java @@ -0,0 +1,31 @@ +package org.implab.gradle.common.utils; + +import java.util.Optional; +import java.util.Set; + +public class ExtraPropsNone implements ExtraProps { + + @Override + public Set keys() { + return Set.of(); + } + + @Override + public boolean has(String name) { + return false; + } + + @Override + public Optional get(String name, Class clazz) { + return Optional.empty(); + } + + @Override + public void put(String name, Object value) { + } + + @Override + public void remove(String name) { + } + +} 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 @@ -1,5 +1,6 @@ package org.implab.gradle.common.utils; +import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Spliterators; @@ -11,6 +12,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; +import org.gradle.api.Action; +import org.gradle.api.provider.MapProperty; import org.gradle.api.provider.Provider; public final class Values { @@ -20,7 +23,7 @@ public final class Values { /** * Converts values in the specified map - * + * * @param * @param * @param @@ -35,6 +38,33 @@ public final class Values { .collect(Collectors.toMap(Entry::getKey, getter.andThen(mapper))); } + public static void mergeMap(MapProperty prop, Map map, Class clazz) { + map.forEach((k,v) -> { + if(v instanceof Provider) + prop.put(k, ((Provider)v).map(clazz::cast)); + else + prop.put(k, clazz.cast(v)); + }); + } + + public static void mergeMap(MapProperty prop, Map map, Class clazz, Function mapper) { + Function caster = clazz::cast; + var castMap = caster.andThen(mapper); + + map.forEach((k,v) -> { + if(v instanceof Provider) + prop.put(k, ((Provider)v).map(x -> castMap.apply(x))); + else + prop.put(k, castMap.apply(v)); + }); + } + + public static void configureMap(MapProperty prop, Action> configure, Class clazz, Function mapper) { + var map = new HashMap(); + configure.execute(map); + mergeMap(prop, map, clazz, mapper); + } + /** * Converts the supplied value to a string. */