diff --git a/src/main/java/cz/kamma/kfmanager/service/FileOperations.java b/src/main/java/cz/kamma/kfmanager/service/FileOperations.java index 5f9d29d..f41a42a 100644 --- a/src/main/java/cz/kamma/kfmanager/service/FileOperations.java +++ b/src/main/java/cz/kamma/kfmanager/service/FileOperations.java @@ -138,7 +138,11 @@ public class FileOperations { callback.onProgress(currentItem[0], totalItems, source.getFileName().toString()); callback.onFileProgress(fileSize, fileSize); } - Files.setLastModifiedTime(target, Files.getLastModifiedTime(source)); + try { + Files.setLastModifiedTime(target, Files.getLastModifiedTime(source)); + } catch (IOException e) { + // Ignore failure to set time on some filesystems (like network mounts) + } } private static void copySymlink(Path source, Path target, long totalItems, long[] currentItem, ProgressCallback callback) throws IOException { @@ -289,27 +293,36 @@ public class FileOperations { } } - if (callback != null) { - // For move, we report the start of moving the item. - // Note: if it's a directory, this counts as multiple items in totalItems, - // but Files.move will do it in one go. We increment currentItem by the actual count. - long itemCount = countItems(source.toPath()); - currentItem[0] += itemCount; - callback.onProgress(currentItem[0], totalItems, source.getName()); - } - + long itemCount = countItems(source.toPath()); while (true) { try { Files.move(source.toPath(), target.toPath(), StandardCopyOption.REPLACE_EXISTING); + currentItem[0] += itemCount; + if (callback != null) { + callback.onProgress(currentItem[0], totalItems, source.getName()); + } break; } catch (IOException e) { - if (callback != null) { - ErrorResponse res = callback.onError(source, e); - if (res == ErrorResponse.ABORT) throw e; - if (res == ErrorResponse.RETRY) continue; + // Fallback for cross-device moves (e.g., to network/Samba mounts) + try { + if (source.isDirectory()) { + copyDirectory(source.toPath(), target.toPath(), totalItems, currentItem, callback, globalResponse); + currentItem[0]++; // For the directory itself which copyDirectory skips + deleteDirectoryInternal(source.toPath()); + } else { + copyFileWithProgress(source.toPath(), target.toPath(), totalItems, currentItem, callback); + Files.delete(source.toPath()); + } break; - } else { - throw e; + } catch (IOException ex) { + if (callback != null) { + ErrorResponse res = callback.onError(source, ex); + if (res == ErrorResponse.ABORT) throw ex; + if (res == ErrorResponse.RETRY) continue; + break; + } else { + throw ex; + } } } }