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) */