Skip to content

Commit f01913e

Browse files
dschogitster
authored andcommitted
Add "--expire <time>" option to 'git prune'
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> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 28391a8 commit f01913e

File tree

3 files changed

+42
-2
lines changed

3 files changed

+42
-2
lines changed

Documentation/git-prune.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ git-prune - Prune all unreachable objects from the object database
88

99
SYNOPSIS
1010
--------
11-
'git-prune' [-n] [--] [<head>...]
11+
'git-prune' [-n] [--expire <expire>] [--] [<head>...]
1212

1313
DESCRIPTION
1414
-----------
@@ -31,6 +31,9 @@ OPTIONS
3131
\--::
3232
Do not interpret any more arguments as options.
3333

34+
\--expire <time>::
35+
Only expire loose objects older than <time>.
36+
3437
<head>...::
3538
In addition to objects
3639
reachable from any of our references, keep objects

builtin-prune.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,24 @@
77

88
static const char prune_usage[] = "git-prune [-n]";
99
static int show_only;
10+
static unsigned long expire;
1011

1112
static int prune_object(char *path, const char *filename, const unsigned char *sha1)
1213
{
14+
const char *fullpath = mkpath("%s/%s", path, filename);
15+
if (expire) {
16+
struct stat st;
17+
if (lstat(fullpath, &st))
18+
return error("Could not stat '%s'", fullpath);
19+
if (st.st_mtime > expire)
20+
return 0;
21+
}
1322
if (show_only) {
1423
enum object_type type = sha1_object_info(sha1, NULL);
1524
printf("%s %s\n", sha1_to_hex(sha1),
1625
(type > 0) ? typename(type) : "unknown");
1726
} else
18-
unlink(mkpath("%s/%s", path, filename));
27+
unlink(fullpath);
1928
return 0;
2029
}
2130

@@ -85,6 +94,16 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
8594
show_only = 1;
8695
continue;
8796
}
97+
if (!strcmp(arg, "--expire")) {
98+
if (++i < argc) {
99+
expire = approxidate(argv[i]);
100+
continue;
101+
}
102+
}
103+
else if (!prefixcmp(arg, "--expire=")) {
104+
expire = approxidate(arg + 9);
105+
continue;
106+
}
88107
usage(prune_usage);
89108
}
90109

t/t1410-reflog.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,4 +175,22 @@ test_expect_success 'recover and check' '
175175
176176
'
177177

178+
test_expect_success 'prune --expire' '
179+
180+
before=$(git count-objects | sed "s/ .*//") &&
181+
BLOB=$(echo aleph | git hash-object -w --stdin) &&
182+
BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") &&
183+
test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
184+
test -f $BLOB_FILE &&
185+
git reset --hard &&
186+
git prune --expire=1.hour.ago &&
187+
test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
188+
test -f $BLOB_FILE &&
189+
test-chmtime -86500 $BLOB_FILE &&
190+
git prune --expire 1.day &&
191+
test $before = $(git count-objects | sed "s/ .*//") &&
192+
! test -f $BLOB_FILE
193+
194+
'
195+
178196
test_done

0 commit comments

Comments
 (0)