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 2d707da62273 CAMEL-26930: camel-jbang - an example run in the
background deletes its folder when it ends (#29982)
2d707da62273 is described below
commit 2d707da62273cedf10b7bee56a0adebab85827fb
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat Nov 14 21:57:32 2026 +0100
CAMEL-26930: camel-jbang - an example run in the background deletes its
folder when it ends (#29982)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
.../apache/camel/dsl/jbang/core/commands/Run.java | 8 ++++
.../camel/dsl/jbang/core/common/ExampleHelper.java | 38 +++++++++++++++
.../core/common/ExampleHelperExampleDirTest.java | 56 ++++++++++++++++++++++
3 files changed, 102 insertions(+)
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 5b5eada118ec..8062ef890a96 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
@@ -695,6 +695,10 @@ public class Run extends CamelCommand implements
CommandLifecycle {
}
ProcessBuilder pb = new ProcessBuilder(cmds);
pb.directory(dir.toFile());
+ if (background) {
+ // the JVM that runs the example in the background deletes its
folder when it ends
+ pb.environment().put(ExampleHelper.EXAMPLE_DIR_ENV,
dir.toString());
+ }
pb.inheritIO(); // run in foreground (with IO so logs are visible)
Process p = pb.start();
this.spawnPid = p.pid();
@@ -1621,6 +1625,10 @@ public class Run extends CamelCommand implements
CommandLifecycle {
* Runs Camel in this JVM, which the run configured, and waits for it to
end.
*/
protected int runKameletMain(ConfiguredRun run) throws Exception {
+ if (spawned) {
+ // the JVM that runs an example started in the background: its
folder goes when it ends
+
ExampleHelper.deleteExampleDirOnExit(System.getenv(ExampleHelper.EXAMPLE_DIR_ENV));
+ }
return withChaosVerdict(run.start().waitFor());
}
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/ExampleHelper.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/ExampleHelper.java
index 382c4b2a335e..a72292720ae8 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/ExampleHelper.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/ExampleHelper.java
@@ -574,6 +574,44 @@ public final class ExampleHelper {
Runtime.getRuntime().addShutdownHook(new Thread(() ->
FileUtil.removeDir(dir.toFile()), "CamelExampleCleanup"));
}
+ /**
+ * The environment variable with the folder of an example run in the
background, for the JVM that runs it: that JVM
+ * outlives the camel run that made the folder, and deletes it when it
ends, such as by camel stop. The folder was
+ * left in the temporary directory (CAMEL-26930).
+ */
+ public static final String EXAMPLE_DIR_ENV = "CAMEL_CLI_EXAMPLE_DIR";
+
+ /**
+ * Deletes the folder of the example when this JVM exits, when the folder
is one this CLI made for an example: a
+ * {@value #EXAMPLE_DIR_PREFIX} folder in the temporary directory. Any
other folder is left alone.
+ *
+ * @param dir the folder, from {@link #EXAMPLE_DIR_ENV}, or null
+ */
+ public static void deleteExampleDirOnExit(String dir) {
+ Path path = exampleDir(dir);
+ if (path != null) {
+ deleteOnExit(path);
+ }
+ }
+
+ /** The folder, when it is a folder of an example in the temporary
directory; else null. */
+ static Path exampleDir(String dir) {
+ return exampleDir(dir, Path.of(System.getProperty("java.io.tmpdir")));
+ }
+
+ static Path exampleDir(String dir, Path tmp) {
+ if (dir == null || dir.isBlank()) {
+ return null;
+ }
+ Path path = realPath(Path.of(dir));
+ if (!Files.isDirectory(path) || path.getFileName() == null
+ ||
!path.getFileName().toString().startsWith(EXAMPLE_DIR_PREFIX)
+ || !realPath(tmp).equals(path.getParent())) {
+ return null;
+ }
+ return path;
+ }
+
/**
* The folders of examples in the temporary directory that are older than
the given age and that none of the given
* folders (those of running integrations) is in: left behind by runs that
ended, or by a process that was killed.
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/ExampleHelperExampleDirTest.java
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/ExampleHelperExampleDirTest.java
new file mode 100644
index 000000000000..7a33228ab30e
--- /dev/null
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/ExampleHelperExampleDirTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.common;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * The JVM that runs an example in the background deletes the folder of the
example when it ends, and only a folder the
+ * CLI made for an example (CAMEL-26930).
+ */
+class ExampleHelperExampleDirTest {
+
+ @TempDir
+ Path tmp;
+
+ @Test
+ void anExampleFolderInTheTemporaryDirectory() throws Exception {
+ Path example =
Files.createDirectory(tmp.resolve(ExampleHelper.EXAMPLE_DIR_PREFIX + "123"));
+
+ assertThat(ExampleHelper.exampleDir(example.toString(),
tmp)).isEqualTo(example.toRealPath());
+ }
+
+ @Test
+ void anyOtherFolderIsLeftAlone() throws Exception {
+ Path other = Files.createDirectory(tmp.resolve("my-project"));
+ Path nested =
Files.createDirectories(tmp.resolve("x").resolve(ExampleHelper.EXAMPLE_DIR_PREFIX
+ "1"));
+
+ assertThat(ExampleHelper.exampleDir(other.toString(), tmp)).isNull();
+ // not directly in the temporary directory
+ assertThat(ExampleHelper.exampleDir(nested.toString(), tmp)).isNull();
+
assertThat(ExampleHelper.exampleDir(tmp.resolve(ExampleHelper.EXAMPLE_DIR_PREFIX
+ "gone").toString(), tmp))
+ .isNull();
+ assertThat(ExampleHelper.exampleDir(null, tmp)).isNull();
+ assertThat(ExampleHelper.exampleDir("", tmp)).isNull();
+ }
+}