Merge branch 'bb/date-iso-strict'
authorJunio C Hamano <gitster@pobox.com>
Fri, 19 Sep 2014 18:38:32 +0000 (11:38 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 19 Sep 2014 18:38:32 +0000 (11:38 -0700)
"log --date=iso" uses a slight variant of ISO 8601 format that is
made more human readable. A new "--date=iso-strict" option gives
datetime output that is more strictly conformant.

* bb/date-iso-strict:
pretty: provide a strict ISO 8601 date format

1  2 
Documentation/pretty-formats.txt
builtin/blame.c
cache.h
pretty.c
t/t4205-log-pretty-formats.sh
index eac79096d3d9cb544c9e213d285b5a3158367246,50a2c3058e2f8fa1fc1eb5e17fe1fa86d12931c0..6c30723740cff5d88d3696f45e2325bc565e5f4a
@@@ -115,18 -115,20 +115,20 @@@ The placeholders are
  - '%aD': author date, RFC2822 style
  - '%ar': author date, relative
  - '%at': author date, UNIX timestamp
- - '%ai': author date, ISO 8601 format
+ - '%ai': author date, ISO 8601-like format
+ - '%aI': author date, strict ISO 8601 format
  - '%cn': committer name
  - '%cN': committer name (respecting .mailmap, see
    linkgit:git-shortlog[1] or linkgit:git-blame[1])
  - '%ce': committer email
  - '%cE': committer email (respecting .mailmap, see
    linkgit:git-shortlog[1] or linkgit:git-blame[1])
 -- '%cd': committer date
 +- '%cd': committer date (format respects --date= option)
  - '%cD': committer date, RFC2822 style
  - '%cr': committer date, relative
  - '%ct': committer date, UNIX timestamp
- - '%ci': committer date, ISO 8601 format
+ - '%ci': committer date, ISO 8601-like format
+ - '%cI': committer date, strict ISO 8601 format
  - '%d': ref names, like the --decorate option of linkgit:git-log[1]
  - '%e': encoding
  - '%s': subject
diff --combined builtin/blame.c
index ca4ba6ff15b91d9cbb6b2ce3783fa3e69d0f3ff1,01349d07f2ff4f04de4c53805ac756d852b3377d..3838be2b0274fbd72b200c2bf294e4d2842a020c
@@@ -2580,6 -2580,9 +2580,9 @@@ parse_done
        case DATE_RFC2822:
                blame_date_width = sizeof("Thu, 19 Oct 2006 16:00:04 -0700");
                break;
+       case DATE_ISO8601_STRICT:
+               blame_date_width = sizeof("2006-10-19T16:00:04-07:00");
+               break;
        case DATE_ISO8601:
                blame_date_width = sizeof("2006-10-19 16:00:04 -0700");
                break;
         * uninteresting.
         */
        if (prepare_revision_walk(&revs))
 -              die("revision walk setup failed");
 +              die(_("revision walk setup failed"));
  
        if (is_null_sha1(sb.final->object.sha1)) {
                o = sb.final->util;
diff --combined cache.h
index dfa1a5696d448b407644276df58fb24e25c57113,fa92aaf95ce803234f5ce642d2129dd368972edb..823feb87b70b205b5de25dc10e84e97d88cb6c62
+++ b/cache.h
@@@ -8,7 -8,6 +8,7 @@@
  #include "gettext.h"
  #include "convert.h"
  #include "trace.h"
 +#include "string-list.h"
  
  #include SHA1_HEADER
  #ifndef git_SHA_CTX
@@@ -586,7 -585,6 +586,7 @@@ extern NORETURN void unable_to_lock_ind
  extern int hold_lock_file_for_update(struct lock_file *, const char *path, int);
  extern int hold_lock_file_for_append(struct lock_file *, const char *path, int);
  extern int commit_lock_file(struct lock_file *);
 +extern int reopen_lock_file(struct lock_file *);
  extern void update_index_if_able(struct index_state *, struct lock_file *);
  
  extern int hold_locked_index(struct lock_file *, int);
@@@ -1039,6 -1037,7 +1039,7 @@@ enum date_mode 
        DATE_SHORT,
        DATE_LOCAL,
        DATE_ISO8601,
+       DATE_ISO8601_STRICT,
        DATE_RFC2822,
        DATE_RAW
  };
@@@ -1063,7 -1062,6 +1064,7 @@@ extern const char *git_author_info(int)
  extern const char *git_committer_info(int);
  extern const char *fmt_ident(const char *name, const char *email, const char *date_str, int);
  extern const char *fmt_name(const char *name, const char *email);
 +extern const char *ident_default_name(void);
  extern const char *ident_default_email(void);
  extern const char *git_editor(void);
  extern const char *git_pager(int stdout_is_tty);
@@@ -1297,7 -1295,7 +1298,7 @@@ extern int git_config_from_buf(config_f
                               const char *buf, size_t len, void *data);
  extern void git_config_push_parameter(const char *text);
  extern int git_config_from_parameters(config_fn_t fn, void *data);
 -extern int git_config(config_fn_t fn, void *);
 +extern void git_config(config_fn_t fn, void *);
  extern int git_config_with_options(config_fn_t fn, void *,
                                   struct git_config_source *config_source,
                                   int respect_includes);
@@@ -1354,69 -1352,6 +1355,69 @@@ extern int parse_config_key(const char 
                            const char **subsection, int *subsection_len,
                            const char **key);
  
 +struct config_set_element {
 +      struct hashmap_entry ent;
 +      char *key;
 +      struct string_list value_list;
 +};
 +
 +struct configset_list_item {
 +      struct config_set_element *e;
 +      int value_index;
 +};
 +
 +/*
 + * the contents of the list are ordered according to their
 + * position in the config files and order of parsing the files.
 + * (i.e. key-value pair at the last position of .git/config will
 + * be at the last item of the list)
 + */
 +struct configset_list {
 +      struct configset_list_item *items;
 +      unsigned int nr, alloc;
 +};
 +
 +struct config_set {
 +      struct hashmap config_hash;
 +      int hash_initialized;
 +      struct configset_list list;
 +};
 +
 +extern void git_configset_init(struct config_set *cs);
 +extern int git_configset_add_file(struct config_set *cs, const char *filename);
 +extern int git_configset_get_value(struct config_set *cs, const char *key, const char **value);
 +extern const struct string_list *git_configset_get_value_multi(struct config_set *cs, const char *key);
 +extern void git_configset_clear(struct config_set *cs);
 +extern int git_configset_get_string_const(struct config_set *cs, const char *key, const char **dest);
 +extern int git_configset_get_string(struct config_set *cs, const char *key, char **dest);
 +extern int git_configset_get_int(struct config_set *cs, const char *key, int *dest);
 +extern int git_configset_get_ulong(struct config_set *cs, const char *key, unsigned long *dest);
 +extern int git_configset_get_bool(struct config_set *cs, const char *key, int *dest);
 +extern int git_configset_get_bool_or_int(struct config_set *cs, const char *key, int *is_bool, int *dest);
 +extern int git_configset_get_maybe_bool(struct config_set *cs, const char *key, int *dest);
 +extern int git_configset_get_pathname(struct config_set *cs, const char *key, const char **dest);
 +
 +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);
 +extern void git_config_iter(config_fn_t fn, void *data);
 +extern int git_config_get_string_const(const char *key, const char **dest);
 +extern int git_config_get_string(const char *key, char **dest);
 +extern int git_config_get_int(const char *key, int *dest);
 +extern int git_config_get_ulong(const char *key, unsigned long *dest);
 +extern int git_config_get_bool(const char *key, int *dest);
 +extern int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest);
 +extern int git_config_get_maybe_bool(const char *key, int *dest);
 +extern int git_config_get_pathname(const char *key, const char **dest);
 +
 +struct key_value_info {
 +      const char *filename;
 +      int linenr;
 +};
 +
 +extern NORETURN void git_die_config(const char *key, const char *err, ...) __attribute__((format(printf, 2, 3)));
 +extern NORETURN void git_die_config_linenr(const char *key, const char *filename, int linenr);
 +
  extern int committer_ident_sufficiently_given(void);
  extern int author_ident_sufficiently_given(void);
  
diff --combined pretty.c
index 44b9f643725c68325a9caf92dff819e22e38e3ad,7dd5601e64873d71651260aa099594f47df7433d..5f012a6b8ed6cdf345b350e3fa2f6b821ceebd7d
+++ b/pretty.c
@@@ -24,11 -24,6 +24,11 @@@ static size_t commit_formats_len
  static size_t commit_formats_alloc;
  static struct cmt_fmt_map *find_commit_format(const char *sought);
  
 +int commit_format_is_empty(enum cmit_fmt fmt)
 +{
 +      return fmt == CMIT_FMT_USERFORMAT && !*user_format;
 +}
 +
  static void save_user_format(struct rev_info *rev, const char *cp, int is_tformat)
  {
        free(user_format);
@@@ -70,9 -65,7 +70,9 @@@ static int git_pretty_formats_config(co
  
        commit_format->name = xstrdup(name);
        commit_format->format = CMIT_FMT_USERFORMAT;
 -      git_config_string(&fmt, var, value);
 +      if (git_config_string(&fmt, var, value))
 +              return -1;
 +
        if (starts_with(fmt, "format:") || starts_with(fmt, "tformat:")) {
                commit_format->is_tformat = fmt[0] == 't';
                fmt = strchr(fmt, ':') + 1;
@@@ -153,7 -146,7 +153,7 @@@ void get_commit_format(const char *arg
        struct cmt_fmt_map *commit_format;
  
        rev->use_terminator = 0;
 -      if (!arg || !*arg) {
 +      if (!arg) {
                rev->commit_format = CMIT_FMT_DEFAULT;
                return;
        }
                return;
        }
  
 -      if (strchr(arg, '%')) {
 +      if (!*arg || strchr(arg, '%')) {
                save_user_format(rev, arg, 1);
                return;
        }
@@@ -738,9 -731,12 +738,12 @@@ static size_t format_person_part(struc
        case 'r':       /* date, relative */
                strbuf_addstr(sb, show_ident_date(&s, DATE_RELATIVE));
                return placeholder_len;
-       case 'i':       /* date, ISO 8601 */
+       case 'i':       /* date, ISO 8601-like */
                strbuf_addstr(sb, show_ident_date(&s, DATE_ISO8601));
                return placeholder_len;
+       case 'I':       /* date, ISO 8601 strict */
+               strbuf_addstr(sb, show_ident_date(&s, DATE_ISO8601_STRICT));
+               return placeholder_len;
        }
  
  skip:
index de0cc4a0fd5fe37bb36a3268182d95de3589f4b4,f2f748399d4b3066ef3cf16ae28ec99e698e1d72..9b75399572b1cbe1bfcb00995e1660a93fe6a4c6
@@@ -431,13 -431,14 +431,21 @@@ EO
        test_cmp expected actual
  '
  
 +test_expect_success 'strbuf_utf8_replace() not producing NUL' '
 +      git log --color --pretty="tformat:%<(10,trunc)%s%>>(10,ltrunc)%C(auto)%d" |
 +              test_decode_color |
 +              nul_to_q >actual &&
 +      ! grep Q actual
 +'
 +
+ # ISO strict date format
+ test_expect_success 'ISO and ISO-strict date formats display the same values' '
+       git log --format=%ai%n%ci |
+       sed -e "s/ /T/; s/ //; s/..\$/:&/" >expected &&
+       git log --format=%aI%n%cI >actual &&
+       test_cmp expected actual
+ '
  # get new digests (with no abbreviations)
  head1=$(git rev-parse --verify HEAD~0) &&
  head2=$(git rev-parse --verify HEAD~1) &&