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

org.kuali.maven.plugins.fusion.FuseMojo Maven / Gradle / Ivy

/**
 * 
 */
package org.kuali.maven.plugins.fusion;

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Execute;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.eclipse.jgit.api.CheckoutCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.kuali.maven.plugins.fusion.util.GitFusionUtils;
import org.kuali.student.git.model.GitRepositoryUtils;
import org.kuali.student.git.model.ExternalModuleUtils;
import org.kuali.student.git.model.ref.utils.GitRefUtils;
import org.kuali.student.git.utils.ExternalGitUtils;
import org.kuali.student.svn.model.ExternalModuleInfo;

/**
 * @author ocleirig
 * 
 */
@Mojo(name = FusionMavenPluginConstants.FUSE_MOJO)
@Execute(goal = FusionMavenPluginConstants.FUSE_MOJO)
public class FuseMojo extends AbstractFusionMojo {

	
	/*
	 * The location of a text file that contains the fusion-maven-plugin.dat definitions
	 * 
	 */
	@Parameter (property=FusionMavenPluginConstants.PREFER_FUSION_DATA_FILE, defaultValue=FusionMavenPluginConstants.PREFER_FUSION_DATA_FILE_DEFAULT)
	protected String preferFusionDataFile;
	
	/*
	 * Resolve the fusion heads using the latest values for the branches named.
	 * 
	 */
	@Parameter (property=FusionMavenPluginConstants.FUSE_LATEST_BRANCH_HEADS, defaultValue=FusionMavenPluginConstants.FUSE_LATEST_BRANCH_HEADS_DEFAULT)
	protected String fuseLatestBranchHeads;
	
	/*
	 * The location of a text file that contains the fusion-maven-plugin.dat definitions
	 * 
	 */
	@Parameter (property=FusionMavenPluginConstants.FUSION_DATA_FILE, defaultValue=FusionMavenPluginConstants.FUSION_DATA_FILE_DEFAULT)
	protected File fusionDataFile;
	
	/*
	 * true or false and is used to determine if we should check out the newly
	 * created fused branch.
	 */
	@Parameter(property = FusionMavenPluginConstants.CHECKOUT_FUSED_BRANCH_PREFIX, defaultValue = FusionMavenPluginConstants.CHECKOUT_FUSED_BRANCH_PREFIX_DEFAULT)
	protected String checkoutFusedBranch;

	/**
	 * 
	 */
	public FuseMojo() {
		// TODO Auto-generated constructor stub
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.maven.plugin.Mojo#execute()
	 */
	@Override
	public void execute() throws MojoExecutionException, MojoFailureException {

		try {
			/*
			 * Assume that we are running on the aggregate and that the
			 * configuration will tell us how to fuse with our modules.
			 */

			File baseDir = project.getBasedir();

			/*
			 * Assume that the pom is located in the working copy of the git
			 * repository on the branch we want to fuse into
			 */

			Repository repo = GitRepositoryUtils.buildFileRepository(baseDir,
					false, false);
			
			ObjectReader objectReader = repo.newObjectReader();

			ObjectInserter objectInserter = repo.newObjectInserter();

			RevWalk rw = new RevWalk(repo);

			String currentBranchName = repo.getBranch();

			Ref currentHead = repo
					.getRef(Constants.R_HEADS + currentBranchName);

			RevCommit commit = rw.parseCommit(currentHead.getObjectId());

			List externals = new ArrayList<>();

			Set mergeParents = new HashSet<>();

			Set mergedModules = new HashSet<>();

			mergeParents.add(currentHead.getObjectId());

			if (nullSafePropertyValueCheck(this.preferFusionDataFile, "true") && this.fusionDataFile != null) {
				
				/*
				 * Could change this to look into the tree of the aggregate and if present then reconstitute using this file.
				 * 
				 * The flag would then become more of a use file if it exists instead of the mappings from the pom.xml
				 */
				
				FileInputStream inputStream;
				/*
				 * Source the externals from the file not the pom.
				 */
				externals.addAll(ExternalModuleUtils.extractFusionMavenPluginData(inputStream = new FileInputStream (this.fusionDataFile)));
				
				inputStream.close();
				
				for (ExternalModuleInfo external : externals) {
					
					ObjectId commitId = external.getBranchHeadId();
					
					if (nullSafePropertyValueCheck(this.fuseLatestBranchHeads, "true")) {
						// resolve using the latest branch version
						Ref ref = repo.getRef(external.getBranchName());
						
						if (ref == null) {
							
							ref = repo.getRef(getBranchName (external));
							
							if (ref == null)
								throw new MojoFailureException("For module: " + external.getModuleName() + "Can't resolve branch name: " + external.getBranchName());
						}
						
						ObjectId latestCommitId = ref.getObjectId();
						
						getLog().info("overriding " + commitId.name() + " with the latest commit on branch: " + external.getBranchName() + " with : " + latestCommitId.name());
						
						commitId = latestCommitId;
						
						external.setBranchHeadId(commitId);
						
						
					}
					
					mergeParents.add(commitId);
					
					mergedModules.add(external.getModuleName());
				}
				
			} else {

				if (mappings == null)
					throw new MojoFailureException("There are no mappings defined in the pom.xml file");
				
				for (Mapping mapping : mappings) {

					Ref branchHead = repo.getRef(getBranchName(mapping));

					if (branchHead == null) {
						
						objectReader.release();
						objectInserter.flush();
						rw.release();

						repo.close();
						
						throw new MojoFailureException(
								"Unable to find a branch head for : "
										+ mapping.getBranchName());
					}

					ObjectId headCommitId = branchHead.getObjectId();

					ExternalModuleInfo external = new ExternalModuleInfo(
							mapping.getModule(), mapping.getBranchName(), 
							headCommitId);

					externals.add(external);

					mergeParents.add(headCommitId);

					mergedModules.add(mapping.getModule());

				}
			}

			AnyObjectId fusedTree = ExternalModuleUtils.createFusedTree(
					objectReader, objectInserter, rw, commit, externals, true);

			/*
			 * Who should we commit as? and where should that be specified?
			 * 
			 * I think we might be able to use something like how the build
			 * number is set.
			 */

			ObjectId commitId = GitFusionUtils.commit(objectInserter, "jcaddel", "[email protected]", "Fused " + currentBranchName, fusedTree.toObjectId(), mergeParents);

			String fusedBranchName = "fused_" + currentBranchName;

			Ref branch = GitRefUtils.createOrUpdateBranch(repo,
					Constants.R_HEADS + fusedBranchName, commitId);

			if (branch == null)
				throw new MojoFailureException(
						"Unable to create fused branch: " + fusedBranchName);

			getLog().info(
					"created fused branch : " + fusedBranchName
							+ " from modules : "
							+ StringUtils.join(mergedModules.iterator(), ", "));

			if (this.checkoutFusedBranch != null
					&& this.checkoutFusedBranch.equals("true")) {

				if (this.externalCGitCommand != null) {
					// use C git
					if (!ExternalGitUtils.checkoutBranch(this.externalCGitCommand, repo, fusedBranchName, true, System.out)) {
						getLog().error("Failed to checkout " + fusedBranchName);
					}
				}
				else {
				
				CheckoutCommand checkOutCommand = new Git(repo).checkout();

				checkOutCommand.setName(fusedBranchName);
				checkOutCommand.setCreateBranch(false);
				checkOutCommand.setForce(true);

				Ref ref = checkOutCommand.call();

				if (ref == null)
					throw new MojoFailureException(
							"Unable to checkout fused branch: "
									+ fusedBranchName);

				getLog().info("checkedout fused branch : " + fusedBranchName);
				
				}
			}
			
			objectReader.release();
			objectInserter.flush();
			rw.release();

			repo.close();
			
		} catch (Exception e) {

			if (e instanceof MojoExecutionException)
				throw (MojoExecutionException) e;
			else if (e instanceof MojoFailureException)
				throw (MojoFailureException) e;
			else
				throw new MojoExecutionException(
						"FuseMojo failed unexpectantly: ", e);
		}

	}

	

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy