@matheusbsbs / matheus-bagliano / commits / 7d7ff15b39
Fork 0

rerere: fix overeager gc

'rerere gc' prunes resolutions of conflicted merges that occurred long time ago, and when doing so it takes the creation time of the conflicted automerge results into account. This can cause the loss of frequently used conflict resolutions (e.g. long-living topic branches are merged into a regularly rebuilt integration branch (think of git's pu)) when they become old enough to exceed 'rerere gc's threshold. To prevent the loss of valuable merge resolutions 'rerere' will (1) update the timestamp of the recorded conflict resolution (i.e. 'postimage') each time when encountering and resolving the same merge conflict, and (2) take this timestamp, i.e. the time of the last usage into account when gc'ing. Signed-off-by: SZEDER Gábor <szeder@ira.uka.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

SZEDER Gábor committed Jul 13, 2010 at 01:42 UTC 7d7ff15b39abfa9e73b6475f189006a74dc26376
3 files changed +34 -9
builtin/rerere.c
+16 -5
@@ -19,6 +19,12 @@ static time_t rerere_created_at(const char *name)
19 return stat(rerere_path(name, "preimage"), &st) ? (time_t) 0 : st.st_mtime;
20 }
21
22 +static time_t rerere_last_used_at(const char *name)
23 +{
24 + struct stat st;
25 + return stat(rerere_path(name, "postimage"), &st) ? (time_t) 0 : st.st_mtime;
26 +}
27 +
28 static void unlink_rr_item(const char *name)
29 {
30 unlink(rerere_path(name, "thisimage"));
@@ -53,11 +59,16 @@ static void garbage_collect(struct string_list *rr)
59 while ((e = readdir(dir))) {
60 if (is_dot_or_dotdot(e->d_name))
61 continue;
56 - then = rerere_created_at(e->d_name);
57 - if (!then)
58 - continue;
59 - cutoff = (has_rerere_resolution(e->d_name)
60 - ? cutoff_resolve : cutoff_noresolve);
62 +
63 + then = rerere_last_used_at(e->d_name);
64 + if (then) {
65 + cutoff = cutoff_resolve;
66 + } else {
67 + then = rerere_created_at(e->d_name);
68 + if (!then)
69 + continue;
70 + cutoff = cutoff_noresolve;
71 + }
72 if (then < now - cutoff * 86400)
73 string_list_append(e->d_name, &to_remove);
74 }
rerere.c
+7 -1
@@ -378,7 +378,13 @@ static int merge(const char *name, const char *path)
378 }
379 ret = ll_merge(&result, path, &base, NULL, &cur, "", &other, "", 0);
380 if (!ret) {
381 - FILE *f = fopen(path, "w");
381 + FILE *f;
382 +
383 + if (utime(rerere_path(name, "postimage"), NULL) < 0)
384 + warning("failed utime() on %s: %s",
385 + rerere_path(name, "postimage"),
386 + strerror(errno));
387 + f = fopen(path, "w");
388 if (!f)
389 return error("Could not open %s: %s", path,
390 strerror(errno));
t/t4200-rerere.sh
+11 -3
@@ -132,6 +132,8 @@ test_expect_success 'commit succeeds' \
132
133 test_expect_success 'recorded postimage' "test -f $rr/postimage"
134
135 +oldmtimepost=$(test-chmtime -v -60 $rr/postimage |cut -f 1)
136 +
137 test_expect_success 'another conflicting merge' '
138 git checkout -b third master &&
139 git show second^:a1 | sed "s/To die: t/To die! T/" > a1 &&
@@ -144,6 +146,11 @@ test_expect_success 'rerere kicked in' "! grep ^=======$ a1"
146
147 test_expect_success 'rerere prefers first change' 'test_cmp a1 expect'
148
149 +test_expect_success 'rerere updates postimage timestamp' '
150 + newmtimepost=$(test-chmtime -v +0 $rr/postimage |cut -f 1) &&
151 + test $oldmtimepost -lt $newmtimepost
152 +'
153 +
154 rm $rr/postimage
155 echo "$sha1 a1" | perl -pe 'y/\012/\000/' > .git/MERGE_RR
156
@@ -165,15 +172,16 @@ just_over_15_days_ago=$((-1-15*86400))
172 almost_60_days_ago=$((60-60*86400))
173 just_over_60_days_ago=$((-1-60*86400))
174
168 -test-chmtime =$almost_60_days_ago $rr/preimage
175 +test-chmtime =$just_over_60_days_ago $rr/preimage
176 +test-chmtime =$almost_60_days_ago $rr/postimage
177 test-chmtime =$almost_15_days_ago $rr2/preimage
178
179 test_expect_success 'garbage collection (part1)' 'git rerere gc'
180
173 -test_expect_success 'young records still live' \
181 +test_expect_success 'young or recently used records still live' \
182 "test -f $rr/preimage && test -f $rr2/preimage"
183
176 -test-chmtime =$just_over_60_days_ago $rr/preimage
184 +test-chmtime =$just_over_60_days_ago $rr/postimage
185 test-chmtime =$just_over_15_days_ago $rr2/preimage
186
187 test_expect_success 'garbage collection (part2)' 'git rerere gc'