diff --git a/app/src/processing/app/tools/ZipDeflater.java b/app/src/processing/app/tools/ZipDeflater.java index 651ff37ba..6a1cf2c5d 100644 --- a/app/src/processing/app/tools/ZipDeflater.java +++ b/app/src/processing/app/tools/ZipDeflater.java @@ -14,26 +14,30 @@ public class ZipDeflater { private final ZipFile zipFile; private final File destFolder; + private final Random random; + private final File file; public ZipDeflater(File file, File destFolder) throws ZipException, IOException { + this.file = file; this.destFolder = destFolder; this.zipFile = new ZipFile(file); + this.random = new Random(); } public void deflate() throws IOException { - String folderName = tempFolderNameFromZip(); + String tmpFolderName = folderNameFromZip() + random.nextInt(1000000); - File folder = new File(destFolder, folderName); + File tmpFolder = new File(destFolder, tmpFolderName); - if (!folder.mkdir()) { - throw new IOException("Unable to create folder " + folderName); + if (!tmpFolder.mkdir()) { + throw new IOException("Unable to create folder " + tmpFolderName); } Enumeration entries = zipFile.entries(); while (entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); - ensureFoldersOfEntryExist(folder, entry); - File entryFile = new File(folder, entry.getName()); + ensureFoldersOfEntryExist(tmpFolder, entry); + File entryFile = new File(tmpFolder, entry.getName()); if (entry.isDirectory()) { entryFile.mkdir(); } else { @@ -58,8 +62,33 @@ public class ZipDeflater { } } - // Test.zip may or may not contain Test folder. We use zip name to create libraries folder. Therefore, a contained Test folder is useless and must be removed - ensureOneLevelFolder(folder); + deleteUndesiredFoldersAndFiles(tmpFolder); + + // Test.zip may or may not contain Test folder. If it does, we keep it. If not, we use zip name. + ensureOneLevelFolder(tmpFolder); + } + + private void deleteUndesiredFoldersAndFiles(File folder) { + for (File file : folder.listFiles()) { + if (file.isDirectory() && "__MACOSX".equals(file.getName())) { + recursiveDelete(file); + } else if (file.getName().startsWith(".")) { + recursiveDelete(file); + } + } + } + + private void recursiveDelete(File file) { + if (file.isDirectory()) { + for (File current : file.listFiles()) { + if (current.isDirectory()) { + recursiveDelete(current); + } else { + current.delete(); + } + } + } + file.delete(); } private void ensureFoldersOfEntryExist(File folder, ZipEntry entry) { @@ -73,25 +102,22 @@ public class ZipDeflater { private void ensureOneLevelFolder(File folder) { File[] files = folder.listFiles(); - if (files.length == 1 && files[0].isDirectory()) { - File tempFile = new File(files[0].getPath() + new Random().nextInt(1000)); - files[0].renameTo(tempFile); - for (File file : tempFile.listFiles()) { - file.renameTo(new File(folder, file.getName())); - } - tempFile.delete(); + + if (files.length != 1) { + folder.renameTo(new File(folder.getParentFile(), folderNameFromZip())); + return; } + + files[0].renameTo(new File(folder.getParentFile(), files[0].getName())); + recursiveDelete(folder); } - private String tempFolderNameFromZip() { - String folderName = zipFile.getName(); - if (folderName.lastIndexOf(".") != -1) { - folderName = folderName.substring(0, folderName.lastIndexOf(".")); + private String folderNameFromZip() { + String filename = file.getName(); + if (filename.lastIndexOf(".") != -1) { + filename = filename.substring(0, filename.lastIndexOf(".")); } - if (folderName.lastIndexOf(File.separator) != -1) { - folderName = folderName.substring(folderName.lastIndexOf(File.separator) + 1); - } - return folderName; + return filename; } } diff --git a/app/test/Keypad_mac.zip b/app/test/Keypad_mac.zip new file mode 100644 index 000000000..a8046ed02 Binary files /dev/null and b/app/test/Keypad_mac.zip differ diff --git a/app/test/Keypad_with_hidden_files.zip b/app/test/Keypad_with_hidden_files.zip new file mode 100644 index 000000000..71eeb3920 Binary files /dev/null and b/app/test/Keypad_with_hidden_files.zip differ diff --git a/app/test/processing/app/tools/ZipDeflaterTest.java b/app/test/processing/app/tools/ZipDeflaterTest.java index 6a147dd5c..a24688318 100644 --- a/app/test/processing/app/tools/ZipDeflaterTest.java +++ b/app/test/processing/app/tools/ZipDeflaterTest.java @@ -10,8 +10,6 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; -import processing.app.tools.ZipDeflater; - public class ZipDeflaterTest { private File destFolder; @@ -62,6 +60,47 @@ public class ZipDeflaterTest { assertEquals("readme.txt", files[4]); } + @Test + public void shouldDeflateMacZip() throws Exception { + File file = new File(ZipDeflater.class.getResource("/Keypad_mac.zip").getFile()); + new ZipDeflater(file, destFolder).deflate(); + + String[] files = destFolder.list(); + assertEquals(1, files.length); + assertEquals("Keypad", files[0]); + + file = destFolder.listFiles()[0]; + files = file.list(); + assertEquals(4, files.length); + Arrays.sort(files); + assertEquals("Keypad.cpp", files[0]); + assertEquals("Keypad.h", files[1]); + assertEquals("examples", files[2]); + assertEquals("keywords.txt", files[3]); + + files = new File(file, "examples").list(); + assertEquals(4, files.length); + Arrays.sort(files); + assertEquals("CustomKeypad", files[0]); + assertEquals("DynamicKeypad", files[1]); + assertEquals("EventKeypad", files[2]); + assertEquals("HelloKeypad", files[3]); + } + + @Test + public void shouldDeleteHiddenFiles() throws Exception { + File file = new File(ZipDeflater.class.getResource("/Keypad_with_hidden_files.zip").getFile()); + new ZipDeflater(file, destFolder).deflate(); + + String[] files = destFolder.list(); + assertEquals(1, files.length); + assertEquals("Keypad_with_hidden_files", files[0]); + + file = destFolder.listFiles()[0]; + files = file.list(); + assertEquals(4, files.length); + } + @After public void deleteTempFolder() { recursiveDelete(destFolder);