Merge branch 'jk/commit-date-approxidate'
authorJunio C Hamano <gitster@pobox.com>
Tue, 3 Jun 2014 19:06:46 +0000 (12:06 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 3 Jun 2014 19:06:46 +0000 (12:06 -0700)
* jk/commit-date-approxidate:
commit: accept more date formats for "--date"
commit: print "Date" line when the user has set date
pretty: make show_ident_date public
commit: use split_ident_line to compare author/committer

1  2 
builtin/commit.c
cache.h
diff --combined builtin/commit.c
index f0b790640d63244d277495856a7019264bb75dcc,d1c90db95d3f89d8417ee8652c4eeee82982c6ed..caec5c0e186f0b2870fc9066f34425cec06283a9
@@@ -526,10 -526,29 +526,29 @@@ static int sane_ident_split(struct iden
        return 1;
  }
  
+ static int parse_force_date(const char *in, char *out, int len)
+ {
+       if (len < 1)
+               return -1;
+       *out++ = '@';
+       len--;
+       if (parse_date(in, out, len) < 0) {
+               int errors = 0;
+               unsigned long t = approxidate_careful(in, &errors);
+               if (errors)
+                       return -1;
+               snprintf(out, len, "%lu", t);
+       }
+       return 0;
+ }
  static void determine_author_info(struct strbuf *author_ident)
  {
        char *name, *email, *date;
        struct ident_split author;
+       char date_buf[64];
  
        name = getenv("GIT_AUTHOR_NAME");
        email = getenv("GIT_AUTHOR_EMAIL");
                email = xstrndup(lb + 2, rb - (lb + 2));
        }
  
-       if (force_date)
-               date = force_date;
+       if (force_date) {
+               if (parse_force_date(force_date, date_buf, sizeof(date_buf)))
+                       die(_("invalid date format: %s"), force_date);
+               date = date_buf;
+       }
        strbuf_addstr(author_ident, fmt_ident(name, email, date, IDENT_STRICT));
        if (!split_ident_line(&author, author_ident->buf, author_ident->len) &&
            sane_ident_split(&author)) {
        }
  }
  
- static char *cut_ident_timestamp_part(char *string)
+ static void split_ident_or_die(struct ident_split *id, const struct strbuf *buf)
  {
-       char *ket = strrchr(string, '>');
-       if (!ket || ket[1] != ' ')
-               die(_("Malformed ident string: '%s'"), string);
-       *++ket = '\0';
-       return ket;
+       if (split_ident_line(id, buf->buf, buf->len) ||
+           !sane_ident_split(id))
+               die(_("Malformed ident string: '%s'"), buf->buf);
+ }
+ static int author_date_is_interesting(void)
+ {
+       return author_message || force_date;
  }
  
  static int prepare_to_commit(const char *index_file, const char *prefix,
        if (use_editor && include_status) {
                int ident_shown = 0;
                int saved_color_setting;
-               char *ai_tmp, *ci_tmp;
+               struct ident_split ci, ai;
                if (whence != FROM_COMMIT) {
                        if (cleanup_mode == CLEANUP_SCISSORS)
                                wt_status_add_cut_line(s->fp);
                        status_printf_ln(s, GIT_COLOR_NORMAL,
                                        "%s", only_include_assumed);
  
-               ai_tmp = cut_ident_timestamp_part(author_ident->buf);
-               ci_tmp = cut_ident_timestamp_part(committer_ident.buf);
-               if (strcmp(author_ident->buf, committer_ident.buf))
+               split_ident_or_die(&ai, author_ident);
+               split_ident_or_die(&ci, &committer_ident);
+               if (ident_cmp(&ai, &ci))
                        status_printf_ln(s, GIT_COLOR_NORMAL,
                                _("%s"
-                               "Author:    %s"),
+                               "Author:    %.*s <%.*s>"),
                                ident_shown++ ? "" : "\n",
-                               author_ident->buf);
+                               (int)(ai.name_end - ai.name_begin), ai.name_begin,
+                               (int)(ai.mail_end - ai.mail_begin), ai.mail_begin);
+               if (author_date_is_interesting())
+                       status_printf_ln(s, GIT_COLOR_NORMAL,
+                               _("%s"
+                               "Date:      %s"),
+                               ident_shown++ ? "" : "\n",
+                               show_ident_date(&ai, DATE_NORMAL));
  
                if (!committer_ident_sufficiently_given())
                        status_printf_ln(s, GIT_COLOR_NORMAL,
                                _("%s"
-                               "Committer: %s"),
+                               "Committer: %.*s <%.*s>"),
                                ident_shown++ ? "" : "\n",
-                               committer_ident.buf);
+                               (int)(ci.name_end - ci.name_begin), ci.name_begin,
+                               (int)(ci.mail_end - ci.mail_begin), ci.mail_begin);
  
                if (ident_shown)
                        status_printf_ln(s, GIT_COLOR_NORMAL, "");
                s->use_color = 0;
                commitable = run_status(s->fp, index_file, prefix, 1, s);
                s->use_color = saved_color_setting;
-               *ai_tmp = ' ';
-               *ci_tmp = ' ';
        } else {
                unsigned char sha1[20];
                const char *parent = "HEAD";
@@@ -1356,6 -1390,13 +1390,13 @@@ static void print_summary(const char *p
                strbuf_addstr(&format, "\n Author: ");
                strbuf_addbuf_percentquote(&format, &author_ident);
        }
+       if (author_date_is_interesting()) {
+               struct strbuf date = STRBUF_INIT;
+               format_commit_message(commit, "%ad", &date, &pctx);
+               strbuf_addstr(&format, "\n Date: ");
+               strbuf_addbuf_percentquote(&format, &date);
+               strbuf_release(&date);
+       }
        if (!committer_ident_sufficiently_given()) {
                strbuf_addstr(&format, "\n Committer: ");
                strbuf_addbuf_percentquote(&format, &committer_ident);
@@@ -1672,10 -1713,6 +1713,10 @@@ int cmd_commit(int argc, const char **a
                                           ? NULL
                                           : current_head->object.sha1,
                                           0, NULL);
 +      if (!ref_lock) {
 +              rollback_index_files();
 +              die(_("cannot lock HEAD ref"));
 +      }
  
        nl = strchr(sb.buf, '\n');
        if (nl)
        strbuf_insert(&sb, 0, reflog_msg, strlen(reflog_msg));
        strbuf_insert(&sb, strlen(reflog_msg), ": ", 2);
  
 -      if (!ref_lock) {
 -              rollback_index_files();
 -              die(_("cannot lock HEAD ref"));
 -      }
        if (write_ref_sha1(ref_lock, sha1, sb.buf) < 0) {
                rollback_index_files();
                die(_("cannot update HEAD ref"));
diff --combined cache.h
index 557bd6ae812e44e88efa90511dbbd767c52e5895,dd9e689daf12491c1a1a1edee13bb8fa41a0b56c..62a4d39efcfa5f0cbf4257acfbbb9f8fdd5d2859
+++ b/cache.h
@@@ -74,21 -74,6 +74,21 @@@ unsigned long git_deflate_bound(git_zst
  #define S_IFGITLINK   0160000
  #define S_ISGITLINK(m)        (((m) & S_IFMT) == S_IFGITLINK)
  
 +/*
 + * Some mode bits are also used internally for computations.
 + *
 + * They *must* not overlap with any valid modes, and they *must* not be emitted
 + * to outside world - i.e. appear on disk or network. In other words, it's just
 + * temporary fields, which we internally use, but they have to stay in-house.
 + *
 + * ( such approach is valid, as standard S_IF* fits into 16 bits, and in Git
 + *   codebase mode is `unsigned int` which is assumed to be at least 32 bits )
 + */
 +
 +/* used internally in tree-diff */
 +#define S_DIFFTREE_IFXMIN_NEQ 0x80000000
 +
 +
  /*
   * Intensive research over the course of many years has shown that
   * port 9418 is totally unused by anything else. Or
@@@ -294,7 -279,6 +294,7 @@@ struct index_state 
                 initialized : 1;
        struct hashmap name_hash;
        struct hashmap dir_hash;
 +      unsigned char sha1[20];
  };
  
  extern struct index_state the_index;
@@@ -1061,6 -1045,13 +1061,13 @@@ struct ident_split 
   */
  extern int split_ident_line(struct ident_split *, const char *, int);
  
+ /*
+  * Like show_date, but pull the timestamp and tz parameters from
+  * the ident_split. It will also sanity-check the values and produce
+  * a well-known sentinel date if they appear bogus.
+  */
+ const char *show_ident_date(const struct ident_split *id, enum date_mode mode);
  /*
   * Compare split idents for equality or strict ordering. Note that we
   * compare only the ident part of the line, ignoring any timestamp.
@@@ -1338,8 -1329,6 +1345,8 @@@ extern void fsync_or_die(int fd, const 
  
  extern ssize_t read_in_full(int fd, void *buf, size_t count);
  extern ssize_t write_in_full(int fd, const void *buf, size_t count);
 +extern ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset);
 +
  static inline ssize_t write_str_in_full(int fd, const char *str)
  {
        return write_in_full(fd, str, strlen(str));