wt-status: move strbuf into read_and_strip_branch()

The strbufs are placed outside read_and_strip_branch as a premature
optimization: when it reads "refs/heads/foo" to strbuf and wants to
return just "foo", it could do so without memory movement. In return
the caller must not use the returned pointer after releasing strbufs,
which own the buffers that contain the returned strings. It's a clumsy
design.

By moving strbufs into read_and_strip_branch(), the returned pointer
always points to a malloc'd buffer or NULL. The pointer can be passed
around and freed after use.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Nguyễn Thái Ngọc Duy 2013-03-16 09:12:36 +07:00 коммит произвёл Junio C Hamano
Родитель cdd76db373
Коммит 8b87cfd000
2 изменённых файлов: 32 добавлений и 37 удалений

Просмотреть файл

@ -967,41 +967,41 @@ static void show_bisect_in_progress(struct wt_status *s,
/* /*
* Extract branch information from rebase/bisect * Extract branch information from rebase/bisect
*/ */
static void read_and_strip_branch(struct strbuf *sb, static char *read_and_strip_branch(const char *path)
const char **branch,
const char *path)
{ {
struct strbuf sb = STRBUF_INIT;
unsigned char sha1[20]; unsigned char sha1[20];
strbuf_reset(sb); if (strbuf_read_file(&sb, git_path("%s", path), 0) <= 0)
if (strbuf_read_file(sb, git_path("%s", path), 0) <= 0) goto got_nothing;
return;
while (sb->len && sb->buf[sb->len - 1] == '\n') while (&sb.len && sb.buf[sb.len - 1] == '\n')
strbuf_setlen(sb, sb->len - 1); strbuf_setlen(&sb, sb.len - 1);
if (!sb->len) if (!sb.len)
return; goto got_nothing;
if (!prefixcmp(sb->buf, "refs/heads/")) if (!prefixcmp(sb.buf, "refs/heads/"))
*branch = sb->buf + strlen("refs/heads/"); strbuf_remove(&sb,0, strlen("refs/heads/"));
else if (!prefixcmp(sb->buf, "refs/")) else if (!prefixcmp(sb.buf, "refs/"))
*branch = sb->buf; ;
else if (!get_sha1_hex(sb->buf, sha1)) { else if (!get_sha1_hex(sb.buf, sha1)) {
const char *abbrev; const char *abbrev;
abbrev = find_unique_abbrev(sha1, DEFAULT_ABBREV); abbrev = find_unique_abbrev(sha1, DEFAULT_ABBREV);
strbuf_reset(sb); strbuf_reset(&sb);
strbuf_addstr(sb, abbrev); strbuf_addstr(&sb, abbrev);
*branch = sb->buf; } else if (!strcmp(sb.buf, "detached HEAD")) /* rebase */
} else if (!strcmp(sb->buf, "detached HEAD")) /* rebase */ goto got_nothing;
;
else /* bisect */ else /* bisect */
*branch = sb->buf; ;
return strbuf_detach(&sb, NULL);
got_nothing:
strbuf_release(&sb);
return NULL;
} }
static void wt_status_print_state(struct wt_status *s) static void wt_status_print_state(struct wt_status *s)
{ {
const char *state_color = color(WT_STATUS_HEADER, s); const char *state_color = color(WT_STATUS_HEADER, s);
struct strbuf branch = STRBUF_INIT;
struct strbuf onto = STRBUF_INIT;
struct wt_status_state state; struct wt_status_state state;
struct stat st; struct stat st;
@ -1016,27 +1016,22 @@ static void wt_status_print_state(struct wt_status *s)
state.am_empty_patch = 1; state.am_empty_patch = 1;
} else { } else {
state.rebase_in_progress = 1; state.rebase_in_progress = 1;
read_and_strip_branch(&branch, &state.branch, state.branch = read_and_strip_branch("rebase-apply/head-name");
"rebase-apply/head-name"); state.onto = read_and_strip_branch("rebase-apply/onto");
read_and_strip_branch(&onto, &state.onto,
"rebase-apply/onto");
} }
} else if (!stat(git_path("rebase-merge"), &st)) { } else if (!stat(git_path("rebase-merge"), &st)) {
if (!stat(git_path("rebase-merge/interactive"), &st)) if (!stat(git_path("rebase-merge/interactive"), &st))
state.rebase_interactive_in_progress = 1; state.rebase_interactive_in_progress = 1;
else else
state.rebase_in_progress = 1; state.rebase_in_progress = 1;
read_and_strip_branch(&branch, &state.branch, state.branch = read_and_strip_branch("rebase-merge/head-name");
"rebase-merge/head-name"); state.onto = read_and_strip_branch("rebase-merge/onto");
read_and_strip_branch(&onto, &state.onto,
"rebase-merge/onto");
} else if (!stat(git_path("CHERRY_PICK_HEAD"), &st)) { } else if (!stat(git_path("CHERRY_PICK_HEAD"), &st)) {
state.cherry_pick_in_progress = 1; state.cherry_pick_in_progress = 1;
} }
if (!stat(git_path("BISECT_LOG"), &st)) { if (!stat(git_path("BISECT_LOG"), &st)) {
state.bisect_in_progress = 1; state.bisect_in_progress = 1;
read_and_strip_branch(&branch, &state.branch, state.branch = read_and_strip_branch("BISECT_START");
"BISECT_START");
} }
if (state.merge_in_progress) if (state.merge_in_progress)
@ -1049,8 +1044,8 @@ static void wt_status_print_state(struct wt_status *s)
show_cherry_pick_in_progress(s, &state, state_color); show_cherry_pick_in_progress(s, &state, state_color);
if (state.bisect_in_progress) if (state.bisect_in_progress)
show_bisect_in_progress(s, &state, state_color); show_bisect_in_progress(s, &state, state_color);
strbuf_release(&branch); free(state.branch);
strbuf_release(&onto); free(state.onto);
} }
void wt_status_print(struct wt_status *s) void wt_status_print(struct wt_status *s)

Просмотреть файл

@ -79,8 +79,8 @@ struct wt_status_state {
int rebase_interactive_in_progress; int rebase_interactive_in_progress;
int cherry_pick_in_progress; int cherry_pick_in_progress;
int bisect_in_progress; int bisect_in_progress;
const char *branch; char *branch;
const char *onto; char *onto;
}; };
void wt_status_prepare(struct wt_status *s); void wt_status_prepare(struct wt_status *s);