From 90b46a187170e4c736bb89de08ab718c61ec66b8 Mon Sep 17 00:00:00 2001 From: Randall Hauch Date: Tue, 9 Jul 2013 09:42:27 -0500 Subject: [PATCH] MODE-1990 Corrected Git connector's use of remote names The remote names are now properly parsed and collected, then used when resolving all branch names. If an empty list of names is provided, then local branch names will be used. Also changed the documentation and a parameter name of the Pageable and Connector interfaces (no semantic changes whatsoever). --- .../modeshape/connector/git/GitConnector.java | 13 ++++ .../modeshape/connector/git/GitFunction.java | 74 +++++++++++++++---- .../jcr/federation/spi/Connector.java | 7 +- .../jcr/federation/spi/Pageable.java | 6 +- 4 files changed, 79 insertions(+), 21 deletions(-) diff --git a/connectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/GitConnector.java b/connectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/GitConnector.java index 55b3ea4bdd..1746aab125 100644 --- a/connectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/GitConnector.java +++ b/connectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/GitConnector.java @@ -26,6 +26,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -119,6 +120,12 @@ public class GitConnector extends ReadOnlyConnector implements Pageable { */ private String remoteName = DEFAULT_REMOTE_NAME; + /** + * The optional string value representing the name of the remote that serves as the primary remote repository. By default this + * is "origin". This is set via reflection. + */ + private List parsedRemoteNames; + /** * The optional boolean value specifying whether the connector should set the "jcr:mimeType" property on the "jcr:content" * child node under each "git:file" node. By default this is '{@value GitConnector#DEFAULT_INCLUDE_MIME_TYPE}'. This is set @@ -170,10 +177,12 @@ public void initialize( NamespaceRegistry registry, // Make sure the remote exists ... Set remoteNames = repository.getConfig().getSubsections("remote"); + parsedRemoteNames = new ArrayList(); String remoteName = null; for (String desiredName : this.remoteName.split(",")) { if (remoteNames.contains(desiredName)) { remoteName = desiredName; + parsedRemoteNames.add(desiredName); break; } } @@ -305,6 +314,10 @@ protected final String remoteName() { return remoteName; } + protected final List remoteNames() { + return parsedRemoteNames; + } + protected List getQueryableBranches() { return queryableBranches; } diff --git a/connectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/GitFunction.java b/connectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/GitFunction.java index 577da8250e..f3f4c47426 100644 --- a/connectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/GitFunction.java +++ b/connectors/modeshape-connector-git/src/main/java/org/modeshape/connector/git/GitFunction.java @@ -26,7 +26,9 @@ import java.io.IOException; import java.util.Collections; import java.util.Comparator; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.ListBranchCommand; import org.eclipse.jgit.api.ListBranchCommand.ListMode; @@ -90,8 +92,16 @@ public abstract Document execute( Repository repository, DocumentWriter writer, Values values ) throws GitAPIException, IOException; - private String remoteBranchPrefix() { - String remoteName = connector.remoteName(); + private Set remoteBranchPrefixes() { + Set prefixes = new HashSet(); + for (String remoteName : connector.remoteNames()) { + String prefix = remoteBranchPrefix(remoteName); + prefixes.add(prefix); + } + return prefixes; + } + + private String remoteBranchPrefix( String remoteName ) { return REMOTE_BRANCH_PREFIX + remoteName + "/"; } @@ -102,7 +112,19 @@ private String remoteBranchPrefix() { * @return the branch ref name */ protected String branchRefForName( String branchName ) { - return remoteBranchPrefix() + branchName; + return remoteBranchPrefix(connector.remoteName()) + branchName; + } + + /** + * Obtain the name of the branch reference + * + * @param branchName + * @param remoteName the name of the remote + * @return the branch ref name + */ + protected String branchRefForName( String branchName, + String remoteName ) { + return remoteBranchPrefix(remoteName) + branchName; } /** @@ -118,8 +140,11 @@ protected ObjectId resolveBranchOrTagOrCommitId( Repository repository, String branchOrTagOrCommitId ) throws IOException { ObjectId objId = repository.resolve(branchOrTagOrCommitId); if (objId == null) { - String branchRef = branchRefForName(branchOrTagOrCommitId); - objId = repository.resolve(branchRef); + for (String remoteName : connector.remoteNames()) { + String branchRef = branchRefForName(branchOrTagOrCommitId, remoteName); + objId = repository.resolve(branchRef); + if (objId != null) break; + } } return objId; } @@ -135,24 +160,43 @@ protected ObjectId resolveBranchOrTagOrCommitId( Repository repository, protected void addBranchesAsChildren( Git git, CallSpecification spec, DocumentWriter writer ) throws GitAPIException { - // Generate the child references to the branches, which will be sorted by name (by the command). + Set remoteBranchPrefixes = remoteBranchPrefixes(); + if (remoteBranchPrefixes.isEmpty()) { + // Generate the child references to the LOCAL branches, which will be sorted by name ... + ListBranchCommand command = git.branchList(); + List branches = command.call(); + // Reverse the sort of the branch names, since they might be version numbers ... + Collections.sort(branches, REVERSE_REF_COMPARATOR); + for (Ref ref : branches) { + String name = ref.getName(); + writer.addChild(spec.childId(name), name); + } + return; + } + // There is at least one REMOTE branch, so generate the child references to the REMOTE branches, + // which will be sorted by name (by the command)... ListBranchCommand command = git.branchList(); command.setListMode(ListMode.REMOTE); - String remoteBranchPrefix = remoteBranchPrefix(); List branches = command.call(); // Reverse the sort of the branch names, since they might be version numbers ... Collections.sort(branches, REVERSE_REF_COMPARATOR); + Set uniqueNames = new HashSet(); for (Ref ref : branches) { String name = ref.getName(); - // We only want the branch if it matches the remote ... - if (name.startsWith(remoteBranchPrefix)) { - // Remove the prefix ... - name = name.replaceFirst(remoteBranchPrefix, ""); - } else { + if (uniqueNames.contains(name)) continue; + // We only want the branch if it matches one of the listed remotes ... + boolean skip = false; + for (String remoteBranchPrefix : remoteBranchPrefixes) { + if (name.startsWith(remoteBranchPrefix)) { + // Remove the prefix ... + name = name.replaceFirst(remoteBranchPrefix, ""); + break; + } // Otherwise, it's a remote branch from a different remote that we don't want ... - continue; + skip = true; } - writer.addChild(spec.childId(name), name); + if (skip) continue; + if (uniqueNames.add(name)) writer.addChild(spec.childId(name), name); } } @@ -259,7 +303,7 @@ protected void addCommitsAsPageOfChildren( Git git, } protected boolean isQueryable( CallSpecification callSpec ) { - //by default, a git function does not return queryable content + // by default, a git function does not return queryable content return false; } diff --git a/modeshape-jcr/src/main/java/org/modeshape/jcr/federation/spi/Connector.java b/modeshape-jcr/src/main/java/org/modeshape/jcr/federation/spi/Connector.java index 6e169a5518..dfb94f3768 100644 --- a/modeshape-jcr/src/main/java/org/modeshape/jcr/federation/spi/Connector.java +++ b/modeshape-jcr/src/main/java/org/modeshape/jcr/federation/spi/Connector.java @@ -323,12 +323,13 @@ public void shutdown() { public abstract Document getDocumentById( String id ); /** - * Returns the id of an external node located at the given path. + * Returns the id of an external node located at the given external path within the connector's exposed tree of content. * - * @param path a {@code non-null} string representing an exeternal path. + * @param externalPath a {@code non-null} string representing an external path, or "/" for the top-level node exposed by the + * connector * @return either the id of the document or {@code null} */ - public abstract String getDocumentId( String path ); + public abstract String getDocumentId( String externalPath ); /** * Return the path(s) of the external node with the given identifier. The resulting paths are from the point of view of the diff --git a/modeshape-jcr/src/main/java/org/modeshape/jcr/federation/spi/Pageable.java b/modeshape-jcr/src/main/java/org/modeshape/jcr/federation/spi/Pageable.java index be1496e48e..8e051847c7 100644 --- a/modeshape-jcr/src/main/java/org/modeshape/jcr/federation/spi/Pageable.java +++ b/modeshape-jcr/src/main/java/org/modeshape/jcr/federation/spi/Pageable.java @@ -27,9 +27,9 @@ import org.infinispan.schematic.document.Document; /** - * Marker interface that should be implemented by {@link org.modeshape.jcr.federation.spi.Connector}(s) that want to expose - * children of nodes in a "page by page" fashion. For effectively creating blocks of children for each page, connector - * implementations should use the {@link PageWriter} extension. + * Interface that should be implemented by {@link org.modeshape.jcr.federation.spi.Connector}(s) that want to expose children of + * nodes in a "page by page" fashion. For effectively creating blocks of children for each page, connector implementations should + * use the {@link PageWriter} extension. * * @author Horia Chiorean (hchiorea@redhat.com) */