Merge "Extend FileUtils.rename to common git semantics"
This commit is contained in:
commit
b1d191a155
|
@ -45,6 +45,7 @@
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.endsWith;
|
import static org.hamcrest.Matchers.endsWith;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
@ -52,6 +53,7 @@
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.junit.JGitTestUtil;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -321,4 +323,71 @@ public void testDeleteNotEmptyTreeNotOkButIgnoreFail() throws IOException {
|
||||||
assertTrue(f.exists());
|
assertTrue(f.exists());
|
||||||
assertFalse(e.exists());
|
assertFalse(e.exists());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRenameOverNonExistingFile() throws IOException {
|
||||||
|
File d = new File(trash, "d");
|
||||||
|
FileUtils.mkdirs(d);
|
||||||
|
File f1 = new File(trash, "d/f");
|
||||||
|
File f2 = new File(trash, "d/g");
|
||||||
|
JGitTestUtil.write(f1, "f1");
|
||||||
|
// test
|
||||||
|
FileUtils.rename(f1, f2);
|
||||||
|
assertFalse(f1.exists());
|
||||||
|
assertTrue(f2.exists());
|
||||||
|
assertEquals("f1", JGitTestUtil.read(f2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRenameOverExistingFile() throws IOException {
|
||||||
|
File d = new File(trash, "d");
|
||||||
|
FileUtils.mkdirs(d);
|
||||||
|
File f1 = new File(trash, "d/f");
|
||||||
|
File f2 = new File(trash, "d/g");
|
||||||
|
JGitTestUtil.write(f1, "f1");
|
||||||
|
JGitTestUtil.write(f2, "f2");
|
||||||
|
// test
|
||||||
|
FileUtils.rename(f1, f2);
|
||||||
|
assertFalse(f1.exists());
|
||||||
|
assertTrue(f2.exists());
|
||||||
|
assertEquals("f1", JGitTestUtil.read(f2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRenameOverExistingNonEmptyDirectory() throws IOException {
|
||||||
|
File d = new File(trash, "d");
|
||||||
|
FileUtils.mkdirs(d);
|
||||||
|
File f1 = new File(trash, "d/f");
|
||||||
|
File f2 = new File(trash, "d/g");
|
||||||
|
File d1 = new File(trash, "d/g/h/i");
|
||||||
|
File f3 = new File(trash, "d/g/h/f");
|
||||||
|
FileUtils.mkdirs(d1);
|
||||||
|
JGitTestUtil.write(f1, "f1");
|
||||||
|
JGitTestUtil.write(f3, "f3");
|
||||||
|
// test
|
||||||
|
try {
|
||||||
|
FileUtils.rename(f1, f2);
|
||||||
|
fail("rename to non-empty directory should fail");
|
||||||
|
} catch (IOException e) {
|
||||||
|
assertEquals("f1", JGitTestUtil.read(f1)); // untouched source
|
||||||
|
assertEquals("f3", JGitTestUtil.read(f3)); // untouched
|
||||||
|
// empty directories within f2 may or may not have been deleted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRenameOverExistingEmptyDirectory() throws IOException {
|
||||||
|
File d = new File(trash, "d");
|
||||||
|
FileUtils.mkdirs(d);
|
||||||
|
File f1 = new File(trash, "d/f");
|
||||||
|
File f2 = new File(trash, "d/g");
|
||||||
|
File d1 = new File(trash, "d/g/h/i");
|
||||||
|
FileUtils.mkdirs(d1);
|
||||||
|
JGitTestUtil.write(f1, "f1");
|
||||||
|
// test
|
||||||
|
FileUtils.rename(f1, f2);
|
||||||
|
assertFalse(f1.exists());
|
||||||
|
assertTrue(f2.exists());
|
||||||
|
assertEquals("f1", JGitTestUtil.read(f2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,7 +171,14 @@ public static void delete(final File f, int options) throws IOException {
|
||||||
* Rename a file or folder. If the rename fails and if we are running on a
|
* Rename a file or folder. If the rename fails and if we are running on a
|
||||||
* filesystem where it makes sense to repeat a failing rename then repeat
|
* 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
|
* the rename operation up to 9 times with 100ms sleep time between two
|
||||||
* calls
|
* calls. Furthermore if the destination exists and is 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 deleted and then the rename is retried.
|
||||||
|
* <p>
|
||||||
|
* This operation is <em>not</me> atomic.
|
||||||
*
|
*
|
||||||
* @see FS#retryFailedLockFileCommit()
|
* @see FS#retryFailedLockFileCommit()
|
||||||
* @param src
|
* @param src
|
||||||
|
@ -188,6 +195,15 @@ public static void rename(final File src, final File dst)
|
||||||
while (--attempts >= 0) {
|
while (--attempts >= 0) {
|
||||||
if (src.renameTo(dst))
|
if (src.renameTo(dst))
|
||||||
return;
|
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;
|
||||||
|
} catch (IOException e) {
|
||||||
|
// ignore and continue retry
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
Thread.sleep(100);
|
Thread.sleep(100);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
|
Loading…
Reference in New Issue