1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.shared.release.phase;
20
21 import java.util.List;
22 import java.util.Map;
23
24 import org.apache.maven.artifact.ArtifactUtils;
25 import org.apache.maven.project.MavenProject;
26 import org.apache.maven.scm.manager.NoSuchScmProviderException;
27 import org.apache.maven.scm.provider.ScmProvider;
28 import org.apache.maven.scm.repository.ScmRepository;
29 import org.apache.maven.scm.repository.ScmRepositoryException;
30 import org.apache.maven.shared.release.ReleaseExecutionException;
31 import org.apache.maven.shared.release.ReleaseResult;
32 import org.apache.maven.shared.release.config.ReleaseDescriptor;
33 import org.apache.maven.shared.release.env.ReleaseEnvironment;
34 import org.apache.maven.shared.release.policy.PolicyException;
35 import org.apache.maven.shared.release.policy.version.VersionPolicy;
36 import org.apache.maven.shared.release.policy.version.VersionPolicyRequest;
37 import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
38 import org.apache.maven.shared.release.util.ReleaseUtil;
39 import org.apache.maven.shared.release.versions.VersionParseException;
40 import org.codehaus.plexus.components.interactivity.Prompter;
41 import org.codehaus.plexus.components.interactivity.PrompterException;
42 import org.codehaus.plexus.util.StringUtils;
43 import org.slf4j.Logger;
44
45 import static java.util.Objects.requireNonNull;
46 import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 public abstract class AbstractMapVersionsPhase extends AbstractReleasePhase {
76
77
78
79 private final ScmRepositoryConfigurator scmRepositoryConfigurator;
80
81
82
83
84 private final Prompter prompter;
85
86
87
88
89 private final Map<String, VersionPolicy> versionPolicies;
90
91
92
93
94 private final boolean convertToSnapshot;
95
96
97
98
99 private final boolean convertToBranch;
100
101 public AbstractMapVersionsPhase(
102 ScmRepositoryConfigurator scmRepositoryConfigurator,
103 Prompter prompter,
104 Map<String, VersionPolicy> versionPolicies,
105 boolean convertToSnapshot,
106 boolean convertToBranch) {
107 this.scmRepositoryConfigurator = requireNonNull(scmRepositoryConfigurator);
108 this.prompter = requireNonNull(prompter);
109 this.versionPolicies = requireNonNull(versionPolicies);
110 this.convertToSnapshot = convertToSnapshot;
111 this.convertToBranch = convertToBranch;
112 }
113
114 @Override
115 public ReleaseResult execute(
116 ReleaseDescriptor releaseDescriptor,
117 ReleaseEnvironment releaseEnvironment,
118 List<MavenProject> reactorProjects)
119 throws ReleaseExecutionException {
120 ReleaseResult result = new ReleaseResult();
121
122 MavenProject rootProject = ReleaseUtil.getRootProject(reactorProjects);
123
124 if (releaseDescriptor.isAutoVersionSubmodules() && ArtifactUtils.isSnapshot(rootProject.getVersion())) {
125
126 MavenProject project = rootProject;
127
128 String projectId = ArtifactUtils.versionlessKey(project.getGroupId(), project.getArtifactId());
129
130 String nextVersion = resolveNextVersion(project, projectId, releaseDescriptor, releaseEnvironment);
131
132 if (!convertToSnapshot) {
133 releaseDescriptor.addReleaseVersion(projectId, nextVersion);
134 } else if (releaseDescriptor.isBranchCreation() && convertToBranch) {
135 releaseDescriptor.addReleaseVersion(projectId, nextVersion);
136 } else {
137 releaseDescriptor.addDevelopmentVersion(projectId, nextVersion);
138 }
139
140 for (MavenProject subProject : reactorProjects) {
141 String subProjectId = ArtifactUtils.versionlessKey(subProject.getGroupId(), subProject.getArtifactId());
142
143 if (convertToSnapshot) {
144 String subProjectNextVersion = releaseDescriptor.getProjectDevelopmentVersion(subProjectId);
145 String v;
146 if (subProjectNextVersion != null) {
147 v = subProjectNextVersion;
148 } else if (ArtifactUtils.isSnapshot(subProject.getVersion())) {
149 v = nextVersion;
150 } else {
151 v = subProject.getVersion();
152 }
153
154 if (releaseDescriptor.isBranchCreation() && convertToBranch) {
155 releaseDescriptor.addReleaseVersion(subProjectId, v);
156 } else {
157 releaseDescriptor.addDevelopmentVersion(subProjectId, v);
158 }
159 } else {
160 String subProjectNextVersion = releaseDescriptor.getProjectReleaseVersion(subProjectId);
161 if (subProjectNextVersion != null) {
162 releaseDescriptor.addReleaseVersion(subProjectId, subProjectNextVersion);
163 } else {
164 releaseDescriptor.addReleaseVersion(subProjectId, nextVersion);
165 }
166 }
167 }
168 } else {
169 for (MavenProject project : reactorProjects) {
170 String projectId = ArtifactUtils.versionlessKey(project.getGroupId(), project.getArtifactId());
171
172 String nextVersion = resolveNextVersion(project, projectId, releaseDescriptor, releaseEnvironment);
173
174 if (!convertToSnapshot) {
175 releaseDescriptor.addReleaseVersion(projectId, nextVersion);
176 } else if (releaseDescriptor.isBranchCreation() && convertToBranch) {
177 releaseDescriptor.addReleaseVersion(projectId, nextVersion);
178 } else {
179 releaseDescriptor.addDevelopmentVersion(projectId, nextVersion);
180 }
181 }
182 }
183
184 result.setResultCode(ReleaseResult.SUCCESS);
185
186 return result;
187 }
188
189 private String resolveNextVersion(
190 MavenProject project,
191 String projectId,
192 ReleaseDescriptor releaseDescriptor,
193 ReleaseEnvironment releaseEnvironment)
194 throws ReleaseExecutionException {
195 String defaultVersion;
196 if (convertToBranch) {
197
198 if (!(releaseDescriptor.isUpdateBranchVersions()
199 && (ArtifactUtils.isSnapshot(project.getVersion())
200 || releaseDescriptor.isUpdateVersionsToSnapshot()))) {
201 return project.getVersion();
202 }
203
204 defaultVersion = getReleaseVersion(projectId, releaseDescriptor);
205 } else if (!convertToSnapshot)
206 {
207 defaultVersion = getReleaseVersion(projectId, releaseDescriptor);
208 } else if (releaseDescriptor.isBranchCreation()) {
209
210 if (!(ArtifactUtils.isSnapshot(project.getVersion()) && releaseDescriptor.isUpdateWorkingCopyVersions())) {
211 return project.getVersion();
212 }
213
214 defaultVersion = getDevelopmentVersion(projectId, releaseDescriptor);
215 } else {
216
217 if (!(releaseDescriptor.isUpdateWorkingCopyVersions())) {
218 return project.getVersion();
219 }
220
221 defaultVersion = getDevelopmentVersion(projectId, releaseDescriptor);
222 }
223
224
225 String suggestedVersion = null;
226 String nextVersion = defaultVersion;
227 String messageFormat = null;
228 try {
229 while (nextVersion == null || ArtifactUtils.isSnapshot(nextVersion) != convertToSnapshot) {
230 if (suggestedVersion == null) {
231 String baseVersion = null;
232 if (convertToSnapshot) {
233 baseVersion = getReleaseVersion(projectId, releaseDescriptor);
234 }
235
236 if (baseVersion == null) {
237 baseVersion = project.getVersion();
238 }
239
240 try {
241 try {
242 suggestedVersion =
243 resolveSuggestedVersion(baseVersion, releaseDescriptor, releaseEnvironment);
244 } catch (VersionParseException e) {
245 if (releaseDescriptor.isInteractive()) {
246 suggestedVersion =
247 resolveSuggestedVersion("1.0", releaseDescriptor, releaseEnvironment);
248 } else {
249 throw new ReleaseExecutionException(
250 "Error parsing version, cannot determine next " + "version: " + e.getMessage(),
251 e);
252 }
253 }
254 } catch (PolicyException | VersionParseException e) {
255 throw new ReleaseExecutionException(e.getMessage(), e);
256 }
257 }
258
259 if (releaseDescriptor.isInteractive()) {
260 if (messageFormat == null) {
261 messageFormat = "What is the " + getContextString(releaseDescriptor) + " version for \"%s\"? ("
262 + buffer().project("%s") + ")";
263 }
264 String message = String.format(messageFormat, project.getName(), project.getArtifactId());
265 nextVersion = prompter.prompt(message, suggestedVersion);
266
267
268 } else if (defaultVersion == null) {
269 nextVersion = suggestedVersion;
270 } else if (convertToSnapshot) {
271 throw new ReleaseExecutionException(defaultVersion + " is invalid, expected a snapshot");
272 } else {
273 throw new ReleaseExecutionException(defaultVersion + " is invalid, expected a non-snapshot");
274 }
275 }
276 } catch (PrompterException e) {
277 throw new ReleaseExecutionException("Error reading version from input handler: " + e.getMessage(), e);
278 }
279 return nextVersion;
280 }
281
282 private String getContextString(ReleaseDescriptor releaseDescriptor) {
283 if (convertToBranch) {
284 return "branch";
285 }
286 if (!convertToSnapshot) {
287 return "release";
288 }
289 if (releaseDescriptor.isBranchCreation()) {
290 return "new working copy";
291 }
292 return "new development";
293 }
294
295 private String resolveSuggestedVersion(
296 String baseVersion, ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment)
297 throws PolicyException, VersionParseException {
298 String policyId = releaseDescriptor.getProjectVersionPolicyId();
299 VersionPolicy policy = versionPolicies.get(policyId);
300 if (policy == null) {
301 throw new PolicyException("Policy '" + policyId + "' is unknown, available: " + versionPolicies.keySet());
302 }
303
304 VersionPolicyRequest request = new VersionPolicyRequest().setVersion(baseVersion);
305
306 if (releaseDescriptor.getProjectVersionPolicyConfig() != null) {
307 request.setConfig(releaseDescriptor.getProjectVersionPolicyConfig().toString());
308 }
309 request.setWorkingDirectory(releaseDescriptor.getWorkingDirectory());
310
311 if (scmRepositoryConfigurator != null && releaseDescriptor.getScmSourceUrl() != null) {
312 try {
313 ScmRepository repository = scmRepositoryConfigurator.getConfiguredRepository(
314 releaseDescriptor, releaseEnvironment.getSettings());
315
316 ScmProvider provider = scmRepositoryConfigurator.getRepositoryProvider(repository);
317
318 request.setScmRepository(repository);
319 request.setScmProvider(provider);
320 } catch (ScmRepositoryException | NoSuchScmProviderException e) {
321 Logger logger = getLogger();
322 if (logger.isWarnEnabled()) {
323 logger.warn("Next Version will NOT be based on the version control: {}", e.getMessage());
324 } else {
325 if (logger.isDebugEnabled()) {
326 logger.warn("Next Version will NOT be based on the version control", e);
327 }
328 }
329 }
330 }
331 return convertToSnapshot
332 ? policy.getDevelopmentVersion(request).getVersion()
333 : policy.getReleaseVersion(request).getVersion();
334 }
335
336 private String getDevelopmentVersion(String projectId, ReleaseDescriptor releaseDescriptor) {
337 String projectVersion = releaseDescriptor.getProjectDevelopmentVersion(projectId);
338
339 if (StringUtils.isEmpty(projectVersion)) {
340 projectVersion = releaseDescriptor.getDefaultDevelopmentVersion();
341 }
342
343 if (StringUtils.isEmpty(projectVersion)) {
344 return null;
345 }
346
347 return projectVersion;
348 }
349
350 private String getReleaseVersion(String projectId, ReleaseDescriptor releaseDescriptor) {
351 String projectVersion = releaseDescriptor.getProjectReleaseVersion(projectId);
352
353 if (StringUtils.isEmpty(projectVersion)) {
354 projectVersion = releaseDescriptor.getDefaultReleaseVersion();
355 }
356
357 if (StringUtils.isEmpty(projectVersion)) {
358 return null;
359 }
360
361 return projectVersion;
362 }
363
364 @Override
365 public ReleaseResult simulate(
366 ReleaseDescriptor releaseDescriptor,
367 ReleaseEnvironment releaseEnvironment,
368 List<MavenProject> reactorProjects)
369 throws ReleaseExecutionException {
370 ReleaseResult result = new ReleaseResult();
371
372
373 execute(releaseDescriptor, releaseEnvironment, reactorProjects);
374
375 result.setResultCode(ReleaseResult.SUCCESS);
376
377 return result;
378 }
379 }