summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FileUtilTest.java69
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java18
2 files changed, 86 insertions, 1 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FileUtilTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FileUtilTest.java
index d0680cab74..f6f6753c75 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FileUtilTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FileUtilTest.java
@@ -45,6 +45,7 @@ package org.eclipse.jgit.util;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.endsWith;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -52,6 +53,7 @@ import static org.junit.Assert.fail;
import java.io.File;
import java.io.IOException;
+import org.eclipse.jgit.junit.JGitTestUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -321,4 +323,71 @@ public class FileUtilTest {
assertTrue(f.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));
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
index dc0bbcb380..5fbbda7c50 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
@@ -171,7 +171,14 @@ public class FileUtils {
* 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
* 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()
* @param src
@@ -189,6 +196,15 @@ public class FileUtils {
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;
+ } catch (IOException e) {
+ // ignore and continue retry
+ }
+ try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new IOException(MessageFormat.format(