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.IOException;
27  import java.nio.file.LinkOption;
28  import java.nio.file.Path;
29  import java.nio.file.Paths;
30  import java.util.Map;
31  
32  import org.apache.maven.artifact.ArtifactUtils;
33  import org.apache.maven.model.Model;
34  import org.apache.maven.model.Scm;
35  import org.apache.maven.project.MavenProject;
36  import org.apache.maven.scm.repository.ScmRepository;
37  import org.apache.maven.shared.release.ReleaseExecutionException;
38  import org.apache.maven.shared.release.ReleaseResult;
39  import org.apache.maven.shared.release.config.ReleaseDescriptor;
40  import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
41  import org.apache.maven.shared.release.scm.ScmTranslator;
42  import org.apache.maven.shared.release.transform.ModelETLFactory;
43  import org.apache.maven.shared.release.util.ReleaseUtil;
44  
45  /**
46   * Rewrite POMs for release.
47   *
48   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
49   */
50  @Singleton
51  @Named( "rewrite-poms-for-release" )
52  public class RewritePomsForReleasePhase
53          extends AbstractRewritePomsPhase
54  {
55      @Inject
56      public RewritePomsForReleasePhase(
57              ScmRepositoryConfigurator scmRepositoryConfigurator,
58              Map<String, ModelETLFactory> modelETLFactories,
59              Map<String, ScmTranslator> scmTranslators )
60      {
61          super( scmRepositoryConfigurator, modelETLFactories, scmTranslators );
62      }
63  
64      @Override
65      protected final String getPomSuffix()
66      {
67          return "tag";
68      }
69  
70      @Override
71      protected void transformScm( MavenProject project, Model modelTarget, ReleaseDescriptor releaseDescriptor,
72                                   String projectId, ScmRepository scmRepository, ReleaseResult result )
73              throws ReleaseExecutionException
74      {
75          // If SCM is null in original model, it is inherited, no mods needed
76          if ( project.getScm() != null )
77          {
78              Scm scmRoot = modelTarget.getScm();
79              if ( scmRoot != null )
80              {
81                  try
82                  {
83                      translateScm( project, releaseDescriptor, scmRoot, scmRepository, result );
84                  }
85                  catch ( IOException e )
86                  {
87                      throw new ReleaseExecutionException( e.getMessage(), e );
88                  }
89              }
90              else
91              {
92                  MavenProject parent = project.getParent();
93                  if ( parent != null )
94                  {
95                      // If the SCM element is not present, only add it if the parent was not mapped (ie, it's external to
96                      // the release process and so has not been modified, so the values will not be correct on the tag),
97                      String parentId = ArtifactUtils.versionlessKey( parent.getGroupId(), parent.getArtifactId() );
98                      if ( !releaseDescriptor.hasOriginalScmInfo( parentId ) )
99                      {
100                         // we need to add it, since it has changed from the inherited value
101                         Scm scmTarget = new Scm();
102                         // reset default value (HEAD)
103                         scmTarget.setTag( null );
104 
105                         try
106                         {
107                             if ( translateScm( project, releaseDescriptor, scmTarget, scmRepository, result ) )
108                             {
109                                 modelTarget.setScm( scmTarget );
110                             }
111                         }
112                         catch ( IOException e )
113                         {
114                             throw new ReleaseExecutionException( e.getMessage(), e );
115                         }
116                     }
117                 }
118             }
119         }
120     }
121 
122     private boolean translateScm( MavenProject project, ReleaseDescriptor releaseDescriptor, Scm scmTarget,
123                                   ScmRepository scmRepository, ReleaseResult relResult )
124             throws IOException
125     {
126         ScmTranslator translator = getScmTranslators().get( scmRepository.getProvider() );
127         boolean result = false;
128         if ( translator != null )
129         {
130             Scm scm = project.getOriginalModel().getScm();
131             if ( scm == null )
132             {
133                 scm = project.getScm();
134             }
135 
136             String tag = releaseDescriptor.getScmReleaseLabel();
137             String tagBase = releaseDescriptor.getScmTagBase();
138 
139             // TODO: svn utils should take care of prepending this
140             if ( tagBase != null )
141             {
142                 tagBase = "scm:svn:" + tagBase;
143             }
144 
145             Path projectBasedir = project.getBasedir().toPath().toRealPath( LinkOption.NOFOLLOW_LINKS );
146             Path workingDirectory = Paths.get( releaseDescriptor.getWorkingDirectory() );
147 
148             int count = ReleaseUtil.getBaseWorkingDirectoryParentCount( workingDirectory, projectBasedir );
149 
150             if ( scm.getConnection() != null )
151             {
152                 String rootUrl = ReleaseUtil.realignScmUrl( count, scm.getConnection() );
153 
154                 String subDirectoryTag = scm.getConnection().substring( rootUrl.length() );
155                 if ( !subDirectoryTag.startsWith( "/" ) )
156                 {
157                     subDirectoryTag = "/" + subDirectoryTag;
158                 }
159 
160                 String scmConnectionTag = tagBase;
161                 if ( scmConnectionTag != null )
162                 {
163                     String trunkUrl = scm.getDeveloperConnection();
164                     if ( trunkUrl == null )
165                     {
166                         trunkUrl = scm.getConnection();
167                     }
168                     scmConnectionTag = translateUrlPath( trunkUrl, tagBase, scm.getConnection() );
169                 }
170                 String value =
171                         translator.translateTagUrl( scm.getConnection(), tag + subDirectoryTag, scmConnectionTag );
172 
173                 if ( !value.equals( scm.getConnection() ) )
174                 {
175                     scmTarget.setConnection( value );
176                     result = true;
177                 }
178             }
179 
180             if ( scm.getDeveloperConnection() != null )
181             {
182                 String rootUrl = ReleaseUtil.realignScmUrl( count, scm.getDeveloperConnection() );
183 
184                 String subDirectoryTag = scm.getDeveloperConnection().substring( rootUrl.length() );
185                 if ( !subDirectoryTag.startsWith( "/" ) )
186                 {
187                     subDirectoryTag = "/" + subDirectoryTag;
188                 }
189 
190                 String value =
191                         translator.translateTagUrl( scm.getDeveloperConnection(), tag + subDirectoryTag, tagBase );
192 
193                 if ( !value.equals( scm.getDeveloperConnection() ) )
194                 {
195                     scmTarget.setDeveloperConnection( value );
196                     result = true;
197                 }
198             }
199 
200             if ( scm.getUrl() != null )
201             {
202                 String rootUrl = ReleaseUtil.realignScmUrl( count, scm.getUrl() );
203 
204                 String subDirectoryTag = scm.getUrl().substring( rootUrl.length() );
205                 if ( !subDirectoryTag.startsWith( "/" ) )
206                 {
207                     subDirectoryTag = "/" + subDirectoryTag;
208                 }
209 
210                 String tagScmUrl = tagBase;
211                 if ( tagScmUrl != null )
212                 {
213                     String trunkUrl = scm.getDeveloperConnection();
214                     if ( trunkUrl == null )
215                     {
216                         trunkUrl = scm.getConnection();
217                     }
218                     tagScmUrl = translateUrlPath( trunkUrl, tagBase, scm.getUrl() );
219                 }
220                 // use original tag base without protocol
221                 String value = translator.translateTagUrl( scm.getUrl(), tag + subDirectoryTag, tagScmUrl );
222                 if ( !value.equals( scm.getUrl() ) )
223                 {
224                     scmTarget.setUrl( value );
225                     result = true;
226                 }
227             }
228 
229             if ( tag != null )
230             {
231                 String value = translator.resolveTag( tag );
232                 if ( value != null && !value.equals( scm.getTag() ) )
233                 {
234                     scmTarget.setTag( value );
235                     result = true;
236                 }
237             }
238         }
239         else
240         {
241             String message = "No SCM translator found - skipping rewrite";
242 
243             relResult.appendDebug( message );
244 
245             getLogger().debug( message );
246         }
247         return result;
248     }
249 
250     @Override
251     protected String getOriginalVersion( ReleaseDescriptor releaseDescriptor, String projectKey, boolean simulate )
252     {
253         return releaseDescriptor.getProjectOriginalVersion( projectKey );
254     }
255 
256     @Override
257     protected String getNextVersion( ReleaseDescriptor releaseDescriptor, String key )
258     {
259         return releaseDescriptor.getProjectReleaseVersion( key );
260     }
261 
262     @Override
263     protected String getResolvedSnapshotVersion( String artifactVersionlessKey,
264                                                  ReleaseDescriptor releaseDescriptor )
265     {
266         return releaseDescriptor.getDependencyReleaseVersion( artifactVersionlessKey );
267     }
268 }