From e9006c1f767abcb760c90574254c6175b0f1b070 Mon Sep 17 00:00:00 2001 From: Andy Damevin Date: Thu, 15 Jun 2023 17:14:51 +0200 Subject: [PATCH] Extract update info as data structures --- .../handlers/ProjectInfoCommandHandler.java | 159 +------ .../handlers/UpdateProjectCommandHandler.java | 418 +++--------------- .../devtools/project/state/ProjectStates.java | 116 +++++ .../project/update/ExtensionMapBuilder.java | 115 +++++ .../project/update/ExtensionUpdateInfo.java | 33 ++ .../devtools/project/update/PlatformInfo.java | 49 ++ .../update/ProjectExtensionsUpdateInfo.java | 45 ++ .../update/ProjectPlatformUpdateInfo.java | 43 ++ .../project/update/ProjectUpdateInfos.java | 269 +++++++++++ .../{ => rewrite}/QuarkusUpdateCommand.java | 4 +- .../{ => rewrite}/QuarkusUpdateException.java | 2 +- .../{ => rewrite}/QuarkusUpdateRecipe.java | 2 +- .../{ => rewrite}/QuarkusUpdateRecipeIO.java | 2 +- .../update/{ => rewrite}/QuarkusUpdates.java | 8 +- .../QuarkusUpdatesRepository.java | 2 +- .../{ => rewrite}/RewriteOperation.java | 2 +- .../UpdateDependencyVersionOperation.java | 4 +- ...dateManagedDependencyVersionOperation.java | 4 +- .../operations/UpdatePropertyOperation.java | 4 +- .../UpgradeGradlePluginOperation.java | 4 +- .../QuarkusUpdateRecipeIOTest.java | 6 +- .../QuarkusUpdatesRepositoryTest.java | 4 +- 22 files changed, 770 insertions(+), 525 deletions(-) create mode 100644 independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/state/ProjectStates.java create mode 100644 independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ExtensionMapBuilder.java create mode 100644 independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ExtensionUpdateInfo.java create mode 100644 independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/PlatformInfo.java create mode 100644 independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ProjectExtensionsUpdateInfo.java create mode 100644 independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ProjectPlatformUpdateInfo.java create mode 100644 independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ProjectUpdateInfos.java rename independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/{ => rewrite}/QuarkusUpdateCommand.java (98%) rename independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/{ => rewrite}/QuarkusUpdateException.java (85%) rename independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/{ => rewrite}/QuarkusUpdateRecipe.java (97%) rename independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/{ => rewrite}/QuarkusUpdateRecipeIO.java (97%) rename independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/{ => rewrite}/QuarkusUpdates.java (89%) rename independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/{ => rewrite}/QuarkusUpdatesRepository.java (99%) rename independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/{ => rewrite}/RewriteOperation.java (88%) rename independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/{ => rewrite}/operations/UpdateDependencyVersionOperation.java (87%) rename independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/{ => rewrite}/operations/UpdateManagedDependencyVersionOperation.java (89%) rename independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/{ => rewrite}/operations/UpdatePropertyOperation.java (86%) rename independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/{ => rewrite}/operations/UpgradeGradlePluginOperation.java (86%) rename independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/update/{ => rewrite}/QuarkusUpdateRecipeIOTest.java (86%) rename independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/update/{ => rewrite}/QuarkusUpdatesRepositoryTest.java (79%) diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/ProjectInfoCommandHandler.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/ProjectInfoCommandHandler.java index 786b9de83d105..e05ade2a0acc4 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/ProjectInfoCommandHandler.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/ProjectInfoCommandHandler.java @@ -2,20 +2,17 @@ import static io.quarkus.devtools.messagewriter.MessageIcons.OUT_OF_DATE_ICON; import static io.quarkus.devtools.messagewriter.MessageIcons.UP_TO_DATE_ICON; +import static io.quarkus.devtools.project.state.ProjectStates.resolveProjectState; import java.nio.file.Path; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import io.quarkus.bootstrap.model.ApplicationModel; -import io.quarkus.bootstrap.workspace.WorkspaceModule; -import io.quarkus.bootstrap.workspace.WorkspaceModuleId; import io.quarkus.devtools.commands.ProjectInfo; import io.quarkus.devtools.commands.data.QuarkusCommandException; import io.quarkus.devtools.commands.data.QuarkusCommandInvocation; @@ -25,12 +22,9 @@ import io.quarkus.devtools.project.state.ModuleState; import io.quarkus.devtools.project.state.ProjectState; import io.quarkus.devtools.project.state.TopExtensionDependency; +import io.quarkus.devtools.project.update.PlatformInfo; import io.quarkus.maven.dependency.ArtifactCoords; import io.quarkus.maven.dependency.ArtifactKey; -import io.quarkus.maven.dependency.Dependency; -import io.quarkus.maven.dependency.DependencyFlags; -import io.quarkus.maven.dependency.ResolvedDependency; -import io.quarkus.registry.catalog.ExtensionCatalog; import io.quarkus.registry.catalog.ExtensionOrigin; public class ProjectInfoCommandHandler implements QuarkusCommandHandler { @@ -58,13 +52,17 @@ protected static boolean logState(ProjectState projectState, boolean perModule, final Map providerInfo = new LinkedHashMap<>(); for (ArtifactCoords bom : projectState.getPlatformBoms()) { - providerInfo.computeIfAbsent(bom.getKey(), k -> new PlatformInfo()).imported = bom; + providerInfo.computeIfAbsent(bom.getKey(), k -> new PlatformInfo(bom, null)); } for (TopExtensionDependency dep : projectState.getExtensions()) { final ExtensionOrigin origin = dep.getOrigin(); if (origin != null && origin.isPlatform()) { - providerInfo.computeIfAbsent(origin.getBom().getKey(), k -> new PlatformInfo()).recommended = origin - .getBom(); + providerInfo.compute(origin.getBom().getKey(), (k, v) -> { + if (v == null) { + return new PlatformInfo(null, origin.getBom()); + } + return new PlatformInfo(v.getImported(), origin.getBom()); + }); } } @@ -74,19 +72,19 @@ protected static boolean logState(ProjectState projectState, boolean perModule, log.info("Quarkus platform BOMs:"); boolean recommendExtraImports = false; for (PlatformInfo platform : providerInfo.values()) { - if (platform.imported == null) { + if (!platform.isImported()) { recommendExtraImports = true; continue; } final StringBuilder sb = new StringBuilder(); - if (platform.recommended == null) { + if (platform.getRecommended() == null) { if (rectify) { sb.append(String.format(UpdateProjectCommandHandler.ITEM_FORMAT, - UpdateProjectCommandHandler.REMOVE, platform.imported.toCompactCoords())); + UpdateProjectCommandHandler.REMOVE, platform.getImported().toCompactCoords())); recommendationsAvailable = true; } else { sb.append(" "); - sb.append(platform.imported.toCompactCoords()); + sb.append(platform.getImported().toCompactCoords()); if (!projectState.getExtensions().isEmpty()) { // The extension check is for modules that are aggregating modules (e.g. parent POMs) // that import common BOMs. It's however not how it should be done. @@ -96,9 +94,9 @@ protected static boolean logState(ProjectState projectState, boolean perModule, } } else if (platform.isVersionUpdateRecommended()) { sb.append(String.format(UpdateProjectCommandHandler.ITEM_FORMAT, - rectify ? UpdateProjectCommandHandler.UPDATE : "", platform.imported.toCompactCoords())); + rectify ? UpdateProjectCommandHandler.UPDATE : "", platform.getImported().toCompactCoords())); if (rectify) { - sb.append(platform.imported.toCompactCoords()).append(" -> ") + sb.append(platform.getImported().toCompactCoords()).append(" -> ") .append(platform.getRecommendedVersion()); } else { sb.append(" ").append(OUT_OF_DATE_ICON.iconOrMessage()); @@ -106,17 +104,17 @@ protected static boolean logState(ProjectState projectState, boolean perModule, recommendationsAvailable = true; } else { sb.append(String.format(UpdateProjectCommandHandler.ITEM_FORMAT, "", - platform.imported.toCompactCoords())) + platform.getImported().toCompactCoords())) .append(" ").append(UP_TO_DATE_ICON.iconOrMessage()); } log.info(sb.toString()); } if (rectify && recommendExtraImports) { for (PlatformInfo platform : providerInfo.values()) { - if (platform.imported == null) { + if (platform.getImported() == null) { log.info(String.format(UpdateProjectCommandHandler.ITEM_FORMAT, UpdateProjectCommandHandler.ADD, - platform.recommended.toCompactCoords())); + platform.getRecommended().toCompactCoords())); } } recommendationsAvailable = true; @@ -299,125 +297,4 @@ private static boolean logModuleInfo(ProjectState project, ModuleState module, P return recommendationsAvailable; } - protected static ProjectState resolveProjectState(ApplicationModel appModel, ExtensionCatalog currentCatalog) { - final ProjectState.Builder projectBuilder = ProjectState.builder(); - - final Collection importedPlatformBoms = appModel.getPlatforms().getImportedPlatformBoms(); - if (importedPlatformBoms.isEmpty()) { - return projectBuilder.build(); - } - - final Map extProviderBuilders = new LinkedHashMap<>(importedPlatformBoms.size()); - importedPlatformBoms.forEach(bom -> { - projectBuilder.addPlatformBom(bom); - extProviderBuilders.put(ExtensionProvider.key(bom, true), - ExtensionProvider.builder().setArtifact(bom).setPlatform(true)); - }); - - final Map projectModuleBuilders = new HashMap<>(); - final Map> directModuleDeps = new HashMap<>(); - - final WorkspaceModule appModule = appModel.getAppArtifact().getWorkspaceModule(); - if (appModule != null) { - final ModuleState.Builder module = ModuleState.builder().setWorkspaceModule(appModule).setMainModule(true); - projectModuleBuilders.put(appModule.getId(), module); - appModule.getDirectDependencies() - .forEach(d -> directModuleDeps.computeIfAbsent(d.getKey(), dk -> new ArrayList<>()).add(module)); - - for (Dependency constraint : appModule.getDirectDependencyConstraints()) { - if (extProviderBuilders.containsKey(constraint.toCompactCoords())) { - module.addPlatformBom(constraint); - } - } - - } - for (ResolvedDependency dep : appModel.getDependencies()) { - if (dep.getWorkspaceModule() != null) { - projectModuleBuilders.computeIfAbsent(dep.getWorkspaceModule().getId(), k -> { - final ModuleState.Builder module = ModuleState.builder() - .setWorkspaceModule(dep.getWorkspaceModule()); - dep.getWorkspaceModule().getDirectDependencies().forEach( - d -> directModuleDeps.computeIfAbsent(d.getKey(), dk -> new ArrayList<>()).add(module)); - return module; - }); - } - } - - final Map directExtDeps = new HashMap<>(); - for (ResolvedDependency dep : appModel.getDependencies()) { - if (dep.isFlagSet(DependencyFlags.TOP_LEVEL_RUNTIME_EXTENSION_ARTIFACT)) { - directExtDeps.put(dep.getKey(), TopExtensionDependency.builder().setResolvedDependency(dep) - .setTransitive(!directModuleDeps.containsKey(dep.getKey()))); - } else if (dep.isRuntimeExtensionArtifact() && directModuleDeps.containsKey(dep.getKey())) { - directExtDeps.put(dep.getKey(), TopExtensionDependency.builder().setResolvedDependency(dep)); - } - } - - if (directExtDeps.isEmpty()) { - return projectBuilder.build(); - } - - currentCatalog.getExtensions().forEach(e -> { - final ArtifactKey key = e.getArtifact().getKey(); - final TopExtensionDependency.Builder dep = directExtDeps.get(key); - if (dep != null) { - dep.setCatalogMetadata(e); - } - }); - - for (TopExtensionDependency.Builder extBuilder : directExtDeps.values()) { - final List modules = directModuleDeps.getOrDefault(extBuilder.getKey(), - Collections.emptyList()); - final TopExtensionDependency dep = extBuilder.setTransitive(modules.isEmpty()).build(); - projectBuilder.addExtensionDependency(dep); - for (ModuleState.Builder module : modules) { - module.addExtensionDependency(dep); - } - final ExtensionProvider.Builder provider = extProviderBuilders.computeIfAbsent(dep.getProviderKey(), - k -> ExtensionProvider.builder().setOrigin(dep.getOrigin())); - provider.addExtension(dep); - } - - for (ExtensionProvider.Builder builder : extProviderBuilders.values()) { - projectBuilder.addExtensionProvider(builder.build()); - } - - for (ModuleState.Builder builder : projectModuleBuilders.values()) { - projectBuilder.addModule(builder.build()); - } - - return projectBuilder.build(); - } - - static class PlatformInfo { - ArtifactCoords imported; - ArtifactCoords recommended; - - boolean isVersionUpdateRecommended() { - return imported != null && recommended != null && !imported.getVersion().equals(recommended.getVersion()); - } - - String getRecommendedVersion() { - return recommended == null ? null : recommended.getVersion(); - } - - boolean isImported() { - return imported != null; - } - - boolean isToBeImported() { - return imported == null && recommended != null; - } - - ArtifactCoords getRecommendedCoords() { - return recommended == null ? imported : recommended; - } - - String getRecommendedProviderKey() { - if (recommended != null) { - return ExtensionProvider.key(recommended, true); - } - return ExtensionProvider.key(imported, true); - } - } } diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/UpdateProjectCommandHandler.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/UpdateProjectCommandHandler.java index 612fef8f32b1c..e206cfd755d0f 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/UpdateProjectCommandHandler.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/UpdateProjectCommandHandler.java @@ -1,46 +1,39 @@ package io.quarkus.devtools.commands.handlers; +import static io.quarkus.devtools.project.state.ProjectStates.resolveProjectState; +import static io.quarkus.devtools.project.update.ProjectUpdateInfos.resolvePlatformUpdateInfo; +import static io.quarkus.devtools.project.update.ProjectUpdateInfos.resolveRecommendedState; + import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.stream.Collectors; import io.quarkus.bootstrap.model.ApplicationModel; import io.quarkus.devtools.commands.UpdateProject; import io.quarkus.devtools.commands.data.QuarkusCommandException; import io.quarkus.devtools.commands.data.QuarkusCommandInvocation; import io.quarkus.devtools.commands.data.QuarkusCommandOutcome; -import io.quarkus.devtools.commands.handlers.ProjectInfoCommandHandler.PlatformInfo; import io.quarkus.devtools.messagewriter.MessageWriter; import io.quarkus.devtools.project.BuildTool; import io.quarkus.devtools.project.QuarkusProject; import io.quarkus.devtools.project.QuarkusProjectHelper; -import io.quarkus.devtools.project.state.ExtensionProvider; -import io.quarkus.devtools.project.state.ModuleState; import io.quarkus.devtools.project.state.ProjectState; -import io.quarkus.devtools.project.state.TopExtensionDependency; -import io.quarkus.devtools.project.update.QuarkusUpdateCommand; -import io.quarkus.devtools.project.update.QuarkusUpdateException; -import io.quarkus.devtools.project.update.QuarkusUpdates; -import io.quarkus.devtools.project.update.QuarkusUpdatesRepository; +import io.quarkus.devtools.project.update.ExtensionUpdateInfo; +import io.quarkus.devtools.project.update.PlatformInfo; +import io.quarkus.devtools.project.update.ProjectExtensionsUpdateInfo; +import io.quarkus.devtools.project.update.ProjectPlatformUpdateInfo; +import io.quarkus.devtools.project.update.ProjectUpdateInfos; +import io.quarkus.devtools.project.update.rewrite.QuarkusUpdateCommand; +import io.quarkus.devtools.project.update.rewrite.QuarkusUpdateException; +import io.quarkus.devtools.project.update.rewrite.QuarkusUpdates; +import io.quarkus.devtools.project.update.rewrite.QuarkusUpdatesRepository; import io.quarkus.maven.dependency.ArtifactCoords; -import io.quarkus.maven.dependency.ArtifactKey; import io.quarkus.platform.tools.ToolsConstants; -import io.quarkus.registry.catalog.Extension; import io.quarkus.registry.catalog.ExtensionCatalog; -import io.quarkus.registry.catalog.ExtensionOrigin; -import io.quarkus.registry.catalog.selection.ExtensionOrigins; -import io.quarkus.registry.catalog.selection.OriginCombination; -import io.quarkus.registry.catalog.selection.OriginPreference; -import io.quarkus.registry.catalog.selection.OriginSelector; public class UpdateProjectCommandHandler implements QuarkusCommandHandler { public static final String ADD = "Add:"; @@ -55,7 +48,7 @@ public QuarkusCommandOutcome execute(QuarkusCommandInvocation invocation) throws final String targetPlatformVersion = invocation.getValue(UpdateProject.TARGET_PLATFORM_VERSION); final boolean perModule = invocation.getValue(UpdateProject.PER_MODULE, false); - final ProjectState currentState = ProjectInfoCommandHandler.resolveProjectState(appModel, + final ProjectState currentState = resolveProjectState(appModel, invocation.getQuarkusProject().getExtensionsCatalog()); final ArtifactCoords projectQuarkusPlatformBom = getProjectQuarkusPlatformBOM(currentState); if (projectQuarkusPlatformBom == null) { @@ -68,7 +61,15 @@ public QuarkusCommandOutcome execute(QuarkusCommandInvocation invocation) throws invocation.log().info("Instructions to update this project from '%s' to '%s':", projectQuarkusPlatformBom.getVersion(), targetPlatformVersion); final QuarkusProject quarkusProject = invocation.getQuarkusProject(); - logUpdates(currentState, targetCatalog, false, perModule, quarkusProject.log()); + final ProjectState recommendedState = resolveRecommendedState(currentState, targetCatalog, invocation.log()); + final ProjectPlatformUpdateInfo platformUpdateInfo = resolvePlatformUpdateInfo(currentState, + recommendedState); + final ProjectExtensionsUpdateInfo extensionsUpdateInfo = ProjectUpdateInfos.resolveExtensionsUpdateInfo( + currentState, + recommendedState); + + logUpdates(currentState, recommendedState, platformUpdateInfo, extensionsUpdateInfo, false, perModule, + quarkusProject.log()); final boolean noRewrite = invocation.getValue(UpdateProject.NO_REWRITE, false); if (!noRewrite) { @@ -129,7 +130,9 @@ private static ArtifactCoords getProjectQuarkusPlatformBOM(ProjectState currentS return null; } - private static void logUpdates(ProjectState currentState, ExtensionCatalog recommendedCatalog, boolean recommendState, + private static void logUpdates(ProjectState currentState, ProjectState recommendedState, + ProjectPlatformUpdateInfo platformUpdateInfo, + ProjectExtensionsUpdateInfo extensionsUpdateInfo, boolean recommendState, boolean perModule, MessageWriter log) { if (currentState.getPlatformBoms().isEmpty()) { log.info("The project does not import any Quarkus platform BOM"); @@ -139,7 +142,6 @@ private static void logUpdates(ProjectState currentState, ExtensionCatalog recom log.info("Quarkus extension were not found among the project dependencies"); return; } - final ProjectState recommendedState = resolveRecommendedState(currentState, recommendedCatalog, log); if (currentState == recommendedState) { log.info("The project is up-to-date"); return; @@ -150,151 +152,83 @@ private static void logUpdates(ProjectState currentState, ExtensionCatalog recom return; } - // log instructions - final Map platformImports = new LinkedHashMap<>(); - for (ArtifactCoords c : currentState.getPlatformBoms()) { - final PlatformInfo info = new PlatformInfo(); - info.imported = c; - platformImports.put(c.getKey(), info); - } - List importVersionUpdates = new ArrayList<>(); - List newImports = new ArrayList<>(0); - for (ArtifactCoords c : recommendedState.getPlatformBoms()) { - final PlatformInfo importInfo = platformImports.computeIfAbsent(c.getKey(), k -> new PlatformInfo()); - importInfo.recommended = c; - if (importInfo.isToBeImported()) { - newImports.add(importInfo); - } else if (importInfo.isVersionUpdateRecommended()) { - importVersionUpdates.add(importInfo); - } - } - - log.info(""); - final boolean importsToBeRemoved = platformImports.values().stream().filter(p -> p.recommended == null).findFirst() - .isPresent(); - final boolean platformUpdatesAvailable = !importVersionUpdates.isEmpty() || !newImports.isEmpty() || importsToBeRemoved; - if (platformUpdatesAvailable) { + if (platformUpdateInfo.isPlatformUpdatesAvailable()) { log.info("Recommended Quarkus platform BOM updates:"); - if (!importVersionUpdates.isEmpty()) { - for (PlatformInfo importInfo : importVersionUpdates) { + if (!platformUpdateInfo.getImportVersionUpdates().isEmpty()) { + for (PlatformInfo importInfo : platformUpdateInfo.getImportVersionUpdates()) { log.info(String.format(UpdateProjectCommandHandler.ITEM_FORMAT, - UpdateProjectCommandHandler.UPDATE, importInfo.imported.toCompactCoords()) + " -> " + UpdateProjectCommandHandler.UPDATE, importInfo.getImported().toCompactCoords()) + " -> " + importInfo.getRecommendedVersion()); } } - if (!newImports.isEmpty()) { - for (PlatformInfo importInfo : newImports) { + if (!platformUpdateInfo.getNewImports().isEmpty()) { + for (PlatformInfo importInfo : platformUpdateInfo.getNewImports()) { log.info(String.format(UpdateProjectCommandHandler.ITEM_FORMAT, - UpdateProjectCommandHandler.ADD, importInfo.recommended.toCompactCoords())); + UpdateProjectCommandHandler.ADD, importInfo.getRecommended().toCompactCoords())); } } - if (importsToBeRemoved) { - for (PlatformInfo importInfo : platformImports.values()) { - if (importInfo.recommended == null) { + if (platformUpdateInfo.isImportsToBeRemoved()) { + for (PlatformInfo importInfo : platformUpdateInfo.getPlatformImports().values()) { + if (importInfo.getRecommended() == null) { log.info(String.format(UpdateProjectCommandHandler.ITEM_FORMAT, - UpdateProjectCommandHandler.REMOVE, importInfo.imported.toCompactCoords())); + UpdateProjectCommandHandler.REMOVE, importInfo.getImported().toCompactCoords())); } } } log.info(""); } - final ExtensionMap extensionInfo = new ExtensionMap(currentState.getExtensions().size()); - for (TopExtensionDependency dep : currentState.getExtensions()) { - extensionInfo.add(new ExtensionInfo(dep)); - } - for (TopExtensionDependency dep : recommendedState.getExtensions()) { - final ExtensionInfo info = extensionInfo.get(dep.getKey()); - if (info != null) { - info.recommendedDep = dep; - } - } - final Map> versionedManagedExtensions = new LinkedHashMap<>(0); - final Map> removedExtensions = new LinkedHashMap<>(0); - final Map> addedExtensions = new LinkedHashMap<>(0); - final Map> nonPlatformExtensionUpdates = new LinkedHashMap<>(); - for (ExtensionInfo info : extensionInfo.values()) { - if (!info.isUpdateRecommended()) { - continue; - } - if (!info.currentDep.getKey().equals(info.getRecommendedDependency().getKey())) { - if (info.currentDep.isPlatformExtension()) { - removedExtensions.computeIfAbsent(info.currentDep.getProviderKey(), k -> new ArrayList<>()) - .add(info.currentDep.getArtifact()); - } else { - nonPlatformExtensionUpdates.computeIfAbsent(info.currentDep.getProviderKey(), k -> new ArrayList<>()) - .add(info); - } - if (info.getRecommendedDependency().isPlatformExtension()) { - addedExtensions.computeIfAbsent(info.getRecommendedDependency().getProviderKey(), k -> new ArrayList<>()) - .add(info.getRecommendedDependency().getArtifact()); - } else { - nonPlatformExtensionUpdates - .computeIfAbsent(info.getRecommendedDependency().getProviderKey(), k -> new ArrayList<>()) - .add(info); - } - } else if (info.getRecommendedDependency().isPlatformExtension()) { - if (info.currentDep.isNonRecommendedVersion()) { - versionedManagedExtensions - .computeIfAbsent(info.getRecommendedDependency().getProviderKey(), k -> new ArrayList<>()) - .add(info); - } - } else if (!info.currentDep.getVersion().equals(info.getRecommendedDependency().getVersion())) { - nonPlatformExtensionUpdates - .computeIfAbsent(info.getRecommendedDependency().getProviderKey(), k -> new ArrayList<>()).add(info); - } - } - - if (versionedManagedExtensions.isEmpty() - && removedExtensions.isEmpty() - && addedExtensions.isEmpty() - && nonPlatformExtensionUpdates.isEmpty()) { - if (!platformUpdatesAvailable) { + if (extensionsUpdateInfo.isEmpty()) { + if (!platformUpdateInfo.isPlatformUpdatesAvailable()) { log.info("The project is up-to-date"); } return; } - for (PlatformInfo platform : platformImports.values()) { + for (PlatformInfo platform : platformUpdateInfo.getPlatformImports().values()) { final String provider = platform.getRecommendedProviderKey(); - if (!versionedManagedExtensions.containsKey(provider) - && !removedExtensions.containsKey(provider) - && !addedExtensions.containsKey(provider)) { + if (!extensionsUpdateInfo.getVersionedManagedExtensions().containsKey(provider) + && !extensionsUpdateInfo.getRemovedExtensions().containsKey(provider) + && !extensionsUpdateInfo.getAddedExtensions().containsKey(provider)) { continue; } log.info("Extensions from " + platform.getRecommendedProviderKey() + ":"); - for (ExtensionInfo e : versionedManagedExtensions.getOrDefault(provider, Collections.emptyList())) { + for (ExtensionUpdateInfo e : extensionsUpdateInfo.getVersionedManagedExtensions().getOrDefault(provider, + Collections.emptyList())) { final StringBuilder sb = new StringBuilder(); sb.append(String.format(UpdateProjectCommandHandler.ITEM_FORMAT, - UpdateProjectCommandHandler.UPDATE, e.currentDep.getArtifact().toCompactCoords())); + UpdateProjectCommandHandler.UPDATE, e.getCurrentDep().getArtifact().toCompactCoords())); sb.append(" -> remove version (managed)"); log.info(sb.toString()); } - for (ArtifactCoords e : addedExtensions.getOrDefault(provider, Collections.emptyList())) { + for (ArtifactCoords e : extensionsUpdateInfo.getAddedExtensions().getOrDefault(provider, Collections.emptyList())) { log.info(String.format(UpdateProjectCommandHandler.ITEM_FORMAT, UpdateProjectCommandHandler.ADD, e.getKey().toGacString())); } - for (ArtifactCoords e : removedExtensions.getOrDefault(provider, Collections.emptyList())) { + for (ArtifactCoords e : extensionsUpdateInfo.getRemovedExtensions().getOrDefault(provider, + Collections.emptyList())) { log.info(String.format(UpdateProjectCommandHandler.ITEM_FORMAT, UpdateProjectCommandHandler.REMOVE, e.getKey().toGacString())); } log.info(""); } - if (!nonPlatformExtensionUpdates.isEmpty()) { - for (Map.Entry> provider : nonPlatformExtensionUpdates.entrySet()) { + if (!extensionsUpdateInfo.getNonPlatformExtensions().isEmpty()) { + for (Map.Entry> provider : extensionsUpdateInfo.getNonPlatformExtensions() + .entrySet()) { log.info("Extensions from " + provider.getKey() + ":"); - for (ExtensionInfo info : provider.getValue()) { - if (info.currentDep.isPlatformExtension()) { + for (ExtensionUpdateInfo info : provider.getValue()) { + if (info.getCurrentDep().isPlatformExtension()) { log.info(String.format(UpdateProjectCommandHandler.ITEM_FORMAT, UpdateProjectCommandHandler.ADD, info.getRecommendedDependency().getArtifact().toCompactCoords())); } else if (info.getRecommendedDependency().isPlatformExtension()) { log.info(String.format(UpdateProjectCommandHandler.ITEM_FORMAT, - UpdateProjectCommandHandler.REMOVE, info.currentDep.getArtifact().toCompactCoords())); + UpdateProjectCommandHandler.REMOVE, info.getCurrentDep().getArtifact().toCompactCoords())); } else { log.info(String.format(UpdateProjectCommandHandler.ITEM_FORMAT, - UpdateProjectCommandHandler.UPDATE, info.currentDep.getArtifact().toCompactCoords() + " -> " + UpdateProjectCommandHandler.UPDATE, + info.getCurrentDep().getArtifact().toCompactCoords() + " -> " + info.getRecommendedDependency().getVersion())); } } @@ -303,243 +237,6 @@ private static void logUpdates(ProjectState currentState, ExtensionCatalog recom } } - private static ProjectState resolveRecommendedState(ProjectState currentState, ExtensionCatalog latestCatalog, - MessageWriter log) { - if (currentState.getPlatformBoms().isEmpty()) { - return currentState; - } - if (currentState.getExtensions().isEmpty()) { - return currentState; - } - - final ExtensionMap extensionInfo = new ExtensionMap(); - for (TopExtensionDependency dep : currentState.getExtensions()) { - extensionInfo.add(new ExtensionInfo(dep)); - } - - for (Extension e : latestCatalog.getExtensions()) { - final ExtensionInfo candidate = extensionInfo.get(e.getArtifact().getKey()); - if (candidate != null && candidate.latestMetadata == null) { - // if the latestMetadata has already been initialized, it's already the preferred one - // that could happen if an artifact has relocated - candidate.latestMetadata = e; - } - } - - final List unknownExtensions = new ArrayList<>(0); - final List updateCandidates = new ArrayList<>(extensionInfo.size()); - final Map updateCandidatesByOrigin = new HashMap<>(); - for (ExtensionInfo i : extensionInfo.values()) { - if (i.latestMetadata == null) { - unknownExtensions.add(i); - } else { - updateCandidates.add(i.latestMetadata); - for (ExtensionOrigin o : i.latestMetadata.getOrigins()) { - updateCandidatesByOrigin.computeIfAbsent(o.getId(), k -> new ExtensionMap()).add(i); - } - } - } - - if (extensionInfo.isEmpty()) { - return currentState; - } - - if (!unknownExtensions.isEmpty()) { - log.warn( - "The configured Quarkus registries did not provide any compatibility information for the following extensions in the context of the currently recommended Quarkus platforms:"); - unknownExtensions.forEach(e -> log.warn(" " + e.currentDep.getArtifact().toCompactCoords())); - } - - final List recommendedOrigins; - try { - recommendedOrigins = getRecommendedOrigins(latestCatalog, updateCandidates); - } catch (QuarkusCommandException e) { - log.info("Failed to find a compatible configuration update for the project"); - return currentState; - } - - int collectedUpdates = 0; - for (ExtensionCatalog recommendedOrigin : recommendedOrigins) { - final ExtensionMap candidates = updateCandidatesByOrigin.get(recommendedOrigin.getId()); - for (Extension e : recommendedOrigin.getExtensions()) { - final ExtensionInfo info = candidates.get(e.getArtifact().getKey()); - if (info != null && info.recommendedMetadata == null) { - info.setRecommendedMetadata(e); - if (++collectedUpdates == updateCandidates.size()) { - break; - } - } - } - } - - final ProjectState.Builder stateBuilder = ProjectState.builder(); - for (ExtensionCatalog c : recommendedOrigins) { - if (c.isPlatform()) { - stateBuilder.addPlatformBom(c.getBom()); - } - } - - final Map extProviders = new LinkedHashMap<>(recommendedOrigins.size()); - for (ExtensionInfo info : extensionInfo.values()) { - final TopExtensionDependency ext = info.getRecommendedDependency(); - stateBuilder.addExtensionDependency(ext); - extProviders.computeIfAbsent(ext.getProviderKey(), k -> ExtensionProvider.builder().setOrigin(ext.getOrigin())) - .addExtension(ext); - } - - extProviders.values().forEach(b -> stateBuilder.addExtensionProvider(b.build())); - - for (ModuleState module : currentState.getModules()) { - final ModuleState.Builder moduleBuilder = ModuleState.builder() - .setMainModule(module.isMain()) - .setWorkspaceModule(module.getWorkspaceModule()); - for (TopExtensionDependency dep : module.getExtensions()) { - final TopExtensionDependency recommendedDep = extensionInfo.get(dep.getKey()).getRecommendedDependency(); - moduleBuilder.addExtensionDependency(recommendedDep); - final ExtensionOrigin origin = recommendedDep.getOrigin(); - if (origin != null && origin.isPlatform()) { - moduleBuilder.addPlatformBom(origin.getBom()); - } - } - stateBuilder.addModule(moduleBuilder.build()); - } - - return stateBuilder.build(); - } - - private static class ExtensionInfo { - final TopExtensionDependency currentDep; - Extension latestMetadata; - Extension recommendedMetadata; - TopExtensionDependency recommendedDep; - - ExtensionInfo(TopExtensionDependency currentDep) { - this.currentDep = currentDep; - } - - void setRecommendedMetadata(Extension e) { - this.recommendedMetadata = e; - if (!currentDep.getArtifact().getKey().equals(e.getArtifact().getKey())) { - } - } - - Extension getRecommendedMetadata() { - if (recommendedMetadata != null) { - return recommendedMetadata; - } - if (recommendedDep == null) { - return currentDep.getCatalogMetadata(); - } - return recommendedMetadata = currentDep.getCatalogMetadata(); - } - - TopExtensionDependency getRecommendedDependency() { - if (recommendedDep != null) { - return recommendedDep; - } - if (recommendedMetadata == null) { - return currentDep; - } - return recommendedDep = TopExtensionDependency.builder() - .setArtifact(recommendedMetadata.getArtifact()) - .setCatalogMetadata(recommendedMetadata) - .setTransitive(currentDep.isTransitive()) - .build(); - } - - boolean isUpdateRecommended() { - return getRecommendedDependency() != currentDep; - } - } - - private static List getRecommendedOrigins(ExtensionCatalog extensionCatalog, List extensions) - throws QuarkusCommandException { - final List extOrigins = new ArrayList<>(extensions.size()); - for (Extension e : extensions) { - addOrigins(extOrigins, e); - } - - final OriginCombination recommendedCombination = OriginSelector.of(extOrigins).calculateRecommendedCombination(); - if (recommendedCombination == null) { - final StringBuilder buf = new StringBuilder(); - buf.append("Failed to determine a compatible Quarkus version for the requested extensions: "); - buf.append(extensions.get(0).getArtifact().getKey().toGacString()); - for (int i = 1; i < extensions.size(); ++i) { - buf.append(", ").append(extensions.get(i).getArtifact().getKey().toGacString()); - } - throw new QuarkusCommandException(buf.toString()); - } - return recommendedCombination.getUniqueSortedOrigins().stream().map(o -> o.getCatalog()).collect(Collectors.toList()); - } - - private static void addOrigins(final List extOrigins, Extension e) { - ExtensionOrigins.Builder eoBuilder = null; - for (ExtensionOrigin o : e.getOrigins()) { - if (!(o instanceof ExtensionCatalog)) { - continue; - } - final ExtensionCatalog c = (ExtensionCatalog) o; - final OriginPreference op = (OriginPreference) c.getMetadata().get("origin-preference"); - if (op == null) { - continue; - } - if (eoBuilder == null) { - eoBuilder = ExtensionOrigins.builder(e.getArtifact().getKey()); - } - eoBuilder.addOrigin(c, op); - } - if (eoBuilder != null) { - extOrigins.add(eoBuilder.build()); - } - } - - private static class ExtensionMap { - final Map> extensionInfo; - final List list = new ArrayList<>(); - - ExtensionMap() { - this.extensionInfo = new LinkedHashMap<>(); - } - - ExtensionMap(int size) { - this.extensionInfo = new LinkedHashMap<>(size); - } - - void add(ExtensionInfo e) { - extensionInfo.put(e.currentDep.getArtifact().getArtifactId(), Collections.singletonList(e)); - list.add(e); - } - - ExtensionInfo get(ArtifactKey key) { - final List list = extensionInfo.get(key.getArtifactId()); - if (list == null || list.isEmpty()) { - return null; - } - if (list.size() == 1) { - return list.get(0); - } - for (ExtensionInfo e : list) { - if (e.currentDep.getKey().equals(key) - || e.getRecommendedDependency() != null && e.getRecommendedDependency().getKey().equals(key)) { - return e; - } - } - throw new IllegalArgumentException(key + " isn't found in the extension map"); - } - - Collection values() { - return list; - } - - int size() { - return extensionInfo.size(); - } - - boolean isEmpty() { - return extensionInfo.isEmpty(); - } - } - @SuppressWarnings({ "rawtypes", "unchecked" }) private T getMetadata(ExtensionCatalog catalog, String... path) { Object currentValue = catalog.getMetadata(); @@ -553,4 +250,5 @@ private T getMetadata(ExtensionCatalog catalog, String... path) { return (T) currentValue; } + } diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/state/ProjectStates.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/state/ProjectStates.java new file mode 100644 index 0000000000000..1364dbb3eee2e --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/state/ProjectStates.java @@ -0,0 +1,116 @@ +package io.quarkus.devtools.project.state; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import io.quarkus.bootstrap.model.ApplicationModel; +import io.quarkus.bootstrap.workspace.WorkspaceModule; +import io.quarkus.bootstrap.workspace.WorkspaceModuleId; +import io.quarkus.maven.dependency.ArtifactCoords; +import io.quarkus.maven.dependency.ArtifactKey; +import io.quarkus.maven.dependency.Dependency; +import io.quarkus.maven.dependency.DependencyFlags; +import io.quarkus.maven.dependency.ResolvedDependency; +import io.quarkus.registry.catalog.ExtensionCatalog; + +public final class ProjectStates { + + private ProjectStates() { + } + + public static ProjectState resolveProjectState(ApplicationModel appModel, ExtensionCatalog currentCatalog) { + final ProjectState.Builder projectBuilder = ProjectState.builder(); + + final Collection importedPlatformBoms = appModel.getPlatforms().getImportedPlatformBoms(); + if (importedPlatformBoms.isEmpty()) { + return projectBuilder.build(); + } + + final Map extProviderBuilders = new LinkedHashMap<>(importedPlatformBoms.size()); + importedPlatformBoms.forEach(bom -> { + projectBuilder.addPlatformBom(bom); + extProviderBuilders.put(ExtensionProvider.key(bom, true), + ExtensionProvider.builder().setArtifact(bom).setPlatform(true)); + }); + + final Map projectModuleBuilders = new HashMap<>(); + final Map> directModuleDeps = new HashMap<>(); + + final WorkspaceModule appModule = appModel.getAppArtifact().getWorkspaceModule(); + if (appModule != null) { + final ModuleState.Builder module = ModuleState.builder().setWorkspaceModule(appModule).setMainModule(true); + projectModuleBuilders.put(appModule.getId(), module); + appModule.getDirectDependencies() + .forEach(d -> directModuleDeps.computeIfAbsent(d.getKey(), dk -> new ArrayList<>()).add(module)); + + for (Dependency constraint : appModule.getDirectDependencyConstraints()) { + if (extProviderBuilders.containsKey(constraint.toCompactCoords())) { + module.addPlatformBom(constraint); + } + } + + } + for (ResolvedDependency dep : appModel.getDependencies()) { + if (dep.getWorkspaceModule() != null) { + projectModuleBuilders.computeIfAbsent(dep.getWorkspaceModule().getId(), k -> { + final ModuleState.Builder module = ModuleState.builder() + .setWorkspaceModule(dep.getWorkspaceModule()); + dep.getWorkspaceModule().getDirectDependencies().forEach( + d -> directModuleDeps.computeIfAbsent(d.getKey(), dk -> new ArrayList<>()).add(module)); + return module; + }); + } + } + + final Map directExtDeps = new HashMap<>(); + for (ResolvedDependency dep : appModel.getDependencies()) { + if (dep.isFlagSet(DependencyFlags.TOP_LEVEL_RUNTIME_EXTENSION_ARTIFACT)) { + directExtDeps.put(dep.getKey(), TopExtensionDependency.builder().setResolvedDependency(dep) + .setTransitive(!directModuleDeps.containsKey(dep.getKey()))); + } else if (dep.isRuntimeExtensionArtifact() && directModuleDeps.containsKey(dep.getKey())) { + directExtDeps.put(dep.getKey(), TopExtensionDependency.builder().setResolvedDependency(dep)); + } + } + + if (directExtDeps.isEmpty()) { + return projectBuilder.build(); + } + + currentCatalog.getExtensions().forEach(e -> { + final ArtifactKey key = e.getArtifact().getKey(); + final TopExtensionDependency.Builder dep = directExtDeps.get(key); + if (dep != null) { + dep.setCatalogMetadata(e); + } + }); + + for (TopExtensionDependency.Builder extBuilder : directExtDeps.values()) { + final List modules = directModuleDeps.getOrDefault(extBuilder.getKey(), + Collections.emptyList()); + final TopExtensionDependency dep = extBuilder.setTransitive(modules.isEmpty()).build(); + projectBuilder.addExtensionDependency(dep); + for (ModuleState.Builder module : modules) { + module.addExtensionDependency(dep); + } + final ExtensionProvider.Builder provider = extProviderBuilders.computeIfAbsent(dep.getProviderKey(), + k -> ExtensionProvider.builder().setOrigin(dep.getOrigin())); + provider.addExtension(dep); + } + + for (ExtensionProvider.Builder builder : extProviderBuilders.values()) { + projectBuilder.addExtensionProvider(builder.build()); + } + + for (ModuleState.Builder builder : projectModuleBuilders.values()) { + projectBuilder.addModule(builder.build()); + } + + return projectBuilder.build(); + } + +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ExtensionMapBuilder.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ExtensionMapBuilder.java new file mode 100644 index 0000000000000..e91c09f14670b --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ExtensionMapBuilder.java @@ -0,0 +1,115 @@ +package io.quarkus.devtools.project.update; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import io.quarkus.devtools.project.state.TopExtensionDependency; +import io.quarkus.maven.dependency.ArtifactKey; +import io.quarkus.registry.catalog.Extension; + +final class ExtensionMapBuilder { + final Map> extensionInfo; + final List list = new ArrayList<>(); + + public ExtensionMapBuilder() { + this.extensionInfo = new LinkedHashMap<>(); + } + + public ExtensionMapBuilder(int size) { + this.extensionInfo = new LinkedHashMap<>(size); + } + + public void add(ExtensionUpdateInfoBuilder e) { + extensionInfo.put(e.currentDep.getArtifact().getArtifactId(), Collections.singletonList(e)); + list.add(e); + } + + public ExtensionUpdateInfoBuilder get(ArtifactKey key) { + final List list = extensionInfo.get(key.getArtifactId()); + if (list == null || list.isEmpty()) { + return null; + } + if (list.size() == 1) { + return list.get(0); + } + for (ExtensionUpdateInfoBuilder e : list) { + final TopExtensionDependency recommendedDep = e.resolveRecommendedDep(); + if (e.currentDep.getKey().equals(key) + || recommendedDep != null && recommendedDep.getKey().equals(key)) { + return e; + } + } + throw new IllegalArgumentException(key + " isn't found in the extension map"); + } + + public Collection values() { + return list; + } + + public int size() { + return extensionInfo.size(); + } + + public boolean isEmpty() { + return extensionInfo.isEmpty(); + } + + public static final class ExtensionUpdateInfoBuilder { + private final TopExtensionDependency currentDep; + private Extension recommendedMetadata; + private TopExtensionDependency recommendedDep; + + private Extension latestMetadata; + + public ExtensionUpdateInfoBuilder(TopExtensionDependency currentDep) { + this.currentDep = currentDep; + } + + public TopExtensionDependency getCurrentDep() { + return currentDep; + } + + public Extension getRecommendedMetadata() { + return recommendedMetadata; + } + + public void setRecommendedMetadata(Extension e) { + this.recommendedMetadata = e; + } + + public ExtensionUpdateInfoBuilder setRecommendedDep(TopExtensionDependency recommendedDep) { + this.recommendedDep = recommendedDep; + return this; + } + + public ExtensionUpdateInfo build() { + return new ExtensionUpdateInfo(currentDep, currentDep.getCatalogMetadata(), resolveRecommendedDep()); + } + + public TopExtensionDependency resolveRecommendedDep() { + if (recommendedDep != null) { + return recommendedDep; + } + return recommendedMetadata == null ? currentDep + : TopExtensionDependency.builder() + .setArtifact(recommendedMetadata.getArtifact()) + .setCatalogMetadata(recommendedMetadata) + .setTransitive(currentDep.isTransitive()) + .build(); + } + + public Extension getLatestMetadata() { + return latestMetadata; + } + + public ExtensionUpdateInfoBuilder setLatestMetadata(Extension latestMetadata) { + this.latestMetadata = latestMetadata; + return this; + } + } + +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ExtensionUpdateInfo.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ExtensionUpdateInfo.java new file mode 100644 index 0000000000000..5d2b530460937 --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ExtensionUpdateInfo.java @@ -0,0 +1,33 @@ +package io.quarkus.devtools.project.update; + +import io.quarkus.devtools.project.state.TopExtensionDependency; +import io.quarkus.registry.catalog.Extension; + +public final class ExtensionUpdateInfo { + private final TopExtensionDependency currentDep; + private final Extension recommendedMetadata; + private final TopExtensionDependency recommendedDep; + + public ExtensionUpdateInfo(TopExtensionDependency currentDep, Extension recommendedMetadata, + TopExtensionDependency recommendedDep) { + this.currentDep = currentDep; + this.recommendedMetadata = recommendedMetadata; + this.recommendedDep = recommendedDep; + } + + public TopExtensionDependency getCurrentDep() { + return currentDep; + } + + public Extension getRecommendedMetadata() { + return recommendedMetadata; + } + + public TopExtensionDependency getRecommendedDependency() { + return recommendedDep; + } + + public boolean isUpdateRecommended() { + return recommendedDep != currentDep; + } +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/PlatformInfo.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/PlatformInfo.java new file mode 100644 index 0000000000000..020b9a94b90aa --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/PlatformInfo.java @@ -0,0 +1,49 @@ +package io.quarkus.devtools.project.update; + +import io.quarkus.devtools.project.state.ExtensionProvider; +import io.quarkus.maven.dependency.ArtifactCoords; + +public class PlatformInfo { + private final ArtifactCoords imported; + private final ArtifactCoords recommended; + + public PlatformInfo(ArtifactCoords imported, ArtifactCoords recommended) { + this.imported = imported; + this.recommended = recommended; + } + + public ArtifactCoords getImported() { + return imported; + } + + public ArtifactCoords getRecommended() { + return recommended; + } + + public boolean isVersionUpdateRecommended() { + return imported != null && recommended != null && !imported.getVersion().equals(recommended.getVersion()); + } + + public String getRecommendedVersion() { + return recommended == null ? null : recommended.getVersion(); + } + + public boolean isImported() { + return imported != null; + } + + public boolean isToBeImported() { + return imported == null && recommended != null; + } + + public ArtifactCoords getRecommendedCoords() { + return recommended == null ? imported : recommended; + } + + public String getRecommendedProviderKey() { + if (recommended != null) { + return ExtensionProvider.key(recommended, true); + } + return ExtensionProvider.key(imported, true); + } +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ProjectExtensionsUpdateInfo.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ProjectExtensionsUpdateInfo.java new file mode 100644 index 0000000000000..e4cb0c6445605 --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ProjectExtensionsUpdateInfo.java @@ -0,0 +1,45 @@ +package io.quarkus.devtools.project.update; + +import java.util.List; +import java.util.Map; + +import io.quarkus.maven.dependency.ArtifactCoords; + +public class ProjectExtensionsUpdateInfo { + final Map> versionedManagedExtensions; + final Map> removedExtensions; + final Map> addedExtensions; + final Map> nonPlatformExtensions; + + public ProjectExtensionsUpdateInfo(Map> versionedManagedExtensions, + Map> removedExtensions, Map> addedExtensions, + Map> nonPlatformExtensionUpdate) { + this.versionedManagedExtensions = versionedManagedExtensions; + this.removedExtensions = removedExtensions; + this.addedExtensions = addedExtensions; + this.nonPlatformExtensions = nonPlatformExtensionUpdate; + } + + public Map> getVersionedManagedExtensions() { + return versionedManagedExtensions; + } + + public Map> getRemovedExtensions() { + return removedExtensions; + } + + public Map> getAddedExtensions() { + return addedExtensions; + } + + public Map> getNonPlatformExtensions() { + return nonPlatformExtensions; + } + + public boolean isEmpty() { + return versionedManagedExtensions.isEmpty() + && removedExtensions.isEmpty() + && addedExtensions.isEmpty() + && nonPlatformExtensions.isEmpty(); + } +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ProjectPlatformUpdateInfo.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ProjectPlatformUpdateInfo.java new file mode 100644 index 0000000000000..1958ee644329e --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ProjectPlatformUpdateInfo.java @@ -0,0 +1,43 @@ +package io.quarkus.devtools.project.update; + +import java.util.List; +import java.util.Map; + +import io.quarkus.maven.dependency.ArtifactKey; + +public class ProjectPlatformUpdateInfo { + private final Map platformImports; + private final List importVersionUpdates; + private final List newImports; + private final boolean importsToBeRemoved; + private final boolean platformUpdatesAvailable; + + public ProjectPlatformUpdateInfo(Map platformImports, List importVersionUpdates, + List newImports) { + this.platformImports = platformImports; + this.importVersionUpdates = importVersionUpdates; + this.newImports = newImports; + this.importsToBeRemoved = platformImports.values().stream().anyMatch(p -> p.getRecommended() == null); + this.platformUpdatesAvailable = !importVersionUpdates.isEmpty() || !newImports.isEmpty() || importsToBeRemoved; + } + + public boolean isImportsToBeRemoved() { + return importsToBeRemoved; + } + + public boolean isPlatformUpdatesAvailable() { + return platformUpdatesAvailable; + } + + public Map getPlatformImports() { + return platformImports; + } + + public List getImportVersionUpdates() { + return importVersionUpdates; + } + + public List getNewImports() { + return newImports; + } +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ProjectUpdateInfos.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ProjectUpdateInfos.java new file mode 100644 index 0000000000000..34443d1a17209 --- /dev/null +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ProjectUpdateInfos.java @@ -0,0 +1,269 @@ +package io.quarkus.devtools.project.update; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import io.quarkus.devtools.commands.data.QuarkusCommandException; +import io.quarkus.devtools.messagewriter.MessageWriter; +import io.quarkus.devtools.project.state.ExtensionProvider; +import io.quarkus.devtools.project.state.ModuleState; +import io.quarkus.devtools.project.state.ProjectState; +import io.quarkus.devtools.project.state.TopExtensionDependency; +import io.quarkus.devtools.project.update.ExtensionMapBuilder.ExtensionUpdateInfoBuilder; +import io.quarkus.maven.dependency.ArtifactCoords; +import io.quarkus.maven.dependency.ArtifactKey; +import io.quarkus.registry.catalog.Extension; +import io.quarkus.registry.catalog.ExtensionCatalog; +import io.quarkus.registry.catalog.ExtensionOrigin; +import io.quarkus.registry.catalog.selection.ExtensionOrigins; +import io.quarkus.registry.catalog.selection.OriginCombination; +import io.quarkus.registry.catalog.selection.OriginPreference; +import io.quarkus.registry.catalog.selection.OriginSelector; + +public final class ProjectUpdateInfos { + + private ProjectUpdateInfos() { + } + + public static ProjectExtensionsUpdateInfo resolveExtensionsUpdateInfo(ProjectState currentState, + ProjectState recommendedState) { + checkProjectState(currentState, recommendedState); + + final ExtensionMapBuilder extensionInfo = new ExtensionMapBuilder(currentState.getExtensions().size()); + for (TopExtensionDependency dep : currentState.getExtensions()) { + extensionInfo.add(new ExtensionUpdateInfoBuilder(dep)); + } + for (TopExtensionDependency dep : recommendedState.getExtensions()) { + final ExtensionUpdateInfoBuilder info = extensionInfo.get(dep.getKey()); + if (info != null) { + info.setRecommendedDep(dep); + } + } + final Map> versionedManagedExtensions = new LinkedHashMap<>(0); + final Map> removedExtensions = new LinkedHashMap<>(0); + final Map> addedExtensions = new LinkedHashMap<>(0); + final Map> nonPlatformExtensionUpdates = new LinkedHashMap<>(); + for (ExtensionUpdateInfoBuilder infoBuilder : extensionInfo.values()) { + final ExtensionUpdateInfo info = infoBuilder.build(); + if (!info.isUpdateRecommended()) { + continue; + } + if (!info.getCurrentDep().getKey().equals(info.getRecommendedDependency().getKey())) { + if (info.getCurrentDep().isPlatformExtension()) { + removedExtensions.computeIfAbsent(info.getCurrentDep().getProviderKey(), k -> new ArrayList<>()) + .add(info.getCurrentDep().getArtifact()); + } else { + nonPlatformExtensionUpdates.computeIfAbsent(info.getCurrentDep().getProviderKey(), k -> new ArrayList<>()) + .add(info); + } + if (info.getRecommendedDependency().isPlatformExtension()) { + addedExtensions.computeIfAbsent(info.getRecommendedDependency().getProviderKey(), k -> new ArrayList<>()) + .add(info.getRecommendedDependency().getArtifact()); + } else { + nonPlatformExtensionUpdates + .computeIfAbsent(info.getRecommendedDependency().getProviderKey(), k -> new ArrayList<>()) + .add(info); + } + } else if (info.getRecommendedDependency().isPlatformExtension()) { + if (info.getCurrentDep().isNonRecommendedVersion()) { + versionedManagedExtensions + .computeIfAbsent(info.getRecommendedDependency().getProviderKey(), k -> new ArrayList<>()) + .add(info); + } + } else if (!info.getCurrentDep().getVersion().equals(info.getRecommendedDependency().getVersion())) { + nonPlatformExtensionUpdates + .computeIfAbsent(info.getRecommendedDependency().getProviderKey(), k -> new ArrayList<>()).add(info); + } + } + return new ProjectExtensionsUpdateInfo(versionedManagedExtensions, removedExtensions, addedExtensions, + nonPlatformExtensionUpdates); + } + + public static ProjectPlatformUpdateInfo resolvePlatformUpdateInfo(ProjectState currentState, + ProjectState recommendedState) { + checkProjectState(currentState, recommendedState); + + final Map platformImports = new LinkedHashMap<>(); + for (ArtifactCoords c : currentState.getPlatformBoms()) { + final PlatformInfo info = new PlatformInfo(c, null); + platformImports.put(c.getKey(), info); + } + List importVersionUpdates = new ArrayList<>(); + List newImports = new ArrayList<>(0); + for (ArtifactCoords c : recommendedState.getPlatformBoms()) { + final PlatformInfo importInfo = platformImports.compute(c.getKey(), (k, v) -> { + if (v == null) { + return new PlatformInfo(null, c); + } + return new PlatformInfo(v.getImported(), c); + }); + if (importInfo.isToBeImported()) { + newImports.add(importInfo); + } else if (importInfo.isVersionUpdateRecommended()) { + importVersionUpdates.add(importInfo); + } + } + return new ProjectPlatformUpdateInfo(platformImports, importVersionUpdates, newImports); + } + + private static void checkProjectState(ProjectState currentState, ProjectState recommendedState) { + if (currentState.getPlatformBoms().isEmpty()) { + throw new IllegalStateException("The project does not import any Quarkus platform BOM"); + } + if (currentState.getExtensions().isEmpty()) { + throw new IllegalStateException("Quarkus extension were not found among the project dependencies"); + } + if (currentState == recommendedState) { + throw new IllegalStateException("The project is up-to-date"); + } + } + + public static ProjectState resolveRecommendedState(ProjectState currentState, ExtensionCatalog recommendedCatalog, + MessageWriter log) { + if (currentState.getPlatformBoms().isEmpty()) { + return currentState; + } + if (currentState.getExtensions().isEmpty()) { + return currentState; + } + + final ExtensionMapBuilder builder = new ExtensionMapBuilder(); + for (TopExtensionDependency dep : currentState.getExtensions()) { + builder.add(new ExtensionUpdateInfoBuilder(dep)); + } + + for (Extension e : recommendedCatalog.getExtensions()) { + final ExtensionUpdateInfoBuilder candidate = builder.get(e.getArtifact().getKey()); + if (candidate != null && candidate.getLatestMetadata() == null) { + // if the latestMetadata has already been initialized, it's already the preferred one + // that could happen if an artifact has relocated + candidate.setLatestMetadata(e); + } + } + + final List unknownExtensions = new ArrayList<>(0); + final List updateCandidates = new ArrayList<>(builder.size()); + final Map updateCandidatesByOrigin = new HashMap<>(); + for (ExtensionUpdateInfoBuilder i : builder.values()) { + if (i.getLatestMetadata() == null) { + unknownExtensions.add(i); + } else { + updateCandidates.add(i.getLatestMetadata()); + for (ExtensionOrigin o : i.getLatestMetadata().getOrigins()) { + updateCandidatesByOrigin.computeIfAbsent(o.getId(), k -> new ExtensionMapBuilder()).add(i); + } + } + } + + if (builder.isEmpty()) { + return currentState; + } + + if (!unknownExtensions.isEmpty()) { + log.warn( + "The configured Quarkus registries did not provide any compatibility information for the following extensions in the context of the currently recommended Quarkus platforms:"); + unknownExtensions.forEach(e -> log.warn(" " + e.getCurrentDep().getArtifact().toCompactCoords())); + } + + final List recommendedOrigins; + try { + recommendedOrigins = getRecommendedOrigins(recommendedCatalog, updateCandidates); + } catch (QuarkusCommandException e) { + log.warn("Failed to find a compatible configuration update for the project"); + return currentState; + } + + int collectedUpdates = 0; + for (ExtensionCatalog recommendedOrigin : recommendedOrigins) { + final ExtensionMapBuilder candidates = updateCandidatesByOrigin.get(recommendedOrigin.getId()); + for (Extension e : recommendedOrigin.getExtensions()) { + final ExtensionUpdateInfoBuilder info = candidates.get(e.getArtifact().getKey()); + if (info != null && info.getRecommendedMetadata() == null) { + info.setRecommendedMetadata(e); + if (++collectedUpdates == updateCandidates.size()) { + break; + } + } + } + } + + final ProjectState.Builder stateBuilder = ProjectState.builder(); + for (ExtensionCatalog c : recommendedOrigins) { + if (c.isPlatform()) { + stateBuilder.addPlatformBom(c.getBom()); + } + } + + final Map extProviders = new LinkedHashMap<>(recommendedOrigins.size()); + for (ExtensionUpdateInfoBuilder info : builder.values()) { + final TopExtensionDependency ext = info.resolveRecommendedDep(); + stateBuilder.addExtensionDependency(ext); + extProviders.computeIfAbsent(ext.getProviderKey(), k -> ExtensionProvider.builder().setOrigin(ext.getOrigin())) + .addExtension(ext); + } + + extProviders.values().forEach(b -> stateBuilder.addExtensionProvider(b.build())); + + for (ModuleState module : currentState.getModules()) { + final ModuleState.Builder moduleBuilder = ModuleState.builder() + .setMainModule(module.isMain()) + .setWorkspaceModule(module.getWorkspaceModule()); + for (TopExtensionDependency dep : module.getExtensions()) { + final TopExtensionDependency recommendedDep = builder.get(dep.getKey()).resolveRecommendedDep(); + moduleBuilder.addExtensionDependency(recommendedDep); + final ExtensionOrigin origin = recommendedDep.getOrigin(); + if (origin != null && origin.isPlatform()) { + moduleBuilder.addPlatformBom(origin.getBom()); + } + } + stateBuilder.addModule(moduleBuilder.build()); + } + + return stateBuilder.build(); + } + + private static List getRecommendedOrigins(ExtensionCatalog extensionCatalog, List extensions) + throws QuarkusCommandException { + final List extOrigins = new ArrayList<>(extensions.size()); + for (Extension e : extensions) { + addOrigins(extOrigins, e); + } + + final OriginCombination recommendedCombination = OriginSelector.of(extOrigins).calculateRecommendedCombination(); + if (recommendedCombination == null) { + final StringBuilder buf = new StringBuilder(); + buf.append("Failed to determine a compatible Quarkus version for the requested extensions: "); + buf.append(extensions.get(0).getArtifact().getKey().toGacString()); + for (int i = 1; i < extensions.size(); ++i) { + buf.append(", ").append(extensions.get(i).getArtifact().getKey().toGacString()); + } + throw new QuarkusCommandException(buf.toString()); + } + return recommendedCombination.getUniqueSortedOrigins().stream().map(o -> o.getCatalog()).collect(Collectors.toList()); + } + + private static void addOrigins(final List extOrigins, Extension e) { + ExtensionOrigins.Builder eoBuilder = null; + for (ExtensionOrigin o : e.getOrigins()) { + if (!(o instanceof ExtensionCatalog)) { + continue; + } + final ExtensionCatalog c = (ExtensionCatalog) o; + final OriginPreference op = (OriginPreference) c.getMetadata().get("origin-preference"); + if (op == null) { + continue; + } + if (eoBuilder == null) { + eoBuilder = ExtensionOrigins.builder(e.getArtifact().getKey()); + } + eoBuilder.addOrigin(c, op); + } + if (eoBuilder != null) { + extOrigins.add(eoBuilder.build()); + } + } +} diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/QuarkusUpdateCommand.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdateCommand.java similarity index 98% rename from independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/QuarkusUpdateCommand.java rename to independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdateCommand.java index 9709f184cb539..41d4c6ccf6c17 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/QuarkusUpdateCommand.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdateCommand.java @@ -1,6 +1,6 @@ -package io.quarkus.devtools.project.update; +package io.quarkus.devtools.project.update.rewrite; -import static io.quarkus.devtools.project.update.QuarkusUpdateRecipe.RECIPE_IO_QUARKUS_OPENREWRITE_QUARKUS; +import static io.quarkus.devtools.project.update.rewrite.QuarkusUpdateRecipe.RECIPE_IO_QUARKUS_OPENREWRITE_QUARKUS; import java.io.BufferedReader; import java.io.File; diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/QuarkusUpdateException.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdateException.java similarity index 85% rename from independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/QuarkusUpdateException.java rename to independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdateException.java index 6bceefbf0b9cb..755c396fdbe39 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/QuarkusUpdateException.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdateException.java @@ -1,4 +1,4 @@ -package io.quarkus.devtools.project.update; +package io.quarkus.devtools.project.update.rewrite; public class QuarkusUpdateException extends Exception { diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/QuarkusUpdateRecipe.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdateRecipe.java similarity index 97% rename from independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/QuarkusUpdateRecipe.java rename to independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdateRecipe.java index 6df006981e367..2d6339b98ae9d 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/QuarkusUpdateRecipe.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdateRecipe.java @@ -1,4 +1,4 @@ -package io.quarkus.devtools.project.update; +package io.quarkus.devtools.project.update.rewrite; import java.util.ArrayList; import java.util.List; diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/QuarkusUpdateRecipeIO.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdateRecipeIO.java similarity index 97% rename from independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/QuarkusUpdateRecipeIO.java rename to independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdateRecipeIO.java index 964e0e44822ba..c6f6485ddb0d0 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/QuarkusUpdateRecipeIO.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdateRecipeIO.java @@ -1,4 +1,4 @@ -package io.quarkus.devtools.project.update; +package io.quarkus.devtools.project.update.rewrite; import java.io.IOException; import java.nio.file.Files; diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/QuarkusUpdates.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdates.java similarity index 89% rename from independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/QuarkusUpdates.java rename to independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdates.java index 46140c32f074a..3520a54cadeda 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/QuarkusUpdates.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdates.java @@ -1,4 +1,4 @@ -package io.quarkus.devtools.project.update; +package io.quarkus.devtools.project.update.rewrite; import java.io.IOException; import java.nio.file.Path; @@ -6,9 +6,9 @@ import io.quarkus.bootstrap.resolver.maven.MavenArtifactResolver; import io.quarkus.devtools.messagewriter.MessageWriter; import io.quarkus.devtools.project.BuildTool; -import io.quarkus.devtools.project.update.QuarkusUpdatesRepository.FetchResult; -import io.quarkus.devtools.project.update.operations.UpdatePropertyOperation; -import io.quarkus.devtools.project.update.operations.UpgradeGradlePluginOperation; +import io.quarkus.devtools.project.update.rewrite.QuarkusUpdatesRepository.FetchResult; +import io.quarkus.devtools.project.update.rewrite.operations.UpdatePropertyOperation; +import io.quarkus.devtools.project.update.rewrite.operations.UpgradeGradlePluginOperation; public final class QuarkusUpdates { diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/QuarkusUpdatesRepository.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdatesRepository.java similarity index 99% rename from independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/QuarkusUpdatesRepository.java rename to independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdatesRepository.java index b3f86eab45342..1758eba2497df 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/QuarkusUpdatesRepository.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdatesRepository.java @@ -1,4 +1,4 @@ -package io.quarkus.devtools.project.update; +package io.quarkus.devtools.project.update.rewrite; import java.io.IOException; import java.io.InputStream; diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/RewriteOperation.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/RewriteOperation.java similarity index 88% rename from independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/RewriteOperation.java rename to independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/RewriteOperation.java index 1cd866a5ef55e..7e69d0e413720 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/RewriteOperation.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/RewriteOperation.java @@ -1,4 +1,4 @@ -package io.quarkus.devtools.project.update; +package io.quarkus.devtools.project.update.rewrite; import java.util.Map; diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/operations/UpdateDependencyVersionOperation.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/operations/UpdateDependencyVersionOperation.java similarity index 87% rename from independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/operations/UpdateDependencyVersionOperation.java rename to independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/operations/UpdateDependencyVersionOperation.java index 8f6c63b65e4fd..ea47c75b415c6 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/operations/UpdateDependencyVersionOperation.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/operations/UpdateDependencyVersionOperation.java @@ -1,9 +1,9 @@ -package io.quarkus.devtools.project.update.operations; +package io.quarkus.devtools.project.update.rewrite.operations; import java.util.Map; import io.quarkus.devtools.project.BuildTool; -import io.quarkus.devtools.project.update.RewriteOperation; +import io.quarkus.devtools.project.update.rewrite.RewriteOperation; public class UpdateDependencyVersionOperation implements RewriteOperation { diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/operations/UpdateManagedDependencyVersionOperation.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/operations/UpdateManagedDependencyVersionOperation.java similarity index 89% rename from independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/operations/UpdateManagedDependencyVersionOperation.java rename to independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/operations/UpdateManagedDependencyVersionOperation.java index 4959ee7d2e832..172e077f0a1a2 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/operations/UpdateManagedDependencyVersionOperation.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/operations/UpdateManagedDependencyVersionOperation.java @@ -1,9 +1,9 @@ -package io.quarkus.devtools.project.update.operations; +package io.quarkus.devtools.project.update.rewrite.operations; import java.util.Map; import io.quarkus.devtools.project.BuildTool; -import io.quarkus.devtools.project.update.RewriteOperation; +import io.quarkus.devtools.project.update.rewrite.RewriteOperation; public class UpdateManagedDependencyVersionOperation implements RewriteOperation { diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/operations/UpdatePropertyOperation.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/operations/UpdatePropertyOperation.java similarity index 86% rename from independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/operations/UpdatePropertyOperation.java rename to independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/operations/UpdatePropertyOperation.java index 464f625ec42f3..0929c5a8780ae 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/operations/UpdatePropertyOperation.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/operations/UpdatePropertyOperation.java @@ -1,9 +1,9 @@ -package io.quarkus.devtools.project.update.operations; +package io.quarkus.devtools.project.update.rewrite.operations; import java.util.Map; import io.quarkus.devtools.project.BuildTool; -import io.quarkus.devtools.project.update.RewriteOperation; +import io.quarkus.devtools.project.update.rewrite.RewriteOperation; public class UpdatePropertyOperation implements RewriteOperation { diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/operations/UpgradeGradlePluginOperation.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/operations/UpgradeGradlePluginOperation.java similarity index 86% rename from independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/operations/UpgradeGradlePluginOperation.java rename to independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/operations/UpgradeGradlePluginOperation.java index 2ad0899601f87..2fdcbb2a5d71f 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/operations/UpgradeGradlePluginOperation.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/operations/UpgradeGradlePluginOperation.java @@ -1,9 +1,9 @@ -package io.quarkus.devtools.project.update.operations; +package io.quarkus.devtools.project.update.rewrite.operations; import java.util.Map; import io.quarkus.devtools.project.BuildTool; -import io.quarkus.devtools.project.update.RewriteOperation; +import io.quarkus.devtools.project.update.rewrite.RewriteOperation; public class UpgradeGradlePluginOperation implements RewriteOperation { diff --git a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/update/QuarkusUpdateRecipeIOTest.java b/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdateRecipeIOTest.java similarity index 86% rename from independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/update/QuarkusUpdateRecipeIOTest.java rename to independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdateRecipeIOTest.java index 54b7b59986984..1c231d8cc9dc9 100644 --- a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/update/QuarkusUpdateRecipeIOTest.java +++ b/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdateRecipeIOTest.java @@ -1,4 +1,4 @@ -package io.quarkus.devtools.project.update; +package io.quarkus.devtools.project.update.rewrite; import static org.assertj.core.api.Assertions.assertThat; @@ -6,8 +6,8 @@ import org.junit.jupiter.api.Test; -import io.quarkus.devtools.project.update.operations.UpdateManagedDependencyVersionOperation; -import io.quarkus.devtools.project.update.operations.UpdatePropertyOperation; +import io.quarkus.devtools.project.update.rewrite.operations.UpdateManagedDependencyVersionOperation; +import io.quarkus.devtools.project.update.rewrite.operations.UpdatePropertyOperation; class QuarkusUpdateRecipeIOTest { diff --git a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/update/QuarkusUpdatesRepositoryTest.java b/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdatesRepositoryTest.java similarity index 79% rename from independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/update/QuarkusUpdatesRepositoryTest.java rename to independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdatesRepositoryTest.java index 5e4dd6d4935d6..9915e9bdf0fda 100644 --- a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/update/QuarkusUpdatesRepositoryTest.java +++ b/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdatesRepositoryTest.java @@ -1,6 +1,6 @@ -package io.quarkus.devtools.project.update; +package io.quarkus.devtools.project.update.rewrite; -import static io.quarkus.devtools.project.update.QuarkusUpdatesRepository.shouldApplyRecipe; +import static io.quarkus.devtools.project.update.rewrite.QuarkusUpdatesRepository.shouldApplyRecipe; import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.params.ParameterizedTest;