23
23
import java .text .DateFormat ;
24
24
import java .text .SimpleDateFormat ;
25
25
import java .util .ArrayList ;
26
+ import java .util .Arrays ;
26
27
import java .util .Collection ;
27
28
import java .util .Date ;
28
29
import java .util .List ;
29
30
import java .util .Map ;
30
31
import java .util .Properties ;
31
32
import java .util .TimeZone ;
33
+ import java .util .regex .Matcher ;
34
+ import java .util .regex .Pattern ;
32
35
33
36
import org .apache .maven .artifact .Artifact ;
34
37
import org .apache .maven .artifact .ArtifactUtils ;
@@ -89,6 +92,18 @@ public abstract class AbstractRewritePomsPhase extends AbstractReleasePhase impl
89
92
*/
90
93
private String modelETL = JDomModelETLFactory .NAME ;
91
94
95
+ /**
96
+ * Regular expression pattern matching Maven expressions (i.e. references to Maven properties).
97
+ * The first group selects the property name the expression refers to.
98
+ */
99
+ private static final Pattern EXPRESSION_PATTERN = Pattern .compile ("\\ $\\ {(.+)\\ }" );
100
+
101
+ /**
102
+ * All Maven properties allowed to be referenced in parent versions via expressions
103
+ * @see <a href="https://maven.apache.org/maven-ci-friendly.html">CI-Friendly Versions</a>
104
+ */
105
+ private static final List <String > CI_FRIENDLY_PROPERTIES = Arrays .asList ("revision" , "sha1" , "changelist" );
106
+
92
107
private long startTime = -1 * 1000 ;
93
108
94
109
protected AbstractRewritePomsPhase (
@@ -266,7 +281,7 @@ private void transformDocument(
266
281
267
282
Properties properties = modelTarget .getProperties ();
268
283
269
- String parentVersion = rewriteParent (project , modelTarget , releaseDescriptor , simulate );
284
+ String parentVersion = rewriteParent (project , modelTarget , result , releaseDescriptor , simulate );
270
285
271
286
String projectId = ArtifactUtils .versionlessKey (project .getGroupId (), project .getArtifactId ());
272
287
@@ -440,8 +455,29 @@ private void rewriteVersion(
440
455
modelTarget .setVersion (version );
441
456
}
442
457
458
+ /**
459
+ * Extracts the Maven property name from a given expression.
460
+ * @param expression the expression
461
+ * @return either {@code null} if value is no expression otherwise the property referenced in the expression
462
+ */
463
+ public static String extractPropertyFromExpression (String expression ) {
464
+ Matcher matcher = EXPRESSION_PATTERN .matcher (expression );
465
+ if (!matcher .matches ()) {
466
+ return null ;
467
+ }
468
+ return matcher .group (1 );
469
+ }
470
+
471
+ public static boolean isCiFriendlyVersion (String version ) {
472
+ return CI_FRIENDLY_PROPERTIES .contains (extractPropertyFromExpression (version ));
473
+ }
474
+
443
475
private String rewriteParent (
444
- MavenProject project , Model targetModel , ReleaseDescriptor releaseDescriptor , boolean simulate )
476
+ MavenProject project ,
477
+ Model targetModel ,
478
+ ReleaseResult result ,
479
+ ReleaseDescriptor releaseDescriptor ,
480
+ boolean simulate )
445
481
throws ReleaseFailureException {
446
482
String parentVersion = null ;
447
483
if (project .hasParent ()) {
@@ -458,7 +494,13 @@ private String rewriteParent(
458
494
throw new ReleaseFailureException ("Version for parent '" + parent .getName () + "' was not mapped" );
459
495
}
460
496
} else {
461
- targetModel .getParent ().setVersion (parentVersion );
497
+ if (!isCiFriendlyVersion (targetModel .getParent ().getVersion ())) {
498
+ targetModel .getParent ().setVersion (parentVersion );
499
+ } else {
500
+ logInfo (
501
+ result ,
502
+ " Ignoring parent version update for CI friendly expression " + parent .getVersion ());
503
+ }
462
504
}
463
505
}
464
506
return parentVersion ;
@@ -521,61 +563,73 @@ private void rewriteArtifactVersions(
521
563
if (rawVersion .equals (originalVersion )) {
522
564
logInfo (result , " Updating " + artifactId + " to " + mappedVersion );
523
565
coordinate .setVersion (mappedVersion );
524
- } else if (rawVersion .matches ("\\ $\\ {.+\\ }" )) {
525
- String expression = rawVersion .substring (2 , rawVersion .length () - 1 );
526
-
527
- if (expression .startsWith ("project." )
528
- || expression .startsWith ("pom." )
529
- || "version" .equals (expression )) {
530
- if (!mappedVersion .equals (getNextVersion (releaseDescriptor , projectId ))) {
531
- logInfo (result , " Updating " + artifactId + " to " + mappedVersion );
532
- coordinate .setVersion (mappedVersion );
533
- } else {
534
- logInfo (result , " Ignoring artifact version update for expression " + rawVersion );
535
- }
536
- } else if (properties != null ) {
537
- // version is an expression, check for properties to update instead
538
-
539
- String propertyValue = properties .getProperty (expression );
540
-
541
- if (propertyValue != null ) {
542
- if (propertyValue .equals (originalVersion )) {
543
- logInfo (result , " Updating " + rawVersion + " to " + mappedVersion );
544
- // change the property only if the property is the same as what's in the reactor
545
- properties .setProperty (expression , mappedVersion );
546
- } else if (mappedVersion .equals (propertyValue )) {
547
- // this property may have been updated during processing a sibling.
548
- logInfo (
549
- result ,
550
- " Ignoring artifact version update for expression " + rawVersion
551
- + " because it is already updated" );
552
- } else if (!mappedVersion .equals (rawVersion )) {
553
- // WARNING: ${pom.*} prefix support and ${version} is about to be dropped in mvn4!
554
- // https://issues.apache.org/jira/browse/MNG-7404
555
- // https://issues.apache.org/jira/browse/MNG-7244
556
- if (mappedVersion .matches ("\\ $\\ {project.+\\ }" )
557
- || mappedVersion .matches ("\\ $\\ {pom.+\\ }" )
558
- || "${version}" .equals (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.
559
588
logInfo (
560
589
result ,
561
- " Ignoring artifact version update for expression " + mappedVersion );
562
- // ignore... we cannot update this expression
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 );
563
617
} else {
564
- // the value of the expression conflicts with what the user wanted to release
565
- throw new ReleaseFailureException ("The artifact (" + key + ") requires a "
566
- + "different version (" + mappedVersion + ") than what is found ("
567
- + propertyValue + ") for the expression (" + expression + ") in the "
568
- + "project (" + projectId + ")." );
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 );
569
622
}
570
623
}
571
624
} else {
572
625
// the expression used to define the version of this artifact may be inherited
573
626
// TODO needs a better error message, what pom? what dependency?
574
- throw new ReleaseFailureException ("The version could not be updated: " + rawVersion );
627
+ throw new ReleaseFailureException (
628
+ "Could not find properties resolving version expression : " + rawVersion );
575
629
}
630
+ } else {
631
+ // different/previous version not related to current release
576
632
}
577
- } else {
578
- // different/previous version not related to current release
579
633
}
580
634
} else if (resolvedSnapshotVersion != null ) {
581
635
logInfo (result , " Updating " + artifactId + " to " + resolvedSnapshotVersion );
0 commit comments