Jeff King <peff@xxxxxxxx> writes: > On Tue, Mar 29, 2016 at 09:30:38PM -0400, Eric Sunshine wrote: > >> The implementation of strbuf_list_free() is this: >> >> struct strbuf **s = sbs; >> while (*s) { >> strbuf_release(*s); >> free(*s++); >> } >> free(sbs); >> >> which means that wt-status.c is leaking not only 'split', but also >> each element of split[], right? > > Yeah, I didn't notice that, but I think you're right. Correct. I suspect that we would be better off in the longer term if we made conscious effort to deprecate and eradicate the use of strbuf_split* API functions. They are easy to write crappy code with, inefficient, and error prone. You would rarely need to have N resulting pieces as strbufs to be easily manipulatable [*1*]. The function can be written by not using the "split and then rebuild" pattern, perhaps like so, and the result is even easier to read and understand, I would say. A sample rewrite is attached at the end. [Footnote] *1* I wouldn't be this harsh if the function were to fill an array of pointers or offsets into the original string. wt-status.c | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/wt-status.c b/wt-status.c index ef74864..4886c35 100644 --- a/wt-status.c +++ b/wt-status.c @@ -1037,35 +1037,30 @@ static int split_commit_in_progress(struct wt_status *s) */ static void abbrev_sha1_in_line(struct strbuf *line) { - struct strbuf **split; - int i; + const char *cp, *ep, *abbrev; + unsigned char sha1[20]; - if (starts_with(line->buf, "exec ") || - starts_with(line->buf, "x ")) + /* the oddball "exec" does not have 40-hex as the second token */ + if (starts_with(line->buf, "exec ") || starts_with(line->buf, "x ")) return; - split = strbuf_split_max(line, ' ', 3); - if (split[0] && split[1]) { - unsigned char sha1[20]; - const char *abbrev; + /* find the second token on the line */ + cp = strchr(line->buf, ' '); + if (!cp) + return; + cp++; + ep = strchr(cp, ' '); + if (!ep) + return; - /* - * strbuf_split_max left a space. Trim it and re-add - * it after abbreviation. - */ - strbuf_trim(split[1]); - if (!get_sha1(split[1]->buf, sha1)) { - abbrev = find_unique_abbrev(sha1, DEFAULT_ABBREV); - strbuf_reset(split[1]); - strbuf_addf(split[1], "%s ", abbrev); - strbuf_reset(line); - for (i = 0; split[i]; i++) - strbuf_addf(line, "%s", split[i]->buf); - } - } - for (i = 0; split[i]; i++) - strbuf_release(split[i]); + /* is it 40-hex? */ + if (ep - cp != GIT_SHA1_HEXSZ || get_sha1_hex(cp, sha1)) + return; + /* replace it with its abbreviation */ + abbrev = find_unique_abbrev(sha1, DEFAULT_ABBREV); + strbuf_splice(line, cp - line->buf, GIT_SHA1_HEXSZ, + abbrev, strlen(abbrev)); } static void read_rebase_todolist(const char *fname, struct string_list *lines) -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html