summaryrefslogtreecommitdiff
path: root/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java
diff options
context:
space:
mode:
Diffstat (limited to 'platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java')
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java184
1 files changed, 120 insertions, 64 deletions
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java
index 2a409e12c854..45f5c68e1d0a 100644
--- a/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java
@@ -29,8 +29,11 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ValidationInfo;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.ui.CheckedTreeNode;
+import com.intellij.ui.SimpleColoredText;
+import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.hash.HashMap;
@@ -38,7 +41,6 @@ import com.intellij.vcs.log.VcsFullCommitDetails;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@@ -48,15 +50,15 @@ import java.util.concurrent.atomic.AtomicReference;
public class PushController implements Disposable {
@NotNull private final Project myProject;
- @NotNull private final List<PushSupport<? extends Repository>> myPushSupports;
+ @NotNull private final List<PushSupport<? extends Repository, ? extends PushSource, ? extends PushTarget>> myPushSupports;
@NotNull private final PushLog myPushLog;
@NotNull private final VcsPushDialog myDialog;
private boolean mySingleRepoProject;
private static final int DEFAULT_CHILDREN_PRESENTATION_NUMBER = 20;
private final Map<PushSupport, MyPushOptionValueModel> myAdditionalValuesMap;
- private final Map<RepositoryNode, MyRepoModel> myView2Model = new HashMap<RepositoryNode, MyRepoModel>();
-
+ private final Map<RepositoryNode, MyRepoModel> myView2Model = new TreeMap<RepositoryNode, MyRepoModel>();
+ //todo need to sort repositories in ui tree using natural order
public PushController(@NotNull Project project,
@NotNull VcsPushDialog dialog,
@@ -72,6 +74,20 @@ public class PushController implements Disposable {
myDialog.updateButtons();
startLoadingCommits();
Disposer.register(dialog.getDisposable(), this);
+ selectFirstChecked();
+ }
+
+ private void selectFirstChecked() {
+ Map.Entry<RepositoryNode, MyRepoModel> selected =
+ ContainerUtil.find(myView2Model.entrySet(), new Condition<Map.Entry<RepositoryNode, MyRepoModel>>() {
+ @Override
+ public boolean value(Map.Entry<RepositoryNode, MyRepoModel> entry) {
+ return entry.getValue().isSelected();
+ }
+ });
+ if (selected != null) {
+ myPushLog.selectNode(selected.getKey());
+ }
}
@Nullable
@@ -80,16 +96,8 @@ public class PushController implements Disposable {
for (Map.Entry<RepositoryNode, MyRepoModel> entry : myView2Model.entrySet()) {
MyRepoModel model = entry.getValue();
if (model.isSelected()) {
- //has one or more selected roots
+ if (model.hasError()) return new ValidationInfo(model.getError().getText());
validInfo = null;
- RepositoryNode node = entry.getKey();
- PushTarget target = model.getSpec().getTarget();
- //todo add validation for model -> hasErrors, too
- if (target == null) {
- JComponent editingComponent = myPushLog.startEditNode(node);
- return new ValidationInfo("Invalid remote for repository " + DvcsUtil.getShortRepositoryName(model.getRepository()),
- editingComponent);
- }
}
}
return validInfo;
@@ -123,36 +131,44 @@ public class PushController implements Disposable {
private boolean createTreeModel(@NotNull CheckedTreeNode rootNode, @NotNull List<? extends Repository> preselectedRepositories) {
if (myPushSupports.isEmpty()) return true;
int repoCount = 0;
- for (PushSupport<? extends Repository> support : myPushSupports) {
+ for (PushSupport<? extends Repository, ? extends PushSource, ? extends PushTarget> support : myPushSupports) {
repoCount += createNodesForVcs(support, rootNode, preselectedRepositories);
}
return repoCount == 1;
}
- private <T extends Repository> int createNodesForVcs(@NotNull PushSupport<T> pushSupport,
- @NotNull CheckedTreeNode rootNode,
- @NotNull List<? extends Repository> preselectedRepositories) {
- RepositoryManager<T> repositoryManager = pushSupport.getRepositoryManager();
- List<T> repositories = repositoryManager.getRepositories();
- for (T repository : repositories) {
+ private <R extends Repository, S extends PushSource, T extends PushTarget> int createNodesForVcs(
+ @NotNull PushSupport<R, S, T> pushSupport,
+ @NotNull CheckedTreeNode rootNode,
+ @NotNull List<? extends Repository> preselectedRepositories) {
+ RepositoryManager<R> repositoryManager = pushSupport.getRepositoryManager();
+ List<R> repositories = repositoryManager.getRepositories();
+ for (R repository : repositories) {
createRepoNode(pushSupport, repository, rootNode, preselectedRepositories.contains(repository), repositories.size() == 1);
}
return repositories.size();
}
- private <T extends Repository> void createRepoNode(@NotNull final PushSupport<T> support,
- @NotNull final T repository,
- @NotNull CheckedTreeNode rootNode,
- boolean isSelected,
- boolean isSingleRepositoryProject) {
- PushTarget target = support.getDefaultTarget(repository);
- final MyRepoModel model = new MyRepoModel(repository, support, isSelected, new PushSpec(support.getSource(repository), target),
- DEFAULT_CHILDREN_PRESENTATION_NUMBER);
- RepositoryWithBranchPanel repoPanel = new RepositoryWithBranchPanel(myProject, DvcsUtil.getShortRepositoryName(repository),
+ private <R extends Repository, S extends PushSource, T extends PushTarget> void createRepoNode(@NotNull final PushSupport<R, S, T> support,
+ @NotNull final R repository,
+ @NotNull CheckedTreeNode rootNode,
+ boolean isSelected,
+ boolean isSingleRepositoryProject) {
+ T target = support.getDefaultTarget(repository);
+ String repoName = DvcsUtil.getShortRepositoryName(repository);
+ final MyRepoModel<R, S, T> model = new MyRepoModel<R, S, T>(repository, support, isSingleRepositoryProject || isSelected,
+ support.getSource(repository), target,
+ DEFAULT_CHILDREN_PRESENTATION_NUMBER);
+ if (target == null) {
+ model.setError(VcsError.createEmptyTargetError(repoName));
+ }
+ RepositoryWithBranchPanel repoPanel = new RepositoryWithBranchPanel(myProject, repoName,
support.getSource(repository).getPresentation(),
target == null ? "" : target.getPresentation(),
support.getTargetNames(repository));
- final RepositoryNode repoNode = isSingleRepositoryProject ? new SingleRepositoryNode(repoPanel) : new RepositoryNode(repoPanel);
+ final RepositoryNode repoNode = isSingleRepositoryProject
+ ? new SingleRepositoryNode(repoPanel, support.renderTarget(target))
+ : new RepositoryNode(repoPanel, support.renderTarget(target));
myView2Model.put(repoNode, model);
repoNode.setChecked(model.isSelected());
repoPanel.addRepoNodeListener(new RepositoryNodeListener() {
@@ -160,19 +176,25 @@ public class PushController implements Disposable {
public void onTargetChanged(String newValue) {
VcsError validationError = support.validate(model.getRepository(), newValue);
if (validationError == null) {
- myView2Model.get(repoNode).setSpec(new PushSpec(model.getSpec().getSource(), support.createTarget(repository, newValue)));
+ T newTarget = support.createTarget(repository, newValue);
+ repoNode.setTargetPresentation(support.renderTarget(newTarget));
+ model.setTarget(newTarget);
+ model.clearErrors();
loadCommits(model, repoNode, false);
}
else {
- //todo may be should store validation errors in model and get errors during dialog validation
- myView2Model.get(repoNode).setSpec(new PushSpec(model.getSpec().getSource(), null));
+ repoNode.setTargetPresentation(StringUtil.isEmptyOrSpaces(newValue)
+ ? support.renderTarget(null)
+ : new SimpleColoredText(newValue, SimpleTextAttributes.ERROR_ATTRIBUTES));
+ model.setError(validationError); // todo may be should accept and store errors collection, now store one major target error
+ model.setTarget(null);
}
myDialog.updateButtons();
}
@Override
public void onSelectionChanged(boolean isSelected) {
- myView2Model.get(repoNode).setSelected(isSelected);
+ model.setSelected(isSelected);
repoNode.setChecked(isSelected);
myDialog.updateButtons();
}
@@ -180,13 +202,15 @@ public class PushController implements Disposable {
rootNode.add(repoNode);
}
- private void loadCommits(@NotNull final MyRepoModel model,
- @NotNull final RepositoryNode node,
- final boolean initial) {
+ private <R extends Repository, S extends PushSource, T extends PushTarget> void loadCommits(@NotNull final MyRepoModel<R, S, T> model,
+ @NotNull final RepositoryNode node,
+ final boolean initial) {
node.stopLoading();
+ final T target = model.getTarget();
+ if (target == null) return; //todo should be removed when commit loader executor will be modified
myPushLog.startLoading(node);
final ProgressIndicator indicator = node.startLoading();
- final PushSupport support = model.getSupport();
+ final PushSupport<R, S, T> support = model.getSupport();
final AtomicReference<OutgoingResult> result = new AtomicReference<OutgoingResult>();
Task.Backgroundable task = new Task.Backgroundable(myProject, "Loading Commits", true) {
@@ -229,7 +253,7 @@ public class PushController implements Disposable {
@Override
public void run(@NotNull ProgressIndicator indicator) {
OutgoingResult outgoing = support.getOutgoingCommitsProvider()
- .getOutgoingCommits(model.getRepository(), model.getSpec(), initial);
+ .getOutgoingCommits(model.getRepository(), new PushSpec<S, T>(model.getSource(), model.getTarget()), initial);
result.compareAndSet(null, outgoing);
}
};
@@ -237,8 +261,7 @@ public class PushController implements Disposable {
ProgressManagerImpl.runProcessWithProgressAsynchronously(task, indicator, null, ModalityState.any());
}
-
- public PushLog getPushPanelInfo() {
+ public PushLog getPushPanelLog() {
return myPushLog;
}
@@ -247,22 +270,32 @@ public class PushController implements Disposable {
@Override
public void run(@NotNull ProgressIndicator indicator) {
for (PushSupport support : myPushSupports) {
- MyPushOptionValueModel additionalOptionsModel = myAdditionalValuesMap.get(support);
- support.getPusher()
- .push(collectPushInfoForVcs(support), additionalOptionsModel == null ? null : additionalOptionsModel.getCurrentValue(), force);
+ doPush(support, force);
}
}
};
task.queue();
}
+ private <R extends Repository, S extends PushSource, T extends PushTarget> void doPush(@NotNull PushSupport<R, S, T> support,
+ boolean force) {
+ MyPushOptionValueModel additionalOptionsModel = myAdditionalValuesMap.get(support);
+ VcsPushOptionValue options = additionalOptionsModel == null ? null : additionalOptionsModel.getCurrentValue();
+ Pusher<R, S, T> pusher = support.getPusher();
+ pusher.push(collectPushSpecsForVcs(support), options, force);
+ }
+
@NotNull
- private Map<Repository, PushSpec> collectPushInfoForVcs(@NotNull final PushSupport pushSupport) {
- Map<Repository, PushSpec> pushSpecs = new HashMap<Repository, PushSpec>();
+ private <R extends Repository, S extends PushSource, T extends PushTarget> Map<R, PushSpec<S, T>> collectPushSpecsForVcs(@NotNull PushSupport<R, S, T> pushSupport) {
+ Map<R, PushSpec<S, T>> pushSpecs = ContainerUtil.newHashMap();
Collection<MyRepoModel> repositoriesInformation = getSelectedRepoNode();
for (MyRepoModel repoModel : repositoriesInformation) {
if (pushSupport.equals(repoModel.getSupport())) {
- pushSpecs.put(repoModel.getRepository(), repoModel.getSpec());
+ //todo improve generics: unchecked casts
+ T target = (T)repoModel.getTarget();
+ if (target != null) {
+ pushSpecs.put((R)repoModel.getRepository(), new PushSpec<S, T>((S)repoModel.getSource(), target));
+ }
}
}
return pushSpecs;
@@ -356,38 +389,53 @@ public class PushController implements Disposable {
});
}
- private static class MyRepoModel {
- @NotNull final Repository myRepository;
- @NotNull private PushSupport mySupport;
+ private static class MyRepoModel<Repo extends Repository, S extends PushSource, T extends PushTarget> {
+ @NotNull final Repo myRepository;
+ @NotNull private PushSupport<Repo, S, T> mySupport;
+ @NotNull private final S mySource;
+ @Nullable private T myTarget;
+ @Nullable VcsError myTargetError;
- @NotNull PushSpec mySpec;
int myNumberOfShownCommits;
-
List<? extends VcsFullCommitDetails> myLoadedCommits;
boolean myIsSelected;
- public MyRepoModel(@NotNull Repository repository,
- @NotNull PushSupport supportForRepo,
- boolean isSelected,
- @NotNull PushSpec spec,
+ public MyRepoModel(@NotNull Repo repository,
+ @NotNull PushSupport<Repo, S, T> supportForRepo,
+ boolean isSelected, @NotNull S source, @Nullable T target,
int num) {
myRepository = repository;
mySupport = supportForRepo;
myIsSelected = isSelected;
- mySpec = spec;
+ mySource = source;
+ myTarget = target;
myNumberOfShownCommits = num;
}
@NotNull
- public Repository getRepository() {
+ public Repo getRepository() {
return myRepository;
}
@NotNull
- public PushSupport getSupport() {
+ public PushSupport<Repo, S, T> getSupport() {
return mySupport;
}
+ @NotNull
+ public S getSource() {
+ return mySource;
+ }
+
+ @Nullable
+ public T getTarget() {
+ return myTarget;
+ }
+
+ public void setTarget(@Nullable T target) {
+ myTarget = target;
+ }
+
public boolean isSelected() {
return myIsSelected;
}
@@ -396,13 +444,21 @@ public class PushController implements Disposable {
return myRepository.getVcs();
}
- @NotNull
- public PushSpec getSpec() {
- return mySpec;
+ @Nullable
+ public VcsError getError() {
+ return myTargetError;
+ }
+
+ public void setError(@Nullable VcsError error) {
+ myTargetError = error;
+ }
+
+ public void clearErrors() {
+ myTargetError = null;
}
- public void setSpec(@NotNull PushSpec spec) {
- mySpec = spec;
+ public boolean hasError() {
+ return myTargetError != null;
}
public void setSelected(boolean isSelected) {