Skip to content

Commit e2745ed

Browse files
authored
[MRELEASE-1154] Never fail for unresolvable version expressions (#230)
Improve exception message for unresolvable version expressions Refactor code and add tests
1 parent b95c97c commit e2745ed

File tree

2 files changed

+299
-107
lines changed

2 files changed

+299
-107
lines changed

maven-release-manager/src/main/java/org/apache/maven/shared/release/phase/AbstractRewritePomsPhase.java

+156-107
Original file line numberDiff line numberDiff line change
@@ -517,128 +517,177 @@ private void rewriteArtifactVersions(
517517
if (elements == null) {
518518
return;
519519
}
520-
String projectId = ArtifactUtils.versionlessKey(projectModel.getGroupId(), projectModel.getArtifactId());
521520
for (MavenCoordinate coordinate : elements) {
522-
String rawVersion = coordinate.getVersion();
523-
if (rawVersion == null) {
524-
// managed dependency or unversioned plugin
525-
continue;
526-
}
521+
rewriteArtifactVersion(coordinate, projectModel, properties, result, releaseDescriptor, simulate);
522+
}
523+
}
527524

528-
String rawGroupId = coordinate.getGroupId();
529-
if (rawGroupId == null) {
530-
if ("plugin".equals(coordinate.getName())) {
531-
rawGroupId = "org.apache.maven.plugins";
532-
} else {
533-
// incomplete dependency
534-
continue;
535-
}
536-
}
537-
String groupId = ReleaseUtil.interpolate(rawGroupId, projectModel);
525+
private void rewriteArtifactVersion(
526+
MavenCoordinate artifact,
527+
Model projectModel,
528+
Properties properties,
529+
ReleaseResult result,
530+
ReleaseDescriptor releaseDescriptor,
531+
boolean simulate)
532+
throws ReleaseExecutionException, ReleaseFailureException {
533+
String projectId = ArtifactUtils.versionlessKey(projectModel.getGroupId(), projectModel.getArtifactId());
534+
String rawVersion = artifact.getVersion();
535+
if (rawVersion == null) {
536+
// managed dependency or unversioned plugin
537+
return;
538+
}
538539

539-
String rawArtifactId = coordinate.getArtifactId();
540-
if (rawArtifactId == null) {
541-
// incomplete element
542-
continue;
543-
}
544-
String artifactId = ReleaseUtil.interpolate(rawArtifactId, projectModel);
545-
546-
String key = ArtifactUtils.versionlessKey(groupId, artifactId);
547-
String resolvedSnapshotVersion = getResolvedSnapshotVersion(key, releaseDescriptor);
548-
String mappedVersion = getNextVersion(releaseDescriptor, key);
549-
String originalVersion = getOriginalVersion(releaseDescriptor, key, simulate);
550-
if (originalVersion == null) {
551-
originalVersion = getOriginalResolvedSnapshotVersion(key, releaseDescriptor);
540+
String rawGroupId = artifact.getGroupId();
541+
if (rawGroupId == null) {
542+
if ("plugin".equals(artifact.getName())) {
543+
rawGroupId = "org.apache.maven.plugins";
544+
} else {
545+
// incomplete dependency
546+
return;
552547
}
548+
}
549+
String groupId = ReleaseUtil.interpolate(rawGroupId, projectModel);
553550

554-
// MRELEASE-220
555-
if (mappedVersion != null
556-
&& mappedVersion.endsWith(Artifact.SNAPSHOT_VERSION)
557-
&& !rawVersion.endsWith(Artifact.SNAPSHOT_VERSION)
558-
&& !releaseDescriptor.isUpdateDependencies()) {
559-
continue;
560-
}
551+
String rawArtifactId = artifact.getArtifactId();
552+
if (rawArtifactId == null) {
553+
// incomplete element
554+
return;
555+
}
556+
String artifactId = ReleaseUtil.interpolate(rawArtifactId, projectModel);
557+
558+
String key = ArtifactUtils.versionlessKey(groupId, artifactId);
559+
String resolvedSnapshotVersion = getResolvedSnapshotVersion(key, releaseDescriptor);
560+
String mappedVersion = getNextVersion(releaseDescriptor, key);
561+
String originalVersion = getOriginalVersion(releaseDescriptor, key, simulate);
562+
if (originalVersion == null) {
563+
originalVersion = getOriginalResolvedSnapshotVersion(key, releaseDescriptor);
564+
}
561565

562-
if (mappedVersion != null) {
563-
if (rawVersion.equals(originalVersion)) {
564-
logInfo(result, " Updating " + artifactId + " to " + mappedVersion);
565-
coordinate.setVersion(mappedVersion);
566-
} else {
567-
String property = extractPropertyFromExpression(rawVersion);
568-
if (property != null) {
569-
if (property.startsWith("project.")
570-
|| property.startsWith("pom.")
571-
|| "version".equals(property)) {
572-
if (!mappedVersion.equals(getNextVersion(releaseDescriptor, projectId))) {
573-
logInfo(result, " Updating " + artifactId + " to " + mappedVersion);
574-
coordinate.setVersion(mappedVersion);
575-
} else {
576-
logInfo(result, " Ignoring artifact version update for expression " + rawVersion);
577-
}
578-
} else if (properties != null) {
579-
// version is an expression, check for properties to update instead
580-
String propertyValue = properties.getProperty(property);
581-
if (propertyValue != null) {
582-
if (propertyValue.equals(originalVersion)) {
583-
logInfo(result, " Updating " + rawVersion + " to " + mappedVersion);
584-
// change the property only if the property is the same as what's in the reactor
585-
properties.setProperty(property, mappedVersion);
586-
} else if (mappedVersion.equals(propertyValue)) {
587-
// this property may have been updated during processing a sibling.
588-
logInfo(
589-
result,
590-
" Ignoring artifact version update for expression " + rawVersion
591-
+ " because it is already updated");
592-
} else if (!mappedVersion.equals(rawVersion)) {
593-
// WARNING: ${pom.*} prefix support and ${version} is about to be dropped in mvn4!
594-
// https://issues.apache.org/jira/browse/MNG-7404
595-
// https://issues.apache.org/jira/browse/MNG-7244
596-
if (mappedVersion.matches("\\$\\{project.+\\}")
597-
|| mappedVersion.matches("\\$\\{pom.+\\}")
598-
|| "${version}".equals(mappedVersion)) {
599-
logInfo(
600-
result,
601-
" Ignoring artifact version update for expression " + mappedVersion);
602-
// ignore... we cannot update this expression
603-
} else {
604-
// the value of the expression conflicts with what the user wanted to release
605-
throw new ReleaseFailureException("The artifact (" + key + ") requires a "
606-
+ "different version (" + mappedVersion + ") than what is found ("
607-
+ propertyValue + ") for the expression (" + rawVersion + ") in the "
608-
+ "project (" + projectId + ").");
609-
}
610-
}
611-
} else {
612-
if (CI_FRIENDLY_PROPERTIES.contains(property)) {
613-
logInfo(
614-
result,
615-
" Ignoring artifact version update for CI friendly expression "
616-
+ rawVersion);
617-
} else {
618-
// the expression used to define the version of this artifact may be inherited
619-
// TODO needs a better error message, what pom? what dependency?
620-
throw new ReleaseFailureException(
621-
"Could not find property resolving version expression: " + rawVersion);
622-
}
623-
}
566+
// MRELEASE-220
567+
if (mappedVersion != null
568+
&& mappedVersion.endsWith(Artifact.SNAPSHOT_VERSION)
569+
&& !rawVersion.endsWith(Artifact.SNAPSHOT_VERSION)
570+
&& !releaseDescriptor.isUpdateDependencies()) {
571+
return;
572+
}
573+
574+
if (mappedVersion != null) {
575+
if (rawVersion.equals(originalVersion)) {
576+
logInfo(result, " Updating " + key + " to " + mappedVersion);
577+
artifact.setVersion(mappedVersion);
578+
} else {
579+
String property = extractPropertyFromExpression(rawVersion);
580+
if (property != null) {
581+
if (property.startsWith("project.") || property.startsWith("pom.") || "version".equals(property)) {
582+
// those properties are read-only, replace with literal version in case it is supposed to be
583+
// different from the project's version
584+
if (!mappedVersion.equals(getNextVersion(releaseDescriptor, projectId))) {
585+
logInfo(result, " Updating " + key + " to " + mappedVersion);
586+
artifact.setVersion(mappedVersion);
624587
} else {
625-
// the expression used to define the version of this artifact may be inherited
626-
// TODO needs a better error message, what pom? what dependency?
627-
throw new ReleaseFailureException(
628-
"Could not find properties resolving version expression : " + rawVersion);
588+
logInfo(result, " Ignoring artifact version update for expression " + rawVersion);
629589
}
630590
} else {
631-
// different/previous version not related to current release
591+
rewritePropertyUsedInVersionExpression(
592+
projectId,
593+
key,
594+
rawVersion,
595+
mappedVersion,
596+
originalVersion,
597+
property,
598+
properties,
599+
result,
600+
releaseDescriptor);
632601
}
633602
}
634-
} else if (resolvedSnapshotVersion != null) {
635-
logInfo(result, " Updating " + artifactId + " to " + resolvedSnapshotVersion);
603+
}
604+
} else if (resolvedSnapshotVersion != null) {
605+
logInfo(result, " Updating " + key + " to " + resolvedSnapshotVersion);
636606

637-
coordinate.setVersion(resolvedSnapshotVersion);
607+
artifact.setVersion(resolvedSnapshotVersion);
608+
} else {
609+
// artifact not related to current release
610+
}
611+
}
612+
613+
/**
614+
* This is a best-effort implementation for adjusting property values used in versions to be adjusted.
615+
* It only ever rewrites properties in the non-effective local POM.
616+
* If the property used in the version expression cannot be rewritten this is just logged for informational purposes.
617+
*
618+
* @param projectKey the key of the project where to rewrite
619+
* @param artifactKey the key of the artifact whose version is changed
620+
* @param rawVersion the non interpolated version of the artifact
621+
* @param mappedVersion the new version of the artifact
622+
* @param originalVersion the original version (prior modification) of the artifact in the reactor
623+
* @param property the property referenced in the version expression
624+
* @param properties the local properties of the project (may be {@code null})
625+
* @param result
626+
* @param releaseDescriptor
627+
* @return {@code true} if the property was rewritten, otherwise {@code false}
628+
*/
629+
boolean rewritePropertyUsedInVersionExpression(
630+
String projectKey,
631+
String artifactKey,
632+
String rawVersion,
633+
String mappedVersion,
634+
String originalVersion,
635+
String property,
636+
Properties properties,
637+
ReleaseResult result,
638+
ReleaseDescriptor releaseDescriptor)
639+
throws ReleaseFailureException {
640+
if (properties == null) {
641+
logInfo(
642+
result,
643+
" Ignoring artifact version update for " + artifactKey + " as expression " + rawVersion
644+
+ " cannot be locally resolved");
645+
return false;
646+
}
647+
// check for value of property
648+
boolean isUpdated = false;
649+
String propertyValue = properties.getProperty(property);
650+
if (propertyValue != null) {
651+
if (propertyValue.equals(originalVersion)) {
652+
logInfo(result, " Updating " + rawVersion + " to " + mappedVersion);
653+
// change the property only if the property is the same as what's in the reactor
654+
properties.setProperty(property, mappedVersion);
655+
isUpdated = true;
656+
} else if (mappedVersion.equals(propertyValue)) {
657+
// this property may have been updated during processing a sibling.
658+
logInfo(
659+
result,
660+
" Ignoring artifact version update for expression " + rawVersion
661+
+ " because it is already updated");
662+
} else if (!mappedVersion.equals(rawVersion)) {
663+
// WARNING: ${pom.*} prefix support and ${version} is about to be dropped in mvn4!
664+
// https://issues.apache.org/jira/browse/MNG-7404
665+
// https://issues.apache.org/jira/browse/MNG-7244
666+
if (mappedVersion.matches("\\$\\{project.+\\}")
667+
|| mappedVersion.matches("\\$\\{pom.+\\}")
668+
|| "${version}".equals(mappedVersion)) {
669+
logInfo(result, " Ignoring artifact version update for expression " + mappedVersion);
670+
// ignore... we cannot update this expression
671+
} else {
672+
// the value of the expression conflicts with what the user wanted to release
673+
throw new ReleaseFailureException("The artifact (" + artifactKey + ") requires a "
674+
+ "different version (" + mappedVersion + ") than what is found ("
675+
+ propertyValue + ") for the expression (" + rawVersion + ") in the "
676+
+ "project (" + projectKey + ").");
677+
}
678+
}
679+
} else {
680+
if (CI_FRIENDLY_PROPERTIES.contains(property)) {
681+
logInfo(result, " Ignoring artifact version update for CI friendly expression " + rawVersion);
638682
} else {
639-
// artifact not related to current release
683+
// the expression used to define the version of this artifact may be inherited
684+
logInfo(
685+
result,
686+
" Ignoring artifact version update for " + artifactKey + " as expression " + rawVersion
687+
+ " cannot be locally resolved");
640688
}
641689
}
690+
return isUpdated;
642691
}
643692

644693
private void prepareScm(

0 commit comments

Comments
 (0)