mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[git] Use GitImpl for all remote commands
Relates to IDEA-98189.
This commit is contained in:
@@ -17,19 +17,20 @@ package git4idea.actions;
|
||||
|
||||
import com.intellij.history.Label;
|
||||
import com.intellij.history.LocalHistory;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.update.ActionInfo;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.GitRevisionNumber;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.commands.Git;
|
||||
import git4idea.commands.GitCommandResult;
|
||||
import git4idea.commands.GitLineHandler;
|
||||
import git4idea.commands.GitStandardProgressAnalyzer;
|
||||
import git4idea.commands.GitTask;
|
||||
import git4idea.commands.GitTaskResultHandlerAdapter;
|
||||
import git4idea.i18n.GitBundle;
|
||||
import git4idea.merge.GitMergeUtil;
|
||||
import git4idea.merge.GitPullDialog;
|
||||
@@ -68,7 +69,7 @@ public class GitPull extends GitRepositoryAction {
|
||||
new Task.Backgroundable(project, GitBundle.message("pulling.title", dialog.getRemote()), true) {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
final GitRepositoryManager repositoryManager = GitUtil.getRepositoryManager(myProject);
|
||||
final GitRepositoryManager repositoryManager = GitUtil.getRepositoryManager(project);
|
||||
|
||||
GitRepository repository = repositoryManager.getRepositoryForRoot(dialog.gitRoot());
|
||||
assert repository != null : "Repository can't be null for root " + dialog.gitRoot();
|
||||
@@ -76,13 +77,18 @@ public class GitPull extends GitRepositoryAction {
|
||||
|
||||
|
||||
GitRemote remote = GitUtil.findRemoteByName(repository, remoteOrUrl);
|
||||
String url = (remote == null) ? remoteOrUrl : remote.getFirstUrl();
|
||||
final String url = (remote == null) ? remoteOrUrl : remote.getFirstUrl();
|
||||
if (url == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final GitLineHandler handler = dialog.makeHandler(url);
|
||||
|
||||
final Git git = ServiceManager.getService(Git.class);
|
||||
GitCommandResult result = git.runRemoteCommand(new Computable<GitLineHandler>() {
|
||||
@Override
|
||||
public GitLineHandler compute() {
|
||||
return dialog.makeHandler(url);
|
||||
}
|
||||
});
|
||||
final VirtualFile root = dialog.gitRoot();
|
||||
affectedRoots.add(root);
|
||||
String revision = repository.getCurrentRevision();
|
||||
@@ -90,25 +96,16 @@ public class GitPull extends GitRepositoryAction {
|
||||
return;
|
||||
}
|
||||
final GitRevisionNumber currentRev = new GitRevisionNumber(revision);
|
||||
|
||||
GitTask pullTask = new GitTask(project, handler, GitBundle.message("pulling.title", dialog.getRemote()));
|
||||
pullTask.setProgressIndicator(indicator);
|
||||
pullTask.setProgressAnalyzer(new GitStandardProgressAnalyzer());
|
||||
pullTask.execute(true, false, new GitTaskResultHandlerAdapter() {
|
||||
@Override
|
||||
protected void onSuccess() {
|
||||
root.refresh(false, true);
|
||||
GitMergeUtil.showUpdates(GitPull.this, project, exceptions, root, currentRev, beforeLabel, getActionName(), ActionInfo.UPDATE);
|
||||
repositoryManager.updateRepository(root);
|
||||
runFinalTasks(project, GitVcs.getInstance(project), affectedRoots, getActionName(), exceptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailure() {
|
||||
GitUIUtil.notifyGitErrors(project, "Error pulling " + dialog.getRemote(), "", handler.errors());
|
||||
repositoryManager.updateRepository(root);
|
||||
}
|
||||
});
|
||||
if (result.success()) {
|
||||
root.refresh(false, true);
|
||||
GitMergeUtil.showUpdates(GitPull.this, project, exceptions, root, currentRev, beforeLabel, getActionName(), ActionInfo.UPDATE);
|
||||
repositoryManager.updateRepository(root);
|
||||
runFinalTasks(project, GitVcs.getInstance(project), affectedRoots, getActionName(), exceptions);
|
||||
}
|
||||
else {
|
||||
GitUIUtil.notifyError(project, "Error pulling " + dialog.getRemote(), result.getErrorOutputAsJoinedString(), true, null);
|
||||
repositoryManager.updateRepository(root);
|
||||
}
|
||||
}
|
||||
}.queue();
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
package git4idea.commands;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.GitCommit;
|
||||
import git4idea.history.browser.GitHeavyCommit;
|
||||
import git4idea.push.GitPushSpec;
|
||||
import git4idea.repo.GitRepository;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -35,6 +35,15 @@ import java.util.Set;
|
||||
*/
|
||||
public interface Git {
|
||||
|
||||
/**
|
||||
* A generic method to run a Git remote command, when existing methods like {@link #fetch(GitRepository, String, String, List, String...)}
|
||||
* are not sufficient.
|
||||
* @param handlerConstructor this is needed, since the operation may need to repeat (e.g. in case of authentication failure).
|
||||
* make sure to supply a stateless constructor.
|
||||
*/
|
||||
@NotNull
|
||||
GitCommandResult runRemoteCommand(@NotNull Computable<GitLineHandler> handlerConstructor);
|
||||
|
||||
@NotNull
|
||||
GitCommandResult init(@NotNull Project project, @NotNull VirtualFile root, @NotNull GitLineHandlerListener... listeners);
|
||||
|
||||
@@ -128,5 +137,6 @@ public interface Git {
|
||||
List<GitCommit> history(@NotNull GitRepository repository, @NotNull String range);
|
||||
|
||||
@NotNull
|
||||
GitCommandResult fetch(@NotNull GitRepository repository, @NotNull String url, @NotNull String remote, String... params);
|
||||
GitCommandResult fetch(@NotNull GitRepository repository, @NotNull String url, @NotNull String remote,
|
||||
@NotNull List<GitLineHandlerListener> listeners, String... params);
|
||||
}
|
||||
|
||||
@@ -85,4 +85,9 @@ public class GitCommandResult {
|
||||
public static GitCommandResult error(@NotNull String error) {
|
||||
return new GitCommandResult(false, 1, Collections.singletonList(error), Collections.<String>emptyList(), null);
|
||||
}
|
||||
|
||||
public boolean cancelled() {
|
||||
return false; // will be implemented later
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package git4idea.commands;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
@@ -25,6 +26,8 @@ import com.intellij.vcsUtil.VcsFileUtil;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.GitCommit;
|
||||
import git4idea.GitExecutionException;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.config.GitVersionSpecialty;
|
||||
import git4idea.history.GitHistoryUtils;
|
||||
import git4idea.push.GitPushSpec;
|
||||
import git4idea.repo.GitRemote;
|
||||
@@ -362,21 +365,27 @@ public class GitImpl implements Git {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public GitCommandResult push(@NotNull GitRepository repository, @NotNull String remote, @NotNull String url, @NotNull String spec,
|
||||
boolean updateTracking, @NotNull GitLineHandlerListener... listeners) {
|
||||
final GitLineHandlerPasswordRequestAware h = new GitLineHandlerPasswordRequestAware(repository.getProject(), repository.getRoot(),
|
||||
GitCommand.PUSH);
|
||||
h.setUrl(url);
|
||||
h.setSilent(false);
|
||||
h.setStdoutSuppressed(false);
|
||||
addListeners(h, listeners);
|
||||
h.addProgressParameter();
|
||||
h.addParameters(remote);
|
||||
h.addParameters(spec);
|
||||
if (updateTracking) {
|
||||
h.addParameters("--set-upstream");
|
||||
}
|
||||
return run(h);
|
||||
public GitCommandResult push(@NotNull final GitRepository repository, @NotNull final String remote, @NotNull final String url,
|
||||
@NotNull final String spec, final boolean updateTracking,
|
||||
@NotNull final GitLineHandlerListener... listeners) {
|
||||
return runRemoteCommand(new Computable<GitLineHandler>() {
|
||||
@Override
|
||||
public GitLineHandler compute() {
|
||||
final GitLineHandlerPasswordRequestAware h = new GitLineHandlerPasswordRequestAware(repository.getProject(), repository.getRoot(),
|
||||
GitCommand.PUSH);
|
||||
h.setUrl(url);
|
||||
h.setSilent(false);
|
||||
h.setStdoutSuppressed(false);
|
||||
addListeners(h, listeners);
|
||||
h.addProgressParameter();
|
||||
h.addParameters(remote);
|
||||
h.addParameters(spec);
|
||||
if (updateTracking) {
|
||||
h.addParameters("--set-upstream");
|
||||
}
|
||||
return h;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -435,32 +444,46 @@ public class GitImpl implements Git {
|
||||
*/
|
||||
@Override
|
||||
@NotNull
|
||||
public GitCommandResult fetch(@NotNull GitRepository repository, @NotNull String url, @NotNull String remote, String... params) {
|
||||
final GitLineHandlerPasswordRequestAware h =
|
||||
new GitLineHandlerPasswordRequestAware(repository.getProject(), repository.getRoot(), GitCommand.FETCH);
|
||||
h.setUrl(url);
|
||||
h.addParameters(remote);
|
||||
h.addParameters(params);
|
||||
h.addProgressParameter();
|
||||
return run(h);
|
||||
public GitCommandResult fetch(@NotNull final GitRepository repository, @NotNull final String url, @NotNull final String remote,
|
||||
@NotNull final List<GitLineHandlerListener> listeners, final String... params) {
|
||||
return runRemoteCommand(new Computable<GitLineHandler>() {
|
||||
@Override
|
||||
public GitLineHandler compute() {
|
||||
final GitLineHandlerPasswordRequestAware h = new GitLineHandlerPasswordRequestAware(repository.getProject(), repository.getRoot(),
|
||||
GitCommand.FETCH);
|
||||
h.setUrl(url);
|
||||
h.addParameters(remote);
|
||||
h.addParameters(params);
|
||||
h.addProgressParameter();
|
||||
GitVcs vcs = GitVcs.getInstance(repository.getProject());
|
||||
if (vcs != null && GitVersionSpecialty.SUPPORTS_FETCH_PRUNE.existsIn(vcs.getVersion())) {
|
||||
h.addParameters("--prune");
|
||||
}
|
||||
addListeners(h, listeners);
|
||||
return h;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void addListeners(@NotNull GitLineHandler handler, @NotNull GitLineHandlerListener... listeners) {
|
||||
addListeners(handler, Arrays.asList(listeners));
|
||||
}
|
||||
|
||||
private static void addListeners(@NotNull GitLineHandler handler, @NotNull List<GitLineHandlerListener> listeners) {
|
||||
for (GitLineHandlerListener listener : listeners) {
|
||||
handler.addLineListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the given {@link GitLineHandler} in the current thread and returns the {@link GitCommandResult}.
|
||||
*/
|
||||
private static GitCommandResult run(@NotNull GitLineHandler handler) {
|
||||
@NotNull
|
||||
private static GitCommandResult run(@NotNull Computable<GitLineHandler> handlerConstructor) {
|
||||
final List<String> errorOutput = new ArrayList<String>();
|
||||
final List<String> output = new ArrayList<String>();
|
||||
final AtomicInteger exitCode = new AtomicInteger();
|
||||
final AtomicBoolean startFailed = new AtomicBoolean();
|
||||
final AtomicReference<Throwable> exception = new AtomicReference<Throwable>();
|
||||
|
||||
|
||||
GitLineHandler handler = handlerConstructor.compute();
|
||||
handler.addLineListener(new GitLineHandlerListener() {
|
||||
@Override public void onLineAvailable(String line, Key outputType) {
|
||||
if (isError(line)) {
|
||||
@@ -480,7 +503,7 @@ public class GitImpl implements Git {
|
||||
exception.set(t);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
handler.runInCurrentThread(null);
|
||||
|
||||
if (handler instanceof GitLineHandlerPasswordRequestAware && ((GitLineHandlerPasswordRequestAware)handler).hadAuthRequest()) {
|
||||
@@ -491,6 +514,20 @@ public class GitImpl implements Git {
|
||||
(handler.isIgnoredErrorCode(exitCode.get()) || exitCode.get() == 0);
|
||||
return new GitCommandResult(success, exitCode.get(), errorOutput, output, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the given {@link GitLineHandler} in the current thread and returns the {@link GitCommandResult}.
|
||||
*/
|
||||
@NotNull
|
||||
private static GitCommandResult run(@NotNull GitLineHandler handler) {
|
||||
return run(new Computable.PredefinedValueComputable<GitLineHandler>(handler));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public GitCommandResult runRemoteCommand(@NotNull Computable<GitLineHandler> handlerConstructor) {
|
||||
return run(handlerConstructor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the line looks line an error message
|
||||
|
||||
@@ -16,21 +16,24 @@
|
||||
package git4idea.update;
|
||||
|
||||
import com.intellij.dvcs.DvcsUtil;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.VcsNotifier;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import git4idea.GitLocalBranch;
|
||||
import git4idea.GitRemoteBranch;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.branch.GitBranchUtil;
|
||||
import git4idea.commands.*;
|
||||
import git4idea.config.GitVersionSpecialty;
|
||||
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;
|
||||
@@ -40,11 +43,7 @@ import git4idea.util.GitUIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -136,7 +135,7 @@ public class GitFetcher {
|
||||
if (GitHttpAdapter.shouldUseJGit(url)) {
|
||||
return GitHttpAdapter.fetch(repository, remote, url, branch);
|
||||
}
|
||||
return fetchNatively(repository.getRoot(), remote, url, branch);
|
||||
return fetchNatively(repository, remote, url, branch);
|
||||
}
|
||||
|
||||
// leaving this unused method, because the wanted behavior can change again
|
||||
@@ -154,7 +153,7 @@ public class GitFetcher {
|
||||
if (GitHttpAdapter.shouldUseJGit(url)) {
|
||||
return GitHttpAdapter.fetch(repository, remote, url, remoteBranch);
|
||||
}
|
||||
return fetchNatively(repository.getRoot(), remote, url, remoteBranch);
|
||||
return fetchNatively(repository, remote, url, remoteBranch);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -202,7 +201,7 @@ public class GitFetcher {
|
||||
}
|
||||
}
|
||||
else {
|
||||
GitFetchResult res = fetchNatively(repository.getRoot(), remote, url, null);
|
||||
GitFetchResult res = fetchNatively(repository, remote, url, null);
|
||||
res.addPruneInfo(fetchResult.getPrunedRefs());
|
||||
fetchResult = res;
|
||||
if (!fetchResult.isSuccess()) {
|
||||
@@ -213,54 +212,30 @@ public class GitFetcher {
|
||||
return fetchResult;
|
||||
}
|
||||
|
||||
private GitFetchResult fetchNatively(@NotNull VirtualFile root, @NotNull GitRemote remote, @NotNull String url, @Nullable String branch) {
|
||||
final GitLineHandlerPasswordRequestAware h = new GitLineHandlerPasswordRequestAware(myProject, root, GitCommand.FETCH);
|
||||
h.setUrl(url);
|
||||
h.addProgressParameter();
|
||||
if (GitVersionSpecialty.SUPPORTS_FETCH_PRUNE.existsIn(myVcs.getVersion())) {
|
||||
h.addParameters("--prune");
|
||||
}
|
||||
|
||||
String remoteName = remote.getName();
|
||||
h.addParameters(remoteName);
|
||||
if (branch != null) {
|
||||
h.addParameters(getFetchSpecForBranch(branch, remoteName));
|
||||
}
|
||||
|
||||
final GitTask fetchTask = new GitTask(myProject, h, "Fetching " + remote.getFirstUrl());
|
||||
fetchTask.setProgressIndicator(myProgressIndicator);
|
||||
fetchTask.setProgressAnalyzer(new GitStandardProgressAnalyzer());
|
||||
@NotNull
|
||||
private static GitFetchResult fetchNatively(@NotNull GitRepository repository, @NotNull GitRemote remote, @NotNull String url,
|
||||
@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();
|
||||
h.addLineListener(pruneDetector);
|
||||
GitCommandResult result =
|
||||
git.fetch(repository, url, remote.getName(), Collections.<GitLineHandlerListener>singletonList(pruneDetector), additionalParams);
|
||||
|
||||
final AtomicReference<GitFetchResult> result = new AtomicReference<GitFetchResult>();
|
||||
fetchTask.execute(true, false, new GitTaskResultHandlerAdapter() {
|
||||
@Override
|
||||
protected void onSuccess() {
|
||||
result.set(GitFetchResult.success());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCancel() {
|
||||
LOG.info("Cancelled fetch.");
|
||||
result.set(GitFetchResult.cancel());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailure() {
|
||||
LOG.info("Error fetching: " + h.errors());
|
||||
if (!h.hadAuthRequest()) {
|
||||
myErrors.addAll(h.errors());
|
||||
} else {
|
||||
myErrors.add(new VcsException("Authentication failed"));
|
||||
}
|
||||
result.set(GitFetchResult.error(myErrors));
|
||||
}
|
||||
});
|
||||
|
||||
result.get().addPruneInfo(pruneDetector.getPrunedRefs());
|
||||
return result.get();
|
||||
GitFetchResult fetchResult;
|
||||
if (result.success()) {
|
||||
fetchResult = GitFetchResult.success();
|
||||
}
|
||||
else if (result.cancelled()) {
|
||||
fetchResult = GitFetchResult.cancel();
|
||||
}
|
||||
else {
|
||||
fetchResult = GitFetchResult.error(result.getErrorOutputAsJoinedString());
|
||||
}
|
||||
fetchResult.addPruneInfo(pruneDetector.getPrunedRefs());
|
||||
return fetchResult;
|
||||
}
|
||||
|
||||
private static String getRidOfPrefixIfExists(String branch) {
|
||||
|
||||
@@ -99,8 +99,7 @@ public class GitUIUtil {
|
||||
}
|
||||
|
||||
public static void notifyError(Project project, String title, String description, boolean important, @Nullable Exception error) {
|
||||
notifyMessage(
|
||||
project, title, description, important, Collections.singleton(error));
|
||||
notifyMessage(project, title, description, important, error == null ? null : Collections.singleton(error));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -40,8 +40,6 @@ import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.openapi.util.text.StringUtil.join;
|
||||
import static git4idea.test.GitExecutor.cd;
|
||||
import static git4idea.test.GitExecutor.git;
|
||||
import static java.lang.String.format;
|
||||
|
||||
/**
|
||||
@@ -227,7 +225,8 @@ public class GitTestImpl implements Git {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public GitCommandResult fetch(@NotNull GitRepository repository, @NotNull String url, @NotNull String remote, String... params) {
|
||||
public GitCommandResult fetch(@NotNull GitRepository repository, @NotNull String url, @NotNull String remote,
|
||||
@NotNull List<GitLineHandlerListener> listeners, String... params) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user