From 70f8aa3a5e0434a2486a050489fc6f836310429e Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Fri, 29 Aug 2014 02:39:11 +0400 Subject: [PATCH] IDEA-129008 PushDialog: create PushSpec only for @NotNull PushTarget, and add annotations. * nullable target could be only in MyRepoModel,in any other places PushTarget should be @NotNull; * generics updated, need to improve --- .../src/com/intellij/dvcs/push/PushSpec.java | 8 +- .../com/intellij/dvcs/push/PushSupport.java | 7 +- .../src/com/intellij/dvcs/push/VcsError.java | 4 + .../intellij/dvcs/push/PushController.java | 95 ++++++++++++------- .../push/HgOutgoingCommitsProvider.java | 12 +-- .../org/zmlx/hg4idea/push/HgPushSupport.java | 8 +- .../src/org/zmlx/hg4idea/push/HgPusher.java | 3 - 7 files changed, 84 insertions(+), 53 deletions(-) diff --git a/platform/dvcs-api/src/com/intellij/dvcs/push/PushSpec.java b/platform/dvcs-api/src/com/intellij/dvcs/push/PushSpec.java index 1557dbb8f1e7..e205009a4c0d 100644 --- a/platform/dvcs-api/src/com/intellij/dvcs/push/PushSpec.java +++ b/platform/dvcs-api/src/com/intellij/dvcs/push/PushSpec.java @@ -16,7 +16,6 @@ package com.intellij.dvcs.push; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; /** * For a single repository, specifies what is pushed and where. @@ -24,9 +23,9 @@ import org.jetbrains.annotations.Nullable; public class PushSpec { @NotNull private S mySource; - @Nullable private T myTarget; + @NotNull private T myTarget; - public PushSpec(@NotNull S source, @Nullable T target) { + public PushSpec(@NotNull S source, @NotNull T target) { mySource = source; myTarget = target; } @@ -36,7 +35,7 @@ public class PushSpec { return mySource; } - @Nullable + @NotNull public T getTarget() { return myTarget; } @@ -45,5 +44,4 @@ public class PushSpec { public String toString() { return mySource + "->" + myTarget; } - } diff --git a/platform/dvcs-api/src/com/intellij/dvcs/push/PushSupport.java b/platform/dvcs-api/src/com/intellij/dvcs/push/PushSupport.java index 087004b05bf9..fbf6f148c3b1 100644 --- a/platform/dvcs-api/src/com/intellij/dvcs/push/PushSupport.java +++ b/platform/dvcs-api/src/com/intellij/dvcs/push/PushSupport.java @@ -41,7 +41,7 @@ public abstract class PushSupport getPusher(); @NotNull - public abstract OutgoingCommitsProvider getOutgoingCommitsProvider(); + public abstract OutgoingCommitsProvider getOutgoingCommitsProvider(); /** * @return Default push destination @@ -63,12 +63,11 @@ public abstract class PushSupportnull if the target name is not valid. + * Parse user input string, and create the VALID target for push * * @see #validateSpec(Repository, PushSpec) */ - @Nullable + @NotNull public abstract Target createTarget(@NotNull Repo repository, @NotNull String targetName); /** diff --git a/platform/dvcs-api/src/com/intellij/dvcs/push/VcsError.java b/platform/dvcs-api/src/com/intellij/dvcs/push/VcsError.java index de2c640d12b1..b76095629ccd 100644 --- a/platform/dvcs-api/src/com/intellij/dvcs/push/VcsError.java +++ b/platform/dvcs-api/src/com/intellij/dvcs/push/VcsError.java @@ -40,4 +40,8 @@ public class VcsError { myErrorHandleListener.handleError(loader); } } + + public static VcsError createEmptyTargetError(@NotNull String name) { + return new VcsError("Please, specify remote push path for repository " + name + "."); + } } 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 8861d8e2490f..45f5c68e1d0a 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java @@ -96,13 +96,8 @@ public class PushController implements Disposable { for (Map.Entry 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; - PushTarget target = model.getSpec().getTarget(); - //todo add validation for model -> hasErrors, too - if (target == null) { - return new ValidationInfo("Invalid remote for repository " + DvcsUtil.getShortRepositoryName(model.getRepository())); - } } } return validInfo; @@ -145,8 +140,7 @@ public class PushController implements Disposable { private int createNodesForVcs( @NotNull PushSupport pushSupport, @NotNull CheckedTreeNode rootNode, - @NotNull List preselectedRepositories) - { + @NotNull List preselectedRepositories) { RepositoryManager repositoryManager = pushSupport.getRepositoryManager(); List repositories = repositoryManager.getRepositories(); for (R repository : repositories) { @@ -156,15 +150,19 @@ public class PushController implements Disposable { } private void createRepoNode(@NotNull final PushSupport support, - @NotNull final R repository, - @NotNull CheckedTreeNode rootNode, - boolean isSelected, - boolean isSingleRepositoryProject) { + @NotNull final R repository, + @NotNull CheckedTreeNode rootNode, + boolean isSelected, + boolean isSingleRepositoryProject) { T target = support.getDefaultTarget(repository); + String repoName = DvcsUtil.getShortRepositoryName(repository); final MyRepoModel model = new MyRepoModel(repository, support, isSingleRepositoryProject || isSelected, - new PushSpec(support.getSource(repository), target), + support.getSource(repository), target, DEFAULT_CHILDREN_PRESENTATION_NUMBER); - RepositoryWithBranchPanel repoPanel = new RepositoryWithBranchPanel(myProject, DvcsUtil.getShortRepositoryName(repository), + 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)); @@ -180,15 +178,16 @@ public class PushController implements Disposable { if (validationError == null) { T newTarget = support.createTarget(repository, newValue); repoNode.setTargetPresentation(support.renderTarget(newTarget)); - model.setSpec(new PushSpec(model.getSpec().getSource(), newTarget)); + model.setTarget(newTarget); + model.clearErrors(); loadCommits(model, repoNode, false); } else { - //todo change presentation for invalid/null target!!!! Should it be common for all invalid target or custom? repoNode.setTargetPresentation(StringUtil.isEmptyOrSpaces(newValue) ? support.renderTarget(null) : new SimpleColoredText(newValue, SimpleTextAttributes.ERROR_ATTRIBUTES)); - model.setSpec(new PushSpec(model.getSpec().getSource(), null)); + model.setError(validationError); // todo may be should accept and store errors collection, now store one major target error + model.setTarget(null); } myDialog.updateButtons(); } @@ -203,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 void loadCommits(@NotNull final MyRepoModel 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 support = model.getSupport(); final AtomicReference result = new AtomicReference(); Task.Backgroundable task = new Task.Backgroundable(myProject, "Loading Commits", true) { @@ -251,7 +252,8 @@ public class PushController implements Disposable { @Override public void run(@NotNull ProgressIndicator indicator) { - OutgoingResult outgoing = support.getOutgoingCommitsProvider().getOutgoingCommits(model.getRepository(), model.getSpec(), initial); + OutgoingResult outgoing = support.getOutgoingCommitsProvider() + .getOutgoingCommits(model.getRepository(), new PushSpec(model.getSource(), model.getTarget()), initial); result.compareAndSet(null, outgoing); } }; @@ -289,7 +291,11 @@ public class PushController implements Disposable { Collection repositoriesInformation = getSelectedRepoNode(); for (MyRepoModel repoModel : repositoriesInformation) { if (pushSupport.equals(repoModel.getSupport())) { - pushSpecs.put((R)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)repoModel.getSource(), target)); + } } } return pushSpecs; @@ -386,22 +392,23 @@ public class PushController implements Disposable { private static class MyRepoModel { @NotNull final Repo myRepository; @NotNull private PushSupport mySupport; + @NotNull private final S mySource; + @Nullable private T myTarget; + @Nullable VcsError myTargetError; - @NotNull PushSpec mySpec; int myNumberOfShownCommits; - List myLoadedCommits; boolean myIsSelected; public MyRepoModel(@NotNull Repo repository, @NotNull PushSupport supportForRepo, - boolean isSelected, - @NotNull PushSpec spec, + boolean isSelected, @NotNull S source, @Nullable T target, int num) { myRepository = repository; mySupport = supportForRepo; myIsSelected = isSelected; - mySpec = spec; + mySource = source; + myTarget = target; myNumberOfShownCommits = num; } @@ -415,6 +422,20 @@ public class PushController implements Disposable { 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; } @@ -423,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 setSpec(@NotNull PushSpec spec) { - mySpec = spec; + public void setError(@Nullable VcsError error) { + myTargetError = error; + } + + public void clearErrors() { + myTargetError = null; + } + + public boolean hasError() { + return myTargetError != null; } public void setSelected(boolean isSelected) { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgOutgoingCommitsProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgOutgoingCommitsProvider.java index 70055cafe1a1..a3ea93d7f0b9 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgOutgoingCommitsProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgOutgoingCommitsProvider.java @@ -16,7 +16,6 @@ package org.zmlx.hg4idea.push; import com.intellij.dvcs.push.*; -import com.intellij.dvcs.repo.Repository; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; @@ -27,6 +26,7 @@ import org.zmlx.hg4idea.command.HgOutgoingCommand; import org.zmlx.hg4idea.execution.HgCommandResult; import org.zmlx.hg4idea.log.HgBaseLogParser; import org.zmlx.hg4idea.log.HgHistoryUtil; +import org.zmlx.hg4idea.repo.HgRepository; import org.zmlx.hg4idea.util.HgChangesetUtil; import org.zmlx.hg4idea.util.HgErrorUtil; import org.zmlx.hg4idea.util.HgVersion; @@ -35,7 +35,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -public class HgOutgoingCommitsProvider extends OutgoingCommitsProvider { +public class HgOutgoingCommitsProvider extends OutgoingCommitsProvider { private static final Logger LOG = Logger.getInstance(HgOutgoingCommitsProvider.class); @@ -43,8 +43,8 @@ public class HgOutgoingCommitsProvider extends OutgoingCommitsProvider { @NotNull @Override - public OutgoingResult getOutgoingCommits(@NotNull final Repository repository, - @NotNull final PushSpec pushSpec, + public OutgoingResult getOutgoingCommits(@NotNull final HgRepository repository, + @NotNull final PushSpec pushSpec, boolean initial) { final Project project = repository.getProject(); HgVcs hgvcs = HgVcs.getInstance(project); @@ -52,9 +52,9 @@ public class HgOutgoingCommitsProvider extends OutgoingCommitsProvider { final HgVersion version = hgvcs.getVersion(); String[] templates = HgBaseLogParser.constructFullTemplateArgument(true, version); HgOutgoingCommand hgOutgoingCommand = new HgOutgoingCommand(project); - HgTarget hgTarget = (HgTarget)pushSpec.getTarget(); + HgTarget hgTarget = pushSpec.getTarget(); List errors = new ArrayList(); - if (hgTarget == null || StringUtil.isEmptyOrSpaces(hgTarget.myTarget)) { + if (StringUtil.isEmptyOrSpaces(hgTarget.myTarget)) { errors.add(new VcsError("Hg push path could not be empty.")); return new OutgoingResult(Collections.emptyList(), errors); } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java index bb7db85a14f7..13f4aaa08f6a 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java @@ -15,6 +15,7 @@ */ package org.zmlx.hg4idea.push; +import com.intellij.dvcs.DvcsUtil; import com.intellij.dvcs.push.*; import com.intellij.dvcs.repo.RepositoryManager; import com.intellij.openapi.project.Project; @@ -58,7 +59,7 @@ public class HgPushSupport extends PushSupport getOutgoingCommitsProvider() { return new HgOutgoingCommitsProvider(); } @@ -88,6 +89,7 @@ public class HgPushSupport extends PushSupport { HgRepository repository = entry.getKey(); PushSpec hgSpec = entry.getValue(); HgTarget destination = hgSpec.getTarget(); - if (destination == null) { - continue; - } HgPushSource source = hgSpec.getSource(); Project project = repository.getProject(); final HgPushCommand pushCommand = new HgPushCommand(project, repository.getRoot(), destination.myTarget);