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.Arrays;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Properties;
25 import java.util.concurrent.atomic.AtomicReference;
26
27 import org.apache.maven.artifact.ArtifactUtils;
28 import org.apache.maven.project.MavenProject;
29 import org.apache.maven.scm.manager.NoSuchScmProviderException;
30 import org.apache.maven.scm.provider.ScmProvider;
31 import org.apache.maven.scm.repository.ScmRepository;
32 import org.apache.maven.scm.repository.ScmRepositoryException;
33 import org.apache.maven.shared.release.ReleaseExecutionException;
34 import org.apache.maven.shared.release.ReleaseResult;
35 import org.apache.maven.shared.release.config.ReleaseDescriptor;
36 import org.apache.maven.shared.release.env.ReleaseEnvironment;
37 import org.apache.maven.shared.release.policy.PolicyException;
38 import org.apache.maven.shared.release.policy.naming.NamingPolicy;
39 import org.apache.maven.shared.release.policy.naming.NamingPolicyRequest;
40 import org.apache.maven.shared.release.scm.ReleaseScmRepositoryException;
41 import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
42 import org.apache.maven.shared.release.util.ReleaseUtil;
43 import org.codehaus.plexus.components.interactivity.Prompter;
44 import org.codehaus.plexus.components.interactivity.PrompterException;
45 import org.codehaus.plexus.interpolation.InterpolationException;
46 import org.codehaus.plexus.interpolation.Interpolator;
47 import org.codehaus.plexus.interpolation.PrefixAwareRecursionInterceptor;
48 import org.codehaus.plexus.interpolation.PrefixedPropertiesValueSource;
49 import org.codehaus.plexus.interpolation.RecursionInterceptor;
50 import org.codehaus.plexus.interpolation.StringSearchInterpolator;
51
52 import static java.util.Objects.requireNonNull;
53 import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
54
55
56
57
58
59
60 public abstract class AbstractInputVariablesPhase extends AbstractReleasePhase {
61
62
63
64 private final AtomicReference<Prompter> prompter;
65
66
67
68
69 private final ScmRepositoryConfigurator scmRepositoryConfigurator;
70
71
72
73
74 private final Map<String, NamingPolicy> namingPolicies;
75
76
77
78
79 private final boolean branchOperation;
80
81
82
83
84 private final String defaultNamingPolicy;
85
86 protected AbstractInputVariablesPhase(
87 Prompter prompter,
88 ScmRepositoryConfigurator scmRepositoryConfigurator,
89 Map<String, NamingPolicy> namingPolicies,
90 boolean branchOperation,
91 String defaultNamingPolicy) {
92 this.prompter = new AtomicReference<>(requireNonNull(prompter));
93 this.scmRepositoryConfigurator = requireNonNull(scmRepositoryConfigurator);
94 this.namingPolicies = requireNonNull(namingPolicies);
95 this.branchOperation = branchOperation;
96 this.defaultNamingPolicy = defaultNamingPolicy;
97 }
98
99
100
101
102 public void setPrompter(Prompter prompter) {
103 this.prompter.set(prompter);
104 }
105
106 boolean isBranchOperation() {
107 return branchOperation;
108 }
109
110
111
112
113
114
115
116
117
118
119 protected ScmProvider getScmProvider(ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment)
120 throws ReleaseScmRepositoryException, ReleaseExecutionException {
121 try {
122 ScmRepository repository = scmRepositoryConfigurator.getConfiguredRepository(
123 releaseDescriptor, releaseEnvironment.getSettings());
124
125 return scmRepositoryConfigurator.getRepositoryProvider(repository);
126 } catch (ScmRepositoryException e) {
127 throw new ReleaseScmRepositoryException(
128 e.getMessage() + " for URL: " + releaseDescriptor.getScmSourceUrl(), e.getValidationMessages());
129 } catch (NoSuchScmProviderException e) {
130 throw new ReleaseExecutionException("Unable to configure SCM repository: " + e.getMessage(), e);
131 }
132 }
133
134 @Override
135 public ReleaseResult execute(
136 ReleaseDescriptor releaseDescriptor,
137 ReleaseEnvironment releaseEnvironment,
138 List<MavenProject> reactorProjects)
139 throws ReleaseExecutionException {
140 ReleaseResult result = new ReleaseResult();
141
142
143 MavenProject project = ReleaseUtil.getRootProject(reactorProjects);
144
145 String tag = releaseDescriptor.getScmReleaseLabel();
146
147 if (tag == null) {
148
149 String key = ArtifactUtils.versionlessKey(project.getGroupId(), project.getArtifactId());
150 String releaseVersion = releaseDescriptor.getProjectReleaseVersion(key);
151 if (releaseVersion == null) {
152 throw new ReleaseExecutionException("Project tag cannot be selected if version is not yet mapped");
153 }
154
155 String suggestedName;
156 String scmTagNameFormat = releaseDescriptor.getScmTagNameFormat();
157 if (releaseDescriptor.getProjectNamingPolicyId() != null) {
158 try {
159 suggestedName =
160 resolveSuggestedName(releaseDescriptor.getProjectNamingPolicyId(), releaseVersion, project);
161 } catch (PolicyException e) {
162 throw new ReleaseExecutionException(e.getMessage(), e);
163 }
164 } else if (scmTagNameFormat != null) {
165 Interpolator interpolator = new StringSearchInterpolator("@{", "}");
166 List<String> possiblePrefixes = Arrays.asList("project", "pom");
167 Properties values = new Properties();
168 values.setProperty("artifactId", project.getArtifactId());
169 values.setProperty("groupId", project.getGroupId());
170 values.setProperty("version", releaseVersion);
171 interpolator.addValueSource(new PrefixedPropertiesValueSource(possiblePrefixes, values, true));
172 RecursionInterceptor recursionInterceptor = new PrefixAwareRecursionInterceptor(possiblePrefixes);
173 try {
174 suggestedName = interpolator.interpolate(scmTagNameFormat, recursionInterceptor);
175 } catch (InterpolationException e) {
176 throw new ReleaseExecutionException(
177 "Could not interpolate specified tag name format: " + scmTagNameFormat, e);
178 }
179 } else {
180 try {
181 suggestedName = resolveSuggestedName(defaultNamingPolicy, releaseVersion, project);
182 } catch (PolicyException e) {
183 throw new ReleaseExecutionException(e.getMessage(), e);
184 }
185 }
186
187 ScmProvider provider;
188 try {
189 provider = getScmProvider(releaseDescriptor, releaseEnvironment);
190 } catch (ReleaseScmRepositoryException e) {
191 throw new ReleaseExecutionException(
192 "No scm provider can be found for url: " + releaseDescriptor.getScmSourceUrl(), e);
193 }
194
195 suggestedName = provider.sanitizeTagName(suggestedName);
196
197 if (releaseDescriptor.isInteractive()) {
198 try {
199 if (branchOperation) {
200 tag = prompter.get()
201 .prompt("What is the branch name for \"" + project.getName() + "\"? ("
202 + buffer().project(project.getArtifactId()) + ")");
203 if (tag == null || tag.isEmpty()) {
204 throw new ReleaseExecutionException("No branch name was given.");
205 }
206 } else {
207 tag = prompter.get()
208 .prompt(
209 "What is the SCM release tag or label for \"" + project.getName() + "\"? ("
210 + buffer().project(project.getArtifactId()) + ")",
211 suggestedName);
212 }
213 } catch (PrompterException e) {
214 throw new ReleaseExecutionException(
215 "Error reading version from input handler: " + e.getMessage(), e);
216 }
217 } else if (suggestedName == null) {
218 if (isBranchOperation()) {
219 throw new ReleaseExecutionException("No branch name was given.");
220 } else {
221 throw new ReleaseExecutionException("No tag name was given.");
222 }
223 } else {
224 tag = suggestedName;
225 }
226 releaseDescriptor.setScmReleaseLabel(tag);
227 }
228
229 result.setResultCode(ReleaseResult.SUCCESS);
230
231 return result;
232 }
233
234 @Override
235 public ReleaseResult simulate(
236 ReleaseDescriptor releaseDescriptor,
237 ReleaseEnvironment releaseEnvironment,
238 List<MavenProject> reactorProjects)
239 throws ReleaseExecutionException {
240 ReleaseResult result = new ReleaseResult();
241
242
243 execute(releaseDescriptor, releaseEnvironment, reactorProjects);
244
245 result.setResultCode(ReleaseResult.SUCCESS);
246
247 return result;
248 }
249
250 private String resolveSuggestedName(String policyId, String version, MavenProject project) throws PolicyException {
251 if (policyId == null) {
252 return null;
253 }
254
255 NamingPolicy policy = namingPolicies.get(policyId);
256 if (policy == null) {
257 throw new PolicyException("Policy '" + policyId + "' is unknown, available: " + namingPolicies.keySet());
258 }
259
260 NamingPolicyRequest request = new NamingPolicyRequest()
261 .setGroupId(project.getGroupId())
262 .setArtifactId(project.getArtifactId())
263 .setVersion(version);
264 return policy.getName(request).getName();
265 }
266 }