If the pruneexpire config is set to "now", then any unreferenced loose objects are immediately eligible for gc. So there is no need to actually write the loose objects. Users who run hosting services which sometimes accept large, entirely garbage packs might set the following configurations: gc.pruneExpire = now gc.prunePackExpire = 2.weeks Then garbage objects will be kept around in packs, but after two weeks the packs themselves will get deleted. For client-side users of jgit, the default settings will loosen garbage objects, and, after an hour, delete the old packs in which they resided. Change-Id: I8f686ac60b40181b1ee92ac6c313c3f33b55c44c Signed-off-by: David Turner <dturner@twosigma.com>tags/v4.7.0.201704051617-r
@@ -55,8 +55,10 @@ import java.util.Date; | |||
import java.util.List; | |||
import org.eclipse.jgit.junit.TestRepository.BranchBuilder; | |||
import org.eclipse.jgit.lib.ConfigConstants; | |||
import org.eclipse.jgit.lib.RefUpdate; | |||
import org.eclipse.jgit.revwalk.RevCommit; | |||
import org.eclipse.jgit.storage.file.FileBasedConfig; | |||
import org.eclipse.jgit.storage.pack.PackConfig; | |||
import org.junit.Test; | |||
import org.junit.experimental.theories.DataPoints; | |||
@@ -247,7 +249,44 @@ public class GcBasicPackingTest extends GcTestCase { | |||
// times | |||
assertEquals(6, stats.numberOfPackedObjects); | |||
assertEquals(1, stats.numberOfPackFiles); | |||
} | |||
@Test | |||
public void testImmediatePruning() throws Exception { | |||
BranchBuilder bb = tr.branch("refs/heads/master"); | |||
bb.commit().message("M").add("M", "M").create(); | |||
String tempRef = "refs/heads/soon-to-be-unreferenced"; | |||
BranchBuilder bb2 = tr.branch(tempRef); | |||
bb2.commit().message("M").add("M", "M").create(); | |||
gc.setExpireAgeMillis(0); | |||
gc.gc(); | |||
stats = gc.getStatistics(); | |||
fsTick(); | |||
// delete the temp ref, orphaning its commit | |||
RefUpdate update = tr.getRepository().getRefDatabase().newUpdate(tempRef, false); | |||
update.setForceUpdate(true); | |||
update.delete(); | |||
bb.commit().message("B").add("B", "Q").create(); | |||
// We want to immediately prune deleted objects | |||
FileBasedConfig config = repo.getConfig(); | |||
config.setString(ConfigConstants.CONFIG_GC_SECTION, null, | |||
ConfigConstants.CONFIG_KEY_PRUNEEXPIRE, "now"); | |||
config.save(); | |||
//And we don't want to keep packs full of dead objects | |||
gc.setPackExpireAgeMillis(0); | |||
gc.gc(); | |||
stats = gc.getStatistics(); | |||
assertEquals(0, stats.numberOfLooseObjects); | |||
assertEquals(6, stats.numberOfPackedObjects); | |||
assertEquals(1, stats.numberOfPackFiles); | |||
} | |||
@Test |
@@ -274,7 +274,8 @@ public class GC { | |||
ObjectReader reader = repo.newObjectReader(); | |||
ObjectDirectory dir = repo.getObjectDatabase(); | |||
ObjectDirectoryInserter inserter = dir.newInserter(); | |||
boolean shouldLoosen = getExpireDate() < Long.MAX_VALUE; | |||
boolean shouldLoosen = !"now".equals(getPruneExpireStr()) && //$NON-NLS-1$ | |||
getExpireDate() < Long.MAX_VALUE; | |||
prunePreserved(); | |||
long packExpireDate = getPackExpireDate(); | |||
@@ -297,6 +298,7 @@ public class GC { | |||
prunePack(oldName); | |||
} | |||
} | |||
// close the complete object database. That's my only chance to force | |||
// rescanning and to detect that certain pack files are now deleted. | |||
repo.getObjectDatabase().close(); | |||
@@ -599,9 +601,7 @@ public class GC { | |||
long expireDate = Long.MAX_VALUE; | |||
if (expire == null && expireAgeMillis == -1) { | |||
String pruneExpireStr = repo.getConfig().getString( | |||
ConfigConstants.CONFIG_GC_SECTION, null, | |||
ConfigConstants.CONFIG_KEY_PRUNEEXPIRE); | |||
String pruneExpireStr = getPruneExpireStr(); | |||
if (pruneExpireStr == null) | |||
pruneExpireStr = PRUNE_EXPIRE_DEFAULT; | |||
expire = GitDateParser.parse(pruneExpireStr, null, SystemReader | |||
@@ -615,6 +615,12 @@ public class GC { | |||
return expireDate; | |||
} | |||
private String getPruneExpireStr() { | |||
return repo.getConfig().getString( | |||
ConfigConstants.CONFIG_GC_SECTION, null, | |||
ConfigConstants.CONFIG_KEY_PRUNEEXPIRE); | |||
} | |||
private long getPackExpireDate() throws ParseException { | |||
long packExpireDate = Long.MAX_VALUE; | |||