# [PATCH] gc: make --prune useful again by accepting an optional parameter

3 messages from 2008-12-15 to 2008-12-15. Participants: Johannes Schindelin, Brandon Casey.
Thread: https://gitlist.dev/t/16743

## Johannes Schindelin, 2008-12-15 20:22

Subject: [PATCH] gc: make --prune useful again by accepting an optional parameter
Message-ID: <alpine.DEB.1.00.0812152121260.30769@pacific.mpi-cbg.de>
URL: https://gitlist.dev/e/alpine.DEB.1.00.0812152121260.30769%40pacific.mpi-cbg.de

```

With this patch, "git gc --no-prune" will not prune any loose (and
dangling) object, and "git gc --prune=5.minutes.ago" will prune
all loose objects older than 5 minutes.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---

	Not meant for 1.6.1, obviously.

 Documentation/git-gc.txt |    9 ++++++++-
 builtin-gc.c             |   13 ++++++++-----
 t/t5304-prune.sh         |   20 ++++++++++++++++++++
 3 files changed, 36 insertions(+), 6 deletions(-)

diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt
index 7086eea..fcef5fb 100644
--- a/Documentation/git-gc.txt
+++ b/Documentation/git-gc.txt
@@ -8,7 +8,7 @@ git-gc - Cleanup unnecessary files and optimize the local repository
 
 SYNOPSIS
 --------
-'git gc' [--aggressive] [--auto] [--quiet]
+'git gc' [--aggressive] [--auto] [--quiet] [--prune=<date>]
 
 DESCRIPTION
 -----------
@@ -59,6 +59,13 @@ are consolidated into a single pack by using the `-A` option of
 'git-repack'. Setting `gc.autopacklimit` to 0 disables
 automatic consolidation of packs.
 
+--prune=<date>::
+	Prune loose objects older than date (default is 2 weeks ago).
+	This option is on by default.
+
+--no-prune::
+	Do not prune any loose objects.
+
 --quiet::
 	Suppress all progress reports.
 
diff --git a/builtin-gc.c b/builtin-gc.c
index bbc41ac..078c5b3 100644
--- a/builtin-gc.c
+++ b/builtin-gc.c
@@ -199,14 +199,15 @@ static int need_to_gc(void)
 
 int cmd_gc(int argc, const char **argv, const char *prefix)
 {
-	int prune = 0;
 	int aggressive = 0;
 	int auto_gc = 0;
 	int quiet = 0;
 	char buf[80];
 
 	struct option builtin_gc_options[] = {
-		OPT_BOOLEAN(0, "prune", &prune, "prune unreferenced objects (deprecated)"),
+		{ OPTION_STRING, 0, "prune", &prune_expire, "date",
+			"prune unreferenced objects (deprecated)",
+			PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire },
 		OPT_BOOLEAN(0, "aggressive", &aggressive, "be more thorough (increased runtime)"),
 		OPT_BOOLEAN(0, "auto", &auto_gc, "enable auto-gc mode"),
 		OPT_BOOLEAN('q', "quiet", &quiet, "suppress progress reports"),
@@ -255,9 +256,11 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
 	if (run_command_v_opt(argv_repack, RUN_GIT_CMD))
 		return error(FAILED_RUN, argv_repack[0]);
 
-	argv_prune[2] = prune_expire;
-	if (run_command_v_opt(argv_prune, RUN_GIT_CMD))
-		return error(FAILED_RUN, argv_prune[0]);
+	if (prune_expire) {
+		argv_prune[2] = prune_expire;
+		if (run_command_v_opt(argv_prune, RUN_GIT_CMD))
+			return error(FAILED_RUN, argv_prune[0]);
+	}
 
 	if (run_command_v_opt(argv_rerere, RUN_GIT_CMD))
 		return error(FAILED_RUN, argv_rerere[0]);
diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh
index 771c0a0..2e9c4a9 100755
--- a/t/t5304-prune.sh
+++ b/t/t5304-prune.sh
@@ -112,4 +112,24 @@ test_expect_success 'prune: do not prune heads listed as an argument' '
 
 '
 
+test_expect_success 'gc --no-prune && gc --prune=<date>' '
+
+	before=$(git count-objects | sed "s/ .*//") &&
+	BLOB=$(echo aleph_0 | git hash-object -w --stdin) &&
+	BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") &&
+	test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
+	test -f $BLOB_FILE &&
+	test-chmtime =-$((86400*5001)) $BLOB_FILE &&
+	git gc --no-prune &&
+	test 1 = $(git count-objects | sed "s/ .*//") &&
+	test -f $BLOB_FILE &&
+	git gc --prune=5002.days.ago &&
+	test 1 = $(git count-objects | sed "s/ .*//") &&
+	test -f $BLOB_FILE &&
+	git gc --prune=5000.days.ago &&
+	test 0 = $(git count-objects | sed "s/ .*//") &&
+	test ! -f $BLOB_FILE
+
+'
+
 test_done
-- 
1.6.0.4.1189.g8876f

```

## Brandon Casey, 2008-12-15 21:07

Subject: Re: [PATCH] gc: make --prune useful again by accepting an optional parameter
Message-ID: <j2kXTHA5qGwfTMznJutKnr1RHH7prDrQbr4BYlw-pt2V9gVgqTSERQ@cipher.nrlssc.navy.mil>
URL: https://gitlist.dev/e/j2kXTHA5qGwfTMznJutKnr1RHH7prDrQbr4BYlw-pt2V9gVgqTSERQ%40cipher.nrlssc.navy.mil
In-Reply-To: <alpine.DEB.1.00.0812152121260.30769@pacific.mpi-cbg.de>

```
Johannes Schindelin wrote:
> With this patch, "git gc --no-prune" will not prune any loose (and
> dangling) object, and "git gc --prune=5.minutes.ago" will prune
> all loose objects older than 5 minutes.
> 
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> ---

<snip>

> diff --git a/builtin-gc.c b/builtin-gc.c
> index bbc41ac..078c5b3 100644
> --- a/builtin-gc.c
> +++ b/builtin-gc.c
> @@ -199,14 +199,15 @@ static int need_to_gc(void)
>  
>  int cmd_gc(int argc, const char **argv, const char *prefix)
>  {
> -	int prune = 0;
>  	int aggressive = 0;
>  	int auto_gc = 0;
>  	int quiet = 0;
>  	char buf[80];
>  
>  	struct option builtin_gc_options[] = {
> -		OPT_BOOLEAN(0, "prune", &prune, "prune unreferenced objects (deprecated)"),
> +		{ OPTION_STRING, 0, "prune", &prune_expire, "date",
> +			"prune unreferenced objects (deprecated)",

The help string still contains "deprecated".

> +			PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire },
>  		OPT_BOOLEAN(0, "aggressive", &aggressive, "be more thorough (increased runtime)"),
>  		OPT_BOOLEAN(0, "auto", &auto_gc, "enable auto-gc mode"),
>  		OPT_BOOLEAN('q', "quiet", &quiet, "suppress progress reports"),
> @@ -255,9 +256,11 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
>  	if (run_command_v_opt(argv_repack, RUN_GIT_CMD))
>  		return error(FAILED_RUN, argv_repack[0]);
>  
> -	argv_prune[2] = prune_expire;
> -	if (run_command_v_opt(argv_prune, RUN_GIT_CMD))
> -		return error(FAILED_RUN, argv_prune[0]);
> +	if (prune_expire) {
> +		argv_prune[2] = prune_expire;
> +		if (run_command_v_opt(argv_prune, RUN_GIT_CMD))
> +			return error(FAILED_RUN, argv_prune[0]);
> +	}


When --no-prune is used, not only will packed loose objects not be pruned,
but the cleanup of temporary files that git-prune performs will not be done.

Maybe this should be relaxed from "will not prune _any_ loose object" to "will
not prune any unreferenced object".

If something like:

   if (!prune_expire)
   	prune_expire = "never";

is added after option parsing, then I think this will satisfy people's requests
and it will also apply nicely on top of Nico's patch to avoid unpacking objects
when prune_expire == "now".

-brandon

```

## Brandon Casey, 2008-12-15 21:17

Subject: Re: [PATCH] gc: make --prune useful again by accepting an optional parameter
Message-ID: <4SmUUF2C_ZbcUqUDScx1sSKXIHaQNjKdBXG6Q2GBMY4@cipher.nrlssc.navy.mil>
URL: https://gitlist.dev/e/4SmUUF2C_ZbcUqUDScx1sSKXIHaQNjKdBXG6Q2GBMY4%40cipher.nrlssc.navy.mil
In-Reply-To: <j2kXTHA5qGwfTMznJutKnr1RHH7prDrQbr4BYlw-pt2V9gVgqTSERQ@cipher.nrlssc.navy.mil>

```
Brandon Casey wrote:

> When --no-prune is used, not only will packed loose objects not be pruned,
> but the cleanup of temporary files that git-prune performs will not be done.

I forgot that the temporary file cleanup also honors --expire, so there will
still be no cleanup of temporary files if prune_expire = "never". I think the
rest of my remarks are still valid.

-brandon

```
