diff --git a/devtools/cli/src/main/java/io/quarkus/cli/QuarkusCli.java b/devtools/cli/src/main/java/io/quarkus/cli/QuarkusCli.java index ef9ad75138415..52ac95068681f 100644 --- a/devtools/cli/src/main/java/io/quarkus/cli/QuarkusCli.java +++ b/devtools/cli/src/main/java/io/quarkus/cli/QuarkusCli.java @@ -104,6 +104,7 @@ public int run(String... args) throws Exception { boolean noCommand = args.length == 0 || args[0].startsWith("-"); boolean helpCommand = Arrays.stream(args).anyMatch(arg -> arg.equals("--help")); boolean pluginCommand = args.length >= 1 && (args[0].equals("plug") || args[0].equals("plugin")); + boolean pluginSyncCommand = pluginCommand && args.length >= 2 && args[1].equals("sync"); try { Optional missingCommand = checkMissingCommand(cmd, args); @@ -117,7 +118,9 @@ public int run(String... args) throws Exception { } PluginCommandFactory pluginCommandFactory = new PluginCommandFactory(output); PluginManager pluginManager = pluginManager(output, testDir, interactiveMode); - pluginManager.syncIfNeeded(); + if (!pluginSyncCommand) { // Let`s not sync before the actual command + pluginManager.syncIfNeeded(); + } Map plugins = new HashMap<>(pluginManager.getInstalledPlugins()); pluginCommandFactory.populateCommands(cmd, plugins); missingCommand.filter(m -> !plugins.containsKey(m)).ifPresent(m -> { diff --git a/devtools/cli/src/main/java/io/quarkus/cli/plugin/PluginCommandFactory.java b/devtools/cli/src/main/java/io/quarkus/cli/plugin/PluginCommandFactory.java index 2e2f67ca0d5b0..5b5cc2d6a1dd5 100644 --- a/devtools/cli/src/main/java/io/quarkus/cli/plugin/PluginCommandFactory.java +++ b/devtools/cli/src/main/java/io/quarkus/cli/plugin/PluginCommandFactory.java @@ -40,6 +40,12 @@ private Optional createPluginCommand(Plugin plugin) { return plugin.getLocation().map(l -> new JBangCommand(l, output)); case executable: return plugin.getLocation().map(l -> new ShellCommand(plugin.getName(), Paths.get(l), output)); + case extension: + if (PluginUtil.checkGACTV(plugin.getLocation()).isPresent()) { + return plugin.getLocation().flatMap(PluginUtil::checkGACTV).map(g -> new JBangCommand(toGAVC(g), output)); + } else if (plugin.getLocation().filter(l -> l.endsWith(".jar")).isPresent()) { + return plugin.getLocation().map(l -> new JBangCommand(l, output)); + } default: throw new IllegalStateException("Unknown plugin type!"); } diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/cli/plugin/Plugin.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/cli/plugin/Plugin.java index 00cce05c386ed..b9224f6484b08 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/cli/plugin/Plugin.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/cli/plugin/Plugin.java @@ -92,6 +92,10 @@ public Plugin withCatalogLocation(Optional catalogLocation) { return new Plugin(name, type, location, description, catalogLocation, inUserCatalog); } + public Plugin withType(PluginType type) { + return new Plugin(name, type, location, description, catalogLocation, inUserCatalog); + } + public Plugin inUserCatalog() { return new Plugin(name, type, location, description, catalogLocation, true); } diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/cli/plugin/PluginManager.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/cli/plugin/PluginManager.java index aabcfa800b8ae..06f9bcc5eeb22 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/cli/plugin/PluginManager.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/cli/plugin/PluginManager.java @@ -236,7 +236,7 @@ public boolean reconcile() { */ private boolean reconcile(PluginCatalog catalog) { Path location = catalog.getCatalogLocation() - .orElseThrow(() -> new IllegalArgumentException("Unknwon plugin catalog location.")); + .orElseThrow(() -> new IllegalArgumentException("Unknown plugin catalog location.")); List installedTypes = catalog.getPlugins().entrySet().stream().map(Map.Entry::getValue).map(Plugin::getType) .collect(Collectors.toList()); //Let's only fetch installable plugins of the corresponding types. @@ -279,24 +279,31 @@ private boolean reconcile(PluginCatalog catalog) { * @return true if changes any catalog was modified. */ public boolean sync() { - boolean catalogModified = reconcile(); - Map installedPlugins = getInstalledPlugins(); - Map extensionPlugins = state.getExtensionPlugins(); - Map pluginsToInstall = extensionPlugins.entrySet().stream() - .filter(e -> !installedPlugins.containsKey(e.getKey())) - .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue())); - catalogModified = catalogModified || !pluginsToInstall.isEmpty(); - pluginsToInstall.forEach((name, plugin) -> { - addPlugin(plugin); - }); - state.invalidate(); - if (!catalogModified) { - PluginCatalogService pluginCatalogService = state.getPluginCatalogService(); - PluginCatalog catalog = state.pluginCatalog(false); - pluginCatalogService.writeCatalog(catalog); - // here we are just touching the catalog, no need to invalidate + if (state.isSynced()) { + return false; + } + try { + boolean catalogModified = reconcile(); + Map installedPlugins = getInstalledPlugins(); + Map extensionPlugins = state.getExtensionPlugins(); + Map pluginsToInstall = extensionPlugins.entrySet().stream() + .filter(e -> !installedPlugins.containsKey(e.getKey())) + .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue())); + catalogModified = catalogModified || !pluginsToInstall.isEmpty(); + pluginsToInstall.forEach((name, plugin) -> { + addPlugin(plugin); + }); + state.invalidate(); + if (!catalogModified) { + PluginCatalogService pluginCatalogService = state.getPluginCatalogService(); + PluginCatalog catalog = state.pluginCatalog(false); + pluginCatalogService.writeCatalog(catalog); + // here we are just touching the catalog, no need to invalidate + } + return catalogModified; + } finally { + state.synced(); } - return catalogModified; } /** diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/cli/plugin/PluginMangerState.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/cli/plugin/PluginMangerState.java index 71abd3b42c2fa..ee1744e7a9b3e 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/cli/plugin/PluginMangerState.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/cli/plugin/PluginMangerState.java @@ -61,6 +61,8 @@ class PluginMangerState { private PluginCatalog _combinedCatalog; + private boolean synced; + public PluginCatalogService getPluginCatalogService() { return pluginCatalogService; } @@ -119,6 +121,9 @@ public Map installablePlugins(List types) { case executable: installablePlugins.putAll(executablePlugins()); break; + case extension: + installablePlugins.putAll(extensionPlugins()); + break; } } installablePlugins.putAll(executablePlugins().entrySet().stream().filter(e -> types.contains(e.getValue().getType())) @@ -186,8 +191,8 @@ public Map extensionPlugins() { for (ArtifactKey key : allKeys) { Extension extension = allExtensions.get(key); for (String cliPlugin : ExtensionProcessor.getCliPlugins(extension)) { - Plugin plugin = cliPlugin.contains(ALIAS_SEPARATOR) ? util.fromAlias(cliPlugin) - : util.fromLocation(cliPlugin); + Plugin plugin = (cliPlugin.contains(ALIAS_SEPARATOR) ? util.fromAlias(cliPlugin) + : util.fromLocation(cliPlugin)).withType(PluginType.extension); extensionPlugins.put(plugin.getName(), plugin); } } @@ -249,6 +254,14 @@ public Optional getProjectRoot() { return this.projectRoot; } + public boolean isSynced() { + return synced; + } + + public void synced() { + this.synced = true; + } + public void invalidateCatalogs() { _projectCatalog = null; _userCatalog = null; diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/cli/plugin/PluginType.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/cli/plugin/PluginType.java index 1b8b54d7c4172..3a751f419a312 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/cli/plugin/PluginType.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/cli/plugin/PluginType.java @@ -5,5 +5,6 @@ public enum PluginType { java, maven, executable, - jbang; + jbang, + extension } diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/cli/plugin/PluginUtil.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/cli/plugin/PluginUtil.java index 40f5c3bab818a..c3dbdbf410cb5 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/cli/plugin/PluginUtil.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/cli/plugin/PluginUtil.java @@ -84,7 +84,7 @@ public static boolean shouldRemove(Plugin p) { if (checkUrl(p.getLocation()).isPresent()) { //We don't want to remove remotely located plugins return false; } - if (checkGACTV(p.getLocation()).isPresent()) { //We don't want to remove remotely located plugins + if (checkGACTV(p.getLocation()).isPresent() && p.getType() != PluginType.extension) { //We don't want to remove remotely located plugins return false; } if (p.getLocation().map(PluginUtil::isLocalFile).orElse(false)) {