use of io.quarkus.devtools.project.state.ProjectState in project quarkus by quarkusio.
the class InfoCommandHandler method resolveProjectState.
protected static ProjectState resolveProjectState(ApplicationModel appModel, ExtensionCatalog currentCatalog) {
final ProjectState.Builder projectBuilder = ProjectState.builder();
final Collection<ArtifactCoords> importedPlatformBoms = appModel.getPlatforms().getImportedPlatformBoms();
if (importedPlatformBoms.isEmpty()) {
return projectBuilder.build();
}
final Map<String, ExtensionProvider.Builder> 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<WorkspaceModuleId, ModuleState.Builder> projectModuleBuilders = new HashMap<>();
final Map<ArtifactKey, List<ModuleState.Builder>> 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<ArtifactKey, TopExtensionDependency.Builder> 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<ModuleState.Builder> 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();
}
use of io.quarkus.devtools.project.state.ProjectState in project quarkus by quarkusio.
the class UpdateCommandHandler method resolveRecommendedState.
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<ExtensionInfo> unknownExtensions = new ArrayList<>(0);
final List<Extension> updateCandidates = new ArrayList<>(extensionInfo.size());
final Map<String, ExtensionMap> 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<ExtensionCatalog> 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<String, ExtensionProvider.Builder> 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();
}
use of io.quarkus.devtools.project.state.ProjectState in project quarkus by quarkusio.
the class InfoCommandHandler method logModuleInfo.
private static boolean logModuleInfo(ProjectState project, ModuleState module, Path baseDir, MessageWriter log, boolean rectify) {
if (module.getExtensions().isEmpty() && module.getPlatformBoms().isEmpty() && !module.isMain()) {
return false;
}
boolean recommendationsAvailable = false;
final StringBuilder sb = new StringBuilder();
if (module.isMain()) {
sb.append("Main application module ");
} else {
sb.append("Module ");
}
sb.append(module.getId().getGroupId()).append(':').append(module.getId().getArtifactId()).append(':');
log.info(sb.toString());
final Iterator<Path> i = module.getWorkspaceModule().getBuildFiles().iterator();
if (i.hasNext()) {
sb.setLength(0);
sb.append(" Build file: ");
sb.append(baseDir.relativize(i.next()));
while (i.hasNext()) {
sb.append(", ").append(baseDir.relativize(i.next()));
}
log.info(sb.toString());
}
if (!module.getPlatformBoms().isEmpty()) {
log.info(" Platform BOMs:");
for (ArtifactCoords bom : module.getPlatformBoms()) {
log.info(" " + bom.toCompactCoords());
}
}
if (!module.getExtensions().isEmpty()) {
final Map<String, List<TopExtensionDependency>> extDepsByProvider = new LinkedHashMap<>();
for (TopExtensionDependency dep : module.getExtensions()) {
extDepsByProvider.computeIfAbsent(dep.getProviderKey(), k -> new ArrayList<>()).add(dep);
}
for (ExtensionProvider provider : project.getExtensionProviders()) {
if (!provider.isPlatform()) {
continue;
}
final List<TopExtensionDependency> extList = extDepsByProvider.getOrDefault(provider.getKey(), Collections.emptyList());
if (!extList.isEmpty()) {
log.info(" Extensions from " + provider.getKey() + ":");
for (TopExtensionDependency dep : extList) {
sb.setLength(0);
sb.append(" ");
recommendationsAvailable = logExtensionInfo(dep, rectify, sb, recommendationsAvailable);
log.info(sb.toString());
}
log.info("");
}
}
for (ExtensionProvider provider : project.getExtensionProviders()) {
if (provider.isPlatform()) {
continue;
}
final List<TopExtensionDependency> extList = extDepsByProvider.getOrDefault(provider.getKey(), Collections.emptyList());
if (!extList.isEmpty()) {
log.info(" Extensions from " + provider.getKey() + ":");
for (TopExtensionDependency dep : extList) {
sb.setLength(0);
sb.append(" ");
recommendationsAvailable = logExtensionInfo(dep, rectify, sb, recommendationsAvailable);
log.info(sb.toString());
}
log.info("");
}
}
}
return recommendationsAvailable;
}
use of io.quarkus.devtools.project.state.ProjectState in project quarkus by quarkusio.
the class UpdateCommandHandler method logUpdates.
private static void logUpdates(ProjectState currentState, ExtensionCatalog recommendedCatalog, boolean recommendState, boolean perModule, MessageWriter log) {
if (currentState.getPlatformBoms().isEmpty()) {
log.info("The project does not import any Quarkus platform BOM");
return;
}
if (currentState.getExtensions().isEmpty()) {
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;
}
if (recommendState) {
InfoCommandHandler.logState(recommendedState, perModule, false, log);
return;
}
// log instructions
final Map<ArtifactKey, PlatformInfo> platformImports = new LinkedHashMap<>();
for (ArtifactCoords c : currentState.getPlatformBoms()) {
final PlatformInfo info = new PlatformInfo();
info.imported = c;
platformImports.put(c.getKey(), info);
}
List<PlatformInfo> importVersionUpdates = new ArrayList<>();
List<PlatformInfo> 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) {
log.info("Recommended Quarkus platform BOM updates:");
if (!importVersionUpdates.isEmpty()) {
for (PlatformInfo importInfo : importVersionUpdates) {
log.info(String.format(UpdateCommandHandler.PLATFORM_RECTIFY_FORMAT, UpdateCommandHandler.UPDATE, importInfo.imported.toCompactCoords()) + " -> " + importInfo.getRecommendedVersion());
}
}
if (!newImports.isEmpty()) {
for (PlatformInfo importInfo : newImports) {
log.info(String.format(UpdateCommandHandler.PLATFORM_RECTIFY_FORMAT, UpdateCommandHandler.ADD, importInfo.recommended.toCompactCoords()));
}
}
if (importsToBeRemoved) {
for (PlatformInfo importInfo : platformImports.values()) {
if (importInfo.recommended == null) {
log.info(String.format(UpdateCommandHandler.PLATFORM_RECTIFY_FORMAT, UpdateCommandHandler.REMOVE, importInfo.imported.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<String, List<ExtensionInfo>> versionedManagedExtensions = new LinkedHashMap<>(0);
final Map<String, List<ArtifactCoords>> removedExtensions = new LinkedHashMap<>(0);
final Map<String, List<ArtifactCoords>> addedExtensions = new LinkedHashMap<>(0);
final Map<String, List<ExtensionInfo>> 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) {
log.info("The project is up-to-date");
}
return;
}
for (PlatformInfo platform : platformImports.values()) {
final String provider = platform.getRecommendedProviderKey();
if (!versionedManagedExtensions.containsKey(provider) && !removedExtensions.containsKey(provider) && !addedExtensions.containsKey(provider)) {
continue;
}
log.info("Extensions from " + platform.getRecommendedProviderKey() + ":");
for (ExtensionInfo e : versionedManagedExtensions.getOrDefault(provider, Collections.emptyList())) {
final StringBuilder sb = new StringBuilder();
sb.append(String.format(UpdateCommandHandler.PLATFORM_RECTIFY_FORMAT, UpdateCommandHandler.UPDATE, e.currentDep.getArtifact().toCompactCoords()));
sb.append(" -> remove version (managed)");
log.info(sb.toString());
}
for (ArtifactCoords e : addedExtensions.getOrDefault(provider, Collections.emptyList())) {
log.info(String.format(UpdateCommandHandler.PLATFORM_RECTIFY_FORMAT, UpdateCommandHandler.ADD, e.getKey().toGacString()));
}
for (ArtifactCoords e : removedExtensions.getOrDefault(provider, Collections.emptyList())) {
log.info(String.format(UpdateCommandHandler.PLATFORM_RECTIFY_FORMAT, UpdateCommandHandler.REMOVE, e.getKey().toGacString()));
}
log.info("");
}
if (!nonPlatformExtensionUpdates.isEmpty()) {
for (Map.Entry<String, List<ExtensionInfo>> provider : nonPlatformExtensionUpdates.entrySet()) {
log.info("Extensions from " + provider.getKey() + ":");
for (ExtensionInfo info : provider.getValue()) {
if (info.currentDep.isPlatformExtension()) {
log.info(String.format(UpdateCommandHandler.PLATFORM_RECTIFY_FORMAT, UpdateCommandHandler.ADD, info.getRecommendedDependency().getArtifact().toCompactCoords()));
} else if (info.getRecommendedDependency().isPlatformExtension()) {
log.info(String.format(UpdateCommandHandler.PLATFORM_RECTIFY_FORMAT, UpdateCommandHandler.REMOVE, info.currentDep.getArtifact().toCompactCoords()));
} else {
log.info(String.format(UpdateCommandHandler.PLATFORM_RECTIFY_FORMAT, UpdateCommandHandler.UPDATE, info.currentDep.getArtifact().toCompactCoords() + " -> " + info.getRecommendedDependency().getVersion()));
}
}
log.info("");
}
}
}
use of io.quarkus.devtools.project.state.ProjectState in project quarkus by quarkusio.
the class UpdateCommandHandler method execute.
@Override
public QuarkusCommandOutcome execute(QuarkusCommandInvocation invocation) throws QuarkusCommandException {
final ApplicationModel appModel = invocation.getValue(APP_MODEL);
final ExtensionCatalog latestCatalog = invocation.getValue(UpdateCommandHandler.LATEST_CATALOG);
final boolean logRecommendedState = invocation.getValue(UpdateCommandHandler.LOG_RECOMMENDED_STATE, false);
final boolean logStatePerModule = invocation.getValue(UpdateCommandHandler.LOG_STATE_PER_MODULE, false);
final boolean rectify = invocation.getValue(UpdateCommandHandler.RECTIFY, false);
if (logStatePerModule && !rectify) {
throw new QuarkusCommandException("Update per module isn't supported yet!");
}
final ProjectState currentState = InfoCommandHandler.resolveProjectState(appModel, invocation.getQuarkusProject().getExtensionsCatalog());
if (rectify) {
InfoCommandHandler.logState(currentState, logStatePerModule, rectify, invocation.getQuarkusProject().log());
} else {
logUpdates(currentState, latestCatalog, logRecommendedState, logStatePerModule, invocation.getQuarkusProject().log());
}
return QuarkusCommandOutcome.success();
}
Aggregations