mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[git] IDEA-102778 Remove unused JGit
* Remove "shouldUseJGit" branches in the Git integration code. * Remove JGit adapter classes. * Move GitHttpAuthDataProvider to a more appropriate package. * Remove jgit lib.
This commit is contained in:
@@ -48,17 +48,6 @@
|
||||
</SOURCES>
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library">
|
||||
<library name="jgit-2.1.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/lib/jgit/org.eclipse.jgit-2.1.0.201209190230-r.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$MODULE_DIR$/lib/jgit/org.eclipse.jgit-2.1.0.201209190230-r_source.zip!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="library" scope="TEST" name="Groovy" level="project" />
|
||||
<orderEntry type="module" module-name="dvcs" exported="" />
|
||||
<orderEntry type="library" scope="TEST" name="cucumber-jvm" level="project" />
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -209,6 +209,6 @@
|
||||
</extensions>
|
||||
|
||||
<extensionPoints>
|
||||
<extensionPoint qualifiedName="Git4Idea.GitHttpAuthDataProvider" interface="git4idea.jgit.GitHttpAuthDataProvider"/>
|
||||
<extensionPoint qualifiedName="Git4Idea.GitHttpAuthDataProvider" interface="git4idea.remote.GitHttpAuthDataProvider"/>
|
||||
</extensionPoints>
|
||||
</idea-plugin>
|
||||
|
||||
@@ -23,12 +23,10 @@ import com.intellij.openapi.util.Couple;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsNotifier;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.GitPlatformFacade;
|
||||
import git4idea.commands.Git;
|
||||
import git4idea.commands.GitCommandResult;
|
||||
import git4idea.commands.GitCompoundResult;
|
||||
import git4idea.jgit.GitHttpAdapter;
|
||||
import git4idea.push.GitSimplePushResult;
|
||||
import git4idea.repo.GitRemote;
|
||||
import git4idea.repo.GitRepository;
|
||||
@@ -166,15 +164,7 @@ class GitDeleteRemoteBranchOperation extends GitBranchOperation {
|
||||
LOG.warn("No urls are defined for remote: " + remote);
|
||||
return GitCommandResult.error("There is no urls defined for remote " + remote.getName());
|
||||
}
|
||||
if (GitHttpAdapter.shouldUseJGit(remoteUrl)) {
|
||||
String fullBranchName = branchName.startsWith(GitBranch.REFS_HEADS_PREFIX) ? branchName : GitBranch.REFS_HEADS_PREFIX + branchName;
|
||||
String spec = ":" + fullBranchName;
|
||||
GitSimplePushResult simplePushResult = GitHttpAdapter.push(repository, remote.getName(), remoteUrl, spec);
|
||||
return convertSimplePushResultToCommandResult(simplePushResult);
|
||||
}
|
||||
else {
|
||||
return pushDeletionNatively(repository, remoteName, remoteUrl, branchName);
|
||||
}
|
||||
return pushDeletionNatively(repository, remoteName, remoteUrl, branchName);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -30,9 +30,6 @@ import git4idea.commands.Git;
|
||||
import git4idea.commands.GitCommandResult;
|
||||
import git4idea.commands.GitLineHandlerListener;
|
||||
import git4idea.commands.GitStandardProgressAnalyzer;
|
||||
import git4idea.jgit.GitHttpAdapter;
|
||||
import git4idea.update.GitFetchResult;
|
||||
import git4idea.update.GitFetcher;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -109,26 +106,13 @@ public class GitCheckoutProvider implements CheckoutProvider {
|
||||
|
||||
public static boolean doClone(@NotNull Project project, @NotNull ProgressIndicator indicator, @NotNull Git git,
|
||||
@NotNull String directoryName, @NotNull String parentDirectory, @NotNull String sourceRepositoryURL) {
|
||||
if (GitHttpAdapter.shouldUseJGit(sourceRepositoryURL)) {
|
||||
GitFetchResult result = GitHttpAdapter.cloneRepository(project, new File(parentDirectory, directoryName), sourceRepositoryURL);
|
||||
GitFetcher.displayFetchResult(project, result, "Clone failed", result.getErrors());
|
||||
return result.isSuccess();
|
||||
}
|
||||
else {
|
||||
return cloneNatively(project, indicator, git, new File(parentDirectory), sourceRepositoryURL, directoryName);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean cloneNatively(@NotNull Project project, @NotNull final ProgressIndicator indicator,
|
||||
@NotNull Git git, @NotNull File directory, @NotNull String url, @NotNull String cloneDirectoryName) {
|
||||
indicator.setIndeterminate(false);
|
||||
GitLineHandlerListener progressListener = GitStandardProgressAnalyzer.createListener(indicator);
|
||||
GitCommandResult result = git.clone(project, directory, url, cloneDirectoryName, progressListener);
|
||||
GitCommandResult result = git.clone(project, new File(parentDirectory), sourceRepositoryURL, directoryName, progressListener);
|
||||
if (result.success()) {
|
||||
return true;
|
||||
}
|
||||
VcsNotifier.getInstance(project).notifyError("Clone failed", result.getErrorOutputAsHtmlString());
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import com.intellij.util.UriUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.io.URLUtil;
|
||||
import com.intellij.vcsUtil.AuthDialog;
|
||||
import git4idea.jgit.GitHttpAuthDataProvider;
|
||||
import git4idea.remote.GitHttpAuthDataProvider;
|
||||
import git4idea.remote.GitRememberedInputs;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -1,525 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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.jgit;
|
||||
|
||||
import com.intellij.ide.passwordSafe.PasswordSafe;
|
||||
import com.intellij.ide.passwordSafe.PasswordSafeException;
|
||||
import com.intellij.ide.passwordSafe.config.PasswordSafeSettings;
|
||||
import com.intellij.ide.passwordSafe.impl.PasswordSafeImpl;
|
||||
import com.intellij.ide.passwordSafe.impl.PasswordSafeProvider;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.util.AuthData;
|
||||
import com.intellij.util.proxy.CommonProxy;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.push.GitSimplePushResult;
|
||||
import git4idea.remote.GitRememberedInputs;
|
||||
import git4idea.repo.GitRemote;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.update.GitFetchResult;
|
||||
import git4idea.update.GitFetcher;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.api.errors.InvalidRemoteException;
|
||||
import org.eclipse.jgit.api.errors.JGitInternalException;
|
||||
import org.eclipse.jgit.errors.NoRemoteRepositoryException;
|
||||
import org.eclipse.jgit.errors.NotSupportedException;
|
||||
import org.eclipse.jgit.errors.TransportException;
|
||||
import org.eclipse.jgit.lib.ConfigConstants;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.lib.StoredConfig;
|
||||
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
|
||||
import org.eclipse.jgit.transport.RefSpec;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Handles remote operations over HTTP via JGit library.
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public final class GitHttpAdapter {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(GitHttpAdapter.class);
|
||||
|
||||
private static final String IGNORECASE_SETTING = "ignorecase";
|
||||
|
||||
public static boolean shouldUseJGit(@NotNull String url) {
|
||||
return "jgit".equals(System.getProperty("git.http"));
|
||||
}
|
||||
|
||||
private enum GeneralResult {
|
||||
SUCCESS,
|
||||
CANCELLED,
|
||||
NOT_AUTHORIZED
|
||||
}
|
||||
|
||||
private GitHttpAdapter() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the given remote in the given Git repository.
|
||||
* Asks username and password if needed.
|
||||
*/
|
||||
@NotNull
|
||||
public static GitFetchResult fetch(@NotNull final GitRepository repository, @NotNull final GitRemote remote,
|
||||
@NotNull String remoteUrl, @Nullable String remoteBranch) {
|
||||
GitFetchResult.Type resultType;
|
||||
try {
|
||||
final Git git = convertToGit(repository);
|
||||
final GitHttpCredentialsProvider provider = new GitHttpCredentialsProvider(repository.getProject(), remoteUrl);
|
||||
|
||||
List<String> specs;
|
||||
if (remoteBranch == null) {
|
||||
specs = remote.getFetchRefSpecs();
|
||||
}
|
||||
else {
|
||||
specs = Collections.singletonList(GitFetcher.getFetchSpecForBranch(remoteBranch, remote.getName()));
|
||||
}
|
||||
|
||||
GeneralResult result = callWithAuthRetry(new GitHttpRemoteCommand.Fetch(git, provider, remoteUrl, convertRefSpecs(specs)),
|
||||
repository.getProject());
|
||||
resultType = convertToFetchResultType(result);
|
||||
} catch (IOException e) {
|
||||
logException(repository, remote.getName(), remoteUrl, e, "fetching");
|
||||
return GitFetchResult.error(e);
|
||||
}
|
||||
catch (InvalidRemoteException e) {
|
||||
logException(repository, remote.getName(), remoteUrl, e, "fetching");
|
||||
return GitFetchResult.error(e);
|
||||
}
|
||||
catch (URISyntaxException e) {
|
||||
logException(repository, remote.getName(), remoteUrl, e, "fetching");
|
||||
return GitFetchResult.error(e);
|
||||
}
|
||||
return new GitFetchResult(resultType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<RefSpec> convertRefSpecs(@NotNull List<String> refSpecs) {
|
||||
List<RefSpec> jgitSpecs = new ArrayList<RefSpec>();
|
||||
for (String spec : refSpecs) {
|
||||
jgitSpecs.add(new RefSpec(spec));
|
||||
}
|
||||
return jgitSpecs;
|
||||
}
|
||||
|
||||
private static void logException(GitRepository repository, String remoteName, String remoteUrl, Exception e, String operation) {
|
||||
LOG.error("Exception while " + operation + " " + remoteName + "(" + remoteUrl + ")" + " in " + repository.toLogString(), e);
|
||||
}
|
||||
|
||||
private static GitFetchResult.Type convertToFetchResultType(GeneralResult result) {
|
||||
switch (result) {
|
||||
case CANCELLED: return GitFetchResult.Type.CANCELLED;
|
||||
case SUCCESS: return GitFetchResult.Type.SUCCESS;
|
||||
case NOT_AUTHORIZED: return GitFetchResult.Type.NOT_AUTHORIZED;
|
||||
}
|
||||
return GitFetchResult.Type.CANCELLED;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static GitSimplePushResult push(@NotNull final GitRepository repository, @NotNull final String remoteName,
|
||||
@NotNull final String remoteUrl, @NotNull String pushSpec) {
|
||||
try {
|
||||
final Git git = convertToGit(repository);
|
||||
final GitHttpCredentialsProvider provider = new GitHttpCredentialsProvider(repository.getProject(), remoteUrl);
|
||||
GitHttpRemoteCommand.Push pushCommand = new GitHttpRemoteCommand.Push(git, provider, remoteName, remoteUrl,
|
||||
convertRefSpecs(Collections.singletonList(pushSpec)));
|
||||
GeneralResult result = callWithAuthRetry(pushCommand, repository.getProject());
|
||||
GitSimplePushResult pushResult = pushCommand.getResult();
|
||||
if (pushResult == null) {
|
||||
return convertToPushResultType(result);
|
||||
} else {
|
||||
return pushResult;
|
||||
}
|
||||
}
|
||||
catch (SmartPushNotSupportedException e) {
|
||||
return GitSimplePushResult.error("Remote <code>" + remoteUrl + "</code> doesn't support <a href=\"http://progit.org/2010/03/04/smart-http.html\">" +
|
||||
"smart HTTP push. </a><br/>" +
|
||||
"Please set the server to use smart push or use other protocol (SSH for example). <br/>" +
|
||||
"If neither is possible, as a workaround you may add authentication data directly to the remote url in <code>.git/config</code>.");
|
||||
}
|
||||
catch (InvalidRemoteException e) {
|
||||
logException(repository, remoteName, remoteUrl, e, "pushing");
|
||||
return makeErrorResultFromException(e);
|
||||
}
|
||||
catch (IOException e) {
|
||||
logException(repository, remoteName, remoteUrl, e, "pushing");
|
||||
return makeErrorResultFromException(e);
|
||||
}
|
||||
catch (URISyntaxException e) {
|
||||
logException(repository, remoteName, remoteUrl, e, "pushing");
|
||||
return makeErrorResultFromException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Collection<String> lsRemote(@NotNull GitRepository repository, @NotNull String remoteName, @NotNull String remoteUrl) {
|
||||
try {
|
||||
final Git git = convertToGit(repository);
|
||||
final GitHttpCredentialsProvider provider = new GitHttpCredentialsProvider(repository.getProject(), remoteUrl);
|
||||
GitHttpRemoteCommand.LsRemote lsRemoteCommand = new GitHttpRemoteCommand.LsRemote(git, provider, remoteUrl);
|
||||
callWithAuthRetry(lsRemoteCommand, repository.getProject());
|
||||
return convertRefsToStrings(lsRemoteCommand.getRefs());
|
||||
} catch (IOException e) {
|
||||
logException(repository, remoteName, remoteUrl, e, "ls-remote");
|
||||
}
|
||||
catch (InvalidRemoteException e) {
|
||||
logException(repository, remoteName, remoteUrl, e, "ls-remote");
|
||||
}
|
||||
catch (URISyntaxException e) {
|
||||
logException(repository, remoteName, remoteUrl, e, "ls-remote");
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Collection<String> convertRefsToStrings(@NotNull Collection<Ref> lsRemoteCommandRefs) {
|
||||
Collection<String> refs = new ArrayList<String>();
|
||||
for (Ref ref : lsRemoteCommandRefs) {
|
||||
String refName = ref.getName();
|
||||
if (refName.startsWith(GitBranch.REFS_HEADS_PREFIX)) {
|
||||
refName = refName.substring(GitBranch.REFS_HEADS_PREFIX.length());
|
||||
}
|
||||
refs.add(refName);
|
||||
}
|
||||
return refs;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static GitFetchResult cloneRepository(@NotNull Project project, @NotNull final File directory, @NotNull final String url) {
|
||||
GitFetchResult.Type resultType;
|
||||
try {
|
||||
final GitHttpCredentialsProvider provider = new GitHttpCredentialsProvider(project, url);
|
||||
GitHttpRemoteCommand.Clone command = new GitHttpRemoteCommand.Clone(directory, provider, url);
|
||||
GeneralResult result = callWithAuthRetry(command, project);
|
||||
resultType = convertToFetchResultType(result);
|
||||
if (resultType.equals(GitFetchResult.Type.SUCCESS)) {
|
||||
updateCoreIgnoreCaseSetting(command.getGit());
|
||||
}
|
||||
return new GitFetchResult(resultType);
|
||||
}
|
||||
catch (InvalidRemoteException e) {
|
||||
LOG.info("Exception while cloning " + url + " to " + directory, e);
|
||||
return GitFetchResult.error(e);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info("Exception while cloning " + url + " to " + directory, e);
|
||||
return GitFetchResult.error(e);
|
||||
}
|
||||
catch (URISyntaxException e) {
|
||||
LOG.info("Exception while cloning " + url + " to " + directory, e);
|
||||
return GitFetchResult.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateCoreIgnoreCaseSetting(@Nullable Git git) {
|
||||
if (SystemInfo.isFileSystemCaseSensitive) {
|
||||
return;
|
||||
}
|
||||
if (git == null) {
|
||||
LOG.info("jgit.Git is null, the command should have failed. Not updating the settings.");
|
||||
return;
|
||||
}
|
||||
StoredConfig config = git.getRepository().getConfig();
|
||||
config.setString(ConfigConstants.CONFIG_CORE_SECTION, null, IGNORECASE_SETTING, Boolean.TRUE.toString());
|
||||
try {
|
||||
config.save();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info("Couldn't save config for " + git.getRepository().getDirectory().getPath(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static GitSimplePushResult convertToPushResultType(GeneralResult result) {
|
||||
switch (result) {
|
||||
case SUCCESS:
|
||||
return GitSimplePushResult.success();
|
||||
case CANCELLED:
|
||||
return GitSimplePushResult.cancel();
|
||||
case NOT_AUTHORIZED:
|
||||
return GitSimplePushResult.notAuthorized();
|
||||
default:
|
||||
return GitSimplePushResult.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
private static GitSimplePushResult makeErrorResultFromException(Exception e) {
|
||||
return GitSimplePushResult.error(e.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the given runnable.
|
||||
* If user cancels the authentication dialog, returns.
|
||||
* If user enters incorrect data, he has 2 more attempts to go before failure.
|
||||
* Cleanups are executed after each incorrect attempt to enter password, and after other retriable actions.
|
||||
*/
|
||||
private static GeneralResult callWithAuthRetry(@NotNull GitHttpRemoteCommand command, @NotNull Project project) throws InvalidRemoteException, IOException, URISyntaxException {
|
||||
boolean httpTransportErrorFixTried = false;
|
||||
boolean noRemoteWithoutGitErrorFixTried = false;
|
||||
|
||||
String url = command.getUrl();
|
||||
GitHttpCredentialsProvider provider = command.getCredentialsProvider();
|
||||
try {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
try {
|
||||
AuthData authData = getUsernameAndPassword(provider.getProject(), provider.getUrl());
|
||||
if (authData != null) {
|
||||
provider.fillAuthDataIfNotFilled(authData.getLogin(), authData.getPassword());
|
||||
}
|
||||
if (i == 0) {
|
||||
provider.setAlwaysShowDialog(false); // if username and password are supplied, no need to show the dialog
|
||||
} else {
|
||||
provider.setAlwaysShowDialog(true); // unless these values fail authentication
|
||||
}
|
||||
command.run();
|
||||
rememberPassword(provider);
|
||||
return GeneralResult.SUCCESS;
|
||||
}
|
||||
catch (GitAPIException e) {
|
||||
if (!noRemoteWithoutGitErrorFixTried && isNoRemoteWithoutDotGitError(e, url)) {
|
||||
url = addDotGitToUrl(url);
|
||||
command.setUrl(url);
|
||||
provider.setUrl(url);
|
||||
noRemoteWithoutGitErrorFixTried = true;
|
||||
// don't "eat" one password entering attempt
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
i--;
|
||||
}
|
||||
command.cleanup();
|
||||
}
|
||||
catch (JGitInternalException e) {
|
||||
try {
|
||||
if (authError(e)) {
|
||||
if (provider.wasCancelled()) { // if user cancels the dialog, just return
|
||||
return GeneralResult.CANCELLED;
|
||||
}
|
||||
// otherwise give more tries to enter password
|
||||
}
|
||||
else if (!httpTransportErrorFixTried && isTransportExceptionForHttp(e, url)) {
|
||||
url = url.replaceFirst("http", "https");
|
||||
command.setUrl(url);
|
||||
provider.setUrl(url);
|
||||
httpTransportErrorFixTried = true;
|
||||
// don't "eat" one password entering attempt
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
i--;
|
||||
}
|
||||
else if (!noRemoteWithoutGitErrorFixTried && isNoRemoteWithoutDotGitError(e, url)) {
|
||||
url = addDotGitToUrl(url);
|
||||
command.setUrl(url);
|
||||
provider.setUrl(url);
|
||||
noRemoteWithoutGitErrorFixTried = true;
|
||||
// don't "eat" one password entering attempt
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
i--;
|
||||
}
|
||||
else if (smartHttpPushNotSupported(e)) {
|
||||
throw new SmartPushNotSupportedException(e.getCause().getMessage());
|
||||
}
|
||||
else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
command.cleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
return GeneralResult.NOT_AUTHORIZED;
|
||||
}
|
||||
finally {
|
||||
log(command, project);
|
||||
}
|
||||
}
|
||||
|
||||
private static CommonProxy.HostInfo getHostInfo(String url) throws URISyntaxException {
|
||||
final boolean isSecure = url.startsWith("https");
|
||||
final String protocol = isSecure ? "https" : "http";
|
||||
final URI uri = new URI(url);
|
||||
int port = uri.getPort();
|
||||
port = port < 0 ? (isSecure ? 443 : 80) : port;
|
||||
return new CommonProxy.HostInfo(protocol, uri.getHost(), port);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String addDotGitToUrl(@NotNull String url) {
|
||||
if (url.endsWith("/")) {
|
||||
url = url.substring(0, url.length() - 1);
|
||||
}
|
||||
return url + GitUtil.DOT_GIT;
|
||||
}
|
||||
|
||||
private static void log(@NotNull GitHttpRemoteCommand command, @NotNull Project project) {
|
||||
GitVcs vcs = GitVcs.getInstance(project);
|
||||
if (vcs != null) {
|
||||
vcs.showCommandLine(command.getCommandString());
|
||||
}
|
||||
LOG.info(command.getLogString());
|
||||
}
|
||||
|
||||
private static boolean smartHttpPushNotSupported(JGitInternalException e) {
|
||||
if (e.getCause() instanceof NotSupportedException) {
|
||||
NotSupportedException nse = (NotSupportedException)e.getCause();
|
||||
String message = nse.getMessage();
|
||||
return message != null && message.toLowerCase().contains("smart http push");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isNoRemoteWithoutDotGitError(Throwable e, String url) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause == null || (!(cause instanceof NoRemoteRepositoryException) && !(cause.getCause() instanceof NoRemoteRepositoryException))) {
|
||||
return false;
|
||||
}
|
||||
return !url.toLowerCase().endsWith(GitUtil.DOT_GIT);
|
||||
}
|
||||
|
||||
private static boolean isTransportExceptionForHttp(@NotNull JGitInternalException e, @NotNull String url) {
|
||||
if (!(e.getCause() instanceof TransportException)) {
|
||||
return false;
|
||||
}
|
||||
return url.toLowerCase().startsWith("http") && !url.toLowerCase().startsWith("https");
|
||||
}
|
||||
|
||||
private static void rememberPassword(@NotNull GitHttpCredentialsProvider credentialsProvider) {
|
||||
if (!credentialsProvider.wasDialogShown()) { // the dialog is not shown => everything is already stored
|
||||
return;
|
||||
}
|
||||
final PasswordSafeImpl passwordSafe = (PasswordSafeImpl)PasswordSafe.getInstance();
|
||||
if (passwordSafe.getSettings().getProviderType() == PasswordSafeSettings.ProviderType.DO_NOT_STORE) {
|
||||
return;
|
||||
}
|
||||
String login = credentialsProvider.getUserName();
|
||||
if (login == null || credentialsProvider.getPassword() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String url = adjustHttpUrl(credentialsProvider.getUrl());
|
||||
String key = keyForUrlAndLogin(url, login);
|
||||
try {
|
||||
// store in memory always
|
||||
storePassword(passwordSafe.getMemoryProvider(), credentialsProvider, key);
|
||||
if (credentialsProvider.isRememberPassword()) {
|
||||
storePassword(passwordSafe.getMasterKeyProvider(), credentialsProvider, key);
|
||||
}
|
||||
GitRememberedInputs.getInstance().addUrl(url, login);
|
||||
}
|
||||
catch (PasswordSafeException e) {
|
||||
LOG.info("Couldn't store the password for key [" + key + "]", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void storePassword(PasswordSafeProvider passwordProvider, GitHttpCredentialsProvider credentialsProvider, String key) throws PasswordSafeException {
|
||||
passwordProvider.storePassword(credentialsProvider.getProject(), GitHttpCredentialsProvider.class, key, credentialsProvider.getPassword());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static AuthData getUsernameAndPassword(Project project, String url) {
|
||||
url = adjustHttpUrl(url);
|
||||
String userName = GitRememberedInputs.getInstance().getUserNameForUrl(url);
|
||||
if (userName == null) {
|
||||
return trySavedAuthDataFromProviders(url);
|
||||
}
|
||||
String key = keyForUrlAndLogin(url, userName);
|
||||
final PasswordSafe passwordSafe = PasswordSafe.getInstance();
|
||||
try {
|
||||
String password = passwordSafe.getPassword(project, GitHttpCredentialsProvider.class, key);
|
||||
if (password != null) {
|
||||
return new AuthData(userName, password);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch (PasswordSafeException e) {
|
||||
LOG.info("Couldn't get the password for key [" + key + "]", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static AuthData trySavedAuthDataFromProviders(@NotNull String url) {
|
||||
GitHttpAuthDataProvider[] extensions = GitHttpAuthDataProvider.EP_NAME.getExtensions();
|
||||
for (GitHttpAuthDataProvider provider : extensions) {
|
||||
AuthData authData = provider.getAuthData(url);
|
||||
if (authData != null) {
|
||||
return authData;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* If url is HTTPS, store it as HTTP in the password database, not to make user enter and remember same credentials twice.
|
||||
*/
|
||||
@NotNull
|
||||
private static String adjustHttpUrl(@NotNull String url) {
|
||||
if (url.startsWith("https")) {
|
||||
return url.replaceFirst("https", "http");
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String keyForUrlAndLogin(@NotNull String stringUrl, @NotNull String login) {
|
||||
return login + ":" + stringUrl;
|
||||
}
|
||||
|
||||
private static boolean authError(@NotNull JGitInternalException e) {
|
||||
Throwable cause = e.getCause();
|
||||
return (cause instanceof TransportException && cause.getMessage().contains("not authorized"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts {@link GitRepository} to JGit's {@link Repository}.
|
||||
*/
|
||||
@NotNull
|
||||
private static Repository convert(@NotNull GitRepository repository) throws IOException {
|
||||
FileRepositoryBuilder builder = new FileRepositoryBuilder();
|
||||
return builder.setGitDir(new File(repository.getRoot().getPath(), GitUtil.DOT_GIT))
|
||||
.readEnvironment() // scan environment GIT_* variables
|
||||
.findGitDir() // scan up the file system tree
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts {@link GitRepository} to JGit's {@link Git} object.
|
||||
*/
|
||||
private static Git convertToGit(@NotNull GitRepository repository) throws IOException {
|
||||
return Git.wrap(convert(repository));
|
||||
}
|
||||
|
||||
private static class SmartPushNotSupportedException extends NotSupportedException {
|
||||
private SmartPushNotSupportedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,193 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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.jgit;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.vcsUtil.AuthDialog;
|
||||
import org.eclipse.jgit.errors.UnsupportedCredentialItem;
|
||||
import org.eclipse.jgit.transport.CredentialItem;
|
||||
import org.eclipse.jgit.transport.CredentialsProvider;
|
||||
import org.eclipse.jgit.transport.URIish;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class GitHttpCredentialsProvider extends CredentialsProvider {
|
||||
|
||||
private static final Pattern HTTP_URL_PATTERN = Pattern.compile("http(?:s?)://(?:([\\S^@\\.]*)@)?.*");
|
||||
|
||||
private final Project myProject;
|
||||
private String myRemoteUrl;
|
||||
|
||||
private boolean myCancelled;
|
||||
private boolean myRememberPassword;
|
||||
private String myPassword;
|
||||
private String myUserName;
|
||||
private boolean myShowDialog;
|
||||
private boolean myDialogShown;
|
||||
|
||||
public GitHttpCredentialsProvider(@NotNull Project project, @NotNull String remoteUrl) {
|
||||
myProject = project;
|
||||
myRemoteUrl = remoteUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInteractive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(CredentialItem... items) {
|
||||
for (CredentialItem item : items) {
|
||||
if (item instanceof CredentialItem.Password) {
|
||||
continue;
|
||||
}
|
||||
if (item instanceof CredentialItem.Username) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean get(URIish uri, CredentialItem... items) throws UnsupportedCredentialItem {
|
||||
CredentialItem.Username userNameItem = null;
|
||||
CredentialItem.Password passwordItem = null;
|
||||
for (CredentialItem item : items) {
|
||||
if (item instanceof CredentialItem.Username) {
|
||||
userNameItem = (CredentialItem.Username)item;
|
||||
} else if (item instanceof CredentialItem.Password) {
|
||||
passwordItem = (CredentialItem.Password)item;
|
||||
}
|
||||
}
|
||||
|
||||
if (userNameItem != null || passwordItem != null) {
|
||||
String username = getUserNameFromUrl(myRemoteUrl);
|
||||
String password = null;
|
||||
if (username == null) { // username is not in the url => reading pre-filled value from the password storage
|
||||
username = myUserName;
|
||||
password = myPassword;
|
||||
} else if (username.equals(myUserName)) { // username is in url => read password only if it is for the same user
|
||||
password = myPassword;
|
||||
}
|
||||
|
||||
boolean rememberPassword = myRememberPassword;
|
||||
boolean ok;
|
||||
if (username != null && password != null && !myShowDialog) {
|
||||
ok = true;
|
||||
myDialogShown = false;
|
||||
} else {
|
||||
final AuthDialog dialog = new AuthDialog(myProject, "Login required", "Login to " + myRemoteUrl, username, password, false);
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dialog.show();
|
||||
}
|
||||
});
|
||||
ok = dialog.isOK();
|
||||
myDialogShown = true;
|
||||
if (ok) {
|
||||
username = dialog.getUsername();
|
||||
password = dialog.getPassword();
|
||||
rememberPassword = dialog.isRememberPassword();
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
if (userNameItem != null) {
|
||||
userNameItem.setValue(username);
|
||||
}
|
||||
if (passwordItem != null) {
|
||||
passwordItem.setValue(password.toCharArray());
|
||||
}
|
||||
myRememberPassword = rememberPassword;
|
||||
myPassword = password;
|
||||
myUserName = username;
|
||||
}
|
||||
else {
|
||||
myCancelled = true;
|
||||
myRememberPassword = false; // in case of re-usage of the provider
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isRememberPassword() {
|
||||
return myRememberPassword;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getPassword() {
|
||||
return myPassword;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getUserName() {
|
||||
return myUserName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getUrl() {
|
||||
return myRemoteUrl;
|
||||
}
|
||||
|
||||
public void setUrl(@NotNull String url) {
|
||||
myRemoteUrl = url;
|
||||
}
|
||||
|
||||
public void fillAuthDataIfNotFilled(@NotNull String login, @Nullable String password) {
|
||||
if (myUserName == null) {
|
||||
myUserName = login;
|
||||
myPassword = password;
|
||||
} else if (myPassword != null) {
|
||||
myPassword = password;
|
||||
}
|
||||
}
|
||||
|
||||
public void setAlwaysShowDialog(boolean showDialog) {
|
||||
myShowDialog = showDialog;
|
||||
}
|
||||
|
||||
public boolean wasDialogShown() {
|
||||
return myDialogShown;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getUserNameFromUrl(@NotNull String url) {
|
||||
Matcher matcher = HTTP_URL_PATTERN.matcher(url);
|
||||
if (matcher.matches()) {
|
||||
return matcher.group(1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean wasCancelled() {
|
||||
return myCancelled;
|
||||
}
|
||||
}
|
||||
@@ -1,507 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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.jgit;
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.Function;
|
||||
import git4idea.push.GitSimplePushResult;
|
||||
import org.eclipse.jgit.api.CloneCommand;
|
||||
import org.eclipse.jgit.api.FetchCommand;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.PushCommand;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.api.errors.InvalidRemoteException;
|
||||
import org.eclipse.jgit.api.errors.JGitInternalException;
|
||||
import org.eclipse.jgit.errors.NotSupportedException;
|
||||
import org.eclipse.jgit.errors.TransportException;
|
||||
import org.eclipse.jgit.internal.JGitText;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.ProgressMonitor;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.transport.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
interface GitHttpRemoteCommand {
|
||||
|
||||
String getUrl();
|
||||
void setUrl(String url);
|
||||
void run() throws GitAPIException, URISyntaxException, TransportException;
|
||||
void cleanup();
|
||||
GitHttpCredentialsProvider getCredentialsProvider();
|
||||
String getLogString();
|
||||
String getCommandString();
|
||||
|
||||
class Fetch implements GitHttpRemoteCommand {
|
||||
|
||||
private final Git myGit;
|
||||
private final GitHttpCredentialsProvider myCredentialsProvider;
|
||||
private String myUrl;
|
||||
private final List<RefSpec> myRefSpecs;
|
||||
|
||||
Fetch(@NotNull Git git, @NotNull GitHttpCredentialsProvider credentialsProvider, @NotNull String url, @NotNull List<RefSpec> refSpecs) {
|
||||
myGit = git;
|
||||
myCredentialsProvider = credentialsProvider;
|
||||
myUrl = url;
|
||||
myRefSpecs = refSpecs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() throws GitAPIException {
|
||||
FetchCommand fetchCommand = myGit.fetch();
|
||||
fetchCommand.setRemote(myUrl);
|
||||
fetchCommand.setRefSpecs(myRefSpecs);
|
||||
fetchCommand.setCredentialsProvider(myCredentialsProvider);
|
||||
fetchCommand.call();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUrl(@NotNull String url) {
|
||||
myUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUrl() {
|
||||
return myUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GitHttpCredentialsProvider getCredentialsProvider() {
|
||||
return myCredentialsProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogString() {
|
||||
return getCommandString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandString() {
|
||||
return String.format("git fetch %s %s", myUrl, getRefspecsAsString(myRefSpecs));
|
||||
}
|
||||
|
||||
static String getRefspecsAsString(@NotNull List<RefSpec> refSpecs) {
|
||||
return StringUtil.join(refSpecs, new Function<RefSpec, String>() {
|
||||
@Override
|
||||
public String fun(RefSpec spec) {
|
||||
return spec.toString();
|
||||
}
|
||||
}, " ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
}
|
||||
}
|
||||
|
||||
class Clone implements GitHttpRemoteCommand {
|
||||
|
||||
private final File myTargetDirectory;
|
||||
private final GitHttpCredentialsProvider myCredentialsProvider;
|
||||
private String myUrl;
|
||||
@Nullable private Git myGit;
|
||||
|
||||
Clone(@NotNull File targetDirectory, @NotNull GitHttpCredentialsProvider credentialsProvider, String url) {
|
||||
myTargetDirectory = targetDirectory;
|
||||
myCredentialsProvider = credentialsProvider;
|
||||
myUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() throws GitAPIException {
|
||||
CloneCommand cloneCommand = Git.cloneRepository();
|
||||
cloneCommand.setDirectory(myTargetDirectory);
|
||||
cloneCommand.setURI(myUrl);
|
||||
cloneCommand.setCredentialsProvider(myCredentialsProvider);
|
||||
myGit = cloneCommand.call();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUrl(@NotNull String url) {
|
||||
myUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUrl() {
|
||||
return myUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GitHttpCredentialsProvider getCredentialsProvider() {
|
||||
return myCredentialsProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogString() {
|
||||
return getCommandString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandString() {
|
||||
return String.format("git clone %s %s", myUrl, myTargetDirectory.getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
if (myTargetDirectory.exists()) {
|
||||
FileUtil.delete(myTargetDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Git getGit() {
|
||||
return myGit;
|
||||
}
|
||||
}
|
||||
|
||||
class Push implements GitHttpRemoteCommand {
|
||||
|
||||
private final Git myGit;
|
||||
private final GitHttpCredentialsProvider myCredentialsProvider;
|
||||
private GitSimplePushResult myPushResult;
|
||||
private String myRemoteName;
|
||||
private String myUrl;
|
||||
private final List<RefSpec> myPushSpecs;
|
||||
|
||||
Push(@NotNull Git git, @NotNull GitHttpCredentialsProvider credentialsProvider, @NotNull String remoteName, @NotNull String url, @NotNull List<RefSpec> pushSpecs) {
|
||||
myGit = git;
|
||||
myCredentialsProvider = credentialsProvider;
|
||||
myRemoteName = remoteName;
|
||||
myUrl = url;
|
||||
myPushSpecs = pushSpecs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() throws InvalidRemoteException, URISyntaxException, org.eclipse.jgit.api.errors.TransportException {
|
||||
PushCommand pushCommand = myGit.push();
|
||||
pushCommand.setRemote(myRemoteName);
|
||||
pushCommand.setRefSpecs(myPushSpecs);
|
||||
pushCommand.setCredentialsProvider(myCredentialsProvider);
|
||||
|
||||
/*
|
||||
Need to push to remote NAME (to let push update the remote reference), but to probably another URL.
|
||||
So constructing RemoteConfig based on the original config for the remote, but with other url.
|
||||
No need in fetch urls => just removing them.
|
||||
Remove all push urls (we don't support pushing to multiple urls anyway yet), leaving only single correct url.
|
||||
Then pass the url to the push command.
|
||||
*/
|
||||
RemoteConfig rc = new RemoteConfig(myGit.getRepository().getConfig(), myRemoteName);
|
||||
List<URIish> uris = new ArrayList<URIish>(rc.getURIs());
|
||||
for (URIish uri : uris) {
|
||||
rc.removeURI(uri);
|
||||
}
|
||||
uris = new ArrayList<URIish>(rc.getPushURIs());
|
||||
for (URIish uri : uris) {
|
||||
rc.removePushURI(uri);
|
||||
}
|
||||
rc.addPushURI(new URIish(myUrl));
|
||||
|
||||
Iterable<PushResult> results = call(pushCommand, rc);
|
||||
myPushResult = analyzeResults(results);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUrl(@NotNull String url) {
|
||||
myUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUrl() {
|
||||
return myUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GitHttpCredentialsProvider getCredentialsProvider() {
|
||||
return myCredentialsProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogString() {
|
||||
return String.format("git push %s (%s) %s", myRemoteName, myUrl, GitHttpRemoteCommand.Fetch.getRefspecsAsString(myPushSpecs));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandString() {
|
||||
return String.format("git push %s %s", myRemoteName, GitHttpRemoteCommand.Fetch.getRefspecsAsString(myPushSpecs));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
GitSimplePushResult getResult() {
|
||||
return myPushResult;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static GitSimplePushResult analyzeResults(@NotNull Iterable<PushResult> results) {
|
||||
Collection<String> rejectedBranches = new ArrayList<String>();
|
||||
StringBuilder errorReport = new StringBuilder();
|
||||
|
||||
for (PushResult result : results) {
|
||||
for (RemoteRefUpdate update : result.getRemoteUpdates()) {
|
||||
switch (update.getStatus()) {
|
||||
case REJECTED_NONFASTFORWARD:
|
||||
rejectedBranches.add(update.getSrcRef());
|
||||
// no break: add reject to the output
|
||||
case NON_EXISTING:
|
||||
case REJECTED_NODELETE:
|
||||
case REJECTED_OTHER_REASON:
|
||||
case REJECTED_REMOTE_CHANGED:
|
||||
errorReport.append(update.getSrcRef() + ": " + update.getStatus() + "<br/>");
|
||||
default:
|
||||
// on success do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!rejectedBranches.isEmpty()) {
|
||||
return GitSimplePushResult.reject(rejectedBranches);
|
||||
}
|
||||
else if (errorReport.toString().isEmpty()) {
|
||||
return GitSimplePushResult.success();
|
||||
}
|
||||
else {
|
||||
return GitSimplePushResult.error(errorReport.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
A copy-paste from org.eclipse.jgit.api.PushCommand#call with the following differences:
|
||||
1. Fields are not accessible, so they are substituted by getters, except for credentialsProvider, which we have stored as an instance field.
|
||||
2. checkCallable() won't fail (according to the PushCommand code), so it's safe to remove it.
|
||||
3. Actual push is performed via
|
||||
Transport.openAll(repo, remoteConfig, Transport.Operation.PUSH)
|
||||
instead of
|
||||
Transport.openAll(repo, remote, Transport.Operation.PUSH)
|
||||
where remoteConfig is passed to the method.
|
||||
Original code constructs the remoteConfig based on .git/config.
|
||||
*/
|
||||
@NotNull
|
||||
private Iterable<PushResult> call(PushCommand pushCommand, RemoteConfig remoteConfig)
|
||||
throws JGitInternalException, InvalidRemoteException, org.eclipse.jgit.api.errors.TransportException
|
||||
{
|
||||
ArrayList<PushResult> pushResults = new ArrayList<PushResult>(3);
|
||||
|
||||
List<RefSpec> refSpecs = pushCommand.getRefSpecs();
|
||||
Repository repo = pushCommand.getRepository();
|
||||
boolean force = pushCommand.isForce();
|
||||
int timeout = pushCommand.getTimeout();
|
||||
CredentialsProvider credentialsProvider = myCredentialsProvider;
|
||||
String receivePack = pushCommand.getReceivePack();
|
||||
boolean thin = pushCommand.isThin();
|
||||
boolean dryRun = pushCommand.isDryRun();
|
||||
String remote = pushCommand.getRemote();
|
||||
ProgressMonitor monitor = pushCommand.getProgressMonitor();
|
||||
|
||||
try {
|
||||
if (refSpecs.isEmpty()) {
|
||||
RemoteConfig config = new RemoteConfig(repo.getConfig(), pushCommand.getRemote());
|
||||
refSpecs.addAll(config.getPushRefSpecs());
|
||||
}
|
||||
if (refSpecs.isEmpty()) {
|
||||
Ref head = repo.getRef(Constants.HEAD);
|
||||
if (head != null && head.isSymbolic()) {
|
||||
refSpecs.add(new RefSpec(head.getLeaf().getName()));
|
||||
}
|
||||
}
|
||||
|
||||
if (force) {
|
||||
for (int i = 0; i < refSpecs.size(); i++) {
|
||||
refSpecs.set(i, refSpecs.get(i).setForceUpdate(true));
|
||||
}
|
||||
}
|
||||
|
||||
final List<Transport> transports;
|
||||
transports = Transport.openAll(repo, remoteConfig, 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);
|
||||
}
|
||||
|
||||
final Collection<RemoteRefUpdate> toPush = transport
|
||||
.findRemoteRefUpdatesFor(refSpecs);
|
||||
|
||||
try {
|
||||
PushResult result = transport.push(monitor, toPush);
|
||||
pushResults.add(result);
|
||||
}
|
||||
catch (TransportException e) {
|
||||
throw new org.eclipse.jgit.api.errors.TransportException(e.getMessage(), e);
|
||||
}
|
||||
finally {
|
||||
transport.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (URISyntaxException e) {
|
||||
throw new InvalidRemoteException(MessageFormat.format(
|
||||
JGitText.get().invalidRemote, remote));
|
||||
} catch (TransportException e) {
|
||||
throw new org.eclipse.jgit.api.errors.TransportException(
|
||||
e.getMessage(), e);
|
||||
}
|
||||
catch (NotSupportedException e) {
|
||||
throw new JGitInternalException(
|
||||
JGitText.get().exceptionCaughtDuringExecutionOfPushCommand,
|
||||
e);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new JGitInternalException(
|
||||
JGitText.get().exceptionCaughtDuringExecutionOfPushCommand,
|
||||
e);
|
||||
}
|
||||
|
||||
return pushResults;
|
||||
}
|
||||
}
|
||||
|
||||
class LsRemote implements GitHttpRemoteCommand {
|
||||
|
||||
private final Git myGit;
|
||||
private final GitHttpCredentialsProvider myCredentialsProvider;
|
||||
private String myUrl;
|
||||
private Collection<Ref> myResultRefs;
|
||||
|
||||
public LsRemote(@NotNull Git git, @NotNull GitHttpCredentialsProvider credentialsProvider, @NotNull String url) {
|
||||
myGit = git;
|
||||
myCredentialsProvider = credentialsProvider;
|
||||
myUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() throws InvalidRemoteException, TransportException {
|
||||
myResultRefs = call();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public GitHttpCredentialsProvider getCredentialsProvider() {
|
||||
return myCredentialsProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogString() {
|
||||
return getCommandString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandString() {
|
||||
return String.format("git ls-remote --heads %s ", myUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUrl() {
|
||||
return myUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUrl(@NotNull String url) {
|
||||
myUrl = url;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<Ref> getRefs() {
|
||||
return myResultRefs == null ? Collections.<Ref>emptyList() : myResultRefs;
|
||||
}
|
||||
|
||||
/*
|
||||
Copy-paste of org.eclipse.jgit.api.LsRemote#call with the following changes:
|
||||
1. More specific exceptions declaration.
|
||||
2. Use CredentialsProvider.
|
||||
3. We don't need --tags, we always need --heads.
|
||||
*/
|
||||
private Collection<Ref> call() throws TransportException, InvalidRemoteException {
|
||||
try {
|
||||
Transport transport = Transport.open(myGit.getRepository(), myUrl);
|
||||
|
||||
try {
|
||||
Collection<RefSpec> refSpecs = new ArrayList<RefSpec>(1);
|
||||
refSpecs.add(new RefSpec("refs/heads/*:refs/remotes/origin/*"));
|
||||
Collection<Ref> refs;
|
||||
Map<String, Ref> refmap = new HashMap<String, Ref>();
|
||||
transport.setCredentialsProvider(myCredentialsProvider);
|
||||
FetchConnection fc = transport.openFetch();
|
||||
try {
|
||||
refs = fc.getRefs();
|
||||
if (refSpecs.isEmpty()) {
|
||||
for (Ref r : refs) {
|
||||
refmap.put(r.getName(), r);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (Ref r : refs) {
|
||||
for (RefSpec rs : refSpecs) {
|
||||
if (rs.matchSource(r)) {
|
||||
refmap.put(r.getName(), r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
fc.close();
|
||||
}
|
||||
return refmap.values();
|
||||
}
|
||||
catch (TransportException e) {
|
||||
throw new JGitInternalException(
|
||||
JGitText.get().exceptionCaughtDuringExecutionOfLsRemoteCommand,
|
||||
e);
|
||||
}
|
||||
finally {
|
||||
transport.close();
|
||||
}
|
||||
}
|
||||
catch (URISyntaxException e) {
|
||||
throw new InvalidRemoteException(MessageFormat.format(
|
||||
JGitText.get().invalidRemote, myUrl));
|
||||
}
|
||||
catch (NotSupportedException e) {
|
||||
throw new JGitInternalException(
|
||||
JGitText.get().exceptionCaughtDuringExecutionOfLsRemoteCommand,
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,6 @@ import git4idea.config.GitConfigUtil;
|
||||
import git4idea.config.GitVcsSettings;
|
||||
import git4idea.config.UpdateMethod;
|
||||
import git4idea.history.GitHistoryUtils;
|
||||
import git4idea.jgit.GitHttpAdapter;
|
||||
import git4idea.repo.GitBranchTrackInfo;
|
||||
import git4idea.repo.GitRemote;
|
||||
import git4idea.repo.GitRepository;
|
||||
@@ -321,13 +320,8 @@ public final class GitPusher {
|
||||
}
|
||||
String url = pushUrls.iterator().next();
|
||||
GitSimplePushResult pushResult;
|
||||
if (GitHttpAdapter.shouldUseJGit(url)) {
|
||||
pushResult = GitHttpAdapter.push(repository, remote.getName(), url, formPushSpec(pushSpec, remote));
|
||||
}
|
||||
else {
|
||||
pushResult = pushNatively(repository, pushSpec, url);
|
||||
}
|
||||
|
||||
pushResult = pushNatively(repository, pushSpec, url);
|
||||
|
||||
if (pushResult.getType() == GitSimplePushResult.Type.SUCCESS) {
|
||||
setUpstream(repository, pushSpec.getSource(), pushSpec.getRemote(), pushSpec.getDest());
|
||||
}
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package git4idea.jgit;
|
||||
package git4idea.remote;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.util.AuthData;
|
||||
@@ -21,7 +21,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Provides authentication information to the {@link GitHttpAdapter} on attempt to connect an HTTP remote.
|
||||
* Provides authentication information to the {@link git4idea.commands.GitHttpAuthenticator} on attempt to connect an HTTP remote.
|
||||
* Useful for reusing Github credentials stored in the settings to connect the github remote (IDEA-87530).
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
@@ -34,7 +34,6 @@ import git4idea.commands.Git;
|
||||
import git4idea.commands.GitCommandResult;
|
||||
import git4idea.commands.GitLineHandlerAdapter;
|
||||
import git4idea.commands.GitLineHandlerListener;
|
||||
import git4idea.jgit.GitHttpAdapter;
|
||||
import git4idea.repo.GitBranchTrackInfo;
|
||||
import git4idea.repo.GitRemote;
|
||||
import git4idea.repo.GitRepository;
|
||||
@@ -132,9 +131,6 @@ public class GitFetcher {
|
||||
@NotNull GitRemote remote,
|
||||
@NotNull String url,
|
||||
@Nullable String branch) {
|
||||
if (GitHttpAdapter.shouldUseJGit(url)) {
|
||||
return GitHttpAdapter.fetch(repository, remote, url, branch);
|
||||
}
|
||||
return fetchNatively(repository, remote, url, branch);
|
||||
}
|
||||
|
||||
@@ -150,9 +146,6 @@ public class GitFetcher {
|
||||
GitRemote remote = fetchParams.getRemote();
|
||||
String remoteBranch = fetchParams.getRemoteBranch().getNameForRemoteOperations();
|
||||
String url = fetchParams.getUrl();
|
||||
if (GitHttpAdapter.shouldUseJGit(url)) {
|
||||
return GitHttpAdapter.fetch(repository, remote, url, remoteBranch);
|
||||
}
|
||||
return fetchNatively(repository, remote, url, remoteBranch);
|
||||
}
|
||||
|
||||
@@ -191,22 +184,11 @@ public class GitFetcher {
|
||||
LOG.error("URL is null for remote " + remote.getName());
|
||||
continue;
|
||||
}
|
||||
if (GitHttpAdapter.shouldUseJGit(url)) {
|
||||
GitFetchResult res = GitHttpAdapter.fetch(repository, remote, url, null);
|
||||
res.addPruneInfo(fetchResult.getPrunedRefs());
|
||||
fetchResult = res;
|
||||
myErrors.addAll(fetchResult.getErrors());
|
||||
if (!fetchResult.isSuccess()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
GitFetchResult res = fetchNatively(repository, remote, url, null);
|
||||
res.addPruneInfo(fetchResult.getPrunedRefs());
|
||||
fetchResult = res;
|
||||
if (!fetchResult.isSuccess()) {
|
||||
break;
|
||||
}
|
||||
GitFetchResult res = fetchNatively(repository, remote, url, null);
|
||||
res.addPruneInfo(fetchResult.getPrunedRefs());
|
||||
fetchResult = res;
|
||||
if (!fetchResult.isSuccess()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return fetchResult;
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ package org.jetbrains.plugins.github.extensions;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.AuthData;
|
||||
import git4idea.jgit.GitHttpAuthDataProvider;
|
||||
import git4idea.remote.GitHttpAuthDataProvider;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.github.util.GithubAuthData;
|
||||
|
||||
Reference in New Issue
Block a user