{"thread":{"id":"9835","subject":"Re: Use more strbufs series [on top of next]","startedAt":"2007-09-09T00:04:30Z","lastAt":"2007-09-27T22:56:32Z","messageCount":9,"participants":["Pierre Habouzit","Linus Torvalds"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"53023","messageId":"11892962763548-git-send-email-madcoder@debian.org","threadId":"9835","inReplyTo":null,"subject":"Use more strbufs series [on top of next]","fromName":"Pierre Habouzit","fromEmail":"madcoder@debian.org","sentAt":"2007-09-09T00:04:30Z","receivedAt":"2007-09-09T00:04:30Z","isPatch":false,"sender":{"key":"madcoder@debian.org","avatar":"https://avatars.githubusercontent.com/u/44708?v=4"},"body":"  Here is a series of patches on top of next, which use strbufs in even\nmore places. Most notably, it uses it in the commit pretty printer (and\ncommit message formatter), and it supersedes definitely read_fd\n(previously in sha1_file.c).\n\n  The latter is not strictly speaking necessary, but strbuf_read and\nread_fd do almost the same. The sole difference is that read_fd use\ncustom reallocation mechanisms (which is bad now that strbufs exists)\nthough had a different semantics when an error occurs. Though, like for\nstrbuf_read, read_fd callers either die() or discard the buffer, and\ncurrent strbuf_read semantics works with that.\n\n  As a result we once again have a nice reduction of the code lines.\n\n  $ git diff --shortstat origin/next strbuf.*\n   2 files changed, 24 insertions(+), 0 deletions(-)\n\n  $ git diff --shortstat origin/next ^strbuf.*\n   16 files changed, 270 insertions(+), 466 deletions(-)\n\n  I feel that with the current series commit.c can be simplified\nfurther, but the patch was big enough as is already.\n\n  If this series will be rewritten for this or this reason, please note\nthat I found a memory leak (not a severe one though) in\nbuiltin-archive.c, where the \"fmt\" pointer is allocated and never freed.\n\nCheers,\n"},{"id":"53031","messageId":"11892962761617-git-send-email-madcoder@debian.org","threadId":"9835","inReplyTo":"11892962763548-git-send-email-madcoder@debian.org","subject":"[PATCH 1/6] Add strbuf_rtrim and strbuf_insert.","fromName":"Pierre Habouzit","fromEmail":"madcoder@debian.org","sentAt":"2007-09-09T00:04:31Z","receivedAt":"2007-09-09T00:04:31Z","isPatch":true,"sender":{"key":"madcoder@debian.org","avatar":"https://avatars.githubusercontent.com/u/44708?v=4"},"body":"  * strbuf_rtrim removes trailing spaces.\n  * strbuf_insert insert data at a given position.\n\nSigned-off-by: Pierre Habouzit <madcoder@debian.org>\n---\n strbuf.c |   18 ++++++++++++++++++\n strbuf.h |    6 ++++++\n 2 files changed, 24 insertions(+), 0 deletions(-)\n\ndiff --git a/strbuf.c b/strbuf.c\nindex 7136de1..2643ce1 100644\n--- a/strbuf.c\n+++ b/strbuf.c\n@@ -28,6 +28,24 @@ void strbuf_grow(struct strbuf *sb, size_t extra) {\n \tALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);\n }\n \n+void strbuf_rtrim(struct strbuf *sb)\n+{\n+\twhile (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))\n+\t\tsb->len--;\n+\tsb->buf[sb->len] = '\\0';\n+}\n+\n+void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len) {\n+\tstrbuf_grow(sb, len);\n+\tif (pos >= sb->len) {\n+\t\tsb->len = pos;\n+\t} else {\n+\t\tmemmove(sb->buf + pos + len, sb->buf + pos, sb->len - pos);\n+\t}\n+\tmemcpy(sb->buf + pos, data, len);\n+\tstrbuf_setlen(sb, sb->len + len);\n+}\n+\n void strbuf_add(struct strbuf *sb, const void *data, size_t len) {\n \tstrbuf_grow(sb, len);\n \tmemcpy(sb->buf + sb->len, data, len);\ndiff --git a/strbuf.h b/strbuf.h\nindex b40dc99..b90cbdf 100644\n--- a/strbuf.h\n+++ b/strbuf.h\n@@ -68,6 +68,9 @@ static inline void strbuf_setlen(struct strbuf *sb, size_t len) {\n \n extern void strbuf_grow(struct strbuf *, size_t);\n \n+/*----- content related -----*/\n+extern void strbuf_rtrim(struct strbuf *);\n+\n /*----- add data in your buffer -----*/\n static inline void strbuf_addch(struct strbuf *sb, int c) {\n \tstrbuf_grow(sb, 1);\n@@ -75,6 +78,9 @@ static inline void strbuf_addch(struct strbuf *sb, int c) {\n \tsb->buf[sb->len] = '\\0';\n }\n \n+/* inserts after pos, or appends if pos >= sb->len */\n+extern void strbuf_insert(struct strbuf *, size_t pos, const void *, size_t);\n+\n extern void strbuf_add(struct strbuf *, const void *, size_t);\n static inline void strbuf_addstr(struct strbuf *sb, const char *s) {\n \tstrbuf_add(sb, s, strlen(s));\n-- \n1.5.3.1\n"},{"id":"53027","messageId":"11892962764194-git-send-email-madcoder@debian.org","threadId":"9835","inReplyTo":"11892962761617-git-send-email-madcoder@debian.org","subject":"[PATCH 2/6] Change semantics of interpolate to work like snprintf.","fromName":"Pierre Habouzit","fromEmail":"madcoder@debian.org","sentAt":"2007-09-09T00:04:32Z","receivedAt":"2007-09-09T00:04:32Z","isPatch":true,"sender":{"key":"madcoder@debian.org","avatar":"https://avatars.githubusercontent.com/u/44708?v=4"},"body":"  Also fix many off-by-ones and a useless memset.\n\nSigned-off-by: Pierre Habouzit <madcoder@debian.org>\n---\n commit.c      |    9 ++++-----\n interpolate.c |   20 ++++++++------------\n 2 files changed, 12 insertions(+), 17 deletions(-)\n\ndiff --git a/commit.c b/commit.c\nindex 99f65ce..25781cc 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -923,15 +923,14 @@ long format_commit_message(const struct commit *commit, const void *format,\n \n \tdo {\n \t\tchar *buf = *buf_p;\n-\t\tunsigned long space = *space_p;\n+\t\tunsigned long len;\n \n-\t\tspace = interpolate(buf, space, format,\n+\t\tlen = interpolate(buf, *space_p, format,\n \t\t\t\t    table, ARRAY_SIZE(table));\n-\t\tif (!space)\n+\t\tif (len < *space_p)\n \t\t\tbreak;\n-\t\tbuf = xrealloc(buf, space);\n+\t\tALLOC_GROW(buf, len + 1, *space_p);\n \t\t*buf_p = buf;\n-\t\t*space_p = space;\n \t} while (1);\n \tinterp_clear_table(table, ARRAY_SIZE(table));\n \ndiff --git a/interpolate.c b/interpolate.c\nindex 0082677..ff4fb10 100644\n--- a/interpolate.c\n+++ b/interpolate.c\n@@ -44,9 +44,8 @@ void interp_clear_table(struct interp *table, int ninterps)\n  *        { \"%%\", \"%\"},\n  *    }\n  *\n- * Returns 0 on a successful substitution pass that fits in result,\n- * Returns a number of bytes needed to hold the full substituted\n- * string otherwise.\n+ * Returns the length of the substituted string (not including the final \\0).\n+ * Like with snprintf, if the result is >= reslen, then it overflowed.\n  */\n \n unsigned long interpolate(char *result, unsigned long reslen,\n@@ -61,8 +60,6 @@ unsigned long interpolate(char *result, unsigned long reslen,\n \tint i;\n \tchar c;\n \n-        memset(result, 0, reslen);\n-\n \twhile ((c = *src)) {\n \t\tif (c == '%') {\n \t\t\t/* Try to match an interpolation string. */\n@@ -78,9 +75,9 @@ unsigned long interpolate(char *result, unsigned long reslen,\n \t\t\t\tvalue = interps[i].value;\n \t\t\t\tvaluelen = strlen(value);\n \n-\t\t\t\tif (newlen + valuelen + 1 < reslen) {\n+\t\t\t\tif (newlen + valuelen < reslen) {\n \t\t\t\t\t/* Substitute. */\n-\t\t\t\t\tstrncpy(dest, value, valuelen);\n+\t\t\t\t\tmemcpy(dest, value, valuelen);\n \t\t\t\t\tdest += valuelen;\n \t\t\t\t}\n \t\t\t\tnewlen += valuelen;\n@@ -89,14 +86,13 @@ unsigned long interpolate(char *result, unsigned long reslen,\n \t\t\t}\n \t\t}\n \t\t/* Straight copy one non-interpolation character. */\n-\t\tif (newlen + 1 < reslen)\n+\t\tif (newlen < reslen)\n \t\t\t*dest++ = *src;\n \t\tsrc++;\n \t\tnewlen++;\n \t}\n \n-\tif (newlen + 1 < reslen)\n-\t\treturn 0;\n-\telse\n-\t\treturn newlen + 2;\n+\tif (reslen > 0)\n+\t\t*dest = '\\0';\n+\treturn newlen;\n }\n-- \n1.5.3.1\n"},{"id":"53028","messageId":"1189296276114-git-send-email-madcoder@debian.org","threadId":"9835","inReplyTo":"11892962764194-git-send-email-madcoder@debian.org","subject":"[PATCH 3/6] Rework pretty_print_commit to use strbufs instead of custom buffers.","fromName":"Pierre Habouzit","fromEmail":"madcoder@debian.org","sentAt":"2007-09-09T00:04:33Z","receivedAt":"2007-09-09T00:04:33Z","isPatch":true,"sender":{"key":"madcoder@debian.org","avatar":"https://avatars.githubusercontent.com/u/44708?v=4"},"body":"  Also remove the \"len\" parameter, as:\n  (1) it was used as a max boundary, and every caller used ~0u\n  (2) we check for final NUL no matter what, so it doesn't help for speed.\n\n  As a result most of the pp_* function takes 3 arguments less, and we need\na lot less local variables, this makes the code way more readable, and\neasier to extend if needed.\n\n  This patch also fixes some spacing and cosmetic issues.\n\n  This patch also fixes (as a side effect) a memory leak intoruced in\nbuiltin-archive.c at commit df4a394f (fmt was xmalloc'ed and not free'd)\n\nSigned-off-by: Pierre Habouzit <madcoder@debian.org>\n---\n builtin-archive.c     |   38 +++----\n builtin-branch.c      |   15 +--\n builtin-log.c         |   12 +-\n builtin-rev-list.c    |   13 +-\n builtin-show-branch.c |   13 +-\n commit.c              |  330 ++++++++++++++++++-------------------------------\n commit.h              |    9 +-\n log-tree.c            |   56 +++------\n 8 files changed, 189 insertions(+), 297 deletions(-)\n\ndiff --git a/builtin-archive.c b/builtin-archive.c\nindex e221f11..0a41ad7 100644\n--- a/builtin-archive.c\n+++ b/builtin-archive.c\n@@ -84,14 +84,16 @@ static int run_remote_archiver(const char *remote, int argc,\n static void *format_subst(const struct commit *commit, const char *format,\n                           unsigned long *sizep)\n {\n-\tunsigned long len = *sizep, result_len = 0;\n+\tunsigned long len = *sizep;\n \tconst char *a = format;\n-\tchar *result = NULL;\n+\tstruct strbuf result;\n+\tstruct strbuf fmt;\n+\n+\tstrbuf_init(&result);\n+\tstrbuf_init(&fmt);\n \n \tfor (;;) {\n \t\tconst char *b, *c;\n-\t\tchar *fmt, *formatted = NULL;\n-\t\tunsigned long a_len, fmt_len, formatted_len, allocated = 0;\n \n \t\tb = memmem(a, len, \"$Format:\", 8);\n \t\tif (!b || a + len < b + 9)\n@@ -100,31 +102,23 @@ static void *format_subst(const struct commit *commit, const char *format,\n \t\tif (!c)\n \t\t\tbreak;\n \n-\t\ta_len = b - a;\n-\t\tfmt_len = c - b - 8;\n-\t\tfmt = xmalloc(fmt_len + 1);\n-\t\tmemcpy(fmt, b + 8, fmt_len);\n-\t\tfmt[fmt_len] = '\\0';\n-\n-\t\tformatted_len = format_commit_message(commit, fmt, &formatted,\n-\t\t                                      &allocated);\n-\t\tresult = xrealloc(result, result_len + a_len + formatted_len);\n-\t\tmemcpy(result + result_len, a, a_len);\n-\t\tmemcpy(result + result_len + a_len, formatted, formatted_len);\n-\t\tresult_len += a_len + formatted_len;\n+\t\tstrbuf_reset(&fmt);\n+\t\tstrbuf_add(&fmt, b + 8, c - b - 8);\n+\n+\t\tstrbuf_add(&result, a, b - a);\n+\t\tformat_commit_message(commit, fmt.buf, &result);\n \t\tlen -= c + 1 - a;\n \t\ta = c + 1;\n \t}\n \n-\tif (result && len) {\n-\t\tresult = xrealloc(result, result_len + len);\n-\t\tmemcpy(result + result_len, a, len);\n-\t\tresult_len += len;\n+\tif (result.len && len) {\n+\t\tstrbuf_add(&result, a, len);\n \t}\n \n-\t*sizep = result_len;\n+\t*sizep = result.len;\n \n-\treturn result;\n+\tstrbuf_release(&fmt);\n+\treturn strbuf_detach(&result);\n }\n \n static void *convert_to_archive(const char *path,\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 5f5c182..68cd5f9 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -268,23 +268,22 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,\n \t}\n \n \tif (verbose) {\n-\t\tchar *subject = NULL;\n-\t\tunsigned long subject_len = 0;\n+\t\tstruct strbuf subject;\n \t\tconst char *sub = \" **** invalid ref ****\";\n \n+\t\tstrbuf_init(&subject);\n+\n \t\tcommit = lookup_commit(item->sha1);\n \t\tif (commit && !parse_commit(commit)) {\n-\t\t\tpretty_print_commit(CMIT_FMT_ONELINE, commit, ~0,\n-\t\t\t\t\t    &subject, &subject_len, 0,\n-\t\t\t\t\t    NULL, NULL, 0);\n-\t\t\tsub = subject;\n+\t\t\tpretty_print_commit(CMIT_FMT_ONELINE, commit,\n+\t\t\t\t\t    &subject, 0, NULL, NULL, 0);\n+\t\t\tsub = subject.buf;\n \t\t}\n \t\tprintf(\"%c %s%-*s%s %s %s\\n\", c, branch_get_color(color),\n \t\t       maxwidth, item->name,\n \t\t       branch_get_color(COLOR_BRANCH_RESET),\n \t\t       find_unique_abbrev(item->sha1, abbrev), sub);\n-\t\tif (subject)\n-\t\t\tfree(subject);\n+\t\tstrbuf_release(&subject);\n \t} else {\n \t\tprintf(\"%c %s%s%s\\n\", c, branch_get_color(color), item->name,\n \t\t       branch_get_color(COLOR_BRANCH_RESET));\ndiff --git a/builtin-log.c b/builtin-log.c\nindex fa81c25..21b35a1 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -763,13 +763,13 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)\n \t\t\tsign = '-';\n \n \t\tif (verbose) {\n-\t\t\tchar *buf = NULL;\n-\t\t\tunsigned long buflen = 0;\n-\t\t\tpretty_print_commit(CMIT_FMT_ONELINE, commit, ~0,\n-\t\t\t                    &buf, &buflen, 0, NULL, NULL, 0);\n+\t\t\tstruct strbuf buf;\n+\t\t\tstrbuf_init(&buf);\n+\t\t\tpretty_print_commit(CMIT_FMT_ONELINE, commit,\n+\t\t\t                    &buf, 0, NULL, NULL, 0);\n \t\t\tprintf(\"%c %s %s\\n\", sign,\n-\t\t\t       sha1_to_hex(commit->object.sha1), buf);\n-\t\t\tfree(buf);\n+\t\t\t       sha1_to_hex(commit->object.sha1), buf.buf);\n+\t\t\tstrbuf_release(&buf);\n \t\t}\n \t\telse {\n \t\t\tprintf(\"%c %s\\n\", sign,\ndiff --git a/builtin-rev-list.c b/builtin-rev-list.c\nindex ac551d5..7967f86 100644\n--- a/builtin-rev-list.c\n+++ b/builtin-rev-list.c\n@@ -80,13 +80,12 @@ static void show_commit(struct commit *commit)\n \t\tputchar('\\n');\n \n \tif (revs.verbose_header) {\n-\t\tchar *buf = NULL;\n-\t\tunsigned long buflen = 0;\n-\t\tpretty_print_commit(revs.commit_format, commit, ~0,\n-\t\t\t\t    &buf, &buflen,\n-\t\t\t\t    revs.abbrev, NULL, NULL, revs.date_mode);\n-\t\tprintf(\"%s%c\", buf, hdr_termination);\n-\t\tfree(buf);\n+\t\tstruct strbuf buf;\n+\t\tstrbuf_init(&buf);\n+\t\tpretty_print_commit(revs.commit_format, commit,\n+\t\t\t\t\t&buf, revs.abbrev, NULL, NULL, revs.date_mode);\n+\t\tprintf(\"%s%c\", buf.buf, hdr_termination);\n+\t\tstrbuf_release(&buf);\n \t}\n \tmaybe_flush_or_die(stdout, \"stdout\");\n \tif (commit->parents) {\ndiff --git a/builtin-show-branch.c b/builtin-show-branch.c\nindex 4fa87f6..020116f 100644\n--- a/builtin-show-branch.c\n+++ b/builtin-show-branch.c\n@@ -259,16 +259,15 @@ static void join_revs(struct commit_list **list_p,\n \n static void show_one_commit(struct commit *commit, int no_name)\n {\n-\tchar *pretty = NULL;\n+\tstruct strbuf pretty;\n \tconst char *pretty_str = \"(unavailable)\";\n-\tunsigned long pretty_len = 0;\n \tstruct commit_name *name = commit->util;\n \n+\tstrbuf_init(&pretty);\n \tif (commit->object.parsed) {\n-\t\tpretty_print_commit(CMIT_FMT_ONELINE, commit, ~0,\n-\t\t\t\t    &pretty, &pretty_len,\n-\t\t\t\t    0, NULL, NULL, 0);\n-\t\tpretty_str = pretty;\n+\t\tpretty_print_commit(CMIT_FMT_ONELINE, commit,\n+\t\t\t\t\t&pretty, 0, NULL, NULL, 0);\n+\t\tpretty_str = pretty.buf;\n \t}\n \tif (!prefixcmp(pretty_str, \"[PATCH] \"))\n \t\tpretty_str += 8;\n@@ -289,7 +288,7 @@ static void show_one_commit(struct commit *commit, int no_name)\n \t\t\t       find_unique_abbrev(commit->object.sha1, 7));\n \t}\n \tputs(pretty_str);\n-\tfree(pretty);\n+\tstrbuf_release(&pretty);\n }\n \n static char *ref_name[MAX_REVS + 1];\ndiff --git a/commit.c b/commit.c\nindex 25781cc..02dfd2d 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -458,11 +458,11 @@ void clear_commit_marks(struct commit *commit, unsigned int mark)\n /*\n  * Generic support for pretty-printing the header\n  */\n-static int get_one_line(const char *msg, unsigned long len)\n+static int get_one_line(const char *msg)\n {\n \tint ret = 0;\n \n-\twhile (len--) {\n+\tfor (;;) {\n \t\tchar c = *msg++;\n \t\tif (!c)\n \t\t\tbreak;\n@@ -485,31 +485,24 @@ static int is_rfc2047_special(char ch)\n \treturn (non_ascii(ch) || (ch == '=') || (ch == '?') || (ch == '_'));\n }\n \n-static int add_rfc2047(char *buf, const char *line, int len,\n+static void add_rfc2047(struct strbuf *sb, const char *line, int len,\n \t\t       const char *encoding)\n {\n-\tchar *bp = buf;\n-\tint i, needquote;\n-\tchar q_encoding[128];\n-\tconst char *q_encoding_fmt = \"=?%s?q?\";\n+\tint i, last;\n \n-\tfor (i = needquote = 0; !needquote && i < len; i++) {\n+\tfor (i = 0; i < len; i++) {\n \t\tint ch = line[i];\n \t\tif (non_ascii(ch))\n-\t\t\tneedquote++;\n-\t\tif ((i + 1 < len) &&\n-\t\t    (ch == '=' && line[i+1] == '?'))\n-\t\t\tneedquote++;\n+\t\t\tgoto needquote;\n+\t\tif ((i + 1 < len) && (ch == '=' && line[i+1] == '?'))\n+\t\t\tgoto needquote;\n \t}\n-\tif (!needquote)\n-\t\treturn sprintf(buf, \"%.*s\", len, line);\n-\n-\ti = snprintf(q_encoding, sizeof(q_encoding), q_encoding_fmt, encoding);\n-\tif (sizeof(q_encoding) < i)\n-\t\tdie(\"Insanely long encoding name %s\", encoding);\n-\tmemcpy(bp, q_encoding, i);\n-\tbp += i;\n-\tfor (i = 0; i < len; i++) {\n+\tstrbuf_add(sb, line, len);\n+\treturn;\n+\n+needquote:\n+\tstrbuf_addf(sb, \"=?%s?q?\", encoding);\n+\tfor (i = last = 0; i < len; i++) {\n \t\tunsigned ch = line[i] & 0xFF;\n \t\t/*\n \t\t * We encode ' ' using '=20' even though rfc2047\n@@ -518,15 +511,13 @@ static int add_rfc2047(char *buf, const char *line, int len,\n \t\t * leave the underscore in place.\n \t\t */\n \t\tif (is_rfc2047_special(ch) || ch == ' ') {\n-\t\t\tsprintf(bp, \"=%02X\", ch);\n-\t\t\tbp += 3;\n+\t\t\tstrbuf_add(sb, line + last, i - last);\n+\t\t\tstrbuf_addf(sb, \"=%02X\", ch);\n+\t\t\tlast = i + 1;\n \t\t}\n-\t\telse\n-\t\t\t*bp++ = ch;\n \t}\n-\tmemcpy(bp, \"?=\", 2);\n-\tbp += 2;\n-\treturn bp - buf;\n+\tstrbuf_add(sb, line + last, len - last);\n+\tstrbuf_addstr(sb, \"?=\");\n }\n \n static unsigned long bound_rfc2047(unsigned long len, const char *encoding)\n@@ -537,21 +528,21 @@ static unsigned long bound_rfc2047(unsigned long len, const char *encoding)\n \treturn len * 3 + elen + 100;\n }\n \n-static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf,\n+static void add_user_info(const char *what, enum cmit_fmt fmt, struct strbuf *sb,\n \t\t\t const char *line, enum date_mode dmode,\n \t\t\t const char *encoding)\n {\n \tchar *date;\n \tint namelen;\n \tunsigned long time;\n-\tint tz, ret;\n+\tint tz;\n \tconst char *filler = \"    \";\n \n \tif (fmt == CMIT_FMT_ONELINE)\n-\t\treturn 0;\n+\t\treturn;\n \tdate = strchr(line, '>');\n \tif (!date)\n-\t\treturn 0;\n+\t\treturn;\n \tnamelen = ++date - line;\n \ttime = strtoul(date, &date, 10);\n \ttz = strtol(date, NULL, 10);\n@@ -560,42 +551,35 @@ static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf,\n \t\tchar *name_tail = strchr(line, '<');\n \t\tint display_name_length;\n \t\tif (!name_tail)\n-\t\t\treturn 0;\n+\t\t\treturn;\n \t\twhile (line < name_tail && isspace(name_tail[-1]))\n \t\t\tname_tail--;\n \t\tdisplay_name_length = name_tail - line;\n \t\tfiller = \"\";\n-\t\tstrcpy(buf, \"From: \");\n-\t\tret = strlen(buf);\n-\t\tret += add_rfc2047(buf + ret, line, display_name_length,\n-\t\t\t\t   encoding);\n-\t\tmemcpy(buf + ret, name_tail, namelen - display_name_length);\n-\t\tret += namelen - display_name_length;\n-\t\tbuf[ret++] = '\\n';\n+\t\tstrbuf_addstr(sb, \"From: \");\n+\t\tadd_rfc2047(sb, line, display_name_length, encoding);\n+\t\tstrbuf_add(sb, name_tail, namelen - display_name_length);\n+\t\tstrbuf_addch(sb, '\\n');\n \t}\n \telse {\n-\t\tret = sprintf(buf, \"%s: %.*s%.*s\\n\", what,\n+\t\tstrbuf_addf(sb, \"%s: %.*s%.*s\\n\", what,\n \t\t\t      (fmt == CMIT_FMT_FULLER) ? 4 : 0,\n \t\t\t      filler, namelen, line);\n \t}\n \tswitch (fmt) {\n \tcase CMIT_FMT_MEDIUM:\n-\t\tret += sprintf(buf + ret, \"Date:   %s\\n\",\n-\t\t\t       show_date(time, tz, dmode));\n+\t\tstrbuf_addf(sb, \"Date:   %s\\n\", show_date(time, tz, dmode));\n \t\tbreak;\n \tcase CMIT_FMT_EMAIL:\n-\t\tret += sprintf(buf + ret, \"Date: %s\\n\",\n-\t\t\t       show_date(time, tz, DATE_RFC2822));\n+\t\tstrbuf_addf(sb, \"Date: %s\\n\", show_date(time, tz, DATE_RFC2822));\n \t\tbreak;\n \tcase CMIT_FMT_FULLER:\n-\t\tret += sprintf(buf + ret, \"%sDate: %s\\n\", what,\n-\t\t\t       show_date(time, tz, dmode));\n+\t\tstrbuf_addf(sb, \"%sDate: %s\\n\", what, show_date(time, tz, dmode));\n \t\tbreak;\n \tdefault:\n \t\t/* notin' */\n \t\tbreak;\n \t}\n-\treturn ret;\n }\n \n static int is_empty_line(const char *line, int *len_p)\n@@ -607,16 +591,16 @@ static int is_empty_line(const char *line, int *len_p)\n \treturn !len;\n }\n \n-static int add_merge_info(enum cmit_fmt fmt, char *buf, const struct commit *commit, int abbrev)\n+static void add_merge_info(enum cmit_fmt fmt, struct strbuf *sb,\n+\t\t\tconst struct commit *commit, int abbrev)\n {\n \tstruct commit_list *parent = commit->parents;\n-\tint offset;\n \n \tif ((fmt == CMIT_FMT_ONELINE) || (fmt == CMIT_FMT_EMAIL) ||\n \t    !parent || !parent->next)\n-\t\treturn 0;\n+\t\treturn;\n \n-\toffset = sprintf(buf, \"Merge:\");\n+\tstrbuf_addstr(sb, \"Merge:\");\n \n \twhile (parent) {\n \t\tstruct commit *p = parent->item;\n@@ -629,10 +613,9 @@ static int add_merge_info(enum cmit_fmt fmt, char *buf, const struct commit *com\n \t\tdots = (abbrev && strlen(hex) != 40) ?  \"...\" : \"\";\n \t\tparent = parent->next;\n \n-\t\toffset += sprintf(buf + offset, \" %s%s\", hex, dots);\n+\t\tstrbuf_addf(sb, \" %s%s\", hex, dots);\n \t}\n-\tbuf[offset++] = '\\n';\n-\treturn offset;\n+\tstrbuf_addch(sb, '\\n');\n }\n \n static char *get_header(const struct commit *commit, const char *key)\n@@ -787,8 +770,8 @@ static void fill_person(struct interp *table, const char *msg, int len)\n \tinterp_set_entry(table, 6, show_date(date, tz, DATE_ISO8601));\n }\n \n-long format_commit_message(const struct commit *commit, const void *format,\n-                           char **buf_p, unsigned long *space_p)\n+void format_commit_message(const struct commit *commit,\n+                           const void *format, struct strbuf *sb)\n {\n \tstruct interp table[] = {\n \t\t{ \"%H\" },\t/* commit hash */\n@@ -841,6 +824,7 @@ long format_commit_message(const struct commit *commit, const void *format,\n \t};\n \tstruct commit_list *p;\n \tchar parents[1024];\n+\tunsigned long len;\n \tint i;\n \tenum { HEADER, SUBJECT, BODY } state;\n \tconst char *msg = commit->buffer;\n@@ -921,20 +905,15 @@ long format_commit_message(const struct commit *commit, const void *format,\n \t\tif (!table[i].value)\n \t\t\tinterp_set_entry(table, i, \"<unknown>\");\n \n-\tdo {\n-\t\tchar *buf = *buf_p;\n-\t\tunsigned long len;\n-\n-\t\tlen = interpolate(buf, *space_p, format,\n-\t\t\t\t    table, ARRAY_SIZE(table));\n-\t\tif (len < *space_p)\n-\t\t\tbreak;\n-\t\tALLOC_GROW(buf, len + 1, *space_p);\n-\t\t*buf_p = buf;\n-\t} while (1);\n+\tlen = interpolate(sb->buf + sb->len, strbuf_avail(sb),\n+\t\t\t\tformat, table, ARRAY_SIZE(table));\n+\tif (len > strbuf_avail(sb)) {\n+\t\tstrbuf_grow(sb, len);\n+\t\tinterpolate(sb->buf + sb->len, strbuf_avail(sb) + 1,\n+\t\t\t\t\tformat, table, ARRAY_SIZE(table));\n+\t}\n+\tstrbuf_setlen(sb, sb->len + len);\n \tinterp_clear_table(table, ARRAY_SIZE(table));\n-\n-\treturn strlen(*buf_p);\n }\n \n static void pp_header(enum cmit_fmt fmt,\n@@ -943,34 +922,24 @@ static void pp_header(enum cmit_fmt fmt,\n \t\t      const char *encoding,\n \t\t      const struct commit *commit,\n \t\t      const char **msg_p,\n-\t\t      unsigned long *len_p,\n-\t\t      unsigned long *ofs_p,\n-\t\t      char **buf_p,\n-\t\t      unsigned long *space_p)\n+\t\t      struct strbuf *sb)\n {\n \tint parents_shown = 0;\n \n \tfor (;;) {\n \t\tconst char *line = *msg_p;\n-\t\tchar *dst;\n-\t\tint linelen = get_one_line(*msg_p, *len_p);\n-\t\tunsigned long len;\n+\t\tint linelen = get_one_line(*msg_p);\n \n \t\tif (!linelen)\n \t\t\treturn;\n \t\t*msg_p += linelen;\n-\t\t*len_p -= linelen;\n \n \t\tif (linelen == 1)\n \t\t\t/* End of header */\n \t\t\treturn;\n \n-\t\tALLOC_GROW(*buf_p, linelen + *ofs_p + 20, *space_p);\n-\t\tdst = *buf_p + *ofs_p;\n-\n \t\tif (fmt == CMIT_FMT_RAW) {\n-\t\t\tmemcpy(dst, line, linelen);\n-\t\t\t*ofs_p += linelen;\n+\t\t\tstrbuf_add(sb, line, linelen);\n \t\t\tcontinue;\n \t\t}\n \n@@ -988,10 +957,8 @@ static void pp_header(enum cmit_fmt fmt,\n \t\t\t     parent = parent->next, num++)\n \t\t\t\t;\n \t\t\t/* with enough slop */\n-\t\t\tnum = *ofs_p + num * 50 + 20;\n-\t\t\tALLOC_GROW(*buf_p, num, *space_p);\n-\t\t\tdst = *buf_p + *ofs_p;\n-\t\t\t*ofs_p += add_merge_info(fmt, dst, commit, abbrev);\n+\t\t\tstrbuf_grow(sb, num * 50 + 20);\n+\t\t\tadd_merge_info(fmt, sb, commit, abbrev);\n \t\t\tparents_shown = 1;\n \t\t}\n \n@@ -1001,129 +968,100 @@ static void pp_header(enum cmit_fmt fmt,\n \t\t * FULLER shows both authors and dates.\n \t\t */\n \t\tif (!memcmp(line, \"author \", 7)) {\n-\t\t\tlen = linelen;\n+\t\t\tunsigned long len = linelen;\n \t\t\tif (fmt == CMIT_FMT_EMAIL)\n \t\t\t\tlen = bound_rfc2047(linelen, encoding);\n-\t\t\tALLOC_GROW(*buf_p, *ofs_p + len + 80, *space_p);\n-\t\t\tdst = *buf_p + *ofs_p;\n-\t\t\t*ofs_p += add_user_info(\"Author\", fmt, dst,\n-\t\t\t\t\t\tline + 7, dmode, encoding);\n+\t\t\tstrbuf_grow(sb, len + 80);\n+\t\t\tadd_user_info(\"Author\", fmt, sb, line + 7, dmode, encoding);\n \t\t}\n \n \t\tif (!memcmp(line, \"committer \", 10) &&\n \t\t    (fmt == CMIT_FMT_FULL || fmt == CMIT_FMT_FULLER)) {\n-\t\t\tlen = linelen;\n+\t\t\tunsigned long len = linelen;\n \t\t\tif (fmt == CMIT_FMT_EMAIL)\n \t\t\t\tlen = bound_rfc2047(linelen, encoding);\n-\t\t\tALLOC_GROW(*buf_p, *ofs_p + len + 80, *space_p);\n-\t\t\tdst = *buf_p + *ofs_p;\n-\t\t\t*ofs_p += add_user_info(\"Commit\", fmt, dst,\n-\t\t\t\t\t\tline + 10, dmode, encoding);\n+\t\t\tstrbuf_grow(sb, len + 80);\n+\t\t\tadd_user_info(\"Commit\", fmt, sb, line + 10, dmode, encoding);\n \t\t}\n \t}\n }\n \n static void pp_title_line(enum cmit_fmt fmt,\n \t\t\t  const char **msg_p,\n-\t\t\t  unsigned long *len_p,\n-\t\t\t  unsigned long *ofs_p,\n-\t\t\t  char **buf_p,\n-\t\t\t  unsigned long *space_p,\n-\t\t\t  int indent,\n+\t\t\t  struct strbuf *sb,\n \t\t\t  const char *subject,\n \t\t\t  const char *after_subject,\n \t\t\t  const char *encoding,\n \t\t\t  int plain_non_ascii)\n {\n-\tchar *title;\n-\tunsigned long title_alloc, title_len;\n+\tstruct strbuf title;\n \tunsigned long len;\n \n-\ttitle_len = 0;\n-\ttitle_alloc = 80;\n-\ttitle = xmalloc(title_alloc);\n+\tstrbuf_init(&title);\n+\tstrbuf_grow(&title, 80);\n+\n \tfor (;;) {\n \t\tconst char *line = *msg_p;\n-\t\tint linelen = get_one_line(line, *len_p);\n-\t\t*msg_p += linelen;\n-\t\t*len_p -= linelen;\n+\t\tint linelen = get_one_line(line);\n \n+\t\t*msg_p += linelen;\n \t\tif (!linelen || is_empty_line(line, &linelen))\n \t\t\tbreak;\n \n-\t\tif (title_alloc <= title_len + linelen + 2) {\n-\t\t\ttitle_alloc = title_len + linelen + 80;\n-\t\t\ttitle = xrealloc(title, title_alloc);\n-\t\t}\n-\t\tlen = 0;\n-\t\tif (title_len) {\n+\t\tstrbuf_grow(&title, linelen + 2);\n+\t\tif (title.len) {\n \t\t\tif (fmt == CMIT_FMT_EMAIL) {\n-\t\t\t\tlen++;\n-\t\t\t\ttitle[title_len++] = '\\n';\n+\t\t\t\tstrbuf_addch(&title, '\\n');\n \t\t\t}\n-\t\t\tlen++;\n-\t\t\ttitle[title_len++] = ' ';\n+\t\t\tstrbuf_addch(&title, ' ');\n \t\t}\n-\t\tmemcpy(title + title_len, line, linelen);\n-\t\ttitle_len += linelen;\n+\t\tstrbuf_add(&title, line, linelen);\n \t}\n \n \t/* Enough slop for the MIME header and rfc2047 */\n-\tlen = bound_rfc2047(title_len, encoding)+ 1000;\n+\tlen = bound_rfc2047(title.len, encoding) + 1000;\n \tif (subject)\n \t\tlen += strlen(subject);\n \tif (after_subject)\n \t\tlen += strlen(after_subject);\n \tif (encoding)\n \t\tlen += strlen(encoding);\n-\tALLOC_GROW(*buf_p, title_len + *ofs_p + len, *space_p);\n \n+\tstrbuf_grow(sb, title.len + len);\n \tif (subject) {\n-\t\tlen = strlen(subject);\n-\t\tmemcpy(*buf_p + *ofs_p, subject, len);\n-\t\t*ofs_p += len;\n-\t\t*ofs_p += add_rfc2047(*buf_p + *ofs_p,\n-\t\t\t\t      title, title_len, encoding);\n+\t\tstrbuf_addstr(sb, subject);\n+\t\tadd_rfc2047(sb, title.buf, title.len, encoding);\n \t} else {\n-\t\tmemcpy(*buf_p + *ofs_p, title, title_len);\n-\t\t*ofs_p += title_len;\n+\t\tstrbuf_addbuf(sb, &title);\n \t}\n-\t(*buf_p)[(*ofs_p)++] = '\\n';\n+\tstrbuf_addch(sb, '\\n');\n+\n \tif (plain_non_ascii) {\n \t\tconst char *header_fmt =\n \t\t\t\"MIME-Version: 1.0\\n\"\n \t\t\t\"Content-Type: text/plain; charset=%s\\n\"\n \t\t\t\"Content-Transfer-Encoding: 8bit\\n\";\n-\t\t*ofs_p += snprintf(*buf_p + *ofs_p,\n-\t\t\t\t   *space_p - *ofs_p,\n-\t\t\t\t   header_fmt, encoding);\n+\t\tstrbuf_addf(sb, header_fmt, encoding);\n \t}\n \tif (after_subject) {\n-\t\tlen = strlen(after_subject);\n-\t\tmemcpy(*buf_p + *ofs_p, after_subject, len);\n-\t\t*ofs_p += len;\n+\t\tstrbuf_addstr(sb, after_subject);\n \t}\n-\tfree(title);\n \tif (fmt == CMIT_FMT_EMAIL) {\n-\t\tALLOC_GROW(*buf_p, *ofs_p + 20, *space_p);\n-\t\t(*buf_p)[(*ofs_p)++] = '\\n';\n+\t\tstrbuf_addch(sb, '\\n');\n \t}\n+\tstrbuf_release(&title);\n }\n \n static void pp_remainder(enum cmit_fmt fmt,\n \t\t\t const char **msg_p,\n-\t\t\t unsigned long *len_p,\n-\t\t\t unsigned long *ofs_p,\n-\t\t\t char **buf_p,\n-\t\t\t unsigned long *space_p,\n+\t\t\t struct strbuf *sb,\n \t\t\t int indent)\n {\n \tint first = 1;\n \tfor (;;) {\n \t\tconst char *line = *msg_p;\n-\t\tint linelen = get_one_line(line, *len_p);\n+\t\tint linelen = get_one_line(line);\n \t\t*msg_p += linelen;\n-\t\t*len_p -= linelen;\n \n \t\tif (!linelen)\n \t\t\tbreak;\n@@ -1136,36 +1074,30 @@ static void pp_remainder(enum cmit_fmt fmt,\n \t\t}\n \t\tfirst = 0;\n \n-\t\tALLOC_GROW(*buf_p, *ofs_p + linelen + indent + 20, *space_p);\n+\t\tstrbuf_grow(sb, linelen + indent + 20);\n \t\tif (indent) {\n-\t\t\tmemset(*buf_p + *ofs_p, ' ', indent);\n-\t\t\t*ofs_p += indent;\n+\t\t\tmemset(sb->buf + sb->len, ' ', indent);\n+\t\t\tstrbuf_setlen(sb, sb->len + indent);\n \t\t}\n-\t\tmemcpy(*buf_p + *ofs_p, line, linelen);\n-\t\t*ofs_p += linelen;\n-\t\t(*buf_p)[(*ofs_p)++] = '\\n';\n+\t\tstrbuf_add(sb, line, linelen);\n+\t\tstrbuf_addch(sb, '\\n');\n \t}\n }\n \n-unsigned long pretty_print_commit(enum cmit_fmt fmt,\n-\t\t\t\t  const struct commit *commit,\n-\t\t\t\t  unsigned long len,\n-\t\t\t\t  char **buf_p, unsigned long *space_p,\n-\t\t\t\t  int abbrev, const char *subject,\n-\t\t\t\t  const char *after_subject,\n+void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,\n+\t\t\t\t  struct strbuf *sb, int abbrev,\n+\t\t\t\t  const char *subject, const char *after_subject,\n \t\t\t\t  enum date_mode dmode)\n {\n-\tunsigned long offset = 0;\n \tunsigned long beginning_of_body;\n \tint indent = 4;\n \tconst char *msg = commit->buffer;\n \tint plain_non_ascii = 0;\n \tchar *reencoded;\n \tconst char *encoding;\n-\tchar *buf;\n \n \tif (fmt == CMIT_FMT_USERFORMAT)\n-\t\treturn format_commit_message(commit, user_format, buf_p, space_p);\n+\t\treturn format_commit_message(commit, user_format, sb);\n \n \tencoding = (git_log_output_encoding\n \t\t    ? git_log_output_encoding\n@@ -1175,7 +1107,6 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt,\n \treencoded = logmsg_reencode(commit, encoding);\n \tif (reencoded) {\n \t\tmsg = reencoded;\n-\t\tlen = strlen(reencoded);\n \t}\n \n \tif (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL)\n@@ -1190,14 +1121,13 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt,\n \tif (fmt == CMIT_FMT_EMAIL && !after_subject) {\n \t\tint i, ch, in_body;\n \n-\t\tfor (in_body = i = 0; (ch = msg[i]) && i < len; i++) {\n+\t\tfor (in_body = i = 0; (ch = msg[i]); i++) {\n \t\t\tif (!in_body) {\n \t\t\t\t/* author could be non 7-bit ASCII but\n \t\t\t\t * the log may be so; skip over the\n \t\t\t\t * header part first.\n \t\t\t\t */\n-\t\t\t\tif (ch == '\\n' &&\n-\t\t\t\t    i + 1 < len && msg[i+1] == '\\n')\n+\t\t\t\tif (ch == '\\n' && msg[i+1] == '\\n')\n \t\t\t\t\tin_body = 1;\n \t\t\t}\n \t\t\telse if (non_ascii(ch)) {\n@@ -1207,59 +1137,44 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt,\n \t\t}\n \t}\n \n-\tpp_header(fmt, abbrev, dmode, encoding,\n-\t\t  commit, &msg, &len,\n-\t\t  &offset, buf_p, space_p);\n+\tpp_header(fmt, abbrev, dmode, encoding, commit, &msg, sb);\n \tif (fmt != CMIT_FMT_ONELINE && !subject) {\n-\t\tALLOC_GROW(*buf_p, offset + 20, *space_p);\n-\t\t(*buf_p)[offset++] = '\\n';\n+\t\tstrbuf_addch(sb, '\\n');\n \t}\n \n \t/* Skip excess blank lines at the beginning of body, if any... */\n \tfor (;;) {\n-\t\tint linelen = get_one_line(msg, len);\n+\t\tint linelen = get_one_line(msg);\n \t\tint ll = linelen;\n \t\tif (!linelen)\n \t\t\tbreak;\n \t\tif (!is_empty_line(msg, &ll))\n \t\t\tbreak;\n \t\tmsg += linelen;\n-\t\tlen -= linelen;\n \t}\n \n \t/* These formats treat the title line specially. */\n-\tif (fmt == CMIT_FMT_ONELINE\n-\t    || fmt == CMIT_FMT_EMAIL)\n-\t\tpp_title_line(fmt, &msg, &len, &offset,\n-\t\t\t      buf_p, space_p, indent,\n-\t\t\t      subject, after_subject, encoding,\n-\t\t\t      plain_non_ascii);\n-\n-\tbeginning_of_body = offset;\n-\tif (fmt != CMIT_FMT_ONELINE)\n-\t\tpp_remainder(fmt, &msg, &len, &offset,\n-\t\t\t     buf_p, space_p, indent);\n-\n-\twhile (offset && isspace((*buf_p)[offset-1]))\n-\t\toffset--;\n+\tif (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL)\n+\t\tpp_title_line(fmt, &msg, sb, subject,\n+\t\t\t      after_subject, encoding, plain_non_ascii);\n \n-\tALLOC_GROW(*buf_p, offset + 20, *space_p);\n-\tbuf = *buf_p;\n+\tbeginning_of_body = sb->len;\n+\tif (fmt != CMIT_FMT_ONELINE)\n+\t\tpp_remainder(fmt, &msg, sb, indent);\n+\tstrbuf_rtrim(sb);\n \n \t/* Make sure there is an EOLN for the non-oneline case */\n \tif (fmt != CMIT_FMT_ONELINE)\n-\t\tbuf[offset++] = '\\n';\n+\t\tstrbuf_addch(sb, '\\n');\n \n \t/*\n \t * The caller may append additional body text in e-mail\n \t * format.  Make sure we did not strip the blank line\n \t * between the header and the body.\n \t */\n-\tif (fmt == CMIT_FMT_EMAIL && offset <= beginning_of_body)\n-\t\tbuf[offset++] = '\\n';\n-\tbuf[offset] = '\\0';\n+\tif (fmt == CMIT_FMT_EMAIL && sb->len <= beginning_of_body)\n+\t\tstrbuf_addch(sb, '\\n');\n \tfree(reencoded);\n-\treturn offset;\n }\n \n struct commit *pop_commit(struct commit_list **stack)\n@@ -1338,12 +1253,12 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo,\n \t\tnext=next->next;\n \t}\n \t/*\n-         * find the tips\n-         *\n-         * tips are nodes not reachable from any other node in the list\n-         *\n-         * the tips serve as a starting set for the work queue.\n-         */\n+\t * find the tips\n+\t *\n+\t * tips are nodes not reachable from any other node in the list\n+\t *\n+\t * the tips serve as a starting set for the work queue.\n+\t */\n \tnext=*list;\n \tinsert = &work;\n \twhile (next) {\n@@ -1370,9 +1285,9 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo,\n \t\t\tif (pn) {\n \t\t\t\t/*\n \t\t\t\t * parents are only enqueued for emission\n-                                 * when all their children have been emitted thereby\n-                                 * guaranteeing topological order.\n-                                 */\n+\t\t\t\t * when all their children have been emitted thereby\n+\t\t\t\t * guaranteeing topological order.\n+\t\t\t\t */\n \t\t\t\tpn->indegree--;\n \t\t\t\tif (!pn->indegree) {\n \t\t\t\t\tif (!lifo)\n@@ -1384,9 +1299,9 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo,\n \t\t\tparents=parents->next;\n \t\t}\n \t\t/*\n-                 * work_item is a commit all of whose children\n-                 * have already been emitted. we can emit it now.\n-                 */\n+\t\t * work_item is a commit all of whose children\n+\t\t * have already been emitted. we can emit it now.\n+\t\t */\n \t\t*pptr = work_node->list_item;\n \t\tpptr = &(*pptr)->next;\n \t\t*pptr = NULL;\n@@ -1482,8 +1397,7 @@ static struct commit_list *merge_bases(struct commit *one, struct commit *two)\n }\n \n struct commit_list *get_merge_bases(struct commit *one,\n-\t\t\t\t    struct commit *two,\n-                                    int cleanup)\n+\t\t\t\t\tstruct commit *two, int cleanup)\n {\n \tstruct commit_list *list;\n \tstruct commit **rslt;\ndiff --git a/commit.h b/commit.h\nindex a8d7661..b779de8 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -3,6 +3,7 @@\n \n #include \"object.h\"\n #include \"tree.h\"\n+#include \"strbuf.h\"\n #include \"decorate.h\"\n \n struct commit_list {\n@@ -61,8 +62,12 @@ enum cmit_fmt {\n };\n \n extern enum cmit_fmt get_commit_format(const char *arg);\n-extern long format_commit_message(const struct commit *commit, const void *template, char **buf_p, unsigned long *space_p);\n-extern unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *, unsigned long len, char **buf_p, unsigned long *space_p, int abbrev, const char *subject, const char *after_subject, enum date_mode dmode);\n+extern void format_commit_message(const struct commit *commit,\n+                                  const void *format, struct strbuf *sb);\n+extern void pretty_print_commit(enum cmit_fmt fmt, const struct commit*,\n+                                struct strbuf *,\n+                                int abbrev, const char *subject,\n+                                const char *after_subject, enum date_mode);\n \n /** Removes the first commit from a list sorted by date, and adds all\n  * of its parents.\ndiff --git a/log-tree.c b/log-tree.c\nindex a642371..5186939 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -79,25 +79,14 @@ static int detect_any_signoff(char *letter, int size)\n \treturn seen_head && seen_name;\n }\n \n-static unsigned long append_signoff(char **buf_p, unsigned long *buf_sz_p,\n-\t\t\t\t    unsigned long at, const char *signoff)\n+static void append_signoff(struct strbuf *sb, const char *signoff)\n {\n \tstatic const char signed_off_by[] = \"Signed-off-by: \";\n \tsize_t signoff_len = strlen(signoff);\n \tint has_signoff = 0;\n \tchar *cp;\n-\tchar *buf;\n-\tunsigned long buf_sz;\n-\n-\tbuf = *buf_p;\n-\tbuf_sz = *buf_sz_p;\n-\tif (buf_sz <= at + strlen(signed_off_by) + signoff_len + 3) {\n-\t\tbuf_sz += strlen(signed_off_by) + signoff_len + 3;\n-\t\tbuf = xrealloc(buf, buf_sz);\n-\t\t*buf_p = buf;\n-\t\t*buf_sz_p = buf_sz;\n-\t}\n-\tcp = buf;\n+\n+\tcp = sb->buf;\n \n \t/* First see if we already have the sign-off by the signer */\n \twhile ((cp = strstr(cp, signed_off_by))) {\n@@ -105,29 +94,25 @@ static unsigned long append_signoff(char **buf_p, unsigned long *buf_sz_p,\n \t\thas_signoff = 1;\n \n \t\tcp += strlen(signed_off_by);\n-\t\tif (cp + signoff_len >= buf + at)\n+\t\tif (cp + signoff_len >= sb->buf + sb->len)\n \t\t\tbreak;\n \t\tif (strncmp(cp, signoff, signoff_len))\n \t\t\tcontinue;\n \t\tif (!isspace(cp[signoff_len]))\n \t\t\tcontinue;\n \t\t/* we already have him */\n-\t\treturn at;\n+\t\treturn;\n \t}\n \n \tif (!has_signoff)\n-\t\thas_signoff = detect_any_signoff(buf, at);\n+\t\thas_signoff = detect_any_signoff(sb->buf, sb->len);\n \n \tif (!has_signoff)\n-\t\tbuf[at++] = '\\n';\n-\n-\tstrcpy(buf + at, signed_off_by);\n-\tat += strlen(signed_off_by);\n-\tstrcpy(buf + at, signoff);\n-\tat += signoff_len;\n-\tbuf[at++] = '\\n';\n-\tbuf[at] = 0;\n-\treturn at;\n+\t\tstrbuf_addch(sb, '\\n');\n+\n+\tstrbuf_addstr(sb, signed_off_by);\n+\tstrbuf_add(sb, signoff, signoff_len);\n+\tstrbuf_addch(sb, '\\n');\n }\n \n static unsigned int digits_in_number(unsigned int number)\n@@ -142,14 +127,12 @@ static unsigned int digits_in_number(unsigned int number)\n \n void show_log(struct rev_info *opt, const char *sep)\n {\n-\tchar *msgbuf = NULL;\n-\tunsigned long msgbuf_len = 0;\n+\tstruct strbuf msgbuf;\n \tstruct log_info *log = opt->loginfo;\n \tstruct commit *commit = log->commit, *parent = log->parent;\n \tint abbrev = opt->diffopt.abbrev;\n \tint abbrev_commit = opt->abbrev_commit ? opt->abbrev : 40;\n \tconst char *extra;\n-\tint len;\n \tconst char *subject = NULL, *extra_headers = opt->extra_headers;\n \n \topt->loginfo = NULL;\n@@ -288,18 +271,17 @@ void show_log(struct rev_info *opt, const char *sep)\n \t/*\n \t * And then the pretty-printed message itself\n \t */\n-\tlen = pretty_print_commit(opt->commit_format, commit, ~0u,\n-\t\t\t\t  &msgbuf, &msgbuf_len, abbrev, subject,\n-\t\t\t\t  extra_headers, opt->date_mode);\n+\tstrbuf_init(&msgbuf);\n+\tpretty_print_commit(opt->commit_format, commit, &msgbuf,\n+\t\t\t\t  abbrev, subject, extra_headers, opt->date_mode);\n \n \tif (opt->add_signoff)\n-\t\tlen = append_signoff(&msgbuf, &msgbuf_len, len,\n-\t\t\t\t     opt->add_signoff);\n+\t\tappend_signoff(&msgbuf, opt->add_signoff);\n \tif (opt->show_log_size)\n-\t\tprintf(\"log size %i\\n\", len);\n+\t\tprintf(\"log size %i\\n\", (int)msgbuf.len);\n \n-\tprintf(\"%s%s%s\", msgbuf, extra, sep);\n-\tfree(msgbuf);\n+\tprintf(\"%s%s%s\", msgbuf.buf, extra, sep);\n+\tstrbuf_release(&msgbuf);\n }\n \n int log_tree_diff_flush(struct rev_info *opt)\n-- \n1.5.3.1\n"},{"id":"53032","messageId":"11892962771947-git-send-email-madcoder@debian.org","threadId":"9835","inReplyTo":"1189296276114-git-send-email-madcoder@debian.org","subject":"[PATCH 4/6] Use strbuf_read in builtin-fetch-tool.c.","fromName":"Pierre Habouzit","fromEmail":"madcoder@debian.org","sentAt":"2007-09-09T00:04:34Z","receivedAt":"2007-09-09T00:04:34Z","isPatch":true,"sender":{"key":"madcoder@debian.org","avatar":"https://avatars.githubusercontent.com/u/44708?v=4"},"body":"  xrealloc.use --;\n\nSigned-off-by: Pierre Habouzit <madcoder@debian.org>\n---\n builtin-fetch--tool.c |   23 ++++++-----------------\n 1 files changed, 6 insertions(+), 17 deletions(-)\n\ndiff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c\nindex 24c7e6f..0dd742f 100644\n--- a/builtin-fetch--tool.c\n+++ b/builtin-fetch--tool.c\n@@ -2,27 +2,16 @@\n #include \"cache.h\"\n #include \"refs.h\"\n #include \"commit.h\"\n-\n-#define CHUNK_SIZE 1024\n+#include \"strbuf.h\"\n \n static char *get_stdin(void)\n {\n-\tsize_t offset = 0;\n-\tchar *data = xmalloc(CHUNK_SIZE);\n-\n-\twhile (1) {\n-\t\tssize_t cnt = xread(0, data + offset, CHUNK_SIZE);\n-\t\tif (cnt < 0)\n-\t\t\tdie(\"error reading standard input: %s\",\n-\t\t\t    strerror(errno));\n-\t\tif (cnt == 0) {\n-\t\t\tdata[offset] = 0;\n-\t\t\tbreak;\n-\t\t}\n-\t\toffset += cnt;\n-\t\tdata = xrealloc(data, offset + CHUNK_SIZE);\n+\tstruct strbuf buf;\n+\tstrbuf_init(&buf);\n+\tif (strbuf_read(&buf, 0) < 0) {\n+\t\tdie(\"error reading standard input: %s\", strerror(errno));\n \t}\n-\treturn data;\n+\treturn strbuf_detach(&buf);\n }\n \n static void show_new(enum object_type type, unsigned char *sha1_new)\n-- \n1.5.3.1\n"},{"id":"53024","messageId":"11892962771756-git-send-email-madcoder@debian.org","threadId":"9835","inReplyTo":"11892962771947-git-send-email-madcoder@debian.org","subject":"[PATCH 5/6] Use strbufs to in read_message (imap-send.c), custom buffer--.","fromName":"Pierre Habouzit","fromEmail":"madcoder@debian.org","sentAt":"2007-09-09T00:04:35Z","receivedAt":"2007-09-09T00:04:35Z","isPatch":true,"sender":{"key":"madcoder@debian.org","avatar":"https://avatars.githubusercontent.com/u/44708?v=4"},"body":"Signed-off-by: Pierre Habouzit <madcoder@debian.org>\n---\n imap-send.c |   31 +++++++++++--------------------\n 1 files changed, 11 insertions(+), 20 deletions(-)\n\ndiff --git a/imap-send.c b/imap-send.c\nindex a5a0696..d3dc5dd 100644\n--- a/imap-send.c\n+++ b/imap-send.c\n@@ -23,6 +23,7 @@\n  */\n \n #include \"cache.h\"\n+#include \"strbuf.h\"\n \n typedef struct store_conf {\n \tchar *name;\n@@ -1160,28 +1161,18 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int *uid )\n static int\n read_message( FILE *f, msg_data_t *msg )\n {\n-\tint len, r;\n+\tstruct strbuf buf;\n \n-\tmemset( msg, 0, sizeof *msg );\n-\tlen = CHUNKSIZE;\n-\tmsg->data = xmalloc( len+1 );\n-\tmsg->data[0] = 0;\n-\n-\twhile(!feof( f )) {\n-\t\tif (msg->len >= len) {\n-\t\t\tvoid *p;\n-\t\t\tlen += CHUNKSIZE;\n-\t\t\tp = xrealloc(msg->data, len+1);\n-\t\t\tif (!p)\n-\t\t\t\tbreak;\n-\t\t\tmsg->data = p;\n-\t\t}\n-\t\tr = fread( &msg->data[msg->len], 1, len - msg->len, f );\n-\t\tif (r <= 0)\n+\tmemset(msg, 0, sizeof(*msg));\n+\tstrbuf_init(&buf);\n+\n+\tdo {\n+\t\tif (strbuf_fread(&buf, CHUNKSIZE, f) <= 0)\n \t\t\tbreak;\n-\t\tmsg->len += r;\n-\t}\n-\tmsg->data[msg->len] = 0;\n+\t} while (!feof(f));\n+\n+\tmsg->len  = buf.len;\n+\tmsg->data = strbuf_detach(&buf);\n \treturn msg->len;\n }\n \n-- \n1.5.3.1\n"},{"id":"53025","messageId":"11892962771797-git-send-email-madcoder@debian.org","threadId":"9835","inReplyTo":"11892962771756-git-send-email-madcoder@debian.org","subject":"[PATCH 6/6] Replace all read_fd use with strbuf_read, and get rid of it.","fromName":"Pierre Habouzit","fromEmail":"madcoder@debian.org","sentAt":"2007-09-09T00:04:36Z","receivedAt":"2007-09-09T00:04:36Z","isPatch":true,"sender":{"key":"madcoder@debian.org","avatar":"https://avatars.githubusercontent.com/u/44708?v=4"},"body":"  This brings builtin-stripspace, builtin-tag and mktag to use strbufs.\n\nSigned-off-by: Pierre Habouzit <madcoder@debian.org>\n---\n builtin-stripspace.c |   21 ++++++--------\n builtin-tag.c        |   78 ++++++++++++++++++++------------------------------\n cache.h              |    1 -\n mktag.c              |   15 ++++-----\n sha1_file.c          |   60 ++++++--------------------------------\n 5 files changed, 56 insertions(+), 119 deletions(-)\n\ndiff --git a/builtin-stripspace.c b/builtin-stripspace.c\nindex 916355c..4815f8a 100644\n--- a/builtin-stripspace.c\n+++ b/builtin-stripspace.c\n@@ -1,5 +1,6 @@\n #include \"builtin.h\"\n #include \"cache.h\"\n+#include \"strbuf.h\"\n \n /*\n  * Returns the length of a line, without trailing spaces.\n@@ -74,26 +75,22 @@ size_t stripspace(char *buffer, size_t length, int skip_comments)\n \n int cmd_stripspace(int argc, const char **argv, const char *prefix)\n {\n-\tchar *buffer;\n-\tunsigned long size;\n+\tstruct strbuf buf;\n \tint strip_comments = 0;\n \n \tif (argc > 1 && (!strcmp(argv[1], \"-s\") ||\n \t\t\t\t!strcmp(argv[1], \"--strip-comments\")))\n \t\tstrip_comments = 1;\n \n-\tsize = 1024;\n-\tbuffer = xmalloc(size);\n-\tif (read_fd(0, &buffer, &size)) {\n-\t\tfree(buffer);\n+\tstrbuf_init(&buf);\n+\tif (strbuf_read(&buf, 0) < 0)\n \t\tdie(\"could not read the input\");\n-\t}\n \n-\tsize = stripspace(buffer, size, strip_comments);\n-\twrite_or_die(1, buffer, size);\n-\tif (size)\n-\t\tputc('\\n', stdout);\n+\tstrbuf_setlen(&buf, stripspace(buf.buf, buf.len, strip_comments));\n+\tif (buf.len)\n+\t\tstrbuf_addch(&buf, '\\n');\n \n-\tfree(buffer);\n+\twrite_or_die(1, buf.buf, buf.len);\n+\tstrbuf_release(&buf);\n \treturn 0;\n }\ndiff --git a/builtin-tag.c b/builtin-tag.c\nindex 348919c..1a93037 100644\n--- a/builtin-tag.c\n+++ b/builtin-tag.c\n@@ -8,6 +8,7 @@\n \n #include \"cache.h\"\n #include \"builtin.h\"\n+#include \"strbuf.h\"\n #include \"refs.h\"\n #include \"tag.h\"\n #include \"run-command.h\"\n@@ -17,7 +18,7 @@ static const char builtin_tag_usage[] =\n \n static char signingkey[1000];\n \n-static void launch_editor(const char *path, char **buffer, unsigned long *len)\n+static void launch_editor(const char *path, struct strbuf *buffer)\n {\n \tconst char *editor, *terminal;\n \tstruct child_process child;\n@@ -55,10 +56,8 @@ static void launch_editor(const char *path, char **buffer, unsigned long *len)\n \tfd = open(path, O_RDONLY);\n \tif (fd < 0)\n \t\tdie(\"could not open '%s': %s\", path, strerror(errno));\n-\tif (read_fd(fd, buffer, len)) {\n-\t\tfree(*buffer);\n-\t\tdie(\"could not read message file '%s': %s\",\n-\t\t\t\t\t\tpath, strerror(errno));\n+\tif (strbuf_read(buffer, fd) < 0) {\n+\t\tdie(\"could not read message file '%s': %s\", path, strerror(errno));\n \t}\n \tclose(fd);\n }\n@@ -184,7 +183,7 @@ static int verify_tag(const char *name, const char *ref,\n \treturn 0;\n }\n \n-static ssize_t do_sign(char *buffer, size_t size, size_t max)\n+static int do_sign(struct strbuf *buffer)\n {\n \tstruct child_process gpg;\n \tconst char *args[4];\n@@ -212,17 +211,17 @@ static ssize_t do_sign(char *buffer, size_t size, size_t max)\n \tif (start_command(&gpg))\n \t\treturn error(\"could not run gpg.\");\n \n-\twrite_or_die(gpg.in, buffer, size);\n+\twrite_or_die(gpg.in, buffer->buf, buffer->len);\n \tclose(gpg.in);\n \tgpg.close_in = 0;\n-\tlen = read_in_full(gpg.out, buffer + size, max - size);\n+\tlen = strbuf_read(buffer, gpg.out);\n \n \tfinish_command(&gpg);\n \n-\tif (len == max - size)\n+\tif (len < 0)\n \t\treturn error(\"could not read the entire signature from gpg.\");\n \n-\treturn size + len;\n+\treturn 0;\n }\n \n static const char tag_template[] =\n@@ -245,15 +244,13 @@ static int git_tag_config(const char *var, const char *value)\n \treturn git_default_config(var, value);\n }\n \n-#define MAX_SIGNATURE_LENGTH 1024\n-/* message must be NULL or allocated, it will be reallocated and freed */\n static void create_tag(const unsigned char *object, const char *tag,\n-\t\t       char *message, int sign, unsigned char *result)\n+\t\t       struct strbuf *buf, int message, int sign,\n+\t\t\t   unsigned char *result)\n {\n \tenum object_type type;\n-\tchar header_buf[1024], *buffer = NULL;\n-\tint header_len, max_size;\n-\tunsigned long size = 0;\n+\tchar header_buf[1024];\n+\tint header_len;\n \n \ttype = sha1_object_info(object, NULL);\n \tif (type <= OBJ_NONE)\n@@ -285,52 +282,40 @@ static void create_tag(const unsigned char *object, const char *tag,\n \t\twrite_or_die(fd, tag_template, strlen(tag_template));\n \t\tclose(fd);\n \n-\t\tlaunch_editor(path, &buffer, &size);\n+\t\tlaunch_editor(path, buf);\n \n \t\tunlink(path);\n \t\tfree(path);\n \t}\n-\telse {\n-\t\tbuffer = message;\n-\t\tsize = strlen(message);\n-\t}\n \n-\tsize = stripspace(buffer, size, 1);\n+\tstrbuf_setlen(buf, stripspace(buf->buf, buf->len, 1));\n \n-\tif (!message && !size)\n+\tif (!message && !buf->len)\n \t\tdie(\"no tag message?\");\n \n \t/* insert the header and add the '\\n' if needed: */\n-\tmax_size = header_len + size + (sign ? MAX_SIGNATURE_LENGTH : 0) + 1;\n-\tbuffer = xrealloc(buffer, max_size);\n-\tif (size)\n-\t\tbuffer[size++] = '\\n';\n-\tmemmove(buffer + header_len, buffer, size);\n-\tmemcpy(buffer, header_buf, header_len);\n-\tsize += header_len;\n-\n-\tif (sign) {\n-\t\tsize = do_sign(buffer, size, max_size);\n-\t\tif (size < 0)\n-\t\t\tdie(\"unable to sign the tag\");\n-\t}\n+\tif (buf->len)\n+\t\tstrbuf_addch(buf, '\\n');\n+\tstrbuf_insert(buf, 0, header_buf, header_len);\n \n-\tif (write_sha1_file(buffer, size, tag_type, result) < 0)\n+\tif (sign && do_sign(buf) < 0)\n+\t\tdie(\"unable to sign the tag\");\n+\tif (write_sha1_file(buf->buf, buf->len, tag_type, result) < 0)\n \t\tdie(\"unable to write tag file\");\n-\tfree(buffer);\n }\n \n int cmd_tag(int argc, const char **argv, const char *prefix)\n {\n+\tstruct strbuf buf;\n \tunsigned char object[20], prev[20];\n-\tint annotate = 0, sign = 0, force = 0, lines = 0;\n-\tchar *message = NULL;\n+\tint annotate = 0, sign = 0, force = 0, lines = 0, message = 0;\n \tchar ref[PATH_MAX];\n \tconst char *object_ref, *tag;\n \tint i;\n \tstruct ref_lock *lock;\n \n \tgit_config(git_tag_config);\n+\tstrbuf_init(&buf);\n \n \tfor (i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\n@@ -366,11 +351,11 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \t\t\t\tdie(\"option -m needs an argument.\");\n \t\t\tif (message)\n \t\t\t\tdie(\"only one -F or -m option is allowed.\");\n-\t\t\tmessage = xstrdup(argv[i]);\n+\t\t\tstrbuf_addstr(&buf, argv[i]);\n+\t\t\tmessage = 1;\n \t\t\tcontinue;\n \t\t}\n \t\tif (!strcmp(arg, \"-F\")) {\n-\t\t\tunsigned long len;\n \t\t\tint fd;\n \n \t\t\tannotate = 1;\n@@ -388,12 +373,10 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \t\t\t\t\tdie(\"could not open '%s': %s\",\n \t\t\t\t\t\targv[i], strerror(errno));\n \t\t\t}\n-\t\t\tlen = 1024;\n-\t\t\tmessage = xmalloc(len);\n-\t\t\tif (read_fd(fd, &message, &len)) {\n-\t\t\t\tfree(message);\n+\t\t\tif (strbuf_read(&buf, fd) < 0) {\n \t\t\t\tdie(\"cannot read %s\", argv[i]);\n \t\t\t}\n+\t\t\tmessage = 1;\n \t\t\tcontinue;\n \t\t}\n \t\tif (!strcmp(arg, \"-u\")) {\n@@ -441,7 +424,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \t\tdie(\"tag '%s' already exists\", tag);\n \n \tif (annotate)\n-\t\tcreate_tag(object, tag, message, sign, object);\n+\t\tcreate_tag(object, tag, &buf, message, sign, object);\n \n \tlock = lock_any_ref_for_update(ref, prev, 0);\n \tif (!lock)\n@@ -449,5 +432,6 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \tif (write_ref_sha1(lock, object, NULL) < 0)\n \t\tdie(\"%s: cannot update the ref\", ref);\n \n+\tstrbuf_release(&buf);\n \treturn 0;\n }\ndiff --git a/cache.h b/cache.h\nindex 493983c..231f81d 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -269,7 +269,6 @@ extern int ie_match_stat(struct index_state *, struct cache_entry *, struct stat\n extern int ie_modified(struct index_state *, struct cache_entry *, struct stat *, int);\n extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);\n extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path);\n-extern int read_fd(int fd, char **return_buf, unsigned long *return_size);\n extern int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object);\n extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);\n extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);\ndiff --git a/mktag.c b/mktag.c\nindex 38acd5a..0c29a2b 100644\n--- a/mktag.c\n+++ b/mktag.c\n@@ -1,4 +1,5 @@\n #include \"cache.h\"\n+#include \"strbuf.h\"\n #include \"tag.h\"\n \n /*\n@@ -111,8 +112,7 @@ static int verify_tag(char *buffer, unsigned long size)\n \n int main(int argc, char **argv)\n {\n-\tunsigned long size = 4096;\n-\tchar *buffer = xmalloc(size);\n+\tstruct strbuf buf;\n \tunsigned char result_sha1[20];\n \n \tif (argc != 1)\n@@ -120,21 +120,20 @@ int main(int argc, char **argv)\n \n \tsetup_git_directory();\n \n-\tif (read_fd(0, &buffer, &size)) {\n-\t\tfree(buffer);\n+\tstrbuf_init(&buf);\n+\tif (strbuf_read(&buf, 0) < 0) {\n \t\tdie(\"could not read from stdin\");\n \t}\n \n \t/* Verify it for some basic sanity: it needs to start with\n \t   \"object <sha1>\\ntype\\ntagger \" */\n-\tif (verify_tag(buffer, size) < 0)\n+\tif (verify_tag(buf.buf, buf.len) < 0)\n \t\tdie(\"invalid tag signature file\");\n \n-\tif (write_sha1_file(buffer, size, tag_type, result_sha1) < 0)\n+\tif (write_sha1_file(buf.buf, buf.len, tag_type, result_sha1) < 0)\n \t\tdie(\"unable to write tag file\");\n \n-\tfree(buffer);\n-\n+\tstrbuf_release(&buf);\n \tprintf(\"%s\\n\", sha1_to_hex(result_sha1));\n \treturn 0;\n }\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 9978a58..d011056 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -14,6 +14,7 @@\n #include \"tag.h\"\n #include \"tree.h\"\n #include \"refs.h\"\n+#include \"strbuf.h\"\n \n #ifndef O_NOATIME\n #if defined(__linux__) && (defined(__i386__) || defined(__PPC__))\n@@ -2302,68 +2303,25 @@ int has_sha1_file(const unsigned char *sha1)\n \treturn find_sha1_file(sha1, &st) ? 1 : 0;\n }\n \n-/*\n- * reads from fd as long as possible into a supplied buffer of size bytes.\n- * If necessary the buffer's size is increased using realloc()\n- *\n- * returns 0 if anything went fine and -1 otherwise\n- *\n- * The buffer is always NUL-terminated, not including it in returned size.\n- *\n- * NOTE: both buf and size may change, but even when -1 is returned\n- * you still have to free() it yourself.\n- */\n-int read_fd(int fd, char **return_buf, unsigned long *return_size)\n-{\n-\tchar *buf = *return_buf;\n-\tunsigned long size = *return_size;\n-\tssize_t iret;\n-\tunsigned long off = 0;\n-\n-\tif (!buf || size <= 1) {\n-\t\tsize = 1024;\n-\t\tbuf = xrealloc(buf, size);\n-\t}\n-\n-\tdo {\n-\t\tiret = xread(fd, buf + off, (size - 1) - off);\n-\t\tif (iret > 0) {\n-\t\t\toff += iret;\n-\t\t\tif (off == size - 1) {\n-\t\t\t\tsize = alloc_nr(size);\n-\t\t\t\tbuf = xrealloc(buf, size);\n-\t\t\t}\n-\t\t}\n-\t} while (iret > 0);\n-\n-\tbuf[off] = '\\0';\n-\n-\t*return_buf = buf;\n-\t*return_size = off;\n-\n-\tif (iret < 0)\n-\t\treturn -1;\n-\treturn 0;\n-}\n-\n int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object)\n {\n-\tunsigned long size = 4096;\n-\tchar *buf = xmalloc(size);\n+\tstruct strbuf buf;\n \tint ret;\n \n-\tif (read_fd(fd, &buf, &size)) {\n-\t\tfree(buf);\n+\tstrbuf_init(&buf);\n+\tif (strbuf_read(&buf, fd) < 0) {\n+\t\tstrbuf_release(&buf);\n \t\treturn -1;\n \t}\n \n \tif (!type)\n \t\ttype = blob_type;\n \tif (write_object)\n-\t\tret = write_sha1_file(buf, size, type, sha1);\n+\t\tret = write_sha1_file(buf.buf, buf.len, type, sha1);\n \telse\n-\t\tret = hash_sha1_file(buf, size, type, sha1);\n-\tfree(buf);\n+\t\tret = hash_sha1_file(buf.buf, buf.len, type, sha1);\n+\tstrbuf_release(&buf);\n+\n \treturn ret;\n }\n \n-- \n1.5.3.1\n"},{"id":"53014","messageId":"20070909001205.GD13385@artemis.corp","threadId":"9835","inReplyTo":"11892962763548-git-send-email-madcoder@debian.org","subject":"Re: Use more strbufs series [on top of next]","fromName":"Pierre Habouzit","fromEmail":"madcoder@debian.org","sentAt":"2007-09-09T00:12:05Z","receivedAt":"2007-09-09T00:12:05Z","isPatch":false,"sender":{"key":"madcoder@debian.org","avatar":"https://avatars.githubusercontent.com/u/44708?v=4"},"body":"On Sun, Sep 09, 2007 at 12:04:30AM +0000, Pierre Habouzit wrote:\n>   Here is a series of patches on top of next, which use strbufs in even\n> more places. Most notably, it uses it in the commit pretty printer (and\n> commit message formatter), and it supersedes definitely read_fd\n> (previously in sha1_file.c).\n\n  A side note that could help the patch readers: in some places I've\nmade hunks that basically rename variables called space or size into\nlen. The reason is that (in my coding standards) length is the length of\nthe object we are referring to, whereas space/size/... is the amount of\nmemory we have allocated for it. For a string, the latter is strictly\ngreater than the former because of the ending NUL of course.\n\n  The rename is because my brain is used to this way of thinking and\nthat it helps knowing if the off-by-some (off-by-one for a string) are\nincluded in the length-related number you work with or not. So please\ndon't discard those :)\n-- \n·O·  Pierre Habouzit\n··O                                                madcoder@debian.org\nOOO                                                http://www.madism.org\n"},{"id":"54218","messageId":"alpine.LFD.0.999.0709271554560.3579@woody.linux-foundation.org","threadId":"9835","inReplyTo":"20070910183256.GD32442@artemis.corp","subject":"Re: return void expressions in C (Was: [PATCH 3/6] Rework pretty_print_commit ...)","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-09-27T22:56:32Z","receivedAt":"2007-09-27T22:56:32Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 10 Sep 2007, Pierre Habouzit wrote:\n>\n>   Okay, I stand corrected, but as I'm curious, I've now the Truth about\n> this, for those who still care at that point (as the patch has been\n> fixed in the next round anyways ;p)\n\nThe\n\n\tvoid fn1(void);\n\n\tvoid fn2(void)\n\t{\n\t\treturn fn1();\n\t}\n\nthing is a gcc extension. It happens to be one we use in the kernel too, \nsince it makes for nicer-looking source code in some circumstances, but \nit's definitely nonstandard.\n\n\t\tLinus\n"}]}