All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.atlassian.jgitflow.core.HotfixFinishCommand Maven / Gradle / Ivy

The newest version!
package com.atlassian.jgitflow.core;

import com.atlassian.jgitflow.core.exception.*;
import com.atlassian.jgitflow.core.util.GitHelper;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.MergeCommand;
import org.eclipse.jgit.api.MergeResult;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.merge.MergeStrategy;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.util.StringUtils;

import static com.atlassian.jgitflow.core.util.Preconditions.checkState;

/**
 * Finish a hotfix.
 * 

* This will merge the hotfix into both master and develop and create a tag for the hotfix *

*

* Examples (flow is a {@link JGitFlow} instance): *

* Finish a hotfix: * *

 * flow.hotfixFinish("1.0").call();
 * 
*

* Don't delete the local hotfix branch * *

 * flow.hotfixFinish("1.0").setKeepBranch(true).call();
 * 
*

* Squash all commits on the hotfix branch into one before merging * *

 * flow.hotfixFinish("1.0").setSquash(true).call();
 * 
*

* Push changes to the remote origin * *

 * flow.hotfixFinish("1.0").setPush(true).call();
 * 
*

* Don't create a tag for the hotfix * *

 * flow.hotfixFinish("1.0").setNoTag(true).call();
 * 
*/ public class HotfixFinishCommand extends AbstractGitFlowCommand { private static final String SHORT_NAME = "hotfix-finish"; private final String hotfixName; private boolean fetch; private String message; private boolean push; private boolean keepBranch; private boolean noTag; /** * Create a new hotfix finish command instance. *

* An instance of this class is usually obtained by calling {@link JGitFlow#hotfixFinish(String)} * @param hotfixName The name/version of the hotfix * @param git The git instance to use * @param gfConfig The GitFlowConfiguration to use * @param reporter */ public HotfixFinishCommand(String hotfixName, Git git, GitFlowConfiguration gfConfig, JGitFlowReporter reporter) { super(git, gfConfig, reporter); checkState(!StringUtils.isEmptyOrNull(hotfixName)); this.hotfixName = hotfixName; this.fetch = false; this.message = "tagging hotfix " + hotfixName; this.push = false; this.keepBranch = false; this.noTag = false; } @Override public HotfixFinishCommand setAllowUntracked(boolean allow) { super.setAllowUntracked(allow); return this; } @Override public HotfixFinishCommand setScmMessagePrefix(String scmMessagePrefix) { super.setScmMessagePrefix(scmMessagePrefix); return this; } /** * * @return nothing * @throws JGitFlowGitAPIException * @throws LocalBranchMissingException * @throws DirtyWorkingTreeException * @throws JGitFlowIOException * @throws BranchOutOfDateException */ @Override public ReleaseMergeResult call() throws JGitFlowGitAPIException, LocalBranchMissingException, DirtyWorkingTreeException, JGitFlowIOException, BranchOutOfDateException { String prefixedHotfixName = gfConfig.getPrefixValue(JGitFlowConstants.PREFIXES.HOTFIX.configKey()) + hotfixName; requireLocalBranchExists(prefixedHotfixName); requireCleanWorkingTree(); MergeResult developResult = new MergeResult(null,null,new ObjectId[] { null, null }, MergeResult.MergeStatus.ALREADY_UP_TO_DATE, MergeStrategy.RESOLVE,null); MergeResult masterResult = new MergeResult(null,null,new ObjectId[] { null, null }, MergeResult.MergeStatus.ALREADY_UP_TO_DATE,MergeStrategy.RESOLVE,null); try { if (fetch) { RefSpec developSpec = new RefSpec("+" + Constants.R_HEADS + gfConfig.getDevelop() + ":" + Constants.R_REMOTES + "origin/" + gfConfig.getDevelop()); RefSpec masterSpec = new RefSpec("+" + Constants.R_HEADS + gfConfig.getMaster() + ":" + Constants.R_REMOTES + "origin/" + gfConfig.getMaster()); git.fetch().setRemote(Constants.DEFAULT_REMOTE_NAME).setRefSpecs(masterSpec).call(); git.fetch().setRemote(Constants.DEFAULT_REMOTE_NAME).setRefSpecs(developSpec).call(); git.fetch().setRemote(Constants.DEFAULT_REMOTE_NAME).call(); } if (GitHelper.remoteBranchExists(git, prefixedHotfixName, reporter)) { requireLocalBranchNotBehindRemote(prefixedHotfixName); } if (GitHelper.remoteBranchExists(git, gfConfig.getMaster(), reporter)) { requireLocalBranchNotBehindRemote(gfConfig.getMaster()); } if (GitHelper.remoteBranchExists(git, gfConfig.getDevelop(), reporter)) { requireLocalBranchNotBehindRemote(gfConfig.getDevelop()); } Ref hotfixBranch = GitHelper.getLocalBranch(git, prefixedHotfixName); RevCommit hotfixCommit = GitHelper.getLatestCommit(git, prefixedHotfixName); /* try to merge into master in case a previous attempt to finish this release branch has failed, but the merge into master was successful, we skip it now */ if (!GitHelper.isMergedInto(git, prefixedHotfixName, gfConfig.getMaster())) { git.checkout().setName(gfConfig.getMaster()).call(); masterResult = git.merge().setFastForward(MergeCommand.FastForwardMode.NO_FF).include(hotfixBranch).call(); } if (!noTag && masterResult.getMergeStatus().isSuccessful()) { /* try to tag the release in case a previous attempt to finish this release branch has failed, but the tag was successful, we skip it now */ String tagName = gfConfig.getPrefixValue(JGitFlowConstants.PREFIXES.VERSIONTAG.configKey()) + hotfixName; if (!GitHelper.tagExists(git, tagName)) { reporter.infoText(getCommandName(), "tagging hotfix with name:" + tagName); git.tag().setName(tagName).setMessage(getScmMessagePrefix() + message).setObjectId(hotfixCommit).call(); } } /* try to merge into develop in case a previous attempt to finish this release branch has failed, but the merge into develop was successful, we skip it now */ if (!GitHelper.isMergedInto(git, prefixedHotfixName, gfConfig.getDevelop())) { git.checkout().setName(gfConfig.getDevelop()).call(); developResult = git.merge().setFastForward(MergeCommand.FastForwardMode.NO_FF).include(hotfixBranch).call(); } if (push && masterResult.getMergeStatus().isSuccessful() && developResult.getMergeStatus().isSuccessful()) { //push to develop RefSpec developSpec = new RefSpec(gfConfig.getDevelop()); git.push().setRemote(Constants.DEFAULT_REMOTE_NAME).setRefSpecs(developSpec).call(); //push to master RefSpec masterSpec = new RefSpec(gfConfig.getMaster()); git.push().setRemote(Constants.DEFAULT_REMOTE_NAME).setRefSpecs(masterSpec).call(); if (!noTag) { git.push().setRemote(Constants.DEFAULT_REMOTE_NAME).setPushTags().call(); } if (GitHelper.remoteBranchExists(git, prefixedHotfixName, reporter)) { RefSpec branchSpec = new RefSpec(prefixedHotfixName); git.push().setRemote(Constants.DEFAULT_REMOTE_NAME).setRefSpecs(branchSpec).call(); } } if (!keepBranch && masterResult.getMergeStatus().isSuccessful() && developResult.getMergeStatus().isSuccessful()) { git.checkout().setName(gfConfig.getDevelop()).call(); git.branchDelete().setForce(true).setBranchNames(prefixedHotfixName).call(); if (push && GitHelper.remoteBranchExists(git, prefixedHotfixName, reporter)) { RefSpec deleteSpec = new RefSpec(":" + Constants.R_HEADS + prefixedHotfixName); git.push().setRemote(Constants.DEFAULT_REMOTE_NAME).setRefSpecs(deleteSpec).call(); } } git.checkout().setName(gfConfig.getDevelop()).call(); } catch (GitAPIException e) { throw new JGitFlowGitAPIException(e); } return new ReleaseMergeResult(masterResult,developResult); } /** * Set whether to perform a git fetch of the remote branches before doing the merge * @param fetch * true to do the fetch, false(default) otherwise * @return {@code this} */ public HotfixFinishCommand setFetch(boolean fetch) { this.fetch = fetch; return this; } /** * Set the commit message for the tag creation * @param message * @return {@code this} */ public HotfixFinishCommand setMessage(String message) { this.message = message; return this; } /** * Set whether to push the changes to the remote repository * @param push * true to do the push, false(default) otherwise * @return {@code this} */ public HotfixFinishCommand setPush(boolean push) { this.push = push; return this; } /** * Set whether to keep the local release branch after the merge * @param keepBranch * true to keep the branch, false(default) otherwise * @return {@code this} */ public HotfixFinishCommand setKeepBranch(boolean keepBranch) { this.keepBranch = keepBranch; return this; } /** * Set whether to turn off tagging * @param noTag * true to turn off tagging, false(default) otherwise * @return {@code this} */ public HotfixFinishCommand setNoTag(boolean noTag) { this.noTag = noTag; return this; } @Override protected String getCommandName() { return SHORT_NAME; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy