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

com.codegik.gitflow.core.GitFlow Maven / Gradle / Ivy

There is a newer version: 1.3.1
Show newest version
package com.codegik.gitflow.core;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;

import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
import org.eclipse.jgit.api.CheckoutCommand.Stage;
import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ListBranchCommand.ListMode;
import org.eclipse.jgit.api.MergeResult;
import org.eclipse.jgit.api.ResetCommand.ResetType;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.merge.MergeStrategy;
import org.eclipse.jgit.revwalk.RevCommit;

import com.codegik.gitflow.command.CommandExecutor;
import com.codegik.gitflow.command.GitCommandExecutor;
import com.codegik.gitflow.core.impl.DefaultBranchType;


public abstract class GitFlow {
	private Git git;
	private Log log;
	private File repository;
	private CommandExecutor gitExecutor;
	private GitFlowPattern gitFlowPattern;
	

	public GitFlow(GitFlowPattern gitFlowPattern, Log log, File repository) {
		this.log 			= log;
		this.repository 	= repository;
		this.gitFlowPattern	= gitFlowPattern;
		this.gitExecutor	= new GitCommandExecutor(log);
	}


	public void setGit(Git git) {
		this.git = git;
	}

	public Git getGit() throws Exception {
		if (git == null) {
			git = Git.open(repository);
		}

		return git;
	}


	public String getBranch() throws Exception {
		return getGit().getRepository().getBranch();
	}


	public Ref tag(String tagName, String message) throws Exception {
		getLog().info("Tagging " + tagName);
		return getGit().tag().setName(tagName).setMessage(message).call();
	}


	public void merge(MergeGitFlow mergeGitFlow) throws Exception {
		merge(mergeGitFlow, null);
	}


	public void merge(MergeGitFlow mergeGitFlow, MergeStrategy mergeStrategy) throws Exception {
		getLog().info("Merging " + mergeGitFlow.getTargetRef().getName() + " into " + mergeGitFlow.getBranchName());

		MergeResult mergeResult = null;

		if (mergeStrategy == null) {
			mergeResult = getGit().merge().include(mergeGitFlow.getTargetRef()).call();
		} else {
			mergeResult = getGit().merge().setStrategy(mergeStrategy).include(mergeGitFlow.getTargetRef()).call();
		}

		if (!mergeResult.getMergeStatus().isSuccessful()) {
			processPreferentialConflicts(mergeGitFlow, mergeResult);
		}
	}


	private void processPreferentialConflicts(MergeGitFlow mergeGitFlow, MergeResult merge) throws Exception {
		List toRemove = new ArrayList();

		for (String key : merge.getConflicts().keySet()) {
			for (String file : mergeGitFlow.getIgnoringFiles()) {
				if (key.contains(file)) {
					checkoutFiles(mergeGitFlow.getBranchName(), key, mergeGitFlow.getIgnoringFilesStage());
					toRemove.add(key);
				}
			}
		}

		for (String key : toRemove) {
			merge.getConflicts().remove(key);
		}

		if (merge.getConflicts().size() > 0) {
			throw buildConflictExeption(mergeGitFlow, merge);
		}

		commit("Commiting resolved conflicts");
	}


	public String deleteRemoteBranch(Ref branchRef) throws Exception {
		String simpleName = getSimpleBranchName(branchRef);

		deleteLocalBranch(simpleName);

		return gitExecutor.execute("push", "origin", ":" + simpleName);
	}


	public String deleteRemoteBranch(String branchName) throws Exception {
		getLog().info("Deleting branch " + branchName);
		Ref branchRef = findBranch(branchName);

		if (branchRef == null) {
			throw new MojoExecutionException("Branch " + branchName + " not found");
		}

		return deleteRemoteBranch(branchRef);
	}


	public void deleteRemoteBranch(String version, BranchType branchType) throws Exception {
		getLog().info("Deleting " + branchType.toString() + " branch of release " + version);

		List deleted = new ArrayList();
		String release = branchType.toString() + gitFlowPattern.getGitSeparator() + version;

		for (Ref b : getGit().branchList().setListMode(ListMode.ALL).call()) {
			if (b.getName().contains(release) && !deleted.contains(getSimpleBranchName(b))) {
				deleteRemoteBranch(b);
				deleted.add(getSimpleBranchName(b));
			}
		}
	}


	public String deleteLocalBranch(String branchName) throws Exception {
		getLog().info("Deleting local branch " + branchName);

		if (getBranch().equals(branchName)) {
			throw new MojoExecutionException("Please change to another branch before delete");
		}

		if (findLocalBranch(branchName) != null) {
			return gitExecutor.execute("branch", "-D", branchName);
		}

		return null;
	}


	public String deleteTag(String tagName) throws Exception {
		return gitExecutor.execute("push", "origin", ":" + tagName);
	}


	public Ref reset(String branchName) throws Exception {
		getLog().info("Reseting into " + branchName);
		return getGit().reset().setMode(ResetType.HARD).setRef(branchName).call();
	}


	public Ref checkoutBranchForced(String branchName) throws Exception {
		getLog().info("Checkout forced into " + branchName);
		return getGit().checkout().setCreateBranch(false).setForce(true).setName(branchName).call();
	}


	public Ref checkoutBranch(String branchName) throws Exception {
		getLog().info("Checkout into " + branchName);
		Boolean branchExists = getGit().getRepository().getRef(branchName) != null;

		if (!branchExists) {
			getGit().branchCreate().setName(branchName).setUpstreamMode(SetupUpstreamMode.TRACK).setStartPoint("origin/" + branchName).call();
		}

		return getGit().checkout().setName(branchName).call();
	}


	public Ref checkoutFiles(String branchName, String file, Stage stage) throws Exception {
		getLog().info("Updating file " + file + " from branch " + branchName + " using " + stage.toString());
		Ref ref = getGit().checkout().addPath(file).setName(branchName).setCreateBranch(false).setStage(stage).call();
		getGit().add().addFilepattern(file).call();
		return ref;
	}


	public Ref createBranch(String branchName) throws Exception {
		getLog().info("Creating branch " + branchName);
		return getGit().checkout().setCreateBranch(true).setName(branchName).call();
	}


	public RevCommit commit(String message) throws Exception {
		getLog().info("Commiting... " + message);
		getGit().add().addFilepattern(".").call();
		return getGit().commit().setAll(true).setMessage(message).call();
	}


	public String pull() throws Exception {
		return gitExecutor.execute("pull");
	}


	public String pushBranch(String branchName) throws Exception {
		return gitExecutor.execute("push", "--set-upstream", "origin", branchName);
	}


	public String pushTag(Ref tag) throws Exception {
		getLog().info("Pushing Tag " + tag.getName());

		return gitExecutor.execute("push", "origin", getVersionFromTag(tag));
	}


	public String push() throws Exception {
		getLog().info("Pushing commit");

		return gitExecutor.execute("push");
	}


	private Ref findLocalBranch(String branch) throws Exception {
		getLog().info("Looking for local branch " + branch);

		for (Ref b : getGit().branchList().call()) {
			if (branch.equals(b.getName().toLowerCase().replace("refs/heads/", ""))) {
				return b;
			}
		}

		return null;
	}


	public Ref findBranch(String branch) throws Exception {
		getLog().info("Looking for branch " + branch);

		for (Ref b : getGit().branchList().setListMode(ListMode.REMOTE).call()) {
			if (branch.equals(getSimpleBranchName(b))) {
				return b;
			}
		}

		return null;
	}


	public MojoExecutionException buildConflictExeption(MergeGitFlow mergeGitFlow, MergeResult merge) {
		getLog().error("There is conflicts in the following files:");

		for (String key : merge.getConflicts().keySet()) {
			getLog().error(key);
		}

		String message = "\nThe merge has conflicts, please try resolve manually! [from " + mergeGitFlow.getTargetRef().getName() + " to " + mergeGitFlow.getBranchName() + "]";
		message += "\nExecute the steps:";
		message += "\ngit reset --hard " + mergeGitFlow.getBranchName();
		message += "\ngit checkout " + mergeGitFlow.getBranchName();
		message += "\ngit merge " + mergeGitFlow.getTargetRef().getName();
		message += "\nmvn gitflow:" + mergeGitFlow.getErrorMessage();

		return new MojoExecutionException(message);
	}


	public RevCommit revertCommit(RevCommit commit) throws Exception {
		getLog().info("Reverting commit");
		return getGit().revert().include(commit).setStrategy(MergeStrategy.OURS).call();
	}

	public String getSimpleBranchName(Ref ref) {
		return replaceAll(ref);
	}


	public String replaceAll(Ref ref) {
		String result = ref.getName();

		for (String replace : getGitFlowPattern().getPrefixToReplace()) {
			result = result.replace(replace, "");
		}

		return result;
	}


	public String getReleaseFromVersion(String fullVersion) {
		Matcher matcher = getGitFlowPattern().getTagVersionPattern().matcher(fullVersion);

		if (matcher.matches()) {
			return String.format("%s.%s", matcher.group(1), matcher.group(2));
		}

		return null;
	}


	public String getVersionFromTag(Ref tag) {
		return tag.getName().replace(getGitFlowPattern().getPrefixGitTag() + getGitFlowPattern().getGitSeparator(), "");
	}


	public String buildDevBranchName(String branchType, String version, String branchName) {
		return branchType + getGitFlowPattern().getGitSeparator() + version + getGitFlowPattern().getGitSeparator() + branchName;
	}


	public String buildReleaseBranchName(String version) {
		return getGitFlowPattern().getPrefixGitRelease() + getGitFlowPattern().getGitSeparator() + version;
	}


	public String buildHotfixBranchName(String version, String branchName) {
		return getGitFlowPattern().getPrefixGitHotfix() + getGitFlowPattern().getGitSeparator() + version + getGitFlowPattern().getGitSeparator() + branchName;
	}


	public String buildHotfixBranchName(String branchName) {
		return getGitFlowPattern().getPrefixGitHotfix() + getGitFlowPattern().getGitSeparator() + branchName;
	}


	public String buildRemoteBranchName(Ref ref) {
		return getGitFlowPattern().getPrefixGitHeads() + replaceAll(ref);
	}


	public List branchTypeToArray() {
		List values = new ArrayList();

		for (DefaultBranchType type : DefaultBranchType.values()) {
			values.add(type.name());
		}

		return values;
	}


	public Map validateFullBranchName(String branchName) throws Exception {
		String errorMessage 		= "The fullBranchName must be //. EX: feature/1.1.0/issue3456";
		String[] pattern 			= branchName.split("/");
		Map result 	= new HashMap();

		if (pattern.length != 3) {
			throw new MojoExecutionException(errorMessage);
		}

		if (!branchTypeToArray().contains(pattern[0])) {
			throw new MojoExecutionException(errorMessage);
		}

		result.put("branchType", pattern[0]);
		result.put("version", pattern[1]);
		result.put("branchName", pattern[2]);

		return result;
	}
	

	protected Log getLog() {
		return log;
	}

	
	public GitFlowPattern getGitFlowPattern() {
		return gitFlowPattern;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy