From 378c4392e06b27db124b65aaf6f529610c2c059f Mon Sep 17 00:00:00 2001 From: Federico Fissore Date: Thu, 18 Oct 2012 16:00:02 +0200 Subject: [PATCH] keep included folder name as top level folder name, delete MAC folder and hidden files --- app/src/processing/app/tools/ZipDeflater.java | 72 ++++++++++++------ app/test/Keypad_mac.zip | Bin 0 -> 17267 bytes app/test/Keypad_with_hidden_files.zip | Bin 0 -> 12225 bytes .../processing/app/tools/ZipDeflaterTest.java | 43 ++++++++++- 4 files changed, 90 insertions(+), 25 deletions(-) create mode 100644 app/test/Keypad_mac.zip create mode 100644 app/test/Keypad_with_hidden_files.zip 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 0000000000000000000000000000000000000000..a8046ed028d941bf664b84370ed363920ab6c08f GIT binary patch literal 17267 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 Y3;z8P3#Xds~f157{=JOBUy literal 0 HcmV?d00001 diff --git a/app/test/Keypad_with_hidden_files.zip b/app/test/Keypad_with_hidden_files.zip new file mode 100644 index 0000000000000000000000000000000000000000..71eeb39205d21874f66d4cd1432e9eee506125a1 GIT binary patch literal 12225 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