From 3536943567a050cc911ab173b3f24afb583f54d6 Mon Sep 17 00:00:00 2001 From: Brian Long Date: Mon, 11 Jan 2021 09:50:59 -0500 Subject: [PATCH] massive refactoring of extended Git --- .../java/com/inteligr8/git/ExtendedGit.java | 139 +++++++++++------- 1 file changed, 85 insertions(+), 54 deletions(-) diff --git a/src/main/java/com/inteligr8/git/ExtendedGit.java b/src/main/java/com/inteligr8/git/ExtendedGit.java index 9e2f185..7804b8b 100644 --- a/src/main/java/com/inteligr8/git/ExtendedGit.java +++ b/src/main/java/com/inteligr8/git/ExtendedGit.java @@ -1,38 +1,35 @@ package com.inteligr8.git; import java.io.IOException; -import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.eclipse.jgit.api.CloneCommand; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.ListBranchCommand; -import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode; import org.eclipse.jgit.api.ListBranchCommand.ListMode; import org.eclipse.jgit.api.ResetCommand.ResetType; -import org.eclipse.jgit.api.errors.CheckoutConflictException; import org.eclipse.jgit.api.errors.GitAPIException; -import org.eclipse.jgit.api.errors.InvalidRefNameException; import org.eclipse.jgit.api.errors.InvalidRemoteException; -import org.eclipse.jgit.api.errors.RefAlreadyExistsException; -import org.eclipse.jgit.api.errors.RefNotFoundException; import org.eclipse.jgit.api.errors.TransportException; import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.transport.RemoteConfig; +import org.eclipse.jgit.transport.URIish; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ExtendedGit extends CachedGit { - private static final Pattern gitUrlPattern = Pattern.compile("(((ssh|http(s)?)://([^@]+@)?([^:/]+)(:[0-9]+)?/)|git@([^:]+):)([\\w\\.@\\:/\\-~]+)(\\.git)"); private final Logger logger = LoggerFactory.getLogger(ExtendedGit.class); public ExtendedGit(Git git) { @@ -47,67 +44,87 @@ public class ExtendedGit extends CachedGit { super(repo); } - public String getRepositoryFullyQualifiedName() throws GitAPIException, URISyntaxException { - String gitUrl = this.getFirstRemoteUrl(); - if (this.logger.isDebugEnabled()) - this.logger.debug("Remote URL: " + gitUrl); - return getRepositoryFullyQualifiedName(gitUrl); + public Collection findRemotesByHostname(String hostname) throws GitAPIException { + List matchingRemotes = new LinkedList<>(); + + List remotes = this.remoteList().call(); + for (RemoteConfig remote : remotes) { + for (URIish uri : remote.getURIs()) { + GitUrl url = new GitUrl(uri); + if (hostname.equalsIgnoreCase(url.getHostname())) { + matchingRemotes.add(remote); + break; + } + } + } + + return matchingRemotes; } - public static String getRepositoryFullyQualifiedName(String gitUrl) throws URISyntaxException { - Matcher matcher = gitUrlPattern.matcher(gitUrl); - if (!matcher.find()) - throw new URISyntaxException(gitUrl, "The Git URL does not match the expected regular expression: " + gitUrlPattern.toString()); - return matcher.group(9); + public Collection findRemoteNames(String branchName) throws IOException, GitAPIException { + List remoteNames = new LinkedList<>(); + + List remotes = this.remoteList().call(); + for (RemoteConfig remote : remotes) + if (this.getRepository().exactRef(Constants.R_REMOTES + remote.getName() + "/" + branchName) != null) + remoteNames.add(remote.getName()); + + return remoteNames; } - /** - * Creates a local branch, if one does not already exist. - * Checks out the repository, targeting the remote branch. - * Resets the local branch up to the remote branch. - */ - public Ref normalize(String localBranchName, String exactRemoteBranchName) - throws RefAlreadyExistsException, RefNotFoundException, InvalidRefNameException, CheckoutConflictException, GitAPIException, IOException { + public Collection findRemoteRefsByName(String branchName) throws IOException, GitAPIException { + List refs = new LinkedList<>(); + + List remotes = this.remoteList().call(); + for (RemoteConfig remote : remotes) { + Ref ref = this.getRepository().exactRef(Constants.R_REMOTES + remote.getName() + "/" + branchName); + if (ref != null) + refs.add(ref); + } + + return refs; + } + + public Ref resetAndCheckout(Ref ref) throws IOException, GitAPIException { + if (!ref.getName().startsWith(Constants.R_HEADS)) + throw new IllegalArgumentException("The '" + ref + "' is not a local ref"); + return this._resetAndCheckout(ref); + + } + + public Ref resetAndCheckout(String branchName) throws IOException, GitAPIException { if (this.logger.isTraceEnabled()) - this.logger.trace("normalize('" + localBranchName + "', '" + exactRemoteBranchName + "')"); + this.logger.trace("resetOrCheckout('" + branchName + "')"); - Ref localRef = this.getRepository().exactRef(Constants.R_HEADS + localBranchName); - if (localRef == null) { - if (this.logger.isDebugEnabled()) - this.logger.debug("normalize('" + localBranchName + "', '" + exactRemoteBranchName + "'): local branch does not yet exist"); - localRef = this.branchCreate() - .setUpstreamMode(SetupUpstreamMode.NOTRACK) - .setName(localBranchName) - .setStartPoint(exactRemoteBranchName) - .call(); - if (this.logger.isDebugEnabled()) - this.logger.debug("normalize('" + localBranchName + "', '" + exactRemoteBranchName + "'): created local branch: " + localRef.getName()); + Ref localRef = this.getRepository().exactRef(Constants.R_HEADS + branchName); + if (localRef == null) + throw new IllegalArgumentException("The '" + branchName + "' branch must already exist"); + return this._resetAndCheckout(localRef); + } + + private Ref _resetAndCheckout(Ref ref) throws IOException, GitAPIException { + Ref localRef = ref; + + if (!this.status().call().isClean()) { + if (this.logger.isTraceEnabled()) + this.logger.trace("resetOrCheckout('" + ref + "'): repo is dirty"); + localRef = this.reset().setMode(ResetType.HARD).call(); } - Ref checkoutRef = this.checkout() - .setName(localBranchName) - .setStartPoint(exactRemoteBranchName) - .call(); - if (this.logger.isDebugEnabled()) - this.logger.debug("normalize('" + localBranchName + "', '" + exactRemoteBranchName + "'): checked out"); - - if (!localRef.getObjectId().getName().equals(checkoutRef.getObjectId().getName())) { - this.logger.warn("A checkout did not move the local branch to the proper commit; performing reset: " + localRef.getName()); - this.reset() - .setMode(ResetType.HARD) - .setRef(exactRemoteBranchName) - .call(); - if (this.logger.isDebugEnabled()) - this.logger.debug("normalize('" + localBranchName + "', '" + exactRemoteBranchName + "'): reset"); + if (!this.getRepository().getFullBranch().equals(localRef.getName())) { + if (this.logger.isTraceEnabled()) + this.logger.trace("resetOrCheckout('" + ref + "'): repo is on a different branch"); + localRef = this.checkout().setName(localRef.getName()).call(); } - return checkoutRef; + return localRef; } /** * This method retrieves all branches, but excludes remote branches that are tracked with a local branch. * @return */ + @Deprecated public List getAllUniqueBranches() throws GitAPIException { return this.getAllUniqueBranches(null); } @@ -116,6 +133,7 @@ public class ExtendedGit extends CachedGit { * This method retrieves all branches, but excludes remote branches that are tracked with a local branch. * @return */ + @Deprecated public List getAllUniqueBranches(String containsCommitish) throws GitAPIException { if (this.logger.isTraceEnabled()) this.logger.trace("getAllUniqueBranches('" + containsCommitish + "')"); @@ -184,5 +202,18 @@ public class ExtendedGit extends CachedGit { return trimmedBranches; } + + @Deprecated + private boolean allSameCommit(Collection refs) { + if (refs.size() < 2) + return true; + + Iterator i = refs.iterator(); + ObjectId commit = i.next().getObjectId(); + while (i.hasNext()) + if (!commit.equals(i.next().getObjectId())) + return false; + return true; + } }