Merge branch 'ab/strbuf-addftime-tzname-boolify'
authorJunio C Hamano <gitster@pobox.com>
Fri, 7 Jul 2017 01:14:47 +0000 (18:14 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 7 Jul 2017 01:14:47 +0000 (18:14 -0700)
strbuf_addftime() is further getting tweaked.

* ab/strbuf-addftime-tzname-boolify:
strbuf: change an always NULL/"" strbuf_addftime() param to bool
strbuf.h comment: discuss strbuf_addftime() arguments in order

1  2 
date.c
strbuf.c
strbuf.h
diff --combined date.c
index 1fd6d663758de5a4b9d7f395b16716864317ed84,8aca1363962821f8d42b42883f8756fbcd0d5aed..c3e673fd04221bb444e357ac01a1fe5984375daf
--- 1/date.c
--- 2/date.c
+++ b/date.c
@@@ -39,24 -39,14 +39,24 @@@ static const char *weekday_names[] = 
        "Sundays", "Mondays", "Tuesdays", "Wednesdays", "Thursdays", "Fridays", "Saturdays"
  };
  
 -static time_t gm_time_t(unsigned long time, int tz)
 +static time_t gm_time_t(timestamp_t time, int tz)
  {
        int minutes;
  
        minutes = tz < 0 ? -tz : tz;
        minutes = (minutes / 100)*60 + (minutes % 100);
        minutes = tz < 0 ? -minutes : minutes;
 -      return time + minutes * 60;
 +
 +      if (minutes > 0) {
 +              if (unsigned_add_overflows(time, minutes * 60))
 +                      die("Timestamp+tz too large: %"PRItime" +%04d",
 +                          time, tz);
 +      } else if (time < -minutes * 60)
 +              die("Timestamp before Unix epoch: %"PRItime" %04d", time, tz);
 +      time += minutes * 60;
 +      if (date_overflows(time))
 +              die("Timestamp too large for this system: %"PRItime, time);
 +      return (time_t)time;
  }
  
  /*
   * thing, which means that tz -0100 is passed in as the integer -100,
   * even though it means "sixty minutes off"
   */
 -static struct tm *time_to_tm(unsigned long time, int tz)
 +static struct tm *time_to_tm(timestamp_t time, int tz)
  {
        time_t t = gm_time_t(time, tz);
        return gmtime(&t);
  }
  
 -static struct tm *time_to_tm_local(unsigned long time)
 +static struct tm *time_to_tm_local(timestamp_t time)
  {
        time_t t = time;
        return localtime(&t);
   * What value of "tz" was in effect back then at "time" in the
   * local timezone?
   */
 -static int local_tzoffset(unsigned long time)
 +static int local_tzoffset(timestamp_t time)
  {
        time_t t, t_local;
        struct tm tm;
        int offset, eastwest;
  
 -      t = time;
 +      if (date_overflows(time))
 +              die("Timestamp too large for this system: %"PRItime, time);
 +
 +      t = (time_t)time;
        localtime_r(&t, &tm);
        t_local = tm_to_time_t(&tm);
  
        return offset * eastwest;
  }
  
 -void show_date_relative(unsigned long time, int tz,
 +void show_date_relative(timestamp_t time, int tz,
                               const struct timeval *now,
                               struct strbuf *timebuf)
  {
 -      unsigned long diff;
 +      timestamp_t diff;
        if (now->tv_sec < time) {
                strbuf_addstr(timebuf, _("in the future"));
                return;
        diff = now->tv_sec - time;
        if (diff < 90) {
                strbuf_addf(timebuf,
 -                       Q_("%lu second ago", "%lu seconds ago", diff), diff);
 +                       Q_("%"PRItime" second ago", "%"PRItime" seconds ago", diff), diff);
                return;
        }
        /* Turn it into minutes */
        diff = (diff + 30) / 60;
        if (diff < 90) {
                strbuf_addf(timebuf,
 -                       Q_("%lu minute ago", "%lu minutes ago", diff), diff);
 +                       Q_("%"PRItime" minute ago", "%"PRItime" minutes ago", diff), diff);
                return;
        }
        /* Turn it into hours */
        diff = (diff + 30) / 60;
        if (diff < 36) {
                strbuf_addf(timebuf,
 -                       Q_("%lu hour ago", "%lu hours ago", diff), diff);
 +                       Q_("%"PRItime" hour ago", "%"PRItime" hours ago", diff), diff);
                return;
        }
        /* We deal with number of days from here on */
        diff = (diff + 12) / 24;
        if (diff < 14) {
                strbuf_addf(timebuf,
 -                       Q_("%lu day ago", "%lu days ago", diff), diff);
 +                       Q_("%"PRItime" day ago", "%"PRItime" days ago", diff), diff);
                return;
        }
        /* Say weeks for the past 10 weeks or so */
        if (diff < 70) {
                strbuf_addf(timebuf,
 -                       Q_("%lu week ago", "%lu weeks ago", (diff + 3) / 7),
 +                       Q_("%"PRItime" week ago", "%"PRItime" weeks ago", (diff + 3) / 7),
                         (diff + 3) / 7);
                return;
        }
        /* Say months for the past 12 months or so */
        if (diff < 365) {
                strbuf_addf(timebuf,
 -                       Q_("%lu month ago", "%lu months ago", (diff + 15) / 30),
 +                       Q_("%"PRItime" month ago", "%"PRItime" months ago", (diff + 15) / 30),
                         (diff + 15) / 30);
                return;
        }
        /* Give years and months for 5 years or so */
        if (diff < 1825) {
 -              unsigned long totalmonths = (diff * 12 * 2 + 365) / (365 * 2);
 -              unsigned long years = totalmonths / 12;
 -              unsigned long months = totalmonths % 12;
 +              timestamp_t totalmonths = (diff * 12 * 2 + 365) / (365 * 2);
 +              timestamp_t years = totalmonths / 12;
 +              timestamp_t months = totalmonths % 12;
                if (months) {
                        struct strbuf sb = STRBUF_INIT;
 -                      strbuf_addf(&sb, Q_("%lu year", "%lu years", years), years);
 +                      strbuf_addf(&sb, Q_("%"PRItime" year", "%"PRItime" years", years), years);
                        strbuf_addf(timebuf,
                                 /* TRANSLATORS: "%s" is "<n> years" */
 -                               Q_("%s, %lu month ago", "%s, %lu months ago", months),
 +                               Q_("%s, %"PRItime" month ago", "%s, %"PRItime" months ago", months),
                                 sb.buf, months);
                        strbuf_release(&sb);
                } else
                        strbuf_addf(timebuf,
 -                               Q_("%lu year ago", "%lu years ago", years), years);
 +                               Q_("%"PRItime" year ago", "%"PRItime" years ago", years), years);
                return;
        }
        /* Otherwise, just years. Centuries is probably overkill. */
        strbuf_addf(timebuf,
 -               Q_("%lu year ago", "%lu years ago", (diff + 183) / 365),
 +               Q_("%"PRItime" year ago", "%"PRItime" years ago", (diff + 183) / 365),
                 (diff + 183) / 365);
  }
  
@@@ -191,14 -178,14 +191,14 @@@ struct date_mode *date_mode_from_type(e
        return &mode;
  }
  
 -const char *show_date(unsigned long time, int tz, const struct date_mode *mode)
 +const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)
  {
        struct tm *tm;
        static struct strbuf timebuf = STRBUF_INIT;
  
        if (mode->type == DATE_UNIX) {
                strbuf_reset(&timebuf);
 -              strbuf_addf(&timebuf, "%lu", time);
 +              strbuf_addf(&timebuf, "%"PRItime, time);
                return timebuf.buf;
        }
  
  
        if (mode->type == DATE_RAW) {
                strbuf_reset(&timebuf);
 -              strbuf_addf(&timebuf, "%lu %+05d", time, tz);
 +              strbuf_addf(&timebuf, "%"PRItime" %+05d", time, tz);
                return timebuf.buf;
        }
  
                        tm->tm_hour, tm->tm_min, tm->tm_sec, tz);
        else if (mode->type == DATE_STRFTIME)
                strbuf_addftime(&timebuf, mode->strftime_fmt, tm, tz,
-                               mode->local ? NULL : "");
+                               !mode->local);
        else
                strbuf_addf(&timebuf, "%.3s %.3s %d %02d:%02d:%02d %d%c%+05d",
                                weekday_names[tm->tm_wday],
@@@ -448,7 -435,7 +448,7 @@@ static int is_date(int year, int month
        return 0;
  }
  
 -static int match_multi_number(unsigned long num, char c, const char *date,
 +static int match_multi_number(timestamp_t num, char c, const char *date,
                              char *end, struct tm *tm, time_t now)
  {
        struct tm now_tm;
@@@ -531,9 -518,9 +531,9 @@@ static int match_digit(const char *date
  {
        int n;
        char *end;
 -      unsigned long num;
 +      timestamp_t num;
  
 -      num = strtoul(date, &end, 10);
 +      num = parse_timestamp(date, &end, 10);
  
        /*
         * Seconds since 1970? We trigger on that for any numbers with
@@@ -658,7 -645,7 +658,7 @@@ static int match_tz(const char *date, i
        return end - date;
  }
  
 -static void date_string(unsigned long date, int offset, struct strbuf *buf)
 +static void date_string(timestamp_t date, int offset, struct strbuf *buf)
  {
        int sign = '+';
  
                offset = -offset;
                sign = '-';
        }
 -      strbuf_addf(buf, "%lu %c%02d%02d", date, sign, offset / 60, offset % 60);
 +      strbuf_addf(buf, "%"PRItime" %c%02d%02d", date, sign, offset / 60, offset % 60);
  }
  
  /*
   * Parse a string like "0 +0000" as ancient timestamp near epoch, but
   * only when it appears not as part of any other string.
   */
 -static int match_object_header_date(const char *date, unsigned long *timestamp, int *offset)
 +static int match_object_header_date(const char *date, timestamp_t *timestamp, int *offset)
  {
        char *end;
 -      unsigned long stamp;
 +      timestamp_t stamp;
        int ofs;
  
        if (*date < '0' || '9' < *date)
                return -1;
 -      stamp = strtoul(date, &end, 10);
 -      if (*end != ' ' || stamp == ULONG_MAX || (end[1] != '+' && end[1] != '-'))
 +      stamp = parse_timestamp(date, &end, 10);
 +      if (*end != ' ' || stamp == TIME_MAX || (end[1] != '+' && end[1] != '-'))
                return -1;
        date = end + 2;
        ofs = strtol(date, &end, 10);
  
  /* Gr. strptime is crap for this; it doesn't have a way to require RFC2822
     (i.e. English) day/month names, and it doesn't work correctly with %z. */
 -int parse_date_basic(const char *date, unsigned long *timestamp, int *offset)
 +int parse_date_basic(const char *date, timestamp_t *timestamp, int *offset)
  {
        struct tm tm;
        int tm_gmt;
 -      unsigned long dummy_timestamp;
 +      timestamp_t dummy_timestamp;
        int dummy_offset;
  
        if (!timestamp)
        return 0; /* success */
  }
  
 -int parse_expiry_date(const char *date, unsigned long *timestamp)
 +int parse_expiry_date(const char *date, timestamp_t *timestamp)
  {
        int errors = 0;
  
                 * of the past, and there is nothing from the future
                 * to be kept.
                 */
 -              *timestamp = ULONG_MAX;
 +              *timestamp = TIME_MAX;
        else
                *timestamp = approxidate_careful(date, &errors);
  
  
  int parse_date(const char *date, struct strbuf *result)
  {
 -      unsigned long timestamp;
 +      timestamp_t timestamp;
        int offset;
        if (parse_date_basic(date, &timestamp, &offset))
                return -1;
@@@ -868,7 -855,7 +868,7 @@@ void datestamp(struct strbuf *out
   * Relative time update (eg "2 days ago").  If we haven't set the time
   * yet, we need to set it from current time.
   */
 -static unsigned long update_tm(struct tm *tm, struct tm *now, unsigned long sec)
 +static time_t update_tm(struct tm *tm, struct tm *now, time_t sec)
  {
        time_t n;
  
@@@ -1089,7 -1076,7 +1089,7 @@@ static const char *approxidate_digit(co
                                     time_t now)
  {
        char *end;
 -      unsigned long number = strtoul(date, &end, 10);
 +      timestamp_t number = parse_timestamp(date, &end, 10);
  
        switch (*end) {
        case ':':
@@@ -1137,9 -1124,9 +1137,9 @@@ static void pending_number(struct tm *t
        }
  }
  
 -static unsigned long approxidate_str(const char *date,
 -                                   const struct timeval *tv,
 -                                   int *error_ret)
 +static timestamp_t approxidate_str(const char *date,
 +                                 const struct timeval *tv,
 +                                 int *error_ret)
  {
        int number = 0;
        int touched = 0;
        pending_number(&tm, &number);
        if (!touched)
                *error_ret = 1;
 -      return update_tm(&tm, &now, 0);
 +      return (timestamp_t)update_tm(&tm, &now, 0);
  }
  
 -unsigned long approxidate_relative(const char *date, const struct timeval *tv)
 +timestamp_t approxidate_relative(const char *date, const struct timeval *tv)
  {
 -      unsigned long timestamp;
 +      timestamp_t timestamp;
        int offset;
        int errors = 0;
  
        return approxidate_str(date, tv, &errors);
  }
  
 -unsigned long approxidate_careful(const char *date, int *error_ret)
 +timestamp_t approxidate_careful(const char *date, int *error_ret)
  {
        struct timeval tv;
 -      unsigned long timestamp;
 +      timestamp_t timestamp;
        int offset;
        int dummy = 0;
        if (!error_ret)
        return approxidate_str(date, &tv, error_ret);
  }
  
 -int date_overflows(unsigned long t)
 +int date_overflows(timestamp_t t)
  {
        time_t sys;
  
 -      /* If we overflowed our unsigned long, that's bad... */
 -      if (t == ULONG_MAX)
 +      /* If we overflowed our timestamp data type, that's bad... */
 +      if ((uintmax_t)t >= TIME_MAX)
                return 1;
  
        /*
diff --combined strbuf.c
index c4e91a66567304ee7732e1121229e7098f45384a,89e40bb496b99855e3408fdfa07dbcf851b8a08d..89d22e3b0903a220fa958b8d912607828ab2a9ba
+++ b/strbuf.c
@@@ -204,6 -204,13 +204,6 @@@ void strbuf_addbuf(struct strbuf *sb, c
        strbuf_setlen(sb, sb->len + sb2->len);
  }
  
 -void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len)
 -{
 -      strbuf_grow(sb, len);
 -      memcpy(sb->buf + sb->len, sb->buf + pos, len);
 -      strbuf_setlen(sb, sb->len + len);
 -}
 -
  void strbuf_addchars(struct strbuf *sb, int c, size_t n)
  {
        strbuf_grow(sb, n);
@@@ -779,7 -786,7 +779,7 @@@ char *xstrfmt(const char *fmt, ...
  }
  
  void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm,
-                    int tz_offset, const char *tz_name)
+                    int tz_offset, int suppress_tz_name)
  {
        struct strbuf munged_fmt = STRBUF_INIT;
        size_t hint = 128;
                        fmt++;
                        break;
                case 'Z':
-                       if (tz_name) {
-                               strbuf_addstr(&munged_fmt, tz_name);
+                       if (suppress_tz_name) {
                                fmt++;
                                break;
                        }
diff --combined strbuf.h
index 3646a6291b5026fc6d9e211a0313d76e4d2e100d,9262615ca0bf3009bcb052f36ceb300060302e2c..2075384e0b2df97a6d113acebcbcdcc853237166
+++ b/strbuf.h
@@@ -263,6 -263,12 +263,6 @@@ static inline void strbuf_addstr(struc
   */
  extern void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2);
  
 -/**
 - * Copy part of the buffer from a given position till a given length to the
 - * end of the buffer.
 - */
 -extern void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len);
 -
  /**
   * This function can be used to expand a format string containing
   * placeholders. To that end, it parses the string and calls the specified
@@@ -334,14 -340,15 +334,15 @@@ extern void strbuf_vaddf(struct strbuf 
  
  /**
   * Add the time specified by `tm`, as formatted by `strftime`.
-  * `tz_name` is used to expand %Z internally unless it's NULL.
   * `tz_offset` is in decimal hhmm format, e.g. -600 means six hours west
   * of Greenwich, and it's used to expand %z internally.  However, tokens
   * with modifiers (e.g. %Ez) are passed to `strftime`.
+  * `suppress_tz_name`, when set, expands %Z internally to the empty
+  * string rather than passing it to `strftime`.
   */
  extern void strbuf_addftime(struct strbuf *sb, const char *fmt,
                            const struct tm *tm, int tz_offset,
-                           const char *tz_name);
+                           int suppress_tz_name);
  
  /**
   * Read a given size of data from a FILE* pointer to the buffer.