diff --git a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java index 3ac118fe6b7f..3c7c0c76e03f 100644 --- a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java +++ b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java @@ -402,7 +402,7 @@ public class CloudGitDeploymentRuntime extends CloudDeploymentRuntime { protected void push(@NotNull CloudGitApplication application, @NotNull GitRepository repository, @NotNull String remote) throws ServerRuntimeException { GitCommandResult gitPushResult - = getGit().push(repository, remote, application.getGitUrl(), "master:master", createGitLineHandlerListener()); + = getGit().push(repository, remote, application.getGitUrl(), "master:master", false, createGitLineHandlerListener()); checkGitResult(gitPushResult); } diff --git a/plugins/git4idea/src/git4idea/actions/GitPull.java b/plugins/git4idea/src/git4idea/actions/GitPull.java index 3ed4c84e504d..93877f11c5f2 100644 --- a/plugins/git4idea/src/git4idea/actions/GitPull.java +++ b/plugins/git4idea/src/git4idea/actions/GitPull.java @@ -27,6 +27,7 @@ import git4idea.repo.GitRepository; import git4idea.repo.GitRepositoryManager; import org.jetbrains.annotations.NotNull; +import java.util.Collections; import java.util.List; public class GitPull extends GitMergeAction { @@ -49,17 +50,16 @@ public class GitPull extends GitMergeAction { GitRepository repository = repositoryManager.getRepositoryForRoot(dialog.gitRoot()); assert repository != null : "Repository can't be null for root " + dialog.gitRoot(); String remoteOrUrl = dialog.getRemote(); - - GitRemote remote = GitUtil.findRemoteByName(repository, remoteOrUrl); - final String url = (remote == null) ? remoteOrUrl : remote.getFirstUrl(); - if (url == null) { + if (remoteOrUrl == null) { return null; } + GitRemote remote = GitUtil.findRemoteByName(repository, remoteOrUrl); + final List urls = remote == null ? Collections.singletonList(remoteOrUrl) : remote.getUrls(); Computable handlerProvider = new Computable() { @Override public GitLineHandler compute() { - return dialog.makeHandler(url); + return dialog.makeHandler(urls); } }; return new DialogState(dialog.gitRoot(), GitBundle.message("pulling.title", dialog.getRemote()), handlerProvider); diff --git a/plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java b/plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java index 8aa308623dbd..2bec81e5ef3b 100644 --- a/plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java +++ b/plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java @@ -157,18 +157,12 @@ class GitDeleteRemoteBranchOperation extends GitBranchOperation { return GitCommandResult.error(error); } - String remoteUrl = remote.getFirstUrl(); - if (remoteUrl == null) { - LOG.warn("No urls are defined for remote: " + remote); - return GitCommandResult.error("There is no urls defined for remote " + remote.getName()); - } - return pushDeletionNatively(repository, remoteName, remoteUrl, branchName); + return pushDeletionNatively(repository, remote, branchName); } @NotNull - private GitCommandResult pushDeletionNatively(@NotNull GitRepository repository, @NotNull String remoteName, @NotNull String url, - @NotNull String branchName) { - return myGit.push(repository, remoteName, url,":" + branchName); + private GitCommandResult pushDeletionNatively(@NotNull GitRepository repository, @NotNull GitRemote remote, @NotNull String branchName) { + return myGit.push(repository, remote, ":" + branchName, false, false, null); } @Nullable diff --git a/plugins/git4idea/src/git4idea/commands/Git.java b/plugins/git4idea/src/git4idea/commands/Git.java index 836a6a7d8b79..58035e609e6a 100644 --- a/plugins/git4idea/src/git4idea/commands/Git.java +++ b/plugins/git4idea/src/git4idea/commands/Git.java @@ -20,8 +20,6 @@ import com.intellij.openapi.util.Computable; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import git4idea.GitCommit; -import git4idea.GitLocalBranch; -import git4idea.GitRemoteBranch; import git4idea.repo.GitRemote; import git4idea.repo.GitRepository; import git4idea.reset.GitResetMode; @@ -106,14 +104,10 @@ public interface Git { GitCommandResult push(@NotNull GitRepository repository, @NotNull String remote, @Nullable String url, @NotNull String spec, boolean updateTracking, @NotNull GitLineHandlerListener... listeners); - @NotNull - GitCommandResult push(@NotNull GitRepository repository, @NotNull String remote, @Nullable String url, @NotNull String spec, - @NotNull GitLineHandlerListener... listeners); - @NotNull GitCommandResult push(@NotNull GitRepository repository, - @NotNull GitLocalBranch source, - @NotNull GitRemoteBranch target, + @NotNull GitRemote remote, + @NotNull String spec, boolean force, boolean updateTracking, @Nullable String tagMode, @@ -143,8 +137,10 @@ public interface Git { List history(@NotNull GitRepository repository, @NotNull String range); @NotNull - GitCommandResult fetch(@NotNull GitRepository repository, @NotNull String url, @NotNull String remote, - @NotNull List listeners, String... params); + GitCommandResult fetch(@NotNull GitRepository repository, + @NotNull GitRemote remote, + @NotNull List listeners, + String... params); @NotNull GitCommandResult addRemote(@NotNull GitRepository repository, @NotNull String name, @NotNull String url); diff --git a/plugins/git4idea/src/git4idea/commands/GitHandler.java b/plugins/git4idea/src/git4idea/commands/GitHandler.java index 5bee0181b257..6b9e6f315663 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitHandler.java @@ -22,6 +22,7 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; @@ -36,6 +37,7 @@ import com.intellij.util.EnvironmentUtil; import com.intellij.util.EventDispatcher; import com.intellij.util.ObjectUtils; import com.intellij.util.Processor; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.io.URLUtil; import com.intellij.util.net.HttpConfigurable; import com.intellij.util.net.IdeaWideProxySelector; @@ -52,11 +54,14 @@ import org.jetbrains.git4idea.ssh.GitSSHHandler; import org.jetbrains.git4idea.ssh.GitXmlRpcSshService; import java.io.File; +import java.io.IOException; import java.io.OutputStream; import java.nio.charset.Charset; import java.util.*; import java.util.concurrent.LinkedBlockingQueue; +import static java.util.Collections.singletonList; + /** * A handler for git commands */ @@ -81,7 +86,8 @@ public abstract class GitHandler { private final File myWorkingDirectory; private boolean myEnvironmentCleanedUp = true; // the flag indicating that environment has been cleaned up, by default is true because there is nothing to clean - private int myHandlerNo; + private int mySshHandler; + private int myHttpHandler; private Processor myInputProcessor; // The processor for stdin // if true process might be cancelled @@ -110,7 +116,7 @@ public abstract class GitHandler { private long myStartTime; // git execution start timestamp private static final long LONG_TIME = 10 * 1000; - @Nullable private String myUrl; + @Nullable private Collection myUrls; private boolean myHttpAuthFailed; @@ -234,13 +240,16 @@ public abstract class GitHandler { return file; } - @SuppressWarnings("NullableProblems") public void setUrl(@NotNull String url) { - myUrl = url; + setUrls(singletonList(url)); + } + + public void setUrls(@NotNull Collection urls) { + myUrls = urls; } protected boolean isRemote() { - return myUrl != null; + return myUrls != null; } /** @@ -435,46 +444,12 @@ public abstract class GitHandler { } // setup environment - GitRemoteProtocol remoteProtocol = GitRemoteProtocol.fromUrl(myUrl); - if (remoteProtocol == GitRemoteProtocol.SSH && myProjectSettings.isIdeaSsh()) { - GitXmlRpcSshService ssh = ServiceManager.getService(GitXmlRpcSshService.class); - myEnv.put(GitSSHHandler.GIT_SSH_ENV, ssh.getScriptPath().getPath()); - myHandlerNo = ssh.registerHandler(new GitSSHGUIHandler(myProject)); - myEnvironmentCleanedUp = false; - myEnv.put(GitSSHHandler.SSH_HANDLER_ENV, Integer.toString(myHandlerNo)); - int port = ssh.getXmlRcpPort(); - myEnv.put(GitSSHHandler.SSH_PORT_ENV, Integer.toString(port)); - LOG.debug(String.format("handler=%s, port=%s", myHandlerNo, port)); - - final HttpConfigurable httpConfigurable = HttpConfigurable.getInstance(); - boolean useHttpProxy = httpConfigurable.USE_HTTP_PROXY && !isSshUrlExcluded(httpConfigurable, myUrl); - myEnv.put(GitSSHHandler.SSH_USE_PROXY_ENV, String.valueOf(useHttpProxy)); - - if (useHttpProxy) { - myEnv.put(GitSSHHandler.SSH_PROXY_HOST_ENV, StringUtil.notNullize(httpConfigurable.PROXY_HOST)); - myEnv.put(GitSSHHandler.SSH_PROXY_PORT_ENV, String.valueOf(httpConfigurable.PROXY_PORT)); - boolean proxyAuthentication = httpConfigurable.PROXY_AUTHENTICATION; - myEnv.put(GitSSHHandler.SSH_PROXY_AUTHENTICATION_ENV, String.valueOf(proxyAuthentication)); - - if (proxyAuthentication) { - myEnv.put(GitSSHHandler.SSH_PROXY_USER_ENV, StringUtil.notNullize(httpConfigurable.PROXY_LOGIN)); - myEnv.put(GitSSHHandler.SSH_PROXY_PASSWORD_ENV, StringUtil.notNullize(httpConfigurable.getPlainProxyPassword())); - } + if (isRemote()) { + setupHttpAuthenticator(); + if (myProjectSettings.isIdeaSsh()) { + setupSshAuthenticator(); } } - else if (remoteProtocol == GitRemoteProtocol.HTTP) { - GitHttpAuthService service = ServiceManager.getService(GitHttpAuthService.class); - myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_ENV, service.getScriptPath().getPath()); - assert myUrl != null : "myUrl can't be null here"; - GitHttpAuthenticator httpAuthenticator = service.createAuthenticator(myProject, myCommand, myUrl); - myHandlerNo = service.registerHandler(httpAuthenticator); - myEnvironmentCleanedUp = false; - myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_HANDLER_ENV, Integer.toString(myHandlerNo)); - int port = service.getXmlRcpPort(); - myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_PORT_ENV, Integer.toString(port)); - LOG.debug(String.format("handler=%s, port=%s", myHandlerNo, port)); - addAuthListener(httpAuthenticator); - } myCommandLine.getEnvironment().clear(); myCommandLine.getEnvironment().putAll(myEnv); // start process @@ -493,9 +468,54 @@ public abstract class GitHandler { } } - protected static boolean isSshUrlExcluded(@NotNull HttpConfigurable httpConfigurable, @NotNull String url) { - String host = URLUtil.parseHostFromSshUrl(url); - return ((IdeaWideProxySelector)httpConfigurable.getOnlyBySettingsSelector()).isProxyException(host); + private void setupHttpAuthenticator() throws IOException { + GitHttpAuthService service = ServiceManager.getService(GitHttpAuthService.class); + myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_ENV, service.getScriptPath().getPath()); + GitHttpAuthenticator httpAuthenticator = service.createAuthenticator(myProject, myCommand, ObjectUtils.assertNotNull(myUrls)); + myHttpHandler = service.registerHandler(httpAuthenticator); + myEnvironmentCleanedUp = false; + myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_HANDLER_ENV, Integer.toString(myHttpHandler)); + int port = service.getXmlRcpPort(); + myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_PORT_ENV, Integer.toString(port)); + LOG.debug(String.format("handler=%s, port=%s", myHttpHandler, port)); + addAuthListener(httpAuthenticator); + } + + private void setupSshAuthenticator() throws IOException { + GitXmlRpcSshService ssh = ServiceManager.getService(GitXmlRpcSshService.class); + myEnv.put(GitSSHHandler.GIT_SSH_ENV, ssh.getScriptPath().getPath()); + mySshHandler = ssh.registerHandler(new GitSSHGUIHandler(myProject)); + myEnvironmentCleanedUp = false; + myEnv.put(GitSSHHandler.SSH_HANDLER_ENV, Integer.toString(mySshHandler)); + int port = ssh.getXmlRcpPort(); + myEnv.put(GitSSHHandler.SSH_PORT_ENV, Integer.toString(port)); + LOG.debug(String.format("handler=%s, port=%s", mySshHandler, port)); + + final HttpConfigurable httpConfigurable = HttpConfigurable.getInstance(); + boolean useHttpProxy = httpConfigurable.USE_HTTP_PROXY && !isSshUrlExcluded(httpConfigurable, ObjectUtils.assertNotNull(myUrls)); + myEnv.put(GitSSHHandler.SSH_USE_PROXY_ENV, String.valueOf(useHttpProxy)); + + if (useHttpProxy) { + myEnv.put(GitSSHHandler.SSH_PROXY_HOST_ENV, StringUtil.notNullize(httpConfigurable.PROXY_HOST)); + myEnv.put(GitSSHHandler.SSH_PROXY_PORT_ENV, String.valueOf(httpConfigurable.PROXY_PORT)); + boolean proxyAuthentication = httpConfigurable.PROXY_AUTHENTICATION; + myEnv.put(GitSSHHandler.SSH_PROXY_AUTHENTICATION_ENV, String.valueOf(proxyAuthentication)); + + if (proxyAuthentication) { + myEnv.put(GitSSHHandler.SSH_PROXY_USER_ENV, StringUtil.notNullize(httpConfigurable.PROXY_LOGIN)); + myEnv.put(GitSSHHandler.SSH_PROXY_PASSWORD_ENV, StringUtil.notNullize(httpConfigurable.getPlainProxyPassword())); + } + } + } + + protected static boolean isSshUrlExcluded(@NotNull final HttpConfigurable httpConfigurable, @NotNull Collection urls) { + return ContainerUtil.exists(urls, new Condition() { + @Override + public boolean value(String url) { + String host = URLUtil.parseHostFromSshUrl(url); + return ((IdeaWideProxySelector)httpConfigurable.getOnlyBySettingsSelector()).isProxyException(host); + } + }); } private void addAuthListener(@NotNull final GitHttpAuthenticator authenticator) { @@ -586,17 +606,11 @@ public abstract class GitHandler { if (myEnvironmentCleanedUp) { return; } - GitRemoteProtocol remoteProtocol = GitRemoteProtocol.fromUrl(myUrl); - if (remoteProtocol == GitRemoteProtocol.SSH) { - GitXmlRpcSshService ssh = ServiceManager.getService(GitXmlRpcSshService.class); - myEnvironmentCleanedUp = true; - ssh.unregisterHandler(myHandlerNo); - } - else if (remoteProtocol == GitRemoteProtocol.HTTP) { - GitHttpAuthService service = ServiceManager.getService(GitHttpAuthService.class); - myEnvironmentCleanedUp = true; - service.unregisterHandler(myHandlerNo); + if (isRemote()) { + ServiceManager.getService(GitXmlRpcSshService.class).unregisterHandler(mySshHandler); + ServiceManager.getService(GitHttpAuthService.class).unregisterHandler(myHttpHandler); } + myEnvironmentCleanedUp = true; } /** diff --git a/plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java b/plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java index 712582339405..6ddbcab22147 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java +++ b/plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java @@ -22,6 +22,8 @@ import org.jetbrains.git4idea.http.GitAskPassXmlRpcHandler; import org.jetbrains.git4idea.ssh.GitXmlRpcHandlerService; import org.jetbrains.git4idea.util.ScriptGenerator; +import java.util.Collection; + /** * Provides the authentication mechanism for Git HTTP connections. */ @@ -45,7 +47,9 @@ public abstract class GitHttpAuthService extends GitXmlRpcHandlerService urls); /** * Internal handler implementation class, it is made public to be accessible via XML RPC. diff --git a/plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java b/plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java index cda188d64e4b..0d7b56dc8f9a 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java +++ b/plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java @@ -18,6 +18,8 @@ package git4idea.commands; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; +import java.util.Collection; + /** * @author Kirill Likhodedov */ @@ -25,8 +27,8 @@ class GitHttpAuthServiceImpl extends GitHttpAuthService { @Override @NotNull - public GitHttpAuthenticator createAuthenticator(@NotNull Project project, @NotNull GitCommand command, @NotNull String url) { - return new GitHttpGuiAuthenticator(project, command, url); + public GitHttpAuthenticator createAuthenticator(@NotNull Project project, @NotNull GitCommand command, @NotNull Collection urls) { + return new GitHttpGuiAuthenticator(project, command, urls); } } diff --git a/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java b/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java index cf6b81c36cd6..9e4777be5174 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java +++ b/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java @@ -39,6 +39,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Arrays; +import java.util.Collection; import java.util.List; /** @@ -57,9 +58,9 @@ class GitHttpGuiAuthenticator implements GitHttpAuthenticator { private static final Logger LOG = Logger.getInstance(GitHttpGuiAuthenticator.class); private static final Class PASS_REQUESTER = GitHttpAuthenticator.class; - @NotNull private final Project myProject; - @NotNull private final String myTitle; - @NotNull private final String myUrlFromCommand; + @NotNull private final Project myProject; + @NotNull private final String myTitle; + @NotNull private final Collection myUrlsFromCommand; @Nullable private String myPassword; @Nullable private String myPasswordKey; @@ -69,10 +70,10 @@ class GitHttpGuiAuthenticator implements GitHttpAuthenticator { @Nullable private GitHttpAuthDataProvider myDataProvider; private boolean myWasCancelled; - GitHttpGuiAuthenticator(@NotNull Project project, @NotNull GitCommand command, @NotNull String url) { + GitHttpGuiAuthenticator(@NotNull Project project, @NotNull GitCommand command, @NotNull Collection url) { myProject = project; myTitle = "Git " + StringUtil.capitalize(command.name()); - myUrlFromCommand = url; + myUrlsFromCommand = url; } @Override @@ -195,18 +196,25 @@ class GitHttpGuiAuthenticator implements GitHttpAuthenticator { if (StringUtil.isEmptyOrSpaces(url)) { // if Git doesn't specify the URL in the username/password query, we use the url from the Git command // We only take the host, to avoid entering the same password for different repositories on the same host. - return adjustHttpUrl(getHost(myUrlFromCommand)); + return adjustHttpUrl(getHost(myUrlsFromCommand)); } return adjustHttpUrl(url); } @NotNull - private static String getHost(@NotNull String url) { - Couple split = UriUtil.splitScheme(url); - String scheme = split.getFirst(); - String urlItself = split.getSecond(); - int pathStart = urlItself.indexOf("/"); - return scheme + URLUtil.SCHEME_SEPARATOR + urlItself.substring(0, pathStart); + private static String getHost(@NotNull Collection urls) { + String host = "unknown"; + for (String url : urls) { + Couple split = UriUtil.splitScheme(url); + String scheme = split.getFirst(); + String urlItself = split.getSecond(); + int pathStart = urlItself.indexOf("/"); + host = scheme + URLUtil.SCHEME_SEPARATOR + urlItself.substring(0, pathStart); + if (scheme.startsWith("http")) { + return host; + } + } + return host; } /** diff --git a/plugins/git4idea/src/git4idea/commands/GitImpl.java b/plugins/git4idea/src/git4idea/commands/GitImpl.java index 695ea348bc76..9a4cba14b543 100644 --- a/plugins/git4idea/src/git4idea/commands/GitImpl.java +++ b/plugins/git4idea/src/git4idea/commands/GitImpl.java @@ -39,6 +39,8 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; +import static java.util.Collections.singleton; + /** * Easy-to-use wrapper of common native Git commands. * Most of them return result as {@link GitCommandResult}. @@ -374,29 +376,47 @@ public class GitImpl implements Git { @Override @NotNull - public GitCommandResult push(@NotNull GitRepository repository, @NotNull String remote, @Nullable String url, @NotNull String spec, - boolean updateTracking, @NotNull GitLineHandlerListener... listeners) { - return doPush(repository, remote, url, spec, false, updateTracking, null, listeners); + public GitCommandResult push(@NotNull GitRepository repository, + @NotNull String remote, + @Nullable String url, + @NotNull String spec, + boolean updateTracking, + @NotNull GitLineHandlerListener... listeners) { + return doPush(repository, remote, singleton(url), spec, false, updateTracking, null, listeners); + } + + @Override + @NotNull + public GitCommandResult push(@NotNull GitRepository repository, + @NotNull GitRemote remote, + @NotNull String spec, + boolean force, + boolean updateTracking, + @Nullable String tagMode, + GitLineHandlerListener... listeners) { + return doPush(repository, remote.getName(), remote.getPushUrls(), spec, force, updateTracking, tagMode, listeners); } @NotNull - private GitCommandResult doPush(@NotNull final GitRepository repository, @NotNull final String remote, @Nullable final String url, - @NotNull final String spec, final boolean force, final boolean updateTracking, - @Nullable final String tagMode, - @NotNull final GitLineHandlerListener... listeners) { + private GitCommandResult doPush(@NotNull final GitRepository repository, + @NotNull final String remoteName, + @NotNull final Collection remoteUrls, + @NotNull final String spec, + final boolean force, + final boolean updateTracking, + @Nullable final String tagMode, + @NotNull final GitLineHandlerListener... listeners) { return runCommand(new Computable() { @Override public GitLineHandler compute() { final GitLineHandler h = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.PUSH); - if (url != null) { - h.setUrl(url); - } + h.setUrls(remoteUrls); h.setSilent(false); h.setStdoutSuppressed(false); addListeners(h, listeners); h.addProgressParameter(); h.addParameters("--porcelain"); - h.addParameters(remote); + h.addParameters(remoteName); h.addParameters(spec); if (updateTracking) { h.addParameters("--set-upstream"); @@ -412,31 +432,6 @@ public class GitImpl implements Git { }); } - @Override - @NotNull - public GitCommandResult push(@NotNull GitRepository repository, @NotNull String remote, @Nullable String url, @NotNull String spec, - @NotNull GitLineHandlerListener... listeners) { - return push(repository, remote, url, spec, false, listeners); - } - - @Override - @NotNull - public GitCommandResult push(@NotNull GitRepository repository, @NotNull GitLocalBranch source, @NotNull GitRemoteBranch target, - boolean force, boolean updateTracking, @Nullable String tagMode, GitLineHandlerListener... listeners) { - GitRemote remote = target.getRemote(); - Collection pushUrls = remote.getPushUrls(); // TODO handle the case with multiple pushurls with different protocols - String url; - if (pushUrls.isEmpty()) { - LOG.error("No urls or pushUrls are defined for " + remote); - url = null; - } - else { - url = pushUrls.iterator().next(); - } - String spec = source.getFullName() + ":" + target.getNameForRemoteOperations(); - return doPush(repository, remote.getName(), url, spec, force, updateTracking, tagMode, listeners); - } - @NotNull @Override public GitCommandResult show(@NotNull GitRepository repository, @NotNull String... params) { @@ -476,16 +471,18 @@ public class GitImpl implements Git { */ @Override @NotNull - public GitCommandResult fetch(@NotNull final GitRepository repository, @NotNull final String url, @NotNull final String remote, - @NotNull final List listeners, final String... params) { + public GitCommandResult fetch(@NotNull final GitRepository repository, + @NotNull final GitRemote remote, + @NotNull final List listeners, + final String... params) { return runCommand(new Computable() { @Override public GitLineHandler compute() { final GitLineHandler h = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.FETCH); h.setSilent(false); h.setStdoutSuppressed(false); - h.setUrl(url); - h.addParameters(remote); + h.setUrls(remote.getUrls()); + h.addParameters(remote.getName()); h.addParameters(params); h.addProgressParameter(); GitVcs vcs = GitVcs.getInstance(repository.getProject()); @@ -511,7 +508,7 @@ public class GitImpl implements Git { public GitCommandResult lsRemote(@NotNull final Project project, @NotNull final File workingDir, @NotNull final String url) { - return doLsRemote(project, workingDir, url, url); + return doLsRemote(project, workingDir, url, singleton(url)); } @NotNull @@ -520,27 +517,22 @@ public class GitImpl implements Git { @NotNull VirtualFile workingDir, @NotNull GitRemote remote, String... additionalParameters) { - return doLsRemote(project, VfsUtilCore.virtualToIoFile(workingDir), remote.getName(), remote.getFirstUrl(), additionalParameters); + return doLsRemote(project, VfsUtilCore.virtualToIoFile(workingDir), remote.getName(), remote.getUrls(), additionalParameters); } @NotNull - private GitCommandResult doLsRemote(@NotNull final Project project, - @NotNull final File workingDir, - @NotNull final String remoteId, - @Nullable final String authenticationUrl, - final String... additionalParameters) { + private static GitCommandResult doLsRemote(@NotNull final Project project, + @NotNull final File workingDir, + @NotNull final String remoteId, + @NotNull final Collection authenticationUrls, + final String... additionalParameters) { return run(new Computable() { @Override public GitLineHandler compute() { GitLineHandler h = new GitLineHandler(project, workingDir, GitCommand.LS_REMOTE); h.addParameters(additionalParameters); h.addParameters(remoteId); - if (authenticationUrl != null) { - h.setUrl(authenticationUrl); - } - else { - LOG.error("No valid URLs for remote " + remoteId); - } + h.setUrls(authenticationUrls); return h; } }); diff --git a/plugins/git4idea/src/git4idea/commands/GitRemoteProtocol.java b/plugins/git4idea/src/git4idea/commands/GitRemoteProtocol.java deleted file mode 100644 index be1da0262662..000000000000 --- a/plugins/git4idea/src/git4idea/commands/GitRemoteProtocol.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2000-2013 JetBrains s.r.o. - * - * Licensed under the Apache 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.apache.org/licenses/LICENSE-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 git4idea.commands; - -import org.jetbrains.annotations.Nullable; - -/** -* @author Kirill Likhodedov -*/ -public enum GitRemoteProtocol { - GIT, - SSH, - HTTP; - - @Nullable - public static GitRemoteProtocol fromUrl(@Nullable String url) { - if (url == null) { - return null; - } - url = url.toLowerCase(); - if (url.startsWith("http")) { - return HTTP; - } - if (url.startsWith("git://")) { // "://" are there not to mix with scp-like syntax used for SSH: git@host.com/path/to.git - return GIT; - } - return SSH; - } - -} diff --git a/plugins/git4idea/src/git4idea/merge/GitPullDialog.java b/plugins/git4idea/src/git4idea/merge/GitPullDialog.java index f01a2083980e..21a7d2fb05da 100644 --- a/plugins/git4idea/src/git4idea/merge/GitPullDialog.java +++ b/plugins/git4idea/src/git4idea/merge/GitPullDialog.java @@ -178,11 +178,11 @@ public class GitPullDialog extends DialogWrapper { setOKActionEnabled(myBranchChooser.getMarkedElements().size() != 0); } - public GitLineHandler makeHandler(@NotNull String url) { + public GitLineHandler makeHandler(@NotNull List urls) { GitLineHandler h = new GitLineHandler(myProject, gitRoot(), GitCommand.PULL); // ignore merge failure for the pull h.ignoreErrorCode(1); - h.setUrl(url); + h.setUrls(urls); h.addProgressParameter(); h.addParameters("--no-stat"); if (myNoCommitCheckBox.isSelected()) { diff --git a/plugins/git4idea/src/git4idea/push/GitPushOperation.java b/plugins/git4idea/src/git4idea/push/GitPushOperation.java index 8973cd2b7b4b..545023aadfcc 100644 --- a/plugins/git4idea/src/git4idea/push/GitPushOperation.java +++ b/plugins/git4idea/src/git4idea/push/GitPushOperation.java @@ -368,7 +368,9 @@ public class GitPushOperation { GitLineHandlerListener progressListener = GitStandardProgressAnalyzer.createListener(myProgressIndicator); boolean setUpstream = pushSpec.getTarget().isNewBranchCreated() && !branchTrackingInfoIsSet(repository, sourceBranch); String tagMode = myTagMode == null ? null : myTagMode.getArgument(); - GitCommandResult res = myGit.push(repository, sourceBranch, targetBranch, myForce, setUpstream, tagMode, progressListener); + + String spec = sourceBranch.getFullName() + ":" + targetBranch.getNameForRemoteOperations(); + GitCommandResult res = myGit.push(repository, targetBranch.getRemote(), spec, myForce, setUpstream, tagMode, progressListener); return new ResultWithOutput(res); } diff --git a/plugins/git4idea/src/git4idea/update/GitFetcher.java b/plugins/git4idea/src/git4idea/update/GitFetcher.java index 0d01aaf30786..c9d70532db12 100644 --- a/plugins/git4idea/src/git4idea/update/GitFetcher.java +++ b/plugins/git4idea/src/git4idea/update/GitFetcher.java @@ -102,11 +102,7 @@ public class GitFetcher { if (remote == null) { return logError("Couldn't find remote with the name " + remoteName, null); } - String url = remote.getFirstUrl(); - if (url == null) { - return logError("URL is null for remote " + remote.getName(), null); - } - return fetchRemote(repository, remote, url, branch); + return fetchRemote(repository, remote, branch); } private static GitFetchResult logError(@NotNull String message, @Nullable String additionalInfo) { @@ -123,16 +119,14 @@ public class GitFetcher { } GitRemote remote = fetchParams.getRemote(); - String url = fetchParams.getUrl(); - return fetchRemote(repository, remote, url, null); + return fetchRemote(repository, remote, null); } @NotNull private GitFetchResult fetchRemote(@NotNull GitRepository repository, @NotNull GitRemote remote, - @NotNull String url, @Nullable String branch) { - return fetchNatively(repository, remote, url, branch); + return fetchNatively(repository, remote, branch); } // leaving this unused method, because the wanted behavior can change again @@ -146,8 +140,7 @@ public class GitFetcher { GitRemote remote = fetchParams.getRemote(); String remoteBranch = fetchParams.getRemoteBranch().getNameForRemoteOperations(); - String url = fetchParams.getUrl(); - return fetchNatively(repository, remote, url, remoteBranch); + return fetchNatively(repository, remote, remoteBranch); } @NotNull @@ -167,14 +160,7 @@ public class GitFetcher { } GitRemote remote = trackInfo.getRemote(); - String url = remote.getFirstUrl(); - if (url == null) { - String message = "URL is null for remote " + remote.getName(); - LOG.error(message); - return new FetchParams(GitFetchResult.error(new Exception(message))); - } - - return new FetchParams(remote, trackInfo.getRemoteBranch(), url); + return new FetchParams(remote, trackInfo.getRemoteBranch()); } @NotNull @@ -185,7 +171,7 @@ public class GitFetcher { LOG.error("URL is null for remote " + remote.getName()); continue; } - GitFetchResult res = fetchNatively(repository, remote, url, null); + GitFetchResult res = fetchNatively(repository, remote, null); res.addPruneInfo(fetchResult.getPrunedRefs()); fetchResult = res; if (!fetchResult.isSuccess()) { @@ -196,16 +182,15 @@ public class GitFetcher { } @NotNull - private static GitFetchResult fetchNatively(@NotNull GitRepository repository, @NotNull GitRemote remote, @NotNull String url, - @Nullable String branch) { + private static GitFetchResult fetchNatively(@NotNull GitRepository repository, @NotNull GitRemote remote, @Nullable String branch) { Git git = ServiceManager.getService(Git.class); String[] additionalParams = branch != null ? new String[]{ getFetchSpecForBranch(branch, remote.getName()) } : ArrayUtil.EMPTY_STRING_ARRAY; GitFetchPruneDetector pruneDetector = new GitFetchPruneDetector(); - GitCommandResult result = - git.fetch(repository, url, remote.getName(), Collections.singletonList(pruneDetector), additionalParams); + GitCommandResult result = git.fetch(repository, remote, + Collections.singletonList(pruneDetector), additionalParams); GitFetchResult fetchResult; if (result.success()) { @@ -347,16 +332,14 @@ public class GitFetcher { private GitRemote myRemote; private GitRemoteBranch myRemoteBranch; private GitFetchResult myError; - private String myUrl; FetchParams(GitFetchResult error) { myError = error; } - FetchParams(GitRemote remote, GitRemoteBranch remoteBranch, String url) { + FetchParams(GitRemote remote, GitRemoteBranch remoteBranch) { myRemote = remote; myRemoteBranch = remoteBranch; - myUrl = url; } boolean isError() { @@ -374,9 +357,5 @@ public class GitFetcher { public GitRemoteBranch getRemoteBranch() { return myRemoteBranch; } - - public String getUrl() { - return myUrl; - } } } diff --git a/plugins/git4idea/tests/git4idea/push/GitPushOperationMultiRepoTest.java b/plugins/git4idea/tests/git4idea/push/GitPushOperationMultiRepoTest.java index a053be8e9f6e..d069bd7db5fe 100644 --- a/plugins/git4idea/tests/git4idea/push/GitPushOperationMultiRepoTest.java +++ b/plugins/git4idea/tests/git4idea/push/GitPushOperationMultiRepoTest.java @@ -19,12 +19,11 @@ import com.intellij.dvcs.push.PushSpec; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Trinity; import com.intellij.util.containers.ContainerUtil; -import git4idea.GitLocalBranch; -import git4idea.GitRemoteBranch; import git4idea.commands.Git; import git4idea.commands.GitCommandResult; import git4idea.commands.GitImpl; import git4idea.commands.GitLineHandlerListener; +import git4idea.repo.GitRemote; import git4idea.repo.GitRepository; import git4idea.test.GitTestUtil; import git4idea.update.GitUpdateResult; @@ -80,20 +79,20 @@ public class GitPushOperationMultiRepoTest extends GitPushOperationBaseTest { private static class FailingPushGit extends GitImpl { private Condition myPushShouldFail; - @NotNull @Override + @NotNull public GitCommandResult push(@NotNull GitRepository repository, - @NotNull GitLocalBranch source, - @NotNull GitRemoteBranch target, + @NotNull GitRemote remote, + @NotNull String spec, boolean force, boolean updateTracking, @Nullable String tagMode, GitLineHandlerListener... listeners) { if (myPushShouldFail.value(repository)) { - return new GitCommandResult(false, 128, Collections.singletonList("Failed to push to " + target.getName()), + return new GitCommandResult(false, 128, Collections.singletonList("Failed to push to " + remote.getName()), Collections.emptyList(), null); } - return super.push(repository, source, target, force, updateTracking, tagMode, listeners); + return super.push(repository, remote, spec, force, updateTracking, tagMode, listeners); } } @@ -123,7 +122,7 @@ public class GitPushOperationMultiRepoTest extends GitPushOperationBaseTest { GitPushRepoResult result2 = result.getResults().get(myCommunity); assertResult(GitPushRepoResult.Type.ERROR, -1, "master", "origin/master", null, result1); - assertEquals("Error text is incorrect", "Failed to push to origin/master", result1.getError()); + assertEquals("Error text is incorrect", "Failed to push to origin", result1.getError()); assertResult(GitPushRepoResult.Type.SUCCESS, 1, "master", "origin/master", null, result2); } diff --git a/plugins/git4idea/tests/git4idea/test/GitHttpAuthTestService.java b/plugins/git4idea/tests/git4idea/test/GitHttpAuthTestService.java index 8723ce280269..cc5c9c5e22bf 100644 --- a/plugins/git4idea/tests/git4idea/test/GitHttpAuthTestService.java +++ b/plugins/git4idea/tests/git4idea/test/GitHttpAuthTestService.java @@ -21,6 +21,8 @@ import git4idea.commands.GitHttpAuthService; import git4idea.commands.GitHttpAuthenticator; import org.jetbrains.annotations.NotNull; +import java.util.Collection; + /** * @author Kirill Likhodedov */ @@ -30,23 +32,21 @@ public class GitHttpAuthTestService extends GitHttpAuthService { @NotNull @Override public String askPassword(@NotNull String url) { - throw new IllegalStateException("Authenticator was not registered"); + return ""; } @NotNull @Override public String askUsername(@NotNull String url) { - throw new IllegalStateException("Authenticator was not registered"); + return ""; } @Override public void saveAuthData() { - throw new IllegalStateException("Authenticator was not registered"); } @Override public void forgetPassword() { - throw new IllegalStateException("Authenticator was not registered"); } @Override @@ -59,7 +59,7 @@ public class GitHttpAuthTestService extends GitHttpAuthService { @NotNull @Override - public GitHttpAuthenticator createAuthenticator(@NotNull Project project, @NotNull GitCommand command, @NotNull String url) { + public GitHttpAuthenticator createAuthenticator(@NotNull Project project, @NotNull GitCommand command, @NotNull Collection urls) { return myAuthenticator; } diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubCreatePullRequestTestBase.java b/plugins/github/test/org/jetbrains/plugins/github/GithubCreatePullRequestTestBase.java index b6a2058cd24f..1c0404be9280 100644 --- a/plugins/github/test/org/jetbrains/plugins/github/GithubCreatePullRequestTestBase.java +++ b/plugins/github/test/org/jetbrains/plugins/github/GithubCreatePullRequestTestBase.java @@ -67,7 +67,7 @@ public abstract class GithubCreatePullRequestTestBase extends GithubTest { protected void deleteRemoteBranch() { GitRepository repository = GithubUtil.getGitRepository(myProject, myProjectRoot); if (repository != null) { - ServiceManager.getService(Git.class).push(repository, "origin", PROJECT_URL, ":" + BRANCH_NAME); + ServiceManager.getService(Git.class).push(repository, "origin", PROJECT_URL, ":" + BRANCH_NAME, false); } }