View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.shared.release.phase;
20  
21  import java.io.File;
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.List;
25  
26  import org.apache.maven.project.MavenProject;
27  import org.apache.maven.scm.ScmException;
28  import org.apache.maven.scm.ScmFileSet;
29  import org.apache.maven.scm.ScmVersion;
30  import org.apache.maven.scm.command.checkin.CheckInScmResult;
31  import org.apache.maven.scm.manager.NoSuchScmProviderException;
32  import org.apache.maven.scm.provider.ScmProvider;
33  import org.apache.maven.scm.repository.ScmRepository;
34  import org.apache.maven.scm.repository.ScmRepositoryException;
35  import org.apache.maven.shared.release.ReleaseExecutionException;
36  import org.apache.maven.shared.release.ReleaseFailureException;
37  import org.apache.maven.shared.release.ReleaseResult;
38  import org.apache.maven.shared.release.config.ReleaseDescriptor;
39  import org.apache.maven.shared.release.env.ReleaseEnvironment;
40  import org.apache.maven.shared.release.scm.ReleaseScmCommandException;
41  import org.apache.maven.shared.release.scm.ReleaseScmRepositoryException;
42  import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
43  import org.apache.maven.shared.release.util.ReleaseUtil;
44  
45  import static java.util.Objects.requireNonNull;
46  
47  /**
48   * Holds the basic concept of committing changes to the current working copy.
49   *
50   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
51   * @author <a href="mailto:me@lcorneliussen.de">Lars Corneliussen</a>
52   */
53  public abstract class AbstractScmCommitPhase extends AbstractReleasePhase {
54      /**
55       * Tool that gets a configured SCM repository from release configuration.
56       */
57      protected final ScmRepositoryConfigurator scmRepositoryConfigurator;
58  
59      /**
60       * The getter in the descriptor for the comment.
61       */
62      protected final String descriptorCommentGetter;
63  
64      protected AbstractScmCommitPhase(
65              ScmRepositoryConfigurator scmRepositoryConfigurator, String descriptorCommentGetter) {
66          this.scmRepositoryConfigurator = requireNonNull(scmRepositoryConfigurator);
67          this.descriptorCommentGetter = requireNonNull(descriptorCommentGetter);
68      }
69  
70      @Override
71      public ReleaseResult execute(
72              ReleaseDescriptor releaseDescriptor,
73              ReleaseEnvironment releaseEnvironment,
74              List<MavenProject> reactorProjects)
75              throws ReleaseExecutionException, ReleaseFailureException {
76          ReleaseResult relResult = new ReleaseResult();
77  
78          validateConfiguration(releaseDescriptor);
79  
80          runLogic(releaseDescriptor, releaseEnvironment, reactorProjects, relResult, false);
81  
82          relResult.setResultCode(ReleaseResult.SUCCESS);
83  
84          return relResult;
85      }
86  
87      @Override
88      public ReleaseResult simulate(
89              ReleaseDescriptor releaseDescriptor,
90              ReleaseEnvironment releaseEnvironment,
91              List<MavenProject> reactorProjects)
92              throws ReleaseExecutionException, ReleaseFailureException {
93          ReleaseResult result = new ReleaseResult();
94  
95          validateConfiguration(releaseDescriptor);
96  
97          runLogic(releaseDescriptor, releaseEnvironment, reactorProjects, result, true);
98  
99          result.setResultCode(ReleaseResult.SUCCESS);
100         return result;
101     }
102 
103     /**
104      * <p>runLogic.</p>
105      *
106      * @param releaseDescriptor  a {@link org.apache.maven.shared.release.config.ReleaseDescriptor} object
107      * @param releaseEnvironment a {@link org.apache.maven.shared.release.env.ReleaseEnvironment} object
108      * @param reactorProjects    a {@link java.util.List} object
109      * @param result             a {@link org.apache.maven.shared.release.ReleaseResult} object
110      * @param simulating         a boolean
111      * @throws org.apache.maven.shared.release.scm.ReleaseScmCommandException    if any.
112      * @throws org.apache.maven.shared.release.ReleaseExecutionException         if any.
113      * @throws org.apache.maven.shared.release.scm.ReleaseScmRepositoryException if any.
114      */
115     protected abstract void runLogic(
116             ReleaseDescriptor releaseDescriptor,
117             ReleaseEnvironment releaseEnvironment,
118             List<MavenProject> reactorProjects,
119             ReleaseResult result,
120             boolean simulating)
121             throws ReleaseScmCommandException, ReleaseExecutionException, ReleaseScmRepositoryException;
122 
123     /**
124      * <p>performCheckins.</p>
125      *
126      * @param releaseDescriptor  a {@link org.apache.maven.shared.release.config.ReleaseDescriptor} object
127      * @param releaseEnvironment a {@link org.apache.maven.shared.release.env.ReleaseEnvironment} object
128      * @param reactorProjects    a {@link java.util.List} object
129      * @param message            a {@link java.lang.String} object
130      * @throws org.apache.maven.shared.release.scm.ReleaseScmRepositoryException if any.
131      * @throws org.apache.maven.shared.release.ReleaseExecutionException         if any.
132      * @throws org.apache.maven.shared.release.scm.ReleaseScmCommandException    if any.
133      */
134     protected void performCheckins(
135             ReleaseDescriptor releaseDescriptor,
136             ReleaseEnvironment releaseEnvironment,
137             List<MavenProject> reactorProjects,
138             String message)
139             throws ReleaseScmRepositoryException, ReleaseExecutionException, ReleaseScmCommandException {
140 
141         getLogger().info("Checking in modified POMs...");
142 
143         ScmRepository repository;
144         ScmProvider provider;
145         try {
146             repository = scmRepositoryConfigurator.getConfiguredRepository(
147                     releaseDescriptor, releaseEnvironment.getSettings());
148 
149             repository.getProviderRepository().setPushChanges(releaseDescriptor.isPushChanges());
150 
151             repository.getProviderRepository().setWorkItem(releaseDescriptor.getWorkItem());
152 
153             provider = scmRepositoryConfigurator.getRepositoryProvider(repository);
154         } catch (ScmRepositoryException e) {
155             throw new ReleaseScmRepositoryException(e.getMessage(), e.getValidationMessages());
156         } catch (NoSuchScmProviderException e) {
157             throw new ReleaseExecutionException("Unable to configure SCM repository: " + e.getMessage(), e);
158         }
159 
160         if (releaseDescriptor.isCommitByProject()) {
161             for (MavenProject project : reactorProjects) {
162                 List<File> pomFiles = createPomFiles(releaseDescriptor, project);
163                 ScmFileSet fileSet = new ScmFileSet(project.getFile().getParentFile(), pomFiles);
164 
165                 checkin(provider, repository, fileSet, releaseDescriptor, message);
166             }
167         } else {
168             List<File> pomFiles = createPomFiles(releaseDescriptor, reactorProjects);
169             ScmFileSet fileSet = new ScmFileSet(new File(releaseDescriptor.getWorkingDirectory()), pomFiles);
170 
171             checkin(provider, repository, fileSet, releaseDescriptor, message);
172         }
173     }
174 
175     private void checkin(
176             ScmProvider provider,
177             ScmRepository repository,
178             ScmFileSet fileSet,
179             ReleaseDescriptor releaseDescriptor,
180             String message)
181             throws ReleaseExecutionException, ReleaseScmCommandException {
182         CheckInScmResult result;
183         try {
184             result = provider.checkIn(repository, fileSet, (ScmVersion) null, message);
185         } catch (ScmException e) {
186             throw new ReleaseExecutionException("An error is occurred in the checkin process: " + e.getMessage(), e);
187         }
188 
189         if (!result.isSuccess()) {
190             throw new ReleaseScmCommandException("Unable to commit files", result);
191         }
192         if (releaseDescriptor.isRemoteTagging()) {
193             releaseDescriptor.setScmReleasedPomRevision(result.getScmRevision());
194         }
195     }
196 
197     /**
198      * <p>simulateCheckins.</p>
199      *
200      * @param releaseDescriptor a {@link org.apache.maven.shared.release.config.ReleaseDescriptor} object
201      * @param reactorProjects   a {@link java.util.List} object
202      * @param result            a {@link org.apache.maven.shared.release.ReleaseResult} object
203      * @param message           a {@link java.lang.String} object
204      */
205     protected void simulateCheckins(
206             ReleaseDescriptor releaseDescriptor,
207             List<MavenProject> reactorProjects,
208             ReleaseResult result,
209             String message) {
210         Collection<File> pomFiles = createPomFiles(releaseDescriptor, reactorProjects);
211         logInfo(result, "Full run would be commit " + pomFiles.size() + " files with message: '" + message + "'");
212     }
213 
214     /**
215      * <p>validateConfiguration.</p>
216      *
217      * @param releaseDescriptor a {@link org.apache.maven.shared.release.config.ReleaseDescriptor} object
218      * @throws org.apache.maven.shared.release.ReleaseFailureException if any.
219      */
220     protected void validateConfiguration(ReleaseDescriptor releaseDescriptor) throws ReleaseFailureException {
221         if (releaseDescriptor.getScmReleaseLabel() == null) {
222             throw new ReleaseFailureException("A release label is required for committing");
223         }
224     }
225 
226     /**
227      * <p>createMessage.</p>
228      *
229      * @param reactorProjects   a {@link java.util.List} object
230      * @param releaseDescriptor a {@link org.apache.maven.shared.release.config.ReleaseDescriptor} object
231      * @return a {@link java.lang.String} object
232      * @throws org.apache.maven.shared.release.ReleaseExecutionException if any.
233      */
234     protected String createMessage(List<MavenProject> reactorProjects, ReleaseDescriptor releaseDescriptor)
235             throws ReleaseExecutionException {
236         String comment;
237         boolean branch = false;
238         if ("getScmReleaseCommitComment".equals(descriptorCommentGetter)) {
239             comment = releaseDescriptor.getScmReleaseCommitComment();
240         } else if ("getScmDevelopmentCommitComment".equals(descriptorCommentGetter)) {
241             comment = releaseDescriptor.getScmDevelopmentCommitComment();
242         } else if ("getScmBranchCommitComment".equals(descriptorCommentGetter)) {
243             comment = releaseDescriptor.getScmBranchCommitComment();
244             branch = true;
245         } else if ("getScmRollbackCommitComment".equals(descriptorCommentGetter)) {
246             comment = releaseDescriptor.getScmRollbackCommitComment();
247         } else {
248             throw new ReleaseExecutionException(
249                     "Invalid configuration of descriptorCommentGetter='" + descriptorCommentGetter + "'");
250         }
251 
252         MavenProject project = ReleaseUtil.getRootProject(reactorProjects);
253         comment = comment.replace(
254                 "@{prefix}", releaseDescriptor.getScmCommentPrefix().trim());
255         comment = comment.replace("@{groupId}", project.getGroupId());
256         comment = comment.replace("@{artifactId}", project.getArtifactId());
257         if (branch) {
258             comment = comment.replace("@{branchName}", releaseDescriptor.getScmReleaseLabel());
259         } else {
260             comment = comment.replace("@{releaseLabel}", releaseDescriptor.getScmReleaseLabel());
261         }
262         return comment;
263     }
264 
265     /**
266      * <p>createPomFiles.</p>
267      *
268      * @param releaseDescriptor a {@link org.apache.maven.shared.release.config.ReleaseDescriptor} object
269      * @param project           a {@link org.apache.maven.project.MavenProject} object
270      * @return a {@link java.util.List} object
271      */
272     protected static List<File> createPomFiles(ReleaseDescriptor releaseDescriptor, MavenProject project) {
273         List<File> pomFiles = new ArrayList<>();
274 
275         pomFiles.add(ReleaseUtil.getStandardPom(project));
276 
277         if (releaseDescriptor.isGenerateReleasePoms() && !releaseDescriptor.isSuppressCommitBeforeTagOrBranch()) {
278             pomFiles.add(ReleaseUtil.getReleasePom(project));
279         }
280 
281         return pomFiles;
282     }
283 
284     /**
285      * <p>createPomFiles.</p>
286      *
287      * @param releaseDescriptor a {@link org.apache.maven.shared.release.config.ReleaseDescriptor} object
288      * @param reactorProjects   a {@link java.util.List} object
289      * @return a {@link java.util.List} object
290      */
291     protected static List<File> createPomFiles(
292             ReleaseDescriptor releaseDescriptor, List<MavenProject> reactorProjects) {
293         List<File> pomFiles = new ArrayList<>();
294         for (MavenProject project : reactorProjects) {
295             pomFiles.addAll(createPomFiles(releaseDescriptor, project));
296         }
297         return pomFiles;
298     }
299 }