rerere: allow approxidate in gc.rerereResolved/gc.rerereUnresolved
authorJunio C Hamano <gitster@pobox.com>
Sat, 19 Aug 2017 18:43:39 +0000 (11:43 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 22 Aug 2017 21:51:02 +0000 (14:51 -0700)
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>
Documentation/config.txt
config.c
config.h
rerere.c
t/t4200-rerere.sh
index d5c9c4cab60531d178d5c11d623a5c3f1036a0d0..ac95f5f954145c22fa123bf376ed7200b87d005a 100644 (file)
@@ -1553,11 +1553,13 @@ gc.<pattern>.reflogExpireUnreachable::
 gc.rerereResolved::
        Records of conflicted merge you resolved earlier are
        kept for this many days when 'git rerere gc' is run.
+       You can also use more human-readable "1.month.ago", etc.
        The default is 60 days.  See linkgit:git-rerere[1].
 
 gc.rerereUnresolved::
        Records of conflicted merge you have not resolved are
        kept for this many days when 'git rerere gc' is run.
+       You can also use more human-readable "1.month.ago", etc.
        The default is 15 days.  See linkgit:git-rerere[1].
 
 gitcvs.commitMsgAnnotation::
index 231f9a750b96deda8d62f5a5debb384f40481566..ffca15f594e8c7f709f0d0875bfc6c7033e2a16a 100644 (file)
--- a/config.c
+++ b/config.c
@@ -2066,6 +2066,28 @@ int git_config_get_expiry(const char *key, const char **output)
        return ret;
 }
 
+int git_config_get_expiry_in_days(const char *key, timestamp_t *expiry, timestamp_t now)
+{
+       char *expiry_string;
+       intmax_t days;
+       timestamp_t when;
+
+       if (git_config_get_string(key, &expiry_string))
+               return 1; /* no such thing */
+
+       if (git_parse_signed(expiry_string, &days, maximum_signed_value_of_type(int))) {
+               const int scale = 86400;
+               *expiry = now - days * scale;
+               return 0;
+       }
+
+       if (!parse_expiry_date(expiry_string, &when)) {
+               *expiry = when;
+               return 0;
+       }
+       return -1; /* thing exists but cannot be parsed */
+}
+
 int git_config_get_untracked_cache(void)
 {
        int val = -1;
index 0352da117b9a61498311da5a5b5fdf5e14af8b58..34ddd3eb8d6634581db5cd4e33ca2104720a7931 100644 (file)
--- a/config.h
+++ b/config.h
@@ -205,6 +205,9 @@ extern int git_config_get_max_percent_split_change(void);
 /* This dies if the configured or default date is in the future */
 extern int git_config_get_expiry(const char *key, const char **output);
 
+/* parse either "this many days" integer, or "5.days.ago" approxidate */
+extern int git_config_get_expiry_in_days(const char *key, timestamp_t *, timestamp_t now);
+
 struct key_value_info {
        const char *filename;
        int linenr;
index f0b4bce881963b8e757354f8a022d09e239dcc81..d77235645ea88ff9a51346436fcaac69dabfaaeb 100644 (file)
--- a/rerere.c
+++ b/rerere.c
@@ -1176,16 +1176,6 @@ static void prune_one(struct rerere_id *id,
                unlink_rr_item(id);
 }
 
-static void config_get_expiry(const char *key, timestamp_t *cutoff, timestamp_t now)
-{
-       int days;
-
-       if (!git_config_get_int(key, &days)) {
-               const int scale = 86400;
-               *cutoff = now - days * scale;
-       }
-}
-
 void rerere_gc(struct string_list *rr)
 {
        struct string_list to_remove = STRING_LIST_INIT_DUP;
@@ -1199,8 +1189,8 @@ void rerere_gc(struct string_list *rr)
        if (setup_rerere(rr, 0) < 0)
                return;
 
-       config_get_expiry("gc.rerereresolved", &cutoff_resolve, now);
-       config_get_expiry("gc.rerereunresolved", &cutoff_noresolve, now);
+       git_config_get_expiry_in_days("gc.rerereresolved", &cutoff_resolve, now);
+       git_config_get_expiry_in_days("gc.rerereunresolved", &cutoff_noresolve, now);
        git_config(git_default_config, NULL);
        dir = opendir(git_path("rr-cache"));
        if (!dir)
index 8d437534f2528cc29f819a7b312004a327d66906..d97d2bebc9850c8ba96a8263ed081fced2ecc153 100755 (executable)
@@ -274,6 +274,8 @@ rerere_gc_custom_expiry_test () {
 
 rerere_gc_custom_expiry_test 5 0
 
+rerere_gc_custom_expiry_test 5.days.ago now
+
 test_expect_success 'setup: file2 added differently in two branches' '
        git reset --hard &&