From 63a2c238e36800a514e2324d31151da7497b9007 Mon Sep 17 00:00:00 2001 From: Andy Damevin Date: Mon, 10 May 2021 14:53:06 +0200 Subject: [PATCH] Improve adding extension xp in all tooling --- .../handlers/AddExtensionsCommandHandler.java | 28 +++++++++-- .../devtools/project/buildfile/BuildFile.java | 48 +++++++++++++------ .../buildfile/MavenProjectBuildFile.java | 6 +-- .../extensions/ExtensionInstallPlan.java | 24 +++++++++- .../project/extensions/ExtensionManager.java | 35 +++++++++++--- 5 files changed, 110 insertions(+), 31 deletions(-) diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/AddExtensionsCommandHandler.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/AddExtensionsCommandHandler.java index 732161a32671b..a0caadc8c285f 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/AddExtensionsCommandHandler.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/AddExtensionsCommandHandler.java @@ -42,13 +42,31 @@ public QuarkusCommandOutcome execute(QuarkusCommandInvocation invocation) throws invocation.getQuarkusProject().getExtensionManager()); try { ExtensionInstallPlan extensionInstallPlan = planInstallation(invocation, extensionsQuery); - if (extensionInstallPlan.isNotEmpty()) { + if (extensionInstallPlan.isInstallable()) { final InstallResult result = extensionManager.install(extensionInstallPlan); - result.getInstalled() + result.getInstalledPlatforms() + .forEach(a -> invocation.log() + .info(MessageIcons.OK_ICON + " Platform " + a.getGroupId() + ":" + a.getArtifactId() + + " has been installed")); + result.getInstalledManagedExtensions() .forEach(a -> invocation.log() .info(MessageIcons.OK_ICON + " Extension " + a.getGroupId() + ":" + a.getArtifactId() + " has been installed")); + result.getInstalledIndependentExtensions() + .forEach(a -> invocation.log() + .info(MessageIcons.OK_ICON + " Extension " + a.getGroupId() + ":" + a.getArtifactId() + ":" + + a.getVersion() + + " has been installed")); + result.getAlreadyInstalled() + .forEach(a -> invocation.log() + .info(MessageIcons.NOOP_ICON + " Extension " + a.getGroupId() + ":" + a.getArtifactId() + + " was already installed")); return new QuarkusCommandOutcome(true).setValue(AddExtensions.OUTCOME_UPDATED, result.isSourceUpdated()); + } else { + invocation.log() + .info(NOK_ICON + " Nothing installed because one or more keyword(s) " + + String.join(", ", extensionInstallPlan.getUnmatchedKeywords()) + + " is not matched in our catalog."); } } catch (MultipleExtensionsFoundException m) { StringBuilder sb = new StringBuilder(); @@ -87,9 +105,9 @@ public ExtensionInstallPlan planInstallation(QuarkusCommandInvocation invocation continue; } List listed = listInternalExtensions(quarkusCore, keyword, catalog.getExtensions()); - if (listed.size() != 1 && multipleKeywords) { - // No extension found for this keyword. Return empty immediately - return ExtensionInstallPlan.EMPTY; + if (listed.isEmpty()) { + // No extension found for this keyword. + builder.addUnmatchedKeyword(keyword); } // If it's a pattern allow multiple results // See https://github.com/quarkusio/quarkus/issues/11086#issuecomment-666360783 diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/BuildFile.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/BuildFile.java index 0e352cef901bc..019692b474be7 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/BuildFile.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/BuildFile.java @@ -32,33 +32,44 @@ public BuildFile(final Path projectDirPath, ExtensionCatalog catalog) { @Override public final InstallResult install(Collection coords) throws IOException { - this.refreshData(); - final Collection installed = withoutAlreadyInstalled(coords); - installed.forEach(e -> addDependency(e, e.getVersion() == null)); - this.writeToDisk(); - return new InstallResult(installed); + final ExtensionInstallPlan.Builder builder = ExtensionInstallPlan.builder(); + for (ArtifactCoords coord : coords) { + if ("pom".equals(coord.getType())) { + builder.addPlatform(coord); + } else if (coord.getVersion() == null) { + builder.addManagedExtension(coord); + } else { + builder.addIndependentExtension(coord); + } + } + return install(builder.build()); } @Override public InstallResult install(ExtensionInstallPlan plan) throws IOException { - List installed = new ArrayList<>(); - for (ArtifactCoords platform : withoutAlreadyInstalled(plan.getPlatforms())) { + this.refreshData(); + List installedManagedExtensions = new ArrayList<>(); + List installedIndependentExtensions = new ArrayList<>(); + List installedPlatforms = new ArrayList<>(); + final Set alreadyInstalled = alreadyInstalled(plan.toCollection()); + for (ArtifactCoords platform : withoutAlreadyInstalled(alreadyInstalled, plan.getPlatforms())) { if (addDependency(platform, false)) { - installed.add(platform); + installedPlatforms.add(platform); } } - for (ArtifactCoords managedExtension : withoutAlreadyInstalled(plan.getManagedExtensions())) { + for (ArtifactCoords managedExtension : withoutAlreadyInstalled(alreadyInstalled, plan.getManagedExtensions())) { if (addDependency(managedExtension, true)) { - installed.add(managedExtension); + installedManagedExtensions.add(managedExtension); } } - for (ArtifactCoords independentExtension : withoutAlreadyInstalled(plan.getIndependentExtensions())) { + for (ArtifactCoords independentExtension : withoutAlreadyInstalled(alreadyInstalled, plan.getIndependentExtensions())) { if (addDependency(independentExtension, false)) { - installed.add(independentExtension); + installedIndependentExtensions.add(independentExtension); } } writeToDisk(); - return new InstallResult(installed); + return new InstallResult(installedPlatforms, installedManagedExtensions, installedIndependentExtensions, + alreadyInstalled); } @Override @@ -88,8 +99,17 @@ public final UninstallResult uninstall(Collection keys) throws IOEx return new UninstallResult(uninstalled); } - private Collection withoutAlreadyInstalled(Collection extensions) throws IOException { + private Set alreadyInstalled(Collection extensions) throws IOException { final Set existingKeys = getDependenciesKeys(); + return extensions.stream() + .distinct() + .filter(a -> existingKeys.contains(a.getKey())) + .map(ArtifactCoords::getKey) + .collect(Collectors.toSet()); + } + + private Collection withoutAlreadyInstalled(Set existingKeys, + Collection extensions) { return extensions.stream() .distinct() .filter(a -> !existingKeys.contains(a.getKey())) diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/MavenProjectBuildFile.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/MavenProjectBuildFile.java index fa28530883175..6b9f8a9ac3a6f 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/MavenProjectBuildFile.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/buildfile/MavenProjectBuildFile.java @@ -221,10 +221,10 @@ protected boolean addDependency(ArtifactCoords coords, boolean managed) { } else if (model().getDependencies() .stream() .noneMatch(thisDep -> d.getManagementKey().equals(thisDep.getManagementKey()))) { - model().addDependency(d); + model().getDependencies().add(0, d); // it could still be a transitive dependency or inherited from the parent if (!getDependencies().contains(coords)) { - getDependencies().add(coords); + getDependencies().add(0, coords); } return true; } @@ -241,8 +241,8 @@ protected void removeDependency(ArtifactKey key) throws IOException { i.remove(); break; } - model().getDependencies().removeIf(d -> Objects.equals(toKey(d), key)); } + model().getDependencies().removeIf(d -> Objects.equals(toKey(d), key)); } } diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/extensions/ExtensionInstallPlan.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/extensions/ExtensionInstallPlan.java index aefc0da8ac59e..ef8ed352e86e3 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/extensions/ExtensionInstallPlan.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/extensions/ExtensionInstallPlan.java @@ -1,6 +1,7 @@ package io.quarkus.devtools.project.extensions; import io.quarkus.maven.ArtifactCoords; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; @@ -9,6 +10,7 @@ public class ExtensionInstallPlan { public static final ExtensionInstallPlan EMPTY = new ExtensionInstallPlan( + Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), Collections.emptySet()); @@ -16,13 +18,16 @@ public class ExtensionInstallPlan { private final Set platforms; private final Set managedExtensions; private final Set independentExtensions; + private final Collection unmatchedKeywords; private ExtensionInstallPlan(Set platforms, Set managedExtensions, - Set independentExtensions) { + Set independentExtensions, + Collection unmatchedKeywords) { this.platforms = platforms; this.managedExtensions = managedExtensions; this.independentExtensions = independentExtensions; + this.unmatchedKeywords = unmatchedKeywords; } public boolean isNotEmpty() { @@ -30,6 +35,10 @@ public boolean isNotEmpty() { || !this.independentExtensions.isEmpty(); } + public boolean isInstallable() { + return isNotEmpty() && unmatchedKeywords.isEmpty(); + } + /** * @return a {@link Collection} of all extensions contained in this object */ @@ -63,12 +72,17 @@ public Collection getIndependentExtensions() { return independentExtensions; } + public Collection getUnmatchedKeywords() { + return unmatchedKeywords; + } + @Override public String toString() { return "InstallRequest{" + "platforms=" + platforms + ", managedExtensions=" + managedExtensions + ", independentExtensions=" + independentExtensions + + ", unmatchedKeywords=" + unmatchedKeywords + '}'; } @@ -81,9 +95,10 @@ public static class Builder { private final Set platforms = new LinkedHashSet<>(); private final Set extensionsInPlatforms = new LinkedHashSet<>(); private final Set independentExtensions = new LinkedHashSet<>(); + private final Collection unmatchedKeywords = new ArrayList<>(); public ExtensionInstallPlan build() { - return new ExtensionInstallPlan(platforms, extensionsInPlatforms, independentExtensions); + return new ExtensionInstallPlan(platforms, extensionsInPlatforms, independentExtensions, unmatchedKeywords); } public Builder addIndependentExtension(ArtifactCoords artifactCoords) { @@ -101,6 +116,11 @@ public Builder addPlatform(ArtifactCoords artifactCoords) { return this; } + public Builder addUnmatchedKeyword(String unmatchedKeyword) { + this.unmatchedKeywords.add(unmatchedKeyword); + return this; + } + public boolean hasExtensionInPlatform() { return !this.extensionsInPlatforms.isEmpty(); } diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/extensions/ExtensionManager.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/extensions/ExtensionManager.java index bd717483fee47..08d9a5fbf918f 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/extensions/ExtensionManager.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/extensions/ExtensionManager.java @@ -76,7 +76,7 @@ default boolean isInstalled(ArtifactKey key) throws IOException { /** * This is going to uninstall/remove all the specified extensions from the project build file(s). * - * This is ignoring the {@link Extension} version + * This is ignoring the version * * @param keys the set of {@link ArtifactKey} for the extensions to uninstall * @return the {@link InstallResult} @@ -85,18 +85,39 @@ default boolean isInstalled(ArtifactKey key) throws IOException { UninstallResult uninstall(Collection keys) throws IOException; class InstallResult { - private final Collection installed; + private final Collection installedPlatforms; + private final Collection installedManagedExtensions; + private final Collection installedIndependentExtensions; + private final Collection alreadyInstalled; + + public InstallResult(Collection installedPlatforms, + Collection installedManagedExtensions, + Collection installedIndependentExtensions, Collection alreadyInstalled) { + this.installedPlatforms = installedPlatforms; + this.installedManagedExtensions = installedManagedExtensions; + this.installedIndependentExtensions = installedIndependentExtensions; + this.alreadyInstalled = alreadyInstalled; + } + + public Collection getInstalledManagedExtensions() { + return installedManagedExtensions; + } + + public Collection getInstalledIndependentExtensions() { + return installedIndependentExtensions; + } - public InstallResult(Collection installed) { - this.installed = installed; + public Collection getInstalledPlatforms() { + return installedPlatforms; } - public Collection getInstalled() { - return installed; + public Collection getAlreadyInstalled() { + return alreadyInstalled; } public boolean isSourceUpdated() { - return installed.size() > 0; + return !installedPlatforms.isEmpty() || !installedManagedExtensions.isEmpty() + || !installedIndependentExtensions.isEmpty(); } }