mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[git] Reverting unfinished changes for push.
There are some problems there that can't be fixed soon, so we don't want this in release. This commit reverts the range 50a427639^..d81998d --author=Likhodedov
This commit is contained in:
@@ -251,12 +251,6 @@ public class QueueProcessor<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasPendingJobs() {
|
||||
synchronized (myQueue) {
|
||||
return !myQueue.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyOverrideEquals {
|
||||
private final Object myDelegate;
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
*/
|
||||
public class GitLogger {
|
||||
|
||||
public static final Logger CORE_LOG = Logger.getInstance("GitCore");
|
||||
public static final Logger PUSH_LOG = Logger.getInstance("GitPush");
|
||||
|
||||
}
|
||||
|
||||
@@ -15,74 +15,33 @@
|
||||
*/
|
||||
package git4idea.branch;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import git4idea.GitLocalBranch;
|
||||
import git4idea.GitLogger;
|
||||
import git4idea.GitRemoteBranch;
|
||||
import git4idea.repo.GitRepository;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Holder for a Git branch and the branch it is "connected" with.
|
||||
* Usually it is the tracked branch, but may any other (for example, when pushing to an alternative branch).
|
||||
* Holder for Git branch and the branch it is "connected" with. It is tracked branch or so called "matched" branch.
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class GitBranchPair {
|
||||
private @NotNull GitLocalBranch myBranch;
|
||||
private @Nullable GitRemoteBranch myDestBranch;
|
||||
|
||||
private static final Logger LOG = GitLogger.CORE_LOG;
|
||||
|
||||
@NotNull private GitLocalBranch mySource;
|
||||
@Nullable private GitRemoteBranch myDest;
|
||||
|
||||
public GitBranchPair(@NotNull GitLocalBranch source, @Nullable GitRemoteBranch destination) {
|
||||
mySource = source;
|
||||
myDest = destination;
|
||||
public GitBranchPair(@NotNull GitLocalBranch branch, @Nullable GitRemoteBranch destination) {
|
||||
myBranch = branch;
|
||||
myDestBranch = destination;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static GitBranchPair findCurrentAnTracked(@NotNull GitRepository repository) {
|
||||
repository.update();
|
||||
GitLocalBranch currentBranch = repository.getCurrentBranch();
|
||||
LOG.assertTrue(currentBranch != null, "Push shouldn't be available in the detached HEAD state");
|
||||
return new GitBranchPair(currentBranch, currentBranch.findTrackedBranch(repository));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public GitLocalBranch getSource() {
|
||||
return mySource;
|
||||
public GitLocalBranch getBranch() {
|
||||
return myBranch;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GitRemoteBranch getDest() {
|
||||
return myDest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String dest = myDest == null ? "nowhere" : myDest.getFullName();
|
||||
return mySource.getName() + "->" + dest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
GitBranchPair spec = (GitBranchPair)o;
|
||||
|
||||
if (myDest != null ? !myDest.equals(spec.myDest) : spec.myDest != null) return false;
|
||||
if (!mySource.equals(spec.mySource)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = mySource.hashCode();
|
||||
result = 31 * result + (myDest != null ? myDest.hashCode() : 0);
|
||||
return result;
|
||||
return myDestBranch;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ package git4idea.commands;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.branch.GitBranchPair;
|
||||
import git4idea.history.browser.GitCommit;
|
||||
import git4idea.push.GitPushSpec;
|
||||
import git4idea.repo.GitRepository;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -95,7 +95,7 @@ public interface Git {
|
||||
@NotNull GitLineHandlerListener... listeners);
|
||||
|
||||
@NotNull
|
||||
GitCommandResult push(@NotNull GitRepository repository, @NotNull GitBranchPair pushSpec,
|
||||
GitCommandResult push(@NotNull GitRepository repository, @NotNull GitPushSpec pushSpec,
|
||||
@NotNull GitLineHandlerListener... listeners);
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -25,9 +25,9 @@ import com.intellij.util.ExceptionUtil;
|
||||
import com.intellij.vcsUtil.VcsFileUtil;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.GitExecutionException;
|
||||
import git4idea.branch.GitBranchPair;
|
||||
import git4idea.history.GitHistoryUtils;
|
||||
import git4idea.history.browser.GitCommit;
|
||||
import git4idea.push.GitPushSpec;
|
||||
import git4idea.repo.GitRemote;
|
||||
import git4idea.repo.GitRepository;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -368,7 +368,7 @@ public class GitImpl implements Git {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public GitCommandResult push(@NotNull GitRepository repository, @NotNull GitBranchPair pushSpec,
|
||||
public GitCommandResult push(@NotNull GitRepository repository, @NotNull GitPushSpec pushSpec,
|
||||
@NotNull GitLineHandlerListener... listeners) {
|
||||
GitRemote remote = pushSpec.getDest().getRemote();
|
||||
GitBranch remoteBranch = pushSpec.getDest();
|
||||
|
||||
@@ -78,15 +78,12 @@ final class GitCommitsByBranch {
|
||||
return new GitCommitsByBranch(res);
|
||||
}
|
||||
|
||||
boolean hasAnythingToPush() {
|
||||
Collection<GitCommit> allCommits = new ArrayList<GitCommit>();
|
||||
for (GitPushBranchInfo info : myCommitsByBranch.values()) {
|
||||
if (info.getType() == GitPushBranchInfo.Type.NEW_BRANCH || info.getType() == GitPushBranchInfo.Type.NO_TRACKED_OR_TARGET) {
|
||||
return true;
|
||||
}
|
||||
allCommits.addAll(info.getCommits());
|
||||
@NotNull
|
||||
public Collection<GitCommit> getAllCommits() {
|
||||
Collection<GitCommit> commits = new ArrayList<GitCommit>();
|
||||
for (GitPushBranchInfo branchInfo : myCommitsByBranch.values()) {
|
||||
commits.addAll(branchInfo.getCommits());
|
||||
}
|
||||
return !allCommits.isEmpty();
|
||||
return commits;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,17 +15,19 @@
|
||||
*/
|
||||
package git4idea.push;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.actionSystem.impl.ActionButton;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.ui.ListCellRendererWrapper;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.ui.components.JBTextField;
|
||||
import com.intellij.util.ui.GridBag;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import git4idea.repo.GitRemote;
|
||||
import git4idea.repo.GitRepository;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import java.awt.*;
|
||||
import java.util.Collection;
|
||||
|
||||
@@ -36,6 +38,8 @@ class GitManualPushToBranch extends JPanel {
|
||||
|
||||
private final JTextField myDestBranchTextField;
|
||||
private final JBLabel myComment;
|
||||
private final GitPushLogRefreshAction myRefreshAction;
|
||||
private final JComponent myRefreshButton;
|
||||
private final RemoteSelector myRemoteSelector;
|
||||
private final JComponent myRemoteSelectorComponent;
|
||||
private boolean myMultiRepositoryProject;
|
||||
@@ -44,25 +48,20 @@ class GitManualPushToBranch extends JPanel {
|
||||
super();
|
||||
myMultiRepositoryProject = multiRepositoryProject;
|
||||
|
||||
myDestBranchTextField = new JBTextField(20);
|
||||
myDestBranchTextField.getDocument().addDocumentListener(new DocumentListener() {
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
performOnRefresh.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
performOnRefresh.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
performOnRefresh.run();
|
||||
}
|
||||
});
|
||||
myDestBranchTextField = new JTextField(20);
|
||||
|
||||
myComment = new JBLabel("This will apply to all selected repositories", UIUtil.ComponentStyle.SMALL);
|
||||
|
||||
myRefreshAction = new GitPushLogRefreshAction() {
|
||||
@Override public void actionPerformed(AnActionEvent e) {
|
||||
performOnRefresh.run();
|
||||
}
|
||||
};
|
||||
myRefreshButton = new ActionButton(myRefreshAction, myRefreshAction.getTemplatePresentation(), myRefreshAction.getTemplatePresentation().getText(), ActionToolbar.DEFAULT_MINIMUM_BUTTON_SIZE);
|
||||
myRefreshButton.setFocusable(true);
|
||||
final ShortcutSet shortcutSet = ActionManager.getInstance().getAction(IdeActions.ACTION_REFRESH).getShortcutSet();
|
||||
myRefreshAction.registerCustomShortcutSet(shortcutSet, myRefreshButton);
|
||||
|
||||
myRemoteSelector = new RemoteSelector();
|
||||
myRemoteSelectorComponent = myRemoteSelector.createComponent();
|
||||
|
||||
@@ -80,12 +79,11 @@ class GitManualPushToBranch extends JPanel {
|
||||
.setDefaultInsets(new Insets(0, 0, UIUtil.DEFAULT_VGAP, 5))
|
||||
;
|
||||
JLabel targetBranchLabel = new JBLabel("Target branch: ");
|
||||
targetBranchLabel.setDisplayedMnemonic('b');
|
||||
targetBranchLabel.setLabelFor(myDestBranchTextField);
|
||||
|
||||
panel.add(targetBranchLabel, g.nextLine().next());
|
||||
panel.add(myRemoteSelectorComponent, g.next());
|
||||
panel.add(myDestBranchTextField, g.next());
|
||||
panel.add(myRefreshButton, g.next());
|
||||
if (myMultiRepositoryProject) {
|
||||
panel.add(myComment, g.nextLine().insets(0, 0, 0, 0).coverLine());
|
||||
}
|
||||
@@ -160,4 +158,11 @@ class GitManualPushToBranch extends JPanel {
|
||||
|
||||
}
|
||||
|
||||
private abstract static class GitPushLogRefreshAction extends DumbAwareAction {
|
||||
|
||||
GitPushLogRefreshAction() {
|
||||
super("Refresh commit list", "Refresh commit list", AllIcons.Actions.Refresh);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,13 +15,12 @@
|
||||
*/
|
||||
package git4idea.push;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.concurrency.QueueProcessor;
|
||||
import git4idea.*;
|
||||
import git4idea.branch.GitBranchPair;
|
||||
import git4idea.history.GitHistoryUtils;
|
||||
@@ -36,13 +35,16 @@ import java.util.concurrent.TimeUnit;
|
||||
/**
|
||||
* Collects outgoing commits (commits to be pushed) for all repositories and holds this information.
|
||||
*
|
||||
* <p>The contract of the current implementation (probably, some or the limitations will be removed in the future):
|
||||
* <p>The contract of the current implementations (probably, some or the limitations will be removed in the future):
|
||||
* <ul>
|
||||
* <li>If you want to request outgoing commits (and force refresh, even if they were previously collected),
|
||||
* call {@link #collect(GitPushSpecs, ResultHandler)}. {@link GitPushDialog} should do it to get the up-to-date list of commits to push.</li>
|
||||
* <li>If you want just to get the list of outgoing commits, but not sure if the list is ready, call
|
||||
* {@link #waitForCompletionAndGetCommits()} and {@link #getCommits() get commits}.
|
||||
* It will collect commits if they were not collected yet.</li>
|
||||
* call {@link #collect(ResultHandler)}. {@link GitPushDialog} should do it to get the up-to-date list of commits to push.</li>
|
||||
* <li>If you want to get the list of outgoing commits, but not sure if the list is ready, call
|
||||
* {@link #waitForCompletionAndGetCommits(boolean)} and {@link #getCommits() get commits}.
|
||||
* It will collect commits if they were not collected yet. It won't refresh the list if
|
||||
* commits were collected, unless you specify the {@code refresh} parameter to it. <br/><br/>
|
||||
* The latter is needed, when pushing without opening a push dialog (Commit & Push and if this behavior is switched on in the
|
||||
* settings): otherwise we will get the list of commits requested by previous push dialog, which might be very out-of-date.</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
@@ -52,68 +54,99 @@ class GitOutgoingCommitsCollector {
|
||||
|
||||
private static final Logger LOG = GitLogger.PUSH_LOG;
|
||||
|
||||
@NotNull private final QueueProcessor<GitPushSpecs> myProcessor = new QueueProcessor<GitPushSpecs>(new Collector());
|
||||
@NotNull private final Project myProject;
|
||||
@NotNull private final GitPlatformFacade myPlatformFacade;
|
||||
|
||||
@NotNull private State myState;
|
||||
@NotNull private final Object STATE_LOCK = new Object();
|
||||
@NotNull private final Queue<ResultHandler> myResultHandlers = new ArrayDeque<ResultHandler>();
|
||||
@NotNull private final Queue<ResultHandler> completionHandlers = new ArrayDeque<ResultHandler>();
|
||||
private int refreshWaiters;
|
||||
|
||||
@NotNull private GitCommitsByRepoAndBranch myCommits = GitCommitsByRepoAndBranch.empty();
|
||||
@Nullable private String myError;
|
||||
|
||||
/**
|
||||
* Individual locks for threads which request {@link #waitForCompletionAndGetCommits()}.
|
||||
* Individual locks for threads which request {@link #waitForCompletionAndGetCommits(boolean)}.
|
||||
*/
|
||||
@NotNull private final ThreadLocal<Object> WAITER_LOCK = new ThreadLocal<Object>();
|
||||
|
||||
/**
|
||||
* Pass an instance of this handler to {@link #collect(GitPushSpecs, ResultHandler)}
|
||||
* to handle result when collecting of outgoing commits completes.
|
||||
* Pass an instance of this handler to {@link #collect(ResultHandler)} to handle result when collecting of outgoing commits completes.
|
||||
*/
|
||||
interface ResultHandler {
|
||||
void onSuccess(@NotNull GitCommitsByRepoAndBranch commits);
|
||||
void onError(@NotNull String error);
|
||||
void onSuccess(GitCommitsByRepoAndBranch commits);
|
||||
void onError(String error);
|
||||
}
|
||||
|
||||
private static final ResultHandler EMPTY_RESULT_HANDLER = new ResultHandler() {
|
||||
@Override
|
||||
public void onSuccess(@NotNull GitCommitsByRepoAndBranch commits) {
|
||||
public void onSuccess(GitCommitsByRepoAndBranch commits) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(@NotNull String error) {
|
||||
public void onError(String error) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Current state of the component.
|
||||
*/
|
||||
private enum State {
|
||||
EMPTY, // nothing was collected, need to load.
|
||||
BUSY, // currently loading, please wait.
|
||||
READY // everything loaded; refresh may be requested via the collect() method
|
||||
}
|
||||
|
||||
static GitOutgoingCommitsCollector getInstance(@NotNull Project project) {
|
||||
return ServiceManager.getService(project, GitOutgoingCommitsCollector.class);
|
||||
}
|
||||
|
||||
GitOutgoingCommitsCollector(@NotNull Project project, @NotNull GitPlatformFacade facade) {
|
||||
myProject = project;
|
||||
myPlatformFacade = facade;
|
||||
myState = State.EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect commits (if not yet collected) in background and invoke the given runnable after completion.
|
||||
* @param onComplete Executed after completed (successful or failed) execution of the task.
|
||||
* It is executed in the current thread, so if you need it on AWT, include "invokeLater" to the handler.
|
||||
*/
|
||||
void collect(@NotNull GitPushSpecs pushSpecs, @Nullable ResultHandler onComplete) {
|
||||
void collect(@Nullable ResultHandler onComplete) {
|
||||
synchronized (STATE_LOCK) {
|
||||
// if several collect requests go one by one, it is enough to have only one update: it will receive the up-to-date information.
|
||||
// so we are removing any other pending requests.
|
||||
myProcessor.clear();
|
||||
myProcessor.add(pushSpecs);
|
||||
if (myState == State.READY || myState == State.EMPTY) { // start initial collecting or refresh already collected info
|
||||
myState = State.BUSY;
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Updater());
|
||||
}
|
||||
else if (myState == State.BUSY) { // somebody already started collection => we request more up-to-date info afterwards.
|
||||
refreshWaiters++;
|
||||
}
|
||||
|
||||
// register the action that will be run after collection completes.
|
||||
// important to add at least a fake action not to break the order of [collection requested-execute post-action].
|
||||
myResultHandlers.offer(onComplete != null ? onComplete : EMPTY_RESULT_HANDLER);
|
||||
// important to add at least fake action not to break the order of [collection requested-execute post-action].
|
||||
completionHandlers.offer(onComplete != null ? onComplete : EMPTY_RESULT_HANDLER);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <ul>
|
||||
* <li>If collection has completed immediately returns.</li>
|
||||
* <li>If collection is in progress, waits for the completion.</li>
|
||||
* <li>If collection has completed, and no need to {@code refresh}, immediately returns.</li>
|
||||
* <li>If collection is in progress, waits for the completion.
|
||||
* But if {@code refresh} is needed, starts new completion to get up-to-date results.</li>
|
||||
* <li>If collection hasn't been started yet, starts it and waits for the completion.</li>
|
||||
* </ul>
|
||||
* @param refresh If the list of commits need to be re-queries even if we already have a version of it.
|
||||
*/
|
||||
@NotNull
|
||||
GitCommitsByRepoAndBranch waitForCompletionAndGetCommits() {
|
||||
GitCommitsByRepoAndBranch waitForCompletionAndGetCommits(boolean refresh) {
|
||||
// if nobody has initialized the collection yet, or we need up-to-date version suspecting that something might have changed,
|
||||
// then initialize collection.
|
||||
synchronized (STATE_LOCK) {
|
||||
if (myState == State.EMPTY || refresh) {
|
||||
collect(null); // makes State BUSY and starts collection
|
||||
}
|
||||
}
|
||||
|
||||
while (!isReady()) {
|
||||
try {
|
||||
synchronized (WAITER_LOCK) {
|
||||
@@ -130,7 +163,7 @@ class GitOutgoingCommitsCollector {
|
||||
|
||||
private boolean isReady() {
|
||||
synchronized (STATE_LOCK) {
|
||||
return myProcessor.isEmpty();
|
||||
return myState == State.READY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,7 +181,11 @@ class GitOutgoingCommitsCollector {
|
||||
}
|
||||
}
|
||||
|
||||
private void doCollect(@NotNull GitPushSpecs pushSpecs) {
|
||||
private boolean errorHappened() {
|
||||
return getError() != null;
|
||||
}
|
||||
|
||||
private void doCollect() {
|
||||
// currently we clear the collected information before each collect.
|
||||
// TODO Later we will persist it (providing in the Outgoing view) and update on push and other operations
|
||||
synchronized (STATE_LOCK) {
|
||||
@@ -157,7 +194,7 @@ class GitOutgoingCommitsCollector {
|
||||
}
|
||||
|
||||
try {
|
||||
GitCommitsByRepoAndBranch commits = collectOutgoingCommits(pushSpecs);
|
||||
GitCommitsByRepoAndBranch commits = collectOutgoingCommits(GitPushUtil.getSpecsToPushForAllRepositories(myPlatformFacade, myProject));
|
||||
synchronized (STATE_LOCK) {
|
||||
myCommits = commits;
|
||||
myError = null;
|
||||
@@ -175,9 +212,8 @@ class GitOutgoingCommitsCollector {
|
||||
if (handler == null) {
|
||||
return;
|
||||
}
|
||||
String error = getError();
|
||||
if (error != null) {
|
||||
handler.onError(error);
|
||||
if (errorHappened()) {
|
||||
handler.onError(getError());
|
||||
}
|
||||
else {
|
||||
handler.onSuccess(getCommits());
|
||||
@@ -185,25 +221,28 @@ class GitOutgoingCommitsCollector {
|
||||
}
|
||||
|
||||
// executed on a pooled thread
|
||||
private class Collector implements Consumer<GitPushSpecs> {
|
||||
|
||||
@Override
|
||||
public void consume(@NotNull GitPushSpecs pushSpecs) {
|
||||
doCollect(pushSpecs);
|
||||
private class Updater implements Runnable {
|
||||
public void run() {
|
||||
doCollect();
|
||||
synchronized (STATE_LOCK) {
|
||||
if (!myProcessor.hasPendingJobs()) {
|
||||
// when we are completely up-to-date, execute all remaining tasks
|
||||
while (!myResultHandlers.isEmpty()) {
|
||||
handleResult(myResultHandlers.poll());
|
||||
}
|
||||
if (refreshWaiters > 0) { // if collection was requested again, we need to refresh information
|
||||
refreshWaiters = 0; // but only once: we will get the up-to-date information anyway.
|
||||
|
||||
// execute the correspondent handler
|
||||
handleResult(completionHandlers.poll());
|
||||
|
||||
// queue the next update (in a separate thread to release the lock and return).
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Updater());
|
||||
}
|
||||
else {
|
||||
// execute only the correspondent handler
|
||||
handleResult(myResultHandlers.poll());
|
||||
myState = State.READY;
|
||||
// when we are completely up-to-date execute all remaining tasks
|
||||
while (!completionHandlers.isEmpty()) {
|
||||
handleResult(completionHandlers.poll());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************* ACTUAL COMMITS COLLECTION IS BELOW ********************************************************/
|
||||
@@ -220,7 +259,7 @@ class GitOutgoingCommitsCollector {
|
||||
}
|
||||
}
|
||||
|
||||
Map<GitRepository, List<GitBranchPair>> reposAndBranchesToPush = prepareReposAndBranchesToPush(pushSpecs.getAllSpecs());
|
||||
Map<GitRepository, List<GitBranchPair>> reposAndBranchesToPush = prepareReposAndBranchesToPush(pushSpecs.getSpecs());
|
||||
Set<GitRepository> repositories = reposAndBranchesToPush.keySet();
|
||||
|
||||
Map<GitRepository, GitCommitsByBranch> commitsByRepoAndBranch = new HashMap<GitRepository, GitCommitsByBranch>();
|
||||
@@ -236,13 +275,13 @@ class GitOutgoingCommitsCollector {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Map<GitRepository, List<GitBranchPair>> prepareReposAndBranchesToPush(@NotNull Map<GitRepository, GitBranchPair> pushSpecs)
|
||||
private static Map<GitRepository, List<GitBranchPair>> prepareReposAndBranchesToPush(@NotNull Map<GitRepository, GitPushSpec> pushSpecs)
|
||||
throws VcsException
|
||||
{
|
||||
Set<GitRepository> repositories = pushSpecs.keySet();
|
||||
Map<GitRepository, List<GitBranchPair>> res = new HashMap<GitRepository, List<GitBranchPair>>();
|
||||
for (GitRepository repository : repositories) {
|
||||
GitBranchPair pushSpec = pushSpecs.get(repository);
|
||||
GitPushSpec pushSpec = pushSpecs.get(repository);
|
||||
if (pushSpec == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -257,7 +296,7 @@ class GitOutgoingCommitsCollector {
|
||||
Map<GitBranch, GitPushBranchInfo> commitsByBranch = new HashMap<GitBranch, GitPushBranchInfo>();
|
||||
|
||||
for (GitBranchPair sourceDest : sourcesDestinations) {
|
||||
GitLocalBranch source = sourceDest.getSource();
|
||||
GitLocalBranch source = sourceDest.getBranch();
|
||||
GitRemoteBranch dest = sourceDest.getDest();
|
||||
|
||||
List<GitCommit> commits = Collections.emptyList();
|
||||
|
||||
@@ -23,11 +23,9 @@ import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.ui.components.JBLoadingPanel;
|
||||
import com.intellij.util.Consumer;
|
||||
import git4idea.*;
|
||||
import git4idea.branch.GitBranchPair;
|
||||
import git4idea.branch.GitBranchUtil;
|
||||
import git4idea.repo.GitRemote;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.settings.GitSyncRepoSetting;
|
||||
import git4idea.repo.GitRepositoryManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -44,9 +42,6 @@ public class GitPushDialog extends DialogWrapper {
|
||||
private static final Logger LOG = GitLogger.PUSH_LOG;
|
||||
private static final String DEFAULT_REMOTE = "origin";
|
||||
|
||||
@NotNull private final Collection<GitRepository> myAllRepositories;
|
||||
@NotNull private final Project myProject;
|
||||
@NotNull private final GitPlatformFacade myFacade;
|
||||
@NotNull private final GitPushSpecs myInitialPushSpecs;
|
||||
@NotNull private final GitOutgoingCommitsCollector myOutgoingCommitsCollector;
|
||||
|
||||
@@ -54,32 +49,29 @@ public class GitPushDialog extends DialogWrapper {
|
||||
@NotNull private final JBLoadingPanel myLoadingPanel;
|
||||
@NotNull private final GitManualPushToBranch myRefspecPanel;
|
||||
|
||||
public GitPushDialog(@NotNull Project project, @NotNull GitPlatformFacade facade, @NotNull GitPushSpecs pushSpecs) {
|
||||
public GitPushDialog(@NotNull Project project, @NotNull GitPushSpecs pushSpecs) {
|
||||
super(project);
|
||||
myProject = project;
|
||||
myFacade = facade;
|
||||
myInitialPushSpecs = pushSpecs;
|
||||
myAllRepositories = GitUtil.getRepositoryManager(project).getRepositories();
|
||||
GitRepositoryManager manager = GitUtil.getRepositoryManager(project);
|
||||
|
||||
Collection<GitRepository> repositories = myInitialPushSpecs.getRepositories();
|
||||
|
||||
myOutgoingCommitsCollector = GitOutgoingCommitsCollector.getInstance(project);
|
||||
|
||||
myLoadingPanel = new JBLoadingPanel(new BorderLayout(), this.getDisposable());
|
||||
|
||||
myListPanel = new GitPushLog(project, myAllRepositories, new RepositoryCheckboxListener());
|
||||
myRefspecPanel = new GitManualPushToBranch(myAllRepositories.size() > 1, new RefreshButtonListener());
|
||||
myListPanel = new GitPushLog(project, manager.getRepositories(), new RepositoryCheckboxListener());
|
||||
myRefspecPanel = new GitManualPushToBranch(repositories.size() > 1, new RefreshButtonListener());
|
||||
|
||||
init();
|
||||
setOKButtonText("Push");
|
||||
setOKButtonMnemonic('P');
|
||||
setTitle("Git Push");
|
||||
updateTargetBranchField();
|
||||
update();
|
||||
}
|
||||
|
||||
private void updateTargetBranchField() {
|
||||
private void update() {
|
||||
Collection<GitRepository> repositories = myListPanel.getSelectedRepositories();
|
||||
if (repositories == null) {
|
||||
repositories = myInitialPushSpecs.getSelectedRepositories();
|
||||
}
|
||||
Collection<GitRemote> commonRemotes = getRemotesWithCommonNames(repositories);
|
||||
myRefspecPanel.setRemotes(commonRemotes, getDefaultRemote(repositories));
|
||||
|
||||
@@ -166,6 +158,7 @@ public class GitPushDialog extends DialogWrapper {
|
||||
|
||||
private JComponent createCommitListPanel() {
|
||||
myLoadingPanel.add(myListPanel, BorderLayout.CENTER);
|
||||
loadCommitsInBackground(myInitialPushSpecs);
|
||||
|
||||
JPanel commitListPanel = new JPanel(new BorderLayout());
|
||||
commitListPanel.add(myLoadingPanel, BorderLayout.CENTER);
|
||||
@@ -175,20 +168,20 @@ public class GitPushDialog extends DialogWrapper {
|
||||
private void loadCommitsInBackground(final GitPushSpecs pushSpecs) {
|
||||
final ModalityState modalityState = ModalityState.stateForComponent(getRootPane());
|
||||
myLoadingPanel.startLoading();
|
||||
myOutgoingCommitsCollector.collect(pushSpecs, new GitOutgoingCommitsCollector.ResultHandler() {
|
||||
myOutgoingCommitsCollector.collect(new GitOutgoingCommitsCollector.ResultHandler() {
|
||||
@Override
|
||||
public void onSuccess(@NotNull final GitCommitsByRepoAndBranch commits) {
|
||||
public void onSuccess(final GitCommitsByRepoAndBranch commits) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myListPanel.setCommits(defaultRepository(), pushSpecs.getSelectedRepositories(), commits);
|
||||
myListPanel.setCommits(pushSpecs.getRepositories(), commits);
|
||||
myLoadingPanel.stopLoading();
|
||||
}
|
||||
}, modalityState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(@NotNull final String error) {
|
||||
public void onError(final String error) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -199,34 +192,15 @@ public class GitPushDialog extends DialogWrapper {
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private GitRepository defaultRepository() {
|
||||
GitSyncRepoSetting syncSetting = myFacade.getSettings(myProject).getSyncSetting();
|
||||
if (syncSetting.equals(GitSyncRepoSetting.SYNC)) {
|
||||
return null;
|
||||
}
|
||||
GitRepository currentRepository = GitBranchUtil.getCurrentRepository(myProject);
|
||||
if (currentRepository == null) {
|
||||
LOG.info("Couldn't identify current repository");
|
||||
}
|
||||
return currentRepository;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public GitPushSpecs getPushSpecs() {
|
||||
GitPushSpecs specs = new GitPushSpecs();
|
||||
for (GitRepository repository : myAllRepositories) {
|
||||
GitBranchPair spec = new GitBranchPair(repository.getCurrentBranch(), getTargetBranch()); // TODO what to do with detached head
|
||||
specs.put(repository, spec, isSelected(repository));
|
||||
}
|
||||
return specs;
|
||||
}
|
||||
|
||||
private boolean isSelected(@NotNull GitRepository repository) {
|
||||
Collection<GitRepository> selectedRepositories = myListPanel.getSelectedRepositories();
|
||||
return selectedRepositories != null
|
||||
? selectedRepositories.contains(repository)
|
||||
: myInitialPushSpecs.getSelectedRepositories().contains(repository);
|
||||
Map<GitRepository, GitPushSpec> specs = new HashMap<GitRepository, GitPushSpec>();
|
||||
for (GitRepository repository : selectedRepositories) {
|
||||
GitPushSpec spec = new GitPushSpec(repository.getCurrentBranch(), getTargetBranch()); // TODO what to do with detached head
|
||||
specs.put(repository, spec);
|
||||
}
|
||||
return new GitPushSpecs(specs);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -275,7 +249,7 @@ public class GitPushDialog extends DialogWrapper {
|
||||
|
||||
private class RepositoryCheckboxListener implements Consumer<Boolean> {
|
||||
@Override public void consume(Boolean checked) {
|
||||
updateTargetBranchField();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,6 @@ import git4idea.history.browser.GitCommit;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.util.GitUIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
@@ -159,12 +158,11 @@ class GitPushLog extends JPanel implements TypeSafeDataProvider {
|
||||
return myTree;
|
||||
}
|
||||
|
||||
void setCommits(@Nullable GitRepository defaultRepository, @NotNull Collection<GitRepository> selectedRepositories,
|
||||
@NotNull GitCommitsByRepoAndBranch commits) {
|
||||
void setCommits(Collection<GitRepository> selectedRepositories, @NotNull GitCommitsByRepoAndBranch commits) {
|
||||
try {
|
||||
TREE_CONSTRUCTION_LOCK.writeLock().lock();
|
||||
myRootNode.removeAllChildren();
|
||||
createNodes(defaultRepository, selectedRepositories, commits);
|
||||
createNodes(selectedRepositories, commits);
|
||||
myTreeModel.nodeStructureChanged(myRootNode);
|
||||
myTree.setModel(myTreeModel); // TODO: why doesn't it repaint otherwise?
|
||||
TreeUtil.expandAll(myTree);
|
||||
@@ -217,28 +215,19 @@ class GitPushLog extends JPanel implements TypeSafeDataProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private void createNodes(@Nullable GitRepository defaultRepository,
|
||||
@NotNull Collection<GitRepository> selectedRepositories,
|
||||
@NotNull GitCommitsByRepoAndBranch commits) {
|
||||
for (GitRepository repository : sortRepositories(defaultRepository, selectedRepositories, commits)) {
|
||||
private void createNodes(Collection<GitRepository> selectedRepositories, @NotNull GitCommitsByRepoAndBranch commits) {
|
||||
for (GitRepository repository : sortRepositories(selectedRepositories, commits)) {
|
||||
GitCommitsByBranch commitsByBranch = commits.get(repository);
|
||||
createRepoNode(repository, selectedRepositories.contains(repository), commitsByBranch, myRootNode);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<GitRepository> sortRepositories(@Nullable final GitRepository defaultRepository,
|
||||
@NotNull final Collection<GitRepository> selectedRepositories,
|
||||
private static List<GitRepository> sortRepositories(@NotNull final Collection<GitRepository> selectedRepositories,
|
||||
@NotNull final GitCommitsByRepoAndBranch commits) {
|
||||
List<GitRepository> repos = new ArrayList<GitRepository>(commits.getRepositories());
|
||||
Collections.sort(repos, new Comparator<GitRepository>() {
|
||||
@Override public int compare(GitRepository r1, GitRepository r2) {
|
||||
if (r1.equals(defaultRepository)) {
|
||||
return -1;
|
||||
}
|
||||
if (r2.equals(defaultRepository)) {
|
||||
return 1;
|
||||
}
|
||||
// deselected repositories - to the end
|
||||
if (selectedRepositories.contains(r1) && !selectedRepositories.contains(r2)) {
|
||||
return -1;
|
||||
@@ -313,10 +302,8 @@ class GitPushLog extends JPanel implements TypeSafeDataProvider {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return repositories selected (via checkboxes) to be pushed,
|
||||
* or null if the tree is not ready (therefore no repositories could be selected).
|
||||
* @return repositories selected (via checkboxes) to be pushed.
|
||||
*/
|
||||
@Nullable
|
||||
Collection<GitRepository> getSelectedRepositories() {
|
||||
if (myAllRepositories.size() == 1) {
|
||||
return myAllRepositories;
|
||||
@@ -325,12 +312,12 @@ class GitPushLog extends JPanel implements TypeSafeDataProvider {
|
||||
try {
|
||||
TREE_CONSTRUCTION_LOCK.readLock().lock(); // wait for tree to be constructed
|
||||
if (!myTreeWasConstructed) {
|
||||
return null;
|
||||
return myAllRepositories;
|
||||
}
|
||||
else {
|
||||
Collection<GitRepository> selectedRepositories = new ArrayList<GitRepository>(myAllRepositories.size());
|
||||
if (myRootNode.getChildCount() == 0) { // the method is requested before tree construction began
|
||||
return null;
|
||||
if (myRootNode.getChildCount() == 0) { // the method is requested before tree construction began => returning all repos.
|
||||
return myAllRepositories;
|
||||
}
|
||||
|
||||
for (int i = 0; i < myRootNode.getChildCount(); i++) {
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.push;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import git4idea.GitLocalBranch;
|
||||
import git4idea.GitLogger;
|
||||
import git4idea.GitRemoteBranch;
|
||||
import git4idea.repo.GitRepository;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class GitPushSpec {
|
||||
|
||||
private static final Logger LOG = GitLogger.PUSH_LOG;
|
||||
|
||||
@NotNull private final GitLocalBranch mySource;
|
||||
@Nullable private final GitRemoteBranch myDest;
|
||||
|
||||
@NotNull
|
||||
public static GitPushSpec collect(GitRepository repository) {
|
||||
repository.update();
|
||||
GitLocalBranch currentBranch = repository.getCurrentBranch();
|
||||
LOG.assertTrue(currentBranch != null, "Push shouldn't be available in the detached HEAD state");
|
||||
return new GitPushSpec(currentBranch, currentBranch.findTrackedBranch(repository));
|
||||
}
|
||||
|
||||
GitPushSpec(@NotNull GitLocalBranch source, @Nullable GitRemoteBranch dest) {
|
||||
myDest = dest;
|
||||
mySource = source;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public GitLocalBranch getSource() {
|
||||
return mySource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the destination branch: branch on the remote which the source branch will be pushed to.
|
||||
* @return destination branch or null if no destination branch has been defined (i. e. if there is no current branch, and no branch has
|
||||
* been defined via the Push dialog).
|
||||
*/
|
||||
@Nullable
|
||||
public GitRemoteBranch getDest() {
|
||||
return myDest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return mySource + "->" + myDest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
GitPushSpec spec = (GitPushSpec)o;
|
||||
|
||||
if (myDest != null ? !myDest.equals(spec.myDest) : spec.myDest != null) return false;
|
||||
if (!mySource.equals(spec.mySource)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = mySource.hashCode();
|
||||
result = 31 * result + (myDest != null ? myDest.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,71 +15,41 @@
|
||||
*/
|
||||
package git4idea.push;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Collections2;
|
||||
import git4idea.branch.GitBranchPair;
|
||||
import git4idea.repo.GitRepository;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>A container for push specs (source and target branches) per repository.</p>
|
||||
*
|
||||
* <p>We need GitPushSpecs for two operations:
|
||||
* <ul>
|
||||
* <li>to collect outgoing commits (in all repositories);</li>
|
||||
* <li>to push (in selected repositories).</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>That said, repositories that are not pushed, will have the parameter "selected" false.</p>
|
||||
* Just a container for {@link GitPushSpec} per repository.
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
class GitPushSpecs {
|
||||
|
||||
@NotNull private final Map<GitRepository, GitBranchPair> mySpecs;
|
||||
@NotNull private final Map<GitRepository, Boolean> mySelectedRepositories;
|
||||
@NotNull private final Map<GitRepository, GitPushSpec> mySpecs;
|
||||
|
||||
GitPushSpecs() {
|
||||
mySpecs = new HashMap<GitRepository, GitBranchPair>();
|
||||
mySelectedRepositories = new HashMap<GitRepository, Boolean>();
|
||||
}
|
||||
|
||||
static GitPushSpecs empty() {
|
||||
return new GitPushSpecs();
|
||||
GitPushSpecs(@NotNull Map<GitRepository, GitPushSpec> specs) {
|
||||
mySpecs = specs;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Map<GitRepository, GitBranchPair> getAllSpecs() {
|
||||
Collection<GitRepository> getRepositories() {
|
||||
return mySpecs.keySet();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Map<GitRepository, GitPushSpec> getSpecs() {
|
||||
return mySpecs;
|
||||
}
|
||||
|
||||
void put(@NotNull GitRepository repository, @NotNull GitBranchPair branchPair, boolean selected) {
|
||||
mySpecs.put(repository, branchPair);
|
||||
mySelectedRepositories.put(repository, selected);
|
||||
}
|
||||
|
||||
GitBranchPair get(@NotNull GitRepository repository) {
|
||||
GitPushSpec get(@NotNull GitRepository repository) {
|
||||
return mySpecs.get(repository);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<GitRepository> getSelectedRepositories() {
|
||||
return Collections2.filter(mySpecs.keySet(), new Predicate<GitRepository>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable GitRepository input) {
|
||||
assert input != null;
|
||||
return mySelectedRepositories.get(input);
|
||||
}
|
||||
});
|
||||
static GitPushSpecs empty() {
|
||||
return new GitPushSpecs(Collections.<GitRepository, GitPushSpec>emptyMap());
|
||||
}
|
||||
|
||||
public boolean isSelected(@NotNull GitRepository repository) {
|
||||
return mySelectedRepositories.get(repository);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,16 +17,18 @@ package git4idea.push;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import git4idea.GitLogger;
|
||||
import git4idea.GitPlatformFacade;
|
||||
import git4idea.branch.GitBranchPair;
|
||||
import git4idea.branch.GitBranchUtil;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.repo.GitRepositoryManager;
|
||||
import git4idea.settings.GitSyncRepoSetting;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Utilities specific to push.
|
||||
@@ -40,9 +42,8 @@ class GitPushUtil {
|
||||
@NotNull
|
||||
static GitPushSpecs getRepositoriesAndSpecsToPush(@NotNull GitPlatformFacade facade, @NotNull Project project) {
|
||||
GitSyncRepoSetting syncSetting = facade.getSettings(project).getSyncSetting();
|
||||
|
||||
if (syncSetting.equals(GitSyncRepoSetting.SYNC)) {
|
||||
return getSpecsForAllRepositories(facade, project, null);
|
||||
return getSpecsToPushForAllRepositories(facade, project);
|
||||
}
|
||||
else {
|
||||
if (facade.getRepositoryManager(project).moreThanOneRoot() && syncSetting.equals(GitSyncRepoSetting.NOT_DECIDED)) {
|
||||
@@ -50,21 +51,22 @@ class GitPushUtil {
|
||||
}
|
||||
GitRepository repository = GitBranchUtil.getCurrentRepository(project);
|
||||
if (repository == null) {
|
||||
LOG.info("Couldn't identify current repository");
|
||||
LOG.warn("Couldn't retrieve current repository");
|
||||
return GitPushSpecs.empty();
|
||||
}
|
||||
return getSpecsForAllRepositories(facade, project, repository);
|
||||
return new GitPushSpecs(Collections.singletonMap(repository, GitPushSpec.collect(repository)));
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static GitPushSpecs getSpecsForAllRepositories(@NotNull GitPlatformFacade facade, @NotNull Project project,
|
||||
@Nullable GitRepository selectedRepository) {
|
||||
List<GitRepository> repositories = facade.getRepositoryManager(project).getRepositories();
|
||||
GitPushSpecs specs = new GitPushSpecs();
|
||||
public static GitPushSpecs getSpecsToPushForAllRepositories(@NotNull GitPlatformFacade facade,
|
||||
@NotNull Project project) {
|
||||
GitRepositoryManager manager = facade.getRepositoryManager(project);
|
||||
List<GitRepository> repositories = manager.getRepositories();
|
||||
Map<GitRepository, GitPushSpec> map = new HashMap<GitRepository, GitPushSpec>();
|
||||
for (GitRepository repository : repositories) {
|
||||
boolean selected = selectedRepository == null || repository.equals(selectedRepository);
|
||||
specs.put(repository, GitBranchPair.findCurrentAnTracked(repository), selected);
|
||||
map.put(repository, GitPushSpec.collect(repository));
|
||||
}
|
||||
return specs;
|
||||
return new GitPushSpecs(map);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import com.intellij.openapi.vcs.update.UpdatedFiles;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import git4idea.*;
|
||||
import git4idea.branch.GitBranchPair;
|
||||
import git4idea.commands.Git;
|
||||
import git4idea.commands.GitCommandResult;
|
||||
import git4idea.config.GitConfigUtil;
|
||||
@@ -45,10 +44,7 @@ import git4idea.update.GitUpdateResult;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
@@ -82,7 +78,7 @@ public final class GitPusher {
|
||||
|
||||
public static void showPushDialogAndPerformPush(@NotNull Project project, @NotNull GitPlatformFacade facade) {
|
||||
GitPushSpecs repositoriesToPush = GitPushUtil.getRepositoriesAndSpecsToPush(facade, project);
|
||||
GitPushDialog dialog = new GitPushDialog(project, facade, repositoriesToPush);
|
||||
GitPushDialog dialog = new GitPushDialog(project, repositoriesToPush);
|
||||
dialog.show();
|
||||
if (dialog.isOK()) {
|
||||
runPushInBackground(project, facade, dialog.getPushSpecs());
|
||||
@@ -164,9 +160,9 @@ public final class GitPusher {
|
||||
private GitPushResult tryPushAndGetResult(@NotNull GitPushSpecs pushSpecs) {
|
||||
GitPushResult pushResult = new GitPushResult(myProject);
|
||||
|
||||
GitCommitsByRepoAndBranch commits = myOutgoingCommitsCollector.waitForCompletionAndGetCommits();
|
||||
for (GitRepository repository : pushSpecs.getSelectedRepositories()) {
|
||||
if (!commits.get(repository).hasAnythingToPush()) {
|
||||
GitCommitsByRepoAndBranch commits = myOutgoingCommitsCollector.waitForCompletionAndGetCommits(false);
|
||||
for (GitRepository repository : pushSpecs.getRepositories()) {
|
||||
if (commits.get(repository).getAllCommits().size() == 0) {
|
||||
// don't push repositories when we know that there is nothing to push.
|
||||
continue;
|
||||
}
|
||||
@@ -185,7 +181,7 @@ public final class GitPusher {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private GitPushRepoResult pushRepository(@NotNull GitBranchPair pushSpec,
|
||||
private GitPushRepoResult pushRepository(@NotNull GitPushSpec pushSpec,
|
||||
@NotNull GitRepository repository, @NotNull GitCommitsByRepoAndBranch commits) {
|
||||
GitSimplePushResult simplePushResult = pushAndGetSimpleResult(repository, pushSpec);
|
||||
String output = simplePushResult.getOutput();
|
||||
@@ -238,7 +234,7 @@ public final class GitPusher {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private GitSimplePushResult pushAndGetSimpleResult(@NotNull GitRepository repository, @NotNull GitBranchPair pushSpec) {
|
||||
private GitSimplePushResult pushAndGetSimpleResult(@NotNull GitRepository repository, @NotNull GitPushSpec pushSpec) {
|
||||
if (pushSpec.getDest() == NO_TARGET_BRANCH) {
|
||||
return GitSimplePushResult.notPushed();
|
||||
}
|
||||
@@ -304,7 +300,7 @@ public final class GitPusher {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String formPushSpec(@NotNull GitBranchPair spec, @NotNull GitRemote remote) {
|
||||
private static String formPushSpec(@NotNull GitPushSpec spec, @NotNull GitRemote remote) {
|
||||
String destWithRemote = spec.getDest().getName();
|
||||
String prefix = remote.getName() + "/";
|
||||
String destName;
|
||||
@@ -319,7 +315,7 @@ public final class GitPusher {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private GitSimplePushResult pushNatively(GitRepository repository, GitBranchPair pushSpec) {
|
||||
private GitSimplePushResult pushNatively(GitRepository repository, GitPushSpec pushSpec) {
|
||||
GitPushRejectedDetector rejectedDetector = new GitPushRejectedDetector();
|
||||
GitCommandResult res = myGit.push(repository, pushSpec, rejectedDetector);
|
||||
if (rejectedDetector.rejected()) {
|
||||
@@ -436,12 +432,11 @@ public final class GitPusher {
|
||||
|
||||
@NotNull
|
||||
private static GitPushSpecs retain(@NotNull GitPushSpecs initialSpecs, @NotNull Map<GitRepository, GitBranch> branchesToContinue) {
|
||||
GitPushSpecs specs = new GitPushSpecs();
|
||||
for (Map.Entry<GitRepository, GitBranchPair> entry : initialSpecs.getAllSpecs().entrySet()) {
|
||||
GitRepository repository = entry.getKey();
|
||||
specs.put(repository, entry.getValue(), initialSpecs.isSelected(repository) && branchesToContinue.keySet().contains(repository));
|
||||
Map<GitRepository, GitPushSpec> specs = new HashMap<GitRepository, GitPushSpec>();
|
||||
for (Map.Entry<GitRepository, GitBranch> entry : branchesToContinue.entrySet()) {
|
||||
specs.put(entry.getKey(), initialSpecs.get(entry.getKey()));
|
||||
}
|
||||
return specs;
|
||||
return new GitPushSpecs(specs);
|
||||
}
|
||||
|
||||
private void saveUpdateSettings(@NotNull UpdateSettings updateSettings) {
|
||||
|
||||
@@ -161,7 +161,7 @@ public class GitMergeUpdater extends GitUpdater {
|
||||
|
||||
// git log --name-status master..origin/master
|
||||
GitBranchPair gitBranchPair = myTrackedBranches.get(myRoot);
|
||||
String currentBranch = gitBranchPair.getSource().getName();
|
||||
String currentBranch = gitBranchPair.getBranch().getName();
|
||||
String remoteBranch = gitBranchPair.getDest().getName();
|
||||
try {
|
||||
GitRepository repository = GitUtil.getRepositoryManager(myProject).getRepositoryForRoot(myRoot);
|
||||
|
||||
@@ -107,7 +107,7 @@ public class GitRebaseUpdater extends GitUpdater {
|
||||
GitBranchPair gitBranchPair = myTrackedBranches.get(myRoot);
|
||||
GitBranch dest = gitBranchPair.getDest();
|
||||
LOG.assertTrue(dest != null, String.format("Destination branch is null for source branch %s in %s",
|
||||
gitBranchPair.getSource().getName(), myRoot));
|
||||
gitBranchPair.getBranch().getName(), myRoot));
|
||||
return dest.getName();
|
||||
}
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ public abstract class GitUpdater {
|
||||
*/
|
||||
public boolean isUpdateNeeded() throws VcsException {
|
||||
GitBranchPair gitBranchPair = myTrackedBranches.get(myRoot);
|
||||
String currentBranch = gitBranchPair.getSource().getName();
|
||||
String currentBranch = gitBranchPair.getBranch().getName();
|
||||
GitBranch dest = gitBranchPair.getDest();
|
||||
assert dest != null;
|
||||
String remoteBranch = dest.getName();
|
||||
|
||||
@@ -21,12 +21,12 @@ import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.openapi.vcs.VcsException
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import git4idea.branch.GitBranchPair
|
||||
import git4idea.commands.Git
|
||||
import git4idea.commands.GitCommandResult
|
||||
import git4idea.commands.GitImpl
|
||||
import git4idea.commands.GitLineHandlerListener
|
||||
import git4idea.history.browser.GitCommit
|
||||
import git4idea.push.GitPushSpec
|
||||
import git4idea.repo.GitRepository
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import org.jetbrains.annotations.Nullable
|
||||
@@ -180,7 +180,7 @@ public class GitTestImpl implements Git {
|
||||
@NotNull
|
||||
@Override
|
||||
public GitCommandResult push(@NotNull GitRepository repository,
|
||||
@NotNull GitBranchPair pushSpec,
|
||||
@NotNull GitPushSpec pushSpec,
|
||||
@NotNull GitLineHandlerListener... listeners) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@@ -19,11 +19,11 @@ import com.intellij.execution.process.ProcessOutputTypes
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.util.containers.hash.HashMap
|
||||
import git4idea.branch.GitBranchPair
|
||||
import git4idea.commands.Git
|
||||
import git4idea.commands.GitCommandResult
|
||||
import git4idea.commands.GitLineHandlerListener
|
||||
import git4idea.history.browser.GitCommit
|
||||
import git4idea.push.GitPushSpec
|
||||
import git4idea.repo.GitRepository
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import org.jetbrains.annotations.Nullable
|
||||
@@ -169,7 +169,7 @@ class MockGit implements Git {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
GitCommandResult push(@NotNull GitRepository repository, @NotNull GitBranchPair pushSpec, @NotNull GitLineHandlerListener... listeners) {
|
||||
GitCommandResult push(@NotNull GitRepository repository, @NotNull GitPushSpec pushSpec, @NotNull GitLineHandlerListener... listeners) {
|
||||
throw new UnsupportedOperationException()
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package git4idea.push
|
||||
|
||||
import git4idea.branch.GitBranchPair
|
||||
import git4idea.repo.GitRepository
|
||||
import git4idea.test.GitExecutor
|
||||
import git4idea.test.GitLightTest
|
||||
@@ -97,7 +96,7 @@ class GitPushSpecTest extends GitLightTest {
|
||||
}
|
||||
|
||||
void assertSpec(String local, String remote) {
|
||||
GitBranchPair spec = GitBranchPair.findCurrentAnTracked(myRepository)
|
||||
GitPushSpec spec = GitPushSpec.collect(myRepository)
|
||||
assertEquals("Incorrect local branch to push", local, spec.getSource().getName())
|
||||
if (remote != null) {
|
||||
assertEquals("Incorrect remote branch to push", remote, spec.getDest().getNameForLocalOperations())
|
||||
|
||||
Reference in New Issue
Block a user