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 8832b022893d CAMEL-25817: camel-jbang - camel dirty removes only the
files of processes that are gone (#28109)
8832b022893d is described below
commit 8832b022893d6554f7949fa1d3dd400560554cde
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Oct 19 21:54:00 2026 +0200
CAMEL-25817: camel-jbang - camel dirty removes only the files of processes
that are gone (#28109)
Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
---
.../ROOT/pages/camel-4x-upgrade-guide-4_24.adoc | 8 ++++
.../ROOT/pages/camel-jbang-configuration.adoc | 3 ++
.../dsl/jbang/core/commands/process/Dirty.java | 26 ++++++----
.../dsl/jbang/core/commands/process/DirtyTest.java | 55 ++++++++++++++++++++++
4 files changed, 84 insertions(+), 8 deletions(-)
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
index a29fa617f76d..4a521a7823f7 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
@@ -1699,6 +1699,14 @@ A name in camel case that starts with a lower-case
letter, such as the datasourc
looks like an option name and is written in dash case as a whole, underscores
included (`my-orders`,
`my-data-source`). Quote it to keep it:
`quarkus.datasource."myOrders".db-kind`.
+=== camel-jbang - camel dirty removes only the files of processes that are gone
+
+`camel dirty` counts, and `camel dirty --clean` removes, only the files named
after the pid of a process that is gone,
+such as `<pid>-status.json`. Before, it counted every other file in `~/.camel`
too, and `--clean` removed them: the log of
+a Spring Boot or Quarkus app that `camel run` runs (`<name>.log`), also while
the app ran, the console output that the AI
+tools keep, and the history of the AI prompt. Directories are not counted, and
`--clean` counts only the files it
+removed.
+
=== camel-mongodb-gridfs - the consumer routes a file once
With the `TimeStamp` (default) and `PersistentTimestamp` query strategies, the
`mongodb-gridfs` consumer routed
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 357fe0a30c2f..142cd4d99f47 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang-configuration.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-configuration.adoc
@@ -131,6 +131,9 @@ camel dirty
camel dirty --clean
----
+Only the files named after the pid of a process that is gone count, such as
`<pid>-status.json`. Other files in
+`~/.camel`, such as the log of a Spring Boot or Quarkus app that `camel run`
runs (`<name>.log`), are left alone.
+
The log of the previous run of an integration (`~/.camel/<name>-previous.log`,
see `camel log --previous`) is kept on
purpose, so `camel dirty` leaves it.
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/Dirty.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/Dirty.java
index 5f887eb9b9b5..e1a73c12026e 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/Dirty.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/Dirty.java
@@ -45,7 +45,7 @@ public class Dirty extends ProcessBaseCommand {
@Override
public Integer doCall() throws Exception {
- File[] files = getCamelDir().toFile().listFiles(f ->
!"camel-export.log".equals(f.getName()));
+ File[] files = getCamelDir().toFile().listFiles();
if (files == null || files.length == 0) {
return 0;
}
@@ -56,11 +56,12 @@ public class Dirty extends ProcessBaseCommand {
// kept on purpose: the log of the previous run of an
integration (camel log --previous)
continue;
}
- // the files of a process that is alive are in use (such as the
launcher of an integration that runs in a
- // child process, whose Camel has stopped), and so are the files
of ourselves
- Long pid = pidOf(f.getName());
- boolean running = pid != null &&
ProcessHandle.of(pid).map(ProcessHandle::isAlive).orElse(false);
- if (!running) {
+ // only the files of a process that is gone: a file named after
its pid. The files of a process that is
+ // alive are in use (such as the launcher of an integration that
runs in a child process, whose Camel has
+ // stopped), and so are the files of ourselves. A file that
belongs to no process is left alone (such as the
+ // log of a Spring Boot or Quarkus app, <name>.log, also while the
app runs), and so is a directory.
+ Long pid = f.isFile() ? pidOf(f.getName()) : null;
+ if (pid != null &&
!ProcessHandle.of(pid).map(ProcessHandle::isAlive).orElse(false)) {
dirty.add(f);
}
}
@@ -69,10 +70,19 @@ public class Dirty extends ProcessBaseCommand {
}
if (clean) {
+ int cleaned = 0;
+ List<String> left = new ArrayList<>();
for (File f : dirty) {
- FileUtil.deleteFile(f);
+ if (FileUtil.deleteFile(f)) {
+ cleaned++;
+ } else {
+ left.add(f.getName());
+ }
+ }
+ printer().println("Cleaned " + cleaned + " orphan files");
+ if (!left.isEmpty()) {
+ printer().printWarn("Cannot delete: " + String.join(", ",
left));
}
- printer().println("Cleaned " + dirty.size() + " orphan files");
} else {
printer().println("There are " + dirty.size() + " orphan files");
}
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/process/DirtyTest.java
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/process/DirtyTest.java
index 9e1026d7c90e..85c2629710de 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/process/DirtyTest.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/process/DirtyTest.java
@@ -23,6 +23,8 @@ import java.util.Optional;
import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
import org.apache.camel.dsl.jbang.core.common.CommandLineHelper;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledOnOs;
+import org.junit.jupiter.api.condition.OS;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.MockedStatic;
import org.mockito.junit.jupiter.MockitoExtension;
@@ -123,6 +125,59 @@ class DirtyTest extends ProcessCommandTestSupport {
}
}
+ @Test
+ void testFilesThatBelongToNoProcessAreNotDirty() throws Exception {
+ Path dir = CommandLineHelper.getCamelDir();
+ // the log of a Spring Boot or Quarkus app, which writes it while it
runs
+ Files.writeString(dir.resolve("orders.log"), "Started");
+ // the console output the AI tools keep, and other files of the CLI
+ Files.writeString(dir.resolve("camel-launch-123456.log"), "Started");
+ Files.writeString(dir.resolve("ai-prompt.history"), "hello");
+ Files.writeString(dir.resolve("camel-export.log"), "Exported");
+ // directories, such as a cache
+
Files.createDirectories(dir.resolve("quarkus-extension-registries").resolve("cache"));
+ Files.createDirectories(dir.resolve("12345-dir"));
+
+ Dirty command = new Dirty(new CamelJBangMain().withPrinter(printer));
+ command.clean = true;
+
+ try (MockedStatic<ProcessHandle> mocked =
mockStatic(ProcessHandle.class)) {
+ int exit = command.doCall();
+
+ assertEquals(0, exit);
+ assertEquals("", printer.getOutput().trim());
+ for (String name : new String[] {
+ "orders.log", "camel-launch-123456.log",
"ai-prompt.history", "camel-export.log",
+ "quarkus-extension-registries", "12345-dir" }) {
+ assertTrue(Files.exists(dir.resolve(name)), name + " is left");
+ }
+ }
+ }
+
+ @Test
+ @DisabledOnOs(OS.WINDOWS)
+ void testOnlyTheFilesThatWereRemovedAreCounted() throws Exception {
+ Path dir = CommandLineHelper.getCamelDir();
+ Path orphan = dir.resolve("77777-status.json");
+ Files.writeString(orphan, "{}");
+ // a file in a directory that cannot be written cannot be deleted
+ assertTrue(dir.toFile().setWritable(false));
+
+ Dirty command = new Dirty(new CamelJBangMain().withPrinter(printer));
+ command.clean = true;
+
+ try (MockedStatic<ProcessHandle> mocked =
mockStatic(ProcessHandle.class)) {
+ int exit = command.doCall();
+
+ assertEquals(0, exit);
+ assertTrue(printer.getOutput().contains("Cleaned 0 orphan files"),
printer.getOutput());
+ assertTrue(printer.getOutput().contains("WARN: Cannot delete:
77777-status.json"), printer.getOutput());
+ assertTrue(Files.exists(orphan));
+ } finally {
+ dir.toFile().setWritable(true);
+ }
+ }
+
@Test
void testFileBelongsToTheWholePid() {
// pid 12 does not own the files of pid 123