@@ -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 |
@@ -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)) |
@@ -167,6 +167,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. | |||
* |