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.scm.provider.svn.svnexe.command.tag;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.util.ArrayList;
24  import java.util.Iterator;
25  import java.util.List;
26  
27  import org.apache.commons.lang3.StringUtils;
28  import org.apache.maven.scm.ScmException;
29  import org.apache.maven.scm.ScmFile;
30  import org.apache.maven.scm.ScmFileSet;
31  import org.apache.maven.scm.ScmFileStatus;
32  import org.apache.maven.scm.ScmResult;
33  import org.apache.maven.scm.ScmTag;
34  import org.apache.maven.scm.ScmTagParameters;
35  import org.apache.maven.scm.command.tag.AbstractTagCommand;
36  import org.apache.maven.scm.command.tag.TagScmResult;
37  import org.apache.maven.scm.provider.ScmProviderRepository;
38  import org.apache.maven.scm.provider.svn.SvnCommandUtils;
39  import org.apache.maven.scm.provider.svn.SvnTagBranchUtils;
40  import org.apache.maven.scm.provider.svn.command.SvnCommand;
41  import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository;
42  import org.apache.maven.scm.provider.svn.svnexe.command.SvnCommandLineUtils;
43  import org.codehaus.plexus.util.FileUtils;
44  import org.codehaus.plexus.util.Os;
45  import org.codehaus.plexus.util.cli.CommandLineException;
46  import org.codehaus.plexus.util.cli.CommandLineUtils;
47  import org.codehaus.plexus.util.cli.Commandline;
48  
49  /**
50   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
51   * @author Olivier Lamy
52   *
53   * TODO since this is just a copy, use that instead.
54   */
55  public class SvnTagCommand extends AbstractTagCommand implements SvnCommand {
56  
57      public ScmResult executeTagCommand(ScmProviderRepository repo, ScmFileSet fileSet, String tag, String message)
58              throws ScmException {
59          ScmTagParameters scmTagParameters = new ScmTagParameters(message);
60          // force false to preserve backward comp
61          scmTagParameters.setRemoteTagging(false);
62          scmTagParameters.setPinExternals(false);
63          return executeTagCommand(repo, fileSet, tag, scmTagParameters);
64      }
65  
66      /** {@inheritDoc} */
67      public ScmResult executeTagCommand(
68              ScmProviderRepository repo, ScmFileSet fileSet, String tag, ScmTagParameters scmTagParameters)
69              throws ScmException {
70          // NPE free
71          if (scmTagParameters == null) {
72              logger.debug("SvnTagCommand :: scmTagParameters is null create an empty one");
73              scmTagParameters = new ScmTagParameters();
74              scmTagParameters.setRemoteTagging(false);
75              scmTagParameters.setPinExternals(false);
76          } else {
77              logger.debug("SvnTagCommand :: scmTagParameters.remoteTagging : " + scmTagParameters.isRemoteTagging());
78          }
79          if (tag == null || StringUtils.isEmpty(tag.trim())) {
80              throw new ScmException("tag must be specified");
81          }
82  
83          if (!fileSet.getFileList().isEmpty()) {
84              throw new ScmException("This provider doesn't support tagging subsets of a directory");
85          }
86  
87          SvnScmProviderRepository repository = (SvnScmProviderRepository) repo;
88  
89          File messageFile = FileUtils.createTempFile("maven-scm-", ".commit", null);
90  
91          try {
92              FileUtils.fileWrite(messageFile.getAbsolutePath(), "UTF-8", scmTagParameters.getMessage());
93          } catch (IOException ex) {
94              return new TagScmResult(
95                      null,
96                      "Error while making a temporary file for the commit message: " + ex.getMessage(),
97                      null,
98                      false);
99          }
100 
101         Commandline cl = createCommandLine(repository, fileSet.getBasedir(), tag, messageFile, scmTagParameters);
102 
103         CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
104 
105         CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
106 
107         if (logger.isInfoEnabled()) {
108             logger.info("Executing: " + SvnCommandLineUtils.cryptPassword(cl));
109 
110             if (Os.isFamily(Os.FAMILY_WINDOWS)) {
111                 logger.info("Working directory: " + cl.getWorkingDirectory().getAbsolutePath());
112             }
113         }
114 
115         int exitCode;
116 
117         try {
118             exitCode = SvnCommandLineUtils.execute(cl, stdout, stderr);
119         } catch (CommandLineException ex) {
120             throw new ScmException("Error while executing command.", ex);
121         } finally {
122             try {
123                 FileUtils.forceDelete(messageFile);
124             } catch (IOException ex) {
125                 // ignore
126             }
127         }
128 
129         if (exitCode != 0) {
130             // TODO: Improve this error message
131             return new TagScmResult(cl.toString(), "The svn tag command failed.", stderr.getOutput(), false);
132         }
133 
134         List<ScmFile> fileList = new ArrayList<>();
135 
136         List<File> files = null;
137 
138         try {
139             if (StringUtils.isNotEmpty(fileSet.getExcludes())) {
140                 files = FileUtils.getFiles(
141                         fileSet.getBasedir(),
142                         (StringUtils.isEmpty(fileSet.getIncludes()) ? "**" : fileSet.getIncludes()),
143                         fileSet.getExcludes() + ",**/.svn/**",
144                         false);
145             } else {
146                 files = FileUtils.getFiles(
147                         fileSet.getBasedir(),
148                         (StringUtils.isEmpty(fileSet.getIncludes()) ? "**" : fileSet.getIncludes()),
149                         "**/.svn/**",
150                         false);
151             }
152         } catch (IOException e) {
153             throw new ScmException("Error while executing command.", e);
154         }
155 
156         for (Iterator<File> i = files.iterator(); i.hasNext(); ) {
157             File f = i.next();
158 
159             fileList.add(new ScmFile(f.getPath(), ScmFileStatus.TAGGED));
160         }
161 
162         return new TagScmResult(cl.toString(), fileList);
163     }
164 
165     // ----------------------------------------------------------------------
166     //
167     // ----------------------------------------------------------------------
168 
169     /**
170      * @deprecated
171      * @param repository
172      * @param workingDirectory
173      * @param tag
174      * @param messageFile
175      * @return TODO
176      */
177     public static Commandline createCommandLine(
178             SvnScmProviderRepository repository, File workingDirectory, String tag, File messageFile) {
179         Commandline cl = SvnCommandLineUtils.getBaseSvnCommandLine(workingDirectory, repository);
180 
181         cl.createArg().setValue("copy");
182 
183         cl.createArg().setValue("--parents");
184 
185         cl.createArg().setValue("--file");
186 
187         cl.createArg().setValue(messageFile.getAbsolutePath());
188 
189         cl.createArg().setValue(".");
190 
191         // Note: this currently assumes you have the tag base checked out too
192         String tagUrl = SvnTagBranchUtils.resolveTagUrl(repository, new ScmTag(tag));
193         tagUrl = SvnCommandUtils.fixUrl(tagUrl, repository.getUser());
194         cl.createArg().setValue(tagUrl + "@");
195 
196         return cl;
197     }
198 
199     public static Commandline createCommandLine(
200             SvnScmProviderRepository repository,
201             File workingDirectory,
202             String tag,
203             File messageFile,
204             ScmTagParameters scmTagParameters) {
205         Commandline cl = SvnCommandLineUtils.getBaseSvnCommandLine(workingDirectory, repository);
206 
207         cl.createArg().setValue("copy");
208 
209         cl.createArg().setValue("--file");
210 
211         cl.createArg().setValue(messageFile.getAbsolutePath());
212 
213         cl.createArg().setValue("--encoding");
214 
215         cl.createArg().setValue("UTF-8");
216 
217         cl.createArg().setValue("--parents");
218 
219         if (scmTagParameters != null && scmTagParameters.getScmRevision() != null) {
220             cl.createArg().setValue("--revision");
221 
222             cl.createArg().setValue(scmTagParameters.getScmRevision());
223         }
224 
225         if (scmTagParameters != null && scmTagParameters.isPinExternals()) {
226             cl.createArg().setValue("--pin-externals");
227         }
228 
229         if (scmTagParameters != null && scmTagParameters.isRemoteTagging()) {
230             String url = SvnCommandUtils.fixUrl(repository.getUrl(), repository.getUser());
231             cl.createArg().setValue(url + "@");
232         } else {
233             cl.createArg().setValue(".");
234         }
235 
236         // Note: this currently assumes you have the tag base checked out too
237         String tagUrl = SvnTagBranchUtils.resolveTagUrl(repository, new ScmTag(tag));
238         tagUrl = SvnCommandUtils.fixUrl(tagUrl, repository.getUser());
239         cl.createArg().setValue(tagUrl + "@");
240 
241         return cl;
242     }
243 }