169
ATOM_ELSE,
170
ATOM_REST,
171
ATOM_AHEADBEHIND,
172
+ ATOM_ISBASE,
173
};
174
175
/*
892
return 0;
893
}
894
895
+static int is_base_atom_parser(struct ref_format *format,
896
+ struct used_atom *atom UNUSED,
897
+ const char *arg, struct strbuf *err)
898
+{
899
+ struct string_list_item *item;
900
+
901
+ if (!arg)
902
+ return strbuf_addf_ret(err, -1, _("expected format: %%(is-base:<committish>)"));
903
+
904
+ item = string_list_append(&format->is_base_tips, arg);
905
+ item->util = lookup_commit_reference_by_name(arg);
906
+ if (!item->util)
907
+ die("failed to find '%s'", arg);
908
+
909
+ return 0;
910
+}
911
+
912
static int head_atom_parser(struct ref_format *format UNUSED,
913
struct used_atom *atom,
914
const char *arg, struct strbuf *err)
974
[ATOM_ELSE] = { "else", SOURCE_NONE },
975
[ATOM_REST] = { "rest", SOURCE_NONE, FIELD_STR, rest_atom_parser },
976
[ATOM_AHEADBEHIND] = { "ahead-behind", SOURCE_OTHER, FIELD_STR, ahead_behind_atom_parser },
977
+ [ATOM_ISBASE] = { "is-base", SOURCE_OTHER, FIELD_STR, is_base_atom_parser },
978
/*
979
* Please update $__git_ref_fieldlist in git-completion.bash
980
* when you add new atoms
2359
int i;
2360
struct object_info empty = OBJECT_INFO_INIT;
2361
int ahead_behind_atoms = 0;
2362
+ int is_base_atoms = 0;
2363
2364
CALLOC_ARRAY(ref->value, used_atom_cnt);
2365
2503
v->s = xstrdup("");
2504
}
2505
continue;
2506
+ } else if (atom_type == ATOM_ISBASE) {
2507
+ if (ref->is_base && ref->is_base[is_base_atoms]) {
2508
+ v->s = xstrfmt("(%s)", ref->is_base[is_base_atoms]);
2509
+ free(ref->is_base[is_base_atoms]);
2510
+ } else {
2511
+ v->s = xstrdup("");
2512
+ }
2513
+ is_base_atoms++;
2514
+ continue;
2515
} else
2516
continue;
2517
2917
free(item->value);
2918
}
2919
free(item->counts);
2920
+ free(item->is_base);
2921
free(item);
2922
}
2923
3082
free(commits);
3083
}
3084
3085
+void filter_is_base(struct repository *r,
3086
+ struct ref_format *format,
3087
+ struct ref_array *array)
3088
+{
3089
+ struct commit **bases;
3090
+ size_t bases_nr = 0;
3091
+ struct ref_array_item **back_index;
3092
+
3093
+ if (!format->is_base_tips.nr || !array->nr)
3094
+ return;
3095
+
3096
+ CALLOC_ARRAY(back_index, array->nr);
3097
+ CALLOC_ARRAY(bases, array->nr);
3098
+
3099
+ for (size_t i = 0; i < array->nr; i++) {
3100
+ const char *name = array->items[i]->refname;
3101
+ struct commit *c = lookup_commit_reference_by_name_gently(name, 1);
3102
+
3103
+ CALLOC_ARRAY(array->items[i]->is_base, format->is_base_tips.nr);
3104
+
3105
+ if (!c)
3106
+ continue;
3107
+
3108
+ back_index[bases_nr] = array->items[i];
3109
+ bases[bases_nr] = c;
3110
+ bases_nr++;
3111
+ }
3112
+
3113
+ for (size_t i = 0; i < format->is_base_tips.nr; i++) {
3114
+ struct commit *tip = format->is_base_tips.items[i].util;
3115
+ int base_index = get_branch_base_for_tip(r, tip, bases, bases_nr);
3116
+
3117
+ if (base_index < 0)
3118
+ continue;
3119
+
3120
+ /* Store the string for use in output later. */
3121
+ back_index[base_index]->is_base[i] = xstrdup(format->is_base_tips.items[i].string);
3122
+ }
3123
+
3124
+ free(back_index);
3125
+ free(bases);
3126
+}
3127
+
3128
static int do_filter_refs(struct ref_filter *filter, unsigned int type, each_ref_fn fn, void *cb_data)
3129
{
3130
int ret = 0;
3218
return !(filter->reachable_from ||
3219
filter->unreachable_from ||
3220
sorting ||
3148
- format->bases.nr);
3221
+ format->bases.nr ||
3222
+ format->is_base_tips.nr);
3223
}
3224
3225
void filter_and_format_refs(struct ref_filter *filter, unsigned int type,
3243
struct ref_array array = { 0 };
3244
filter_refs(&array, filter, type);
3245
filter_ahead_behind(the_repository, format, &array);
3246
+ filter_is_base(the_repository, format, &array);
3247
ref_array_sort(sorting, &array);
3248
print_formatted_ref_array(&array, format);
3249
ref_array_clear(&array);