Skip to content

Commit 4805dbe

Browse files
committed
[MNG-8230] Rewrite CI Friendly versions (wip)
1 parent 8f34ea4 commit 4805dbe

File tree

6 files changed

+69
-199
lines changed

6 files changed

+69
-199
lines changed

maven-api-impl/src/main/java/org/apache/maven/api/services/model/ModelVersionProcessor.java

Lines changed: 0 additions & 44 deletions
This file was deleted.

maven-api-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultModelBuilder.java

Lines changed: 58 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import java.nio.file.Path;
2727
import java.nio.file.Paths;
2828
import java.util.ArrayList;
29-
import java.util.Arrays;
3029
import java.util.Collection;
3130
import java.util.HashMap;
3231
import java.util.HashSet;
@@ -45,6 +44,8 @@
4544
import java.util.concurrent.atomic.AtomicReference;
4645
import java.util.function.Supplier;
4746
import java.util.function.UnaryOperator;
47+
import java.util.regex.Matcher;
48+
import java.util.regex.Pattern;
4849
import java.util.stream.Collectors;
4950
import java.util.stream.Stream;
5051

@@ -232,6 +233,8 @@ public ModelBuilderResult build(ModelBuilderRequest request) throws ModelBuilder
232233
}
233234

234235
protected class DefaultModelBuilderSession implements ModelProblemCollector {
236+
private static final Pattern REGEX = Pattern.compile("\\$\\{([^}]+)}");
237+
235238
final Session session;
236239
final ModelBuilderRequest request;
237240
final DefaultModelBuilderResult result;
@@ -562,58 +565,15 @@ public void mergeRepositories(List<Repository> toAdd, boolean replace) {
562565
}
563566

564567
//
565-
// Transform raw model to build pom
566-
//
567-
Model transformFileToRaw(Model model) {
568-
Model.Builder builder = Model.newBuilder(model);
569-
builder = handleParent(model, builder);
570-
builder = handleReactorDependencies(model, builder);
571-
builder = handleCiFriendlyVersion(model, builder);
572-
return builder.build();
573-
}
574-
575-
//
576-
// Infer parent information
577-
//
578-
Model.Builder handleParent(Model model, Model.Builder builder) {
579-
Parent parent = model.getParent();
580-
if (parent != null) {
581-
String version = parent.getVersion();
582-
String modVersion = replaceCiFriendlyVersion(version);
583-
if (!Objects.equals(version, modVersion)) {
584-
if (builder == null) {
585-
builder = Model.newBuilder(model);
586-
}
587-
builder.parent(parent.withVersion(modVersion));
588-
}
589-
}
590-
return builder;
591-
}
592-
593-
//
594-
// CI friendly versions
595-
//
596-
Model.Builder handleCiFriendlyVersion(Model model, Model.Builder builder) {
597-
String version = model.getVersion();
598-
String modVersion = replaceCiFriendlyVersion(version);
599-
if (!Objects.equals(version, modVersion)) {
600-
if (builder == null) {
601-
builder = Model.newBuilder(model);
602-
}
603-
builder.version(modVersion);
604-
}
605-
return builder;
606-
}
607-
608-
//
568+
// Transform raw model to build pom.
609569
// Infer inner reactor dependencies version
610570
//
611-
Model.Builder handleReactorDependencies(Model model, Model.Builder builder) {
571+
Model transformFileToRaw(Model model) {
612572
List<Dependency> newDeps = new ArrayList<>();
613573
boolean modified = false;
614574
for (Dependency dep : model.getDependencies()) {
615-
Dependency.Builder depBuilder = null;
616575
if (dep.getVersion() == null) {
576+
Dependency.Builder depBuilder = null;
617577
Model depModel = getRawModel(model.getPomFile(), dep.getGroupId(), dep.getArtifactId());
618578
if (depModel != null) {
619579
String version = depModel.getVersion();
@@ -634,30 +594,35 @@ Model.Builder handleReactorDependencies(Model model, Model.Builder builder) {
634594
depBuilder.groupId(depGroupId).location("groupId", groupIdLocation);
635595
}
636596
}
597+
if (depBuilder != null) {
598+
newDeps.add(depBuilder.build());
599+
modified = true;
600+
} else {
601+
newDeps.add(dep);
602+
}
637603
}
638-
if (depBuilder != null) {
639-
newDeps.add(depBuilder.build());
640-
modified = true;
641-
} else {
642-
newDeps.add(dep);
643-
}
644-
}
645-
if (modified) {
646-
if (builder == null) {
647-
builder = Model.newBuilder(model);
648-
}
649-
builder.dependencies(newDeps);
650604
}
651-
return builder;
605+
return modified ? model.withDependencies(newDeps) : model;
652606
}
653607

654-
String replaceCiFriendlyVersion(String version) {
608+
String replaceCiFriendlyVersion(Map<String, String> properties, String version) {
609+
// TODO: we're using a simple regex here, but we should probably use
610+
// a proper interpolation service to do the replacements
611+
// once one is available in maven-api-impl
612+
// https://issues.apache.org/jira/browse/MNG-8262
655613
if (version != null) {
656-
for (String key : Arrays.asList("changelist", "revision", "sha1")) {
657-
String val = request.getUserProperties().get(key);
658-
if (val != null) {
659-
version = version.replace("${" + key + "}", val);
660-
}
614+
Matcher matcher = REGEX.matcher(version);
615+
if (matcher.find()) {
616+
StringBuilder result = new StringBuilder();
617+
do {
618+
// extract the key inside ${}
619+
String key = matcher.group(1);
620+
// get replacement from the map, or use the original ${xy} if not found
621+
String replacement = properties.getOrDefault(key, "\\" + matcher.group(0));
622+
matcher.appendReplacement(result, replacement);
623+
} while (matcher.find());
624+
matcher.appendTail(result); // Append the remaining part of the string
625+
return result.toString();
661626
}
662627
}
663628
return version;
@@ -738,7 +703,6 @@ Stream<DefaultModelBuilderResult> results(DefaultModelBuilderResult r) {
738703
return Stream.concat(Stream.of(r), r.getChildren().stream().flatMap(this::results));
739704
}
740705

741-
@SuppressWarnings("checkstyle:MethodLength")
742706
private void loadFromRoot(Path root, Path top) {
743707
try (PhasingExecutor executor = createExecutor()) {
744708
DefaultModelBuilderResult r = Objects.equals(top, root) ? result : new DefaultModelBuilderResult();
@@ -1225,16 +1189,18 @@ Model readFileModel() throws ModelBuilderException {
12251189
Model doReadFileModel() throws ModelBuilderException {
12261190
ModelSource modelSource = request.getSource();
12271191
Model model;
1192+
Path rootDirectory;
12281193
setSource(modelSource.getLocation());
12291194
logger.debug("Reading file model from " + modelSource.getLocation());
12301195
try {
12311196
boolean strict = request.getRequestType() == ModelBuilderRequest.RequestType.BUILD_POM;
1232-
// TODO: we do cache, but what if strict does not have the same value?
1233-
Path rootDirectory;
12341197
try {
12351198
rootDirectory = request.getSession().getRootDirectory();
12361199
} catch (IllegalStateException ignore) {
12371200
rootDirectory = modelSource.getPath();
1201+
while (rootDirectory != null && !Files.isDirectory(rootDirectory)) {
1202+
rootDirectory = rootDirectory.getParent();
1203+
}
12381204
}
12391205
try (InputStream is = modelSource.openStream()) {
12401206
model = modelProcessor.read(XmlReaderRequest.builder()
@@ -1372,6 +1338,29 @@ Model doReadFileModel() throws ModelBuilderException {
13721338
add(Severity.FATAL, ModelProblem.Version.V41, "Error discovering subprojects", e);
13731339
}
13741340
}
1341+
1342+
// CI friendly version
1343+
// All expressions are interpolated using user properties and properties
1344+
// defined on the root project.
1345+
Map<String, String> properties = new HashMap<>();
1346+
if (!Objects.equals(rootDirectory, model.getProjectDirectory())) {
1347+
Model rootModel = derive(ModelSource.fromPath(modelProcessor.locateExistingPom(rootDirectory)))
1348+
.readFileModel();
1349+
properties.putAll(rootModel.getProperties());
1350+
} else {
1351+
properties.putAll(model.getProperties());
1352+
}
1353+
properties.putAll(session.getUserProperties());
1354+
model = model.with()
1355+
.version(replaceCiFriendlyVersion(properties, model.getVersion()))
1356+
.parent(
1357+
model.getParent() != null
1358+
? model.getParent()
1359+
.withVersion(replaceCiFriendlyVersion(
1360+
properties,
1361+
model.getParent().getVersion()))
1362+
: null)
1363+
.build();
13751364
}
13761365

13771366
for (var transformer : transformers) {

maven-api-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultModelValidator.java

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@
7070
import org.apache.maven.api.services.ModelProblem.Version;
7171
import org.apache.maven.api.services.ModelProblemCollector;
7272
import org.apache.maven.api.services.model.ModelValidator;
73-
import org.apache.maven.api.services.model.ModelVersionProcessor;
7473
import org.apache.maven.model.v4.MavenModelVersion;
7574
import org.apache.maven.model.v4.MavenTransformer;
7675

@@ -290,12 +289,8 @@ protected ActivationProperty.Builder transformActivationProperty_Value(
290289

291290
private final Set<String> validProfileIds = new HashSet<>();
292291

293-
private final ModelVersionProcessor versionProcessor;
294-
295292
@Inject
296-
public DefaultModelValidator(ModelVersionProcessor versionProcessor) {
297-
this.versionProcessor = versionProcessor;
298-
}
293+
public DefaultModelValidator() {}
299294

300295
@Override
301296
@SuppressWarnings("checkstyle:MethodLength")
@@ -1652,19 +1647,14 @@ private boolean validateVersionNoExpression(
16521647

16531648
Matcher m = EXPRESSION_NAME_PATTERN.matcher(string.trim());
16541649
while (m.find()) {
1655-
String property = m.group(1);
1656-
if (!versionProcessor.isValidProperty(property)) {
1657-
addViolation(
1658-
problems,
1659-
severity,
1660-
version,
1661-
fieldName,
1662-
null,
1663-
"contains an expression but should be a constant.",
1664-
tracker);
1665-
1666-
return false;
1667-
}
1650+
addViolation(
1651+
problems,
1652+
severity,
1653+
version,
1654+
fieldName,
1655+
null,
1656+
"contains an expression but should be a constant.",
1657+
tracker);
16681658
}
16691659

16701660
return true;

maven-api-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultModelVersionProcessor.java

Lines changed: 0 additions & 63 deletions
This file was deleted.

maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/RepositorySystemSupplier.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
import org.apache.maven.internal.impl.model.DefaultModelPathTranslator;
4343
import org.apache.maven.internal.impl.model.DefaultModelProcessor;
4444
import org.apache.maven.internal.impl.model.DefaultModelValidator;
45-
import org.apache.maven.internal.impl.model.DefaultModelVersionProcessor;
4645
import org.apache.maven.internal.impl.model.DefaultPathTranslator;
4746
import org.apache.maven.internal.impl.model.DefaultPluginManagementInjector;
4847
import org.apache.maven.internal.impl.model.DefaultProfileInjector;
@@ -1041,7 +1040,7 @@ protected ModelBuilder createModelBuilder() {
10411040
DefaultModelProcessor modelProcessor = new DefaultModelProcessor(new DefaultModelXmlFactory(), List.of());
10421041
return new DefaultModelBuilder(
10431042
modelProcessor,
1044-
new DefaultModelValidator(new DefaultModelVersionProcessor()),
1043+
new DefaultModelValidator(),
10451044
new DefaultModelNormalizer(),
10461045
new DefaultModelInterpolator(
10471046
new DefaultPathTranslator(), new DefaultUrlNormalizer(), new DefaultRootLocator()),

maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemSupplier.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
import org.apache.maven.internal.impl.model.DefaultModelPathTranslator;
4343
import org.apache.maven.internal.impl.model.DefaultModelProcessor;
4444
import org.apache.maven.internal.impl.model.DefaultModelValidator;
45-
import org.apache.maven.internal.impl.model.DefaultModelVersionProcessor;
4645
import org.apache.maven.internal.impl.model.DefaultPathTranslator;
4746
import org.apache.maven.internal.impl.model.DefaultPluginManagementInjector;
4847
import org.apache.maven.internal.impl.model.DefaultProfileInjector;
@@ -1044,7 +1043,7 @@ protected ModelBuilder createModelBuilder() {
10441043
DefaultModelProcessor modelProcessor = new DefaultModelProcessor(new DefaultModelXmlFactory(), List.of());
10451044
return new DefaultModelBuilder(
10461045
modelProcessor,
1047-
new DefaultModelValidator(new DefaultModelVersionProcessor()),
1046+
new DefaultModelValidator(),
10481047
new DefaultModelNormalizer(),
10491048
new DefaultModelInterpolator(
10501049
new DefaultPathTranslator(), new DefaultUrlNormalizer(), new DefaultRootLocator()),

0 commit comments

Comments
 (0)