| @@ -120,7 +120,10 public abstract class BuildVariant imple | |||
|
|
120 | 120 | |
|
|
121 | 121 | public LayerLink link(String from, String to, String kind) { |
|
|
122 | 122 | ensureMutable("add links"); |
|
|
123 |
var link = new LayerLink( |
|
|
|
123 | var link = new LayerLink( | |
|
|
124 | requireLinkValue("from", from), | |
|
|
125 | requireLinkValue("to", to), | |
|
|
126 | requireLinkValue("kind", kind)); | |
|
|
124 | 127 | links.add(link); |
|
|
125 | 128 | return link; |
|
|
126 | 129 | } |
| @@ -191,6 +194,13 public abstract class BuildVariant imple | |||
|
|
191 | 194 | throw new InvalidUserDataException("Variant '" + name + "' is finalized and cannot " + operation); |
|
|
192 | 195 | } |
|
|
193 | 196 | |
|
|
197 | private static String requireLinkValue(String field, String value) { | |
|
|
198 | if (value == null || value.trim().isEmpty()) | |
|
|
199 | throw new InvalidUserDataException("Link '" + field + "' must not be null or blank"); | |
|
|
200 | ||
|
|
201 | return value.trim(); | |
|
|
202 | } | |
|
|
203 | ||
|
|
194 | 204 | public final class RolesSpec { |
|
|
195 | 205 | public BuildRole role(String name, Action<? super BuildRole> configure) { |
|
|
196 | 206 | return BuildVariant.this.role(name, configure); |
| @@ -158,8 +158,18 public abstract class BuildVariantsExten | |||
|
|
158 | 158 | var errors = new ArrayList<String>(); |
|
|
159 | 159 | |
|
|
160 | 160 | var layersByName = new LinkedHashMap<String, BuildLayer>(); |
|
|
161 | for (var layer : layers) | |
|
|
162 |
|
|
|
|
161 | for (var layer : layers) { | |
|
|
162 | var layerName = normalize(layer.getName()); | |
|
|
163 | if (layerName == null) { | |
|
|
164 | errors.add("Layer name must not be blank"); | |
|
|
165 | continue; | |
|
|
166 | } | |
|
|
167 | ||
|
|
168 | var previous = layersByName.putIfAbsent(layerName, layer); | |
|
|
169 | if (previous != null) { | |
|
|
170 | errors.add("Layer '" + layerName + "' is declared more than once"); | |
|
|
171 | } | |
|
|
172 | } | |
|
|
163 | 173 | |
|
|
164 | 174 | for (var variant : variants) |
|
|
165 | 175 | validateVariant(variant, layersByName, errors); |
| @@ -174,28 +184,69 public abstract class BuildVariantsExten | |||
|
|
174 | 184 | } |
|
|
175 | 185 | |
|
|
176 | 186 | private static void validateVariant(BuildVariant variant, Map<String, BuildLayer> layersByName, List<String> errors) { |
|
|
187 | var variantName = normalize(variant.getName()); | |
|
|
188 | if (variantName == null) { | |
|
|
189 | errors.add("Variant name must not be blank"); | |
|
|
190 | return; | |
|
|
191 | } | |
|
|
192 | ||
|
|
193 | validateRoleAndArtifactNames(variant, errors); | |
|
|
177 | 194 | var variantLayers = validateRoleMappings(variant, layersByName, errors); |
|
|
178 | 195 | validateLinks(variant, variantLayers, errors); |
|
|
179 | 196 | } |
|
|
180 | 197 | |
|
|
198 | private static void validateRoleAndArtifactNames(BuildVariant variant, List<String> errors) { | |
|
|
199 | var roleNames = new LinkedHashSet<String>(); | |
|
|
200 | for (var role : variant.getRoles()) { | |
|
|
201 | var roleName = normalize(role.getName()); | |
|
|
202 | if (roleName == null) { | |
|
|
203 | errors.add("Variant '" + variant.getName() + "' contains blank role name"); | |
|
|
204 | continue; | |
|
|
205 | } | |
|
|
206 | if (!roleNames.add(roleName)) { | |
|
|
207 | errors.add("Variant '" + variant.getName() + "' contains duplicated role name '" + roleName + "'"); | |
|
|
208 | } | |
|
|
209 | } | |
|
|
210 | ||
|
|
211 | var slotNames = new LinkedHashSet<String>(); | |
|
|
212 | for (var slot : variant.getArtifactSlots()) { | |
|
|
213 | var slotName = normalize(slot.getName()); | |
|
|
214 | if (slotName == null) { | |
|
|
215 | errors.add("Variant '" + variant.getName() + "' contains blank artifact slot name"); | |
|
|
216 | continue; | |
|
|
217 | } | |
|
|
218 | if (!slotNames.add(slotName)) { | |
|
|
219 | errors.add("Variant '" + variant.getName() + "' contains duplicated artifact slot name '" + slotName + "'"); | |
|
|
220 | } | |
|
|
221 | } | |
|
|
222 | } | |
|
|
223 | ||
|
|
181 | 224 | private static Set<String> validateRoleMappings(BuildVariant variant, Map<String, BuildLayer> layersByName, |
|
|
182 | 225 | List<String> errors) { |
|
|
183 | 226 | var variantLayers = new LinkedHashSet<String>(); |
|
|
184 | 227 | |
|
|
185 | 228 | for (var role : variant.getRoles()) { |
|
|
229 | var seenLayers = new LinkedHashSet<String>(); | |
|
|
186 | 230 | for (var layerName : role.getLayers().getOrElse(List.of())) { |
|
|
187 | if (isBlank(layerName)) { | |
|
|
231 | var normalizedLayerName = normalize(layerName); | |
|
|
232 | if (normalizedLayerName == null) { | |
|
|
188 | 233 | errors.add("Variant '" + variant.getName() + "', role '" + role.getName() + "' contains blank layer name"); |
|
|
189 | 234 | continue; |
|
|
190 | 235 | } |
|
|
191 | 236 | |
|
|
192 | var layer = layersByName.get(layerName); | |
|
|
237 | var layer = layersByName.get(normalizedLayerName); | |
|
|
193 | 238 | if (layer == null) { |
|
|
194 | errors.add("Variant '" + variant.getName() + "' references unknown layer '" + layerName + "'"); | |
|
|
239 | errors.add("Variant '" + variant.getName() + "' references unknown layer '" + normalizedLayerName + "'"); | |
|
|
195 | 240 | continue; |
|
|
196 | 241 | } |
|
|
197 | 242 | |
|
|
198 |
|
|
|
|
243 | if (!seenLayers.add(normalizedLayerName)) { | |
|
|
244 | errors.add("Variant '" + variant.getName() + "', role '" + role.getName() | |
|
|
245 | + "' contains duplicated layer reference '" + normalizedLayerName + "'"); | |
|
|
246 | continue; | |
|
|
247 | } | |
|
|
248 | ||
|
|
249 | variantLayers.add(normalizedLayerName); | |
|
|
199 | 250 | } |
|
|
200 | 251 | } |
|
|
201 | 252 | |
| @@ -40,6 +40,7 public abstract class VariantSourcesExte | |||
|
|
40 | 40 | private final List<SourceSetContext> boundContexts = new ArrayList<>(); |
|
|
41 | 41 | private final LinkedHashMap<String, NamedDomainObjectProvider<GenericSourceSet>> sourceSetsByName = new LinkedHashMap<>(); |
|
|
42 | 42 | private final LinkedHashMap<String, String> sourceSetLayersByName = new LinkedHashMap<>(); |
|
|
43 | private boolean sourceSetsRegistered; | |
|
|
43 | 44 | |
|
|
44 | 45 | @Inject |
|
|
45 | 46 | public VariantSourcesExtension(ObjectFactory objects) { |
| @@ -137,6 +138,10 public abstract class VariantSourcesExte | |||
|
|
137 | 138 | } |
|
|
138 | 139 | |
|
|
139 | 140 | void registerSourceSets(BuildVariantsExtension variants, NamedDomainObjectContainer<GenericSourceSet> sources) { |
|
|
141 | if (sourceSetsRegistered) { | |
|
|
142 | throw new InvalidUserDataException("variantSources source sets are already registered"); | |
|
|
143 | } | |
|
|
144 | ||
|
|
140 | 145 | validateBindings(variants); |
|
|
141 | 146 | |
|
|
142 | 147 | var usages = layerUsages(variants).toList(); |
| @@ -157,6 +162,8 public abstract class VariantSourcesExte | |||
|
|
157 | 162 | registeredContexts.size() - registeredBefore, |
|
|
158 | 163 | boundContexts.size() - boundBefore, |
|
|
159 | 164 | sourceSetsByName.size()); |
|
|
165 | ||
|
|
166 | sourceSetsRegistered = true; | |
|
|
160 | 167 | } |
|
|
161 | 168 | |
|
|
162 | 169 | private Stream<LayerUsage> layerUsages(BuildVariantsExtension variants) { |
| @@ -156,7 +156,7 class VariantsPluginFunctionalTest { | |||
|
|
156 | 156 | link('a', 'b', null) |
|
|
157 | 157 | } |
|
|
158 | 158 | } |
|
|
159 | """, "has incomplete link (from/to/kind are required)"); | |
|
|
159 | """, "Link 'kind' must not be null or blank"); | |
|
|
160 | 160 | } |
|
|
161 | 161 | |
|
|
162 | 162 | @Test |
| @@ -224,6 +224,25 class VariantsPluginFunctionalTest { | |||
|
|
224 | 224 | } |
|
|
225 | 225 | |
|
|
226 | 226 | @Test |
|
|
227 | void failsOnDuplicatedLayerReferenceInRole() throws Exception { | |
|
|
228 | assertBuildFails(""" | |
|
|
229 | plugins { | |
|
|
230 | id 'org.implab.gradle-variants' | |
|
|
231 | } | |
|
|
232 | ||
|
|
233 | variants { | |
|
|
234 | layer('a') | |
|
|
235 | ||
|
|
236 | variant('browser') { | |
|
|
237 | role('main') { | |
|
|
238 | layers('a', 'a') | |
|
|
239 | } | |
|
|
240 | } | |
|
|
241 | } | |
|
|
242 | """, "contains duplicated layer reference 'a'"); | |
|
|
243 | } | |
|
|
244 | ||
|
|
245 | @Test | |
|
|
227 | 246 | void failsOnLateLayerMutationAfterFinalize() throws Exception { |
|
|
228 | 247 | assertBuildFails(""" |
|
|
229 | 248 | plugins { |
General Comments 0
You need to be logged in to leave comments.
Login now
