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 2b1f09734d0e CAMEL-26912: camel-jbang - camel export no longer deletes
the files of a directory that no export created (#29813)
2b1f09734d0e is described below
commit 2b1f09734d0ef02b11d51048b3630614de5bebcd
Author: Claus Ibsen <[email protected]>
AuthorDate: Fri Nov 13 16:40:40 2026 +0100
CAMEL-26912: camel-jbang - camel export no longer deletes the files of a
directory that no export created (#29813)
An export to a directory other than the current one writes a .camel-export
file in it, and a later export only cleans a directory that has it. Any
other
directory with files is not exported to without --clean-dir.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: Claus Ibsen <[email protected]>
---
.../ROOT/pages/camel-4x-upgrade-guide-4_24.adoc | 16 ++++++
.../modules/ROOT/pages/camel-jbang-projects.adoc | 4 ++
.../jbang/core/commands/DependencyUpdateTest.java | 2 +
.../test/resources/golden/expected/deps.export.txt | 1 +
.../resources/golden/expected/excludes.export.txt | 1 +
.../resources/golden/expected/groovy.export.txt | 1 +
.../test/resources/golden/expected/java.export.txt | 1 +
.../resources/golden/expected/kamelet.export.txt | 1 +
.../golden/expected/local-kamelet-dir.export.txt | 1 +
.../golden/expected/maven-main-chaos.maven.txt | 1 +
.../golden/expected/maven-main-mixed.maven.txt | 1 +
.../resources/golden/expected/maven-main.maven.txt | 1 +
.../golden/expected/maven-quarkus-dev.maven.txt | 1 +
.../golden/expected/maven-quarkus.maven.txt | 1 +
.../golden/expected/maven-spring-boot.maven.txt | 1 +
.../resources/golden/expected/mixed.export.txt | 1 +
.../resources/golden/expected/openapi.export.txt | 1 +
.../resources/golden/expected/options.export.txt | 1 +
.../golden/expected/pom-project.export.txt | 1 +
.../golden/expected/profile-prod.export.txt | 1 +
.../resources/golden/expected/profile.export.txt | 1 +
.../golden/expected/resource-dir.export.txt | 1 +
.../golden/expected/run-settings.export.txt | 1 +
.../test/resources/golden/expected/xml.export.txt | 1 +
.../resources/golden/expected/yaml-deps.export.txt | 1 +
.../test/resources/golden/expected/yaml.export.txt | 1 +
.../camel/dsl/jbang/run/common/ExportHelper.java | 26 ++++++++++
.../dsl/jbang/run/export/CamelMainExporter.java | 16 +++---
.../camel/dsl/jbang/run/export/Exporter.java | 53 +++++++++++++++++++
.../dsl/jbang/run/export/QuarkusExporter.java | 16 +++---
.../dsl/jbang/run/export/SpringBootExporter.java | 16 +++---
.../dsl/jbang/run/export/ProjectExporterTest.java | 59 ++++++++++++++++++++++
32 files changed, 201 insertions(+), 30 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 a419236e5e35..f74c0e2bff83 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
@@ -2079,6 +2079,22 @@ events, such as `QueueParamsEvent`, `QueueMemberEvent`
and `PeerEntryEvent`. Bef
`ManagerResponse` saying that the list will follow, and the events were lost.
A route that read that response from
the body now finds it in `${body.response}`. `EXTENSION_STATE` still sets the
`ManagerResponse` as the body.
+=== camel-jbang - camel export no longer deletes the files of a directory that
no export created
+
+`camel export --dir=<dir>` to a directory other than the current one used to
delete the files of that directory first,
+whatever they were. It now only does so for a directory that an earlier export
created: the export writes a
+`.camel-export` file in it. Exporting to a directory with other files fails,
and keeps them:
+
+----
+Cannot export to /home/me/project because it has files that camel export did
not create: use --clean-dir to delete them, or export to another directory
+----
+
+This includes exporting to the directory of the exported files themselves from
another directory (such as
+`camel export /work/route.camel.yaml --dir=/work`), which deleted the source
files: use `--clean-dir --yes` for that.
+A directory that an earlier Camel version exported to has no `.camel-export`
file yet: export to it once with
+`--clean-dir --yes`. An empty directory, one with only hidden files (such as
`.git`), and the current directory are
+exported to as before.
+
=== camel-jbang - camel validate and camel overview report the same endpoints
no route consumes
`camel validate source` and `camel overview` now use the same rules for a
`direct:`, `seda:` or `disruptor:` endpoint
diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-projects.adoc
b/docs/user-manual/modules/ROOT/pages/camel-jbang-projects.adoc
index 19a3bd7a267c..5b4820208a6b 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang-projects.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-projects.adoc
@@ -15,6 +15,10 @@ camel export --runtime=camel-main
--gav=com.foo:acme:1.0-SNAPSHOT
NOTE: Without `--directory`, files are exported to the current directory. Use
`--directory=../myproject` to copy to a separate folder.
+The export writes a `.camel-export` file in a separate folder, and replaces
that folder when it exports to it again, so
+no stale files of the earlier export are left. It does not delete the files of
a folder that no export created: the
+export fails, unless `--clean-dir` is given. Without `--directory`, the files
of the current directory are kept.
+
TIP: Run `camel export --help` for all options.
Notes:
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 b56e6faf8945..6a3bbc0881f6 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
@@ -126,6 +126,8 @@ class DependencyUpdateTest extends
CamelCommandBaseTestSupport {
CommandLineTestHelper.parse(exportCommand,
"--gav=examples:route:1.0.0",
"--dir=" + workingDir,
+ // the directory has the route that camel init created, which
the export replaces with the project
+ "--clean-dir", "--yes",
"--camel-version=4.13.0",
"--runtime=" + rt.runtime(),
CamelCommandBaseTestSupport.quarkusExtRegistry(),
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/deps.export.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/deps.export.txt
index eb85d46ca72a..95e3dd96bdfd 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/deps.export.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/deps.export.txt
@@ -27,6 +27,7 @@
dependency=mvn\:org.apache.camel\:camel-timer\:${camel.version}
dependency=mvn\:org.apache.camel\:camel-log\:${camel.version}
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/excludes.export.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/excludes.export.txt
index 28a8c7d6d95d..55216ddbfe3b 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/excludes.export.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/excludes.export.txt
@@ -23,6 +23,7 @@
dependency=mvn\:org.apache.camel\:camel-core-languages\:${camel.version}
dependency=mvn\:org.apache.camel\:camel-log\:${camel.version}
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/groovy.export.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/groovy.export.txt
index f7b23d6a7f69..55d469ff5fd0 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/groovy.export.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/groovy.export.txt
@@ -25,6 +25,7 @@
dependency=mvn\:org.apache.camel\:camel-timer\:${camel.version}
dependency=mvn\:org.apache.camel\:camel-log\:${camel.version}
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/java.export.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/java.export.txt
index a3235ce03fd1..f0113945af1f 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/java.export.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/java.export.txt
@@ -24,6 +24,7 @@
dependency=mvn\:org.apache.camel\:camel-core-languages\:${camel.version}
dependency=mvn\:org.apache.camel\:camel-log\:${camel.version}
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/kamelet.export.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/kamelet.export.txt
index 18b45dafd656..8b2d36f0bd35 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/kamelet.export.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/kamelet.export.txt
@@ -24,6 +24,7 @@
dependency=mvn\:org.apache.camel\:camel-timer\:${camel.version}
dependency=mvn\:org.apache.camel\:camel-core-languages\:${camel.version}
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/local-kamelet-dir.export.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/local-kamelet-dir.export.txt
index 912522d34780..5adeb10e9532 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/local-kamelet-dir.export.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/local-kamelet-dir.export.txt
@@ -25,6 +25,7 @@
dependency=mvn\:org.apache.camel\:camel-timer\:${camel.version}
dependency=mvn\:org.apache.camel\:camel-core-languages\:${camel.version}
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-main-chaos.maven.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-main-chaos.maven.txt
index 0856fb89e29d..115f78e1496e 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-main-chaos.maven.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-main-chaos.maven.txt
@@ -15,6 +15,7 @@ ${run-dir}/target/runner.jar
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-main-mixed.maven.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-main-mixed.maven.txt
index eafd54d75faf..38f49f5c2635 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-main-mixed.maven.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-main-mixed.maven.txt
@@ -21,6 +21,7 @@ ${run-dir}/target/runner.jar
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-main.maven.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-main.maven.txt
index 5f9eda63a551..6930b833224c 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-main.maven.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-main.maven.txt
@@ -14,6 +14,7 @@ ${run-dir}/target/runner.jar
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-quarkus-dev.maven.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-quarkus-dev.maven.txt
index 5370d58244b2..c28773f95499 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-quarkus-dev.maven.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-quarkus-dev.maven.txt
@@ -9,6 +9,7 @@ quarkus:dev
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-quarkus.maven.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-quarkus.maven.txt
index f5c432aa851c..bb11589a1a0a 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-quarkus.maven.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-quarkus.maven.txt
@@ -8,6 +8,7 @@ quarkus:run
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-spring-boot.maven.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-spring-boot.maven.txt
index 150af3e13b96..f948b093ad2c 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-spring-boot.maven.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/maven-spring-boot.maven.txt
@@ -8,6 +8,7 @@ spring-boot:run
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/mixed.export.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/mixed.export.txt
index a6762287608c..af681bb2e231 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/mixed.export.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/mixed.export.txt
@@ -34,6 +34,7 @@ dependency=mvn\:org.apache.camel\:camel-bean\:${camel.version}
dependency=mvn\:org.apache.camel\:camel-log\:${camel.version}
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/openapi.export.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/openapi.export.txt
index 8721f93bbe14..b1cf361d4135 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/openapi.export.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/openapi.export.txt
@@ -28,6 +28,7 @@ dependency=mvn\:org.apache.camel\:camel-http\:${camel.version}
dependency=mvn\:org.apache.camel\:camel-jackson3\:${camel.version}
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/options.export.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/options.export.txt
index bea6226d1990..b97bd8c2da98 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/options.export.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/options.export.txt
@@ -36,6 +36,7 @@
dependency=mvn\:org.apache.camel\:camel-platform-http-vertx\:${camel.version}
dependency=mvn\:org.apache.camel\:camel-platform-http-jolokia\:${camel.version}
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/pom-project.export.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/pom-project.export.txt
index eb34ebff9fca..80e17313e023 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/pom-project.export.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/pom-project.export.txt
@@ -28,6 +28,7 @@
dependency=mvn\:org.apache.camel\:camel-timer\:${camel.version}
dependency=mvn\:org.apache.camel\:camel-log\:${camel.version}
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/profile-prod.export.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/profile-prod.export.txt
index 98a0862b40bb..6fa82ed8a30f 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/profile-prod.export.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/profile-prod.export.txt
@@ -23,6 +23,7 @@
dependency=mvn\:org.apache.camel\:camel-timer\:${camel.version}
dependency=mvn\:org.apache.camel\:camel-seda\:${camel.version}
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/profile.export.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/profile.export.txt
index 7104ad660b91..a5459397ff5c 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/profile.export.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/profile.export.txt
@@ -26,6 +26,7 @@
dependency=mvn\:org.apache.camel\:camel-timer\:${camel.version}
dependency=mvn\:org.apache.camel\:camel-log\:${camel.version}
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/resource-dir.export.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/resource-dir.export.txt
index 0db33c8bd607..8d05f585a583 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/resource-dir.export.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/resource-dir.export.txt
@@ -25,6 +25,7 @@
dependency=mvn\:org.apache.camel\:camel-core-languages\:${camel.version}
dependency=mvn\:org.apache.camel\:camel-log\:${camel.version}
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/run-settings.export.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/run-settings.export.txt
index e3b48d1734bc..1457fd91232c 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/run-settings.export.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/run-settings.export.txt
@@ -24,6 +24,7 @@
dependency=mvn\:org.apache.camel\:camel-core-languages\:${camel.version}
dependency=mvn\:org.apache.camel\:camel-log\:${camel.version}
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/xml.export.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/xml.export.txt
index 2a70cb830b1d..def1a5c76b31 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/xml.export.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/xml.export.txt
@@ -22,6 +22,7 @@
dependency=mvn\:org.apache.camel\:camel-timer\:${camel.version}
dependency=mvn\:org.apache.camel\:camel-log\:${camel.version}
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/yaml-deps.export.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/yaml-deps.export.txt
index ebb8c8551d36..02305a360a58 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/yaml-deps.export.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/yaml-deps.export.txt
@@ -23,6 +23,7 @@
dependency=mvn\:org.apache.camel\:camel-timer\:${camel.version}
dependency=mvn\:org.apache.camel\:camel-log\:${camel.version}
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/yaml.export.txt
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/yaml.export.txt
index 79392d2dcfe6..3c84d8d0fba5 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/yaml.export.txt
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/golden/expected/yaml.export.txt
@@ -23,6 +23,7 @@
dependency=mvn\:org.apache.camel\:camel-core-languages\:${camel.version}
dependency=mvn\:org.apache.camel\:camel-log\:${camel.version}
# project files
+.camel-export
.mvn/wrapper/maven-wrapper.jar
.mvn/wrapper/maven-wrapper.properties
AGENTS.md
diff --git
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/common/ExportHelper.java
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/common/ExportHelper.java
index 03c8acb5d7ff..e9ad4cbe2f73 100644
---
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/common/ExportHelper.java
+++
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/common/ExportHelper.java
@@ -52,6 +52,12 @@ public final class ExportHelper {
*/
public static final String RUN_SETTINGS_FILE =
"camel-jbang-run.properties";
+ /**
+ * The file that camel export writes in the directory it exports to, other
than the current directory: a later
+ * export may replace that directory (CAMEL-26912).
+ */
+ public static final String EXPORT_MARKER = ".camel-export";
+
public static final int MAX_RESOURCE_DIR_FILES = 1000;
private ExportHelper() {
@@ -108,6 +114,26 @@ public final class ExportHelper {
}
}
+ /**
+ * Whether the directory has files or directories that are not hidden. A
directory that does not exist has none.
+ */
+ public static boolean hasVisibleFiles(Path dir) {
+ if (!Files.isDirectory(dir)) {
+ return false;
+ }
+ try (Stream<Path> paths = Files.list(dir)) {
+ return paths.anyMatch(p -> {
+ try {
+ return !Files.isHidden(p);
+ } catch (IOException e) {
+ return true;
+ }
+ });
+ } catch (IOException e) {
+ return true;
+ }
+ }
+
public static void cleanExportDir(String dir) {
cleanExportDir(dir, true);
}
diff --git
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/export/CamelMainExporter.java
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/export/CamelMainExporter.java
index 8a673b9514e8..924e4c2e12f3 100644
---
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/export/CamelMainExporter.java
+++
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/export/CamelMainExporter.java
@@ -63,6 +63,9 @@ class CamelMainExporter extends Exporter {
printer().printErr("--gav must be in syntax:
groupId:artifactId:version");
return 1;
}
+ if (!canExportTo()) {
+ return 1;
+ }
if (request.parentPom != null) {
try {
MavenGav.parseStrictGav(request.parentPom);
@@ -199,20 +202,13 @@ class CamelMainExporter extends Exporter {
}
String appJar = Paths.get("target", ids[1] + "-" + ids[2] +
".jar").toString();
copyReadme(buildDir.toString(), appJar);
- if (request.cleanExportDir ||
!ExportHelper.isCurrentDirOrParent(request.exportDir)) {
- // cleaning current dir can be a bit dangerous so only clean if
explicit enabled
- // otherwise always clean export-dir to avoid stale data
- if (request.cleanExportDir) {
- String absPath =
Path.of(request.exportDir).toAbsolutePath().toString();
- if (!request.yes && !exportContext.confirm("Are you sure you
want to delete " + absPath + "?")) {
- return 1;
- }
- }
- ExportHelper.cleanExportDir(request.exportDir);
+ if (cleanExportDir() != 0) {
+ return 1;
}
// copy to export dir and remove work dir
PathUtils.copyDirectory(buildDir, Path.of(request.exportDir));
createDeferredSymlinks(buildDir, Path.of(request.exportDir));
+ markExportDir();
PathUtils.deleteDirectory(buildDir);
return 0;
diff --git
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/export/Exporter.java
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/export/Exporter.java
index 60d77a598d4b..8b6a3c9e8bae 100644
---
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/export/Exporter.java
+++
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/export/Exporter.java
@@ -105,6 +105,59 @@ abstract class Exporter {
this.exportContext = context;
}
+ /**
+ * Whether the project can be exported to the export directory: the
current directory (or one that contains it),
+ * whose files are kept, a directory that is empty or does not exist, or
one that an earlier export created (it has
+ * the {@link ExportHelper#EXPORT_MARKER} file), which the export replaces
so no stale files of it are left. The
+ * files of any other directory are not deleted without --clean-dir
(CAMEL-26912).
+ */
+ protected boolean canExportTo() {
+ if (request.cleanExportDir ||
ExportHelper.isCurrentDirOrParent(request.exportDir)) {
+ return true;
+ }
+ Path dir = Path.of(request.exportDir);
+ if (Files.exists(dir.resolve(ExportHelper.EXPORT_MARKER)) ||
!ExportHelper.hasVisibleFiles(dir)) {
+ return true;
+ }
+ printer().printErr("Cannot export to " +
dir.toAbsolutePath().normalize()
+ + " because it has files that camel export did not
create: use --clean-dir to delete them,"
+ + " or export to another directory");
+ return false;
+ }
+
+ /**
+ * Cleans the export directory before the project is copied to it: with
--clean-dir, when the user confirms it, or a
+ * directory that is not the current directory (see {@link
#canExportTo()}).
+ *
+ * @return 0, or 1 when the user does not confirm --clean-dir
+ */
+ protected int cleanExportDir() {
+ if (request.cleanExportDir) {
+ String absPath =
Path.of(request.exportDir).toAbsolutePath().toString();
+ if (!request.yes && !exportContext.confirm("Are you sure you want
to delete " + absPath + "?")) {
+ return 1;
+ }
+ ExportHelper.cleanExportDir(request.exportDir);
+ } else if (!ExportHelper.isCurrentDirOrParent(request.exportDir)) {
+ // no stale data of an earlier export
+ ExportHelper.cleanExportDir(request.exportDir);
+ }
+ return 0;
+ }
+
+ /**
+ * Marks the export directory as created by camel export, so the next
export to it may replace it. The current
+ * directory is not marked: an export from another directory must not
delete the files of this one.
+ */
+ protected void markExportDir() throws IOException {
+ if (!ExportHelper.isCurrentDirOrParent(request.exportDir)) {
+
Files.writeString(Path.of(request.exportDir).resolve(ExportHelper.EXPORT_MARKER),
"""
+ # Created by camel export, which replaces the files of
this directory when it exports to it again.
+ # Delete this file to keep them: camel export then needs
--clean-dir to export here.
+ """);
+ }
+ }
+
/**
* The directory in the work directory where the project is built, before
it is copied to the export directory.
*/
diff --git
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/export/QuarkusExporter.java
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/export/QuarkusExporter.java
index 08527f199bfb..b6f0a1373bd6 100644
---
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/export/QuarkusExporter.java
+++
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/export/QuarkusExporter.java
@@ -86,6 +86,9 @@ class QuarkusExporter extends Exporter {
printer().printErr("--gav must be in syntax:
groupId:artifactId:version");
return 1;
}
+ if (!canExportTo()) {
+ return 1;
+ }
if (request.parentPom != null) {
try {
MavenGav.parseStrictGav(request.parentPom);
@@ -193,20 +196,13 @@ class QuarkusExporter extends Exporter {
copyCamelWrapper();
}
- if (request.cleanExportDir ||
!ExportHelper.isCurrentDirOrParent(request.exportDir)) {
- // cleaning current dir can be a bit dangerous so only clean if
explicit enabled
- // otherwise always clean export-dir to avoid stale data
- if (request.cleanExportDir) {
- String absPath =
Path.of(request.exportDir).toAbsolutePath().toString();
- if (!request.yes && !exportContext.confirm("Are you sure you
want to delete " + absPath + "?")) {
- return 1;
- }
- }
- ExportHelper.cleanExportDir(request.exportDir);
+ if (cleanExportDir() != 0) {
+ return 1;
}
// copy to export dir and remove work dir
PathUtils.copyDirectory(buildDir, Path.of(request.exportDir));
createDeferredSymlinks(buildDir, Path.of(request.exportDir));
+ markExportDir();
PathUtils.deleteDirectory(buildDir);
return 0;
diff --git
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/export/SpringBootExporter.java
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/export/SpringBootExporter.java
index d87ff8947fd4..f86b392bd16b 100644
---
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/export/SpringBootExporter.java
+++
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/export/SpringBootExporter.java
@@ -71,6 +71,9 @@ class SpringBootExporter extends Exporter {
printer().printErr("--gav must be in syntax:
groupId:artifactId:version");
return 1;
}
+ if (!canExportTo()) {
+ return 1;
+ }
if (request.parentPom != null) {
try {
MavenGav.parseStrictGav(request.parentPom);
@@ -199,20 +202,13 @@ class SpringBootExporter extends Exporter {
}
String appJar = "target" + File.separator + ids[1] + "-" + ids[2] +
".jar";
copyReadme(buildDir.toString(), appJar);
- if (request.cleanExportDir ||
!ExportHelper.isCurrentDirOrParent(request.exportDir)) {
- // cleaning current dir can be a bit dangerous so only clean if
explicit enabled
- // otherwise always clean export-dir to avoid stale data
- if (request.cleanExportDir) {
- String absPath =
Paths.get(request.exportDir).toAbsolutePath().toString();
- if (!request.yes && !exportContext.confirm("Are you sure you
want to delete " + absPath + "?")) {
- return 1;
- }
- }
- ExportHelper.cleanExportDir(request.exportDir);
+ if (cleanExportDir() != 0) {
+ return 1;
}
// copy to export dir and remove work dir
PathUtils.copyDirectory(buildDir, Paths.get(request.exportDir));
createDeferredSymlinks(buildDir, Paths.get(request.exportDir));
+ markExportDir();
PathUtils.deleteDirectory(buildDir);
return 0;
diff --git
a/dsl/camel-jbang/camel-jbang-run/src/test/java/org/apache/camel/dsl/jbang/run/export/ProjectExporterTest.java
b/dsl/camel-jbang/camel-jbang-run/src/test/java/org/apache/camel/dsl/jbang/run/export/ProjectExporterTest.java
index c7089deea347..c9e59fe8b35f 100644
---
a/dsl/camel-jbang/camel-jbang-run/src/test/java/org/apache/camel/dsl/jbang/run/export/ProjectExporterTest.java
+++
b/dsl/camel-jbang/camel-jbang-run/src/test/java/org/apache/camel/dsl/jbang/run/export/ProjectExporterTest.java
@@ -263,6 +263,65 @@ class ProjectExporterTest {
return new ExportContext().withPrinter(new
StringPrinter()).withDependencyResolver(resolver);
}
+ @Test
+ void replacesTheDirectoryOfAnEarlierExport() throws Exception {
+ Path exportDir = dir.resolve("export");
+ assertThat(export(request(writeRoute("first"), exportDir))).isZero();
+ assertThat(exportDir.resolve(ExportHelper.EXPORT_MARKER)).exists();
+
+ // the export replaces the earlier one, so no stale files of it are
left
+ assertThat(export(request(writeRoute("second"), exportDir))).isZero();
+
assertThat(exportDir.resolve("src/main/resources/camel")).isDirectoryContaining("glob:**/second.camel.yaml")
+ .isDirectoryNotContaining("glob:**/first.camel.yaml");
+ assertThat(exportDir.resolve(ExportHelper.EXPORT_MARKER)).exists();
+ }
+
+ @Test
+ void keepsTheFilesOfADirectoryThatNoExportCreated() throws Exception {
+ Path exportDir = Files.createDirectories(dir.resolve("export"));
+ Path todo = Files.writeString(exportDir.resolve("TODO.txt"), "my
notes");
+ Path notes =
Files.writeString(Files.createDirectories(exportDir.resolve("docs")).resolve("notes.txt"),
"more");
+
+ StringPrinter printer = new StringPrinter();
+ int exit = new ProjectExporter(new
ExportContext().withPrinter(printer).withDependencyResolver(resolver))
+ .export(request(writeRoute("hello"), exportDir));
+
+ assertThat(exit).isEqualTo(1);
+ assertThat(printer.getOutput()).contains("Cannot export to " +
exportDir.toAbsolutePath(), "--clean-dir");
+ assertThat(todo).hasContent("my notes");
+ assertThat(notes).hasContent("more");
+ assertThat(exportDir.resolve("pom.xml")).doesNotExist();
+ // nothing was resolved: the export stops before it boots the
integration
+ assertThat(resolved).isEmpty();
+
+ // unless they are deleted on purpose
+ ExportRequest request = request(writeRoute("hello"), exportDir);
+ request.cleanExportDir = true;
+ request.yes = true;
+ assertThat(export(request)).isZero();
+ assertThat(todo).doesNotExist();
+ assertThat(exportDir.resolve("pom.xml")).exists();
+ }
+
+ @Test
+ void exportsToADirectoryWithOnlyHiddenFiles() throws Exception {
+ // such as a clone of an empty Git repository
+ Path exportDir = Files.createDirectories(dir.resolve("export"));
+ Path git =
Files.writeString(Files.createDirectories(exportDir.resolve(".git")).resolve("HEAD"),
"ref");
+
+ assertThat(export(request(writeRoute("hello"), exportDir))).isZero();
+ assertThat(exportDir.resolve("pom.xml")).exists();
+ assertThat(git).hasContent("ref");
+ }
+
+ private int export(ExportRequest request) throws Exception {
+ StringPrinter printer = new StringPrinter();
+ int exit = new ProjectExporter(new
ExportContext().withPrinter(printer).withDependencyResolver(resolver))
+ .export(request);
+ assertThat(exit).as(printer.getOutput()).isNotNegative();
+ return exit;
+ }
+
private Path writeRoute(String name) throws Exception {
Path route = dir.resolve(name + ".camel.yaml");
Files.writeString(route, """