Package com.atlassian.jgitflow.core

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

package com.atlassian.jgitflow.core;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.Callable;

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

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.revwalk.filter.RevFilter;

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

/**
* The base class for all JGitFlow commands.
* <p>
* Most commands should extend this class as it provides common helper methods
* and methods to ensure valid state.
* </p>
* @param <T> The return type of the call() method
*/
public abstract class AbstractGitFlowCommand<T> implements Callable<T>
{
    protected final Git git;
    protected final GitFlowConfiguration gfConfig;

    protected AbstractGitFlowCommand(Git git, GitFlowConfiguration gfConfig)
    {
        checkNotNull(git);
        checkNotNull(gfConfig);

        this.git = git;
        this.gfConfig = gfConfig;
    }

    /**
     * Requires that git flow has been initialized for the project represented by the internal {Git} instance
     * @throws NotInitializedException
     * @throws JGitFlowGitAPIException
     */
    protected void requireGitFlowInitialized() throws NotInitializedException, JGitFlowGitAPIException
    {
        if (!gfConfig.gitFlowIsInitialized())
        {
            throw new NotInitializedException("Git flow is not initialized in " + git.getRepository().getWorkTree().getPath());
        }
    }

    /**
     * Requires that a local branch with the given name does not yet exist
     * @param branch the name of the branch to test
     * @throws LocalBranchExistsException
     * @throws JGitFlowGitAPIException
     */
    protected void requireLocalBranchAbsent(String branch) throws LocalBranchExistsException, JGitFlowGitAPIException
    {
        if (GitHelper.localBranchExists(git, branch))
        {
            throw new LocalBranchExistsException("local branch '" + branch + "' already exists");
        }
    }

    /**
     * Requires that a local branch with the given name exists
     * @param branch The name of the branch to test
     * @throws LocalBranchMissingException
     * @throws JGitFlowGitAPIException
     */
    protected void requireLocalBranchExists(String branch) throws LocalBranchMissingException, JGitFlowGitAPIException
    {
        if (!GitHelper.localBranchExists(git, branch))
        {
            throw new LocalBranchMissingException("local branch " + branch + " does not exist");
        }
    }

    /**
     * Requires that a remote branch with the given name does not yet exist
     * @param branch The name of the branch to test
     * @throws RemoteBranchExistsException
     * @throws JGitFlowGitAPIException
     */
    protected void requireRemoteBranchAbsent(String branch) throws RemoteBranchExistsException, JGitFlowGitAPIException
    {
        if (GitHelper.remoteBranchExists(git, branch))
        {
            throw new RemoteBranchExistsException("remote branch '" + branch + "' already exists");
        }
    }

    /**
     * Requires that a remote branch with the given name exists
     * @param branch The name of the branch to test
     * @throws RemoteBranchMissingException
     * @throws JGitFlowGitAPIException
     */
    protected void requireRemoteBranchExists(String branch) throws RemoteBranchMissingException, JGitFlowGitAPIException
    {
        if (!GitHelper.remoteBranchExists(git, branch))
        {
            throw new RemoteBranchMissingException("remote branch " + branch + " does not exist");
        }
    }

    /**
     * Requires that a tag with the given name does not yet exist
     * @param name The name of the tag to test
     * @throws TagExistsException
     * @throws JGitFlowGitAPIException
     */
    protected void requireTagAbsent(String name) throws TagExistsException, JGitFlowGitAPIException
    {
        if (GitHelper.tagExists(git, name))
        {
            throw new TagExistsException("tag '" + name + "' already exists");
        }
    }

    /**
     * Requires that the local branch with the given name is not behind a remote brach with the same name
     * @param branch The name of the branch to test
     * @throws BranchOutOfDateException
     * @throws JGitFlowIOException
     */
    protected void requireLocalBranchNotBehindRemote(String branch) throws BranchOutOfDateException, JGitFlowIOException
    {
        final RevWalk walk = new RevWalk(git.getRepository());
        walk.setRetainBody(true);
        boolean behind = false;
        try
        {
            Ref remote = GitHelper.getRemoteBranch(git, branch);
            Ref local = GitHelper.getLocalBranch(git, branch);

            checkNotNull(remote);
            checkNotNull(local);

            ObjectId remoteId = git.getRepository().resolve(remote.getObjectId().getName());
            RevCommit remoteCommit = walk.parseCommit(remoteId);
            RevCommit localCommit = walk.parseCommit(local.getObjectId());

            if (!localCommit.equals(remoteCommit))
            {
                behind = true;
                walk.setRevFilter(RevFilter.MERGE_BASE);
                walk.markStart(localCommit);
                walk.markStart(remoteCommit);

                RevCommit base = walk.next();
                if (null != base)
                {
                    walk.parseBody(base);

                    //remote is behind
                    if (remoteCommit.equals(base))
                    {
                        behind = false;
                    }
                }
            }

        }
        catch (IOException e)
        {
            throw new JGitFlowIOException(e);
        }
        finally
        {
            walk.release();
        }

        if (behind)
        {
            throw new BranchOutOfDateException("local branch '" + branch + "' is behind the remote branch");
        }
    }

    /**
     * Requires that the local working tree has no un-committed changes
     * @throws DirtyWorkingTreeException
     * @throws JGitFlowIOException
     * @throws JGitFlowGitAPIException
     */
    protected void requireCleanWorkingTree() throws DirtyWorkingTreeException, JGitFlowIOException, JGitFlowGitAPIException
    {
        if (!GitHelper.workingTreeIsClean(git))
        {
            throw new DirtyWorkingTreeException("Working tree has uncommitted changes");
        }
    }

    /**
     * Requires that no release branches already exist
     * @throws ReleaseBranchExistsException
     * @throws JGitFlowGitAPIException
     */
    protected void requireNoExistingReleaseBranches() throws ReleaseBranchExistsException, JGitFlowGitAPIException
    {
        List<Ref> branches = GitHelper.listBranchesWithPrefix(git, JGitFlowConstants.PREFIXES.RELEASE.configKey());

        if (!branches.isEmpty())
        {
            throw new ReleaseBranchExistsException("a release branch [" + branches.get(0).getName() + "] already exists. Finish that first!");
        }
    }

    /**
     * Requires that no hotfix branches already exist
     * @throws HotfixBranchExistsException
     * @throws JGitFlowGitAPIException
     */
    protected void requireNoExistingHotfixBranches() throws HotfixBranchExistsException, JGitFlowGitAPIException
    {
        List<Ref> branches = GitHelper.listBranchesWithPrefix(git, JGitFlowConstants.PREFIXES.HOTFIX.configKey());

        if (!branches.isEmpty())
        {
            throw new HotfixBranchExistsException("a hotfix branch [" + branches.get(0).getName() + "] already exists. Finish that first!");
        }
    }

}
TOP

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

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.