Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

List extensions from arbitrary platform #17966

Merged
merged 1 commit into from
Jun 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,7 +1,11 @@
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.platform.tools.ToolsUtils;
Expand All @@ -18,7 +22,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 +48,8 @@ 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()) {
return catalogResolver.resolveExtensionCatalog(targetVersion.getStream());
}

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