Skip to content

Commit 68e6c86

Browse files
authored
Merge pull request #32410 from iocanel/even-more-cli-fixes
Dev tools fixes and improvements
2 parents fecea42 + 568ee7c commit 68e6c86

25 files changed

+525
-289
lines changed

devtools/cli/src/main/java/io/quarkus/cli/BuildToolDelegatingCommand.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ public void prepare(BuildToolContext context) {
123123

124124
public void prepareMaven(BuildToolContext context) {
125125
BuildSystemRunner runner = getRunner(context);
126-
BuildSystemRunner.BuildCommandArgs compileArgs = runner.prepareAction("compiler:compile", context.getBuildOptions(),
126+
BuildSystemRunner.BuildCommandArgs compileArgs = runner.prepareAction("resources:resources",
127+
context.getBuildOptions(),
127128
context.getRunModeOption(),
128129
context.getParams());
129130

devtools/cli/src/main/java/io/quarkus/cli/QuarkusCli.java

+33-26
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
import java.util.List;
1111
import java.util.Map;
1212
import java.util.Optional;
13+
import java.util.Set;
1314
import java.util.concurrent.Callable;
15+
import java.util.function.Supplier;
1416

1517
import jakarta.inject.Inject;
1618

@@ -25,7 +27,6 @@
2527
import io.quarkus.cli.plugin.PluginManager;
2628
import io.quarkus.cli.plugin.PluginManagerSettings;
2729
import io.quarkus.cli.registry.RegistryClientMixin;
28-
import io.quarkus.cli.utils.Registries;
2930
import io.quarkus.devtools.project.BuildTool;
3031
import io.quarkus.devtools.project.QuarkusProject;
3132
import io.quarkus.devtools.project.QuarkusProjectHelper;
@@ -95,18 +96,23 @@ public int run(String... args) throws Exception {
9596
try {
9697
Optional<String> missing = checkMissingCommand(cmd, args);
9798
missing.ifPresent(m -> {
98-
Map<String, Plugin> installable = pluginManager.getInstallablePlugins();
99-
if (installable.containsKey(m)) {
100-
Plugin candidate = installable.get(m);
101-
PluginListItem item = new PluginListItem(false, candidate);
102-
PluginListTable table = new PluginListTable(List.of(item));
103-
output.info("Command %s not installed but the following plugin is available:\n%s", m, table.getContent());
104-
if (interactiveMode && Prompt.yesOrNo(true,
105-
"Would you like to install it now ?",
106-
args)) {
107-
pluginManager.addPlugin(m).ifPresent(added -> plugins.put(added.getName(), added));
108-
pluginCommandFactory.populateCommands(cmd, plugins);
99+
try {
100+
Map<String, Plugin> installable = pluginManager.getInstallablePlugins();
101+
if (installable.containsKey(m)) {
102+
Plugin candidate = installable.get(m);
103+
PluginListItem item = new PluginListItem(false, candidate);
104+
PluginListTable table = new PluginListTable(List.of(item));
105+
output.info("Command %s not installed but the following plugin is available:\n%s", m,
106+
table.getContent());
107+
if (interactiveMode && Prompt.yesOrNo(true,
108+
"Would you like to install it now ?",
109+
args)) {
110+
pluginManager.addPlugin(m).ifPresent(added -> plugins.put(added.getName(), added));
111+
pluginCommandFactory.populateCommands(cmd, plugins);
112+
}
109113
}
114+
} catch (Exception e) {
115+
output.error("Command %s is missing and can't be installed.", m);
110116
}
111117
});
112118
} catch (MutuallyExclusiveArgsException e) {
@@ -241,25 +247,26 @@ private Optional<Path> getProjectRoot(Optional<String> testDir) {
241247
return Optional.ofNullable(projectRoot);
242248
}
243249

244-
private Optional<QuarkusProject> quarkusProject(Optional<String> testDir) {
245-
try {
246-
Path root = getProjectRoot(testDir).orElseThrow();
247-
BuildTool buildTool = QuarkusProjectHelper.detectExistingBuildTool(root);
248-
if (buildTool == null) {
249-
return Optional.empty();
250-
}
251-
return Optional
252-
.ofNullable(registryClient.createQuarkusProject(root, new TargetQuarkusPlatformGroup(), buildTool, output));
253-
} catch (Exception e) {
254-
return Optional.empty();
250+
private Supplier<QuarkusProject> quarkusProject(Optional<String> testDir) {
251+
Path root = getProjectRoot(testDir).orElseThrow();
252+
BuildTool buildTool = QuarkusProjectHelper.detectExistingBuildTool(root);
253+
if (buildTool == null) {
254+
return () -> null;
255255
}
256+
return () -> {
257+
try {
258+
return registryClient.createQuarkusProject(root, new TargetQuarkusPlatformGroup(), buildTool, output);
259+
} catch (Exception e) {
260+
return null;
261+
}
262+
};
256263
}
257264

258265
private PluginManager pluginManager(OutputOptionMixin output, Optional<String> testDir, boolean interactiveMode) {
259266
PluginManagerSettings settings = PluginManagerSettings.defaultSettings()
260-
.withCatalogs(Registries.getRegistries(registryClient, "quarkusio"))
267+
.withCatalogs(Set.<String> of("quarkusio"))
261268
.withInteractivetMode(interactiveMode); // Why not just getting it from output.isClieTest ? Cause args have not been parsed yet.
262-
return new PluginManager(settings, output, Optional.ofNullable(Paths.get(System.getProperty("user.home"))),
263-
getProjectRoot(testDir), quarkusProject(testDir), p -> true);
269+
return PluginManager.create(settings, output, Optional.ofNullable(Paths.get(System.getProperty("user.home"))),
270+
getProjectRoot(testDir), quarkusProject(testDir));
264271
}
265272
}

devtools/cli/src/main/java/io/quarkus/cli/deploy/Kind.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import io.quarkus.cli.BuildToolContext;
44
import picocli.CommandLine;
55

6-
@CommandLine.Command(name = "kind", sortOptions = false, showDefaultValues = true, mixinStandardHelpOptions = false, header = "Perform the deploy action on minikube.", description = "%n"
6+
@CommandLine.Command(name = "kind", sortOptions = false, showDefaultValues = true, mixinStandardHelpOptions = false, header = "Perform the deploy action on kind.", description = "%n"
77
+ "The command will deploy the application on kind.", footer = "%n"
88
+ "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")
99
public class Kind extends BaseKubernetesDeployCommand {

devtools/cli/src/main/java/io/quarkus/cli/plugin/CliPluginsAdd.java

+10-2
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,24 @@ public Integer call() {
4545

4646
Integer addPlugin() throws IOException {
4747
PluginManager pluginManager = pluginManager();
48-
Optional<Plugin> addedPlugin = pluginManager.addPlugin(nameOrLocation, description);
48+
String name = pluginManager.getUtil().getName(nameOrLocation);
49+
Optional<Plugin> existingPlugin = Optional.ofNullable(pluginManager.getInstalledPlugins().get(name));
50+
Optional<Plugin> addedPlugin = pluginManager.addPlugin(nameOrLocation, catalogOptions.user, description);
4951

5052
return addedPlugin.map(plugin -> {
5153
PluginListTable table = new PluginListTable(List.of(new PluginListItem(true, plugin)), false);
5254
output.info("Added plugin:");
5355
output.info(table.getContent());
54-
if (!plugin.isInUserCatalog() && userPluginManager().getInstalledPlugins().containsKey(plugin.getName())) {
56+
if (plugin.isInProjectCatalog() && existingPlugin.filter(p -> p.isInUserCatalog()).isPresent()) {
5557
output.warn(
5658
"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!");
5759
}
60+
61+
if (plugin.isInUserCatalog() && existingPlugin.filter(p -> p.isInProjectCatalog()).isPresent()) {
62+
output.warn(
63+
"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!");
64+
}
65+
5866
return CommandLine.ExitCode.OK;
5967
}).orElseGet(() -> {
6068
output.error("No plugin available at: " + this.nameOrLocation);
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
package io.quarkus.cli.plugin;
22

33
import java.nio.file.Path;
4-
import java.nio.file.Paths;
54
import java.util.Optional;
6-
import java.util.Set;
5+
import java.util.function.Predicate;
76

87
import io.quarkus.cli.build.BaseBuildCommand;
98
import io.quarkus.cli.common.TargetQuarkusPlatformGroup;
10-
import io.quarkus.cli.utils.Registries;
119
import io.quarkus.devtools.project.QuarkusProject;
1210
import picocli.CommandLine;
1311

@@ -37,29 +35,11 @@ public Optional<QuarkusProject> quarkusProject() {
3735
}
3836

3937
public PluginManager pluginManager() {
40-
Set<String> registries = Registries.getRegistries(registryClient, "quarkusio");
41-
PluginManagerSettings settings = PluginManagerSettings.defaultSettings()
42-
.withCatalogs(registries)
43-
.withInteractivetMode(!output.isCliTest());
44-
45-
return new PluginManager(settings, output,
46-
catalogOptions.userDirectory.or(() -> Optional.ofNullable(Paths.get(System.getProperty("user.home")))),
47-
catalogOptions.user ? Optional.empty() : Optional.ofNullable(projectRoot()),
48-
catalogOptions.user ? Optional.empty() : quarkusProject(),
49-
p -> type.map(t -> t == p.getType()).orElse(true));
38+
return PluginManager.get();
5039
}
5140

52-
public PluginManager userPluginManager() {
53-
Set<String> registries = Registries.getRegistries(registryClient, "quarkusio");
54-
PluginManagerSettings settings = PluginManagerSettings.defaultSettings()
55-
.withCatalogs(registries)
56-
.withInteractivetMode(!output.isCliTest());
57-
58-
return new PluginManager(settings, output,
59-
catalogOptions.userDirectory.or(() -> Optional.ofNullable(Paths.get(System.getProperty("user.home")))),
60-
Optional.empty(),
61-
Optional.empty(),
62-
p -> type.map(t -> t == p.getType()).orElse(true));
41+
public Predicate<Plugin> pluginFilter() {
42+
return p -> type.map(t -> t == p.getType()).orElse(true) &&
43+
!(catalogOptions.user && p.isInProjectCatalog());
6344
}
64-
6545
}

devtools/cli/src/main/java/io/quarkus/cli/plugin/CliPluginsList.java

+8-4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.util.Map;
88
import java.util.TreeMap;
99
import java.util.concurrent.Callable;
10+
import java.util.function.Predicate;
1011
import java.util.regex.Pattern;
1112
import java.util.stream.Collectors;
1213

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

6869
Integer listPluigns() {
6970
PluginManager pluginManager = pluginManager();
71+
Predicate<Plugin> pluginFilter = pluginFilter();
7072
pluginManager.reconcile();
71-
installedPlugins.putAll(pluginManager.getInstalledPlugins());
73+
installedPlugins.putAll(pluginManager.getInstalledPlugins(catalogOptions.user));
7274

7375
Map<String, PluginListItem> items = new HashMap<>();
7476
if (installable) {
7577
Map<String, Plugin> availablePlugins = pluginManager.getInstallablePlugins();
7678
items.putAll(availablePlugins
77-
.entrySet().stream()
78-
.filter(e -> !installedPlugins.containsKey(e.getKey()))
79-
.map(e -> new PluginListItem(installedPlugins.containsKey(e.getKey()), e.getValue()))
79+
.values().stream()
80+
.filter(p -> !installedPlugins.containsKey(p.getName()))
81+
.filter(pluginFilter)
82+
.map(p -> new PluginListItem(installedPlugins.containsKey(p.getName()), p))
8083
.collect(Collectors.toMap(p -> p.getName(), p -> p)));
8184
}
8285

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

devtools/cli/src/main/java/io/quarkus/cli/plugin/CliPluginsRemove.java

+8-5
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class CliPluginsRemove extends CliPluginsBase implements Callable<Integer
1616
@CommandLine.Mixin
1717
RunModeOption runMode;
1818

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

2222
@Override
@@ -39,17 +39,20 @@ public Integer call() {
3939

4040
Integer removePlugin() throws IOException {
4141
PluginManager pluginManager = pluginManager();
42-
Plugin toRemove = pluginManager.getInstalledPlugins().get(name);
43-
Optional<Plugin> removedPlugin = pluginManager.removePlugin(name);
42+
Optional<Plugin> removedPlugin = pluginManager.removePlugin(name, catalogOptions.user);
4443

4544
return removedPlugin.map(plugin -> {
4645
PluginListTable table = new PluginListTable(List.of(new PluginListItem(false, plugin)), false);
4746
output.info("Removed plugin:");
4847
output.info(table.getContent());
49-
if (!plugin.isInUserCatalog()) {
50-
if (userPluginManager().getInstalledPlugins().containsKey(plugin.getName())) {
48+
// Check if plugin still exists
49+
if (pluginManager.getInstalledPlugins().containsKey(plugin.getName())) {
50+
if (plugin.isInProjectCatalog()) {
5151
output.warn(
5252
"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!");
53+
} else {
54+
output.warn(
55+
"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!");
5356
}
5457
}
5558
return CommandLine.ExitCode.OK;

devtools/cli/src/main/java/io/quarkus/cli/plugin/JBangCommand.java

+7
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,11 @@ public List<String> getArguments() {
4949
public OutputOptionMixin getOutput() {
5050
return output;
5151
}
52+
53+
@Override
54+
public void useArguments(List<String> arguments) {
55+
this.arguments.clear();
56+
this.arguments.add(location);
57+
this.arguments.addAll(arguments);
58+
}
5259
}

devtools/cli/src/main/java/io/quarkus/cli/plugin/PluginCommand.java

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ public interface PluginCommand extends Callable<Integer> {
1717

1818
OutputOptionMixin getOutput();
1919

20+
void useArguments(List<String> arguments);
21+
2022
default Path getWorkingDirectory() {
2123
return Paths.get(System.getProperty("user.dir"));
2224
}

devtools/cli/src/main/java/io/quarkus/cli/plugin/PluginCommandFactory.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ public PluginCommandFactory(OutputOptionMixin output) {
2727

2828
private Optional<PluginCommand> createPluginCommand(Plugin plugin) {
2929
switch (plugin.getType()) {
30-
case jar:
3130
case maven:
3231
return plugin.getLocation().flatMap(PluginUtil::checkGACTV).map(g -> new JBangCommand(toGAVC(g), output));
32+
case java:
33+
case jar:
3334
case jbang:
3435
return plugin.getLocation().map(l -> new JBangCommand(l, output));
3536
case executable:
@@ -60,7 +61,7 @@ public <T> T set(T value) throws Exception {
6061
}
6162
if (value instanceof String[]) {
6263
String[] array = (String[]) value;
63-
command.getArguments().addAll(Arrays.asList(array));
64+
command.useArguments(Arrays.asList(array));
6465
}
6566
return value;
6667
}

devtools/cli/src/main/java/io/quarkus/cli/plugin/ShellCommand.java

+6
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ public List<String> getArguments() {
4242
return arguments;
4343
}
4444

45+
@Override
46+
public void useArguments(List<String> arguments) {
47+
this.arguments.clear();
48+
this.arguments.addAll(arguments);
49+
}
50+
4551
public OutputOptionMixin getOutput() {
4652
return output;
4753
}

devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/Deploy.java

+17-15
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
import java.util.List;
66
import java.util.Map;
77
import java.util.Optional;
8+
import java.util.Set;
89
import java.util.stream.Collectors;
910

1011
import javax.inject.Inject;
1112

1213
import org.gradle.api.tasks.Input;
13-
import org.gradle.api.tasks.StopExecutionException;
1414
import org.gradle.api.tasks.TaskAction;
1515
import org.gradle.api.tasks.options.Option;
1616

@@ -47,11 +47,6 @@ public String[] getRequiresOneOf() {
4747
}
4848
}
4949

50-
@Inject
51-
public Deploy() {
52-
super("Deploy");
53-
}
54-
5550
@Input
5651
Optional<String> deployer = Optional.empty();
5752
boolean imageBuild = false;
@@ -73,8 +68,9 @@ public void setImageBuilder(String imageBuilder) {
7368
this.imageBuild = true;
7469
}
7570

76-
public Deploy(String description) {
77-
super(description);
71+
@Inject
72+
public Deploy() {
73+
super("Deploy");
7874
extension().forcedPropertiesProperty().convention(
7975
getProject().provider(() -> {
8076
Map<String, String> props = new HashMap<>();
@@ -96,6 +92,7 @@ public void checkRequiredExtensions() {
9692
List<String> projectDependencies = getProject().getConfigurations().stream().flatMap(c -> c.getDependencies().stream())
9793
.map(d -> d.getName())
9894
.collect(Collectors.toList());
95+
9996
if (!projectDependencies.contains(requiredDeployerExtension)) {
10097
abort("Task: {} requires extensions: {}\n" +
10198
"To add the extensions to the project you can run the following command:\n" +
@@ -118,19 +115,24 @@ public void checkRequiredExtensions() {
118115
}
119116

120117
public Deployer getDeployer() {
121-
return deployer.or(() -> DeploymentUtil.getEnabledDeployer()).map(d -> Deployer.valueOf(d)).orElse(Deployer.kubernetes);
118+
return deployer
119+
.or(() -> DeploymentUtil.getEnabledDeployer())
120+
.or(() -> getProjectDeployers().stream().findFirst())
121+
.map(Deployer::valueOf)
122+
.orElse(Deployer.kubernetes);
122123
}
123124

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

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

0 commit comments

Comments
 (0)