21
21
22
22
import javax .inject .Inject ;
23
23
24
+ import java .util .Arrays ;
25
+ import java .util .Collections ;
24
26
import java .util .Map ;
27
+ import java .util .Optional ;
28
+ import java .util .stream .Collectors ;
25
29
26
30
import org .apache .maven .artifact .Artifact ;
27
31
import org .apache .maven .artifact .versioning .ArtifactVersion ;
32
+ import org .apache .maven .artifact .versioning .InvalidVersionSpecificationException ;
33
+ import org .apache .maven .artifact .versioning .VersionRange ;
28
34
import org .apache .maven .plugin .MojoExecutionException ;
29
35
import org .apache .maven .plugin .MojoFailureException ;
30
36
import org .apache .maven .plugins .annotations .Mojo ;
37
+ import org .apache .maven .plugins .annotations .Parameter ;
31
38
import org .apache .maven .repository .RepositorySystem ;
32
39
import org .apache .maven .wagon .Wagon ;
40
+ import org .codehaus .mojo .versions .api .ArtifactVersions ;
41
+ import org .codehaus .mojo .versions .api .Segment ;
33
42
import org .codehaus .mojo .versions .api .VersionRetrievalException ;
34
43
import org .codehaus .mojo .versions .api .recording .ChangeRecorder ;
44
+ import org .codehaus .mojo .versions .ordering .InvalidSegmentException ;
35
45
import org .codehaus .mojo .versions .rewriting .ModifiedPomXMLEventReader ;
46
+ import org .codehaus .mojo .versions .utils .DefaultArtifactVersionCache ;
36
47
import org .codehaus .mojo .versions .utils .DependencyBuilder ;
48
+ import org .codehaus .mojo .versions .utils .SegmentUtils ;
49
+
50
+ import static org .apache .maven .shared .utils .StringUtils .isBlank ;
37
51
38
52
/**
39
53
* Displays any updates of the project's parent project
@@ -46,6 +60,78 @@ public class DisplayParentUpdatesMojo extends AbstractVersionsDisplayMojo {
46
60
47
61
public static final int MESSAGE_LENGTH = 68 ;
48
62
63
+ // ------------------------------ FIELDS ------------------------------
64
+
65
+ /**
66
+ * <p>If {@code skipResolution} is not set, specifies the <em>bottom</em> version considered
67
+ * for target version resolution. If it is a version range, the resolved version will be
68
+ * restricted by that range.</p>
69
+ *
70
+ * <p>If {@code skipResolution} is {@code true}, will specify the target version to which
71
+ * the parent artifact will be updated.</p>
72
+ * @since 2.17.0
73
+ */
74
+ @ Parameter (property = "parentVersion" )
75
+ protected String parentVersion = null ;
76
+
77
+ /**
78
+ * to update parent version by force when it is RELEASE or LATEST
79
+ *
80
+ * @since 2.17.0
81
+ */
82
+ @ Parameter (property = "forceUpdate" , defaultValue = "false" )
83
+ protected boolean forceUpdate = false ;
84
+
85
+ /**
86
+ * Skips version resolution, only valid if {@code parentVersion} is set.
87
+ * Will effectively set the new parent version to the one from {@code parentVersion}
88
+ *
89
+ * @since 2.17.0
90
+ */
91
+ @ Parameter (property = "skipResolution" , defaultValue = "false" )
92
+ protected boolean skipResolution = false ;
93
+
94
+ /**
95
+ * <p>Whether to downgrade a snapshot dependency if <code>allowSnapshots</code> is <code>false</code>
96
+ * and there exists a version within the range fulfilling the criteria.</p>
97
+ * <p>Default <code>false</code></p>
98
+ *
99
+ * @since 2.17.0
100
+ */
101
+ @ Parameter (property = "allowDowngrade" , defaultValue = "false" )
102
+ protected boolean allowDowngrade ;
103
+
104
+ /**
105
+ * Whether to allow the major version number to be changed.
106
+ *
107
+ * @since 2.17.0
108
+ */
109
+ @ Parameter (property = "allowMajorUpdates" , defaultValue = "true" )
110
+ protected boolean allowMajorUpdates = true ;
111
+
112
+ /**
113
+ * <p>Whether to allow the minor version number to be changed.</p>
114
+ *
115
+ * <p><b>Note: {@code false} also implies {@linkplain #allowMajorUpdates} {@code false}</b></p>
116
+ *
117
+ * @since 2.17.0
118
+ */
119
+ @ Parameter (property = "allowMinorUpdates" , defaultValue = "true" )
120
+ protected boolean allowMinorUpdates = true ;
121
+
122
+ /**
123
+ * <p>Whether to allow the incremental version number to be changed.</p>
124
+ *
125
+ * <p><b>Note: {@code false} also implies {@linkplain #allowMajorUpdates}
126
+ * and {@linkplain #allowMinorUpdates} {@code false}</b></p>
127
+ *
128
+ * @since 2.17.0
129
+ */
130
+ @ Parameter (property = "allowIncrementalUpdates" , defaultValue = "true" )
131
+ protected boolean allowIncrementalUpdates = true ;
132
+
133
+ // -------------------------- OTHER METHODS --------------------------
134
+
49
135
@ Inject
50
136
public DisplayParentUpdatesMojo (
51
137
RepositorySystem repositorySystem ,
@@ -68,36 +154,34 @@ public void execute() throws MojoExecutionException, MojoFailureException {
68
154
return ;
69
155
}
70
156
71
- String currentVersion = getProject ().getParent ().getVersion ();
72
- Artifact artifact = getHelper ()
73
- .createDependencyArtifact (DependencyBuilder .newBuilder ()
74
- .withGroupId (getProject ().getParent ().getGroupId ())
75
- .withArtifactId (getProject ().getParent ().getArtifactId ())
76
- .withVersion (currentVersion )
77
- .withType ("pom" )
78
- .build ());
79
-
157
+ if (skipResolution && isBlank (parentVersion )) {
158
+ throw new MojoExecutionException ("skipResolution is only valid if parentVersion is set" );
159
+ }
160
+ String initialVersion = Optional .ofNullable (parentVersion )
161
+ .orElse (getProject ().getParent ().getVersion ());
80
162
ArtifactVersion artifactVersion ;
81
163
try {
82
- artifactVersion = findLatestVersion (artifact , null , allowSnapshots , false );
83
- } catch (VersionRetrievalException e ) {
164
+ artifactVersion = skipResolution
165
+ ? DefaultArtifactVersionCache .of (parentVersion )
166
+ : resolveTargetVersion (initialVersion );
167
+ } catch (VersionRetrievalException | InvalidVersionSpecificationException | InvalidSegmentException e ) {
84
168
throw new MojoExecutionException (e .getMessage (), e );
85
169
}
86
170
87
- if (artifactVersion == null || currentVersion .equals (artifactVersion .toString ())) {
171
+ if (artifactVersion == null || initialVersion .equals (artifactVersion .toString ())) {
88
172
logLine (false , "The parent project is the latest version:" );
89
173
StringBuilder buf = new StringBuilder (MESSAGE_LENGTH );
90
174
buf .append (" " );
91
175
buf .append (getProject ().getParent ().getGroupId ());
92
176
buf .append (':' );
93
177
buf .append (getProject ().getParent ().getArtifactId ());
94
178
buf .append (' ' );
95
- int padding = MESSAGE_LENGTH - currentVersion .length ();
179
+ int padding = MESSAGE_LENGTH - initialVersion .length ();
96
180
while (buf .length () < padding ) {
97
181
buf .append ('.' );
98
182
}
99
183
buf .append (' ' );
100
- buf .append (currentVersion );
184
+ buf .append (initialVersion );
101
185
logLine (false , buf .toString ());
102
186
} else {
103
187
logLine (false , "The parent project has a newer version:" );
@@ -108,20 +192,70 @@ public void execute() throws MojoExecutionException, MojoFailureException {
108
192
buf .append (getProject ().getParent ().getArtifactId ());
109
193
buf .append (' ' );
110
194
int padding = MESSAGE_LENGTH
111
- - currentVersion .length ()
195
+ - initialVersion .length ()
112
196
- artifactVersion .toString ().length ()
113
197
- " -> " .length ();
114
198
while (buf .length () < padding ) {
115
199
buf .append ('.' );
116
200
}
117
201
buf .append (' ' );
118
- buf .append (currentVersion );
202
+ buf .append (initialVersion );
119
203
buf .append (" -> " );
120
204
buf .append (artifactVersion );
121
205
logLine (false , buf .toString ());
122
206
}
123
207
}
124
208
209
+ protected ArtifactVersion resolveTargetVersion (String initialVersion )
210
+ throws MojoExecutionException , VersionRetrievalException , InvalidVersionSpecificationException ,
211
+ InvalidSegmentException {
212
+ Artifact artifact = getHelper ()
213
+ .createDependencyArtifact (DependencyBuilder .newBuilder ()
214
+ .withGroupId (getProject ().getParent ().getGroupId ())
215
+ .withArtifactId (getProject ().getParent ().getArtifactId ())
216
+ .withVersion (initialVersion )
217
+ .withType ("pom" )
218
+ .build ());
219
+
220
+ VersionRange targetVersionRange = VersionRange .createFromVersionSpec (initialVersion );
221
+ if (targetVersionRange .getRecommendedVersion () != null ) {
222
+ targetVersionRange = targetVersionRange .restrict (
223
+ VersionRange .createFromVersionSpec ("[" + targetVersionRange .getRecommendedVersion () + ",)" ));
224
+ }
225
+
226
+ final ArtifactVersions versions = getHelper ().lookupArtifactVersions (artifact , false );
227
+ Optional <Segment > unchangedSegment = SegmentUtils .determineUnchangedSegment (
228
+ allowMajorUpdates , allowMinorUpdates , allowIncrementalUpdates , getLog ());
229
+
230
+ // currentVersion (set to parentVersion here) is not included in the version range for searching upgrades
231
+ // unless we set allowDowngrade to true
232
+ for (ArtifactVersion candidate : reverse (versions .getNewerVersions (
233
+ initialVersion , unchangedSegment , allowSnapshots , !isBlank (parentVersion ) || allowDowngrade ))) {
234
+ if (allowDowngrade
235
+ || targetVersionRange == null
236
+ || ArtifactVersions .isVersionInRange (candidate , targetVersionRange )) {
237
+ if (shouldApplyUpdate (artifact , getProject ().getParent ().getVersion (), candidate , forceUpdate )) {
238
+ return candidate ;
239
+ } else {
240
+ getLog ().debug ("Update not applied. Exiting." );
241
+ return null ;
242
+ }
243
+ }
244
+ }
245
+
246
+ if (versions .isEmpty (allowSnapshots )) {
247
+ getLog ().info ("No versions found" );
248
+ } else {
249
+ getLog ().info ("The parent project is the latest version" );
250
+ }
251
+
252
+ return null ;
253
+ }
254
+
255
+ private static <T > Iterable <T > reverse (T [] array ) {
256
+ return Arrays .stream (array ).sorted (Collections .reverseOrder ()).collect (Collectors .toList ());
257
+ }
258
+
125
259
@ Override
126
260
protected void update (ModifiedPomXMLEventReader pom ) {}
127
261
}
0 commit comments