Skip to content

Commit

Permalink
Merge pull request #32410 from iocanel/even-more-cli-fixes
Browse files Browse the repository at this point in the history
Dev tools fixes and improvements
  • Loading branch information
gsmet authored Apr 12, 2023
2 parents fecea42 + 568ee7c commit 68e6c86
Show file tree
Hide file tree
Showing 25 changed files with 525 additions and 289 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ public void prepare(BuildToolContext context) {

public void prepareMaven(BuildToolContext context) {
BuildSystemRunner runner = getRunner(context);
BuildSystemRunner.BuildCommandArgs compileArgs = runner.prepareAction("compiler:compile", context.getBuildOptions(),
BuildSystemRunner.BuildCommandArgs compileArgs = runner.prepareAction("resources:resources",
context.getBuildOptions(),
context.getRunModeOption(),
context.getParams());

Expand Down
59 changes: 33 additions & 26 deletions devtools/cli/src/main/java/io/quarkus/cli/QuarkusCli.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.function.Supplier;

import jakarta.inject.Inject;

Expand All @@ -25,7 +27,6 @@
import io.quarkus.cli.plugin.PluginManager;
import io.quarkus.cli.plugin.PluginManagerSettings;
import io.quarkus.cli.registry.RegistryClientMixin;
import io.quarkus.cli.utils.Registries;
import io.quarkus.devtools.project.BuildTool;
import io.quarkus.devtools.project.QuarkusProject;
import io.quarkus.devtools.project.QuarkusProjectHelper;
Expand Down Expand Up @@ -95,18 +96,23 @@ public int run(String... args) throws Exception {
try {
Optional<String> missing = checkMissingCommand(cmd, args);
missing.ifPresent(m -> {
Map<String, Plugin> installable = pluginManager.getInstallablePlugins();
if (installable.containsKey(m)) {
Plugin candidate = installable.get(m);
PluginListItem item = new PluginListItem(false, candidate);
PluginListTable table = new PluginListTable(List.of(item));
output.info("Command %s not installed but the following plugin is available:\n%s", m, table.getContent());
if (interactiveMode && Prompt.yesOrNo(true,
"Would you like to install it now ?",
args)) {
pluginManager.addPlugin(m).ifPresent(added -> plugins.put(added.getName(), added));
pluginCommandFactory.populateCommands(cmd, plugins);
try {
Map<String, Plugin> installable = pluginManager.getInstallablePlugins();
if (installable.containsKey(m)) {
Plugin candidate = installable.get(m);
PluginListItem item = new PluginListItem(false, candidate);
PluginListTable table = new PluginListTable(List.of(item));
output.info("Command %s not installed but the following plugin is available:\n%s", m,
table.getContent());
if (interactiveMode && Prompt.yesOrNo(true,
"Would you like to install it now ?",
args)) {
pluginManager.addPlugin(m).ifPresent(added -> plugins.put(added.getName(), added));
pluginCommandFactory.populateCommands(cmd, plugins);
}
}
} catch (Exception e) {
output.error("Command %s is missing and can't be installed.", m);
}
});
} catch (MutuallyExclusiveArgsException e) {
Expand Down Expand Up @@ -241,25 +247,26 @@ private Optional<Path> getProjectRoot(Optional<String> testDir) {
return Optional.ofNullable(projectRoot);
}

private Optional<QuarkusProject> quarkusProject(Optional<String> testDir) {
try {
Path root = getProjectRoot(testDir).orElseThrow();
BuildTool buildTool = QuarkusProjectHelper.detectExistingBuildTool(root);
if (buildTool == null) {
return Optional.empty();
}
return Optional
.ofNullable(registryClient.createQuarkusProject(root, new TargetQuarkusPlatformGroup(), buildTool, output));
} catch (Exception e) {
return Optional.empty();
private Supplier<QuarkusProject> quarkusProject(Optional<String> testDir) {
Path root = getProjectRoot(testDir).orElseThrow();
BuildTool buildTool = QuarkusProjectHelper.detectExistingBuildTool(root);
if (buildTool == null) {
return () -> null;
}
return () -> {
try {
return registryClient.createQuarkusProject(root, new TargetQuarkusPlatformGroup(), buildTool, output);
} catch (Exception e) {
return null;
}
};
}

private PluginManager pluginManager(OutputOptionMixin output, Optional<String> testDir, boolean interactiveMode) {
PluginManagerSettings settings = PluginManagerSettings.defaultSettings()
.withCatalogs(Registries.getRegistries(registryClient, "quarkusio"))
.withCatalogs(Set.<String> of("quarkusio"))
.withInteractivetMode(interactiveMode); // Why not just getting it from output.isClieTest ? Cause args have not been parsed yet.
return new PluginManager(settings, output, Optional.ofNullable(Paths.get(System.getProperty("user.home"))),
getProjectRoot(testDir), quarkusProject(testDir), p -> true);
return PluginManager.create(settings, output, Optional.ofNullable(Paths.get(System.getProperty("user.home"))),
getProjectRoot(testDir), quarkusProject(testDir));
}
}
2 changes: 1 addition & 1 deletion devtools/cli/src/main/java/io/quarkus/cli/deploy/Kind.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import io.quarkus.cli.BuildToolContext;
import picocli.CommandLine;

@CommandLine.Command(name = "kind", sortOptions = false, showDefaultValues = true, mixinStandardHelpOptions = false, header = "Perform the deploy action on minikube.", description = "%n"
@CommandLine.Command(name = "kind", sortOptions = false, showDefaultValues = true, mixinStandardHelpOptions = false, header = "Perform the deploy action on kind.", description = "%n"
+ "The command will deploy the application on kind.", footer = "%n"
+ "For example (using default values), it will create a Deployment named '<project.artifactId>' using the image with REPOSITORY='${user.name}/<project.artifactId>' and TAG='<project.version>' and will deploy it to the target cluster.", headerHeading = "%n", commandListHeading = "%nCommands:%n", synopsisHeading = "%nUsage: ", parameterListHeading = "%n", optionListHeading = "Options:%n")
public class Kind extends BaseKubernetesDeployCommand {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,24 @@ public Integer call() {

Integer addPlugin() throws IOException {
PluginManager pluginManager = pluginManager();
Optional<Plugin> addedPlugin = pluginManager.addPlugin(nameOrLocation, description);
String name = pluginManager.getUtil().getName(nameOrLocation);
Optional<Plugin> existingPlugin = Optional.ofNullable(pluginManager.getInstalledPlugins().get(name));
Optional<Plugin> addedPlugin = pluginManager.addPlugin(nameOrLocation, catalogOptions.user, description);

return addedPlugin.map(plugin -> {
PluginListTable table = new PluginListTable(List.of(new PluginListItem(true, plugin)), false);
output.info("Added plugin:");
output.info(table.getContent());
if (!plugin.isInUserCatalog() && userPluginManager().getInstalledPlugins().containsKey(plugin.getName())) {
if (plugin.isInProjectCatalog() && existingPlugin.filter(p -> p.isInUserCatalog()).isPresent()) {
output.warn(
"Plugin was added in the project scope, but another with the same name exists in the user scope!\nThe project scoped one will take precedence when invoked from within the project!");
}

if (plugin.isInUserCatalog() && existingPlugin.filter(p -> p.isInProjectCatalog()).isPresent()) {
output.warn(
"Plugin was added in the user scope, but another with the same name exists in the project scope!\nThe project scoped one will take precedence when invoked from within the project!");
}

return CommandLine.ExitCode.OK;
}).orElseGet(() -> {
output.error("No plugin available at: " + this.nameOrLocation);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package io.quarkus.cli.plugin;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;

import io.quarkus.cli.build.BaseBuildCommand;
import io.quarkus.cli.common.TargetQuarkusPlatformGroup;
import io.quarkus.cli.utils.Registries;
import io.quarkus.devtools.project.QuarkusProject;
import picocli.CommandLine;

Expand Down Expand Up @@ -37,29 +35,11 @@ public Optional<QuarkusProject> quarkusProject() {
}

public PluginManager pluginManager() {
Set<String> registries = Registries.getRegistries(registryClient, "quarkusio");
PluginManagerSettings settings = PluginManagerSettings.defaultSettings()
.withCatalogs(registries)
.withInteractivetMode(!output.isCliTest());

return new PluginManager(settings, output,
catalogOptions.userDirectory.or(() -> Optional.ofNullable(Paths.get(System.getProperty("user.home")))),
catalogOptions.user ? Optional.empty() : Optional.ofNullable(projectRoot()),
catalogOptions.user ? Optional.empty() : quarkusProject(),
p -> type.map(t -> t == p.getType()).orElse(true));
return PluginManager.get();
}

public PluginManager userPluginManager() {
Set<String> registries = Registries.getRegistries(registryClient, "quarkusio");
PluginManagerSettings settings = PluginManagerSettings.defaultSettings()
.withCatalogs(registries)
.withInteractivetMode(!output.isCliTest());

return new PluginManager(settings, output,
catalogOptions.userDirectory.or(() -> Optional.ofNullable(Paths.get(System.getProperty("user.home")))),
Optional.empty(),
Optional.empty(),
p -> type.map(t -> t == p.getType()).orElse(true));
public Predicate<Plugin> pluginFilter() {
return p -> type.map(t -> t == p.getType()).orElse(true) &&
!(catalogOptions.user && p.isInProjectCatalog());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.Callable;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -67,20 +68,23 @@ Integer dryRunList(CommandLine.Help help, BuildTool buildTool) {

Integer listPluigns() {
PluginManager pluginManager = pluginManager();
Predicate<Plugin> pluginFilter = pluginFilter();
pluginManager.reconcile();
installedPlugins.putAll(pluginManager.getInstalledPlugins());
installedPlugins.putAll(pluginManager.getInstalledPlugins(catalogOptions.user));

Map<String, PluginListItem> items = new HashMap<>();
if (installable) {
Map<String, Plugin> availablePlugins = pluginManager.getInstallablePlugins();
items.putAll(availablePlugins
.entrySet().stream()
.filter(e -> !installedPlugins.containsKey(e.getKey()))
.map(e -> new PluginListItem(installedPlugins.containsKey(e.getKey()), e.getValue()))
.values().stream()
.filter(p -> !installedPlugins.containsKey(p.getName()))
.filter(pluginFilter)
.map(p -> new PluginListItem(installedPlugins.containsKey(p.getName()), p))
.collect(Collectors.toMap(p -> p.getName(), p -> p)));
}

items.putAll(installedPlugins.entrySet().stream()
.filter(e -> pluginFilter.test(e.getValue()))
.map(e -> new PluginListItem(true, e.getValue()))
.collect(Collectors.toMap(p -> p.getName(), p -> p)));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class CliPluginsRemove extends CliPluginsBase implements Callable<Integer
@CommandLine.Mixin
RunModeOption runMode;

@CommandLine.Parameters(arity = "1", paramLabel = "PLUGIN_NAME", description = "Plugin name to add to the CLI")
@CommandLine.Parameters(arity = "1", paramLabel = "PLUGIN_NAME", description = "Plugin name to remove from the CLI")
String name;

@Override
Expand All @@ -39,17 +39,20 @@ public Integer call() {

Integer removePlugin() throws IOException {
PluginManager pluginManager = pluginManager();
Plugin toRemove = pluginManager.getInstalledPlugins().get(name);
Optional<Plugin> removedPlugin = pluginManager.removePlugin(name);
Optional<Plugin> removedPlugin = pluginManager.removePlugin(name, catalogOptions.user);

return removedPlugin.map(plugin -> {
PluginListTable table = new PluginListTable(List.of(new PluginListItem(false, plugin)), false);
output.info("Removed plugin:");
output.info(table.getContent());
if (!plugin.isInUserCatalog()) {
if (userPluginManager().getInstalledPlugins().containsKey(plugin.getName())) {
// Check if plugin still exists
if (pluginManager.getInstalledPlugins().containsKey(plugin.getName())) {
if (plugin.isInProjectCatalog()) {
output.warn(
"The removed plugin was available both in user and project scopes. It was removed from the project but will remain available in the user scope!");
} else {
output.warn(
"The removed plugin was available both in user and project scopes. It was removed from the user but will remain available in the project scope!");
}
}
return CommandLine.ExitCode.OK;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,11 @@ public List<String> getArguments() {
public OutputOptionMixin getOutput() {
return output;
}

@Override
public void useArguments(List<String> arguments) {
this.arguments.clear();
this.arguments.add(location);
this.arguments.addAll(arguments);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public interface PluginCommand extends Callable<Integer> {

OutputOptionMixin getOutput();

void useArguments(List<String> arguments);

default Path getWorkingDirectory() {
return Paths.get(System.getProperty("user.dir"));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ public PluginCommandFactory(OutputOptionMixin output) {

private Optional<PluginCommand> createPluginCommand(Plugin plugin) {
switch (plugin.getType()) {
case jar:
case maven:
return plugin.getLocation().flatMap(PluginUtil::checkGACTV).map(g -> new JBangCommand(toGAVC(g), output));
case java:
case jar:
case jbang:
return plugin.getLocation().map(l -> new JBangCommand(l, output));
case executable:
Expand Down Expand Up @@ -60,7 +61,7 @@ public <T> T set(T value) throws Exception {
}
if (value instanceof String[]) {
String[] array = (String[]) value;
command.getArguments().addAll(Arrays.asList(array));
command.useArguments(Arrays.asList(array));
}
return value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ public List<String> getArguments() {
return arguments;
}

@Override
public void useArguments(List<String> arguments) {
this.arguments.clear();
this.arguments.addAll(arguments);
}

public OutputOptionMixin getOutput() {
return output;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import javax.inject.Inject;

import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.StopExecutionException;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.options.Option;

Expand Down Expand Up @@ -47,11 +47,6 @@ public String[] getRequiresOneOf() {
}
}

@Inject
public Deploy() {
super("Deploy");
}

@Input
Optional<String> deployer = Optional.empty();
boolean imageBuild = false;
Expand All @@ -73,8 +68,9 @@ public void setImageBuilder(String imageBuilder) {
this.imageBuild = true;
}

public Deploy(String description) {
super(description);
@Inject
public Deploy() {
super("Deploy");
extension().forcedPropertiesProperty().convention(
getProject().provider(() -> {
Map<String, String> props = new HashMap<>();
Expand All @@ -96,6 +92,7 @@ public void checkRequiredExtensions() {
List<String> projectDependencies = getProject().getConfigurations().stream().flatMap(c -> c.getDependencies().stream())
.map(d -> d.getName())
.collect(Collectors.toList());

if (!projectDependencies.contains(requiredDeployerExtension)) {
abort("Task: {} requires extensions: {}\n" +
"To add the extensions to the project you can run the following command:\n" +
Expand All @@ -118,19 +115,24 @@ public void checkRequiredExtensions() {
}

public Deployer getDeployer() {
return deployer.or(() -> DeploymentUtil.getEnabledDeployer()).map(d -> Deployer.valueOf(d)).orElse(Deployer.kubernetes);
return deployer
.or(() -> DeploymentUtil.getEnabledDeployer())
.or(() -> getProjectDeployers().stream().findFirst())
.map(Deployer::valueOf)
.orElse(Deployer.kubernetes);
}

public Optional<String> requiredContainerImageExtension() {
return imageBuilder.map(b -> "quarkus-container-image-" + b)
.or(() -> imageBuild ? Arrays.stream(getDeployer().requiresOneOf).findFirst() : Optional.empty());
}

private void abort(String message, Object... args) {
getProject().getLogger().warn(message, args);
getProject().getTasks().stream().filter(t -> t != this).forEach(t -> {
t.setEnabled(false);
});
throw new StopExecutionException();
private Set<String> getProjectDeployers() {
return getProject().getConfigurations().stream().flatMap(c -> c.getDependencies().stream())
.map(d -> d.getName())
.filter(d -> Arrays.stream(Deployer.values()).map(Deployer::getExtension).anyMatch(e -> d.equals(e)))
.map(d -> d.replaceAll("^quarkus\\-", ""))
.collect(Collectors.toSet());
}

}
Loading

0 comments on commit 68e6c86

Please sign in to comment.