From 2d2b14e494db14b6f48e60ef1a9d4c3170f52cb0 Mon Sep 17 00:00:00 2001 From: Ivan Semenov Date: Wed, 13 Jun 2018 17:58:31 +0300 Subject: [PATCH] [vcs] Allow loading repository url suggestions separately Some hosting service integrations (like github) can provide loaders that will load urls in several steps. It is better to allow displaying partial results. --- .../dvcs/hosting/RepositoryListLoader.java | 26 +++++++++++++++++- .../com/intellij/dvcs/ui/CloneDvcsDialog.java | 27 ++++++++++++++----- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/platform/dvcs-api/src/com/intellij/dvcs/hosting/RepositoryListLoader.java b/platform/dvcs-api/src/com/intellij/dvcs/hosting/RepositoryListLoader.java index 4dc8c8e46782..8747760882b7 100644 --- a/platform/dvcs-api/src/com/intellij/dvcs/hosting/RepositoryListLoader.java +++ b/platform/dvcs-api/src/com/intellij/dvcs/hosting/RepositoryListLoader.java @@ -4,14 +4,19 @@ package com.intellij.dvcs.hosting; import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.CalledInBackground; import org.jetbrains.annotations.NotNull; +import java.util.Collections; import java.util.List; /** * Allows to query remote service for a list of available VCS repositories with the current IDEA settings. * Can be used to suggest the list of repositories that can be checked out. + *

+ * Implement either {@link #getAvailableRepositories(ProgressIndicator)} to load everything in a single request + * or {@link #getAvailableRepositoriesFromMultipleSources(ProgressIndicator)} to load in several requests */ public interface RepositoryListLoader { /** @@ -24,7 +29,26 @@ public interface RepositoryListLoader { */ boolean enable(); + /** + * Load repository urls in a single requests + */ @CalledInBackground @NotNull - List getAvailableRepositories(@NotNull ProgressIndicator progressIndicator) throws RepositoryListLoadingException; + default List getAvailableRepositories(@NotNull ProgressIndicator progressIndicator) throws RepositoryListLoadingException { + return Collections.emptyList(); + } + + /** + * Load repository urls in multiple requests with ability to show partial result + */ + @CalledInBackground + @NotNull + default Pair, List> getAvailableRepositoriesFromMultipleSources(@NotNull ProgressIndicator progressIndicator) { + try { + return Pair.create(getAvailableRepositories(progressIndicator), Collections.emptyList()); + } + catch (RepositoryListLoadingException e) { + return Pair.create(Collections.emptyList(), Collections.singletonList(e)); + } + } } diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java index 977c0aadef59..7b410775f6c5 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java @@ -20,6 +20,7 @@ import com.intellij.dvcs.DvcsRememberedInputs; import com.intellij.dvcs.DvcsUtil; import com.intellij.dvcs.hosting.RepositoryHostingService; import com.intellij.dvcs.hosting.RepositoryListLoader; +import com.intellij.dvcs.hosting.RepositoryListLoadingException; import com.intellij.ide.impl.ProjectUtil; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.ActionManager; @@ -41,6 +42,7 @@ import com.intellij.openapi.ui.ValidationInfo; import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; @@ -109,6 +111,7 @@ public abstract class CloneDvcsDialog extends DialogWrapper { @NotNull private final List myLoadedRepositoryHostingServicesNames; @Nullable private Alarm myRepositoryUrlAutoCompletionTooltipAlarm; @NotNull private final Set myUniqueAvailableRepositories; + @NotNull private List myRepositoryListLoadingErrors = new ArrayList<>(); public CloneDvcsDialog(@NotNull Project project, @NotNull String displayName, @NotNull String vcsDirectoryName) { this(project, displayName, vcsDirectoryName, null); @@ -261,7 +264,7 @@ public abstract class CloneDvcsDialog extends DialogWrapper { List loginActions = new ArrayList<>(); Map enabledLoaders = new HashMap<>(); - for (RepositoryHostingService service : repositoryHostingServices) { + for (RepositoryHostingService service: repositoryHostingServices) { String serviceDisplayName = service.getServiceDisplayName(); RepositoryListLoader loader = service.getRepositoryListLoader(myProject); if (loader == null) continue; @@ -304,14 +307,18 @@ public abstract class CloneDvcsDialog extends DialogWrapper { private void schedule(@NotNull String serviceDisplayName, @NotNull RepositoryListLoader loader) { mySpinnerProgressManager.run(new Task.Backgroundable(myProject, "Not Visible") { private final List myNewRepositories = new ArrayList<>(); + private final List myErrors = new ArrayList<>(); @Override public void run(@NotNull ProgressIndicator indicator) { - for (String repository : loader.getAvailableRepositories(indicator)) { + Pair, List> loadingResult = + loader.getAvailableRepositoriesFromMultipleSources(indicator); + for (String repository: loadingResult.first) { if (myUniqueAvailableRepositories.add(repository)) { myNewRepositories.add(repository); } } + myErrors.addAll(loadingResult.second); } @Override @@ -324,11 +331,16 @@ public abstract class CloneDvcsDialog extends DialogWrapper { } myLoadedRepositoryHostingServicesNames.add(serviceDisplayName); showRepositoryUrlAutoCompletionTooltip(); - } - - @Override - public void onThrowable(@NotNull Throwable error) { - //TODO: show warning + if (!myErrors.isEmpty()) { + for (RepositoryListLoadingException error: myErrors) { + StringBuilder errorMessageBuilder = new StringBuilder(); + errorMessageBuilder.append(error.getMessage()); + Throwable cause = error.getCause(); + if (cause != null) errorMessageBuilder.append(": ").append(cause.getMessage()); + myRepositoryListLoadingErrors.add(new ValidationInfo(errorMessageBuilder.toString(), false)); + } + startTrackingValidation(); + } } }); } @@ -416,6 +428,7 @@ public abstract class CloneDvcsDialog extends DialogWrapper { ContainerUtil.addIfNotNull(infoList, myCreateDirectoryValidationInfo); ContainerUtil.addIfNotNull(infoList, urlValidation); ContainerUtil.addIfNotNull(infoList, directoryValidation); + infoList.addAll(myRepositoryListLoadingErrors); return infoList; }