From 3465fcf97b653ecf249c858786c34fc5ba73caf4 Mon Sep 17 00:00:00 2001 From: Federico Fissore Date: Wed, 15 Apr 2015 10:19:39 +0200 Subject: [PATCH 1/3] File.deleteOnExit is not recursive. Replaced by DeleteFilesOnShutdown shutdown hook. Fixes #2971 --- app/src/processing/app/Base.java | 5 ++- .../processing/app/EditorConsoleStream.java | 8 ++-- app/test/processing/app/AbstractGUITest.java | 3 +- .../app/AbstractWithPreferencesTest.java | 8 +++- .../arduino/files/DeleteFilesOnShutdown.java | 42 +++++++++++++++++++ .../src/processing/app/BaseNoGui.java | 6 ++- 6 files changed, 64 insertions(+), 8 deletions(-) create mode 100644 arduino-core/src/cc/arduino/files/DeleteFilesOnShutdown.java diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index f59a1dfa8..9b5a01bfd 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -32,6 +32,7 @@ import cc.arduino.contributions.packages.ContributionInstaller; import cc.arduino.contributions.packages.ContributionsIndexer; import cc.arduino.contributions.DownloadableContributionVersionComparator; import cc.arduino.contributions.packages.ui.ContributionManagerUI; +import cc.arduino.files.DeleteFilesOnShutdown; import cc.arduino.packages.DiscoveryManager; import cc.arduino.utils.Progress; import cc.arduino.view.SplashScreenHelper; @@ -127,6 +128,8 @@ public class Base { } static public void guardedMain(String args[]) throws Exception { + Runtime.getRuntime().addShutdownHook(new Thread(DeleteFilesOnShutdown.INSTANCE)); + BaseNoGui.initLogger(); BaseNoGui.notifier = new GUIUserNotifier(); @@ -202,7 +205,7 @@ public class Base { // Create a location for untitled sketches untitledFolder = createTempFolder("untitled"); - untitledFolder.deleteOnExit(); + DeleteFilesOnShutdown.add(untitledFolder); new Base(args); } diff --git a/app/src/processing/app/EditorConsoleStream.java b/app/src/processing/app/EditorConsoleStream.java index 06e232673..cfe78fd66 100644 --- a/app/src/processing/app/EditorConsoleStream.java +++ b/app/src/processing/app/EditorConsoleStream.java @@ -1,5 +1,7 @@ package processing.app; +import cc.arduino.files.DeleteFilesOnShutdown; + import static processing.app.I18n._; import java.io.File; @@ -33,19 +35,19 @@ class EditorConsoleStream extends OutputStream { // The files and folders are not deleted on exit because they may be // needed for debugging or bug reporting. tempFolder = Base.createTempFolder("console"); - tempFolder.deleteOnExit(); + DeleteFilesOnShutdown.add(tempFolder); try { String outFileName = Preferences.get("console.output.file"); if (outFileName != null) { outFile = new File(tempFolder, outFileName); - outFile.deleteOnExit(); + DeleteFilesOnShutdown.add(outFile); stdoutFile = new FileOutputStream(outFile); } String errFileName = Preferences.get("console.error.file"); if (errFileName != null) { errFile = new File(tempFolder, errFileName); - errFile.deleteOnExit(); + DeleteFilesOnShutdown.add(errFile); stderrFile = new FileOutputStream(errFile); } } catch (IOException e) { diff --git a/app/test/processing/app/AbstractGUITest.java b/app/test/processing/app/AbstractGUITest.java index 1568db5d1..6532fd3d7 100644 --- a/app/test/processing/app/AbstractGUITest.java +++ b/app/test/processing/app/AbstractGUITest.java @@ -6,6 +6,7 @@ import org.fest.swing.edt.GuiQuery; import org.junit.After; import org.junit.Before; import processing.app.helpers.ArduinoFrameFixture; +import processing.app.helpers.FileUtils; import javax.swing.*; @@ -25,7 +26,6 @@ public abstract class AbstractGUITest { Theme.init(); Base.getPlatform().setLookAndFeel(); Base.untitledFolder = Base.createTempFolder("untitled"); - Base.untitledFolder.deleteOnExit(); window = GuiActionRunner.execute(new GuiQuery() { @Override @@ -38,6 +38,7 @@ public abstract class AbstractGUITest { @After public void stopTheIDE() { window.cleanUp(); + FileUtils.recursiveDelete(Base.untitledFolder); } } diff --git a/app/test/processing/app/AbstractWithPreferencesTest.java b/app/test/processing/app/AbstractWithPreferencesTest.java index ca07ec385..73a41b059 100644 --- a/app/test/processing/app/AbstractWithPreferencesTest.java +++ b/app/test/processing/app/AbstractWithPreferencesTest.java @@ -1,6 +1,8 @@ package processing.app; +import org.junit.After; import org.junit.Before; +import processing.app.helpers.FileUtils; public abstract class AbstractWithPreferencesTest { @@ -11,7 +13,11 @@ public abstract class AbstractWithPreferencesTest { Theme.init(); Base.untitledFolder = Base.createTempFolder("untitled"); - Base.untitledFolder.deleteOnExit(); } + + @After + public void cleanup() { + FileUtils.recursiveDelete(Base.untitledFolder); + } } diff --git a/arduino-core/src/cc/arduino/files/DeleteFilesOnShutdown.java b/arduino-core/src/cc/arduino/files/DeleteFilesOnShutdown.java new file mode 100644 index 000000000..db3a4f395 --- /dev/null +++ b/arduino-core/src/cc/arduino/files/DeleteFilesOnShutdown.java @@ -0,0 +1,42 @@ +package cc.arduino.files; + +import processing.app.helpers.FileUtils; + +import java.io.File; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +public class DeleteFilesOnShutdown implements Runnable { + + public static final DeleteFilesOnShutdown INSTANCE = new DeleteFilesOnShutdown(); + + public static void add(File file) { + INSTANCE.addFile(file); + } + + private final List files; + + public DeleteFilesOnShutdown() { + this.files = new LinkedList(); + } + + public synchronized void addFile(File file) { + this.files.add(file); + } + + @Override + public void run() { + List copyOfFiles; + synchronized (this) { + copyOfFiles = new LinkedList(files); + } + Collections.reverse(copyOfFiles); + for (File file : copyOfFiles) { + if (file.exists() && file.canWrite()) { + FileUtils.recursiveDelete(file); + } + } + } + +} diff --git a/arduino-core/src/processing/app/BaseNoGui.java b/arduino-core/src/processing/app/BaseNoGui.java index aaa7eaa0e..e7a08c261 100644 --- a/arduino-core/src/processing/app/BaseNoGui.java +++ b/arduino-core/src/processing/app/BaseNoGui.java @@ -1,11 +1,11 @@ package processing.app; import cc.arduino.contributions.libraries.LibrariesIndexer; +import cc.arduino.files.DeleteFilesOnShutdown; import cc.arduino.packages.DiscoveryManager; import cc.arduino.packages.Uploader; import cc.arduino.contributions.packages.ContributedTool; import cc.arduino.contributions.packages.ContributionsIndexer; -import cc.arduino.utils.ArchiveExtractor; import org.apache.commons.logging.impl.LogFactoryImpl; import org.apache.commons.logging.impl.NoOpLog; import processing.app.debug.Compiler; @@ -133,7 +133,7 @@ public class BaseNoGui { //File folder = new File(getTempFolder(), "build"); //if (!folder.exists()) folder.mkdirs(); buildFolder = createTempFolder("build"); - buildFolder.deleteOnExit(); + DeleteFilesOnShutdown.add(buildFolder); } } return buildFolder; @@ -703,6 +703,8 @@ public class BaseNoGui { if (args.length == 0) showError(_("No parameters"), _("No command line parameters found"), null); + Runtime.getRuntime().addShutdownHook(new Thread(DeleteFilesOnShutdown.INSTANCE)); + initPlatform(); initPortableFolder(); From 96c45769624b9bae3a379e2525aa13caeac5b7b0 Mon Sep 17 00:00:00 2001 From: Federico Fissore Date: Wed, 15 Apr 2015 11:00:01 +0200 Subject: [PATCH 2/3] Added --preserve-temp-files command line option --- app/src/processing/app/Base.java | 1 + .../src/cc/arduino/files/DeleteFilesOnShutdown.java | 5 +++++ .../src/processing/app/helpers/CommandlineParser.java | 11 +++++++++++ build/shared/manpage.adoc | 6 +++++- 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 9b5a01bfd..6b74e80ad 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -404,6 +404,7 @@ public class Base { // Set verbosity for command line build Preferences.set("build.verbose", "" + parser.isDoVerboseBuild()); Preferences.set("upload.verbose", "" + parser.isDoVerboseUpload()); + Preferences.set("runtime.preserve.temp.files", Boolean.toString(parser.isPreserveTempFiles())); // Make sure these verbosity preferences are only for the // current session diff --git a/arduino-core/src/cc/arduino/files/DeleteFilesOnShutdown.java b/arduino-core/src/cc/arduino/files/DeleteFilesOnShutdown.java index db3a4f395..7d9f60139 100644 --- a/arduino-core/src/cc/arduino/files/DeleteFilesOnShutdown.java +++ b/arduino-core/src/cc/arduino/files/DeleteFilesOnShutdown.java @@ -1,5 +1,6 @@ package cc.arduino.files; +import processing.app.PreferencesData; import processing.app.helpers.FileUtils; import java.io.File; @@ -27,6 +28,10 @@ public class DeleteFilesOnShutdown implements Runnable { @Override public void run() { + boolean preserveTempFiles = PreferencesData.getBoolean("runtime.preserve.temp.files"); + if (preserveTempFiles) { + return; + } List copyOfFiles; synchronized (this) { copyOfFiles = new LinkedList(files); diff --git a/arduino-core/src/processing/app/helpers/CommandlineParser.java b/arduino-core/src/processing/app/helpers/CommandlineParser.java index d0e314bcd..2e66e6361 100644 --- a/arduino-core/src/processing/app/helpers/CommandlineParser.java +++ b/arduino-core/src/processing/app/helpers/CommandlineParser.java @@ -36,6 +36,7 @@ public class CommandlineParser { private boolean doVerboseBuild = false; private boolean doVerboseUpload = false; private boolean doUseProgrammer = false; + private boolean preserveTempFiles; private boolean noUploadPort = false; private boolean forceSavePrefs = false; private String getPref; @@ -105,6 +106,12 @@ public class CommandlineParser { action = ACTION.NOOP; continue; } + if (args[i].equals("--preserve-temp-files")) { + preserveTempFiles = true; + if (action == ACTION.GUI) + action = ACTION.NOOP; + continue; + } if (args[i].equals("--verbose-build")) { doVerboseBuild = true; if (action == ACTION.GUI) @@ -330,4 +337,8 @@ public class CommandlineParser { public String getLibraryToInstall() { return libraryToInstall; } + + public boolean isPreserveTempFiles() { + return preserveTempFiles; + } } diff --git a/build/shared/manpage.adoc b/build/shared/manpage.adoc index 4572c5480..5c17d1521 100644 --- a/build/shared/manpage.adoc +++ b/build/shared/manpage.adoc @@ -25,7 +25,7 @@ SYNOPSIS -------- *arduino* ['FILE.ino'...] -*arduino* [*--verify*|*--upload*] [*--board* __package__:__arch__:__board__[:__parameters__]] [*--port* __portname__] [*--pref* __name__=__value__] [*-v*|*--verbose*] [__FILE.ino__] +*arduino* [*--verify*|*--upload*] [*--board* __package__:__arch__:__board__[:__parameters__]] [*--port* __portname__] [*--pref* __name__=__value__] [*-v*|*--verbose*] [--preserve-temp-files] [__FILE.ino__] *arduino* [*--get-pref* __preference__] @@ -117,6 +117,10 @@ OPTIONS verbose mode during build is *disabled* regardless of the current preferences. +*--preserve-temp-files*:: + Keep temporary files (preprocessed sketch, object files...) after termination. + If omitted, temporary files are deleted. + {empty}:: This option is only valid together with *--verify* or *--upload*. From dabd6e49036d6ae7692a143540f17e3b0fe97f57 Mon Sep 17 00:00:00 2001 From: Federico Fissore Date: Wed, 15 Apr 2015 11:00:23 +0200 Subject: [PATCH 3/3] Tests weren't deleting temporary files: fixed --- app/test/processing/app/AbstractGUITest.java | 5 +++-- .../processing/app/AbstractWithPreferencesTest.java | 10 +++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/app/test/processing/app/AbstractGUITest.java b/app/test/processing/app/AbstractGUITest.java index 6532fd3d7..60e702bce 100644 --- a/app/test/processing/app/AbstractGUITest.java +++ b/app/test/processing/app/AbstractGUITest.java @@ -1,12 +1,12 @@ package processing.app; +import cc.arduino.files.DeleteFilesOnShutdown; import org.fest.swing.edt.FailOnThreadViolationRepaintManager; import org.fest.swing.edt.GuiActionRunner; import org.fest.swing.edt.GuiQuery; import org.junit.After; import org.junit.Before; import processing.app.helpers.ArduinoFrameFixture; -import processing.app.helpers.FileUtils; import javax.swing.*; @@ -17,6 +17,7 @@ public abstract class AbstractGUITest { @Before public void startUpTheIDE() throws Exception { System.setProperty("mrj.version", "whynot"); //makes sense only on osx. See https://github.com/alexruiz/fest-swing-1.x/issues/2#issuecomment-86532042 + Runtime.getRuntime().addShutdownHook(new Thread(DeleteFilesOnShutdown.INSTANCE)); FailOnThreadViolationRepaintManager.install(); @@ -26,6 +27,7 @@ public abstract class AbstractGUITest { Theme.init(); Base.getPlatform().setLookAndFeel(); Base.untitledFolder = Base.createTempFolder("untitled"); + DeleteFilesOnShutdown.add(Base.untitledFolder); window = GuiActionRunner.execute(new GuiQuery() { @Override @@ -38,7 +40,6 @@ public abstract class AbstractGUITest { @After public void stopTheIDE() { window.cleanUp(); - FileUtils.recursiveDelete(Base.untitledFolder); } } diff --git a/app/test/processing/app/AbstractWithPreferencesTest.java b/app/test/processing/app/AbstractWithPreferencesTest.java index 73a41b059..cabf9ec11 100644 --- a/app/test/processing/app/AbstractWithPreferencesTest.java +++ b/app/test/processing/app/AbstractWithPreferencesTest.java @@ -1,23 +1,19 @@ package processing.app; -import org.junit.After; +import cc.arduino.files.DeleteFilesOnShutdown; import org.junit.Before; -import processing.app.helpers.FileUtils; public abstract class AbstractWithPreferencesTest { @Before public void init() throws Exception { + Runtime.getRuntime().addShutdownHook(new Thread(DeleteFilesOnShutdown.INSTANCE)); Base.initPlatform(); Preferences.init(null); Theme.init(); Base.untitledFolder = Base.createTempFolder("untitled"); - + DeleteFilesOnShutdown.add(Base.untitledFolder); } - @After - public void cleanup() { - FileUtils.recursiveDelete(Base.untitledFolder); - } }