1919import io .qameta .allure .internal .Allure2ModelJackson ;
2020import io .qameta .allure .model .TestResult ;
2121import io .qameta .allure .model .TestResultContainer ;
22+ import org .slf4j .Logger ;
23+ import org .slf4j .LoggerFactory ;
2224
2325import java .io .IOException ;
2426import java .io .InputStream ;
2527import java .nio .file .Files ;
2628import java .nio .file .Path ;
29+ import java .util .Comparator ;
2730import java .util .Objects ;
2831import java .util .UUID ;
32+ import java .util .stream .Stream ;
33+ import java .util .concurrent .atomic .AtomicBoolean ;
2934
3035/**
3136 * @author charlie (Dmitry Baev).
3237 */
3338public class FileSystemResultsWriter implements AllureResultsWriter {
3439
40+ private static final Logger LOGGER = LoggerFactory .getLogger (FileSystemResultsWriter .class );
41+
3542 private final Path outputDirectory ;
3643
3744 private final ObjectMapper mapper ;
3845
46+ private final boolean cleanBeforeRun ;
47+
48+ private final boolean cleanOnlyOnce ;
49+
50+ private final AtomicBoolean cleaned = new AtomicBoolean (false );
51+
3952 public FileSystemResultsWriter (final Path outputDirectory ) {
53+ this (outputDirectory , false , true );
54+ }
55+
56+ public FileSystemResultsWriter (final Path outputDirectory ,
57+ final boolean cleanBeforeRun ,
58+ final boolean cleanOnlyOnce ) {
4059 this .outputDirectory = outputDirectory ;
60+ this .cleanBeforeRun = cleanBeforeRun ;
61+ this .cleanOnlyOnce = cleanOnlyOnce ;
4162 this .mapper = Allure2ModelJackson .createMapper ();
4263 }
4364
@@ -46,7 +67,7 @@ public void write(final TestResult testResult) {
4667 final String testResultName = Objects .isNull (testResult .getUuid ())
4768 ? generateTestResultName ()
4869 : generateTestResultName (testResult .getUuid ());
49- createDirectories ( outputDirectory );
70+ ensureInitialized ( );
5071 final Path file = outputDirectory .resolve (testResultName );
5172 try {
5273 mapper .writeValue (file .toFile (), testResult );
@@ -60,7 +81,7 @@ public void write(final TestResultContainer testResultContainer) {
6081 final String testResultContainerName = Objects .isNull (testResultContainer .getUuid ())
6182 ? generateTestResultContainerName ()
6283 : generateTestResultContainerName (testResultContainer .getUuid ());
63- createDirectories ( outputDirectory );
84+ ensureInitialized ( );
6485 final Path file = outputDirectory .resolve (testResultContainerName );
6586 try {
6687 mapper .writeValue (file .toFile (), testResultContainer );
@@ -71,7 +92,7 @@ public void write(final TestResultContainer testResultContainer) {
7192
7293 @ Override
7394 public void write (final String source , final InputStream attachment ) {
74- createDirectories ( outputDirectory );
95+ ensureInitialized ( );
7596 final Path file = outputDirectory .resolve (source );
7697 try (InputStream is = attachment ) {
7798 Files .copy (is , file );
@@ -88,6 +109,35 @@ private void createDirectories(final Path directory) {
88109 }
89110 }
90111
112+ private void ensureInitialized () {
113+ createDirectories (outputDirectory );
114+ if (cleanBeforeRun ) {
115+ final boolean shouldClean = !cleanOnlyOnce || cleaned .compareAndSet (false , true );
116+ if (shouldClean ) {
117+ cleanDirectoryContents (outputDirectory );
118+ }
119+ }
120+ }
121+
122+ private void cleanDirectoryContents (final Path directory ) {
123+ if (!Files .exists (directory )) {
124+ return ;
125+ }
126+ try (Stream <Path > stream = Files .walk (directory )) {
127+ stream .sorted (Comparator .reverseOrder ())
128+ .filter (path -> !path .equals (directory ))
129+ .forEach (path -> {
130+ try {
131+ Files .deleteIfExists (path );
132+ } catch (IOException e ) {
133+ LOGGER .warn ("Failed to delete {} during directory cleanup" , path , e );
134+ }
135+ });
136+ } catch (IOException e ) {
137+ LOGGER .warn ("Failed to clean directory contents: {}" , directory , e );
138+ }
139+ }
140+
91141 protected static String generateTestResultName () {
92142 return generateTestResultName (UUID .randomUUID ().toString ());
93143 }
0 commit comments