This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new b2d5c02d7b48 CAMEL-26455: camel-jbang - camel config set dev=true does
not set the --dev option of camel run (#28792)
b2d5c02d7b48 is described below
commit b2d5c02d7b48d4de0677b84433bf0da010ab7b2f
Author: Claus Ibsen <[email protected]>
AuthorDate: Sun Nov 1 16:21:17 2026 +0100
CAMEL-26455: camel-jbang - camel config set dev=true does not set the --dev
option of camel run (#28792)
A default from the user configuration was only looked up by the longest
name of an option, so dev=true did not set --reload,--dev. Every long name
is now looked up, the command's own key (camel.run.dev) first.
Two option definitions cleaned up before the port to aesh (CAMEL-23810):
dependency update sets the files of the export from its own target files,
instead of relying on picocli giving them to both, and --output-directory
of dependency copy is no longer required next to its default.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: Claus Ibsen <[email protected]>
---
.../ROOT/pages/camel-jbang-configuration.adoc | 9 +++++
.../META-INF/camel-jbang-commands-metadata.json | 2 +-
.../dsl/jbang/core/commands/DependencyCopy.java | 2 +-
.../dsl/jbang/core/commands/DependencyUpdate.java | 9 +++--
.../dsl/jbang/core/common/CommandLineHelper.java | 43 ++++++++++++++++++++++
.../jbang/core/commands/DependencyUpdateTest.java | 25 +++++++++++++
.../core/commands/UserConfigDefaultsTest.java | 42 +++++++++++++++++++++
.../src/test/resources/golden/cli-parse.txt | 4 +-
8 files changed, 128 insertions(+), 8 deletions(-)
diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-configuration.adoc
b/docs/user-manual/modules/ROOT/pages/camel-jbang-configuration.adoc
index 142cd4d99f47..68aee5cfb6dd 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang-configuration.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-configuration.adoc
@@ -104,6 +104,15 @@ camel config list
camel config get gav
----
+A key is the name of a command option without `--`, and the value is its
default for every command that has the
+option. An option with more than one name, such as `--reload` and `--dev` of
`camel run`, can be set by any of them.
+To set the default for one command only, start the key with `camel.` and the
command:
+
+[source,bash]
+----
+camel config set camel.run.dev=true
+----
+
=== Placeholder substitution
Configuration values can be referenced as placeholders with `#optionName`:
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
index 05eb2ab9ac66..a9c0aabcb36f 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
+++
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
@@ -7,7 +7,7 @@
{ "name": "completion", "fullName": "completion", "description": "Generate
completion script for bash\/zsh", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.Complete", "options": [ { "names":
"-h,--help", "description": "Display the help and sub-commands", "javaType":
"boolean", "type": "boolean" } ] },
{ "name": "config", "fullName": "config", "description": "Get and set user
configuration values", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.config.ConfigCommand", "options": [ {
"names": "-h,--help", "description": "Display the help and sub-commands",
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "get",
"fullName": "config get", "description": "Display user configuration value",
"sourceClass": "org.apache.camel.dsl.jbang.core.commands.config. [...]
{ "name": "debug", "fullName": "debug", "description": "Debug local Camel
integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Debug",
"options": [ { "names": "--ago", "description": "Use ago instead of yyyy-MM-dd
HH:mm:ss in timestamp.", "javaType": "boolean", "type": "boolean" }, { "names":
"--background", "description": "Run in the background", "defaultValue":
"false", "javaType": "boolean", "type": "boolean" }, { "names":
"--background-wait", "description": "How [...]
- { "name": "dependency", "fullName": "dependency", "description": "Displays
all Camel dependencies required to run", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.DependencyCommand", "options": [ {
"names": "-h,--help", "description": "Display the help and sub-commands",
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name":
"copy", "fullName": "dependency copy", "description": "Copies all Camel
dependencies required to run to a specific directory", "sourc [...]
+ { "name": "dependency", "fullName": "dependency", "description": "Displays
all Camel dependencies required to run", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.DependencyCommand", "options": [ {
"names": "-h,--help", "description": "Display the help and sub-commands",
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name":
"copy", "fullName": "dependency copy", "description": "Copies all Camel
dependencies required to run to a specific directory", "sourc [...]
{ "name": "dev", "fullName": "dev", "description": "Run in dev mode with
live reload", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Dev",
"options": [ { "names": "--background", "description": "Run in the background",
"defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names":
"--background-wait", "description": "How long to wait for the integration in
the background to start, before returning, in millis or as a duration such as
2m (true waits 60 secon [...]
{ "name": "dirty", "fullName": "dirty", "description": "Check if there are
dirty files from previous Camel runs that did not terminate gracefully",
"sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.Dirty",
"options": [ { "names": "--clean", "description": "Clean dirty files which are
no longer in use", "defaultValue": "false", "javaType": "boolean", "type":
"boolean" }, { "names": "-h,--help", "description": "Display the help and
sub-commands", "javaType": "boolean", " [...]
{ "name": "doc", "fullName": "doc", "description": "Shows documentation
for kamelet, component, EIP, and other Camel resources", "sourceClass":
"org.apache.camel.dsl.jbang.core.commands.catalog.CatalogDoc", "options": [ {
"names": "--camel-version", "description": "To use a different Camel version
than the default version", "javaType": "java.lang.String", "type": "string" },
{ "names": "--download", "description": "Whether to allow automatic downloading
JAR dependencies (over the int [...]
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyCopy.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyCopy.java
index d1ec34795362..e2b6beef71fc 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyCopy.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyCopy.java
@@ -45,7 +45,7 @@ public class DependencyCopy extends DependencyList {
private MavenDownloader downloader;
@CommandLine.Option(names = { "--output-directory" }, description =
"Directory where dependencies should be copied",
- defaultValue = "lib", required = true)
+ defaultValue = "lib")
protected String outputDirectory;
private boolean outputDirectoryCreated = false;
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyUpdate.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyUpdate.java
index effadb16e0d8..87bda04d17c4 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyUpdate.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyUpdate.java
@@ -85,6 +85,10 @@ public class DependencyUpdate extends DependencyList {
return CliExitCode.USAGE;
}
+ // every file is a source file of the export pipeline: the Java files
for their //DEPS and the route
+ // definition files (YAML, XML) for the dependency resolution (a
pom.xml is skipped there).
+ // The command line can also give them to the files of the export, so
they are set only from here.
+ this.files.clear();
for (Path file : targetFiles) {
if (!Files.exists(file)) {
printer().printErr("Source file does not exist: " + file);
@@ -94,11 +98,8 @@ public class DependencyUpdate extends DependencyList {
String ext = FileUtil.onlyExt(name, true);
if ("pom.xml".equals(name) || "java".equals(ext)) {
updateTargets.add(file);
- } else {
- // route definition files (YAML, XML) are used as source files
- // for the export pipeline dependency resolution
- this.files.add(file.toString());
}
+ this.files.add(file.toString());
}
if (scanRoutes) {
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CommandLineHelper.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CommandLineHelper.java
index edb006cc7470..8186242c0828 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CommandLineHelper.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CommandLineHelper.java
@@ -24,6 +24,8 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Properties;
import java.util.function.Consumer;
@@ -235,12 +237,16 @@ public final class CommandLineHelper {
private static class CamelUserConfigDefaultValueProvider extends
CommandLine.PropertiesDefaultProvider {
+ private final Properties properties;
+
public CamelUserConfigDefaultValueProvider(Path file) {
super(file.toFile());
+ this.properties = null;
}
public CamelUserConfigDefaultValueProvider(Properties properties) {
super(properties);
+ this.properties = properties;
}
@Override
@@ -250,8 +256,45 @@ public final class CommandLineHelper {
if (parent != null && parent.name().equals("plugin")) {
return null;
}
+ if (properties != null && argSpec instanceof
CommandLine.Model.OptionSpec option) {
+ return optionDefaultValue(option);
+ }
return super.defaultValue(argSpec);
}
+
+ // picocli only looks up the longest name of an option, so dev=true
would not set --reload,--dev:
+ // look up every long name, first for the command (camel.run.dev) and
then for all commands (dev)
+ private String optionDefaultValue(CommandLine.Model.OptionSpec option)
{
+ List<String> names = new ArrayList<>();
+ names.add(option.longestName());
+ for (String name : option.names()) {
+ if (name.startsWith("--") && !names.contains(name)) {
+ names.add(name);
+ }
+ }
+ String command = option.command().qualifiedName(".");
+ for (String name : names) {
+ String value = properties.getProperty(command + "." +
stripPrefix(name));
+ if (value != null) {
+ return value;
+ }
+ }
+ for (String name : names) {
+ String value = properties.getProperty(stripPrefix(name));
+ if (value != null) {
+ return value;
+ }
+ }
+ return null;
+ }
+
+ private static String stripPrefix(String name) {
+ int i = 0;
+ while (i < name.length() &&
!Character.isJavaIdentifierPart(name.charAt(i))) {
+ i++;
+ }
+ return name.substring(i);
+ }
}
}
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/DependencyUpdateTest.java
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/DependencyUpdateTest.java
index 1c5a528fc1a5..f6e9fffd722d 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/DependencyUpdateTest.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/DependencyUpdateTest.java
@@ -385,6 +385,31 @@ class DependencyUpdateTest extends
CamelCommandBaseTestSupport {
assertThat(content2).contains("//DEPS org.apache.camel:camel-bom:");
}
+ @Test
+ void shouldUpdateWhenOnlyTheTargetFilesAreGiven() throws Exception {
+ Path java = createFile("MyRoute.java", """
+ ///usr/bin/env jbang
+ import org.apache.camel.builder.RouteBuilder;
+ public class MyRoute extends RouteBuilder {
+ public void configure() {
+ from("timer:tick").to("arangodb:myDb");
+ }
+ }
+ """);
+
+ DependencyUpdate command = new DependencyUpdate(new
CamelJBangMain().withPrinter(printer));
+ CommandLine.populateCommand(command,
+ "--dir=" + workingDir,
+ java.toAbsolutePath().toString());
+ // picocli also gives the files to the <files> of the export, a
command line parser may not
+ command.files.clear();
+
+ int exit = command.doCall();
+ Assertions.assertEquals(0, exit, printer.getLines().toString());
+
+ assertThat(Files.readString(java)).contains("//DEPS
org.apache.camel:camel-arangodb");
+ }
+
// ==================== Helpers ====================
private void addArangodbToCamelFile() throws Exception {
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/UserConfigDefaultsTest.java
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/UserConfigDefaultsTest.java
index ee87738b010c..649770e29ccd 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/UserConfigDefaultsTest.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/UserConfigDefaultsTest.java
@@ -83,12 +83,32 @@ class UserConfigDefaultsTest extends BaseConfigTestSupport {
assertThat(run("plugin", "echo")).isEqualTo("sort=pid repos=null");
}
+ @Test
+ void everyLongNameOfAnOption() throws Exception {
+ UserConfigHelper.createUserConfig("dev=true");
+ assertThat(run("dev")).isEqualTo("dev=true");
+
+ UserConfigHelper.createUserConfig("reload=true");
+ assertThat(run("dev")).isEqualTo("dev=true");
+
+ UserConfigHelper.createUserConfig("camel.dev.dev=true");
+ assertThat(run("dev")).isEqualTo("dev=true");
+ }
+
+ @Test
+ void configurationOfOneCommandWinsForAnyName() throws Exception {
+ UserConfigHelper.createUserConfig("reload=true\ncamel.dev.dev=false");
+
+ assertThat(run("dev")).isEqualTo("dev=false");
+ }
+
private static String run(String... args) {
StringPrinter out = new StringPrinter();
CamelJBangMain main = new CamelJBangMain().withPrinter(out);
CommandLine commandLine = new CommandLine(main)
.addSubcommand("echo", new CommandLine(new EchoCommand(main)))
.addSubcommand("other", new CommandLine(new EchoCommand(main)))
+ .addSubcommand("dev", new CommandLine(new DevCommand(main)))
.addSubcommand("plugin", new CommandLine(new
PluginCommand(main))
.addSubcommand("echo", new CommandLine(new
EchoCommand(main))));
CommandLineHelper.augmentWithUserConfiguration(commandLine);
@@ -121,4 +141,26 @@ class UserConfigDefaultsTest extends BaseConfigTestSupport
{
return 0;
}
}
+
+ // an option with two long names, as --reload,--dev of camel run
+ static class DevCommand extends CamelCommand {
+
+ @CommandLine.Option(names = { "--reload", "--dev" })
+ boolean dev;
+
+ DevCommand(CamelJBangMain main) {
+ super(main);
+ }
+
+ @Override
+ protected boolean disarrangeLogging() {
+ return false;
+ }
+
+ @Override
+ public Integer doCall() {
+ printer().println("dev=" + dev);
+ return 0;
+ }
+ }
}
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/cli-parse.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/cli-parse.txt
index df67a10a13e6..c6379d430612 100644
--- a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/cli-parse.txt
+++ b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/cli-parse.txt
@@ -6270,7 +6270,7 @@
debugOptions.openTelemetryAgentExport="tui"
debugOptions.trace=false
dependencies=[]
- dev=false
+ dev=true
empty=false
example=null
excludes=[]
@@ -6331,7 +6331,7 @@
stub=null
verbose=false
> run --dev=false
- (defaults)
+ dev=false
> export
applicationProperties=null
buildProperties=[]