##// END OF EJS Templates
WIP Added ArtifactAssemblyBridge to wire variants with slot assemblies
cin -
r49:e7554f6ac360 default
parent child
Show More
@@ -0,0 +1,54
1 package org.implab.gradle.variants.artifacts.internal;
2
3 import org.eclipse.jdt.annotation.NonNullByDefault;
4 import org.gradle.api.Action;
5 import org.implab.gradle.variants.artifacts.ArtifactAssemblies;
6 import org.implab.gradle.variants.artifacts.ArtifactSlot;
7 import org.implab.gradle.variants.artifacts.OutgoingVariant;
8
9 /**
10 * Связывает описание исходящих конфигураций gradle и сборку содержимого слотов
11 * из {@link ArtifactAssemblies}
12 */
13 @NonNullByDefault
14 public class ArtifactAssemblyBridge implements Action<OutgoingVariant> {
15
16 private final ArtifactAssemblies resolver;
17
18 public ArtifactAssemblyBridge(ArtifactAssemblies resolver) {
19 this.resolver = resolver;
20 }
21
22 @Override
23 public void execute(OutgoingVariant outgoingVariant) {
24 var slots = outgoingVariant.getSlots();
25 var primarySlotProvider = outgoingVariant.getPrimarySlot();
26 var variant = outgoingVariant.getVariant();
27
28 // связываем конфигурацию
29 outgoingVariant.configure(configuration -> {
30 var primarySlot = primarySlotProvider.get();
31 var outgoing = configuration.getOutgoing();
32
33 // связываем основной вариант конфигурации
34 resolver.when(
35 new ArtifactSlot(variant, primarySlot),
36 assembly -> outgoing.artifact(assembly.getArtifact()));
37
38 // для всех объявленных слотов
39 slots.all(slot -> {
40 // кроме основного
41 if (slot.equals(primarySlot))
42 return;
43
44 // связываем артефакты
45 resolver.when(
46 new ArtifactSlot(variant, slot),
47 assembly -> outgoing.getVariants()
48 .register(slot.getName())
49 .configure(cv -> cv.artifact(assembly.getArtifact())));
50 });
51 });
52 }
53
54 }
@@ -0,0 +1,55
1 package org.implab.gradle.variants.artifacts.internal;
2
3 import java.util.Collection;
4 import java.util.Set;
5 import java.util.function.Consumer;
6 import java.util.function.Function;
7
8 import org.implab.gradle.variants.artifacts.ArtifactSlot;
9 import org.implab.gradle.variants.core.VariantsView;
10 import org.implab.gradle.variants.sources.CompileUnit;
11 import org.implab.gradle.variants.sources.VariantSourcesContext;
12
13 public class SlotInputsAssembler implements SlotContributionVisitor {
14
15 VariantsView variantView;
16 VariantSourcesContext sources;
17 ArtifactSlot artifactSlot;
18
19 Set<SlotInputKey> seen;
20
21 @Override
22 public void visit(DirectContribution contribution) {
23 contribute(
24 SlotInputKey.newUniqueKey("Direct input for " + artifactSlot),
25 contribution.input());
26 }
27
28 @Override
29 public void visit(VariantOutputsContribution contribution) {
30 sources.getCompileUnits().getUnitsForVariant(artifactSlot.variant()).stream()
31 }
32
33 @Override
34 public void visit(RoleOutputsContribution contribution) {
35 // TODO Auto-generated method stub
36 throw new UnsupportedOperationException("Unimplemented method 'visit'");
37 }
38
39 @Override
40 public void visit(LayerOutputsContribution contribution) {
41 // TODO Auto-generated method stub
42 throw new UnsupportedOperationException("Unimplemented method 'visit'");
43 }
44
45 private void contribute(SlotInputKey key, Object input) {
46
47 }
48
49 private Function<CompileUnit, Object> resolveOutputs(Collection<? extends String> outputs) {
50 return unit -> {
51
52 };
53 }
54
55 }
@@ -29,3 +29,17
29 - whenFinalized
29 - whenFinalized
30 - whenOutgoingConfiguration
30 - whenOutgoingConfiguration
31 - whenOutgoingSlot
31 - whenOutgoingSlot
32
33 outgoing = outgoings.maybeCreate(variant)
34
35 slot = outgoings.slots.maybeCreate(slotName)
36 assembly = assemblies.register(variantSlot, task, mapOutput)
37 outgoing.configure(configuration -> {
38 slots.all(slot -> {
39 assemblies.when(variant, slot) { assembly ->
40 configuration.variants.create(slot.name) {
41 artifact(assembly.artifact)
42 }
43 }
44 });
45 }); No newline at end of file
@@ -5,11 +5,11 import org.gradle.api.Plugin;
5 import org.gradle.api.Project;
5 import org.gradle.api.Project;
6 import org.implab.gradle.common.core.lang.Deferred;
6 import org.implab.gradle.common.core.lang.Deferred;
7 import org.implab.gradle.variants.artifacts.ArtifactAssemblyRegistry;
7 import org.implab.gradle.variants.artifacts.ArtifactAssemblyRegistry;
8 import org.implab.gradle.variants.artifacts.OutgoingArtifactSlotSpec;
9 import org.implab.gradle.variants.artifacts.OutgoingConfigurationSpec;
8 import org.implab.gradle.variants.artifacts.OutgoingConfigurationSpec;
10 import org.implab.gradle.variants.artifacts.VariantArtifactsContext;
9 import org.implab.gradle.variants.artifacts.OutgoingVariantsContext;
11 import org.implab.gradle.variants.artifacts.VariantArtifactsExtension;
10 import org.implab.gradle.variants.artifacts.VariantArtifactsExtension;
12 import org.implab.gradle.variants.artifacts.VariantArtifactsSpec;
11 import org.implab.gradle.variants.artifacts.VariantArtifactsSpec;
12 import org.implab.gradle.variants.artifacts.internal.ArtifactAssemblyBridge;
13 import org.implab.gradle.variants.artifacts.internal.OutgoingRegistry;
13 import org.implab.gradle.variants.artifacts.internal.OutgoingRegistry;
14 import org.implab.gradle.variants.core.Variant;
14 import org.implab.gradle.variants.core.Variant;
15 import org.implab.gradle.variants.core.VariantsExtension;
15 import org.implab.gradle.variants.core.VariantsExtension;
@@ -32,10 +32,14 public abstract class VariantArtifactsPl
32 var outgoing = new OutgoingRegistry(configurations, objects, providers);
32 var outgoing = new OutgoingRegistry(configurations, objects, providers);
33 var assemblies = new ArtifactAssemblyRegistry(objects, tasks);
33 var assemblies = new ArtifactAssemblyRegistry(objects, tasks);
34
34
35 var deferred = new Deferred<VariantArtifactsContext>();
35 var assembliesBridge = new ArtifactAssemblyBridge(assemblies);
36
37 var deferred = new Deferred<OutgoingVariantsContext>();
38
39 deferred.whenResolved(context -> context.all(assembliesBridge));
36
40
37 variantsExtension.whenFinalized(variants -> {
41 variantsExtension.whenFinalized(variants -> {
38 deferred.resolve(new VariantArtifactsRegistry(variants));
42
39 });
43 });
40
44
41 var variantArtifacts = new VariantArtifactsExtension() {
45 var variantArtifacts = new VariantArtifactsExtension() {
@@ -47,7 +51,7 public abstract class VariantArtifactsPl
47 }
51 }
48
52
49 @Override
53 @Override
50 public void whenFinalized(Action<? super VariantArtifactsContext> action) {
54 public void whenFinalized(Action<? super OutgoingVariantsContext> action) {
51 deferred.whenResolved(registry -> action.execute(registry.variantsContext()));
55 deferred.whenResolved(registry -> action.execute(registry.variantsContext()));
52 }
56 }
53
57
@@ -3,6 +3,7 package org.implab.gradle.variants.artif
3 import java.util.Optional;
3 import java.util.Optional;
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.InvalidUserDataException;
7 import org.gradle.api.InvalidUserDataException;
7
8
8 /**
9 /**
@@ -29,5 +30,25 public interface ArtifactAssemblies {
29 .orElseThrow(() -> new InvalidUserDataException("Artifact assembly '" + slot + "' isn't registered"));
30 .orElseThrow(() -> new InvalidUserDataException("Artifact assembly '" + slot + "' isn't registered"));
30 }
31 }
31
32
33 /**
34 * Регистрирует обработчик на конкретный слот. Если слот еще не зарегистрирован,
35 * то обработчик будет добавлен в очередь и будет вызван при регистрации слота.
36 * Порядок и точный момент вызова обработчиков не определен.
37 *
38 * @param slot Слот на который нужно зарегистрировать обработчик
39 * @param action Обработчик
40 */
41 void when(ArtifactSlot slot, Action<? super ArtifactAssembly> action);
42
43 /**
44 * Регистрирует глобальный обработчик, который будет вызван для всех слотов.
45 * Обработчик будет вызван как для уже зарегистрированных слотов так и для тех,
46 * которые будут зарегистрированы в будущем.
47 *
48 * @param action Обработчик
49 */
50 void all(Action<? super ArtifactAssembly> action);
51
52 /** Ищет зарегистрированный слот */
32 Optional<ArtifactAssembly> find(ArtifactSlot slot);
53 Optional<ArtifactAssembly> find(ArtifactSlot slot);
33 }
54 }
@@ -6,6 +6,7 import java.util.Optional;
6 import java.util.function.Function;
6 import java.util.function.Function;
7
7
8 import org.eclipse.jdt.annotation.NonNullByDefault;
8 import org.eclipse.jdt.annotation.NonNullByDefault;
9 import org.gradle.api.Action;
9 import org.gradle.api.InvalidUserDataException;
10 import org.gradle.api.InvalidUserDataException;
10 import org.gradle.api.Task;
11 import org.gradle.api.Task;
11 import org.gradle.api.file.Directory;
12 import org.gradle.api.file.Directory;
@@ -17,12 +18,15 import org.gradle.api.tasks.Copy;
17 import org.gradle.api.tasks.TaskContainer;
18 import org.gradle.api.tasks.TaskContainer;
18 import org.gradle.api.tasks.TaskProvider;
19 import org.gradle.api.tasks.TaskProvider;
19 import org.gradle.language.base.plugins.LifecycleBasePlugin;
20 import org.gradle.language.base.plugins.LifecycleBasePlugin;
21 import org.implab.gradle.common.core.lang.Deferred;
22 import org.implab.gradle.internal.ReplayableQueue;
20
23
21 @NonNullByDefault
24 @NonNullByDefault
22 public class ArtifactAssemblyRegistry implements ArtifactAssemblies {
25 public class ArtifactAssemblyRegistry implements ArtifactAssemblies {
23 private final ObjectFactory objects;
26 private final ObjectFactory objects;
24 private final TaskContainer tasks;
27 private final TaskContainer tasks;
25 private final Map<ArtifactSlot, ArtifactAssembly> assemblies = new LinkedHashMap<>();
28 private final Map<ArtifactSlot, Deferred<ArtifactAssembly>> assembliesBySlots = new LinkedHashMap<>();
29 private final ReplayableQueue<ArtifactAssembly> assemblies = new ReplayableQueue<>();
26
30
27 public ArtifactAssemblyRegistry(ObjectFactory objects, TaskContainer tasks) {
31 public ArtifactAssemblyRegistry(ObjectFactory objects, TaskContainer tasks) {
28 this.objects = objects;
32 this.objects = objects;
@@ -47,24 +51,45 public class ArtifactAssemblyRegistry im
47 public <T extends Task> ArtifactAssembly register(
51 public <T extends Task> ArtifactAssembly register(
48 ArtifactSlot slot,
52 ArtifactSlot slot,
49 TaskProvider<T> task,
53 TaskProvider<T> task,
50 Function<? super T, ? extends Provider<? extends FileSystemLocation>> mapOutputDirectory) {
54 Function<? super T, ? extends Provider<? extends FileSystemLocation>> mapOutputArtifact) {
51 if (assemblies.containsKey(slot)) {
55
56 var deferred = getDeferred(slot);
57 if (deferred.resolved()) {
52 throw new InvalidUserDataException("Artifact assembly '" + slot + "' is already registered");
58 throw new InvalidUserDataException("Artifact assembly '" + slot + "' is already registered");
53 }
59 }
54 var outputArtifact = task.flatMap(t -> mapOutputDirectory.apply(t));
60 var outputArtifact = task.flatMap(mapOutputArtifact::apply);
55
61
56 var output = objects.fileCollection()
62 var output = objects.fileCollection()
57 .from(outputArtifact)
63 .from(outputArtifact)
58 .builtBy(task);
64 .builtBy(task);
59
65
60 var assembly = new Assembly(outputArtifact, task, output);
66 var assembly = new Assembly(outputArtifact, task, output);
61 assemblies.put(slot, assembly);
67 deferred.resolve(assembly);
68 assemblies.add(assembly);
62 return assembly;
69 return assembly;
63 }
70 }
64
71
65 @Override
72 @Override
66 public Optional<ArtifactAssembly> find(ArtifactSlot slot) {
73 public Optional<ArtifactAssembly> find(ArtifactSlot slot) {
67 return Optional.ofNullable(assemblies.get(slot));
74 // to prevent creation of map entries on lookup use the map directly
75 var deferred = assembliesBySlots.get(slot);
76 return deferred != null && deferred.resolved()
77 ? Optional.of(deferred.value())
78 : Optional.empty();
79 }
80
81 @Override
82 public void when(ArtifactSlot slot, Action<? super ArtifactAssembly> action) {
83 getDeferred(slot).whenResolved(action::execute);
84 }
85
86 @Override
87 public void all(Action<? super ArtifactAssembly> action) {
88 assemblies.forEach(action::execute);
89 }
90
91 private Deferred<ArtifactAssembly> getDeferred(ArtifactSlot slot) {
92 return assembliesBySlots.computeIfAbsent(slot, k -> new Deferred<>());
68 }
93 }
69
94
70 static class Assembly implements ArtifactAssembly {
95 static class Assembly implements ArtifactAssembly {
@@ -13,7 +13,7 import org.implab.gradle.common.core.lan
13 * publication tweaks should be applied here rather than through {@link OutgoingConfigurationSpec}, which
13 * publication tweaks should be applied here rather than through {@link OutgoingConfigurationSpec}, which
14 * is limited to the root outgoing configuration of the variant.
14 * is limited to the root outgoing configuration of the variant.
15 */
15 */
16 public interface OutgoingArtifactSlotSpec {
16 public interface OutgoingConfigurationSlotSpec {
17 /**
17 /**
18 * Returns the published slot identity.
18 * Returns the published slot identity.
19 *
19 *
@@ -1,13 +1,21
1 package org.implab.gradle.variants.artifacts;
1 package org.implab.gradle.variants.artifacts;
2
2
3 import org.gradle.api.Action;
3 import org.gradle.api.NamedDomainObjectContainer;
4 import org.gradle.api.NamedDomainObjectContainer;
4 import org.gradle.api.NamedDomainObjectProvider;
5 import org.gradle.api.NamedDomainObjectProvider;
5 import org.gradle.api.artifacts.Configuration;
6 import org.gradle.api.artifacts.Configuration;
6 import org.gradle.api.provider.Property;
7 import org.gradle.api.provider.Property;
7 import org.implab.gradle.variants.core.Variant;
8 import org.implab.gradle.variants.core.Variant;
8
9
9 /** Описывает исходящую конфигурацию варианта */
10 /**
10 public interface OutgoingConfiguration {
11 * Описывает исходящую конфигурацию варианта
12 *
13 * Задает связь между моделью вариантов и моделью конфигураций gradle через
14 * свойство {@link #getConfiguration()}. Также задает отдельную ось слотов
15 * публикации, но не задает правил связывания этих слотов с самой конфигурацией
16 * и их содержимым. Самый простой вариант это {@link ArtifactAssemblies}.
17 */
18 public interface OutgoingVariant {
11 /**
19 /**
12 * Исходный вариант для которого строится Outgoing конфигурация
20 * Исходный вариант для которого строится Outgoing конфигурация
13 */
21 */
@@ -16,7 +24,11 public interface OutgoingConfiguration {
16 /**
24 /**
17 * Провайдер зарегистрированной конфигурации
25 * Провайдер зарегистрированной конфигурации
18 */
26 */
19 NamedDomainObjectProvider<Configuration> getOutgoingConfiguration();
27 NamedDomainObjectProvider<Configuration> getConfiguration();
28
29 default void configure(Action<? super Configuration> action) {
30 getConfiguration().configure(action);
31 }
20
32
21 /**
33 /**
22 * Слоты конфигурации, данная коллекция живая, используется для
34 * Слоты конфигурации, данная коллекция живая, используется для
@@ -11,7 +11,7 import org.implab.gradle.variants.core.V
11 * Контекст работы с вариантами публикации, становится доступным после
11 * Контекст работы с вариантами публикации, становится доступным после
12 * финализации модели вариантов. Фактически является живой моделью
12 * финализации модели вариантов. Фактически является живой моделью
13 */
13 */
14 public interface VariantArtifactsContext {
14 public interface OutgoingVariantsContext {
15
15
16 /**
16 /**
17 * Зафиксированное представление о вариантах на основе которого адаптеры могут
17 * Зафиксированное представление о вариантах на основе которого адаптеры могут
@@ -24,11 +24,11 public interface VariantArtifactsContext
24 /**
24 /**
25 * Replayable hook для всех объявленных конфигураций
25 * Replayable hook для всех объявленных конфигураций
26 */
26 */
27 void all(Action<? super OutgoingConfiguration> action);
27 void all(Action<? super OutgoingVariant> action);
28
28
29 Optional<OutgoingConfiguration> findOutgoing(Variant variant);
29 Optional<OutgoingVariant> findOutgoing(Variant variant);
30
30
31 default OutgoingConfiguration requireOutgoing(Variant variant) {
31 default OutgoingVariant requireOutgoing(Variant variant) {
32 return findOutgoing(variant)
32 return findOutgoing(variant)
33 .orElseThrow(() -> new InvalidUserDataException("Outgoing variant '" + variant + "' isn't registered"));
33 .orElseThrow(() -> new InvalidUserDataException("Outgoing variant '" + variant + "' isn't registered"));
34 }
34 }
@@ -29,7 +29,7 public interface VariantArtifactsExtensi
29 *
29 *
30 * @param action finalized-model callback
30 * @param action finalized-model callback
31 */
31 */
32 void whenFinalized(Action<? super VariantArtifactsContext> action);
32 void whenFinalized(Action<? super OutgoingVariantsContext> action);
33
33
34 default void whenFinalized(Closure<?> closure) {
34 default void whenFinalized(Closure<?> closure) {
35 whenFinalized(Closures.action(closure));
35 whenFinalized(Closures.action(closure));
@@ -51,7 +51,7 public interface VariantArtifactsExtensi
51 *
51 *
52 * @param action slot-level outgoing publication callback
52 * @param action slot-level outgoing publication callback
53 */
53 */
54 void whenOutgoingSlot(Action<? super OutgoingArtifactSlotSpec> action);
54 void whenOutgoingSlot(Action<? super OutgoingConfigurationSlotSpec> action);
55
55
56 default void whenOutgoingSlot(Closure<?> closure) {
56 default void whenOutgoingSlot(Closure<?> closure) {
57 whenOutgoingSlot(Closures.action(closure));
57 whenOutgoingSlot(Closures.action(closure));
@@ -7,11 +7,11 import org.gradle.api.model.ObjectFactor
7 import org.gradle.api.provider.Property;
7 import org.gradle.api.provider.Property;
8 import org.gradle.api.provider.ProviderFactory;
8 import org.gradle.api.provider.ProviderFactory;
9 import org.gradle.api.provider.Provider;
9 import org.gradle.api.provider.Provider;
10 import org.implab.gradle.variants.artifacts.OutgoingConfiguration;
10 import org.implab.gradle.variants.artifacts.OutgoingVariant;
11 import org.implab.gradle.variants.artifacts.Slot;
11 import org.implab.gradle.variants.artifacts.Slot;
12 import org.implab.gradle.variants.core.Variant;
12 import org.implab.gradle.variants.core.Variant;
13
13
14 class DefaultOutgoingConfiguration implements OutgoingConfiguration {
14 class DefaultOutgoingConfiguration implements OutgoingVariant {
15
15
16 private final Variant variant;
16 private final Variant variant;
17
17
@@ -46,7 +46,7 class DefaultOutgoingConfiguration imple
46 }
46 }
47
47
48 @Override
48 @Override
49 public NamedDomainObjectProvider<Configuration> getOutgoingConfiguration() {
49 public NamedDomainObjectProvider<Configuration> getConfiguration() {
50 return configurationProvider;
50 return configurationProvider;
51 }
51 }
52
52
@@ -1,17 +1,21
1 package org.implab.gradle.variants.artifacts.internal;
1 package org.implab.gradle.variants.artifacts.internal;
2
2
3 import java.util.LinkedHashMap;
3 import java.util.LinkedHashMap;
4 import java.util.LinkedList;
5 import java.util.List;
4 import java.util.Map;
6 import java.util.Map;
5 import java.util.Optional;
7 import java.util.Optional;
8 import java.util.function.Consumer;
6
9
7 import org.gradle.api.artifacts.ConfigurationContainer;
10 import org.gradle.api.artifacts.ConfigurationContainer;
8 import org.gradle.api.model.ObjectFactory;
11 import org.gradle.api.model.ObjectFactory;
9 import org.gradle.api.provider.ProviderFactory;
12 import org.gradle.api.provider.ProviderFactory;
10 import org.implab.gradle.variants.artifacts.OutgoingConfiguration;
13 import org.implab.gradle.variants.artifacts.OutgoingVariant;
11 import org.implab.gradle.variants.core.Variant;
14 import org.implab.gradle.variants.core.Variant;
12
15
13 public class OutgoingRegistry {
16 public class OutgoingRegistry {
14 private final Map<Variant, DefaultOutgoingConfiguration> outgoingByVariant = new LinkedHashMap<>();
17 private final Map<Variant, DefaultOutgoingConfiguration> outgoingByVariant = new LinkedHashMap<>();
18 private final List<Consumer<? super DefaultOutgoingConfiguration>> hooks = new LinkedList<>();
15
19
16 private final ConfigurationContainer configurations;
20 private final ConfigurationContainer configurations;
17 private final ObjectFactory objects;
21 private final ObjectFactory objects;
@@ -23,12 +27,19 public class OutgoingRegistry {
23 this.providers = providers;
27 this.providers = providers;
24 }
28 }
25
29
26 public Optional<OutgoingConfiguration> findOutgoing(Variant variant) {
30 public Optional<OutgoingVariant> findOutgoing(Variant variant) {
27 return Optional.ofNullable(outgoingByVariant.get(variant));
31 return Optional.ofNullable(outgoingByVariant.get(variant));
28 }
32 }
29
33
30 public OutgoingConfiguration maybeCreate(Variant variant) {
34 public OutgoingVariant maybeCreate(Variant variant) {
31 return outgoingByVariant.computeIfAbsent(variant, this::newOutgoingConfiguration);
35 var outgoing = outgoingByVariant.computeIfAbsent(variant, this::newOutgoingConfiguration);
36 hooks.forEach(hook -> hook.accept(outgoing));
37 return outgoing;
38 }
39
40 public void all(Consumer<? super OutgoingVariant> action) {
41 outgoingByVariant.values().forEach(action);
42 hooks.add(action);
32 }
43 }
33
44
34 private DefaultOutgoingConfiguration newOutgoingConfiguration(Variant variant) {
45 private DefaultOutgoingConfiguration newOutgoingConfiguration(Variant variant) {
@@ -37,7 +48,7 public class OutgoingRegistry {
37 return new DefaultOutgoingConfiguration(variant, configuration, objects, providers);
48 return new DefaultOutgoingConfiguration(variant, configuration, objects, providers);
38 }
49 }
39
50
40 String outgoingConfigurationName(Variant variant) {
51 private String outgoingConfigurationName(Variant variant) {
41 return variant.getName() + "Elements";
52 return variant.getName() + "Elements";
42 }
53 }
43
54
@@ -34,8 +34,8
34 * }</pre>
34 * }</pre>
35 *
35 *
36 * <p>After finalization, slot identities can be observed through
36 * <p>After finalization, slot identities can be observed through
37 * {@link org.implab.gradle.variants.artifacts.VariantArtifactsContext#getSlots()}, while slot bodies are
37 * {@link org.implab.gradle.variants.artifacts.OutgoingVariantsContext#getSlots()}, while slot bodies are
38 * obtained on demand through
38 * obtained on demand through
39 * {@link org.implab.gradle.variants.artifacts.VariantArtifactsContext#getAssemblies()}.
39 * {@link org.implab.gradle.variants.artifacts.OutgoingVariantsContext#getAssemblies()}.
40 */
40 */
41 package org.implab.gradle.variants.artifacts;
41 package org.implab.gradle.variants.artifacts;
General Comments 0
You need to be logged in to leave comments. Login now