From da901c49688ef72858cd2b6904e0f8e478fa0ec3 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 8 Nov 2011 12:49:16 -0800 Subject: [PATCH] Support a configured credentials provider in LsRemoteCommand Refactored the three common transport configuration options: credentials provider, timeout, and transport config callback into a new TransportCommand base class which is now extended by all commands that use a Transport object during execution. Bug: 349188 Change-Id: I90c2c14fb4e3cc4712905158f9047153a0c235c2 Signed-off-by: Kevin Sawicki Signed-off-by: Chris Aniszczyk --- .../org/eclipse/jgit/api/CloneCommand.java | 92 +++-------- .../org/eclipse/jgit/api/FetchCommand.java | 53 +----- .../org/eclipse/jgit/api/LsRemoteCommand.java | 4 +- .../src/org/eclipse/jgit/api/PullCommand.java | 49 +----- .../src/org/eclipse/jgit/api/PushCommand.java | 55 +------ .../eclipse/jgit/api/TransportCommand.java | 155 ++++++++++++++++++ 6 files changed, 192 insertions(+), 216 deletions(-) create mode 100644 org.eclipse.jgit/src/org/eclipse/jgit/api/TransportCommand.java diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java index 281704fad..5c98e6a28 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java @@ -49,7 +49,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.concurrent.Callable; import org.eclipse.jgit.JGitText; import org.eclipse.jgit.api.errors.InvalidRemoteException; @@ -67,7 +66,6 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; -import org.eclipse.jgit.transport.CredentialsProvider; import org.eclipse.jgit.transport.FetchResult; import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.transport.RemoteConfig; @@ -80,7 +78,7 @@ * @see Git documentation about Clone */ -public class CloneCommand implements Callable { +public class CloneCommand extends TransportCommand { private String uri; @@ -94,17 +92,18 @@ public class CloneCommand implements Callable { private ProgressMonitor monitor = NullProgressMonitor.INSTANCE; - private CredentialsProvider credentialsProvider; - - private int timeout; - private boolean cloneAllBranches; private boolean noCheckout; private Collection branchesToClone; - private TransportConfigCallback transportConfigCallback; + /** + * Create clone command with no repository set + */ + public CloneCommand() { + super(null); + } /** * Executes the {@code Clone} command. @@ -142,12 +141,12 @@ private Repository init(URIish u) { return command.call().getRepository(); } - private FetchResult fetch(Repository repo, URIish u) + private FetchResult fetch(Repository clonedRepo, URIish u) throws URISyntaxException, JGitInternalException, InvalidRemoteException, IOException { // create the remote config and save it - RemoteConfig config = new RemoteConfig(repo.getConfig(), remote); + RemoteConfig config = new RemoteConfig(clonedRepo.getConfig(), remote); config.addURI(u); final String dst = bare ? Constants.R_HEADS : Constants.R_REMOTES @@ -157,19 +156,16 @@ private FetchResult fetch(Repository repo, URIish u) refSpec = refSpec.setSourceDestination(Constants.R_HEADS + "*", dst + "/*"); //$NON-NLS-1$ //$NON-NLS-2$ config.addFetchRefSpec(refSpec); - config.update(repo.getConfig()); + config.update(clonedRepo.getConfig()); - repo.getConfig().save(); + clonedRepo.getConfig().save(); // run the fetch command - FetchCommand command = new FetchCommand(repo); + FetchCommand command = new FetchCommand(clonedRepo); command.setRemote(remote); command.setProgressMonitor(monitor); command.setTagOpt(TagOpt.FETCH_TAGS); - command.setTimeout(timeout); - if (credentialsProvider != null) - command.setCredentialsProvider(credentialsProvider); - command.setTransportConfigCallback(transportConfigCallback); + configure(command); List specs = calculateRefSpecs(dst); command.setRefSpecs(specs); @@ -193,7 +189,7 @@ else if (branchesToClone != null return specs; } - private void checkout(Repository repo, FetchResult result) + private void checkout(Repository clonedRepo, FetchResult result) throws JGitInternalException, MissingObjectException, IncorrectObjectTypeException, IOException { @@ -208,22 +204,22 @@ private void checkout(Repository repo, FetchResult result) return; // throw exception? if (head.getName().startsWith(Constants.R_HEADS)) { - final RefUpdate newHead = repo.updateRef(Constants.HEAD); + final RefUpdate newHead = clonedRepo.updateRef(Constants.HEAD); newHead.disableRefLog(); newHead.link(head.getName()); - addMergeConfig(repo, head); + addMergeConfig(clonedRepo, head); } - final RevCommit commit = parseCommit(repo, head); + final RevCommit commit = parseCommit(clonedRepo, head); boolean detached = !head.getName().startsWith(Constants.R_HEADS); - RefUpdate u = repo.updateRef(Constants.HEAD, detached); + RefUpdate u = clonedRepo.updateRef(Constants.HEAD, detached); u.setNewObjectId(commit.getId()); u.forceUpdate(); if (!bare) { - DirCache dc = repo.lockDirCache(); - DirCacheCheckout co = new DirCacheCheckout(repo, dc, + DirCache dc = clonedRepo.lockDirCache(); + DirCacheCheckout co = new DirCacheCheckout(clonedRepo, dc, commit.getTree()); co.checkout(); } @@ -246,19 +242,20 @@ private Ref findBranchToCheckout(FetchResult result) { return foundBranch; } - private void addMergeConfig(Repository repo, Ref head) throws IOException { + private void addMergeConfig(Repository clonedRepo, Ref head) + throws IOException { String branchName = Repository.shortenRefName(head.getName()); - repo.getConfig().setString(ConfigConstants.CONFIG_BRANCH_SECTION, + clonedRepo.getConfig().setString(ConfigConstants.CONFIG_BRANCH_SECTION, branchName, ConfigConstants.CONFIG_KEY_REMOTE, remote); - repo.getConfig().setString(ConfigConstants.CONFIG_BRANCH_SECTION, + clonedRepo.getConfig().setString(ConfigConstants.CONFIG_BRANCH_SECTION, branchName, ConfigConstants.CONFIG_KEY_MERGE, head.getName()); - repo.getConfig().save(); + clonedRepo.getConfig().save(); } - private RevCommit parseCommit(final Repository repo, final Ref ref) + private RevCommit parseCommit(final Repository clonedRepo, final Ref ref) throws MissingObjectException, IncorrectObjectTypeException, IOException { - final RevWalk rw = new RevWalk(repo); + final RevWalk rw = new RevWalk(clonedRepo); final RevCommit commit; try { commit = rw.parseCommit(ref.getObjectId()); @@ -342,27 +339,6 @@ public CloneCommand setProgressMonitor(ProgressMonitor monitor) { return this; } - /** - * @param credentialsProvider - * the {@link CredentialsProvider} to use - * @return {@code this} - */ - public CloneCommand setCredentialsProvider( - CredentialsProvider credentialsProvider) { - this.credentialsProvider = credentialsProvider; - return this; - } - - /** - * @param timeout - * the timeout used for the fetch step - * @return {@code this} - */ - public CloneCommand setTimeout(int timeout) { - this.timeout = timeout; - return this; - } - /** * @param cloneAllBranches * true when all branches have to be fetched (indicates wildcard @@ -396,18 +372,4 @@ public CloneCommand setNoCheckout(boolean noCheckout) { this.noCheckout = noCheckout; return this; } - - /** - * @param transportConfigCallback - * if set, the callback will be invoked after the Transport has - * created, but before the Transport is used. The callback can - * use this opportunity to set additional type-specific - * configuration on the Transport instance. - * @return {@code this} - */ - public CloneCommand setTransportConfigCallback( - TransportConfigCallback transportConfigCallback) { - this.transportConfigCallback = transportConfigCallback; - return this; - } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java index 8fe9d59a2..3ed78ee23 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java @@ -57,7 +57,6 @@ import org.eclipse.jgit.lib.NullProgressMonitor; import org.eclipse.jgit.lib.ProgressMonitor; import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.transport.CredentialsProvider; import org.eclipse.jgit.transport.FetchResult; import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.transport.TagOpt; @@ -71,7 +70,7 @@ * @see Git documentation about Fetch */ -public class FetchCommand extends GitCommand { +public class FetchCommand extends TransportCommand { private String remote = Constants.DEFAULT_REMOTE_NAME; @@ -87,14 +86,8 @@ public class FetchCommand extends GitCommand { private boolean thin = Transport.DEFAULT_FETCH_THIN; - private int timeout; - - private CredentialsProvider credentialsProvider; - private TagOpt tagOption; - private TransportConfigCallback transportConfigCallback; - /** * @param repo */ @@ -127,15 +120,11 @@ public FetchResult call() throws JGitInternalException, try { transport.setCheckFetchedObjects(checkFetchedObjects); transport.setRemoveDeletedRefs(removeDeletedRefs); - transport.setTimeout(timeout); transport.setDryRun(dryRun); if (tagOption != null) transport.setTagOpt(tagOption); transport.setFetchThin(thin); - if (credentialsProvider != null) - transport.setCredentialsProvider(credentialsProvider); - if (transportConfigCallback != null) - transportConfigCallback.configure(transport); + configure(transport); FetchResult result = transport.fetch(monitor, refSpecs); return result; @@ -182,17 +171,6 @@ public String getRemote() { return remote; } - /** - * @param timeout - * the timeout used for the fetch operation - * @return {@code this} - */ - public FetchCommand setTimeout(int timeout) { - checkCallable(); - this.timeout = timeout; - return this; - } - /** * @return the timeout used for the fetch operation */ @@ -334,18 +312,6 @@ public FetchCommand setThin(boolean thin) { return this; } - /** - * @param credentialsProvider - * the {@link CredentialsProvider} to use - * @return {@code this} - */ - public FetchCommand setCredentialsProvider( - CredentialsProvider credentialsProvider) { - checkCallable(); - this.credentialsProvider = credentialsProvider; - return this; - } - /** * Sets the specification of annotated tag behavior during fetch * @@ -357,19 +323,4 @@ public FetchCommand setTagOpt(TagOpt tagOpt) { this.tagOption = tagOpt; return this; } - - /** - * @param transportConfigCallback - * if set, the callback will be invoked after the Transport has - * created, but before the Transport is used. The callback can - * use this opportunity to set additional type-specific - * configuration on the Transport instance. - * @return {@code this} - */ - public FetchCommand setTransportConfigCallback( - TransportConfigCallback transportConfigCallback) { - checkCallable(); - this.transportConfigCallback = transportConfigCallback; - return this; - } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/LsRemoteCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/LsRemoteCommand.java index 093d6cc1b..f15859614 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/LsRemoteCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/LsRemoteCommand.java @@ -68,7 +68,8 @@ * href="http://www.kernel.org/pub/software/scm/git/docs/git-ls-remote.html" * >Git documentation about ls-remote */ -public class LsRemoteCommand extends GitCommand> { +public class LsRemoteCommand extends + TransportCommand> { private String remote = Constants.DEFAULT_REMOTE_NAME; @@ -133,6 +134,7 @@ public Collection call() throws Exception { try { Transport transport = Transport.open(repo, remote); transport.setOptionUploadPack(uploadPack); + configure(transport); try { Collection refSpecs = new ArrayList(1); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java index 3e42da567..67f9832fb 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java @@ -70,7 +70,6 @@ import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.RepositoryState; -import org.eclipse.jgit.transport.CredentialsProvider; import org.eclipse.jgit.transport.FetchResult; /** @@ -79,17 +78,12 @@ * @see Git documentation about Pull */ -public class PullCommand extends GitCommand { - private int timeout = 0; +public class PullCommand extends TransportCommand { private final static String DOT = "."; private ProgressMonitor monitor = NullProgressMonitor.INSTANCE; - private CredentialsProvider credentialsProvider; - - private TransportConfigCallback transportConfigCallback; - /** * @param repo */ @@ -97,16 +91,6 @@ protected PullCommand(Repository repo) { super(repo); } - /** - * @param timeout - * in seconds - * @return this instance - */ - public PullCommand setTimeout(int timeout) { - this.timeout = timeout; - return this; - } - /** * @param monitor * a progress monitor @@ -117,33 +101,6 @@ public PullCommand setProgressMonitor(ProgressMonitor monitor) { return this; } - /** - * @param credentialsProvider - * the {@link CredentialsProvider} to use - * @return this instance - */ - public PullCommand setCredentialsProvider( - CredentialsProvider credentialsProvider) { - checkCallable(); - this.credentialsProvider = credentialsProvider; - return this; - } - - /** - * @param transportConfigCallback - * if set, the callback will be invoked after the Transport has - * created, but before the Transport is used. The callback can - * use this opportunity to set additional type-specific - * configuration on the Transport instance. - * @return {@code this} - */ - public PullCommand setTransportConfigCallback( - TransportConfigCallback transportConfigCallback) { - checkCallable(); - this.transportConfigCallback = transportConfigCallback; - return this; - } - /** * Executes the {@code Pull} command with all the options and parameters * collected by the setter methods (e.g. @@ -229,9 +186,7 @@ public PullResult call() throws WrongRepositoryStateException, FetchCommand fetch = new FetchCommand(repo); fetch.setRemote(remote); fetch.setProgressMonitor(monitor); - fetch.setTimeout(this.timeout); - fetch.setCredentialsProvider(credentialsProvider); - fetch.setTransportConfigCallback(transportConfigCallback); + configure(fetch); fetchRes = fetch.call(); } else { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java index a89e131ba..a7a057715 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java @@ -60,7 +60,6 @@ import org.eclipse.jgit.lib.ProgressMonitor; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.transport.CredentialsProvider; import org.eclipse.jgit.transport.PushResult; import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.transport.RemoteConfig; @@ -75,7 +74,8 @@ * @see Git documentation about Push */ -public class PushCommand extends GitCommand> { +public class PushCommand extends + TransportCommand> { private String remote = Constants.DEFAULT_REMOTE_NAME; @@ -91,12 +91,6 @@ public class PushCommand extends GitCommand> { private boolean thin = Transport.DEFAULT_PUSH_THIN; - private int timeout; - - private CredentialsProvider credentialsProvider; - - private TransportConfigCallback transportConfigCallback; - /** * @param repo */ @@ -145,16 +139,11 @@ public Iterable call() throws JGitInternalException, final List transports; transports = Transport.openAll(repo, remote, Transport.Operation.PUSH); for (final Transport transport : transports) { - if (0 <= timeout) - transport.setTimeout(timeout); transport.setPushThin(thin); if (receivePack != null) transport.setOptionReceivePack(receivePack); transport.setDryRun(dryRun); - if (credentialsProvider != null) - transport.setCredentialsProvider(credentialsProvider); - if (transportConfigCallback != null) - transportConfigCallback.configure(transport); + configure(transport); final Collection toPush = transport .findRemoteRefUpdatesFor(refSpecs); @@ -233,17 +222,6 @@ public String getReceivePack() { return receivePack; } - /** - * @param timeout - * the timeout used for the push operation - * @return {@code this} - */ - public PushCommand setTimeout(int timeout) { - checkCallable(); - this.timeout = timeout; - return this; - } - /** * @return the timeout used for the push operation */ @@ -423,31 +401,4 @@ public PushCommand setForce(boolean force) { this.force = force; return this; } - - /** - * @param credentialsProvider - * the {@link CredentialsProvider} to use - * @return {@code this} - */ - public PushCommand setCredentialsProvider( - CredentialsProvider credentialsProvider) { - checkCallable(); - this.credentialsProvider = credentialsProvider; - return this; - } - - /** - * @param transportConfigCallback - * if set, the callback will be invoked after the Transport has - * created, but before the Transport is used. The callback can - * use this opportunity to set additional type-specific - * configuration on the Transport instance. - * @return {@code this} - */ - public PushCommand setTransportConfigCallback( - TransportConfigCallback transportConfigCallback) { - checkCallable(); - this.transportConfigCallback = transportConfigCallback; - return this; - } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/TransportCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/TransportCommand.java new file mode 100644 index 000000000..1aeb6109e --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/TransportCommand.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2011, GitHub Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.api; + +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.transport.CredentialsProvider; +import org.eclipse.jgit.transport.Transport; + +/** + * Base class for commands that use a {@link Transport} during execution. + *

+ * This class provides standard configuration of a transport for options such as + * a {@link CredentialsProvider}, a timeout, and a + * {@link TransportConfigCallback}. + * + * @param + * @param + */ +public abstract class TransportCommand extends + GitCommand { + + /** + * Configured credentials provider + */ + protected CredentialsProvider credentialsProvider; + + /** + * Configured transport timeout + */ + protected int timeout; + + /** + * Configured callback for transport configuration + */ + protected TransportConfigCallback transportConfigCallback; + + /** + * @param repo + */ + protected TransportCommand(final Repository repo) { + super(repo); + } + + /** + * @param credentialsProvider + * the {@link CredentialsProvider} to use + * @return {@code this} + */ + public C setCredentialsProvider( + final CredentialsProvider credentialsProvider) { + this.credentialsProvider = credentialsProvider; + return self(); + } + + /** + * @param timeout + * the timeout used for the transport step + * @return {@code this} + */ + public C setTimeout(int timeout) { + this.timeout = timeout; + return self(); + } + + /** + * @param transportConfigCallback + * if set, the callback will be invoked after the + * {@link Transport} has created, but before the + * {@link Transport} is used. The callback can use this + * opportunity to set additional type-specific configuration on + * the {@link Transport} instance. + * @return {@code this} + */ + public C setTransportConfigCallback( + final TransportConfigCallback transportConfigCallback) { + this.transportConfigCallback = transportConfigCallback; + return self(); + } + + /** @return {@code this} */ + @SuppressWarnings("unchecked") + protected final C self() { + return (C) this; + } + + /** + * Configure transport with credentials provider, timeout, and config + * callback + * + * @param transport + * @return {@code this} + */ + protected C configure(final Transport transport) { + if (credentialsProvider != null) + transport.setCredentialsProvider(credentialsProvider); + transport.setTimeout(timeout); + if (transportConfigCallback != null) + transportConfigCallback.configure(transport); + return self(); + } + + /** + * Configure a child command with the current configuration set in + * {@code this} command + * + * @param childCommand + * @return {@code this} + */ + protected C configure(final TransportCommand childCommand) { + childCommand.setCredentialsProvider(credentialsProvider); + childCommand.setTimeout(timeout); + childCommand.setTransportConfigCallback(transportConfigCallback); + return self(); + } +}