Browse Source

Use NIO2 to implement FileUtils.rename() and expose options

- use NIO2's Files.move() to reimplement rename()
- provide a second method accepting CopyOptions which can be used to 
  request atomic move.

Change-Id: Ibcf722978e65745218a1ccda45344ca295911659
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
tags/v4.1.0.201509280440-r
Matthias Sohn 9 years ago
parent
commit
548ba66a37

+ 12
- 0
org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FileUtils7Test.java View File

@@ -48,6 +48,8 @@ import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;

import org.junit.After;
import org.junit.Before;
@@ -83,4 +85,14 @@ public class FileUtils7Test {
assertTrue(dir.exists());
assertTrue(file.exists());
}

@Test
public void testAtomicMove() throws IOException {
File src = new File(trash, "src");
Files.createFile(src.toPath());
File dst = new File(trash, "dst");
FileUtils.rename(src, dst, StandardCopyOption.ATOMIC_MOVE);
assertFalse(Files.exists(src.toPath()));
assertTrue(Files.exists(dst.toPath()));
}
}

+ 55
- 14
org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java View File

@@ -48,9 +48,12 @@ package org.eclipse.jgit.util;
import java.io.File;
import java.io.IOException;
import java.nio.channels.FileLock;
import java.nio.file.AtomicMoveNotSupportedException;
import java.nio.file.CopyOption;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.text.MessageFormat;
import java.text.Normalizer;
import java.text.Normalizer.Form;
@@ -212,30 +215,68 @@ public class FileUtils {
*/
public static void rename(final File src, final File dst)
throws IOException {
rename(src, dst, StandardCopyOption.REPLACE_EXISTING);
}

/**
* Rename a file or folder using the passed {@link CopyOption}s. If the
* rename fails and if we are running on a filesystem where it makes sense
* to repeat a failing rename then repeat the rename operation up to 9 times
* with 100ms sleep time between two calls. Furthermore if the destination
* exists and is a directory hierarchy with only directories in it, the
* whole directory hierarchy will be deleted. If the target represents a
* non-empty directory structure, empty subdirectories within that structure
* may or may not be deleted even if the method fails. Furthermore if the
* destination exists and is a file then the file will be replaced if
* {@link StandardCopyOption#REPLACE_EXISTING} has been set. If
* {@link StandardCopyOption#ATOMIC_MOVE} has been set the rename will be
* done atomically or fail with an {@link AtomicMoveNotSupportedException}
*
* @param src
* the old file
* @param dst
* the new file
* @param options
* options to pass to
* {@link Files#move(java.nio.file.Path, java.nio.file.Path, CopyOption...)}
* @throws AtomicMoveNotSupportedException
* if file cannot be moved as an atomic file system operation
* @throws IOException
* @since 4.1
*/
public static void rename(final File src, final File dst,
CopyOption... options)
throws AtomicMoveNotSupportedException, IOException {
int attempts = FS.DETECTED.retryFailedLockFileCommit() ? 10 : 1;
while (--attempts >= 0) {
if (src.renameTo(dst))
return;
try {
if (!dst.delete())
delete(dst, EMPTY_DIRECTORIES_ONLY | RECURSIVE);
// On *nix there is no try, you do or do not
if (src.renameTo(dst))
return;
Files.move(src.toPath(), dst.toPath(), options);
return;
} catch (AtomicMoveNotSupportedException e) {
throw e;
} catch (IOException e) {
// ignore and continue retry
try {
if (!dst.delete()) {
delete(dst, EMPTY_DIRECTORIES_ONLY | RECURSIVE);
}
// On *nix there is no try, you do or do not
Files.move(src.toPath(), dst.toPath(), options);
return;
} catch (IOException e2) {
// ignore and continue retry
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new IOException(MessageFormat.format(
JGitText.get().renameFileFailed, src.getAbsolutePath(),
dst.getAbsolutePath()));
throw new IOException(
MessageFormat.format(JGitText.get().renameFileFailed,
src.getAbsolutePath(), dst.getAbsolutePath()));
}
}
throw new IOException(MessageFormat.format(
JGitText.get().renameFileFailed, src.getAbsolutePath(),
dst.getAbsolutePath()));
throw new IOException(
MessageFormat.format(JGitText.get().renameFileFailed,
src.getAbsolutePath(), dst.getAbsolutePath()));
}

/**

Loading…
Cancel
Save