aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Nittka <alex@nittka.de>2020-03-13 14:16:50 +0100
committerThomas Wolf <thomas.wolf@paranor.ch>2020-04-03 19:30:31 +0200
commitbc4ed530a5f19b5dae77f3aa76369003bd6c3599 (patch)
tree26f0092c372d7307589a071d83e550ed4365353a
parent9aaa58052b4f810da7a1b3cd67dadbd50e956934 (diff)
downloadjgit-bc4ed530a5f19b5dae77f3aa76369003bd6c3599.tar.gz
jgit-bc4ed530a5f19b5dae77f3aa76369003bd6c3599.zip
FileUtils: improve delete (Windows)
Ensure files are writable before trying to delete them. Bug: 408846 Change-Id: I930a547594bba853c33634ae54bd64d236afade3 Signed-off-by: Alexander Nittka <alex@nittka.de>
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FileUtilsTest.java37
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java51
2 files changed, 70 insertions, 18 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FileUtilsTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FileUtilsTest.java
index f9ec5d8d6f..2b1fb2ef04 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FileUtilsTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FileUtilsTest.java
@@ -79,6 +79,15 @@ public class FileUtilsTest {
}
@Test
+ public void testDeleteReadOnlyFile() throws IOException {
+ File f = new File(trash, "f");
+ FileUtils.createNewFile(f);
+ assertTrue(f.setReadOnly());
+ FileUtils.delete(f);
+ assertFalse(f.exists());
+ }
+
+ @Test
public void testDeleteRecursive() throws IOException {
File f1 = new File(trash, "test/test/a");
FileUtils.mkdirs(f1.getParentFile());
@@ -339,6 +348,34 @@ public class FileUtilsTest {
}
@Test
+ public void testDeleteNonRecursiveTreeNotOk() throws IOException {
+ File t = new File(trash, "t");
+ FileUtils.mkdir(t);
+ File f = new File(t, "f");
+ FileUtils.createNewFile(f);
+ try {
+ FileUtils.delete(t, FileUtils.EMPTY_DIRECTORIES_ONLY);
+ fail("expected failure to delete f");
+ } catch (IOException e) {
+ assertTrue(e.getMessage().endsWith(t.getAbsolutePath()));
+ }
+ assertTrue(f.exists());
+ assertTrue(t.exists());
+ }
+
+ @Test
+ public void testDeleteNonRecursiveTreeIgnoreError() throws IOException {
+ File t = new File(trash, "t");
+ FileUtils.mkdir(t);
+ File f = new File(t, "f");
+ FileUtils.createNewFile(f);
+ FileUtils.delete(t,
+ FileUtils.EMPTY_DIRECTORIES_ONLY | FileUtils.IGNORE_ERRORS);
+ assertTrue(f.exists());
+ assertTrue(t.exists());
+ }
+
+ @Test
public void testRenameOverNonExistingFile() throws IOException {
File d = new File(trash, "d");
FileUtils.mkdirs(d);
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 4831fbb64e..c43956e53d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
@@ -20,6 +20,7 @@ import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.file.AtomicMoveNotSupportedException;
import java.nio.file.CopyOption;
+import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.LinkOption;
@@ -180,21 +181,31 @@ public class FileUtils {
}
if (delete) {
- Throwable t = null;
+ IOException t = null;
Path p = f.toPath();
- try {
- Files.delete(p);
- return;
- } catch (FileNotFoundException e) {
- if ((options & (SKIP_MISSING | IGNORE_ERRORS)) == 0) {
- throw new IOException(MessageFormat.format(
- JGitText.get().deleteFileFailed,
- f.getAbsolutePath()), e);
+ boolean tryAgain;
+ do {
+ tryAgain = false;
+ try {
+ Files.delete(p);
+ return;
+ } catch (NoSuchFileException | FileNotFoundException e) {
+ handleDeleteException(f, e, options,
+ SKIP_MISSING | IGNORE_ERRORS);
+ return;
+ } catch (DirectoryNotEmptyException e) {
+ handleDeleteException(f, e, options, IGNORE_ERRORS);
+ return;
+ } catch (IOException e) {
+ if (!f.canWrite()) {
+ tryAgain = f.setWritable(true);
+ }
+ if (!tryAgain) {
+ t = e;
+ }
}
- return;
- } catch (IOException e) {
- t = e;
- }
+ } while (tryAgain);
+
if ((options & RETRY) != 0) {
for (int i = 1; i < 10; i++) {
try {
@@ -210,11 +221,15 @@ public class FileUtils {
}
}
}
- if ((options & IGNORE_ERRORS) == 0) {
- throw new IOException(MessageFormat.format(
- JGitText.get().deleteFileFailed, f.getAbsolutePath()),
- t);
- }
+ handleDeleteException(f, t, options, IGNORE_ERRORS);
+ }
+ }
+
+ private static void handleDeleteException(File f, IOException e,
+ int allOptions, int checkOptions) throws IOException {
+ if (e != null && (allOptions & checkOptions) == 0) {
+ throw new IOException(MessageFormat.format(
+ JGitText.get().deleteFileFailed, f.getAbsolutePath()), e);
}
}