diff --git a/src/main/java/org/qortal/arbitrary/ArbitraryDataFile.java b/src/main/java/org/qortal/arbitrary/ArbitraryDataFile.java index 75417546..ecc3e147 100644 --- a/src/main/java/org/qortal/arbitrary/ArbitraryDataFile.java +++ b/src/main/java/org/qortal/arbitrary/ArbitraryDataFile.java @@ -112,11 +112,17 @@ public class ArbitraryDataFile { byte[] digest = Crypto.digest(fileContent); ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromHash(digest); - // Copy file to base directory if needed + // Copy file to data directory if needed Path filePath = Paths.get(path); if (Files.exists(filePath) && !arbitraryDataFile.isInBaseDirectory(path)) { arbitraryDataFile.copyToDataDirectory(filePath); } + // Or, if it's already in the data directory, we may need to move it + else if (!filePath.equals(arbitraryDataFile.getFilePath())) { + // Wrong path, so relocate + Path dest = Paths.get(arbitraryDataFile.getFilePath()); + FilesystemUtils.moveFile(filePath, dest, true); + } return arbitraryDataFile; } catch (IOException e) { diff --git a/src/main/java/org/qortal/utils/FilesystemUtils.java b/src/main/java/org/qortal/utils/FilesystemUtils.java index 54054c2d..0325cb60 100644 --- a/src/main/java/org/qortal/utils/FilesystemUtils.java +++ b/src/main/java/org/qortal/utils/FilesystemUtils.java @@ -1,7 +1,9 @@ package org.qortal.utils; +import org.apache.commons.io.FileUtils; import org.qortal.settings.Settings; +import java.io.File; import java.io.IOException; import java.nio.file.*; @@ -30,6 +32,107 @@ public class FilesystemUtils { }); } + + /** + * moveFile + * Allows files to be moved between filesystems + * + * @param source + * @param dest + * @param cleanup + * @throws IOException + */ + public static void moveFile(Path source, Path dest, boolean cleanup) throws IOException { + if (source.compareTo(dest) == 0) { + // Source path matches destination path already + return; + } + + File sourceFile = new File(source.toString()); + File destFile = new File(dest.toString()); + if (sourceFile == null || !sourceFile.exists()) { + throw new IOException("Source file doesn't exist"); + } + if (!sourceFile.isFile()) { + throw new IOException("Source isn't a file"); + } + + // Ensure parent folders exist in the destination + File destParentFile = destFile.getParentFile(); + if (destParentFile != null) { + destParentFile.mkdirs(); + } + if (destParentFile == null || !destParentFile.exists()) { + throw new IOException("Destination directory doesn't exist"); + } + + // Copy to destination + Files.copy(source, dest, StandardCopyOption.REPLACE_EXISTING); + + // Delete existing + if (FilesystemUtils.pathInsideDataOrTempPath(source)) { + System.out.println(String.format("Deleting file %s", source.toString())); + Files.delete(source); + } + + if (cleanup) { + // ... and delete its parent directory if empty + Path parentDirectory = source.getParent(); + if (FilesystemUtils.pathInsideDataOrTempPath(parentDirectory)) { + Files.deleteIfExists(parentDirectory); + } + } + } + + /** + * moveDirectory + * Allows directories to be moved between filesystems + * + * @param source + * @param dest + * @param cleanup + * @throws IOException + */ + public static void moveDirectory(Path source, Path dest, boolean cleanup) throws IOException { + if (source.compareTo(dest) == 0) { + // Source path matches destination path already + return; + } + + File sourceFile = new File(source.toString()); + File destFile = new File(dest.toString()); + if (sourceFile == null || !sourceFile.exists()) { + throw new IOException("Source directory doesn't exist"); + } + if (!sourceFile.isDirectory()) { + throw new IOException("Source isn't a directory"); + } + + // Ensure parent folders exist in the destination + destFile.mkdirs(); + if (destFile == null || !destFile.exists()) { + throw new IOException("Destination directory doesn't exist"); + } + + // Copy to destination + FilesystemUtils.copyAndReplaceDirectory(source.toString(), dest.toString()); + + // Delete existing + if (FilesystemUtils.pathInsideDataOrTempPath(source)) { + File directory = new File(source.toString()); + System.out.println(String.format("Deleting directory %s", directory.toString())); + FileUtils.deleteDirectory(directory); + } + + if (cleanup) { + // ... and delete its parent directory if empty + Path parentDirectory = source.getParent(); + if (FilesystemUtils.pathInsideDataOrTempPath(parentDirectory)) { + Files.deleteIfExists(parentDirectory); + } + } + } + public static boolean pathInsideDataOrTempPath(Path path) { if (path == null) { return false;