Support config param "gc.pruneexpire"

Make GC honor the config parameter gc.pruneexpire. If the parameter is
not set then the default is "2.weeks.ago"

Change-Id: I0ae0ca85993cafb4bc75ba80504da18544894ec3
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
index aaa427b..483482e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
@@ -75,6 +75,9 @@
 	/** The "submodule" section */
 	public static final String CONFIG_SUBMODULE_SECTION = "submodule";
 
+	/** The "gc" section */
+	public static final String CONFIG_GC_SECTION = "gc";
+
 	/** The "pack" section */
 	public static final String CONFIG_PACK_SECTION = "pack";
 
@@ -181,4 +184,7 @@
 
 	/** The "precomposeunicode" key */
 	public static final String CONFIG_KEY_PRECOMPOSEUNICODE = "precomposeunicode";
+
+	/** The "pruneexpire" key */
+	public static final String CONFIG_KEY_PRUNEEXPIRE = "pruneexpire";
 }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/GC.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/GC.java
index 1c2b959..28dc544 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/GC.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/GC.java
@@ -53,6 +53,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -68,6 +69,7 @@
 import org.eclipse.jgit.errors.MissingObjectException;
 import org.eclipse.jgit.errors.NoWorkTreeException;
 import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.lib.ConfigConstants;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.FileMode;
 import org.eclipse.jgit.lib.NullProgressMonitor;
@@ -83,6 +85,7 @@
 import org.eclipse.jgit.treewalk.TreeWalk;
 import org.eclipse.jgit.treewalk.filter.TreeFilter;
 import org.eclipse.jgit.util.FileUtils;
+import org.eclipse.jgit.util.GitDateParser;
 
 /**
  * A garbage collector for git {@link FileRepository}. Instances of this class
@@ -92,11 +95,15 @@
  * adapted to FileRepositories.
  */
 public class GC {
+	private static final String PRUNE_EXPIRE_DEFAULT = "2.weeks.ago";
+
 	private final FileRepository repo;
 
 	private ProgressMonitor pm;
 
-	private long expireAgeMillis;
+	private long expireAgeMillis = -1;
+
+	private Date expire;
 
 	/**
 	 * the refs which existed during the last call to {@link #repack()}. This is
@@ -123,7 +130,6 @@
 	public GC(FileRepository repo) {
 		this.repo = repo;
 		this.pm = NullProgressMonitor.INSTANCE;
-		this.expireAgeMillis = 14 * 24 * 60 * 60 * 1000L;
 	}
 
 	/**
@@ -253,8 +259,21 @@
 	 */
 	public void prune(Set<ObjectId> objectsToKeep)
 			throws IOException {
-		long expireDate = (expireAgeMillis == 0) ? Long.MAX_VALUE : System
-				.currentTimeMillis() - expireAgeMillis;
+		long expireDate = Long.MAX_VALUE;
+
+		if (expire == null && expireAgeMillis == -1) {
+			String pruneExpireStr = repo.getConfig().getString(
+					ConfigConstants.CONFIG_GC_SECTION, null,
+					ConfigConstants.CONFIG_KEY_PRUNEEXPIRE);
+			if (pruneExpireStr == null)
+				pruneExpireStr = PRUNE_EXPIRE_DEFAULT;
+			expire = GitDateParser.parse(pruneExpireStr, null);
+			expireAgeMillis = -1;
+		}
+		if (expire != null)
+			expireDate = expire.getTime();
+		if (expireAgeMillis != -1)
+			expireDate = System.currentTimeMillis() - expireAgeMillis;
 
 		// Collect all loose objects which are old enough, not referenced from
 		// the index and not in objectsToKeep
@@ -807,5 +826,21 @@
 	 */
 	public void setExpireAgeMillis(long expireAgeMillis) {
 		this.expireAgeMillis = expireAgeMillis;
+		expire = null;
 	}
+
+	/**
+	 * During gc() or prune() each unreferenced, loose object which has been
+	 * created or modified after <code>expire</code> will not be pruned. Only
+	 * older objects may be pruned. If set to null then every object is a
+	 * candidate for pruning.
+	 *
+	 * @param expire
+	 *            minimal age of objects to be pruned in milliseconds.
+	 */
+	public void setExpire(Date expire) {
+		this.expire = expire;
+		expireAgeMillis = -1;
+	}
+
 }