git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 3/3] introduce "format" date-mode

From
Eric Sunshine <sunshine@sunshineco.com>
Date
Jun 30, 2015, 17:05 UTC
Message-ID
<CAPig+cTbOkDJDwhKEbboCQkeossBzvPmw=goag01Sbsw2pisSA@mail.gmail.com>
In-Reply-To
<20150630132653.GA25742@peff.net>
On Tue, Jun 30, 2015 at 9:26 AM, Jeff King <peff@peff.net> wrote:
Show 14 quoted lines
> On Mon, Jun 29, 2015 at 06:22:47PM -0400, Eric Sunshine wrote:
>
>> Clients of strbuf rightly expect the buffer to grow as needed in
>> order to complete the requested operation. It is, therefore, both
>> weird and expectation-breaking for strbuf_addftime() to lack this
>> behavior. Worse, it doesn't even signal when the format has failed
>> due to insufficient buffer space.
>>
>> How about taking this approach (or something similar), instead, which
>> grows the strbuf as needed?
>
> Here's a patch, on top of jk/date-mode-format (I think it would also be
> fine to just squash into the tip commit; the explanation in the commit
> message is sufficiently mirrored in the code comment).

As a logical change in itself, I could also see introduction of strbuf_addftime() split out into its own patch (with this patch squashed in). Either way, it's a welcome improvement over the original.

Show 100 quoted lines
> -- >8 --
> Subject: [PATCH] strbuf: make strbuf_addftime more robust
>
> The return value of strftime is poorly designed; when it
> returns 0, the caller cannot tell if the buffer was not
> large enough, or if the output was actually 0 bytes. In the
> original implementation of strbuf_addftime, we simply punted
> and guessed that our 128-byte hint would be large enough.
>
> We can do better, though, if we're willing to treat strftime
> like less of a black box. We can munge the incoming format
> to make sure that it never produces 0-length output, and
> then "fix" the resulting output.  That lets us reliably grow
> the buffer based on strftime's return value.
>
> Clever-idea-by: Eric Sunshine <sunshine@sunshineco.com>
> Signed-off-by: Jeff King <peff@peff.net>
> ---
>  strbuf.c                | 38 +++++++++++++++++++++-----------------
>  t/t6300-for-each-ref.sh | 10 ++++++++++
>  2 files changed, 31 insertions(+), 17 deletions(-)
>
> diff --git a/strbuf.c b/strbuf.c
> index a7ba028..e5e7370 100644
> --- a/strbuf.c
> +++ b/strbuf.c
> @@ -712,29 +712,33 @@ char *xstrfmt(const char *fmt, ...)
>
>  void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm)
>  {
> +       size_t hint = 128;
>         size_t len;
>
> -       /*
> -        * strftime reports "0" if it could not fit the result in the buffer.
> -        * Unfortunately, it also reports "0" if the requested time string
> -        * takes 0 bytes. So if we were to probe and grow, we have to choose
> -        * some arbitrary cap beyond which we guess that the format probably
> -        * just results in a 0-length output. Since we have to choose some
> -        * reasonable cap anyway, and since it is not that big, we may
> -        * as well just grow to their in the first place.
> -        */
> -       strbuf_grow(sb, 128);
> +       if (!*fmt)
> +               return;
> +
> +       strbuf_grow(sb, hint);
>         len = strftime(sb->buf + sb->len, sb->alloc - sb->len, fmt, tm);
>
>         if (!len) {
>                 /*
> -                * Either we failed, or the format actually produces a 0-length
> -                * output. There's not much we can do, so we leave it blank.
> -                * However, the output array is left in an undefined state, so
> -                * we must re-assert our NUL terminator.
> +                * strftime reports "0" if it could not fit the result in the buffer.
> +                * Unfortunately, it also reports "0" if the requested time string
> +                * takes 0 bytes. So our strategy is to munge the format so that the
> +                * output contains at least one character, and then drop the extra
> +                * character before returning.
>                  */
> -               sb->buf[sb->len] = '\0';
> -       } else {
> -               sb->len += len;
> +               struct strbuf munged_fmt = STRBUF_INIT;
> +               strbuf_addf(&munged_fmt, "%s ", fmt);
> +               while (!len) {
> +                       hint *= 2;
> +                       strbuf_grow(sb, hint);
> +                       len = strftime(sb->buf + sb->len, sb->alloc - sb->len,
> +                                      munged_fmt.buf, tm);
> +               }
> +               strbuf_release(&munged_fmt);
> +               len--; /* drop munged space */
>         }
> +       strbuf_setlen(sb, sb->len + len);
>  }
> diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
> index c7f368c..7c9bec7 100755
> --- a/t/t6300-for-each-ref.sh
> +++ b/t/t6300-for-each-ref.sh
> @@ -235,6 +235,16 @@ test_expect_success 'Check format of strftime date fields' '
>         test_cmp expected actual
>  '
>
> +test_expect_success 'exercise strftime with odd fields' '
> +       echo >expected &&
> +       git for-each-ref --format="%(authordate:format:)" refs/heads >actual &&
> +       test_cmp expected actual &&
> +       long="long format -- $_z40$_z40$_z40$_z40$_z40$_z40$_z40" &&
> +       echo $long >expected &&
> +       git for-each-ref --format="%(authordate:format:$long)" refs/heads >actual &&
> +       test_cmp expected actual
> +'
> +
>  cat >expected <<\EOF
>  refs/heads/master
>  refs/remotes/origin/master
> --
> 2.5.0.rc0.336.g8460790
Previous: Jeff KingNext: Eric Sunshine
Message 29 of 31 in “several date related issues”
  1. H.Merijn BrandJun 25, 2015
  2. Jeff KingJun 25, 2015
  3. H.Merijn BrandJun 25, 2015
  4. 0/3 localized date formatJeff King, Jun 25, 2015
  5. 1/3 show-branch: use DATE_RELATIVE instead of magic numberJeff King, Jun 25, 2015
  6. 2/3 convert "enum date_mode" into a structJeff King, Jun 25, 2015
  7. John KeepingJun 25, 2015
  8. Jeff KingJun 25, 2015
  9. Junio C HamanoJul 7, 2015
  10. Jeff KingJul 7, 2015
  11. Junio C HamanoJul 7, 2015
  12. Jeff KingJul 7, 2015
  13. Junio C HamanoJul 7, 2015
  14. 3/3 introduce "format" date-modeJeff King, Jun 25, 2015
  15. Eric SunshineJun 29, 2015
  16. Jeff KingJun 30, 2015
  17. Junio C HamanoJun 30, 2015
  18. Jeff KingJun 30, 2015
  19. Junio C HamanoJun 30, 2015
  20. Jeff KingJun 30, 2015
  21. Eric SunshineJun 30, 2015
  22. Jeff KingJun 30, 2015
  23. Eric SunshineJun 30, 2015
  24. Jeff KingJun 30, 2015
  25. Junio C HamanoJun 30, 2015
  26. Eric SunshineJun 30, 2015
  27. Jeff KingJun 30, 2015
  28. Jeff KingJun 30, 2015
  29. Eric SunshineJun 30, 2015
  30. Eric SunshineJul 21, 2015
  31. Jeff KingJul 21, 2015

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.