Skip to content

Commit

Permalink
List extensions for a platform without a project
Browse files Browse the repository at this point in the history
Either use an explicitly defined platform/stream, or a default
platform/stream (based on CLI version) if list is invoked
outside of a project directory.
  • Loading branch information
ebullient committed Jun 16, 2021
1 parent 255ff06 commit 371df20
Show file tree
Hide file tree
Showing 9 changed files with 189 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@
import io.quarkus.cli.build.BuildSystemRunner;
import io.quarkus.cli.common.ListFormatOptions;
import io.quarkus.cli.common.RunModeOption;
import io.quarkus.cli.create.TargetQuarkusVersionGroup;
import io.quarkus.devtools.commands.ListExtensions;
import io.quarkus.devtools.commands.data.QuarkusCommandException;
import io.quarkus.devtools.commands.data.QuarkusCommandOutcome;
import io.quarkus.devtools.project.BuildTool;
import io.quarkus.devtools.project.QuarkusProject;
import io.quarkus.devtools.project.QuarkusProjectHelper;
import picocli.CommandLine;
import picocli.CommandLine.Mixin;

Expand All @@ -18,12 +24,15 @@ public class ProjectExtensionsList extends BaseBuildCommand implements Callable<
@Mixin
RunModeOption runMode;

@CommandLine.ArgGroup(order = 2, heading = "%nQuarkus version%n")
TargetQuarkusVersionGroup targetQuarkusVersion = new TargetQuarkusVersionGroup();

@CommandLine.Option(names = { "-i",
"--installable" }, defaultValue = "false", order = 2, description = "Display installable extensions.")
boolean installable = false;

@CommandLine.Option(names = { "-s",
"--search" }, defaultValue = "*", paramLabel = "PATTERN", order = 3, description = "Search filter on extension list. The format is based on Java Pattern.")
"--search" }, defaultValue = "*", paramLabel = "PATTERN", order = 3, description = "Search filter on extension list (Java Pattern syntax).")
String searchPattern;

@CommandLine.ArgGroup(heading = "%nOutput format%n")
Expand All @@ -35,33 +44,70 @@ public Integer call() {
output.debug("List extensions with initial parameters: %s", this);
output.throwIfUnmatchedArguments(spec.commandLine());

BuildSystemRunner runner = getRunner();
if (runMode.isDryRun()) {
dryRunList(spec.commandLine().getHelp(), runner.getBuildTool());
return CommandLine.ExitCode.OK;
}
// Test for an existing project
BuildTool buildTool = QuarkusProjectHelper.detectExistingBuildTool(projectRoot()); // nullable

if (buildTool == null || targetQuarkusVersion.isPlatformSpecified() || targetQuarkusVersion.isStreamSpecified()) {
// do not evaluate installables for list of arbitrary version (project-agnostic)
installable = false;
// show origins by default
format.useOriginsUnlessSpecified();

return runner.listExtensions(runMode, format, installable, searchPattern);
if (runMode.isDryRun()) {
return dryRunList(spec.commandLine().getHelp(), null);
}
return listPlatformExtensions();
} else {
BuildSystemRunner runner = getRunner();

if (runMode.isDryRun()) {
return dryRunList(spec.commandLine().getHelp(), runner.getBuildTool());
}
return runner.listExtensions(runMode, format, installable, searchPattern);
}
} catch (Exception e) {
return output.handleCommandException(e,
"Unable to list extensions: " + e.getMessage());
}
}

void dryRunList(CommandLine.Help help, BuildTool buildTool) {
output.printText(new String[] {
"\nList extensions for current project\n",
"\t" + projectRoot().toString()
});
Integer dryRunList(CommandLine.Help help, BuildTool buildTool) {
Map<String, String> dryRunOutput = new TreeMap<>();

dryRunOutput.put("Build tool", buildTool.name());
if (buildTool == null) {
output.printText(new String[] {
"\nList extensions for specified platform\n",
"\t" + targetQuarkusVersion.dryRun()
});
} else {
output.printText(new String[] {
"\nList extensions for current project\n",
"\t" + projectRoot().toString()
});
dryRunOutput.put("Build tool", buildTool.name());
}

dryRunOutput.put("Batch (non-interactive mode)", Boolean.toString(runMode.isBatchMode()));
dryRunOutput.put("List format", format.getFormatString());
dryRunOutput.put("List installable extensions", Boolean.toString(installable));
dryRunOutput.put("Search pattern", searchPattern);

output.info(help.createTextTable(dryRunOutput).toString());
return CommandLine.ExitCode.OK;
}

Integer listPlatformExtensions() throws QuarkusCommandException {
QuarkusProject qp = registryClient.createQuarkusProject(projectRoot(), targetQuarkusVersion,
BuildTool.MAVEN, output);

QuarkusCommandOutcome outcome = new ListExtensions(qp, output)
.fromCli(true)
.all(true)
.format(format.getFormatString())
.search(searchPattern)
.execute();

return outcome.isSuccess() ? CommandLine.ExitCode.OK : CommandLine.ExitCode.SOFTWARE;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ public class ListFormatOptions {
"--origins" }, order = 7, description = "Display extensions including their platform origins.")
boolean origins = false;

/**
* If a value was not specified via options (all false),
* make origins true. Used with specific platform list.
*/
public void useOriginsUnlessSpecified() {
if (name || concise || full || origins) {
return;
}
origins = true;
}

public String getFormatString() {
String formatString = "name";
if (concise)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package io.quarkus.cli.common;

import java.nio.file.Path;

import io.quarkus.cli.Version;
import io.quarkus.cli.create.TargetQuarkusVersionGroup;
import io.quarkus.devtools.project.BuildTool;
import io.quarkus.devtools.project.QuarkusProject;
import io.quarkus.devtools.project.QuarkusProjectHelper;
import io.quarkus.maven.ArtifactCoords;
import io.quarkus.maven.StreamCoords;
import io.quarkus.platform.tools.ToolsUtils;
import io.quarkus.registry.ExtensionCatalogResolver;
import io.quarkus.registry.catalog.ExtensionCatalog;
Expand All @@ -18,7 +23,13 @@ public boolean enabled() {
return enableRegistryClient;
}

public ExtensionCatalog getExtensionCatalog(TargetQuarkusVersionGroup targetVersion, OutputOptionMixin log) {
public QuarkusProject createQuarkusProject(Path projectRoot, TargetQuarkusVersionGroup targetVersion, BuildTool buildTool,
OutputOptionMixin log) {
ExtensionCatalog catalog = getExtensionCatalog(targetVersion, log);
return QuarkusProjectHelper.getProject(projectRoot, catalog, buildTool, log);
}

ExtensionCatalog getExtensionCatalog(TargetQuarkusVersionGroup targetVersion, OutputOptionMixin log) {
log.debug("Resolving Quarkus extension catalog for " + targetVersion);
QuarkusProjectHelper.setMessageWriter(log);

Expand All @@ -38,12 +49,9 @@ public ExtensionCatalog getExtensionCatalog(TargetQuarkusVersionGroup targetVers
QuarkusProjectHelper.artifactResolver(), log);
}

if (targetVersion.isStream()) {
final String stream = targetVersion.getStream();
final int colon = stream.indexOf(':');
final String platformKey = colon <= 0 ? null : stream.substring(0, colon);
final String streamId = colon < 0 ? stream : stream.substring(colon + 1);
return catalogResolver.resolveExtensionCatalog(platformKey, streamId);
if (targetVersion.isStreamSpecified()) {
final StreamCoords stream = targetVersion.getStream();
return catalogResolver.resolveExtensionCatalog(stream.getPlatformKey());
}

return catalogResolver.resolveExtensionCatalog();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,24 @@ public class RunModeOption {
"--batch-mode" }, description = "Run in non-interactive (batch) mode.")
boolean batchMode;

@CommandLine.Option(names = { "--dryrun" }, description = "Show actions that would be taken.")
// Allow the option variant, but don't crowd help
@CommandLine.Option(names = { "--dryrun" }, hidden = true)
boolean dryRun2 = false;

@CommandLine.Option(names = { "--dry-run" }, description = "Show actions that would be taken.")
boolean dryRun = false;

public boolean isBatchMode() {
return batchMode;
}

public boolean isDryRun() {
return dryRun;
return dryRun || dryRun2;
}

@Override
public String toString() {
return "RunModeOption [batchMode=" + batchMode + ", dryRun=" + dryRun + "]";
return "RunModeOption [batchMode=" + batchMode + ", dryRun=" + isDryRun() + "]";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@
import io.quarkus.devtools.commands.data.QuarkusCommandInvocation;
import io.quarkus.devtools.project.BuildTool;
import io.quarkus.devtools.project.QuarkusProject;
import io.quarkus.devtools.project.QuarkusProjectHelper;
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 io.quarkus.registry.catalog.ExtensionCatalog;
import picocli.CommandLine.Help;
import picocli.CommandLine.Mixin;
import picocli.CommandLine.Model.CommandSpec;
Expand Down Expand Up @@ -105,8 +103,7 @@ public QuarkusCommandInvocation build(BuildTool buildTool, TargetQuarkusVersionG
buildTool = BuildTool.MAVEN;
}

ExtensionCatalog catalog = registryClient.getExtensionCatalog(targetVersion, log);
QuarkusProject qp = QuarkusProjectHelper.getProject(projectRoot(), catalog, buildTool, log);
QuarkusProject qp = registryClient.createQuarkusProject(projectRoot(), targetVersion, buildTool, log);
return new QuarkusCommandInvocation(qp, values);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,44 @@
package io.quarkus.cli.create;

import io.quarkus.maven.ArtifactCoords;
import io.quarkus.maven.StreamCoords;
import picocli.CommandLine;
import picocli.CommandLine.Model.CommandSpec;

public class TargetQuarkusVersionGroup {
StreamCoords streamCoords = null;
String validStream = null;

ArtifactCoords platformBom = null;
String validPlatformBom = null;

@CommandLine.Spec
CommandSpec spec;

@CommandLine.Option(paramLabel = "STREAM", names = { "-S",
"--stream" }, description = "A target stream, e.g. default, snapshot", hidden = true)
String stream;
@CommandLine.Option(paramLabel = "platformKey:streamId", names = { "-S",
"--stream" }, description = "A target stream, for example:%n io.quarkus.platform:999-SNAPSHOT%n io.quarkus:1.13")
void setStream(String stream) {
stream = stream.trim();
if (!stream.isEmpty()) {
try {
streamCoords = StreamCoords.fromString(stream);
validStream = stream;
} catch (IllegalArgumentException iex) {
throw new CommandLine.ParameterException(spec.commandLine(),
String.format("Invalid value '%s' for option '--stream'. " +
"Value should be specified as 'platformKey:streamId'. %s", iex.getMessage()));
}
}
}

@CommandLine.Option(paramLabel = "groupId:artifactId:version", names = { "-p",
"--platform-bom" }, description = "A specific Quarkus platform BOM,%ne.g. io.quarkus:quarkus-bom:1.13.4.Final")
"--platform-bom" }, description = "A specific Quarkus platform BOM, for example:%n io.quarkus:quarkus-bom:1.13.4.Final")
void setPlatformBom(String bom) {
bom = bom.trim();
if (!bom.isEmpty()) {
try {
platformBom = ArtifactCoords.fromString(bom);
validPlatformBom = bom; // keep original (valid) string (dryrun)
} catch (IllegalArgumentException iex) {
throw new CommandLine.ParameterException(spec.commandLine(),
String.format("Invalid value '%s' for option '--platform-bom'. " +
Expand All @@ -37,18 +55,28 @@ public ArtifactCoords getPlatformBom() {
return platformBom;
}

public boolean isStream() {
return stream != null;
public boolean isStreamSpecified() {
return streamCoords != null;
}

public String getStream() {
return stream;
public StreamCoords getStream() {
return streamCoords;
}

public String dryRun() {
if (streamCoords != null) {
return "stream " + validStream;
} else if (platformBom != null) {
return "platform " + validPlatformBom;
} else {
return "same as project";
}
}

@Override
public String toString() {
return "TargetQuarkusVersionGroup{"
+ "stream=" + stream
+ "stream=" + streamCoords
+ ", platformBom=" + platformBom
+ '}';
}
Expand Down
41 changes: 20 additions & 21 deletions devtools/cli/src/test/java/io/quarkus/cli/CliNonProjectTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,22 @@ public static void allDone() {
@Test
public void testListOutsideOfProject() throws Exception {
CliDriver.Result result = CliDriver.execute("ext", "-e");
Assertions.assertEquals(CommandLine.ExitCode.USAGE, result.exitCode,
"'quarkus ext list' should fail outside of a quarkus project directory:\n" + result);
System.out.println(result);
Assertions.assertEquals(CommandLine.ExitCode.OK, result.exitCode,
"Expected OK return code." + result);
Assertions.assertTrue(result.stdout.contains("Jackson"),
"Should contain 'Jackson' in the list of extensions, found: " + result.stdout);
}

@Test
public void testListPlatformExtensions() throws Exception {
// List extensions of a specified platform version
CliDriver.Result result = CliDriver.execute("ext", "list", "-p=io.quarkus:quarkus-bom:2.0.0.CR3", "-e");
Assertions.assertEquals(CommandLine.ExitCode.OK, result.exitCode,
"Expected OK return code." + result);
Assertions.assertTrue(result.stdout.contains("Jackson"),
"Should contain 'Jackson' in the list of extensions, found: " + result.stdout);
Assertions.assertTrue(result.stdout.contains("2.0.0.CR3"),
"Should contain '2.0.0.CR3' in the list of extensions (origin), found: " + result.stdout);
}

@Test
Expand All @@ -68,28 +81,14 @@ public void testDevOutsideOfProject() throws Exception {
@Test
public void testCreateAppDryRun() throws Exception {
// A dry run of create should not create any files or directories
CliDriver.Result result = CliDriver.execute("create", "--dryrun", "-e");
CliDriver.Result result = CliDriver.execute("create", "--dry-run", "-e");
Assertions.assertEquals(CommandLine.ExitCode.OK, result.exitCode,
"Expected OK return code." + result);
Assertions.assertTrue(result.stdout.contains("project would have been created"),
"Should contain 'project would have been created', found: " + result.stdout);
}

@Test
public void testCreateAppDryRunMistype() throws Exception {
// A dry run of create should not create any files or directories
CliDriver.Result result = CliDriver.execute("create", "--dry-run", "-e", "--verbose");
Assertions.assertEquals(CommandLine.ExitCode.USAGE, result.exitCode,
"Expected OK return code." + result);
}

@Test
public void testCreateCliDryRun() throws Exception {
// A dry run of create should not create any files or directories
CliDriver.Result result = CliDriver.execute("create", "cli", "--dryrun", "-e");
Assertions.assertEquals(CommandLine.ExitCode.OK, result.exitCode,
"Expected OK return code." + result);
Assertions.assertTrue(result.stdout.contains("project would have been created"),
"Should contain 'project would have been created', found: " + result.stdout);
CliDriver.Result result2 = CliDriver.execute("create", "--dryrun", "-e");
Assertions.assertEquals(result.stdout, result2.stdout,
"Invoking the command with --dryrun should produce the same result");
}
}
Loading

0 comments on commit 371df20

Please sign in to comment.