Package com.atlassian.jgitflow.core

Source Code of com.atlassian.jgitflow.core.FeatureFinishCommand

package com.atlassian.jgitflow.core;

import java.io.File;
import java.nio.charset.Charset;
import java.util.List;

import com.atlassian.jgitflow.core.exception.JGitFlowException;
import com.atlassian.jgitflow.core.exception.MergeConflictsNotResolvedException;
import com.atlassian.jgitflow.core.util.GitHelper;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.io.Files;

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.Ref;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.RefSpec;

import static com.google.common.base.Preconditions.checkState;

/**
* @since version
*/
public class FeatureFinishCommand extends AbstractGitFlowCommand<Void>
{
    private final String branchName;
    private boolean fetchDevelop;
    private boolean rebase;
    private boolean keepBranch;
    private boolean forceDeleteBranch;
    private boolean squash;

    public FeatureFinishCommand(String name, Git git, GitFlowConfiguration gfConfig)
    {
        super(git,gfConfig);

        checkState(!Strings.isNullOrEmpty(name));
        this.branchName = name;
        this.fetchDevelop = false;
        this.rebase = false;
        this.keepBranch = false;
        this.forceDeleteBranch = false;
        this.squash = false;
    }

    @Override
    public Void call() throws Exception
    {
        String prefixedBranchName = gfConfig.getPrefixValue(JGitFlowConstants.PREFIXES.FEATURE.configKey()) + branchName;
       
        requireGitFlowInitialized();
        requireLocalBranchExists(prefixedBranchName);
       
        //check to see if we're restoring from a merge conflict
        File flowDir = new File(git.getRepository().getDirectory(), JGitFlowConstants.GITFLOW_DIR);
        File mergeBase = new File(flowDir, JGitFlowConstants.MERGE_BASE);
       
        if(mergeBase.exists())
        {
            if(GitHelper.workingTreeIsClean(git))
            {
                //check to see if the merge was done
                String finishBase = Files.readFirstLine(mergeBase, Charset.forName("UTF-8"));
                if(GitHelper.isMergedInto(git, prefixedBranchName, finishBase))
                {
                    mergeBase.delete();
                    cleanupBranch(prefixedBranchName);
                    return null;
                }
                else
                {
                    mergeBase.delete();
                }
            }
            else
            {
                throw new MergeConflictsNotResolvedException("Merge conflicts are not resolved");
            }
        }
       
        //not restoring a merge, continue
        requireCleanWorkingTree();
       
        boolean remoteFeatureExists = GitHelper.remoteBranchExists(git,prefixedBranchName);

        //update from remote if needed
        if(remoteFeatureExists && fetchDevelop)
        {
            RefSpec branchSpec = new RefSpec("+" + Constants.R_HEADS + prefixedBranchName + ":" + Constants.R_REMOTES + "origin/" + prefixedBranchName);
            RefSpec developSpec = new RefSpec("+" + Constants.R_HEADS + gfConfig.getDevelop() + ":" + Constants.R_REMOTES + "origin/" + gfConfig.getDevelop());
            git.fetch().setRefSpecs(branchSpec).call();
            git.fetch().setRefSpecs(developSpec).call();
        }
       
        //make sure nothing is behind
        if(remoteFeatureExists)
        {
            requireLocalBranchNotBehindRemote(prefixedBranchName);
        }
       
        if(GitHelper.remoteBranchExists(git,gfConfig.getDevelop()))
        {
            requireLocalBranchNotBehindRemote(gfConfig.getDevelop());
        }
       
        if(rebase)
        {
            FeatureRebaseCommand rebaseCommand = new FeatureRebaseCommand(branchName,git,gfConfig);
            rebaseCommand.call();
        }
       
        //merge into base
        git.checkout().setName(gfConfig.getDevelop()).call();

        Ref featureBranch = GitHelper.getLocalBranch(git, prefixedBranchName);

        RevCommit developCommit = GitHelper.getLatestCommit(git,gfConfig.getDevelop());
        RevCommit featureCommit = GitHelper.getLatestCommit(git, prefixedBranchName);

        List<RevCommit> commitList = ImmutableList.copyOf(git.log().setMaxCount(2).addRange(developCommit,featureCommit).call());
       
        MergeResult mergeResult = null;
               
        if(commitList.size() < 2)
        {
            mergeResult = git.merge().setFastForward(MergeCommand.FastForwardMode.FF).include(featureBranch).call();
        }
        else
        {
            if(squash)
            {
                mergeResult = git.merge().setSquash(true).include(featureBranch).call();
                git.commit().call();
                this.forceDeleteBranch = true;
            }
            else
            {
                mergeResult = git.merge().setFastForward(MergeCommand.FastForwardMode.NO_FF).include(featureBranch).call();
            }
        }
       
        if(null == mergeResult || mergeResult.getMergeStatus().equals(MergeResult.MergeStatus.FAILED) || mergeResult.getMergeStatus().equals(MergeResult.MergeStatus.CONFLICTING))
        {
            Files.createParentDirs(mergeBase);
            Files.touch(mergeBase);
            Files.write(gfConfig.getDevelop(),mergeBase,Charset.forName("UTF-8"));
            throw new MergeConflictsNotResolvedException("merge conflicts exist, please resolve!");
        }

        cleanupBranch(prefixedBranchName);

        return null;
    }

    private void cleanupBranch(String branch) throws JGitFlowException, GitAPIException
    {
        requireLocalBranchExists(branch);
        requireCleanWorkingTree();
       
        //make sure we're on the develop branch
        git.checkout().setName(gfConfig.getDevelop()).call();
       
        //delete the branch
        if(fetchDevelop)
        {
            RefSpec spec = new RefSpec(":" + Constants.R_HEADS + branch);
            git.push().setRemote("origin").setRefSpecs(spec).call();
        }
       
        if(!keepBranch)
        {
            if(forceDeleteBranch)
            {
                git.branchDelete().setForce(true).setBranchNames(branch).call();
            }
            else
            {
                git.branchDelete().setForce(false).setBranchNames(branch).call();
            }
        }
    }
   
    public FeatureFinishCommand setFetchDevelop(boolean fetch)
    {
        this.fetchDevelop = fetch;
        return this;
    }

    public FeatureFinishCommand setRebase(boolean rebase)
    {
        this.rebase = rebase;
        return this;
    }

    public FeatureFinishCommand setKeepBranch(boolean keep)
    {
        this.keepBranch = keep;
        return this;
    }

    public FeatureFinishCommand setForceDeleteBranch(boolean force)
    {
        this.forceDeleteBranch = force;
        return this;
    }

    public FeatureFinishCommand setSquash(boolean squash)
    {
        this.squash = squash;
        return this;
    }
}
TOP

Related Classes of com.atlassian.jgitflow.core.FeatureFinishCommand

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.