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 c06b3a6f4ac1 CAMEL-25349: camel-jbang - camel run . --dev reloads
changed and new route files (#27384)
c06b3a6f4ac1 is described below
commit c06b3a6f4ac1398d72c9b3edd9e9bd2f9b22ed5c
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Oct 5 20:33:17 2026 +0200
CAMEL-25349: camel-jbang - camel run . --dev reloads changed and new route
files (#27384)
Running a directory (camel run . or camel run mycode) now runs it as
--source-dir,
so dev mode watches the directory: changed files are reloaded and new files
are loaded.
Before, the directory was expanded to ./orders.camel.yaml and so on, which
never
matched the reload pattern, so camel run . --dev reloaded nothing. A
directory with a
pom.xml, and the spring-boot and quarkus runtimes, still run the files in
it.
RunHelper.dirToFiles now names the files of the current directory without a
leading ./
Signed-off-by: Claus Ibsen <[email protected]>
Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
---
.../ROOT/pages/camel-4x-upgrade-guide-4_23.adoc | 5 ++
.../modules/ROOT/pages/camel-jbang-running.adoc | 4 ++
.../apache/camel/dsl/jbang/core/commands/Run.java | 18 ++++-
.../camel/dsl/jbang/core/commands/RunHelper.java | 8 ++-
.../dsl/jbang/core/commands/RunDirectoryTest.java | 78 ++++++++++++++++++++++
5 files changed, 110 insertions(+), 3 deletions(-)
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
index b95f0c3b64ab..8afd5488a35a 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
@@ -1796,6 +1796,11 @@ cost of a slower startup. If you passed `--runtime=main`
explicitly and want the
run, use `--runtime=jbang` (or leave the option out). The options
`--background`, `--code`, `--open-api`,
`--empty` and `--mcp-stdio` are not supported with `--runtime=main`.
+Running a directory (`camel run .` or `camel run mycode`) is now the same as
`--source-dir`: the route files in
+its subfolders are loaded too, and in `--dev` mode changed and new files are
reloaded (before, the directory was
+expanded to the files directly in it, and in `--dev` mode `camel run .`
reloaded nothing). A directory with a
+`pom.xml`, and the `spring-boot` and `quarkus` runtimes, still run the files
directly in the directory.
+
Running an existing Maven project (`camel run pom.xml`) is unchanged, and
still detects the runtime
from the `pom.xml`. The other commands that take `--runtime` (such as `camel
export`,
`camel dependency list` and `camel version list`) accept `jbang` as an alias
for `main`.
diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-running.adoc
b/docs/user-manual/modules/ROOT/pages/camel-jbang-running.adoc
index 22d7504d4295..8370e7887b5b 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang-running.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-running.adoc
@@ -50,6 +50,10 @@ and automatically detects new, modified, and deleted files:
camel run --source-dir=mycode --dev
----
+Running a directory is the same as `--source-dir`, so `camel run . --dev` and
`camel run mycode --dev` also reload
+changed files and pick up new ones. A directory with a `pom.xml` (an existing
Maven project), and the Spring Boot and
+Quarkus runtimes, run the files in the directory instead.
+
Without `--source-dir`, Camel only watches the specific files you listed on
the command line.
NOTE: You cannot combine files and source dir: `camel run abc.java
--source-dir=mycode` is not allowed.
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
index 39f92ce7a567..60b810c670a5 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
@@ -737,6 +737,16 @@ public class Run extends CamelCommand {
return prop;
}
+ /**
+ * Whether a directory given as the only file (camel run . or camel run
dirName) runs as --source-dir. A Maven
+ * project keeps running its files, and so do the Spring Boot and Quarkus
runtimes, which export the files to run
+ * them.
+ */
+ boolean runsDirectoryAsSourceDir(Path dir) {
+ return (RuntimeType.jbang == runtime || RuntimeType.main == runtime)
+ && !Files.exists(dir.resolve("pom.xml"));
+ }
+
private int run() throws Exception {
if (!empty && !files.isEmpty() && sourceDir != null) {
// cannot have both files and source dir at the same time
@@ -753,7 +763,13 @@ public class Run extends CamelCommand {
Path first = Path.of(name);
if (Files.isDirectory(first)) {
baseDir = first;
- RunHelper.dirToFiles(name, files);
+ if (runsDirectoryAsSourceDir(first)) {
+ // run the directory as --source-dir, so dev mode
watches it: changed and new files are reloaded
+ sourceDir = name;
+ files.clear();
+ } else {
+ RunHelper.dirToFiles(name, files);
+ }
}
}
}
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/RunHelper.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/RunHelper.java
index b0089a0a40e3..dccf404e15c7 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/RunHelper.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/RunHelper.java
@@ -306,10 +306,14 @@ public final class RunHelper {
}
/**
- * When using camel run . or camel export . then dot should include all
the files in the current folder.
+ * When using camel run . or camel export . then dot should include all
the files in the current folder. The files
+ * of the current folder are named without a leading ./
(orders.camel.yaml), so they match the reload pattern in dev
+ * mode.
*/
public static void dirToFiles(String dir, List<String> files) {
files.clear();
+ boolean currentDir = Paths.get(dir).normalize().toString().isEmpty();
+ String base = currentDir ? "" : FileUtil.stripTrailingSeparator(dir) +
"/";
try (Stream<Path> paths = Files.list(Paths.get(dir))) {
paths.filter(p -> {
try {
@@ -318,7 +322,7 @@ public final class RunHelper {
return false;
}
})
- .forEach(f -> files.add(dir + "/" + f.getFileName()));
+ .forEach(f -> files.add(base + f.getFileName()));
} catch (IOException e) {
// Ignore
}
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/RunDirectoryTest.java
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/RunDirectoryTest.java
new file mode 100644
index 000000000000..79673b81949b
--- /dev/null
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/RunDirectoryTest.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.jbang.core.commands;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import picocli.CommandLine;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * camel run . (or camel run dirName) runs the directory as --source-dir, so
dev mode reloads changed and new files.
+ */
+class RunDirectoryTest {
+
+ private static Run run(String... args) {
+ Run command = new Run(new CamelJBangMain());
+ CommandLine.populateCommand(command, args);
+ return command;
+ }
+
+ @Test
+ void directoryOfRouteFilesRunsAsSourceDir(@TempDir Path dir) throws
Exception {
+ Files.writeString(dir.resolve("orders.camel.yaml"), "- route:\n");
+
+ assertThat(run(dir.toString()).runsDirectoryAsSourceDir(dir)).isTrue();
+ assertThat(run(dir.toString(),
"--runtime=main").runsDirectoryAsSourceDir(dir)).isTrue();
+ }
+
+ @Test
+ void mavenProjectKeepsRunningItsFiles(@TempDir Path dir) throws Exception {
+ Files.writeString(dir.resolve("pom.xml"), "<project/>");
+
+
assertThat(run(dir.toString()).runsDirectoryAsSourceDir(dir)).isFalse();
+ }
+
+ @Test
+ void exportedRuntimesKeepRunningTheFiles(@TempDir Path dir) {
+ assertThat(run(dir.toString(),
"--runtime=spring-boot").runsDirectoryAsSourceDir(dir)).isFalse();
+ assertThat(run(dir.toString(),
"--runtime=quarkus").runsDirectoryAsSourceDir(dir)).isFalse();
+ }
+
+ @Test
+ void filesOfTheCurrentDirectoryHaveNoDotPrefix() {
+ List<String> files = new ArrayList<>();
+ RunHelper.dirToFiles(".", files);
+
+ assertThat(files).isNotEmpty().contains("pom.xml").noneMatch(f ->
f.startsWith("./"));
+ }
+
+ @Test
+ void filesOfAnotherDirectoryKeepTheDirectory(@TempDir Path dir) throws
Exception {
+ Files.writeString(dir.resolve("orders.camel.yaml"), "- route:\n");
+ List<String> files = new ArrayList<>();
+ RunHelper.dirToFiles(dir + "/", files);
+
+ assertThat(files).containsExactly(dir + "/orders.camel.yaml");
+ }
+}