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.branch;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.util.ArrayList;
24  import java.util.List;
25  
26  import org.apache.commons.lang3.StringUtils;
27  import org.apache.maven.scm.ScmBranch;
28  import org.apache.maven.scm.ScmBranchParameters;
29  import org.apache.maven.scm.ScmException;
30  import org.apache.maven.scm.ScmFile;
31  import org.apache.maven.scm.ScmFileSet;
32  import org.apache.maven.scm.ScmFileStatus;
33  import org.apache.maven.scm.ScmResult;
34  import org.apache.maven.scm.command.branch.AbstractBranchCommand;
35  import org.apache.maven.scm.command.branch.BranchScmResult;
36  import org.apache.maven.scm.provider.ScmProviderRepository;
37  import org.apache.maven.scm.provider.svn.SvnCommandUtils;
38  import org.apache.maven.scm.provider.svn.SvnTagBranchUtils;
39  import org.apache.maven.scm.provider.svn.command.SvnCommand;
40  import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository;
41  import org.apache.maven.scm.provider.svn.svnexe.command.SvnCommandLineUtils;
42  import org.codehaus.plexus.util.FileUtils;
43  import org.codehaus.plexus.util.Os;
44  import org.codehaus.plexus.util.cli.CommandLineException;
45  import org.codehaus.plexus.util.cli.CommandLineUtils;
46  import org.codehaus.plexus.util.cli.Commandline;
47  
48  /**
49   * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
50   * @author Olivier Lamy
51   *
52   * TODO since this is just a copy, use that instead.
53   */
54  public class SvnBranchCommand extends AbstractBranchCommand implements SvnCommand {
55  
56      public ScmResult executeBranchCommand(
57              ScmProviderRepository repo, ScmFileSet fileSet, String branch, ScmBranchParameters scmBranchParameters)
58              throws ScmException {
59          if (branch == null || branch.trim().isEmpty()) {
60              throw new ScmException("branch name must be specified");
61          }
62  
63          if (!fileSet.getFileList().isEmpty()) {
64              throw new ScmException("This provider doesn't support branching subsets of a directory");
65          }
66  
67          SvnScmProviderRepository repository = (SvnScmProviderRepository) repo;
68  
69          File messageFile = FileUtils.createTempFile("maven-scm-", ".commit", null);
70  
71          try {
72              FileUtils.fileWrite(messageFile.getAbsolutePath(), "UTF-8", scmBranchParameters.getMessage());
73          } catch (IOException ex) {
74              return new BranchScmResult(
75                      null,
76                      "Error while making a temporary file for the commit message: " + ex.getMessage(),
77                      null,
78                      false);
79          }
80  
81          Commandline cl = createCommandLine(repository, fileSet.getBasedir(), branch, messageFile, scmBranchParameters);
82  
83          CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
84  
85          CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
86  
87          if (logger.isInfoEnabled()) {
88              logger.info("Executing: " + SvnCommandLineUtils.cryptPassword(cl));
89  
90              if (Os.isFamily(Os.FAMILY_WINDOWS)) {
91                  logger.info("Working directory: " + cl.getWorkingDirectory().getAbsolutePath());
92              }
93          }
94  
95          int exitCode;
96  
97          try {
98              exitCode = SvnCommandLineUtils.execute(cl, stdout, stderr);
99          } catch (CommandLineException ex) {
100             throw new ScmException("Error while executing command.", ex);
101         } finally {
102             try {
103                 FileUtils.forceDelete(messageFile);
104             } catch (IOException ex) {
105                 // ignore
106             }
107         }
108 
109         if (exitCode != 0) {
110             return new BranchScmResult(cl.toString(), "The svn branch command failed.", stderr.getOutput(), false);
111         }
112 
113         List<ScmFile> fileList = new ArrayList<>();
114 
115         List<File> files = null;
116 
117         try {
118             files = FileUtils.getFiles(fileSet.getBasedir(), "**", "**/.svn/**", false);
119         } catch (IOException e) {
120             throw new ScmException("Error while executing command.", e);
121         }
122 
123         for (File f : files) {
124             fileList.add(new ScmFile(f.getPath(), ScmFileStatus.TAGGED));
125         }
126 
127         return new BranchScmResult(cl.toString(), fileList);
128     }
129 
130     /** {@inheritDoc} */
131     public ScmResult executeBranchCommand(ScmProviderRepository repo, ScmFileSet fileSet, String branch, String message)
132             throws ScmException {
133         ScmBranchParameters scmBranchParameters = new ScmBranchParameters(message);
134         return executeBranchCommand(repo, fileSet, branch, scmBranchParameters);
135     }
136 
137     // ----------------------------------------------------------------------
138     //
139     // ----------------------------------------------------------------------
140 
141     public static Commandline createCommandLine(
142             SvnScmProviderRepository repository, File workingDirectory, String branch, File messageFile) {
143         ScmBranchParameters scmBranchParameters = new ScmBranchParameters();
144         scmBranchParameters.setRemoteBranching(false);
145         scmBranchParameters.setPinExternals(false);
146         return createCommandLine(repository, workingDirectory, branch, messageFile, scmBranchParameters);
147     }
148 
149     public static Commandline createCommandLine(
150             SvnScmProviderRepository repository,
151             File workingDirectory,
152             String branch,
153             File messageFile,
154             ScmBranchParameters scmBranchParameters) {
155         Commandline cl = SvnCommandLineUtils.getBaseSvnCommandLine(workingDirectory, repository);
156 
157         cl.createArg().setValue("copy");
158 
159         cl.createArg().setValue("--parents");
160 
161         cl.createArg().setValue("--file");
162 
163         cl.createArg().setValue(messageFile.getAbsolutePath());
164 
165         cl.createArg().setValue("--encoding");
166 
167         cl.createArg().setValue("UTF-8");
168 
169         if (scmBranchParameters != null && scmBranchParameters.isPinExternals()) {
170             cl.createArg().setValue("--pin-externals");
171         }
172 
173         if (scmBranchParameters != null && scmBranchParameters.isRemoteBranching()) {
174             if (StringUtils.isNotBlank(scmBranchParameters.getScmRevision())) {
175                 cl.createArg().setValue("--revision");
176                 cl.createArg().setValue(scmBranchParameters.getScmRevision());
177             }
178             String url = SvnCommandUtils.fixUrl(repository.getUrl(), repository.getUser());
179             cl.createArg().setValue(url + "@");
180         } else {
181             cl.createArg().setValue(".");
182         }
183         // Note: this currently assumes you have the branch base checked out too
184         String branchUrl = SvnTagBranchUtils.resolveBranchUrl(repository, new ScmBranch(branch));
185         branchUrl = SvnCommandUtils.fixUrl(branchUrl, repository.getUser());
186         cl.createArg().setValue(branchUrl + "@");
187 
188         return cl;
189     }
190 }