summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GCTest.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java18
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java33
3 files changed, 55 insertions, 3 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GCTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GCTest.java
index bc60f64886..d5c8f12ef6 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GCTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GCTest.java
@@ -435,6 +435,13 @@ public class GCTest extends LocalDiskRepositoryTestCase {
assertEquals(0, stats.numberOfLooseObjects);
assertEquals(4, stats.numberOfPackedObjects);
assertEquals(1, stats.numberOfPackFiles);
+
+ // Do the gc again and check that it hasn't changed anything
+ gc.gc();
+ stats = gc.getStatistics();
+ assertEquals(0, stats.numberOfLooseObjects);
+ assertEquals(4, stats.numberOfPackedObjects);
+ assertEquals(1, stats.numberOfPackFiles);
}
@Test
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
index 22fa827044..bc14d88d60 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
@@ -735,11 +735,21 @@ public class GC {
// rename the temporary files to real files
File realPack = nameFor(id, ".pack"); //$NON-NLS-1$
+
+ // if the packfile already exists (because we are rewriting a
+ // packfile for the same set of objects maybe with different
+ // PackConfig) then make sure we get rid of all handles on the file.
+ // Windows will not allow for rename otherwise.
+ if (realPack.exists())
+ for (PackFile p : repo.getObjectDatabase().getPacks())
+ if (realPack.getPath().equals(p.getPackFile().getPath())) {
+ p.close();
+ break;
+ }
tmpPack.setReadOnly();
boolean delete = true;
try {
- if (!tmpPack.renameTo(realPack))
- return null;
+ FileUtils.rename(tmpPack, realPack);
delete = false;
for (Map.Entry<PackExt, File> tmpEntry : tmpExts.entrySet()) {
File tmpExt = tmpEntry.getValue();
@@ -747,7 +757,9 @@ public class GC {
File realExt = nameFor(
id, "." + tmpEntry.getKey().getExtension()); //$NON-NLS-1$
- if (!tmpExt.renameTo(realExt)) {
+ try {
+ FileUtils.rename(tmpExt, realExt);
+ } catch (IOException e) {
File newExt = new File(realExt.getParentFile(),
realExt.getName() + ".new"); //$NON-NLS-1$
if (!tmpExt.renameTo(newExt))
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 67f371b618..acc1a2c31c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
@@ -168,6 +168,39 @@ 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
+ *
+ * @see FS#retryFailedLockFileCommit()
+ * @param src
+ * the old {@code File}
+ * @param dst
+ * the new {@code File}
+ * @throws IOException
+ * if the rename has failed
+ */
+ public static void rename(final File src, final File dst)
+ throws IOException {
+ int attempts = FS.DETECTED.retryFailedLockFileCommit() ? 10 : 1;
+ while (--attempts >= 0) {
+ if (src.renameTo(dst))
+ return;
+ 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()));
+ }
+
+ /**
* Creates the directory named by this abstract pathname.
*
* @param d