From 88c6f8b7747e83bbef78a3b436a42da3ec6986b5 Mon Sep 17 00:00:00 2001 From: Erin Schnabel Date: Thu, 30 Sep 2021 18:13:33 -0400 Subject: [PATCH] CLI: nix CreateProjectMixin; fix base commands --- .../src/main/java/io/quarkus/cli/Create.java | 12 +- .../main/java/io/quarkus/cli/CreateApp.java | 22 +- .../main/java/io/quarkus/cli/CreateCli.java | 22 +- .../java/io/quarkus/cli/CreateExtension.java | 18 +- .../io/quarkus/cli/ProjectExtensions.java | 10 +- .../main/java/io/quarkus/cli/Registry.java | 12 +- .../io/quarkus/cli/RegistryAddCommand.java | 4 - .../io/quarkus/cli/RegistryListCommand.java | 4 - .../io/quarkus/cli/RegistryRemoveCommand.java | 4 - .../quarkus/cli/create/BaseCreateCommand.java | 256 +++++++++++++++++- .../cli/create/CreateProjectMixin.java | 195 ------------- .../cli/registry/BaseRegistryCommand.java | 3 +- .../cli/registry/RegistryClientMixin.java | 2 +- .../test/java/io/quarkus/cli/CliHelpTest.java | 2 - .../project/codegen/CreateProjectHelper.java | 2 +- 15 files changed, 306 insertions(+), 262 deletions(-) delete mode 100644 devtools/cli/src/main/java/io/quarkus/cli/create/CreateProjectMixin.java diff --git a/devtools/cli/src/main/java/io/quarkus/cli/Create.java b/devtools/cli/src/main/java/io/quarkus/cli/Create.java index 2897b2898cdc4..6b9e608ec9df5 100644 --- a/devtools/cli/src/main/java/io/quarkus/cli/Create.java +++ b/devtools/cli/src/main/java/io/quarkus/cli/Create.java @@ -1,8 +1,9 @@ package io.quarkus.cli; import java.util.List; +import java.util.concurrent.Callable; -import io.quarkus.cli.create.BaseCreateCommand; +import io.quarkus.cli.common.OutputOptionMixin; import picocli.CommandLine; import picocli.CommandLine.ParseResult; import picocli.CommandLine.Unmatched; @@ -11,12 +12,17 @@ CreateApp.class, CreateCli.class, CreateExtension.class }, headerHeading = "%n", commandListHeading = "%nCommands:%n", synopsisHeading = "%nUsage: ", optionListHeading = "%nOptions:%n") -public class Create extends BaseCreateCommand { +public class Create implements Callable { + + @CommandLine.Mixin + protected OutputOptionMixin output; + + @CommandLine.Spec + protected CommandLine.Model.CommandSpec spec; @Unmatched // avoids throwing errors for unmatched arguments List unmatchedArgs; - @Override public Integer call() throws Exception { output.info("Creating an app (default project type, see --help)."); diff --git a/devtools/cli/src/main/java/io/quarkus/cli/CreateApp.java b/devtools/cli/src/main/java/io/quarkus/cli/CreateApp.java index 1a5b9ccc068e7..01212905e640b 100644 --- a/devtools/cli/src/main/java/io/quarkus/cli/CreateApp.java +++ b/devtools/cli/src/main/java/io/quarkus/cli/CreateApp.java @@ -7,7 +7,6 @@ import io.quarkus.cli.common.TargetQuarkusVersionGroup; import io.quarkus.cli.create.BaseCreateCommand; import io.quarkus.cli.create.CodeGenerationGroup; -import io.quarkus.cli.create.CreateProjectMixin; import io.quarkus.cli.create.TargetBuildToolGroup; import io.quarkus.cli.create.TargetGAVGroup; import io.quarkus.cli.create.TargetLanguageGroup; @@ -25,9 +24,6 @@ + "it will use Maven to build an artifact with GROUP-ID='org.acme', ARTIFACT-ID='code-with-quarkus', and VERSION='1.0.0-SNAPSHOT'." + "%n" }, headerHeading = "%n", commandListHeading = "%nCommands:%n", synopsisHeading = "%nUsage: ", parameterListHeading = "%n", optionListHeading = "Options:%n") public class CreateApp extends BaseCreateCommand { - @Mixin - CreateProjectMixin createProject; - @Mixin TargetGAVGroup gav = new TargetGAVGroup(); @@ -56,24 +52,24 @@ public Integer call() throws Exception { output.debug("Creating a new project with initial parameters: %s", this); output.throwIfUnmatchedArguments(spec.commandLine()); - createProject.setSingleProjectGAV(gav); - createProject.setTestOutputDirectory(output.getTestDirectory()); - if (createProject.checkProjectRootAlreadyExists(output, runMode.isDryRun())) { + setSingleProjectGAV(gav); + setTestOutputDirectory(output.getTestDirectory()); + if (checkProjectRootAlreadyExists(runMode.isDryRun())) { return CommandLine.ExitCode.USAGE; } BuildTool buildTool = targetBuildTool.getBuildTool(BuildTool.MAVEN); SourceType sourceType = targetLanguage.getSourceType(buildTool, extensions, output); - createProject.setSourceTypeExtensions(extensions, sourceType); - createProject.setCodegenOptions(codeGeneration); + setSourceTypeExtensions(extensions, sourceType); + setCodegenOptions(codeGeneration); - QuarkusCommandInvocation invocation = createProject.build(buildTool, targetQuarkusVersion, - output, propertiesOptions.properties); + QuarkusCommandInvocation invocation = build(buildTool, targetQuarkusVersion, + propertiesOptions.properties); boolean success = true; if (runMode.isDryRun()) { - createProject.dryRun(buildTool, invocation, output); + dryRun(buildTool, invocation, output); } else if (buildTool == BuildTool.JBANG) { success = new CreateJBangProjectCommandHandler().execute(invocation).isSuccess(); } else { // maven or gradle @@ -103,7 +99,7 @@ public String toString() { + ", targetLanguage=" + targetLanguage + ", codeGeneration=" + codeGeneration + ", extensions=" + extensions - + ", project=" + createProject + + ", project=" + super.toString() + ", properties=" + propertiesOptions.properties + '}'; } diff --git a/devtools/cli/src/main/java/io/quarkus/cli/CreateCli.java b/devtools/cli/src/main/java/io/quarkus/cli/CreateCli.java index a8ec76ca16c91..0cb3452008a54 100644 --- a/devtools/cli/src/main/java/io/quarkus/cli/CreateCli.java +++ b/devtools/cli/src/main/java/io/quarkus/cli/CreateCli.java @@ -7,7 +7,6 @@ import io.quarkus.cli.common.TargetQuarkusVersionGroup; import io.quarkus.cli.create.BaseCreateCommand; import io.quarkus.cli.create.CodeGenerationGroup; -import io.quarkus.cli.create.CreateProjectMixin; import io.quarkus.cli.create.TargetBuildToolGroup; import io.quarkus.cli.create.TargetGAVGroup; import io.quarkus.cli.create.TargetLanguageGroup; @@ -25,9 +24,6 @@ + "it will use Maven to build an artifact with GROUP-ID='org.acme', ARTIFACT-ID='code-with-quarkus', and VERSION='1.0.0-SNAPSHOT'." + "%n" }, headerHeading = "%n", commandListHeading = "%nCommands:%n", synopsisHeading = "%nUsage: ", parameterListHeading = "%n", optionListHeading = "Options:%n") public class CreateCli extends BaseCreateCommand { - @Mixin - CreateProjectMixin createProject; - @Mixin TargetGAVGroup gav = new TargetGAVGroup(); @@ -58,23 +54,23 @@ public Integer call() throws Exception { extensions.add("picocli"); // make sure picocli is selected. - createProject.setSingleProjectGAV(gav); - createProject.setTestOutputDirectory(output.getTestDirectory()); - if (createProject.checkProjectRootAlreadyExists(output, false)) { + setSingleProjectGAV(gav); + setTestOutputDirectory(output.getTestDirectory()); + if (checkProjectRootAlreadyExists(false)) { return CommandLine.ExitCode.USAGE; } BuildTool buildTool = targetBuildTool.getBuildTool(BuildTool.MAVEN); SourceType sourceType = targetLanguage.getSourceType(buildTool, extensions, output); - createProject.setSourceTypeExtensions(extensions, sourceType); - createProject.setCodegenOptions(codeGeneration); + setSourceTypeExtensions(extensions, sourceType); + setCodegenOptions(codeGeneration); - QuarkusCommandInvocation invocation = createProject.build(buildTool, targetQuarkusVersion, - output, propertiesOptions.properties); + QuarkusCommandInvocation invocation = build(buildTool, targetQuarkusVersion, + propertiesOptions.properties); boolean success = true; if (runMode.isDryRun()) { - createProject.dryRun(buildTool, invocation, output); + dryRun(buildTool, invocation, output); } else if (BuildTool.JBANG.equals(buildTool)) { success = new CreateJBangProjectCommandHandler().execute(invocation).isSuccess(); } else { @@ -104,7 +100,7 @@ public String toString() { + ", targetLanguage=" + targetLanguage + ", codeGeneration=" + codeGeneration + ", extensions=" + extensions - + ", project=" + createProject + + ", project=" + super.toString() + ", properties=" + propertiesOptions.properties + '}'; } diff --git a/devtools/cli/src/main/java/io/quarkus/cli/CreateExtension.java b/devtools/cli/src/main/java/io/quarkus/cli/CreateExtension.java index 89ed54e147aae..56be79742c16f 100644 --- a/devtools/cli/src/main/java/io/quarkus/cli/CreateExtension.java +++ b/devtools/cli/src/main/java/io/quarkus/cli/CreateExtension.java @@ -7,7 +7,6 @@ import io.quarkus.cli.common.PropertiesOptions; import io.quarkus.cli.common.TargetQuarkusVersionGroup; import io.quarkus.cli.create.BaseCreateCommand; -import io.quarkus.cli.create.CreateProjectMixin; import io.quarkus.cli.create.ExtensionGAVMixin; import io.quarkus.cli.create.ExtensionNameGenerationGroup; import io.quarkus.cli.create.ExtensionTestGenerationGroup; @@ -73,9 +72,6 @@ public class CreateExtension extends BaseCreateCommand { @CommandLine.Spec protected CommandLine.Model.CommandSpec spec; - @Mixin - CreateProjectMixin createProject; - @Mixin ExtensionGAVMixin gav = new ExtensionGAVMixin(); @@ -97,19 +93,19 @@ public Integer call() throws Exception { output.debug("Creating a new extension project with initial parameters: %s", this); output.throwIfUnmatchedArguments(spec.commandLine()); - createProject.setExtensionId(gav.getExtensionId()); - createProject.setTestOutputDirectory(output.getTestDirectory()); - if (createProject.checkProjectRootAlreadyExists(output, runMode.isDryRun())) { + setExtensionId(gav.getExtensionId()); + setTestOutputDirectory(output.getTestDirectory()); + if (checkProjectRootAlreadyExists(runMode.isDryRun())) { return CommandLine.ExitCode.USAGE; } BuildTool buildTool = BuildTool.MAVEN; - QuarkusProject quarkusProject = createProject.getExtensionVersions(buildTool, targetQuarkusVersion, output); + QuarkusProject quarkusProject = getExtensionVersions(buildTool, targetQuarkusVersion); ExtensionCatalog catalog = quarkusProject.getExtensionsCatalog(); ArtifactCoords quarkusBom = catalog.getBom(); final CreateExtensionCommandHandler createExtension = new io.quarkus.devtools.commands.CreateExtension( - createProject.outputDirectory()) + outputDirectory()) .extensionId(gav.getExtensionId()) .groupId(gav.getGroupId()) .version(gav.getVersion()) @@ -153,12 +149,12 @@ public void dryRun(BuildTool buildTool, CreateExtensionCommandHandler invocation CommandLine.Help help = spec.commandLine().getHelp(); output.printText(new String[] { "\nA new extension would have been created in", - "\t" + createProject.outputDirectory().toString(), + "\t" + outputDirectory().toString(), "\nThe extension would have been created using the following settings:\n" }); Map dryRunOutput = new TreeMap<>(); for (Map.Entry entry : invocation.getData().entrySet()) { - dryRunOutput.put(createProject.prettyName(entry.getKey()), entry.getValue().toString()); + dryRunOutput.put(prettyName(entry.getKey()), entry.getValue().toString()); } dryRunOutput.put("Skip Unit Test", "" + testGeneration.skipUnitTest()); dryRunOutput.put("Skip Dev-mode Test", "" + testGeneration.skipDevModeTest()); diff --git a/devtools/cli/src/main/java/io/quarkus/cli/ProjectExtensions.java b/devtools/cli/src/main/java/io/quarkus/cli/ProjectExtensions.java index f246f4f4715cf..d37dbcd1f4f80 100644 --- a/devtools/cli/src/main/java/io/quarkus/cli/ProjectExtensions.java +++ b/devtools/cli/src/main/java/io/quarkus/cli/ProjectExtensions.java @@ -4,7 +4,7 @@ import java.util.concurrent.Callable; import java.util.stream.Collectors; -import io.quarkus.cli.build.BaseBuildCommand; +import io.quarkus.cli.common.OutputOptionMixin; import picocli.CommandLine; import picocli.CommandLine.ParseResult; import picocli.CommandLine.Unmatched; @@ -15,7 +15,13 @@ ProjectExtensionsCategories.class, ProjectExtensionsAdd.class, ProjectExtensionsRemove.class }, headerHeading = "%n", commandListHeading = "%nCommands:%n", synopsisHeading = "%nUsage: ", optionListHeading = "Options:%n") -public class ProjectExtensions extends BaseBuildCommand implements Callable { +public class ProjectExtensions implements Callable { + + @CommandLine.Mixin + protected OutputOptionMixin output; + + @CommandLine.Spec + protected CommandLine.Model.CommandSpec spec; @Unmatched // avoids throwing errors for unmatched arguments List unmatchedArgs; diff --git a/devtools/cli/src/main/java/io/quarkus/cli/Registry.java b/devtools/cli/src/main/java/io/quarkus/cli/Registry.java index 88749ccbe7f44..9b2fb38fb3b94 100644 --- a/devtools/cli/src/main/java/io/quarkus/cli/Registry.java +++ b/devtools/cli/src/main/java/io/quarkus/cli/Registry.java @@ -1,8 +1,9 @@ package io.quarkus.cli; import java.util.List; +import java.util.concurrent.Callable; -import io.quarkus.cli.registry.BaseRegistryCommand; +import io.quarkus.cli.common.OutputOptionMixin; import picocli.CommandLine; import picocli.CommandLine.ParseResult; import picocli.CommandLine.Unmatched; @@ -11,12 +12,17 @@ RegistryListCommand.class, RegistryAddCommand.class, RegistryRemoveCommand.class }, headerHeading = "%n", commandListHeading = "%nCommands:%n", synopsisHeading = "%nUsage: ", optionListHeading = "%nOptions:%n") -public class Registry extends BaseRegistryCommand { +public class Registry implements Callable { + + @CommandLine.Mixin + protected OutputOptionMixin output; + + @CommandLine.Spec + protected CommandLine.Model.CommandSpec spec; @Unmatched // avoids throwing errors for unmatched arguments List unmatchedArgs; - @Override public Integer call() throws Exception { final ParseResult result = spec.commandLine().getParseResult(); final CommandLine appCommand = spec.subcommands().get("list"); diff --git a/devtools/cli/src/main/java/io/quarkus/cli/RegistryAddCommand.java b/devtools/cli/src/main/java/io/quarkus/cli/RegistryAddCommand.java index 73194c506c8e3..ed92697759b13 100644 --- a/devtools/cli/src/main/java/io/quarkus/cli/RegistryAddCommand.java +++ b/devtools/cli/src/main/java/io/quarkus/cli/RegistryAddCommand.java @@ -7,7 +7,6 @@ import java.util.stream.Collectors; import io.quarkus.cli.registry.BaseRegistryCommand; -import io.quarkus.cli.registry.RegistryClientMixin; import io.quarkus.registry.config.RegistriesConfig; import io.quarkus.registry.config.RegistriesConfigLocator; import io.quarkus.registry.config.RegistryConfig; @@ -20,9 +19,6 @@ + "This command will add a Quarkus extension registry to the registry client configuration unless it's already present.", headerHeading = "%n", commandListHeading = "%nCommands:%n", synopsisHeading = "%nUsage: ", parameterListHeading = "%n", optionListHeading = "Options:%n") public class RegistryAddCommand extends BaseRegistryCommand { - @CommandLine.Mixin - protected RegistryClientMixin registryClient; - @CommandLine.Parameters(arity = "0..1", paramLabel = "REGISTRY-ID[,REGISTRY-ID]", description = "Registry ID to add to the registry client configuration%n" + " Example:%n" + " registry.quarkus.io%n" diff --git a/devtools/cli/src/main/java/io/quarkus/cli/RegistryListCommand.java b/devtools/cli/src/main/java/io/quarkus/cli/RegistryListCommand.java index 79879122707bb..b78639aececbf 100644 --- a/devtools/cli/src/main/java/io/quarkus/cli/RegistryListCommand.java +++ b/devtools/cli/src/main/java/io/quarkus/cli/RegistryListCommand.java @@ -3,7 +3,6 @@ import java.nio.file.Path; import io.quarkus.cli.registry.BaseRegistryCommand; -import io.quarkus.cli.registry.RegistryClientMixin; import io.quarkus.registry.ExtensionCatalogResolver; import io.quarkus.registry.catalog.Platform; import io.quarkus.registry.catalog.PlatformCatalog; @@ -17,9 +16,6 @@ + "This command will list currently enabled Quarkus extension registries.", headerHeading = "%n", commandListHeading = "%nCommands:%n", synopsisHeading = "%nUsage: ", parameterListHeading = "%n", optionListHeading = "Options:%n") public class RegistryListCommand extends BaseRegistryCommand { - @CommandLine.Mixin - protected RegistryClientMixin registryClient; - @CommandLine.Option(names = { "--streams" }, description = "List currently recommended platform streams", defaultValue = "false") boolean streams; diff --git a/devtools/cli/src/main/java/io/quarkus/cli/RegistryRemoveCommand.java b/devtools/cli/src/main/java/io/quarkus/cli/RegistryRemoveCommand.java index 6d159ce28e51f..c9ab8188b52ec 100644 --- a/devtools/cli/src/main/java/io/quarkus/cli/RegistryRemoveCommand.java +++ b/devtools/cli/src/main/java/io/quarkus/cli/RegistryRemoveCommand.java @@ -7,7 +7,6 @@ import java.util.Map; import io.quarkus.cli.registry.BaseRegistryCommand; -import io.quarkus.cli.registry.RegistryClientMixin; import io.quarkus.registry.config.RegistriesConfig; import io.quarkus.registry.config.RegistriesConfigLocator; import io.quarkus.registry.config.RegistryConfig; @@ -19,9 +18,6 @@ + "This command will remove a Quarkus extension registry from the registry client configuration.", headerHeading = "%n", commandListHeading = "%nCommands:%n", synopsisHeading = "%nUsage: ", parameterListHeading = "%n", optionListHeading = "Options:%n") public class RegistryRemoveCommand extends BaseRegistryCommand { - @CommandLine.Mixin - protected RegistryClientMixin registryClient; - @CommandLine.Parameters(arity = "0..1", paramLabel = "REGISTRY-ID[,REGISTRY-ID]", description = "Registry ID to remove from the registry client configuration%n" + " Example:%n" + " registry.quarkus.io%n" diff --git a/devtools/cli/src/main/java/io/quarkus/cli/create/BaseCreateCommand.java b/devtools/cli/src/main/java/io/quarkus/cli/create/BaseCreateCommand.java index 708023858a416..7a398062a6676 100644 --- a/devtools/cli/src/main/java/io/quarkus/cli/create/BaseCreateCommand.java +++ b/devtools/cli/src/main/java/io/quarkus/cli/create/BaseCreateCommand.java @@ -1,32 +1,280 @@ package io.quarkus.cli.create; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; import java.util.concurrent.Callable; -import io.quarkus.cli.common.HelpOption; import io.quarkus.cli.common.OutputOptionMixin; import io.quarkus.cli.common.RunModeOption; +import io.quarkus.cli.common.TargetQuarkusVersionGroup; +import io.quarkus.cli.registry.ToggleRegistryClientMixin; +import io.quarkus.devtools.commands.CreateProject; +import io.quarkus.devtools.commands.data.QuarkusCommandInvocation; +import io.quarkus.devtools.project.BuildTool; +import io.quarkus.devtools.project.QuarkusProject; +import io.quarkus.devtools.project.codegen.CreateProjectHelper; +import io.quarkus.devtools.project.codegen.ProjectGenerator; +import io.quarkus.devtools.project.codegen.SourceType; +import io.quarkus.registry.RegistryResolutionException; import picocli.CommandLine; import picocli.CommandLine.Mixin; import picocli.CommandLine.Model.CommandSpec; import picocli.CommandLine.Spec; public class BaseCreateCommand implements Callable { - @Mixin protected RunModeOption runMode; - @Mixin(name = "output") + @Mixin protected OutputOptionMixin output; @Mixin - protected HelpOption helpOption; + ToggleRegistryClientMixin registryClient; @Spec protected CommandSpec spec; + @CommandLine.Option(paramLabel = "OUTPUT-DIR", names = { "-o", + "--output-directory" }, description = "The directory to create the new project in.") + String targetDirectory; + + /** + * Parameters gathered for project creation + */ + private Map values = new HashMap<>(); + + /** + * Output path. Computed from {@link #targetDirectory} parameter. + * + * @see #outputDirectory() + */ + private Path outputPath; + + /** + * Project root directory. Computed from/within Output path. + * + * @see #checkProjectRootAlreadyExists(boolean) + * @see #projectRoot() + */ + private Path projectRootPath; + + /** + * Project directory name, used with {@link #outputPath} to + * compute {@link #projectRootPath}. + * + * @see #setExtensionId(String) + * @see #setSingleProjectGAV(TargetGAVGroup) + */ + private String projectDirName; + + /** + * If a targetDirectory parameter was not specified, and this was, + * set this as output path. + * + * @param testOutputDirectory The path to use as the output directory if the target directory was not specified, or null + */ + public void setTestOutputDirectory(Path testOutputDirectory) { + if (testOutputDirectory != null && targetDirectory == null) { + outputPath = testOutputDirectory; + } + } + + /** + * Resolve (and create, if necessary) the target output directory. + * + * @return the output directory path + */ + public Path outputDirectory() { + if (outputPath == null) { + outputPath = CreateProjectHelper.createOutputDirectory(targetDirectory); + } + return outputPath; + } + + /** + * @param targetGav Group, Artifact, and Version for the single-module project. + * The artifactId is used as the directory name. + */ + public void setSingleProjectGAV(TargetGAVGroup targetGav) { + projectDirName = targetGav.getArtifactId(); + + setValue(ProjectGenerator.PROJECT_GROUP_ID, targetGav.getGroupId()); + setValue(ProjectGenerator.PROJECT_ARTIFACT_ID, targetGav.getArtifactId()); + setValue(ProjectGenerator.PROJECT_VERSION, targetGav.getVersion()); + } + + /** + * @param extensionId Extension id to be used as project directory name + */ + public void setExtensionId(String extensionId) { + projectDirName = extensionId; + } + + /** + * Resolve and remember the configured project directory. + * + * @param dryRun If true, warn that the directory already exists; otherwise, print an error message. + * @return true IFF configured project root directory already exists and this is not a dry run; + * in other words, return true if caller should exit with an error. + */ + public boolean checkProjectRootAlreadyExists(boolean dryRun) { + if (projectRootPath == null) { + try { + projectRootPath = CreateProjectHelper.checkProjectRootPath(outputDirectory(), projectDirName); + } catch (IllegalArgumentException iex) { + if (dryRun) { + output.warn("A directory named '" + projectDirName + "' already exists."); + projectRootPath = outputDirectory().resolve(projectDirName); + } else { + output.error(iex.getMessage()); + output.out().printf("Specify a different artifactId / directory name.%n"); + output.out().printf("See '%s --help' for more information.%n", spec.qualifiedName()); + return true; + } + } + } + return false; + } + + /** + * Resolve the target output directory. Will throw if the target directory exists + * + * @return the project root path + */ + public Path projectRoot() { + if (projectRootPath == null) { + projectRootPath = CreateProjectHelper.checkProjectRootPath(outputDirectory(), projectDirName); + } + return projectRootPath; + } + + /** + * Add explicitly specified and sourceType-implied extensions + * + * @param extensions Explicitly specified extensions + * @param sourceType Type of source (Kotlin, Java, Scala) + */ + public void setSourceTypeExtensions(Set extensions, SourceType sourceType) { + extensions = CreateProjectHelper.sanitizeExtensions(extensions); + CreateProjectHelper.addSourceTypeExtensions(extensions, sourceType); + + setValue(ProjectGenerator.SOURCE_TYPE, sourceType); + setValue(ProjectGenerator.EXTENSIONS, extensions); + } + + /** + * Process code generation options (save values) + * + * @param codeGeneration + */ + public void setCodegenOptions(CodeGenerationGroup codeGeneration) { + setValue(ProjectGenerator.PACKAGE_NAME, codeGeneration.packageName); + setValue(ProjectGenerator.APP_CONFIG, codeGeneration.getAppConfig()); + + setValue(CreateProject.NO_CODE, !codeGeneration.includeCode); + setValue(CreateProject.NO_BUILDTOOL_WRAPPER, !codeGeneration.includeWrapper); + } + + private void setValue(String name, Object value) { + if (value != null) { + values.put(name, value); + } + } + + /** + * Create a new single-module project. + * + * @param buildTool The build tool the project should use (maven, gradle, jbang) + * @param targetVersion The target quarkus version + * @param properties Additional properties that should be used whiel creating the properties + * @return Quarkus command invocation that can be printed (dry-run) or run to create the project + * @throws RegistryResolutionException + */ + public QuarkusCommandInvocation build(BuildTool buildTool, TargetQuarkusVersionGroup targetVersion, + Map properties) + throws RegistryResolutionException { + + // TODO: Allow the Java version to be configured? infer from active Java version? + CreateProjectHelper.setJavaVersion(values, null); + CreateProjectHelper.handleSpringConfiguration(values); + output.debug("Creating an app using the following settings: %s", values); + + QuarkusProject qp = registryClient.createQuarkusProject(projectRoot(), targetVersion, buildTool, output); + + // TODO: knock on effect with properties.. here? + properties.entrySet().forEach(x -> { + if (x.getValue().length() > 0) { + System.setProperty(x.getKey(), x.getValue()); + output.info("property: %s=%s", x.getKey(), x.getValue()); + } else { + System.setProperty(x.getKey(), ""); + output.info("property: %s", x.getKey()); + } + }); + return new QuarkusCommandInvocation(qp, values); + } + + /** + * @param buildTool The build tool the project should use (maven, gradle, jbang) + * @param targetVersion The target quarkus version + * @return Resolved QuarkusProject for the given build tool and target quarkus version + * @throws RegistryResolutionException + */ + public QuarkusProject getExtensionVersions(BuildTool buildTool, TargetQuarkusVersionGroup targetVersion) + throws RegistryResolutionException { + return registryClient.createQuarkusProject(outputDirectory(), targetVersion, buildTool, output); + } + @Override public Integer call() throws Exception { spec.commandLine().usage(output.out()); return CommandLine.ExitCode.OK; } + + public String toString() { + return "BaseCreateCommand [" + + "outputPath=" + outputPath + + ", registryClient" + registryClient + + ", projectDirName=" + projectDirName + + ", projectRootPath=" + projectRootPath + + ", targetDirectory=" + targetDirectory + + ", values=" + values + "]"; + } + + public void dryRun(BuildTool buildTool, QuarkusCommandInvocation invocation, OutputOptionMixin output) { + CommandLine.Help help = spec.commandLine().getHelp(); + output.printText(new String[] { + "\nA new project would have been created in", + "\t" + projectRoot().toString(), + "\nThe project would have been created using the following settings:\n" + }); + Map dryRunOutput = new TreeMap<>(); + for (Map.Entry entry : values.entrySet()) { + dryRunOutput.put(prettyName(entry.getKey()), entry.getValue().toString()); + } + dryRunOutput.put("Quarkus Core Version", invocation.getExtensionsCatalog().getQuarkusCoreVersion()); + dryRunOutput.put("Build tool", buildTool == null ? "JBang" : buildTool.name()); + output.info(help.createTextTable(dryRunOutput).toString()); + } + + public String prettyName(String key) { + if (CreateProject.NO_BUILDTOOL_WRAPPER.equals(key)) { + return "Omit build tool wrapper"; + } + + key = key.substring(0, 1).toUpperCase() + key.substring(1); + StringBuilder builder = new StringBuilder(key); + for (int i = 0; i < builder.length(); i++) { + // Check char is underscore + if (builder.charAt(i) == '_') { + builder.replace(i, i + 1, " "); + builder.replace(i + 1, i + 2, + String.valueOf(Character.toUpperCase(builder.charAt(i + 1)))); + } + } + return builder.toString(); + } } diff --git a/devtools/cli/src/main/java/io/quarkus/cli/create/CreateProjectMixin.java b/devtools/cli/src/main/java/io/quarkus/cli/create/CreateProjectMixin.java deleted file mode 100644 index 08f8f1571dfec..0000000000000 --- a/devtools/cli/src/main/java/io/quarkus/cli/create/CreateProjectMixin.java +++ /dev/null @@ -1,195 +0,0 @@ -package io.quarkus.cli.create; - -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; - -import io.quarkus.cli.common.OutputOptionMixin; -import io.quarkus.cli.common.TargetQuarkusVersionGroup; -import io.quarkus.cli.registry.ToggleRegistryClientMixin; -import io.quarkus.devtools.commands.CreateProject; -import io.quarkus.devtools.commands.data.QuarkusCommandInvocation; -import io.quarkus.devtools.project.BuildTool; -import io.quarkus.devtools.project.QuarkusProject; -import io.quarkus.devtools.project.codegen.CreateProjectHelper; -import io.quarkus.devtools.project.codegen.ProjectGenerator; -import io.quarkus.devtools.project.codegen.SourceType; -import io.quarkus.registry.RegistryResolutionException; -import picocli.CommandLine.Help; -import picocli.CommandLine.Mixin; -import picocli.CommandLine.Model.CommandSpec; -import picocli.CommandLine.Option; -import picocli.CommandLine.Spec; - -public class CreateProjectMixin { - Map values = new HashMap<>(); - Path outputPath; - Path projectRootPath; - String projectDirName; - - @Spec(Spec.Target.MIXEE) - CommandSpec mixee; - - @Option(paramLabel = "OUTPUT-DIR", names = { "-o", - "--output-directory" }, description = "The directory to create the new project in.") - String targetDirectory; - - @Mixin - ToggleRegistryClientMixin registryClient; - - public void setTestOutputDirectory(Path testOutputDirectory) { - if (testOutputDirectory != null && targetDirectory == null) { - outputPath = testOutputDirectory; - } - } - - public Path outputDirectory() { - if (outputPath == null) { - outputPath = CreateProjectHelper.createOutputDirectory(targetDirectory); - } - return outputPath; - } - - /** - * Resolve and remember the configured project directory. - * - * @param log Output Mixin that will be used to emit error messages - * @param dryRun - * @return true IFF configured project root directory already exists - */ - public boolean checkProjectRootAlreadyExists(OutputOptionMixin log, boolean dryRun) { - if (projectRootPath == null) { - try { - projectRootPath = CreateProjectHelper.checkProjectRootPath(outputDirectory(), projectDirName, dryRun); - return false; - } catch (IllegalArgumentException iex) { - if (dryRun) { - log.warn("A directory named '" + projectDirName + "' already exists."); - projectRootPath = outputDirectory().resolve(projectDirName); - } else { - log.error(iex.getMessage()); - log.out().printf("Specify a different artifactId / directory name.%n"); - log.out().printf("See '%s --help' for more information.%n", mixee.qualifiedName()); - return true; - } - } - } - return false; - } - - public Path projectRoot() { - if (projectRootPath == null) { - projectRootPath = CreateProjectHelper.checkProjectRootPath(outputDirectory(), projectDirName, false); - } - return projectRootPath; - } - - public void setSourceTypeExtensions(Set extensions, SourceType sourceType) { - extensions = CreateProjectHelper.sanitizeExtensions(extensions); - CreateProjectHelper.addSourceTypeExtensions(extensions, sourceType); - - setValue(ProjectGenerator.SOURCE_TYPE, sourceType); - setValue(ProjectGenerator.EXTENSIONS, extensions); - } - - public void setSingleProjectGAV(TargetGAVGroup targetGav) { - projectDirName = targetGav.getArtifactId(); - - setValue(ProjectGenerator.PROJECT_GROUP_ID, targetGav.getGroupId()); - setValue(ProjectGenerator.PROJECT_ARTIFACT_ID, targetGav.getArtifactId()); - setValue(ProjectGenerator.PROJECT_VERSION, targetGav.getVersion()); - } - - public void setExtensionId(String extensionId) { - projectDirName = extensionId; - } - - public void setCodegenOptions(CodeGenerationGroup codeGeneration) { - setValue(ProjectGenerator.PACKAGE_NAME, codeGeneration.packageName); - setValue(ProjectGenerator.APP_CONFIG, codeGeneration.getAppConfig()); - - setValue(CreateProject.NO_CODE, !codeGeneration.includeCode); - setValue(CreateProject.NO_BUILDTOOL_WRAPPER, !codeGeneration.includeWrapper); - } - - public void setValue(String name, Object value) { - if (value != null) { - values.put(name, value); - } - } - - public QuarkusCommandInvocation build(BuildTool buildTool, TargetQuarkusVersionGroup targetVersion, - OutputOptionMixin log, Map properties) - throws RegistryResolutionException { - - // TODO: Allow the Java version to be configured? infer from active Java version? - CreateProjectHelper.setJavaVersion(values, null); - CreateProjectHelper.handleSpringConfiguration(values); - log.debug("Creating an app using the following settings: %s", values); - - QuarkusProject qp = registryClient.createQuarkusProject(projectRoot(), targetVersion, buildTool, log); - - properties.entrySet().forEach(x -> { - if (x.getValue().length() > 0) { - System.setProperty(x.getKey(), x.getValue()); - log.info("property: %s=%s", x.getKey(), x.getValue()); - } else { - System.setProperty(x.getKey(), ""); - log.info("property: %s", x.getKey()); - } - }); - return new QuarkusCommandInvocation(qp, values); - } - - public QuarkusProject getExtensionVersions(BuildTool buildTool, TargetQuarkusVersionGroup targetVersion, - OutputOptionMixin log) throws RegistryResolutionException { - return registryClient.createQuarkusProject(outputDirectory(), targetVersion, buildTool, log); - } - - @Override - public String toString() { - return "CreateProjectMixin [" - + "outputPath=" + outputPath - + ", registryClient" + registryClient - + ", projectDirName=" + projectDirName - + ", projectRootPath=" + projectRootPath - + ", targetDirectory=" + targetDirectory - + ", values=" + values + "]"; - } - - public void dryRun(BuildTool buildTool, QuarkusCommandInvocation invocation, OutputOptionMixin output) { - Help help = mixee.commandLine().getHelp(); - output.printText(new String[] { - "\nA new project would have been created in", - "\t" + projectRoot().toString(), - "\nThe project would have been created using the following settings:\n" - }); - Map dryRunOutput = new TreeMap<>(); - for (Map.Entry entry : values.entrySet()) { - dryRunOutput.put(prettyName(entry.getKey()), entry.getValue().toString()); - } - dryRunOutput.put("Quarkus Core Version", invocation.getExtensionsCatalog().getQuarkusCoreVersion()); - dryRunOutput.put("Build tool", buildTool == null ? "JBang" : buildTool.name()); - output.info(help.createTextTable(dryRunOutput).toString()); - } - - public String prettyName(String key) { - if (CreateProject.NO_BUILDTOOL_WRAPPER.equals(key)) { - return "Omit build tool wrapper"; - } - - key = key.substring(0, 1).toUpperCase() + key.substring(1); - StringBuilder builder = new StringBuilder(key); - for (int i = 0; i < builder.length(); i++) { - // Check char is underscore - if (builder.charAt(i) == '_') { - builder.replace(i, i + 1, " "); - builder.replace(i + 1, i + 2, - String.valueOf(Character.toUpperCase(builder.charAt(i + 1)))); - } - } - return builder.toString(); - } -} diff --git a/devtools/cli/src/main/java/io/quarkus/cli/registry/BaseRegistryCommand.java b/devtools/cli/src/main/java/io/quarkus/cli/registry/BaseRegistryCommand.java index 10d281617a4e2..7078e12881a0a 100644 --- a/devtools/cli/src/main/java/io/quarkus/cli/registry/BaseRegistryCommand.java +++ b/devtools/cli/src/main/java/io/quarkus/cli/registry/BaseRegistryCommand.java @@ -2,7 +2,6 @@ import java.util.concurrent.Callable; -import io.quarkus.cli.common.HelpOption; import io.quarkus.cli.common.OutputOptionMixin; import picocli.CommandLine; import picocli.CommandLine.Mixin; @@ -15,7 +14,7 @@ public class BaseRegistryCommand implements Callable { protected OutputOptionMixin output; @Mixin - protected HelpOption helpOption; + protected RegistryClientMixin registryClient; @Spec protected CommandSpec spec; diff --git a/devtools/cli/src/main/java/io/quarkus/cli/registry/RegistryClientMixin.java b/devtools/cli/src/main/java/io/quarkus/cli/registry/RegistryClientMixin.java index e26064f958b31..9911408fa4cca 100644 --- a/devtools/cli/src/main/java/io/quarkus/cli/registry/RegistryClientMixin.java +++ b/devtools/cli/src/main/java/io/quarkus/cli/registry/RegistryClientMixin.java @@ -24,7 +24,7 @@ public class RegistryClientMixin { /** @see io.quarkus.cli.registry.ToggleRegistryClientMixin#setRegistryClient */ public final String getRegistryClientProperty() { - return "-DquarkusRegistryClient=" + Boolean.toString(enabled()); + return "-DquarkusRegistryClient=" + enabled(); } @CommandLine.Option(names = { diff --git a/devtools/cli/src/test/java/io/quarkus/cli/CliHelpTest.java b/devtools/cli/src/test/java/io/quarkus/cli/CliHelpTest.java index 6ec6ed5cedda6..59552333a2f39 100644 --- a/devtools/cli/src/test/java/io/quarkus/cli/CliHelpTest.java +++ b/devtools/cli/src/test/java/io/quarkus/cli/CliHelpTest.java @@ -4,7 +4,6 @@ import java.nio.file.Paths; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; @@ -54,7 +53,6 @@ public void testCreateCliHelp() throws Exception { @Test @Order(23) - @Disabled public void testCreateExtensionHelp() throws Exception { CliDriver.Result result = CliDriver.execute(workspaceRoot, "create", "extension", "--help"); result.echoSystemOut(); diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/CreateProjectHelper.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/CreateProjectHelper.java index 438bd2732711e..bd06533112e30 100644 --- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/CreateProjectHelper.java +++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/codegen/CreateProjectHelper.java @@ -41,7 +41,7 @@ public static String checkPackageName(String name) { return name; } - public static Path checkProjectRootPath(Path outputPath, String name, boolean dryRun) { + public static Path checkProjectRootPath(Path outputPath, String name) { requireNonNull(name, "Must specify project name"); requireNonNull(outputPath, "Must specify output path");