diff options
Diffstat (limited to 'ref-filter.c')
| -rw-r--r-- | ref-filter.c | 99 |
1 files changed, 90 insertions, 9 deletions
diff --git a/ref-filter.c b/ref-filter.c index 54880a2497..b6c6c10127 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -169,6 +169,7 @@ enum atom_type { ATOM_ELSE, ATOM_REST, ATOM_AHEADBEHIND, + ATOM_ISBASE, }; /* @@ -742,8 +743,7 @@ static int person_name_atom_parser(struct ref_format *format UNUSED, return 0; } -static int email_atom_option_parser(struct used_atom *atom, - const char **arg, struct strbuf *err) +static int email_atom_option_parser(const char **arg) { if (!*arg) return EO_RAW; @@ -761,7 +761,7 @@ static int person_email_atom_parser(struct ref_format *format UNUSED, const char *arg, struct strbuf *err) { for (;;) { - int opt = email_atom_option_parser(atom, &arg, err); + int opt = email_atom_option_parser(&arg); const char *bad_arg = arg; if (opt < 0) @@ -891,6 +891,23 @@ static int ahead_behind_atom_parser(struct ref_format *format, return 0; } +static int is_base_atom_parser(struct ref_format *format, + struct used_atom *atom UNUSED, + const char *arg, struct strbuf *err) +{ + struct string_list_item *item; + + if (!arg) + return strbuf_addf_ret(err, -1, _("expected format: %%(is-base:<committish>)")); + + item = string_list_append(&format->is_base_tips, arg); + item->util = lookup_commit_reference_by_name(arg); + if (!item->util) + die("failed to find '%s'", arg); + + return 0; +} + static int head_atom_parser(struct ref_format *format UNUSED, struct used_atom *atom, const char *arg, struct strbuf *err) @@ -956,6 +973,7 @@ static struct { [ATOM_ELSE] = { "else", SOURCE_NONE }, [ATOM_REST] = { "rest", SOURCE_NONE, FIELD_STR, rest_atom_parser }, [ATOM_AHEADBEHIND] = { "ahead-behind", SOURCE_OTHER, FIELD_STR, ahead_behind_atom_parser }, + [ATOM_ISBASE] = { "is-base", SOURCE_OTHER, FIELD_STR, is_base_atom_parser }, /* * Please update $__git_ref_fieldlist in git-completion.bash * when you add new atoms @@ -2341,9 +2359,16 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err) int i; struct object_info empty = OBJECT_INFO_INIT; int ahead_behind_atoms = 0; + int is_base_atoms = 0; CALLOC_ARRAY(ref->value, used_atom_cnt); + /** + * NEEDSWORK: The following code might be unncessary if all codepaths + * that call populate_value() populates the symref member of ref_array_item + * like in apply_ref_filter(). Currently pretty_print_ref() is the only codepath + * that calls populate_value() without first populating symref. + */ if (need_symref && (ref->flag & REF_ISSYMREF) && !ref->symref) { ref->symref = refs_resolve_refdup(get_main_ref_store(the_repository), ref->refname, @@ -2484,6 +2509,15 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err) v->s = xstrdup(""); } continue; + } else if (atom_type == ATOM_ISBASE) { + if (ref->is_base && ref->is_base[is_base_atoms]) { + v->s = xstrfmt("(%s)", ref->is_base[is_base_atoms]); + free(ref->is_base[is_base_atoms]); + } else { + v->s = xstrdup(""); + } + is_base_atoms++; + continue; } else continue; @@ -2784,7 +2818,7 @@ static int filter_ref_kind(struct ref_filter *filter, const char *refname) return ref_kind_from_refname(refname); } -static struct ref_array_item *apply_ref_filter(const char *refname, const struct object_id *oid, +static struct ref_array_item *apply_ref_filter(const char *refname, const char *referent, const struct object_id *oid, int flag, struct ref_filter *filter) { struct ref_array_item *ref; @@ -2853,6 +2887,7 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const struct ref->commit = commit; ref->flag = flag; ref->kind = kind; + ref->symref = xstrdup_or_null(referent); return ref; } @@ -2866,12 +2901,12 @@ struct ref_filter_cbdata { * A call-back given to for_each_ref(). Filter refs and keep them for * later object processing. */ -static int filter_one(const char *refname, const struct object_id *oid, int flag, void *cb_data) +static int filter_one(const char *refname, const char *referent, const struct object_id *oid, int flag, void *cb_data) { struct ref_filter_cbdata *ref_cbdata = cb_data; struct ref_array_item *ref; - ref = apply_ref_filter(refname, oid, flag, ref_cbdata->filter); + ref = apply_ref_filter(refname, referent, oid, flag, ref_cbdata->filter); if (ref) ref_array_append(ref_cbdata->array, ref); @@ -2889,6 +2924,7 @@ static void free_array_item(struct ref_array_item *item) free(item->value); } free(item->counts); + free(item->is_base); free(item); } @@ -2901,13 +2937,13 @@ struct ref_filter_and_format_cbdata { } internal; }; -static int filter_and_format_one(const char *refname, const struct object_id *oid, int flag, void *cb_data) +static int filter_and_format_one(const char *refname, const char *referent, const struct object_id *oid, int flag, void *cb_data) { struct ref_filter_and_format_cbdata *ref_cbdata = cb_data; struct ref_array_item *ref; struct strbuf output = STRBUF_INIT, err = STRBUF_INIT; - ref = apply_ref_filter(refname, oid, flag, ref_cbdata->filter); + ref = apply_ref_filter(refname, referent, oid, flag, ref_cbdata->filter); if (!ref) return 0; @@ -3053,6 +3089,49 @@ void filter_ahead_behind(struct repository *r, free(commits); } +void filter_is_base(struct repository *r, + struct ref_format *format, + struct ref_array *array) +{ + struct commit **bases; + size_t bases_nr = 0; + struct ref_array_item **back_index; + + if (!format->is_base_tips.nr || !array->nr) + return; + + CALLOC_ARRAY(back_index, array->nr); + CALLOC_ARRAY(bases, array->nr); + + for (size_t i = 0; i < array->nr; i++) { + const char *name = array->items[i]->refname; + struct commit *c = lookup_commit_reference_by_name_gently(name, 1); + + CALLOC_ARRAY(array->items[i]->is_base, format->is_base_tips.nr); + + if (!c) + continue; + + back_index[bases_nr] = array->items[i]; + bases[bases_nr] = c; + bases_nr++; + } + + for (size_t i = 0; i < format->is_base_tips.nr; i++) { + struct commit *tip = format->is_base_tips.items[i].util; + int base_index = get_branch_base_for_tip(r, tip, bases, bases_nr); + + if (base_index < 0) + continue; + + /* Store the string for use in output later. */ + back_index[base_index]->is_base[i] = xstrdup(format->is_base_tips.items[i].string); + } + + free(back_index); + free(bases); +} + static int do_filter_refs(struct ref_filter *filter, unsigned int type, each_ref_fn fn, void *cb_data) { int ret = 0; @@ -3146,7 +3225,8 @@ static inline int can_do_iterative_format(struct ref_filter *filter, return !(filter->reachable_from || filter->unreachable_from || sorting || - format->bases.nr); + format->bases.nr || + format->is_base_tips.nr); } void filter_and_format_refs(struct ref_filter *filter, unsigned int type, @@ -3170,6 +3250,7 @@ void filter_and_format_refs(struct ref_filter *filter, unsigned int type, struct ref_array array = { 0 }; filter_refs(&array, filter, type); filter_ahead_behind(the_repository, format, &array); + filter_is_base(the_repository, format, &array); ref_array_sort(sorting, &array); print_formatted_ref_array(&array, format); ref_array_clear(&array); |
