001package org.apache.maven.scm.provider.git.jgit.command.branch; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import org.apache.maven.scm.ScmException; 023import org.apache.maven.scm.ScmFile; 024import org.apache.maven.scm.ScmFileSet; 025import org.apache.maven.scm.ScmFileStatus; 026import org.apache.maven.scm.ScmResult; 027import org.apache.maven.scm.command.branch.AbstractBranchCommand; 028import org.apache.maven.scm.command.branch.BranchScmResult; 029import org.apache.maven.scm.provider.ScmProviderRepository; 030import org.apache.maven.scm.provider.git.command.GitCommand; 031import org.apache.maven.scm.provider.git.jgit.command.JGitUtils; 032import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository; 033import org.codehaus.plexus.util.StringUtils; 034import org.eclipse.jgit.api.Git; 035import org.eclipse.jgit.api.errors.GitAPIException; 036import org.eclipse.jgit.lib.Constants; 037import org.eclipse.jgit.lib.Ref; 038import org.eclipse.jgit.lib.Repository; 039import org.eclipse.jgit.revwalk.RevCommit; 040import org.eclipse.jgit.revwalk.RevWalk; 041import org.eclipse.jgit.transport.RefSpec; 042import org.eclipse.jgit.treewalk.TreeWalk; 043 044import java.util.ArrayList; 045import java.util.HashSet; 046import java.util.Iterator; 047import java.util.List; 048import java.util.Set; 049 050/** 051 * @author Dominik Bartholdi (imod) 052 * @since 1.9 053 */ 054public class JGitBranchCommand 055 extends AbstractBranchCommand 056 implements GitCommand 057{ 058 059 /** 060 * {@inheritDoc} 061 */ 062 @Override 063 protected ScmResult executeBranchCommand( ScmProviderRepository repo, ScmFileSet fileSet, String branch, 064 String message ) 065 throws ScmException 066 { 067 if ( branch == null || StringUtils.isEmpty( branch.trim() ) ) 068 { 069 throw new ScmException( "branch name must be specified" ); 070 } 071 072 if ( !fileSet.getFileList().isEmpty() ) 073 { 074 throw new ScmException( "This provider doesn't support branching subsets of a directory" ); 075 } 076 077 Git git = null; 078 try 079 { 080 git = Git.open( fileSet.getBasedir() ); 081 Ref branchResult = git.branchCreate().setName( branch ).call(); 082 getLogger().info( "created [" + branchResult.getName() + "]" ); 083 084 if ( getLogger().isDebugEnabled() ) 085 { 086 for ( String branchName : getShortLocalBranchNames( git ) ) 087 { 088 getLogger().debug( "local branch available: " + branchName ); 089 } 090 } 091 092 if ( repo.isPushChanges() ) 093 { 094 getLogger().info( "push branch [" + branch + "] to remote..." ); 095 JGitUtils.push( getLogger(), git, (GitScmProviderRepository) repo, new RefSpec( Constants.R_HEADS 096 + branch ) ); 097 } 098 099 // search for the tagged files 100 final RevWalk revWalk = new RevWalk( git.getRepository() ); 101 RevCommit commit = revWalk.parseCommit( branchResult.getObjectId() ); 102 revWalk.release(); 103 104 final TreeWalk walk = new TreeWalk( git.getRepository() ); 105 walk.reset(); // drop the first empty tree, which we do not need here 106 walk.setRecursive( true ); 107 walk.addTree( commit.getTree() ); 108 109 List<ScmFile> files = new ArrayList<ScmFile>(); 110 while ( walk.next() ) 111 { 112 files.add( new ScmFile( walk.getPathString(), ScmFileStatus.CHECKED_OUT ) ); 113 } 114 walk.release(); 115 116 return new BranchScmResult( "JGit branch", files ); 117 118 } 119 catch ( Exception e ) 120 { 121 throw new ScmException( "JGit branch failed!", e ); 122 } 123 finally 124 { 125 JGitUtils.closeRepo( git ); 126 } 127 } 128 129 /** 130 * gets a set of names of the available branches in the given repo 131 * 132 * @param git the repo to list the branches for 133 * @return set of short branch names 134 * @throws GitAPIException 135 */ 136 public static Set<String> getShortLocalBranchNames( Git git ) 137 throws GitAPIException 138 { 139 Set<String> branches = new HashSet<String>(); 140 Iterator<Ref> iter = git.branchList().call().iterator(); 141 while ( iter.hasNext() ) 142 { 143 branches.add( Repository.shortenRefName( iter.next().getName() ) ); 144 } 145 return branches; 146 } 147}