From: Junio C Hamano Date: Tue, 8 May 2018 06:59:18 +0000 (+0900) Subject: Merge branch 'ot/libify-get-ref-atom-value' X-Git-Tag: v2.18.0-rc0~101 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/b7da73ac8b953afd788e096b5b216e3bd9845659?hp=-c Merge branch 'ot/libify-get-ref-atom-value' Code restructuring, in preparation for further work. * ot/libify-get-ref-atom-value: ref-filter: libify get_ref_atom_value() ref-filter: add return value to parsers ref-filter: change parsing function error handling ref-filter: add return value && strbuf to handlers ref-filter: start adding strbufs with errors ref-filter: add shortcut to work with strbufs --- b7da73ac8b953afd788e096b5b216e3bd9845659 diff --combined builtin/branch.c index 5bd2a0dd48,c21e5a04a0..efc9ac1922 --- a/builtin/branch.c +++ b/builtin/branch.c @@@ -273,7 -273,7 +273,7 @@@ static int delete_branches(int argc, co bname.buf, (flags & REF_ISBROKEN) ? "broken" : (flags & REF_ISSYMREF) ? target - : find_unique_abbrev(oid.hash, DEFAULT_ABBREV)); + : find_unique_abbrev(&oid, DEFAULT_ABBREV)); } delete_branch_config(bname.buf); @@@ -391,7 -391,6 +391,6 @@@ static void print_ref_list(struct ref_f struct ref_array array; int maxwidth = 0; const char *remote_prefix = ""; - struct strbuf out = STRBUF_INIT; char *to_free = NULL; /* @@@ -419,7 -418,10 +418,10 @@@ ref_array_sort(sorting, &array); for (i = 0; i < array.nr; i++) { - format_ref_array_item(array.items[i], format, &out); + struct strbuf out = STRBUF_INIT; + struct strbuf err = STRBUF_INIT; + if (format_ref_array_item(array.items[i], format, &out, &err)) + die("%s", err.buf); if (column_active(colopts)) { assert(!filter->verbose && "--column and --verbose are incompatible"); /* format to a string_list to let print_columns() do its job */ @@@ -428,6 -430,7 +430,7 @@@ fwrite(out.buf, 1, out.len, stdout); putchar('\n'); } + strbuf_release(&err); strbuf_release(&out); } diff --combined ref-filter.c index ac82f9f21e,3bc65e4935..39e2744c94 --- a/ref-filter.c +++ b/ref-filter.c @@@ -101,22 -101,38 +101,38 @@@ static struct used_atom } *used_atom; static int used_atom_cnt, need_tagged, need_symref; - static void color_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *color_value) + /* + * Expand string, append it to strbuf *sb, then return error code ret. + * Allow to save few lines of code. + */ + static int strbuf_addf_ret(struct strbuf *sb, int ret, const char *fmt, ...) + { + va_list ap; + va_start(ap, fmt); + strbuf_vaddf(sb, fmt, ap); + va_end(ap); + return ret; + } + + static int color_atom_parser(const struct ref_format *format, struct used_atom *atom, + const char *color_value, struct strbuf *err) { if (!color_value) - die(_("expected format: %%(color:)")); + return strbuf_addf_ret(err, -1, _("expected format: %%(color:)")); if (color_parse(color_value, atom->u.color) < 0) - die(_("unrecognized color: %%(color:%s)"), color_value); + return strbuf_addf_ret(err, -1, _("unrecognized color: %%(color:%s)"), + color_value); /* * We check this after we've parsed the color, which lets us complain * about syntactically bogus color names even if they won't be used. */ if (!want_color(format->use_color)) color_parse("", atom->u.color); + return 0; } - static void refname_atom_parser_internal(struct refname_atom *atom, - const char *arg, const char *name) + static int refname_atom_parser_internal(struct refname_atom *atom, const char *arg, + const char *name, struct strbuf *err) { if (!arg) atom->option = R_NORMAL; @@@ -126,16 -142,18 +142,18 @@@ skip_prefix(arg, "strip=", &arg)) { atom->option = R_LSTRIP; if (strtol_i(arg, 10, &atom->lstrip)) - die(_("Integer value expected refname:lstrip=%s"), arg); + return strbuf_addf_ret(err, -1, _("Integer value expected refname:lstrip=%s"), arg); } else if (skip_prefix(arg, "rstrip=", &arg)) { atom->option = R_RSTRIP; if (strtol_i(arg, 10, &atom->rstrip)) - die(_("Integer value expected refname:rstrip=%s"), arg); + return strbuf_addf_ret(err, -1, _("Integer value expected refname:rstrip=%s"), arg); } else - die(_("unrecognized %%(%s) argument: %s"), name, arg); + return strbuf_addf_ret(err, -1, _("unrecognized %%(%s) argument: %s"), name, arg); + return 0; } - static void remote_ref_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg) + static int remote_ref_atom_parser(const struct ref_format *format, struct used_atom *atom, + const char *arg, struct strbuf *err) { struct string_list params = STRING_LIST_INIT_DUP; int i; @@@ -145,9 -163,8 +163,8 @@@ if (!arg) { atom->u.remote_ref.option = RR_REF; - refname_atom_parser_internal(&atom->u.remote_ref.refname, - arg, atom->name); - return; + return refname_atom_parser_internal(&atom->u.remote_ref.refname, + arg, atom->name, err); } atom->u.remote_ref.nobracket = 0; @@@ -170,29 -187,38 +187,38 @@@ atom->u.remote_ref.push_remote = 1; } else { atom->u.remote_ref.option = RR_REF; - refname_atom_parser_internal(&atom->u.remote_ref.refname, - arg, atom->name); + if (refname_atom_parser_internal(&atom->u.remote_ref.refname, + arg, atom->name, err)) { + string_list_clear(¶ms, 0); + return -1; + } } } string_list_clear(¶ms, 0); + return 0; } - static void body_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg) + static int body_atom_parser(const struct ref_format *format, struct used_atom *atom, + const char *arg, struct strbuf *err) { if (arg) - die(_("%%(body) does not take arguments")); + return strbuf_addf_ret(err, -1, _("%%(body) does not take arguments")); atom->u.contents.option = C_BODY_DEP; + return 0; } - static void subject_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg) + static int subject_atom_parser(const struct ref_format *format, struct used_atom *atom, + const char *arg, struct strbuf *err) { if (arg) - die(_("%%(subject) does not take arguments")); + return strbuf_addf_ret(err, -1, _("%%(subject) does not take arguments")); atom->u.contents.option = C_SUB; + return 0; } - static void trailers_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg) + static int trailers_atom_parser(const struct ref_format *format, struct used_atom *atom, + const char *arg, struct strbuf *err) { struct string_list params = STRING_LIST_INIT_DUP; int i; @@@ -205,15 -231,20 +231,20 @@@ atom->u.contents.trailer_opts.unfold = 1; else if (!strcmp(s, "only")) atom->u.contents.trailer_opts.only_trailers = 1; - else - die(_("unknown %%(trailers) argument: %s"), s); + else { + strbuf_addf(err, _("unknown %%(trailers) argument: %s"), s); + string_list_clear(¶ms, 0); + return -1; + } } } atom->u.contents.option = C_TRAILERS; string_list_clear(¶ms, 0); + return 0; } - static void contents_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg) + static int contents_atom_parser(const struct ref_format *format, struct used_atom *atom, + const char *arg, struct strbuf *err) { if (!arg) atom->u.contents.option = C_BARE; @@@ -225,16 -256,19 +256,19 @@@ atom->u.contents.option = C_SUB; else if (skip_prefix(arg, "trailers", &arg)) { skip_prefix(arg, ":", &arg); - trailers_atom_parser(format, atom, *arg ? arg : NULL); + if (trailers_atom_parser(format, atom, *arg ? arg : NULL, err)) + return -1; } else if (skip_prefix(arg, "lines=", &arg)) { atom->u.contents.option = C_LINES; if (strtoul_ui(arg, 10, &atom->u.contents.nlines)) - die(_("positive value expected contents:lines=%s"), arg); + return strbuf_addf_ret(err, -1, _("positive value expected contents:lines=%s"), arg); } else - die(_("unrecognized %%(contents) argument: %s"), arg); + return strbuf_addf_ret(err, -1, _("unrecognized %%(contents) argument: %s"), arg); + return 0; } - static void objectname_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg) + static int objectname_atom_parser(const struct ref_format *format, struct used_atom *atom, + const char *arg, struct strbuf *err) { if (!arg) atom->u.objectname.option = O_FULL; @@@ -244,16 -278,18 +278,18 @@@ atom->u.objectname.option = O_LENGTH; if (strtoul_ui(arg, 10, &atom->u.objectname.length) || atom->u.objectname.length == 0) - die(_("positive value expected objectname:short=%s"), arg); + return strbuf_addf_ret(err, -1, _("positive value expected objectname:short=%s"), arg); if (atom->u.objectname.length < MINIMUM_ABBREV) atom->u.objectname.length = MINIMUM_ABBREV; } else - die(_("unrecognized %%(objectname) argument: %s"), arg); + return strbuf_addf_ret(err, -1, _("unrecognized %%(objectname) argument: %s"), arg); + return 0; } - static void refname_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg) + static int refname_atom_parser(const struct ref_format *format, struct used_atom *atom, + const char *arg, struct strbuf *err) { - refname_atom_parser_internal(&atom->u.refname, arg, atom->name); + return refname_atom_parser_internal(&atom->u.refname, arg, atom->name, err); } static align_type parse_align_position(const char *s) @@@ -267,7 -303,8 +303,8 @@@ return -1; } - static void align_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg) + static int align_atom_parser(const struct ref_format *format, struct used_atom *atom, + const char *arg, struct strbuf *err) { struct align *align = &atom->u.align; struct string_list params = STRING_LIST_INIT_DUP; @@@ -275,7 -312,7 +312,7 @@@ unsigned int width = ~0U; if (!arg) - die(_("expected format: %%(align:,)")); + return strbuf_addf_ret(err, -1, _("expected format: %%(align:,)")); align->position = ALIGN_LEFT; @@@ -286,49 -323,65 +323,65 @@@ if (skip_prefix(s, "position=", &s)) { position = parse_align_position(s); - if (position < 0) - die(_("unrecognized position:%s"), s); + if (position < 0) { + strbuf_addf(err, _("unrecognized position:%s"), s); + string_list_clear(¶ms, 0); + return -1; + } align->position = position; } else if (skip_prefix(s, "width=", &s)) { - if (strtoul_ui(s, 10, &width)) - die(_("unrecognized width:%s"), s); + if (strtoul_ui(s, 10, &width)) { + strbuf_addf(err, _("unrecognized width:%s"), s); + string_list_clear(¶ms, 0); + return -1; + } } else if (!strtoul_ui(s, 10, &width)) ; else if ((position = parse_align_position(s)) >= 0) align->position = position; - else - die(_("unrecognized %%(align) argument: %s"), s); + else { + strbuf_addf(err, _("unrecognized %%(align) argument: %s"), s); + string_list_clear(¶ms, 0); + return -1; + } } - if (width == ~0U) - die(_("positive width expected with the %%(align) atom")); + if (width == ~0U) { + string_list_clear(¶ms, 0); + return strbuf_addf_ret(err, -1, _("positive width expected with the %%(align) atom")); + } align->width = width; string_list_clear(¶ms, 0); + return 0; } - static void if_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg) + static int if_atom_parser(const struct ref_format *format, struct used_atom *atom, + const char *arg, struct strbuf *err) { if (!arg) { atom->u.if_then_else.cmp_status = COMPARE_NONE; - return; + return 0; } else if (skip_prefix(arg, "equals=", &atom->u.if_then_else.str)) { atom->u.if_then_else.cmp_status = COMPARE_EQUAL; } else if (skip_prefix(arg, "notequals=", &atom->u.if_then_else.str)) { atom->u.if_then_else.cmp_status = COMPARE_UNEQUAL; - } else { - die(_("unrecognized %%(if) argument: %s"), arg); - } + } else + return strbuf_addf_ret(err, -1, _("unrecognized %%(if) argument: %s"), arg); + return 0; } - static void head_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg) + static int head_atom_parser(const struct ref_format *format, struct used_atom *atom, + const char *arg, struct strbuf *unused_err) { atom->u.head = resolve_refdup("HEAD", RESOLVE_REF_READING, NULL, NULL); + return 0; } static struct { const char *name; cmp_type cmp_type; - void (*parser)(const struct ref_format *format, struct used_atom *atom, const char *arg); + int (*parser)(const struct ref_format *format, struct used_atom *atom, + const char *arg, struct strbuf *err); } valid_atom[] = { { "refname" , FIELD_STR, refname_atom_parser }, { "objecttype" }, @@@ -387,7 -440,8 +440,8 @@@ struct ref_formatting_state struct atom_value { const char *s; - void (*handler)(struct atom_value *atomv, struct ref_formatting_state *state); + int (*handler)(struct atom_value *atomv, struct ref_formatting_state *state, + struct strbuf *err); uintmax_t value; /* used for sorting when not FIELD_STR */ struct used_atom *atom; }; @@@ -396,7 -450,8 +450,8 @@@ * Used to parse format string and sort specifiers */ static int parse_ref_filter_atom(const struct ref_format *format, - const char *atom, const char *ep) + const char *atom, const char *ep, + struct strbuf *err) { const char *sp; const char *arg; @@@ -406,7 -461,8 +461,8 @@@ if (*sp == '*' && sp < ep) sp++; /* deref */ if (ep <= sp) - die(_("malformed field name: %.*s"), (int)(ep-atom), atom); + return strbuf_addf_ret(err, -1, _("malformed field name: %.*s"), + (int)(ep-atom), atom); /* Do we have the atom already used elsewhere? */ for (i = 0; i < used_atom_cnt; i++) { @@@ -432,7 -488,8 +488,8 @@@ } if (ARRAY_SIZE(valid_atom) <= i) - die(_("unknown field name: %.*s"), (int)(ep-atom), atom); + return strbuf_addf_ret(err, -1, _("unknown field name: %.*s"), + (int)(ep-atom), atom); /* Add it in, including the deref prefix */ at = used_atom_cnt; @@@ -451,8 -508,8 +508,8 @@@ } } memset(&used_atom[at].u, 0, sizeof(used_atom[at].u)); - if (valid_atom[i].parser) - valid_atom[i].parser(format, &used_atom[at], arg); + if (valid_atom[i].parser && valid_atom[i].parser(format, &used_atom[at], arg, err)) + return -1; if (*atom == '*') need_tagged = 1; if (!strcmp(valid_atom[i].name, "symref")) @@@ -481,7 -538,8 +538,8 @@@ static void quote_formatting(struct str } } - static void append_atom(struct atom_value *v, struct ref_formatting_state *state) + static int append_atom(struct atom_value *v, struct ref_formatting_state *state, + struct strbuf *unused_err) { /* * Quote formatting is only done when the stack has a single @@@ -493,6 -551,7 +551,7 @@@ quote_formatting(&state->stack->output, v->s, state->quote_style); else strbuf_addstr(&state->stack->output, v->s); + return 0; } static void push_stack_element(struct ref_formatting_stack **stack) @@@ -527,7 -586,8 +586,8 @@@ static void end_align_handler(struct re strbuf_release(&s); } - static void align_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state) + static int align_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state, + struct strbuf *unused_err) { struct ref_formatting_stack *new_stack; @@@ -535,6 -595,7 +595,7 @@@ new_stack = state->stack; new_stack->at_end = end_align_handler; new_stack->at_end_data = &atomv->atom->u.align; + return 0; } static void if_then_else_handler(struct ref_formatting_stack **stack) @@@ -572,7 -633,8 +633,8 @@@ free(if_then_else); } - static void if_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state) + static int if_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state, + struct strbuf *unused_err) { struct ref_formatting_stack *new_stack; struct if_then_else *if_then_else = xcalloc(sizeof(struct if_then_else), 1); @@@ -584,6 -646,7 +646,7 @@@ new_stack = state->stack; new_stack->at_end = if_then_else_handler; new_stack->at_end_data = if_then_else; + return 0; } static int is_empty(const char *s) @@@ -596,7 -659,8 +659,8 @@@ return 1; } - static void then_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state) + static int then_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state, + struct strbuf *err) { struct ref_formatting_stack *cur = state->stack; struct if_then_else *if_then_else = NULL; @@@ -604,11 -668,11 +668,11 @@@ if (cur->at_end == if_then_else_handler) if_then_else = (struct if_then_else *)cur->at_end_data; if (!if_then_else) - die(_("format: %%(then) atom used without an %%(if) atom")); + return strbuf_addf_ret(err, -1, _("format: %%(then) atom used without an %%(if) atom")); if (if_then_else->then_atom_seen) - die(_("format: %%(then) atom used more than once")); + return strbuf_addf_ret(err, -1, _("format: %%(then) atom used more than once")); if (if_then_else->else_atom_seen) - die(_("format: %%(then) atom used after %%(else)")); + return strbuf_addf_ret(err, -1, _("format: %%(then) atom used after %%(else)")); if_then_else->then_atom_seen = 1; /* * If the 'equals' or 'notequals' attribute is used then @@@ -624,9 -688,11 +688,11 @@@ } else if (cur->output.len && !is_empty(cur->output.buf)) if_then_else->condition_satisfied = 1; strbuf_reset(&cur->output); + return 0; } - static void else_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state) + static int else_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state, + struct strbuf *err) { struct ref_formatting_stack *prev = state->stack; struct if_then_else *if_then_else = NULL; @@@ -634,24 -700,26 +700,26 @@@ if (prev->at_end == if_then_else_handler) if_then_else = (struct if_then_else *)prev->at_end_data; if (!if_then_else) - die(_("format: %%(else) atom used without an %%(if) atom")); + return strbuf_addf_ret(err, -1, _("format: %%(else) atom used without an %%(if) atom")); if (!if_then_else->then_atom_seen) - die(_("format: %%(else) atom used without a %%(then) atom")); + return strbuf_addf_ret(err, -1, _("format: %%(else) atom used without a %%(then) atom")); if (if_then_else->else_atom_seen) - die(_("format: %%(else) atom used more than once")); + return strbuf_addf_ret(err, -1, _("format: %%(else) atom used more than once")); if_then_else->else_atom_seen = 1; push_stack_element(&state->stack); state->stack->at_end_data = prev->at_end_data; state->stack->at_end = prev->at_end; + return 0; } - static void end_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state) + static int end_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state, + struct strbuf *err) { struct ref_formatting_stack *current = state->stack; struct strbuf s = STRBUF_INIT; if (!current->at_end) - die(_("format: %%(end) atom used without corresponding atom")); + return strbuf_addf_ret(err, -1, _("format: %%(end) atom used without corresponding atom")); current->at_end(&state->stack); /* Stack may have been popped within at_end(), hence reset the current pointer */ @@@ -668,6 -736,7 +736,7 @@@ } strbuf_release(&s); pop_stack_element(&state->stack); + return 0; } /* @@@ -702,17 -771,21 +771,21 @@@ int verify_ref_format(struct ref_forma format->need_color_reset_at_eol = 0; for (cp = format->format; *cp && (sp = find_next(cp)); ) { + struct strbuf err = STRBUF_INIT; const char *color, *ep = strchr(sp, ')'); int at; if (!ep) return error(_("malformed format string %s"), sp); /* sp points at "%(" and ep points at the closing ")" */ - at = parse_ref_filter_atom(format, sp + 2, ep); + at = parse_ref_filter_atom(format, sp + 2, ep, &err); + if (at < 0) + die("%s", err.buf); cp = ep + 1; if (skip_prefix(used_atom[at].name, "color:", &color)) format->need_color_reset_at_eol = !!strcmp(color, "reset"); + strbuf_release(&err); } if (format->need_color_reset_at_eol && !want_color(format->use_color)) format->need_color_reset_at_eol = 0; @@@ -728,7 -801,7 +801,7 @@@ static void *get_obj(const struct object_id *oid, struct object **obj, unsigned long *sz, int *eaten) { enum object_type type; - void *buf = read_sha1_file(oid->hash, &type, sz); + void *buf = read_object_file(oid, &type, sz); if (buf) *obj = parse_object_buffer(oid, type, *sz, buf, eaten); @@@ -737,18 -810,18 +810,18 @@@ return buf; } -static int grab_objectname(const char *name, const unsigned char *sha1, +static int grab_objectname(const char *name, const struct object_id *oid, struct atom_value *v, struct used_atom *atom) { if (starts_with(name, "objectname")) { if (atom->u.objectname.option == O_SHORT) { - v->s = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV)); + v->s = xstrdup(find_unique_abbrev(oid, DEFAULT_ABBREV)); return 1; } else if (atom->u.objectname.option == O_FULL) { - v->s = xstrdup(sha1_to_hex(sha1)); + v->s = xstrdup(oid_to_hex(oid)); return 1; } else if (atom->u.objectname.option == O_LENGTH) { - v->s = xstrdup(find_unique_abbrev(sha1, atom->u.objectname.length)); + v->s = xstrdup(find_unique_abbrev(oid, atom->u.objectname.length)); return 1; } else die("BUG: unknown %%(objectname) option"); @@@ -775,7 -848,7 +848,7 @@@ static void grab_common_values(struct a v->s = xstrfmt("%lu", sz); } else if (deref) - grab_objectname(name, obj->oid.hash, v, &used_atom[i]); + grab_objectname(name, &obj->oid, v, &used_atom[i]); } } @@@ -1309,14 -1382,10 +1382,14 @@@ char *get_head_description(void memset(&state, 0, sizeof(state)); wt_status_get_state(&state, 1); if (state.rebase_in_progress || - state.rebase_interactive_in_progress) - strbuf_addf(&desc, _("(no branch, rebasing %s)"), - state.branch); - else if (state.bisect_in_progress) + state.rebase_interactive_in_progress) { + if (state.branch) + strbuf_addf(&desc, _("(no branch, rebasing %s)"), + state.branch); + else + strbuf_addf(&desc, _("(no branch, rebasing detached HEAD %s)"), + state.detached_from); + } else if (state.bisect_in_progress) strbuf_addf(&desc, _("(no branch, bisect started on %s)"), state.branch); else if (state.detached_from) { @@@ -1358,28 -1427,30 +1431,30 @@@ static const char *get_refname(struct u return show_ref(&atom->u.refname, ref->refname); } - static void get_object(struct ref_array_item *ref, const struct object_id *oid, - int deref, struct object **obj) + static int get_object(struct ref_array_item *ref, const struct object_id *oid, + int deref, struct object **obj, struct strbuf *err) { int eaten; + int ret = 0; unsigned long size; void *buf = get_obj(oid, obj, &size, &eaten); if (!buf) - die(_("missing object %s for %s"), - oid_to_hex(oid), ref->refname); - if (!*obj) - die(_("parse_object_buffer failed on %s for %s"), - oid_to_hex(oid), ref->refname); - - grab_values(ref->value, deref, *obj, buf, size); + ret = strbuf_addf_ret(err, -1, _("missing object %s for %s"), + oid_to_hex(oid), ref->refname); + else if (!*obj) + ret = strbuf_addf_ret(err, -1, _("parse_object_buffer failed on %s for %s"), + oid_to_hex(oid), ref->refname); + else + grab_values(ref->value, deref, *obj, buf, size); if (!eaten) free(buf); + return ret; } /* * Parse the object referred by ref, and grab needed value. */ - static void populate_value(struct ref_array_item *ref) + static int populate_value(struct ref_array_item *ref, struct strbuf *err) { struct object *obj; int i; @@@ -1459,7 -1530,7 +1534,7 @@@ v->s = xstrdup(buf + 1); } continue; - } else if (!deref && grab_objectname(name, ref->objectname.hash, v, atom)) { + } else if (!deref && grab_objectname(name, &ref->objectname, v, atom)) { continue; } else if (!strcmp(name, "HEAD")) { if (atom->u.head && !strcmp(ref->refname, atom->u.head)) @@@ -1501,16 -1572,17 +1576,17 @@@ break; } if (used_atom_cnt <= i) - return; + return 0; - get_object(ref, &ref->objectname, 0, &obj); + if (get_object(ref, &ref->objectname, 0, &obj, err)) + return -1; /* * If there is no atom that wants to know about tagged * object, we are done. */ if (!need_tagged || (obj->type != OBJ_TAG)) - return; + return 0; /* * If it is a tag object, see if we use a value that derefs @@@ -1524,20 -1596,23 +1600,23 @@@ * is not consistent with what deref_tag() does * which peels the onion to the core. */ - get_object(ref, tagged, 1, &obj); + return get_object(ref, tagged, 1, &obj, err); } /* * Given a ref, return the value for the atom. This lazily gets value * out of the object by calling populate value. */ - static void get_ref_atom_value(struct ref_array_item *ref, int atom, struct atom_value **v) + static int get_ref_atom_value(struct ref_array_item *ref, int atom, + struct atom_value **v, struct strbuf *err) { if (!ref->value) { - populate_value(ref); + if (populate_value(ref, err)) + return -1; fill_missing_values(ref->value); } *v = &ref->value[atom]; + return 0; } /* @@@ -1828,30 -1903,15 +1907,30 @@@ static const struct object_id *match_po return NULL; } -/* Allocate space for a new ref_array_item and copy the objectname and flag to it */ +/* + * Allocate space for a new ref_array_item and copy the name and oid to it. + * + * Callers can then fill in other struct members at their leisure. + */ static struct ref_array_item *new_ref_array_item(const char *refname, - const unsigned char *objectname, - int flag) + const struct object_id *oid) { struct ref_array_item *ref; + FLEX_ALLOC_STR(ref, refname, refname); - hashcpy(ref->objectname.hash, objectname); - ref->flag = flag; + oidcpy(&ref->objectname, oid); + + return ref; +} + +struct ref_array_item *ref_array_push(struct ref_array *array, + const char *refname, + const struct object_id *oid) +{ + struct ref_array_item *ref = new_ref_array_item(refname, oid); + + ALLOC_GROW(array->items, array->nr + 1, array->alloc); + array->items[array->nr++] = ref; return ref; } @@@ -1946,11 -2006,12 +2025,11 @@@ static int ref_filter_handler(const cha * to do its job and the resulting list may yet to be pruned * by maxcount logic. */ - ref = new_ref_array_item(refname, oid->hash, flag); + ref = ref_array_push(ref_cbdata->array, refname, oid); ref->commit = commit; - - REALLOC_ARRAY(ref_cbdata->array->items, ref_cbdata->array->nr + 1); - ref_cbdata->array->items[ref_cbdata->array->nr++] = ref; + ref->flag = flag; ref->kind = kind; + return 0; } @@@ -2075,9 -2136,13 +2154,13 @@@ static int cmp_ref_sorting(struct ref_s int cmp; cmp_type cmp_type = used_atom[s->atom].type; int (*cmp_fn)(const char *, const char *); + struct strbuf err = STRBUF_INIT; - get_ref_atom_value(a, s->atom, &va); - get_ref_atom_value(b, s->atom, &vb); + if (get_ref_atom_value(a, s->atom, &va, &err)) + die("%s", err.buf); + if (get_ref_atom_value(b, s->atom, &vb, &err)) + die("%s", err.buf); + strbuf_release(&err); cmp_fn = s->ignore_case ? strcasecmp : strcmp; if (s->version) cmp = versioncmp(va->s, vb->s); @@@ -2136,9 -2201,10 +2219,10 @@@ static void append_literal(const char * } } - void format_ref_array_item(struct ref_array_item *info, + int format_ref_array_item(struct ref_array_item *info, const struct ref_format *format, - struct strbuf *final_buf) + struct strbuf *final_buf, + struct strbuf *error_buf) { const char *cp, *sp, *ep; struct ref_formatting_state state = REF_FORMATTING_STATE_INIT; @@@ -2148,14 -2214,17 +2232,17 @@@ for (cp = format->format; *cp && (sp = find_next(cp)); cp = ep + 1) { struct atom_value *atomv; + int pos; ep = strchr(sp, ')'); if (cp < sp) append_literal(cp, sp, &state); - get_ref_atom_value(info, - parse_ref_filter_atom(format, sp + 2, ep), - &atomv); - atomv->handler(atomv, &state); + pos = parse_ref_filter_atom(format, sp + 2, ep, error_buf); + if (pos < 0 || get_ref_atom_value(info, pos, &atomv, error_buf) || + atomv->handler(atomv, &state, error_buf)) { + pop_stack_element(&state.stack); + return -1; + } } if (*cp) { sp = cp + strlen(cp); @@@ -2164,30 -2233,39 +2251,39 @@@ if (format->need_color_reset_at_eol) { struct atom_value resetv; resetv.s = GIT_COLOR_RESET; - append_atom(&resetv, &state); + if (append_atom(&resetv, &state, error_buf)) { + pop_stack_element(&state.stack); + return -1; + } + } + if (state.stack->prev) { + pop_stack_element(&state.stack); + return strbuf_addf_ret(error_buf, -1, _("format: %%(end) atom missing")); } - if (state.stack->prev) - die(_("format: %%(end) atom missing")); strbuf_addbuf(final_buf, &state.stack->output); pop_stack_element(&state.stack); + return 0; } void show_ref_array_item(struct ref_array_item *info, const struct ref_format *format) { struct strbuf final_buf = STRBUF_INIT; + struct strbuf error_buf = STRBUF_INIT; - format_ref_array_item(info, format, &final_buf); + if (format_ref_array_item(info, format, &final_buf, &error_buf)) + die("%s", error_buf.buf); fwrite(final_buf.buf, 1, final_buf.len, stdout); + strbuf_release(&error_buf); strbuf_release(&final_buf); putchar('\n'); } -void pretty_print_ref(const char *name, const unsigned char *sha1, +void pretty_print_ref(const char *name, const struct object_id *oid, const struct ref_format *format) { struct ref_array_item *ref_item; - ref_item = new_ref_array_item(name, sha1, 0); + ref_item = new_ref_array_item(name, oid); ref_item->kind = ref_kind_from_refname(name); show_ref_array_item(ref_item, format); free_array_item(ref_item); @@@ -2201,7 -2279,12 +2297,12 @@@ static int parse_sorting_atom(const cha */ struct ref_format dummy = REF_FORMAT_INIT; const char *end = atom + strlen(atom); - return parse_ref_filter_atom(&dummy, atom, end); + struct strbuf err = STRBUF_INIT; + int res = parse_ref_filter_atom(&dummy, atom, end, &err); + if (res < 0) + die("%s", err.buf); + strbuf_release(&err); + return res; } /* If no sorting option is given, use refname to sort as default */ diff --combined ref-filter.h index 76cf87cb6c,e13f8e6f87..85c8ebc3b9 --- a/ref-filter.h +++ b/ref-filter.h @@@ -110,9 -110,10 +110,10 @@@ int verify_ref_format(struct ref_forma /* Sort the given ref_array as per the ref_sorting provided */ void ref_array_sort(struct ref_sorting *sort, struct ref_array *array); /* Based on the given format and quote_style, fill the strbuf */ - void format_ref_array_item(struct ref_array_item *info, - const struct ref_format *format, - struct strbuf *final_buf); + int format_ref_array_item(struct ref_array_item *info, + const struct ref_format *format, + struct strbuf *final_buf, + struct strbuf *error_buf); /* Print the ref using the given format and quote_style */ void show_ref_array_item(struct ref_array_item *info, const struct ref_format *format); /* Parse a single sort specifier and add it to the list */ @@@ -132,15 -133,7 +133,15 @@@ void setup_ref_filter_porcelain_msg(voi * Print a single ref, outside of any ref-filter. Note that the * name must be a fully qualified refname. */ -void pretty_print_ref(const char *name, const unsigned char *sha1, +void pretty_print_ref(const char *name, const struct object_id *oid, const struct ref_format *format); +/* + * Push a single ref onto the array; this can be used to construct your own + * ref_array without using filter_refs(). + */ +struct ref_array_item *ref_array_push(struct ref_array *array, + const char *refname, + const struct object_id *oid); + #endif /* REF_FILTER_H */