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