001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.maven.scm.provider.git.gitexe.command.branch; 020 021import java.io.File; 022import java.util.Map; 023 024import org.apache.maven.scm.ScmException; 025import org.apache.maven.scm.ScmFileSet; 026import org.apache.maven.scm.ScmFileStatus; 027import org.apache.maven.scm.ScmResult; 028import org.apache.maven.scm.command.branch.AbstractBranchCommand; 029import org.apache.maven.scm.command.branch.BranchScmResult; 030import org.apache.maven.scm.provider.ScmProviderRepository; 031import org.apache.maven.scm.provider.git.command.GitCommand; 032import org.apache.maven.scm.provider.git.gitexe.command.GitCommandLineUtils; 033import org.apache.maven.scm.provider.git.gitexe.command.list.GitListCommand; 034import org.apache.maven.scm.provider.git.gitexe.command.list.GitListConsumer; 035import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository; 036import org.codehaus.plexus.util.cli.CommandLineUtils; 037import org.codehaus.plexus.util.cli.Commandline; 038 039/** 040 * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a> 041 */ 042public class GitBranchCommand extends AbstractBranchCommand implements GitCommand { 043 private final Map<String, String> environmentVariables; 044 045 public GitBranchCommand(Map<String, String> environmentVariables) { 046 this.environmentVariables = environmentVariables; 047 } 048 049 /** 050 * {@inheritDoc} 051 */ 052 public ScmResult executeBranchCommand(ScmProviderRepository repo, ScmFileSet fileSet, String branch, String message) 053 throws ScmException { 054 if (branch == null || branch.trim().isEmpty()) { 055 throw new ScmException("branch name must be specified"); 056 } 057 058 if (!fileSet.getFileList().isEmpty()) { 059 throw new ScmException("This provider doesn't support branching subsets of a directory"); 060 } 061 062 GitScmProviderRepository repository = (GitScmProviderRepository) repo; 063 064 Commandline cl = createCommandLine(repository, fileSet.getBasedir(), branch); 065 066 CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer(); 067 CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer(); 068 int exitCode; 069 070 exitCode = GitCommandLineUtils.execute(cl, stdout, stderr); 071 if (exitCode != 0) { 072 return new BranchScmResult(cl.toString(), "The git-branch command failed.", stderr.getOutput(), false); 073 } 074 075 if (repo.isPushChanges()) { 076 // and now push the branch to the upstream repository 077 Commandline clPush = createPushCommandLine(repository, fileSet, branch); 078 079 exitCode = GitCommandLineUtils.execute(clPush, stdout, stderr); 080 if (exitCode != 0) { 081 return new BranchScmResult( 082 clPush.toString(), "The git-push command failed.", stderr.getOutput(), false); 083 } 084 } 085 086 // as last action we search for the branched files 087 GitListConsumer listConsumer = new GitListConsumer(fileSet.getBasedir(), ScmFileStatus.TAGGED); 088 089 Commandline clList = GitListCommand.createCommandLine(repository, fileSet.getBasedir()); 090 091 exitCode = GitCommandLineUtils.execute(clList, listConsumer, stderr); 092 if (exitCode != 0) { 093 return new BranchScmResult( 094 clList.toString(), "The git-ls-files command failed.", stderr.getOutput(), false); 095 } 096 097 return new BranchScmResult(cl.toString(), listConsumer.getListedFiles()); 098 } 099 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}