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.git.gitexe.command.branch;
20  
21  import java.io.File;
22  import java.util.Map;
23  
24  import org.apache.maven.scm.ScmException;
25  import org.apache.maven.scm.ScmFileSet;
26  import org.apache.maven.scm.ScmFileStatus;
27  import org.apache.maven.scm.ScmResult;
28  import org.apache.maven.scm.command.branch.AbstractBranchCommand;
29  import org.apache.maven.scm.command.branch.BranchScmResult;
30  import org.apache.maven.scm.provider.ScmProviderRepository;
31  import org.apache.maven.scm.provider.git.command.GitCommand;
32  import org.apache.maven.scm.provider.git.gitexe.command.GitCommandLineUtils;
33  import org.apache.maven.scm.provider.git.gitexe.command.list.GitListCommand;
34  import org.apache.maven.scm.provider.git.gitexe.command.list.GitListConsumer;
35  import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository;
36  import org.codehaus.plexus.util.cli.CommandLineUtils;
37  import org.codehaus.plexus.util.cli.Commandline;
38  
39  /**
40   * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
41   */
42  public class GitBranchCommand extends AbstractBranchCommand implements GitCommand {
43      private final Map<String, String> environmentVariables;
44  
45      public GitBranchCommand(Map<String, String> environmentVariables) {
46          this.environmentVariables = environmentVariables;
47      }
48  
49      /**
50       * {@inheritDoc}
51       */
52      public ScmResult executeBranchCommand(ScmProviderRepository repo, ScmFileSet fileSet, String branch, String message)
53              throws ScmException {
54          if (branch == null || branch.trim().isEmpty()) {
55              throw new ScmException("branch name must be specified");
56          }
57  
58          if (!fileSet.getFileList().isEmpty()) {
59              throw new ScmException("This provider doesn't support branching subsets of a directory");
60          }
61  
62          GitScmProviderRepository repository = (GitScmProviderRepository) repo;
63  
64          Commandline cl = createCommandLine(repository, fileSet.getBasedir(), branch);
65  
66          CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
67          CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
68          int exitCode;
69  
70          exitCode = GitCommandLineUtils.execute(cl, stdout, stderr);
71          if (exitCode != 0) {
72              return new BranchScmResult(cl.toString(), "The git-branch command failed.", stderr.getOutput(), false);
73          }
74  
75          if (repo.isPushChanges()) {
76              // and now push the branch to the upstream repository
77              Commandline clPush = createPushCommandLine(repository, fileSet, branch);
78  
79              exitCode = GitCommandLineUtils.execute(clPush, stdout, stderr);
80              if (exitCode != 0) {
81                  return new BranchScmResult(
82                          clPush.toString(), "The git-push command failed.", stderr.getOutput(), false);
83              }
84          }
85  
86          // as last action we search for the branched files
87          GitListConsumer listConsumer = new GitListConsumer(fileSet.getBasedir(), ScmFileStatus.TAGGED);
88  
89          Commandline clList = GitListCommand.createCommandLine(repository, fileSet.getBasedir());
90  
91          exitCode = GitCommandLineUtils.execute(clList, listConsumer, stderr);
92          if (exitCode != 0) {
93              return new BranchScmResult(
94                      clList.toString(), "The git-ls-files command failed.", stderr.getOutput(), false);
95          }
96  
97          return new BranchScmResult(cl.toString(), listConsumer.getListedFiles());
98      }
99  
100     // ----------------------------------------------------------------------
101     //
102     // ----------------------------------------------------------------------
103 
104     public static Commandline createCommandLine(
105             GitScmProviderRepository repository, File workingDirectory, String branch) {
106         Commandline cl = GitCommandLineUtils.getBaseGitCommandLine(workingDirectory, "branch");
107 
108         cl.createArg().setValue(branch);
109 
110         return cl;
111     }
112 
113     public Commandline createPushCommandLine(GitScmProviderRepository repository, ScmFileSet fileSet, String branch) {
114         Commandline cl = GitCommandLineUtils.getBaseGitCommandLine(
115                 fileSet.getBasedir(), "push", repository, environmentVariables);
116 
117         cl.createArg().setValue(repository.getPushUrl());
118         cl.createArg().setValue("refs/heads/" + branch);
119 
120         return cl;
121     }
122 
123     /**
124      * Helper function to detect the current branch.
125      */
126     public static String getCurrentBranch(GitScmProviderRepository repository, ScmFileSet fileSet) throws ScmException {
127         Commandline cl = GitCommandLineUtils.getBaseGitCommandLine(fileSet.getBasedir(), "symbolic-ref");
128         cl.createArg().setValue("HEAD");
129 
130         CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
131         GitCurrentBranchConsumer cbConsumer = new GitCurrentBranchConsumer();
132         int exitCode;
133 
134         exitCode = GitCommandLineUtils.execute(cl, cbConsumer, stderr);
135 
136         if (exitCode != 0) {
137             throw new ScmException("Detecting the current branch failed: " + stderr.getOutput());
138         }
139 
140         return cbConsumer.getBranchName();
141     }
142 }