@@ -65,8 +65,7 @@ public static IdeaStepBuilder create(@Nonnull File buildDir) {
6565 private static FormatterStep create (@ Nonnull IdeaStepBuilder builder ) {
6666 Objects .requireNonNull (builder );
6767 return FormatterStep .createLazy (NAME ,
68- () -> createState (builder ),
69- state -> state );
68+ () -> createState (builder ), State ::toFunc );
7069 }
7170
7271 private static State createState (@ Nonnull IdeaStepBuilder builder ) {
@@ -117,22 +116,19 @@ public FormatterStep build() {
117116 }
118117 }
119118
120- private static class State
121- implements FormatterFunc .NeedsFile , Serializable {
119+ private static class State implements Serializable {
122120
123- private static final long serialVersionUID = -1825662355363926318L ;
121+ private static final long serialVersionUID = -1426311255869303398L ;
124122
125- private final String buildDir ;
126- private final String uniquePath ;
123+ private final File uniqueBuildFolder ;
127124 private final String binaryPath ;
128125 @ Nullable
129- private final String codeStyleSettingsPath ; // TODO make sure to save content in state
126+ private final String codeStyleSettingsPath ;
130127 private final boolean withDefaults ;
131128 private final TreeMap <String , String > ideaProperties ;
132129
133130 private State (@ Nonnull IdeaStepBuilder builder ) {
134- this .buildDir = ThrowingEx .get (builder .buildDir ::getCanonicalPath );
135- this .uniquePath = UUID .randomUUID ().toString ();
131+ this .uniqueBuildFolder = new File (builder .buildDir , UUID .randomUUID ().toString ());
136132 this .withDefaults = builder .useDefaults ;
137133 this .codeStyleSettingsPath = builder .codeStyleSettingsPath ;
138134 this .ideaProperties = new TreeMap <>(builder .ideaProperties );
@@ -174,7 +170,6 @@ private static String pathToExe(String binaryPath) {
174170 return null ; // search in PATH
175171 }
176172
177- @ CheckForNull
178173 private static String macOsFix (String binaryPath ) {
179174
180175 // on macOS, the binary is located in the .app bundle which might be invisible to the user
@@ -200,22 +195,18 @@ private static boolean isMacOs() {
200195 return System .getProperty ("os.name" ).toLowerCase ().contains ("mac" );
201196 }
202197
203- @ Override
204- public String applyWithFile (String unix , File file ) throws Exception {
198+ private String format (IdeaStepFormatterCleanupResources ideaStepFormatterCleanupResources , String unix , File file ) throws Exception {
205199 // since we cannot directly work with the file, we need to write the unix string to a temporary file
206200 File tempFile = File .createTempFile ("spotless" , file .getName ());
207201 try {
208202 Files .write (tempFile .toPath (), unix .getBytes (StandardCharsets .UTF_8 ));
209203 List <String > params = getParams (tempFile );
210204
211- try (ProcessRunner runner = new ProcessRunner ()) {
212- Map <String , String > env = createEnv ();
213- var result = runner .exec (null , env , null , params );
214- LOGGER .debug ("command finished with stdout: {}" ,
215- result .assertExitZero (StandardCharsets .UTF_8 ));
216-
217- return Files .readString (tempFile .toPath (), StandardCharsets .UTF_8 );
218- }
205+ Map <String , String > env = createEnv ();
206+ var result = ideaStepFormatterCleanupResources .runner .exec (null , env , null , params );
207+ LOGGER .debug ("command finished with stdout: {}" ,
208+ result .assertExitZero (StandardCharsets .UTF_8 ));
209+ return Files .readString (tempFile .toPath (), StandardCharsets .UTF_8 );
219210 } finally {
220211 Files .delete (tempFile .toPath ());
221212 }
@@ -229,7 +220,7 @@ private Map<String, String> createEnv() {
229220 }
230221
231222 private File createIdeaPropertiesFile () {
232- Path ideaProps = new File ( buildDir ). toPath (). resolve ( uniquePath ).resolve ("idea.properties" );
223+ Path ideaProps = this . uniqueBuildFolder . toPath ().resolve ("idea.properties" );
233224
234225 if (Files .exists (ideaProps )) {
235226 return ideaProps .toFile (); // only create if it does not exist
@@ -269,5 +260,43 @@ private List<String> getParams(File file) {
269260 builder .add (ThrowingEx .get (file ::getCanonicalPath ));
270261 return builder .build ().collect (Collectors .toList ());
271262 }
263+
264+ private FormatterFunc .Closeable toFunc () {
265+ IdeaStepFormatterCleanupResources ideaStepFormatterCleanupResources = new IdeaStepFormatterCleanupResources (uniqueBuildFolder , new ProcessRunner ());
266+ return FormatterFunc .Closeable .of (ideaStepFormatterCleanupResources , this ::format );
267+ }
268+ }
269+
270+ private static class IdeaStepFormatterCleanupResources implements AutoCloseable {
271+ @ Nonnull
272+ private final File uniqueBuildFolder ;
273+ @ Nonnull
274+ private final ProcessRunner runner ;
275+
276+ public IdeaStepFormatterCleanupResources (@ Nonnull File uniqueBuildFolder , @ Nonnull ProcessRunner runner ) {
277+ this .uniqueBuildFolder = uniqueBuildFolder ;
278+ this .runner = runner ;
279+ }
280+
281+ @ Override
282+ public void close () throws Exception {
283+ // close the runner
284+ runner .close ();
285+ // delete the unique build folder
286+ if (uniqueBuildFolder .exists ()) {
287+ // delete the unique build folder recursively
288+ try (Stream <Path > paths = Files .walk (uniqueBuildFolder .toPath ())) {
289+ paths .sorted ((o1 , o2 ) -> o2 .compareTo (o1 )) // delete files first
290+ .forEach (path -> {
291+ try {
292+ Files .delete (path );
293+ } catch (IOException e ) {
294+ LOGGER .warn ("Failed to delete file: {}" , path , e );
295+ }
296+ });
297+ }
298+ }
299+ }
300+
272301 }
273302}
0 commit comments