@matheusbsbs / matheus-bagliano / commits / 8464010f97
Fork 0

Make git prune remove temporary packs that look like write failures

Write errors when repacking (eg, due to out-of-space conditions) can leave temporary packs (and possibly other files beginning with "tmp_") lying around which no existing codepath removes and which aren't obvious to the casual user. These can also be multi-megabyte files wasting noticeable space. Unfortunately there's no way to definitely tell in builtin-prune that a tmp_ file is not being used by a concurrent process, such as a fetch. However, it is documented that pruning should only be done on a quiet repository and --expire is honoured (using code from Johannes Schindelin, along with a test case he wrote) so that its safety is the same as that of loose object pruning. Since they might be signs of a problem (unlike orphaned loose objects) the names of any removed files are printed. Signed-off-by: David Tweed (david.tweed@gmail.com) Acked-by: Nicolas Pitre <nico@cam.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

David Steven Tweed committed Feb 7, 2008 at 02:55 UTC 8464010f974245b1e392d34ddbfb914fcf3d8c23
2 files changed +71
builtin-prune.c
+39
@@ -83,6 +83,44 @@ static void prune_object_dir(const char *path)
83 }
84 }
85
86 +/*
87 + * Write errors (particularly out of space) can result in
88 + * failed temporary packs (and more rarely indexes and other
89 + * files begining with "tmp_") accumulating in the
90 + * object directory.
91 + */
92 +static void remove_temporary_files(void)
93 +{
94 + DIR *dir;
95 + struct dirent *de;
96 + char* dirname=get_object_directory();
97 +
98 + dir = opendir(dirname);
99 + if (!dir) {
100 + fprintf(stderr, "Unable to open object directory %s\n",
101 + dirname);
102 + return;
103 + }
104 + while ((de = readdir(dir)) != NULL) {
105 + if (!prefixcmp(de->d_name, "tmp_")) {
106 + char name[PATH_MAX];
107 + int c = snprintf(name, PATH_MAX, "%s/%s",
108 + dirname, de->d_name);
109 + if (c < 0 || c >= PATH_MAX)
110 + continue;
111 + if (expire) {
112 + struct stat st;
113 + if (stat(name, &st) != 0 || st.st_mtime >= expire)
114 + continue;
115 + }
116 + printf("Removing stale temporary file %s\n", name);
117 + if (!show_only)
118 + unlink(name);
119 + }
120 + }
121 + closedir(dir);
122 +}
123 +
124 int cmd_prune(int argc, const char **argv, const char *prefix)
125 {
126 int i;
@@ -115,5 +153,6 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
153
154 sync();
155 prune_packed_objects(show_only);
156 + remove_temporary_files();
157 return 0;
158 }
t/t5304-prune.sh new
+32
@@ -0,0 +1,32 @@
1 +#!/bin/sh
2 +#
3 +# Copyright (c) 2008 Johannes E. Schindelin
4 +#
5 +
6 +test_description='prune'
7 +. ./test-lib.sh
8 +
9 +test_expect_success setup '
10 +
11 + : > file &&
12 + git add file &&
13 + test_tick &&
14 + git commit -m initial &&
15 + git gc
16 +
17 +'
18 +
19 +test_expect_success 'prune stale packs' '
20 +
21 + orig_pack=$(echo .git/objects/pack/*.pack) &&
22 + : > .git/objects/tmp_1.pack &&
23 + : > .git/objects/tmp_2.pack &&
24 + test-chmtime -86501 .git/objects/tmp_1.pack &&
25 + git prune --expire 1.day &&
26 + test -f $orig_pack &&
27 + test -f .git/objects/tmp_2.pack &&
28 + ! test -f .git/objects/tmp_1.pack
29 +
30 +'
31 +
32 +test_done