filebot/source/net/filebot/StandardRenameAction.java

228 lines
5.5 KiB
Java
Raw Normal View History

2014-04-19 02:30:29 -04:00
package net.filebot;
2016-07-31 01:36:07 -04:00
import static net.filebot.Logging.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
2016-03-10 11:23:45 -05:00
import java.nio.file.LinkOption;
import java.nio.file.attribute.BasicFileAttributes;
2016-07-31 01:36:07 -04:00
import com.apple.eio.FileManager;
import com.sun.jna.Platform;
import com.sun.jna.platform.FileUtils;
2014-04-19 02:30:29 -04:00
import net.filebot.util.FileUtilities;
public enum StandardRenameAction implements RenameAction {
MOVE {
@Override
public File rename(File from, File to) throws Exception {
return FileUtilities.moveRename(from, to);
}
},
COPY {
@Override
public File rename(File from, File to) throws Exception {
return FileUtilities.copyAs(from, to);
}
},
KEEPLINK {
@Override
public File rename(File from, File to) throws Exception {
2016-08-01 02:02:26 -04:00
File dest = FileUtilities.resolveDestination(from, to);
// move file and the create a symlink to the new location via NIO.2
try {
2016-08-01 02:02:26 -04:00
Files.move(from.toPath(), dest.toPath());
FileUtilities.createRelativeSymlink(from, dest, true);
} catch (LinkageError e) {
throw new Exception("Unsupported Operation: move, createSymbolicLink");
}
2016-08-01 02:02:26 -04:00
return dest;
}
},
SYMLINK {
@Override
public File rename(File from, File to) throws Exception {
2016-08-01 02:02:26 -04:00
File dest = FileUtilities.resolveDestination(from, to);
// create symlink via NIO.2
try {
2016-08-01 02:02:26 -04:00
return FileUtilities.createRelativeSymlink(dest, from, true);
} catch (LinkageError e) {
throw new Exception("Unsupported Operation: createSymbolicLink");
}
}
},
HARDLINK {
@Override
public File rename(File from, File to) throws Exception {
2016-08-01 02:02:26 -04:00
File dest = FileUtilities.resolveDestination(from, to);
// create hardlink via NIO.2
try {
2016-08-01 02:02:26 -04:00
return FileUtilities.createHardLinkStructure(dest, from);
} catch (LinkageError e) {
throw new Exception("Unsupported Operation: createLink");
}
}
},
DUPLICATE {
2014-08-10 03:11:09 -04:00
@Override
public File rename(File from, File to) throws Exception {
try {
return HARDLINK.rename(from, to);
} catch (Exception e) {
return COPY.rename(from, to);
}
}
},
2016-08-01 02:02:26 -04:00
REFLINK {
@Override
public File rename(File from, File to) throws Exception {
File dest = FileUtilities.resolveDestination(from, to);
// reflink requires Linux and a filesystem that supports copy-on-write (e.g. btrfs)
ProcessBuilder process = new ProcessBuilder("cp", "--reflink", "--force", from.isDirectory() ? "--recursive" : "--no-target-directory", from.getPath(), dest.getPath());
process.directory(from.getParentFile());
process.inheritIO();
int exitCode = process.start().waitFor();
if (exitCode != 0) {
throw new IOException(String.format("reflink: %s failed with exit code %d", process.command(), exitCode));
}
return dest;
}
},
RENAME {
@Override
2014-08-10 03:11:09 -04:00
public File rename(File from, File to) throws Exception {
// rename only the filename
File dest = new File(from.getParentFile(), to.getName());
2016-08-01 02:02:26 -04:00
if (!from.renameTo(dest)) {
throw new IOException("Failed to rename " + from + " to " + dest);
}
return dest;
}
},
TEST {
@Override
public File rename(File from, File to) throws IOException {
2016-04-13 07:22:03 -04:00
return FileUtilities.resolve(from, to);
}
};
public String getDisplayName() {
switch (this) {
case MOVE:
return "Rename";
case COPY:
return "Copy";
case KEEPLINK:
return "Keeplink";
case SYMLINK:
return "Symlink";
case HARDLINK:
return "Hardlink";
default:
return null;
}
}
public static StandardRenameAction forName(String action) {
for (StandardRenameAction it : values()) {
if (it.name().equalsIgnoreCase(action))
return it;
}
throw new IllegalArgumentException("Illegal rename action: " + action);
}
2016-03-10 11:23:45 -05:00
public static File revert(File current, File original) throws IOException {
// do nothing if current and original path is exactly the same
if (current.equals(original)) {
return original;
}
2016-03-10 11:23:45 -05:00
// reverse move
if (current.exists() && !original.exists()) {
return FileUtilities.moveRename(current, original);
}
BasicFileAttributes currentAttr = Files.readAttributes(current.toPath(), BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
BasicFileAttributes originalAttr = Files.readAttributes(original.toPath(), BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
// reverse symlink
if (currentAttr.isSymbolicLink() && !originalAttr.isSymbolicLink()) {
2016-07-31 01:36:07 -04:00
trash(current);
2016-03-10 11:23:45 -05:00
return original;
}
// reverse keeplink
if (!currentAttr.isSymbolicLink() && originalAttr.isSymbolicLink()) {
2016-07-31 01:36:07 -04:00
trash(original);
2016-03-10 11:23:45 -05:00
return FileUtilities.moveRename(current, original);
}
// reverse copy / hardlink
if (currentAttr.isRegularFile() && originalAttr.isRegularFile()) {
2016-07-31 01:36:07 -04:00
trash(current);
2016-03-10 11:23:45 -05:00
return original;
}
// reverse folder copy
if (currentAttr.isDirectory() && originalAttr.isDirectory()) {
2016-07-31 01:36:07 -04:00
trash(original);
2016-03-10 11:23:45 -05:00
return FileUtilities.moveRename(current, original);
}
2016-05-15 15:09:30 -04:00
throw new IllegalArgumentException(String.format("Cannot revert file: %s => %s", current, original));
2016-03-10 11:23:45 -05:00
}
2016-07-31 01:36:07 -04:00
public static void trash(File file) throws IOException {
// use system trash if possible
try {
if (Platform.isMac()) {
// use com.apple.eio package on OS X platform
if (FileManager.moveToTrash(file)) {
return;
}
} else if (FileUtils.getInstance().hasTrash()) {
// use com.sun.jna.platform package on Windows and Linux
FileUtils.getInstance().moveToTrash(new File[] { file });
return;
}
} catch (Exception e) {
debug.warning(e::toString);
}
// delete permanently if necessary
if (file.exists()) {
FileUtilities.delete(file);
}
}
}