From: Junio C Hamano Date: Tue, 24 Jul 2018 21:50:44 +0000 (-0700) Subject: Merge branch 'jk/for-each-ref-icase' X-Git-Tag: v2.19.0-rc0~138 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/43013305887c2b81858a0741f39872f8ed5f27d6?hp=-c Merge branch 'jk/for-each-ref-icase' The "--ignore-case" option of "git for-each-ref" (and its friends) did not work correctly, which has been fixed. * jk/for-each-ref-icase: ref-filter: avoid backend filtering with --ignore-case for-each-ref: consistently pass WM_IGNORECASE flag t6300: add a test for --ignore-case --- 43013305887c2b81858a0741f39872f8ed5f27d6 diff --combined ref-filter.c index 0ab893a250,85057234ee..492f2b770d --- a/ref-filter.c +++ b/ref-filter.c @@@ -3,7 -3,6 +3,7 @@@ #include "parse-options.h" #include "refs.h" #include "wildmatch.h" +#include "object-store.h" #include "commit.h" #include "remote.h" #include "color.h" @@@ -17,7 -16,6 +17,7 @@@ #include "trailer.h" #include "wt-status.h" #include "commit-slab.h" +#include "commit-graph.h" static struct ref_msg { const char *gone; @@@ -103,38 -101,22 +103,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; @@@ -144,18 -126,16 +144,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; @@@ -165,8 -145,9 +165,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; @@@ -189,38 -170,29 +189,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; @@@ -233,20 -205,15 +233,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; @@@ -258,19 -225,16 +258,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; @@@ -280,18 -244,16 +280,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) @@@ -305,8 -267,7 +305,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; @@@ -314,7 -275,7 +314,7 @@@ unsigned int width = ~0U; if (!arg) - die(_("expected format: %%(align:,)")); + return strbuf_addf_ret(err, -1, _("expected format: %%(align:,)")); align->position = ALIGN_LEFT; @@@ -325,65 -286,49 +325,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" }, @@@ -442,8 -387,7 +442,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; }; @@@ -452,8 -396,7 +452,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; @@@ -463,8 -406,7 +463,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++) { @@@ -490,8 -432,7 +490,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; @@@ -510,8 -451,8 +510,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")) @@@ -540,8 -481,7 +540,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 @@@ -553,7 -493,6 +553,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) @@@ -588,8 -527,7 +588,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; @@@ -597,7 -535,6 +597,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) @@@ -635,8 -572,7 +635,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); @@@ -648,7 -584,6 +648,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) @@@ -661,8 -596,7 +661,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; @@@ -670,11 -604,11 +670,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 @@@ -690,11 -624,9 +690,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; @@@ -702,26 -634,24 +702,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 */ @@@ -738,7 -668,6 +738,7 @@@ } strbuf_release(&s); pop_stack_element(&state->stack); + return 0; } /* @@@ -773,21 -702,17 +773,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; @@@ -803,7 -728,7 +803,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); @@@ -812,21 -737,21 +812,21 @@@ 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"); + BUG("unknown %%(objectname) option"); } return 0; } @@@ -850,7 -775,7 +850,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]); } } @@@ -890,7 -815,7 +890,7 @@@ static void grab_commit_values(struct a if (deref) name++; if (!strcmp(name, "tree")) { - v->s = xstrdup(oid_to_hex(&commit->tree->object.oid)); + v->s = xstrdup(oid_to_hex(get_commit_tree_oid(commit))); } else if (!strcmp(name, "numparent")) { v->value = commit_list_count(commit->parents); @@@ -1374,7 -1299,7 +1374,7 @@@ static void fill_remote_ref_details(str else *s = ""; } else - die("BUG: unhandled RR_* enum"); + BUG("unhandled RR_* enum"); } char *get_head_description(void) @@@ -1384,14 -1309,10 +1384,14 @@@ 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) { @@@ -1433,30 -1354,28 +1433,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; @@@ -1536,7 -1455,7 +1536,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)) @@@ -1578,17 -1497,16 +1578,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 @@@ -1602,23 -1520,20 +1602,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; } /* @@@ -1664,13 -1579,12 +1664,13 @@@ static int in_commit_list(const struct } /* - * Test whether the candidate or one of its parents is contained in the list. + * Test whether the candidate is contained in the list. * Do not recurse to find out, though, but return -1 if inconclusive. */ static enum contains_result contains_test(struct commit *candidate, const struct commit_list *want, - struct contains_cache *cache) + struct contains_cache *cache, + uint32_t cutoff) { enum contains_result *cached = contains_cache_at(cache, candidate); @@@ -1686,10 -1600,6 +1686,10 @@@ /* Otherwise, we don't know; prepare to recurse */ parse_commit_or_die(candidate); + + if (candidate->generation < cutoff) + return CONTAINS_NO; + return CONTAINS_UNKNOWN; } @@@ -1705,18 -1615,8 +1705,18 @@@ static enum contains_result contains_ta struct contains_cache *cache) { struct contains_stack contains_stack = { 0, 0, NULL }; - enum contains_result result = contains_test(candidate, want, cache); + enum contains_result result; + uint32_t cutoff = GENERATION_NUMBER_INFINITY; + const struct commit_list *p; + + for (p = want; p; p = p->next) { + struct commit *c = p->item; + load_commit_graph_info(c); + if (c->generation < cutoff) + cutoff = c->generation; + } + result = contains_test(candidate, want, cache, cutoff); if (result != CONTAINS_UNKNOWN) return result; @@@ -1734,7 -1634,7 +1734,7 @@@ * If we just popped the stack, parents->item has been marked, * therefore contains_test will return a meaningful yes/no. */ - else switch (contains_test(parents->item, want, cache)) { + else switch (contains_test(parents->item, want, cache, cutoff)) { case CONTAINS_YES: *contains_cache_at(cache, commit) = CONTAINS_YES; contains_stack.nr--; @@@ -1748,7 -1648,7 +1748,7 @@@ } } free(contains_stack.contains_stack); - return contains_test(candidate, want, cache); + return contains_test(candidate, want, cache, cutoff); } static int commit_contains(struct ref_filter *filter, struct commit *commit, @@@ -1814,7 -1714,7 +1814,7 @@@ static int match_name_as_path(const str refname[plen] == '/' || p[plen-1] == '/')) return 1; - if (!wildmatch(p, refname, WM_PATHNAME)) + if (!wildmatch(p, refname, flags)) return 1; } return 0; @@@ -1869,6 -1769,15 +1869,15 @@@ static int for_each_fullref_in_pattern( return for_each_fullref_in("", cb, cb_data, broken); } + if (filter->ignore_case) { + /* + * we can't handle case-insensitive comparisons, + * so just return everything and let the caller + * sort it out. + */ + return for_each_fullref_in("", cb, cb_data, broken); + } + if (!filter->name_patterns[0]) { /* no patterns; we have to look at everything */ return for_each_fullref_in("", cb, cb_data, broken); @@@ -1924,30 -1833,15 +1933,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; } @@@ -2042,11 -1936,12 +2051,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; } @@@ -2171,13 -2066,9 +2180,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); @@@ -2236,10 -2127,9 +2245,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; @@@ -2249,17 -2139,14 +2258,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); @@@ -2268,39 -2155,30 +2277,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); @@@ -2314,12 -2192,7 +2323,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 t/t6300-for-each-ref.sh index 48379aa0ee,3bb901d50f..e0496da812 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@@ -310,7 -310,7 +310,7 @@@ test_expect_success 'exercise strftime echo >expected && git for-each-ref --format="%(authordate:format:)" refs/heads >actual && test_cmp expected actual && - long="long format -- $_z40$_z40$_z40$_z40$_z40$_z40$_z40" && + long="long format -- $ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID" && echo $long >expected && git for-each-ref --format="%(authordate:format:$long)" refs/heads >actual && test_cmp expected actual @@@ -795,4 -795,15 +795,15 @@@ test_expect_success ':remotename and :r ) ' + test_expect_success 'for-each-ref --ignore-case ignores case' ' + >expect && + git for-each-ref --format="%(refname)" refs/heads/MASTER >actual && + test_cmp expect actual && + + echo refs/heads/master >expect && + git for-each-ref --format="%(refname)" --ignore-case \ + refs/heads/MASTER >actual && + test_cmp expect actual + ' + test_done