diff options
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse')
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java | 18 | ||||
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java | 33 |
2 files changed, 48 insertions, 3 deletions
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 |