diff --git a/spring-modulith-docs/src/main/java/org/springframework/modulith/docs/Documenter.java b/spring-modulith-docs/src/main/java/org/springframework/modulith/docs/Documenter.java
index 5b6ee6a1..be9a9d45 100644
--- a/spring-modulith-docs/src/main/java/org/springframework/modulith/docs/Documenter.java
+++ b/spring-modulith-docs/src/main/java/org/springframework/modulith/docs/Documenter.java
@@ -183,14 +183,14 @@ public class Documenter {
*
The Module Canvas for each module.
*
*
- * @param options must not be {@literal null}.
+ * @param diagramOptions must not be {@literal null}.
* @param canvasOptions must not be {@literal null}.
* @return the current instance, will never be {@literal null}.
*/
- public Documenter writeDocumentation(DiagramOptions options, CanvasOptions canvasOptions) {
+ public Documenter writeDocumentation(DiagramOptions diagramOptions, CanvasOptions canvasOptions) {
if (this.options.clean) {
- clear();
+ clearOutputFolder();
}
return writeModulesAsPlantUml(options)
@@ -610,10 +610,15 @@ public class Documenter {
.createComponentView(container, prefix + options.toString(), "");
}
- private void clear() {
+ private void clearOutputFolder() {
- try {
- Files.deleteIfExists(Paths.get(options.outputFolder));
+ Path outputPath = Paths.get(options.outputFolder);
+ if (!outputPath.toFile().exists()) {
+ return;
+ }
+
+ try (Stream paths = Files.walk(outputPath)) {
+ paths.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
} catch (IOException o_O) {
throw new RuntimeException(o_O);
}
@@ -1289,14 +1294,37 @@ public class Documenter {
this.clean = clean;
}
+ /**
+ * Creates a default {@link Options} instance configuring a default output folder based on the detected build tool (see {@link Options#DEFAULT_LOCATION}).
+ * Use {@link #withOutputFolder(String)} if you want to customize the output folder.
+ * Per default the output folder is wiped before any files are written to it.
+ * Use {@link #withoutClean()} to disable cleaning of the output folder.
+ *
+ * @return will never be {@literal null}.
+ * @see #withoutClean()
+ * @see #withOutputFolder(String)
+ */
public static Options defaults() {
return new Options(DEFAULT_LOCATION, true);
}
+ /**
+ * Disables the cleaning of the output folder before any file is written.
+ *
+ * @return will never be {@literal null}.
+ */
public Options withoutClean() {
return new Options(outputFolder, false);
}
+ /**
+ * Configures the output folder for the created files.
+ * The given directory is wiped before any files are written to it.
+ *
+ * @param folder if null the default location based on the detected build tool will be used (see {@link Options#DEFAULT_LOCATION}).
+ * The given folder will be created if it does not exist already. Existing folders are supported as well.
+ * @return will never be {@literal null}.
+ */
public Options withOutputFolder(String folder) {
return new Options(folder, clean);
}
diff --git a/spring-modulith-integration-test/src/test/java/org/springframework/modulith/docs/DocumenterTest.java b/spring-modulith-integration-test/src/test/java/org/springframework/modulith/docs/DocumenterTest.java
index ec6cc624..d3c1deb9 100644
--- a/spring-modulith-integration-test/src/test/java/org/springframework/modulith/docs/DocumenterTest.java
+++ b/spring-modulith-integration-test/src/test/java/org/springframework/modulith/docs/DocumenterTest.java
@@ -27,10 +27,12 @@ import java.util.Optional;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
import org.springframework.modulith.core.ApplicationModule;
import org.springframework.modulith.core.ApplicationModules;
import org.springframework.modulith.core.DependencyType;
import org.springframework.modulith.docs.Documenter.DiagramOptions;
+import org.springframework.modulith.docs.Documenter.Options;
import org.springframework.util.function.ThrowingConsumer;
import com.acme.myproject.Application;
@@ -139,6 +141,46 @@ class DocumenterTest {
});
}
+ @Test
+ void shouldCleanOutputLocation(@TempDir Path outputDirectory) throws IOException {
+
+ var filePath = createTestFile(outputDirectory);
+ var nestedFiledPath = createTestFileInSubdirectory(outputDirectory);
+
+ new Documenter(ApplicationModules.of(Application.class), outputDirectory.toString()).writeDocumentation();
+
+ assertThat(filePath).doesNotExist();
+ assertThat(nestedFiledPath).doesNotExist();
+ assertThat(Files.list(outputDirectory)).isNotEmpty();
+ }
+
+ @Test
+ void shouldNotCleanOutputLocation(@TempDir Path outputDirectory) throws IOException {
+
+ var filePath = createTestFile(outputDirectory);
+ var nestedFiledPath = createTestFileInSubdirectory(outputDirectory);
+
+ new Documenter(ApplicationModules.of(Application.class),
+ Options.defaults().withOutputFolder(outputDirectory.toString()).withoutClean())
+ .writeDocumentation();
+
+ assertThat(filePath).exists();
+ assertThat(nestedFiledPath).exists();
+ assertThat(Files.list(outputDirectory)).isNotEmpty();
+ }
+
+ private static Path createTestFile(Path tempDir) throws IOException {
+ return createFile(tempDir.resolve("some-old-module.adoc"));
+ }
+
+ private static Path createTestFileInSubdirectory(Path tempDir) throws IOException {
+ return createFile(tempDir.resolve("some-subdirectory").resolve("old-module.adoc"));
+ }
+
+ private static Path createFile(Path filePath) throws IOException {
+ return Files.createDirectories(filePath);
+ }
+
private static void deleteDirectoryContents(Path path) throws IOException {
if (Files.exists(path) && Files.isDirectory(path)) {