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

io.github.svndump_to_git.git.utils.ExternalGitUtils Maven / Gradle / Ivy

The newest version!
/*
 *  Copyright 2014 The Kuali Foundation Licensed under the
 *	Educational Community License, Version 2.0 (the "License"); you may
 *	not use this file except in compliance with the License. You may
 *	obtain a copy of the License at
 *
 *	http://www.osedu.org/licenses/ECL-2.0
 *
 *	Unless required by applicable law or agreed to in writing,
 *	software distributed under the License is distributed on an "AS IS"
 *	BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 *	or implied. See the License for the specific language governing
 *	permissions and limitations under the License.
 */
package io.github.svndump_to_git.git.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.io.IOUtils;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.eclipse.jgit.transport.ReceiveCommand.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author ocleirig
 * 
 */
public final class ExternalGitUtils {

	private static final Logger log = LoggerFactory
			.getLogger(ExternalGitUtils.class);

	/**
	 * 
	 */
	private ExternalGitUtils() {
		// TODO Auto-generated constructor stub
	}

	/**
	 * Use CGit to fetch the specified remote name from the indicated repository.
	 * 
	 * @param externalCGitCommandPath path to C git binary
	 * @param repo git repository
	 * @param remoteName the name of the remote specified in the repositories git configuration file.
	 * @param depth  if < 1 then apply no limit if >e; 1 then specify with the --depth option for a shallow checkout.
	 * @param redirectStream output stream needed by waitFor
	 * 
	 * @return true if the fetch worked
	 */
	public static boolean fetch (String externalCGitCommandPath, Repository repo, String remoteName, int depth, OutputStream redirectStream) {

		try {
			
			ListcommandArgs = new ArrayList();
			
			commandArgs.add("fetch");
			commandArgs.add(remoteName);
			
			if (depth >= 1) {
				commandArgs.add("--depth=" + depth);
			}
			
			Process p = runGitCommand(externalCGitCommandPath, repo, true, commandArgs.toArray(new String[] {}));

			waitFor(p, redirectStream);

			return true;

		} catch (IOException e) {
			return false;
		} catch (InterruptedException e) {
			return false;
		}
	}
	
	public static boolean applyPatch (String externalGitCommandPath, Repository repo, InputStream patchStream, OutputStream redirectStream) {
		
		try {
			
			/*
			 * First read the patchStream into a temporary file
			 */
			
			File tempFile = File.createTempFile("patch", "dat");
			
			tempFile.deleteOnExit();
			
			int totalCopied = IOUtils.copy(patchStream, new FileOutputStream(tempFile));
			
			log.debug("copied " + totalCopied + " bytes into " + tempFile.getAbsolutePath());
			
			ListcommandArgs = new ArrayList();
			
			commandArgs.add("apply");
			commandArgs.add(tempFile.getAbsolutePath());
			
			Process p = runGitCommand(externalGitCommandPath, repo, false, commandArgs.toArray(new String[] {}));

			waitFor(p, redirectStream);

			return true;

		} catch (IOException e) {
			return false;
		} catch (InterruptedException e) {
			return false;
		}
		
	}
	/**
	 * Use CGit to fetch all of the remotes defined in the projects git configuration.
	 * 
	 * @param externalGitCommandPath
	 * @param repo
	 * @param depth if < 1 then apply no limit if >e; then specify with the --depth option for a shallow checkout.
	 * @param redirectStream
	 * 
	 * @return
	 */
	public static boolean fetchAll (String externalGitCommandPath, Repository repo, int depth, OutputStream redirectStream) {
		
		try {
			
			ListcommandArgs = new ArrayList();
			
			commandArgs.add("fetch");
			commandArgs.add("--all");
			
			if (depth >= 1) {
				commandArgs.add("--depth=" + depth);
			}
			
			Process p = runGitCommand(externalGitCommandPath, repo, true, commandArgs.toArray(new String[] {}));

			waitFor(p, redirectStream);

			return true;

		} catch (IOException e) {
			return false;
		} catch (InterruptedException e) {
			return false;
		}
		
	}
	
	/**
	 * Checkout the named branch using the branch name provided.
	 * 
	 * @param externalGitCommandPath
	 * @param repo
	 * @param branchName
	 * @param redirectStream
	 *            if not null then output from the sub process will be written
	 *            here.
	 * @return
	 */
	public static boolean checkoutBranch(String externalGitCommandPath,
			Repository repo, String branchName, boolean force,
			OutputStream redirectStream) {

		try {

			Process p = null;

			if (force) {
				p = runGitCommand(externalGitCommandPath, repo, false,
						"checkout", branchName, "--force");
			} else {
				p = runGitCommand(externalGitCommandPath, repo, false,
						"checkout", branchName);
			}

			int result = waitFor(p, redirectStream);

			if (result == 0)
				return true;
			else {
				readStream(p.getErrorStream(), redirectStream);
				return false;
			}

		} catch (IOException e) {
			log.error("failed to checkout branch", e);
			return false;
		} catch (InterruptedException e) {
			return false;
		}

	}

	// set inGitMetaDirectory to false to run in the working copy directory.
	private static Process runGitCommand(String externalGitCommandPath,
			Repository repo, boolean inGitMetaDirectory,
			String... gitCommandArgs) throws IOException {

		List commandArgs = new ArrayList<>();

		commandArgs.add(externalGitCommandPath);
		commandArgs.addAll(Arrays.asList(gitCommandArgs));

		return runGitCommand(repo, inGitMetaDirectory, commandArgs);

	}

	private static Process runGitCommand(Repository repo,
			boolean inGitMetaDirectory, List commandArgs)
			throws IOException {

		File gitDirectory = null;

		if (inGitMetaDirectory)
			gitDirectory = repo.getDirectory();
		else
			gitDirectory = repo.getWorkTree();

		// inherit the parent environment
		// locate in the working copy of the gir directory
		Process p = Runtime.getRuntime().exec(
				commandArgs.toArray(new String[] {}), null, gitDirectory);

		return p;
	}

	private static int waitFor(Process p, OutputStream redirectStream)
			throws InterruptedException, IOException {

		if (redirectStream != null) {

			readStream(p.getInputStream(), redirectStream);
		}

		return p.waitFor();

	}

	private static void readStream(InputStream inputStream,
			OutputStream redirectStream) throws IOException {

		BufferedReader outReader = new BufferedReader(new InputStreamReader(
				inputStream));

		while (true) {

			String errorLine = outReader.readLine();

			if (errorLine == null)
				break;

			redirectStream.write(errorLine.getBytes());
			redirectStream.write("\n".getBytes());

		}

	}

	public static boolean runGarbageCollection(String externalGitCommandPath,
			Repository repo, OutputStream redirectStream) {

		try {
			Process p = runGitCommand(externalGitCommandPath, repo, true, "gc");

			waitFor(p, redirectStream);

			return true;

		} catch (IOException e) {
			return false;
		} catch (InterruptedException e) {
			return false;
		}

	}

	public static boolean updateRef(String externalGitCommand, Repository repo,
			String absoluteRefName, ObjectId objectId, boolean force,
			OutputStream redirectStream) throws IOException {

		List commandOptions = new ArrayList<>();

		commandOptions.add("branch");

		if (force)
			commandOptions.add("-f");

		commandOptions.add(absoluteRefName);
		commandOptions.add(objectId.getName());

		try {
			Process p = runGitCommand(repo, true, commandOptions);

			waitFor(p, redirectStream);

			if (p.exitValue() == 0)
				return true;
			else
				return false;
		} catch (InterruptedException e) {
		}
		
		return false;
	}

	/**
	 * Run the batch ref updates using the external git command instead of the
	 * JGit command.
	 * 
	 * @param externalGitCommand
	 * @param repo
	 * @param deferredReferenceDeletes
	 * @param redirectStream
	 * @throws IOException
	 */
	public static void batchRefUpdate(String externalGitCommand,
			Repository repo, List deferredReferenceDeletes,
			OutputStream redirectStream) throws IOException {

		for (ReceiveCommand receiveCommand : deferredReferenceDeletes) {

			String[] parts = receiveCommand.getRefName().split("/");

			String refName = parts[parts.length - 1];

			ObjectId refObjectId = receiveCommand.getNewId();

			List commandOptions = new ArrayList<>();

			commandOptions.add(externalGitCommand);

			switch (receiveCommand.getType()) {

			case CREATE:
				commandOptions.add("branch");
				commandOptions.add(refName);
				commandOptions.add(refObjectId.getName());
				break;
			case DELETE:
				commandOptions.add("branch");
				commandOptions.add("-D");
				commandOptions.add(refName);
				break;
			case UPDATE:
			case UPDATE_NONFASTFORWARD:
				commandOptions.add("branch");
				commandOptions.add("-f");
				commandOptions.add(refName);
				commandOptions.add(refObjectId.getName());
				break;
			}

			try {
				Process p = runGitCommand(repo, true, commandOptions);

				waitFor(p, redirectStream);
				
				if (p.exitValue() == 0) {
					// normal termination
					
					if (receiveCommand.getType().equals(Type.CREATE)) {
						// C git doesn't say anything in this case so log it
						redirectStream.write(("Created branch " + receiveCommand.getRefName() + "\n").getBytes());
					}
					
				}
				
			} catch (InterruptedException e) {
			}

		}
	}
	
	/**
	 * Setup the Credential Helper to point at a file configured with the credentials.
	 * 

* Each line in the file is in the format of: https://user:[email protected] * * @param externalCGitCommand * @param tempFile * @throws IOException */ public static void setupLocalCredentialHelper(String externalCGitCommand, Repository repo, File tempFile) throws IOException { // assuming this is a non-bare repo runGitCommand(externalCGitCommand, repo, false, "config", "--local", "credential.helper", "store --file=" + tempFile.getAbsolutePath()); } /** * Remove any configured Credential Helper Section from the local git repository. * @param externalCGitCommand * @param repo * @throws IOException */ public static void cleanupLocalCredentialHelper(String externalCGitCommand, Repository repo) throws IOException { // assuming this is a non-bare repo runGitCommand(externalCGitCommand, repo, false, "config", "--local", "--remove-section", "credential"); } /** * Push the refspec given to the remote given. * * @param externalGitCommandPath * @param repo * @param refSpec * @param remoteName * @throws IOException */ public static void push (String externalGitCommandPath, Repository repo, String refSpec, String remoteName) throws IOException { runGitCommand(externalGitCommandPath, repo, false, "push", remoteName, refSpec); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy