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.io.File;
22 import java.nio.file.FileSystems;
23 import java.nio.file.Paths;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.HashSet;
27 import java.util.List;
28 import java.util.Set;
29
30 import org.apache.maven.project.MavenProject;
31 import org.apache.maven.scm.ScmException;
32 import org.apache.maven.scm.ScmFileSet;
33 import org.apache.maven.scm.ScmVersion;
34 import org.apache.maven.scm.command.checkin.CheckInScmResult;
35 import org.apache.maven.scm.manager.NoSuchScmProviderException;
36 import org.apache.maven.scm.provider.ScmProvider;
37 import org.apache.maven.scm.repository.ScmRepository;
38 import org.apache.maven.scm.repository.ScmRepositoryException;
39 import org.apache.maven.shared.release.ReleaseExecutionException;
40 import org.apache.maven.shared.release.ReleaseFailureException;
41 import org.apache.maven.shared.release.ReleaseResult;
42 import org.apache.maven.shared.release.config.ReleaseDescriptor;
43 import org.apache.maven.shared.release.env.ReleaseEnvironment;
44 import org.apache.maven.shared.release.scm.ReleaseScmCommandException;
45 import org.apache.maven.shared.release.scm.ReleaseScmRepositoryException;
46 import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
47 import org.apache.maven.shared.release.util.ReleaseUtil;
48
49 import static java.util.Objects.requireNonNull;
50
51
52
53
54
55
56
57 public abstract class AbstractScmCommitPhase extends AbstractReleasePhase {
58
59
60
61 protected final ScmRepositoryConfigurator scmRepositoryConfigurator;
62
63
64
65
66 protected final String descriptorCommentGetter;
67
68 private final Set<String> exclusionPatterns = new HashSet<>();
69
70 protected AbstractScmCommitPhase(
71 ScmRepositoryConfigurator scmRepositoryConfigurator, String descriptorCommentGetter) {
72 this.scmRepositoryConfigurator = requireNonNull(scmRepositoryConfigurator);
73 this.descriptorCommentGetter = requireNonNull(descriptorCommentGetter);
74 }
75
76 @Override
77 public ReleaseResult execute(
78 ReleaseDescriptor releaseDescriptor,
79 ReleaseEnvironment releaseEnvironment,
80 List<MavenProject> reactorProjects)
81 throws ReleaseExecutionException, ReleaseFailureException {
82 ReleaseResult relResult = new ReleaseResult();
83
84 validateConfiguration(releaseDescriptor);
85
86 List<String> additionalExcludes = releaseDescriptor.getCheckModificationExcludes();
87
88 if (additionalExcludes != null) {
89 exclusionPatterns.addAll(additionalExcludes);
90 }
91
92 runLogic(releaseDescriptor, releaseEnvironment, reactorProjects, relResult, false);
93
94 relResult.setResultCode(ReleaseResult.SUCCESS);
95
96 return relResult;
97 }
98
99 @Override
100 public ReleaseResult simulate(
101 ReleaseDescriptor releaseDescriptor,
102 ReleaseEnvironment releaseEnvironment,
103 List<MavenProject> reactorProjects)
104 throws ReleaseExecutionException, ReleaseFailureException {
105 ReleaseResult result = new ReleaseResult();
106
107 validateConfiguration(releaseDescriptor);
108
109 runLogic(releaseDescriptor, releaseEnvironment, reactorProjects, result, true);
110
111 result.setResultCode(ReleaseResult.SUCCESS);
112 return result;
113 }
114
115
116
117
118
119
120
121
122
123
124
125
126
127 protected abstract void runLogic(
128 ReleaseDescriptor releaseDescriptor,
129 ReleaseEnvironment releaseEnvironment,
130 List<MavenProject> reactorProjects,
131 ReleaseResult result,
132 boolean simulating)
133 throws ReleaseScmCommandException, ReleaseExecutionException, ReleaseScmRepositoryException;
134
135
136
137
138
139
140
141
142
143
144
145
146 protected void performCheckins(
147 ReleaseDescriptor releaseDescriptor,
148 ReleaseEnvironment releaseEnvironment,
149 List<MavenProject> reactorProjects,
150 String message)
151 throws ReleaseScmRepositoryException, ReleaseExecutionException, ReleaseScmCommandException {
152
153 getLogger().info("Checking in modified POMs...");
154
155 ScmRepository repository;
156 ScmProvider provider;
157 try {
158 repository = scmRepositoryConfigurator.getConfiguredRepository(
159 releaseDescriptor, releaseEnvironment.getSettings());
160
161 repository.getProviderRepository().setPushChanges(releaseDescriptor.isPushChanges());
162
163 repository.getProviderRepository().setWorkItem(releaseDescriptor.getWorkItem());
164
165 provider = scmRepositoryConfigurator.getRepositoryProvider(repository);
166 } catch (ScmRepositoryException e) {
167 throw new ReleaseScmRepositoryException(e.getMessage(), e.getValidationMessages());
168 } catch (NoSuchScmProviderException e) {
169 throw new ReleaseExecutionException("Unable to configure SCM repository: " + e.getMessage(), e);
170 }
171
172 if (releaseDescriptor.isCommitByProject()) {
173 for (MavenProject project : reactorProjects) {
174 List<File> pomFiles = createPomFiles(releaseDescriptor, project);
175 ScmFileSet fileSet = new ScmFileSet(project.getFile().getParentFile(), pomFiles);
176
177 checkin(provider, repository, fileSet, releaseDescriptor, message);
178 }
179 } else {
180 List<File> pomFiles = createPomFiles(releaseDescriptor, reactorProjects);
181
182 if (!pomFiles.isEmpty()) {
183 ScmFileSet fileSet = new ScmFileSet(new File(releaseDescriptor.getWorkingDirectory()), pomFiles);
184
185 checkin(provider, repository, fileSet, releaseDescriptor, message);
186 }
187 }
188 }
189
190 private void checkin(
191 ScmProvider provider,
192 ScmRepository repository,
193 ScmFileSet fileSet,
194 ReleaseDescriptor releaseDescriptor,
195 String message)
196 throws ReleaseExecutionException, ReleaseScmCommandException {
197 CheckInScmResult result;
198 try {
199 result = provider.checkIn(repository, fileSet, (ScmVersion) null, message);
200 } catch (ScmException e) {
201 throw new ReleaseExecutionException("An error is occurred in the checkin process: " + e.getMessage(), e);
202 }
203
204 if (!result.isSuccess()) {
205 throw new ReleaseScmCommandException("Unable to commit files", result);
206 }
207 if (releaseDescriptor.isRemoteTagging()) {
208 releaseDescriptor.setScmReleasedPomRevision(result.getScmRevision());
209 }
210 }
211
212
213
214
215
216
217
218
219
220 protected void simulateCheckins(
221 ReleaseDescriptor releaseDescriptor,
222 List<MavenProject> reactorProjects,
223 ReleaseResult result,
224 String message) {
225 Collection<File> pomFiles = createPomFiles(releaseDescriptor, reactorProjects);
226 logInfo(result, "Full run would be commit " + pomFiles.size() + " files with message: '" + message + "'");
227 }
228
229
230
231
232
233
234
235 protected void validateConfiguration(ReleaseDescriptor releaseDescriptor) throws ReleaseFailureException {
236 if (releaseDescriptor.getScmReleaseLabel() == null) {
237 throw new ReleaseFailureException("A release label is required for committing");
238 }
239 }
240
241
242
243
244
245
246
247
248
249 protected String createMessage(List<MavenProject> reactorProjects, ReleaseDescriptor releaseDescriptor)
250 throws ReleaseExecutionException {
251 String comment;
252 boolean branch = false;
253 if ("getScmReleaseCommitComment".equals(descriptorCommentGetter)) {
254 comment = releaseDescriptor.getScmReleaseCommitComment();
255 } else if ("getScmDevelopmentCommitComment".equals(descriptorCommentGetter)) {
256 comment = releaseDescriptor.getScmDevelopmentCommitComment();
257 } else if ("getScmBranchCommitComment".equals(descriptorCommentGetter)) {
258 comment = releaseDescriptor.getScmBranchCommitComment();
259 branch = true;
260 } else if ("getScmRollbackCommitComment".equals(descriptorCommentGetter)) {
261 comment = releaseDescriptor.getScmRollbackCommitComment();
262 } else {
263 throw new ReleaseExecutionException(
264 "Invalid configuration of descriptorCommentGetter='" + descriptorCommentGetter + "'");
265 }
266
267 MavenProject project = ReleaseUtil.getRootProject(reactorProjects);
268 comment = comment.replace(
269 "@{prefix}", releaseDescriptor.getScmCommentPrefix().trim());
270 comment = comment.replace("@{groupId}", project.getGroupId());
271 comment = comment.replace("@{artifactId}", project.getArtifactId());
272 if (branch) {
273 comment = comment.replace("@{branchName}", releaseDescriptor.getScmReleaseLabel());
274 } else {
275 comment = comment.replace("@{releaseLabel}", releaseDescriptor.getScmReleaseLabel());
276 }
277 return comment;
278 }
279
280
281
282
283
284
285
286
287 protected static List<File> createPomFiles(ReleaseDescriptor releaseDescriptor, MavenProject project) {
288 List<File> pomFiles = new ArrayList<>();
289
290 pomFiles.add(ReleaseUtil.getStandardPom(project));
291
292 if (releaseDescriptor.isGenerateReleasePoms() && !releaseDescriptor.isSuppressCommitBeforeTagOrBranch()) {
293 pomFiles.add(ReleaseUtil.getReleasePom(project));
294 }
295
296 return pomFiles;
297 }
298
299
300
301
302
303
304
305
306 protected List<File> createPomFiles(ReleaseDescriptor releaseDescriptor, List<MavenProject> reactorProjects) {
307
308 List<File> pomFiles = new ArrayList<>();
309 for (MavenProject project : reactorProjects) {
310
311 final String path = project.getFile().getPath();
312
313 boolean isExcludedPathFound = exclusionPatterns.stream()
314 .anyMatch(exclusionPattern -> FileSystems.getDefault()
315 .getPathMatcher("glob:" + exclusionPattern)
316 .matches(Paths.get(path)));
317 if (!isExcludedPathFound) {
318 pomFiles.addAll(createPomFiles(releaseDescriptor, project));
319 }
320 }
321 return pomFiles;
322 }
323 }