git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] Add "--expire <time>" option to 'git prune'

From
Johannes Schindelin <johannes.schindelin@gmx.de>
Date
Nov 29, 2007, 14:21 UTC
Message-ID
<Pine.LNX.4.64.0711291419350.27959@racer.site>
In-Reply-To
<Pine.LNX.4.64.0711291146090.27959@racer.site>

Earlier, 'git prune' would prune all loose unreachable objects. This could be quite dangerous, as the objects could be used in an ongoing operation.

This patch adds a mode to expire only loose, unreachable objects which are older than a certain time. For example, by

	git prune --expire 14.days

you can prune only those objects which are loose, unreachable and older than 14 days (and thus probably outdated).

The implementation uses st.st_mtime rather than st.st_ctime, because it can be tested better, using 'touch -d <time>' (and omitting the test when the platform does not support that command line switch).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
	On Thu, 29 Nov 2007, Johannes Schindelin wrote:
	> Note that "prune" is not (yet) an option [for repo.or.cz], since 
	> it could possibly destroy objects which are needed in an ongoing 
	> push operation.
	> 
	> However, we could do exactly the same as with reflogs: introduce 
	> a grace period (with loose objects, we can use the ctime...)
	and this patch does that (except using mtime as ctime, for reasons 
	explained in the commit message.
	Obviously, this patch is asking for a cousin, changing
	git-gc to use this option, and maybe introduce a config
	variable gc.pruneAge.
 Documentation/git-prune.txt |    5 ++++-
 builtin-prune.c             |   21 ++++++++++++++++++++-
 t/t1410-reflog.sh           |   18 ++++++++++++++++++
 3 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-prune.txt b/Documentation/git-prune.txt
index 0ace233..9835bdb 100644
--- a/Documentation/git-prune.txt
+++ b/Documentation/git-prune.txt
@@ -8,7 +8,7 @@ git-prune - Prune all unreachable objects from the object database
 
 SYNOPSIS
 --------
-'git-prune' [-n] [--] [<head>...]
+'git-prune' [-n] [--expire <expire>] [--] [<head>...]
 
 DESCRIPTION
 -----------
@@ -31,6 +31,9 @@ OPTIONS
 \--::
 	Do not interpret any more arguments as options.
 
+\--expire <time>::
+	Only expire loose objects older than <time>.
+
 <head>...::
 	In addition to objects
 	reachable from any of our references, keep objects
diff --git a/builtin-prune.c b/builtin-prune.c
index 44df59e..b5e7684 100644
--- a/builtin-prune.c
+++ b/builtin-prune.c
@@ -7,15 +7,24 @@
 
 static const char prune_usage[] = "git-prune [-n]";
 static int show_only;
+static unsigned long expire;
 
 static int prune_object(char *path, const char *filename, const unsigned char *sha1)
 {
+	const char *fullpath = mkpath("%s/%s", path, filename);
+	if (expire) {
+		struct stat st;
+		if (lstat(fullpath, &st))
+			return error("Could not stat '%s'", fullpath);
+		if (st.st_mtime > expire)
+			return 0;
+	}
 	if (show_only) {
 		enum object_type type = sha1_object_info(sha1, NULL);
 		printf("%s %s\n", sha1_to_hex(sha1),
 		       (type > 0) ? typename(type) : "unknown");
 	} else
-		unlink(mkpath("%s/%s", path, filename));
+		unlink(fullpath);
 	return 0;
 }
 
@@ -85,6 +94,16 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
 			show_only = 1;
 			continue;
 		}
+		if (!strcmp(arg, "--expire")) {
+			if (++i < argc) {
+				expire = approxidate(argv[i]);
+				continue;
+			}
+		}
+		else if (!prefixcmp(arg, "--expire=")) {
+			expire = approxidate(arg + 9);
+			continue;
+		}
 		usage(prune_usage);
 	}
 
diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh
index 12a53ed..f093802 100755
--- a/t/t1410-reflog.sh
+++ b/t/t1410-reflog.sh
@@ -201,4 +201,22 @@ test_expect_success 'delete' '
 	! grep dragon < output
 '
 
+test_expect_success 'prune --expire' '
+
+	BLOB=$(echo aleph | git hash-object -w --stdin) &&
+	BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") &&
+	test 20 = $(git count-objects | sed "s/ .*//") &&
+	test -f $BLOB_FILE &&
+	git reset --hard &&
+	if touch -d "Jan 1 1970" $BLOB_FILE
+	then
+		git prune --expire 1.day &&
+		test 19 = $(git count-objects | sed "s/ .*//") &&
+		! test -f $BLOB_FILE
+	else
+		say "Skipping test due to non-working touch -d"
+	fi
+
+'
+
 test_done
-- 
1.5.3.6.2087.g788ea4
Previous: Johannes SchindelinNext: Johannes Sixt
Message 8 of 14 in “[RFC] Alternates and broken repos: A pack and prune scheme to avoid them”
  1. Johannes SixtNov 18, 2007
  2. Junio C HamanoNov 18, 2007
  3. Johannes SixtNov 18, 2007
  4. Junio C HamanoNov 18, 2007
  5. Teach repack to optionally retain otherwise lost objectsJohannes Schindelin, Nov 29, 2007
  6. Junio C HamanoNov 29, 2007
  7. Johannes SchindelinNov 29, 2007
  8. Add "--expire <time>" option to 'git prune'Johannes Schindelin, Nov 29, 2007
  9. Johannes SixtNov 29, 2007
  10. Add "--expire <time>" option to 'git prune'Johannes Schindelin, Nov 29, 2007
  11. Jeff KingNov 29, 2007
  12. Johannes SchindelinNov 29, 2007
  13. Junio C HamanoNov 29, 2007
  14. Add "--expire <time>" option to 'git prune'Johannes Schindelin, Nov 29, 2007

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.