View Javadoc
1   package org.apache.maven.shared.release.phase;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import javax.inject.Inject;
23  import javax.inject.Named;
24  import javax.inject.Singleton;
25  
26  import java.io.File;
27  import java.util.List;
28  
29  import org.apache.maven.project.MavenProject;
30  import org.apache.maven.scm.ScmException;
31  import org.apache.maven.scm.ScmFileSet;
32  import org.apache.maven.scm.ScmTagParameters;
33  import org.apache.maven.scm.command.tag.TagScmResult;
34  import org.apache.maven.scm.manager.NoSuchScmProviderException;
35  import org.apache.maven.scm.provider.ScmProvider;
36  import org.apache.maven.scm.repository.ScmRepository;
37  import org.apache.maven.scm.repository.ScmRepositoryException;
38  import org.apache.maven.shared.release.ReleaseExecutionException;
39  import org.apache.maven.shared.release.ReleaseFailureException;
40  import org.apache.maven.shared.release.ReleaseResult;
41  import org.apache.maven.shared.release.config.ReleaseDescriptor;
42  import org.apache.maven.shared.release.env.ReleaseEnvironment;
43  import org.apache.maven.shared.release.scm.ReleaseScmCommandException;
44  import org.apache.maven.shared.release.scm.ReleaseScmRepositoryException;
45  import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
46  import org.apache.maven.shared.release.util.ReleaseUtil;
47  
48  /**
49   * Tag the SCM repository after committing the release.
50   *
51   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
52   */
53  @Singleton
54  @Named( "scm-tag" )
55  public class ScmTagPhase
56      extends AbstractReleasePhase
57  {
58      /**
59       * Tool that gets a configured SCM repository from release configuration.
60       */
61      private final ScmRepositoryConfigurator scmRepositoryConfigurator;
62  
63      @Inject
64      public ScmTagPhase( ScmRepositoryConfigurator scmRepositoryConfigurator )
65      {
66          this.scmRepositoryConfigurator = scmRepositoryConfigurator;
67      }
68  
69      @Override
70      public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
71                                    List<MavenProject> reactorProjects )
72          throws ReleaseExecutionException, ReleaseFailureException
73      {
74          ReleaseResult relResult = new ReleaseResult();
75  
76          validateConfiguration( releaseDescriptor );
77  
78          if ( releaseDescriptor.getWaitBeforeTagging() > 0 )
79          {
80              logInfo( relResult, "Waiting for " + releaseDescriptor.getWaitBeforeTagging()
81                  + " seconds before tagging the release." );
82              try
83              {
84                  Thread.sleep( 1000L * releaseDescriptor.getWaitBeforeTagging() );
85              }
86              catch ( InterruptedException e )
87              {
88                  // Ignore
89              }
90          }
91  
92          logInfo( relResult, "Tagging release with the label " + releaseDescriptor.getScmReleaseLabel() + "..." );
93  
94          ReleaseDescriptor basedirAlignedReleaseDescriptor =
95              ReleaseUtil.createBasedirAlignedReleaseDescriptor( releaseDescriptor, reactorProjects );
96  
97          ScmRepository repository;
98          ScmProvider provider;
99          try
100         {
101             repository =
102                 scmRepositoryConfigurator.getConfiguredRepository( basedirAlignedReleaseDescriptor.getScmSourceUrl(),
103                                                                    releaseDescriptor,
104                                                                    releaseEnvironment.getSettings() );
105 
106             repository.getProviderRepository().setPushChanges( releaseDescriptor.isPushChanges() );
107 
108             repository.getProviderRepository().setWorkItem( releaseDescriptor.getWorkItem() );
109 
110             provider = scmRepositoryConfigurator.getRepositoryProvider( repository );
111         }
112         catch ( ScmRepositoryException e )
113         {
114             throw new ReleaseScmRepositoryException( e.getMessage(), e.getValidationMessages() );
115         }
116         catch ( NoSuchScmProviderException e )
117         {
118             throw new ReleaseExecutionException( "Unable to configure SCM repository: " + e.getMessage(), e );
119         }
120 
121         TagScmResult result;
122         try
123         {
124             // TODO: want includes/excludes?
125             ScmFileSet fileSet = new ScmFileSet( new File( basedirAlignedReleaseDescriptor.getWorkingDirectory() ) );
126             String tagName = releaseDescriptor.getScmReleaseLabel();
127             ScmTagParameters scmTagParameters =
128                 new ScmTagParameters( releaseDescriptor.getScmCommentPrefix() + "copy for tag " + tagName );
129             scmTagParameters.setRemoteTagging( releaseDescriptor.isRemoteTagging() );
130             scmTagParameters.setSign( releaseDescriptor.isScmSignTags() );
131             scmTagParameters.setScmRevision( releaseDescriptor.getScmReleasedPomRevision() );
132             scmTagParameters.setPinExternals( releaseDescriptor.isPinExternals() );
133             if ( getLogger().isDebugEnabled() )
134             {
135                 getLogger().debug(
136                     "ScmTagPhase :: scmTagParameters remotingTag " + releaseDescriptor.isRemoteTagging() );
137                 getLogger().debug(
138                     "ScmTagPhase :: scmTagParameters scmRevision " + releaseDescriptor.getScmReleasedPomRevision() );
139                 getLogger().debug(
140                         "ScmTagPhase :: scmTagParameters pinExternals " + releaseDescriptor.isPinExternals() );
141                 getLogger().debug( "ScmTagPhase :: fileSet  " + fileSet );
142             }
143             result = provider.tag( repository, fileSet, tagName, scmTagParameters );
144         }
145         catch ( ScmException e )
146         {
147             throw new ReleaseExecutionException( "An error is occurred in the tag process: " + e.getMessage(), e );
148         }
149 
150         if ( !result.isSuccess() )
151         {
152             throw new ReleaseScmCommandException( "Unable to tag SCM", result );
153         }
154 
155         relResult.setResultCode( ReleaseResult.SUCCESS );
156 
157         return relResult;
158     }
159 
160     @Override
161     public ReleaseResult simulate( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
162                                    List<MavenProject> reactorProjects )
163         throws ReleaseExecutionException, ReleaseFailureException
164     {
165         ReleaseResult result = new ReleaseResult();
166 
167         validateConfiguration( releaseDescriptor );
168 
169         ReleaseDescriptor basedirAlignedReleaseDescriptor =
170             ReleaseUtil.createBasedirAlignedReleaseDescriptor( releaseDescriptor, reactorProjects );
171 
172         if ( releaseDescriptor.isRemoteTagging() )
173         {
174             logInfo( result,
175                      "Full run would tag working copy '"
176                      + basedirAlignedReleaseDescriptor.getWorkingDirectory() + "'" );
177         }
178         else
179         {
180             logInfo( result, "Full run would tag remotely '"
181                      + basedirAlignedReleaseDescriptor.getScmSourceUrl() + "'" );
182         }
183         logInfo( result, "  with label '" + releaseDescriptor.getScmReleaseLabel() + "'" );
184         if ( releaseDescriptor.isPinExternals() )
185         {
186             logInfo( result, "  and pinned externals" );
187         }
188 
189         result.setResultCode( ReleaseResult.SUCCESS );
190 
191         return result;
192     }
193 
194     private static void validateConfiguration( ReleaseDescriptor releaseDescriptor )
195         throws ReleaseFailureException
196     {
197         if ( releaseDescriptor.getScmReleaseLabel() == null )
198         {
199             throw new ReleaseFailureException( "A release label is required for committing" );
200         }
201     }
202 }