Merge branch 'jc/cutoff-config'
authorJunio C Hamano <gitster@pobox.com>
Sun, 27 Aug 2017 05:55:08 +0000 (22:55 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sun, 27 Aug 2017 05:55:08 +0000 (22:55 -0700)
"[gc] rerereResolved = 5.days" used to be invalid, as the variable
is defined to take an integer counting the number of days. It now
is allowed.

* jc/cutoff-config:
rerere: allow approxidate in gc.rerereResolved/gc.rerereUnresolved
rerere: represent time duration in timestamp_t internally
t4200: parameterize "rerere gc" custom expiry test
t4200: gather "rerere gc" together
t4200: make "rerere gc" test more robust
t4200: give us a clean slate after "rerere gc" tests

1  2 
Documentation/config.txt
config.c
config.h
diff --combined Documentation/config.txt
index 602c6bef68a6b724d43b65003603ff62a4d21acd,ac95f5f954145c22fa123bf376ed7200b87d005a..9b42e0ca73429d01f987b2b93c413ab49a98fef4
@@@ -216,15 -216,15 +216,15 @@@ boolean:
         synonyms are accepted for 'true' and 'false'; these are all
         case-insensitive.
  
 -       true;; Boolean true can be spelled as `yes`, `on`, `true`,
 -              or `1`.  Also, a variable defined without `= <value>`
 +      true;; Boolean true literals are `yes`, `on`, `true`,
 +              and `1`.  Also, a variable defined without `= <value>`
                is taken as true.
  
 -       false;; Boolean false can be spelled as `no`, `off`,
 -              `false`, or `0`.
 +      false;; Boolean false literals are `no`, `off`, `false`,
 +              `0` and the empty string.
  +
  When converting value to the canonical form using `--bool` type
 -specifier; 'git config' will ensure that the output is "true" or
 +specifier, 'git config' will ensure that the output is "true" or
  "false" (spelled in lowercase).
  
  integer::
@@@ -1077,25 -1077,14 +1077,25 @@@ This does not affect linkgit:git-format
  'git-diff-{asterisk}' plumbing commands.  Can be overridden on the
  command line with the `--color[=<when>]` option.
  
 +diff.colorMoved::
 +      If set to either a valid `<mode>` or a true value, moved lines
 +      in a diff are colored differently, for details of valid modes
 +      see '--color-moved' in linkgit:git-diff[1]. If simply set to
 +      true the default color mode will be used. When set to false,
 +      moved lines are not colored.
 +
  color.diff.<slot>::
        Use customized color for diff colorization.  `<slot>` specifies
        which part of the patch to use the specified color, and is one
        of `context` (context text - `plain` is a historical synonym),
        `meta` (metainformation), `frag`
        (hunk header), 'func' (function in hunk header), `old` (removed lines),
 -      `new` (added lines), `commit` (commit headers), or `whitespace`
 -      (highlighting whitespace errors).
 +      `new` (added lines), `commit` (commit headers), `whitespace`
 +      (highlighting whitespace errors), `oldMoved` (deleted lines),
 +      `newMoved` (added lines), `oldMovedDimmed`, `oldMovedAlternative`,
 +      `oldMovedAlternativeDimmed`, `newMovedDimmed`, `newMovedAlternative`
 +      and `newMovedAlternativeDimmed` (See the '<mode>'
 +      setting of '--color-moved' in linkgit:git-diff[1] for details).
  
  color.decorate.<slot>::
        Use customized color for 'git log --decorate' output.  `<slot>` is one
@@@ -1564,11 -1553,13 +1564,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::
@@@ -2923,8 -2914,8 +2925,8 @@@ sendemail.smtpsslcertpath:
  
  sendemail.<identity>.*::
        Identity-specific versions of the 'sendemail.*' parameters
 -      found below, taking precedence over those when the this
 -      identity is selected, through command-line or
 +      found below, taking precedence over those when this
 +      identity is selected, through either the command-line or
        `sendemail.identity`.
  
  sendemail.aliasesFile::
diff --combined config.c
index 777527daef8a292ec6a3589319c5d84593b3d487,ffca15f594e8c7f709f0d0875bfc6c7033e2a16a..d0d8ce823ae6d8be4b9cc92e1d01e44ca7569e84
+++ b/config.c
@@@ -16,7 -16,6 +16,7 @@@
  #include "string-list.h"
  #include "utf8.h"
  #include "dir.h"
 +#include "color.h"
  
  struct config_source {
        struct config_source *prev;
@@@ -929,7 -928,7 +929,7 @@@ ssize_t git_config_ssize_t(const char *
        return ret;
  }
  
 -int git_parse_maybe_bool(const char *value)
 +static int git_parse_maybe_bool_text(const char *value)
  {
        if (!value)
                return 1;
        return -1;
  }
  
 -int git_config_maybe_bool(const char *name, const char *value)
 +int git_parse_maybe_bool(const char *value)
  {
 -      int v = git_parse_maybe_bool(value);
 +      int v = git_parse_maybe_bool_text(value);
        if (0 <= v)
                return v;
        if (git_parse_int(value, &v))
        return -1;
  }
  
 +int git_config_maybe_bool(const char *name, const char *value)
 +{
 +      return git_parse_maybe_bool(value);
 +}
 +
  int git_config_bool_or_int(const char *name, const char *value, int *is_bool)
  {
 -      int v = git_parse_maybe_bool(value);
 +      int v = git_parse_maybe_bool_text(value);
        if (0 <= v) {
                *is_bool = 1;
                return v;
@@@ -1356,9 -1350,6 +1356,9 @@@ int git_default_config(const char *var
        if (starts_with(var, "advice."))
                return git_default_advice_config(var, value);
  
 +      if (git_color_config(var, value, dummy) < 0)
 +              return -1;
 +
        if (!strcmp(var, "pager.color") || !strcmp(var, "color.pager")) {
                pager_use_color = git_config_bool(var,value);
                return 0;
@@@ -1469,9 -1460,9 +1469,9 @@@ int git_config_from_mem(config_fn_t fn
        return do_config_from(&top, fn, data);
  }
  
 -int git_config_from_blob_sha1(config_fn_t fn,
 +int git_config_from_blob_oid(config_fn_t fn,
                              const char *name,
 -                            const unsigned char *sha1,
 +                            const struct object_id *oid,
                              void *data)
  {
        enum object_type type;
        unsigned long size;
        int ret;
  
 -      buf = read_sha1_file(sha1, &type, &size);
 +      buf = read_sha1_file(oid->hash, &type, &size);
        if (!buf)
                return error("unable to load config blob object '%s'", name);
        if (type != OBJ_BLOB) {
@@@ -1497,11 -1488,11 +1497,11 @@@ static int git_config_from_blob_ref(con
                                    const char *name,
                                    void *data)
  {
 -      unsigned char sha1[20];
 +      struct object_id oid;
  
 -      if (get_sha1(name, sha1) < 0)
 +      if (get_oid(name, &oid) < 0)
                return error("unable to resolve config blob '%s'", name);
 -      return git_config_from_blob_sha1(fn, name, sha1, data);
 +      return git_config_from_blob_oid(fn, name, &oid, data);
  }
  
  const char *git_etc_gitconfig(void)
@@@ -1724,19 -1715,17 +1724,19 @@@ static int configset_add_value(struct c
  }
  
  static int config_set_element_cmp(const void *unused_cmp_data,
 -                                const struct config_set_element *e1,
 -                                const struct config_set_element *e2,
 +                                const void *entry,
 +                                const void *entry_or_key,
                                  const void *unused_keydata)
  {
 +      const struct config_set_element *e1 = entry;
 +      const struct config_set_element *e2 = entry_or_key;
 +
        return strcmp(e1->key, e2->key);
  }
  
  void git_configset_init(struct config_set *cs)
  {
 -      hashmap_init(&cs->config_hash, (hashmap_cmp_fn)config_set_element_cmp,
 -                   NULL, 0);
 +      hashmap_init(&cs->config_hash, config_set_element_cmp, NULL, 0);
        cs->hash_initialized = 1;
        cs->list.nr = 0;
        cs->list.alloc = 0;
@@@ -1857,7 -1846,7 +1857,7 @@@ int git_configset_get_maybe_bool(struc
  {
        const char *value;
        if (!git_configset_get_value(cs, key, &value)) {
 -              *dest = git_config_maybe_bool(key, value);
 +              *dest = git_parse_maybe_bool(value);
                if (*dest == -1)
                        return -1;
                return 0;
@@@ -2064,23 -2053,6 +2064,23 @@@ int git_config_get_pathname(const char 
        return repo_config_get_pathname(the_repository, key, dest);
  }
  
 +/*
 + * Note: This function exists solely to maintain backward compatibility with
 + * 'fetch' and 'update_clone' storing configuration in '.gitmodules' and should
 + * NOT be used anywhere else.
 + *
 + * Runs the provided config function on the '.gitmodules' file found in the
 + * working directory.
 + */
 +void config_from_gitmodules(config_fn_t fn, void *data)
 +{
 +      if (the_repository->worktree) {
 +              char *file = repo_worktree_path(the_repository, GITMODULES_FILE);
 +              git_config_from_file(fn, file, data);
 +              free(file);
 +      }
 +}
 +
  int git_config_get_expiry(const char *key, const char **output)
  {
        int ret = git_config_get_string_const(key, 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;
diff --combined config.h
index 18b6f3f724bd823bf98f039e4699b0c2c5dc5393,34ddd3eb8d6634581db5cd4e33ca2104720a7931..97471b887320b48f1b4c2d5a2023f6ffd1acf94e
+++ b/config.h
@@@ -39,8 -39,8 +39,8 @@@ extern int git_default_config(const cha
  extern int git_config_from_file(config_fn_t fn, const char *, void *);
  extern int git_config_from_mem(config_fn_t fn, const enum config_origin_type,
                                        const char *name, const char *buf, size_t len, void *data);
 -extern int git_config_from_blob_sha1(config_fn_t fn, const char *name,
 -                                   const unsigned char *sha1, void *data);
 +extern int git_config_from_blob_oid(config_fn_t fn, const char *name,
 +                                  const struct object_id *oid, void *data);
  extern void git_config_push_parameter(const char *text);
  extern int git_config_from_parameters(config_fn_t fn, void *data);
  extern void read_early_config(config_fn_t cb, void *data);
@@@ -187,16 -187,6 +187,16 @@@ extern int repo_config_get_maybe_bool(s
  extern int repo_config_get_pathname(struct repository *repo,
                                    const char *key, const char **dest);
  
 +/*
 + * Note: This function exists solely to maintain backward compatibility with
 + * 'fetch' and 'update_clone' storing configuration in '.gitmodules' and should
 + * NOT be used anywhere else.
 + *
 + * Runs the provided config function on the '.gitmodules' file found in the
 + * working directory.
 + */
 +extern void config_from_gitmodules(config_fn_t fn, void *data);
 +
  extern int git_config_get_value(const char *key, const char **value);
  extern const struct string_list *git_config_get_value_multi(const char *key);
  extern void git_config_clear(void);
@@@ -215,6 -205,9 +215,9 @@@ extern int git_config_get_max_percent_s
  /* 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;