package com.atlassian.jgitflow.core.command; import java.io.IOException; import com.atlassian.jgitflow.core.GitFlowConfiguration; import com.atlassian.jgitflow.core.JGitFlowConstants; import com.atlassian.jgitflow.core.exception.*; import com.atlassian.jgitflow.core.extension.BranchCreatingExtension; import com.atlassian.jgitflow.core.extension.JGitFlowExtension; import com.atlassian.jgitflow.core.util.GitHelper; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.util.StringUtils; public abstract class AbstractBranchCreatingCommand<C, T> extends AbstractGitFlowCommand<C, T> { private RevCommit startCommit; private String startCommitString; protected AbstractBranchCreatingCommand(String branchName, Git git, GitFlowConfiguration gfConfig) { super(branchName, git, gfConfig); this.startCommit = null; this.startCommitString = null; } protected Ref doCreateBranch(String rootBranch, String newBranchName, BranchCreatingExtension extension) throws JGitFlowExtensionException, JGitFlowIOException, LocalBranchMissingException, JGitFlowGitAPIException, BranchOutOfDateException, LocalBranchExistsException, TagExistsException, GitAPIException { git.checkout().setName(rootBranch).call(); runExtensionCommands(extension.beforeCreateBranch()); RevCommit startPoint = getStartingPoint(rootBranch); RevCommit latest = GitHelper.getLatestCommit(git, rootBranch); reporter.debugText(getCommandName(), "startPoint is: " + startPoint); reporter.debugText(getCommandName(), "latestCommit is: " + latest.getName()); if (GitHelper.remoteBranchExists(git, rootBranch)) { enforcer().requireLocalBranchNotBehindRemote(rootBranch); } enforcer().requireCommitOnBranch(startPoint, rootBranch); enforcer().requireTagAbsent(gfConfig.getPrefixValue(JGitFlowConstants.PREFIXES.VERSIONTAG.configKey()) + getBranchName()); Ref newBranch = git.checkout() .setName(newBranchName) .setCreateBranch(true) .setStartPoint(startPoint) .call(); reporter.debugText(getCommandName(), "created branch: " + newBranchName); runExtensionCommands(extension.afterCreateBranch()); return newBranch; } protected void doPushNewBranchIfNeeded(JGitFlowExtension pushExtension, String branchToPush) throws GitAPIException, JGitFlowGitAPIException, JGitFlowExtensionException, RemoteBranchExistsException, IOException { if (isPush()) { enforcer().requireRemoteBranchAbsent(branchToPush); reporter.infoText(getCommandName(), "pushing new branch to origin: " + branchToPush); git.push().setRemote(Constants.DEFAULT_REMOTE_NAME).setRefSpecs(new RefSpec(gfConfig.getDevelop()), new RefSpec(branchToPush)).call(); reporter.debugText(getCommandName(), "push complete"); git.fetch().setRemote(Constants.DEFAULT_REMOTE_NAME).call(); //setup tracking StoredConfig config = git.getRepository().getConfig(); config.setString(ConfigConstants.CONFIG_BRANCH_SECTION, branchToPush, ConfigConstants.CONFIG_KEY_REMOTE, Constants.DEFAULT_REMOTE_NAME); config.setString(ConfigConstants.CONFIG_BRANCH_SECTION, branchToPush, ConfigConstants.CONFIG_KEY_MERGE, Constants.R_HEADS + branchToPush); config.save(); try { config.load(); } catch (ConfigInvalidException e) { throw new JGitFlowGitAPIException("unable to load config", e); } runExtensionCommands(pushExtension.afterPush()); } } protected RevCommit getStartingPoint(String fromBranch) throws JGitFlowIOException, LocalBranchMissingException { RevCommit startPoint = null; if (null != startCommit) { startPoint = startCommit; } else if (!StringUtils.isEmptyOrNull(startCommitString)) { startPoint = GitHelper.getCommitForString(git, startCommitString); } else { startPoint = GitHelper.getLatestCommit(git, fromBranch); } return startPoint; } public C setStartCommit(String commitId) { this.startCommitString = commitId; return (C) this; } public C setStartCommit(RevCommit commit) { this.startCommit = commit; return (C) this; } }