rerere: libify rerere_clear() and rerere_gc()

This moves the two features from builtin/rerere.c to a more library-ish portion of the codebase. No behaviour change. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed May 8, 2011 at 12:55 UTC 0f891e7d7eb54f9dca93dc3d462eb38082a3460f
3 files changed +88 -75
builtin/rerere.c
+2 -75
@@ -12,74 +12,6 @@ static const char * const rerere_usage[] = {
12 NULL,
13 };
14
15 -/* these values are days */
16 -static int cutoff_noresolve = 15;
17 -static int cutoff_resolve = 60;
18 -
19 -static time_t rerere_created_at(const char *name)
20 -{
21 - struct stat st;
22 - return stat(rerere_path(name, "preimage"), &st) ? (time_t) 0 : st.st_mtime;
23 -}
24 -
25 -static time_t rerere_last_used_at(const char *name)
26 -{
27 - struct stat st;
28 - return stat(rerere_path(name, "postimage"), &st) ? (time_t) 0 : st.st_mtime;
29 -}
30 -
31 -static void unlink_rr_item(const char *name)
32 -{
33 - unlink(rerere_path(name, "thisimage"));
34 - unlink(rerere_path(name, "preimage"));
35 - unlink(rerere_path(name, "postimage"));
36 - rmdir(git_path("rr-cache/%s", name));
37 -}
38 -
39 -static int git_rerere_gc_config(const char *var, const char *value, void *cb)
40 -{
41 - if (!strcmp(var, "gc.rerereresolved"))
42 - cutoff_resolve = git_config_int(var, value);
43 - else if (!strcmp(var, "gc.rerereunresolved"))
44 - cutoff_noresolve = git_config_int(var, value);
45 - else
46 - return git_default_config(var, value, cb);
47 - return 0;
48 -}
49 -
50 -static void garbage_collect(struct string_list *rr)
51 -{
52 - struct string_list to_remove = STRING_LIST_INIT_DUP;
53 - DIR *dir;
54 - struct dirent *e;
55 - int i, cutoff;
56 - time_t now = time(NULL), then;
57 -
58 - git_config(git_rerere_gc_config, NULL);
59 - dir = opendir(git_path("rr-cache"));
60 - if (!dir)
61 - die_errno("unable to open rr-cache directory");
62 - while ((e = readdir(dir))) {
63 - if (is_dot_or_dotdot(e->d_name))
64 - continue;
65 -
66 - then = rerere_last_used_at(e->d_name);
67 - if (then) {
68 - cutoff = cutoff_resolve;
69 - } else {
70 - then = rerere_created_at(e->d_name);
71 - if (!then)
72 - continue;
73 - cutoff = cutoff_noresolve;
74 - }
75 - if (then < now - cutoff * 86400)
76 - string_list_append(&to_remove, e->d_name);
77 - }
78 - for (i = 0; i < to_remove.nr; i++)
79 - unlink_rr_item(to_remove.items[i].string);
80 - string_list_clear(&to_remove, 0);
81 -}
82 -
15 static int outf(void *dummy, mmbuffer_t *ptr, int nbuf)
16 {
17 int i;
@@ -148,14 +80,9 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
80 return 0;
81
82 if (!strcmp(argv[0], "clear")) {
151 - for (i = 0; i < merge_rr.nr; i++) {
152 - const char *name = (const char *)merge_rr.items[i].util;
153 - if (!has_rerere_resolution(name))
154 - unlink_rr_item(name);
155 - }
156 - unlink_or_warn(git_path("MERGE_RR"));
83 + rerere_clear(&merge_rr);
84 } else if (!strcmp(argv[0], "gc"))
158 - garbage_collect(&merge_rr);
85 + rerere_gc(&merge_rr);
86 else if (!strcmp(argv[0], "status"))
87 for (i = 0; i < merge_rr.nr; i++)
88 printf("%s\n", merge_rr.items[i].string);
rerere.c
+84
@@ -671,3 +671,87 @@ int rerere_forget(const char **pathspec)
671 }
672 return write_rr(&merge_rr, fd);
673 }
674 +
675 +static time_t rerere_created_at(const char *name)
676 +{
677 + struct stat st;
678 + return stat(rerere_path(name, "preimage"), &st) ? (time_t) 0 : st.st_mtime;
679 +}
680 +
681 +static time_t rerere_last_used_at(const char *name)
682 +{
683 + struct stat st;
684 + return stat(rerere_path(name, "postimage"), &st) ? (time_t) 0 : st.st_mtime;
685 +}
686 +
687 +static void unlink_rr_item(const char *name)
688 +{
689 + unlink(rerere_path(name, "thisimage"));
690 + unlink(rerere_path(name, "preimage"));
691 + unlink(rerere_path(name, "postimage"));
692 + rmdir(git_path("rr-cache/%s", name));
693 +}
694 +
695 +struct rerere_gc_config_cb {
696 + int cutoff_noresolve;
697 + int cutoff_resolve;
698 +};
699 +
700 +static int git_rerere_gc_config(const char *var, const char *value, void *cb)
701 +{
702 + struct rerere_gc_config_cb *cf = cb;
703 +
704 + if (!strcmp(var, "gc.rerereresolved"))
705 + cf->cutoff_resolve = git_config_int(var, value);
706 + else if (!strcmp(var, "gc.rerereunresolved"))
707 + cf->cutoff_noresolve = git_config_int(var, value);
708 + else
709 + return git_default_config(var, value, cb);
710 + return 0;
711 +}
712 +
713 +void rerere_gc(struct string_list *rr)
714 +{
715 + struct string_list to_remove = STRING_LIST_INIT_DUP;
716 + DIR *dir;
717 + struct dirent *e;
718 + int i, cutoff;
719 + time_t now = time(NULL), then;
720 + struct rerere_gc_config_cb cf = { 15, 60 };
721 +
722 + git_config(git_rerere_gc_config, &cf);
723 + dir = opendir(git_path("rr-cache"));
724 + if (!dir)
725 + die_errno("unable to open rr-cache directory");
726 + while ((e = readdir(dir))) {
727 + if (is_dot_or_dotdot(e->d_name))
728 + continue;
729 +
730 + then = rerere_last_used_at(e->d_name);
731 + if (then) {
732 + cutoff = cf.cutoff_resolve;
733 + } else {
734 + then = rerere_created_at(e->d_name);
735 + if (!then)
736 + continue;
737 + cutoff = cf.cutoff_noresolve;
738 + }
739 + if (then < now - cutoff * 86400)
740 + string_list_append(&to_remove, e->d_name);
741 + }
742 + for (i = 0; i < to_remove.nr; i++)
743 + unlink_rr_item(to_remove.items[i].string);
744 + string_list_clear(&to_remove, 0);
745 +}
746 +
747 +void rerere_clear(struct string_list *merge_rr)
748 +{
749 + int i;
750 +
751 + for (i = 0; i < merge_rr->nr; i++) {
752 + const char *name = (const char *)merge_rr->items[i].util;
753 + if (!has_rerere_resolution(name))
754 + unlink_rr_item(name);
755 + }
756 + unlink_or_warn(git_path("MERGE_RR"));
757 +}
rerere.h
+2
@@ -19,6 +19,8 @@ extern const char *rerere_path(const char *hex, const char *file);
19 extern int has_rerere_resolution(const char *hex);
20 extern int rerere_forget(const char **);
21 extern int rerere_remaining(struct string_list *);
22 +extern void rerere_clear(struct string_list *);
23 +extern void rerere_gc(struct string_list *);
24
25 #define OPT_RERERE_AUTOUPDATE(v) OPT_UYN(0, "rerere-autoupdate", (v), \
26 "update the index with reused conflict resolution if possible")