rerere: allow approxidate in gc.rerereResolved/gc.rerereUnresolved

These two configuration variables are described in the documentation to take an expiry period expressed in the number of days: gc.rerereResolved:: Records of conflicted merge you resolved earlier are kept for this many days when 'git rerere gc' is run. The default is 60 days. gc.rerereUnresolved:: Records of conflicted merge you have not resolved are kept for this many days when 'git rerere gc' is run. The default is 15 days. There is no strong reason not to allow a more general "approxidate" expiry specification, e.g. "5.days.ago", or "never". Rename the config_get_expiry() helper introduced in the previous step to git_config_get_expiry_in_days() and move it to a more generic place, config.c, and use date.c::parse_expiry_date() to do so. Give it an ability to allow the caller to tell among three cases (i.e. there is no "gc.rerereResolved" config, there is and it is correctly parsed into the *expiry variable, and there was an error in parsing the given value). The current caller can work correctly without using the return value, though. In the future, we may find other variables that only allow an integer that specifies "this many days" or other unit of time, and when it happens we may need to drop "_days" suffix from the name of the function and instead pass the "scale" value as another parameter. But this will do for now. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Aug 19, 2017 at 11:43 UTC 6e96cb5286105bbcf19d5c47e45334ef9a75d09d
5 files changed +31 -12
Documentation/config.txt
+2
@@ -1553,11 +1553,13 @@ gc.<pattern>.reflogExpireUnreachable::
1553 gc.rerereResolved::
1554 Records of conflicted merge you resolved earlier are
1555 kept for this many days when 'git rerere gc' is run.
1556 + You can also use more human-readable "1.month.ago", etc.
1557 The default is 60 days. See linkgit:git-rerere[1].
1558
1559 gc.rerereUnresolved::
1560 Records of conflicted merge you have not resolved are
1561 kept for this many days when 'git rerere gc' is run.
1562 + You can also use more human-readable "1.month.ago", etc.
1563 The default is 15 days. See linkgit:git-rerere[1].
1564
1565 gitcvs.commitMsgAnnotation::
config.c
+22
@@ -2066,6 +2066,28 @@ int git_config_get_expiry(const char *key, const char **output)
2066 return ret;
2067 }
2068
2069 +int git_config_get_expiry_in_days(const char *key, timestamp_t *expiry, timestamp_t now)
2070 +{
2071 + char *expiry_string;
2072 + intmax_t days;
2073 + timestamp_t when;
2074 +
2075 + if (git_config_get_string(key, &expiry_string))
2076 + return 1; /* no such thing */
2077 +
2078 + if (git_parse_signed(expiry_string, &days, maximum_signed_value_of_type(int))) {
2079 + const int scale = 86400;
2080 + *expiry = now - days * scale;
2081 + return 0;
2082 + }
2083 +
2084 + if (!parse_expiry_date(expiry_string, &when)) {
2085 + *expiry = when;
2086 + return 0;
2087 + }
2088 + return -1; /* thing exists but cannot be parsed */
2089 +}
2090 +
2091 int git_config_get_untracked_cache(void)
2092 {
2093 int val = -1;
config.h
+3
@@ -205,6 +205,9 @@ extern int git_config_get_max_percent_split_change(void);
205 /* This dies if the configured or default date is in the future */
206 extern int git_config_get_expiry(const char *key, const char **output);
207
208 +/* parse either "this many days" integer, or "5.days.ago" approxidate */
209 +extern int git_config_get_expiry_in_days(const char *key, timestamp_t *, timestamp_t now);
210 +
211 struct key_value_info {
212 const char *filename;
213 int linenr;
rerere.c
+2 -12
@@ -1176,16 +1176,6 @@ static void prune_one(struct rerere_id *id,
1176 unlink_rr_item(id);
1177 }
1178
1179 -static void config_get_expiry(const char *key, timestamp_t *cutoff, timestamp_t now)
1180 -{
1181 - int days;
1182 -
1183 - if (!git_config_get_int(key, &days)) {
1184 - const int scale = 86400;
1185 - *cutoff = now - days * scale;
1186 - }
1187 -}
1188 -
1179 void rerere_gc(struct string_list *rr)
1180 {
1181 struct string_list to_remove = STRING_LIST_INIT_DUP;
@@ -1199,8 +1189,8 @@ void rerere_gc(struct string_list *rr)
1189 if (setup_rerere(rr, 0) < 0)
1190 return;
1191
1202 - config_get_expiry("gc.rerereresolved", &cutoff_resolve, now);
1203 - config_get_expiry("gc.rerereunresolved", &cutoff_noresolve, now);
1192 + git_config_get_expiry_in_days("gc.rerereresolved", &cutoff_resolve, now);
1193 + git_config_get_expiry_in_days("gc.rerereunresolved", &cutoff_noresolve, now);
1194 git_config(git_default_config, NULL);
1195 dir = opendir(git_path("rr-cache"));
1196 if (!dir)
t/t4200-rerere.sh
+2
@@ -274,6 +274,8 @@ rerere_gc_custom_expiry_test () {
274
275 rerere_gc_custom_expiry_test 5 0
276
277 +rerere_gc_custom_expiry_test 5.days.ago now
278 +
279 test_expect_success 'setup: file2 added differently in two branches' '
280 git reset --hard &&
281