From 0a5327691e4f18a13ed0735461fac0ca9510f616 Mon Sep 17 00:00:00 2001 From: Reinhard Pointner Date: Wed, 13 Apr 2016 18:41:06 +0000 Subject: [PATCH] + Auto-delete left behind empty folders when moving files into a new structure --- source/net/filebot/media/ReleaseInfo.java | 15 ++-- .../net/filebot/ui/rename/RenameAction.java | 70 +++++++++++++++---- 2 files changed, 66 insertions(+), 19 deletions(-) diff --git a/source/net/filebot/media/ReleaseInfo.java b/source/net/filebot/media/ReleaseInfo.java index cbd3ab19..12281e1e 100644 --- a/source/net/filebot/media/ReleaseInfo.java +++ b/source/net/filebot/media/ReleaseInfo.java @@ -220,17 +220,21 @@ public class ReleaseInfo { if (volumeRoots == null) { Set volumes = new HashSet(); + File userHome = ApplicationFolder.UserHome.get(); + List roots = getFileSystemRoots(); + // user root folder - volumes.add(ApplicationFolder.UserHome.get()); + volumes.add(userHome); + volumes.addAll(getChildren(userHome, FOLDERS)); // Windows / Linux / Mac system roots - volumes.addAll(getFileSystemRoots()); + volumes.addAll(roots); // Linux / Mac if (File.separator.equals("/")) { // Linux and Mac system root folders - for (File userFolder : volumes.toArray(new File[0])) { - volumes.addAll(getChildren(userFolder, FOLDERS)); + for (File root : roots) { + volumes.addAll(getChildren(root, FOLDERS)); } for (File mediaRoot : getMediaRoots()) { @@ -241,12 +245,11 @@ public class ReleaseInfo { // Mac if (isMacSandbox()) { - File realUserHome = ApplicationFolder.UserHome.get(); File sandboxUserHome = new File(System.getProperty("user.home")); // e.g. ignore default Movie folder on Mac for (File userFolder : getChildren(sandboxUserHome, FOLDERS)) { - volumes.add(new File(realUserHome, userFolder.getName())); + volumes.add(new File(userHome, userFolder.getName())); } } diff --git a/source/net/filebot/ui/rename/RenameAction.java b/source/net/filebot/ui/rename/RenameAction.java index dd74cbb4..04bee8ff 100644 --- a/source/net/filebot/ui/rename/RenameAction.java +++ b/source/net/filebot/ui/rename/RenameAction.java @@ -1,9 +1,11 @@ package net.filebot.ui.rename; +import static java.util.Arrays.*; import static java.util.Collections.*; import static javax.swing.JOptionPane.*; import static net.filebot.Logging.*; import static net.filebot.Settings.*; +import static net.filebot.media.MediaDetection.*; import static net.filebot.media.XattrMetaInfo.*; import static net.filebot.util.ExceptionUtilities.*; import static net.filebot.util.FileUtilities.*; @@ -16,12 +18,14 @@ import java.awt.event.ActionEvent; import java.beans.PropertyChangeEvent; import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.util.AbstractList; import java.util.AbstractMap.SimpleEntry; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -116,18 +120,12 @@ class RenameAction extends AbstractAction { } } - // write metadata into xattr if xattr is enabled - if (useExtendedFileAttributes() || useCreationDate()) { - for (Match match : matches) { - File file = match.getCandidate(); - Object meta = match.getValue(); - if (renameMap.containsKey(file) && meta != null) { - File destination = resolve(file, renameMap.get(file)); - if (destination.isFile()) { - xattr.setMetaInfo(destination, meta, file.getName()); - } - } - } + // store xattr + storeMetaInfo(renameMap, matches); + + // delete empty folders + if (action == StandardRenameAction.MOVE) { + deleteEmptyFolders(renameMap); } } catch (ExecutionException e) { // ignore, handled in rename worker @@ -138,6 +136,52 @@ class RenameAction extends AbstractAction { window.setCursor(Cursor.getDefaultCursor()); } + private void storeMetaInfo(Map renameMap, List> matches) { + // write metadata into xattr if xattr is enabled + for (Match match : matches) { + File file = match.getCandidate(); + Object meta = match.getValue(); + if (renameMap.containsKey(file) && meta != null) { + File destination = resolve(file, renameMap.get(file)); + if (destination.isFile()) { + xattr.setMetaInfo(destination, meta, file.getName()); + } + } + } + } + + private void deleteEmptyFolders(Map renameMap) { + // collect newly empty folders + Set deleteSet = new LinkedHashSet(); + + renameMap.forEach((s, d) -> { + File sourceFolder = s.getParentFile(); + File destinationFolder = resolve(s, d).getParentFile(); + + if (!destinationFolder.getPath().startsWith(sourceFolder.getPath())) { + int relativePathSize = listPath(d).size() - 1; + for (int i = 0; i < relativePathSize && sourceFolder != null && !isVolumeRoot(sourceFolder); sourceFolder = sourceFolder.getParentFile(), i++) { + File[] children = sourceFolder.listFiles(); + if (children == null || !stream(children).allMatch(f -> f.isHidden() || deleteSet.contains(f))) { + return; + } + + stream(children).forEach(deleteSet::add); + deleteSet.add(sourceFolder); + } + } + }); + + for (File f : deleteSet) { + try { + debug.finest(format("Delete empty folder: %s", f)); + Files.delete(f.toPath()); + } catch (Exception e) { + debug.warning(e::toString); + } + } + } + public boolean isNativeActionSupported(StandardRenameAction action) { try { return NativeRenameAction.isSupported() && NativeRenameAction.valueOf(action.name()) != null; @@ -337,7 +381,7 @@ class RenameAction extends AbstractAction { } // collect renamed types - final List> types = new ArrayList>(); + List> types = new ArrayList>(); // remove renamed matches for (File source : renameLog.keySet()) {