ref-filter.c: refactor to create common helper functions
Factor out parts of 'ref_array_push()', 'ref_filter_handler()', and 'filter_refs()' into new helper functions: * Extract the code to grow a 'struct ref_array' and append a given 'struct ref_array_item *' to it from 'ref_array_push()' into 'ref_array_append()'. * Extract the code to filter a given ref by refname & object ID then create a new 'struct ref_array_item *' from 'filter_one()' into 'apply_ref_filter()'. * Extract the code for filter pre-processing, contains cache creation, and ref iteration from 'filter_refs()' into 'do_filter_refs()'. In later patches, these helpers will be used by new ref-filter API functions. This patch does not result in any user-facing behavior changes or changes to callers outside of 'ref-filter.c'. Signed-off-by: Victoria Dye <vdye@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
9c575b0202
commit
613d991549
183
ref-filter.c
183
ref-filter.c
@ -2632,15 +2632,18 @@ static struct ref_array_item *new_ref_array_item(const char *refname,
|
|||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ref_array_append(struct ref_array *array, struct ref_array_item *ref)
|
||||||
|
{
|
||||||
|
ALLOC_GROW(array->items, array->nr + 1, array->alloc);
|
||||||
|
array->items[array->nr++] = ref;
|
||||||
|
}
|
||||||
|
|
||||||
struct ref_array_item *ref_array_push(struct ref_array *array,
|
struct ref_array_item *ref_array_push(struct ref_array *array,
|
||||||
const char *refname,
|
const char *refname,
|
||||||
const struct object_id *oid)
|
const struct object_id *oid)
|
||||||
{
|
{
|
||||||
struct ref_array_item *ref = new_ref_array_item(refname, oid);
|
struct ref_array_item *ref = new_ref_array_item(refname, oid);
|
||||||
|
ref_array_append(array, ref);
|
||||||
ALLOC_GROW(array->items, array->nr + 1, array->alloc);
|
|
||||||
array->items[array->nr++] = ref;
|
|
||||||
|
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2677,6 +2680,70 @@ static int filter_ref_kind(struct ref_filter *filter, const char *refname)
|
|||||||
return ref_kind_from_refname(refname);
|
return ref_kind_from_refname(refname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct ref_array_item *apply_ref_filter(const char *refname, const struct object_id *oid,
|
||||||
|
int flag, struct ref_filter *filter)
|
||||||
|
{
|
||||||
|
struct ref_array_item *ref;
|
||||||
|
struct commit *commit = NULL;
|
||||||
|
unsigned int kind;
|
||||||
|
|
||||||
|
if (flag & REF_BAD_NAME) {
|
||||||
|
warning(_("ignoring ref with broken name %s"), refname);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag & REF_ISBROKEN) {
|
||||||
|
warning(_("ignoring broken ref %s"), refname);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Obtain the current ref kind from filter_ref_kind() and ignore unwanted refs. */
|
||||||
|
kind = filter_ref_kind(filter, refname);
|
||||||
|
if (!(kind & filter->kind))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!filter_pattern_match(filter, refname))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (filter_exclude_match(filter, refname))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (filter->points_at.nr && !match_points_at(&filter->points_at, oid, refname))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A merge filter is applied on refs pointing to commits. Hence
|
||||||
|
* obtain the commit using the 'oid' available and discard all
|
||||||
|
* non-commits early. The actual filtering is done later.
|
||||||
|
*/
|
||||||
|
if (filter->reachable_from || filter->unreachable_from ||
|
||||||
|
filter->with_commit || filter->no_commit || filter->verbose) {
|
||||||
|
commit = lookup_commit_reference_gently(the_repository, oid, 1);
|
||||||
|
if (!commit)
|
||||||
|
return NULL;
|
||||||
|
/* We perform the filtering for the '--contains' option... */
|
||||||
|
if (filter->with_commit &&
|
||||||
|
!commit_contains(filter, commit, filter->with_commit, &filter->internal.contains_cache))
|
||||||
|
return NULL;
|
||||||
|
/* ...or for the `--no-contains' option */
|
||||||
|
if (filter->no_commit &&
|
||||||
|
commit_contains(filter, commit, filter->no_commit, &filter->internal.no_contains_cache))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We do not open the object yet; sort may only need refname
|
||||||
|
* to do its job and the resulting list may yet to be pruned
|
||||||
|
* by maxcount logic.
|
||||||
|
*/
|
||||||
|
ref = new_ref_array_item(refname, oid);
|
||||||
|
ref->commit = commit;
|
||||||
|
ref->flag = flag;
|
||||||
|
ref->kind = kind;
|
||||||
|
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
struct ref_filter_cbdata {
|
struct ref_filter_cbdata {
|
||||||
struct ref_array *array;
|
struct ref_array *array;
|
||||||
struct ref_filter *filter;
|
struct ref_filter *filter;
|
||||||
@ -2689,64 +2756,11 @@ struct ref_filter_cbdata {
|
|||||||
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 struct object_id *oid, int flag, void *cb_data)
|
||||||
{
|
{
|
||||||
struct ref_filter_cbdata *ref_cbdata = cb_data;
|
struct ref_filter_cbdata *ref_cbdata = cb_data;
|
||||||
struct ref_filter *filter = ref_cbdata->filter;
|
|
||||||
struct ref_array_item *ref;
|
struct ref_array_item *ref;
|
||||||
struct commit *commit = NULL;
|
|
||||||
unsigned int kind;
|
|
||||||
|
|
||||||
if (flag & REF_BAD_NAME) {
|
ref = apply_ref_filter(refname, oid, flag, ref_cbdata->filter);
|
||||||
warning(_("ignoring ref with broken name %s"), refname);
|
if (ref)
|
||||||
return 0;
|
ref_array_append(ref_cbdata->array, ref);
|
||||||
}
|
|
||||||
|
|
||||||
if (flag & REF_ISBROKEN) {
|
|
||||||
warning(_("ignoring broken ref %s"), refname);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Obtain the current ref kind from filter_ref_kind() and ignore unwanted refs. */
|
|
||||||
kind = filter_ref_kind(filter, refname);
|
|
||||||
if (!(kind & filter->kind))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!filter_pattern_match(filter, refname))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (filter_exclude_match(filter, refname))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (filter->points_at.nr && !match_points_at(&filter->points_at, oid, refname))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A merge filter is applied on refs pointing to commits. Hence
|
|
||||||
* obtain the commit using the 'oid' available and discard all
|
|
||||||
* non-commits early. The actual filtering is done later.
|
|
||||||
*/
|
|
||||||
if (filter->reachable_from || filter->unreachable_from ||
|
|
||||||
filter->with_commit || filter->no_commit || filter->verbose) {
|
|
||||||
commit = lookup_commit_reference_gently(the_repository, oid, 1);
|
|
||||||
if (!commit)
|
|
||||||
return 0;
|
|
||||||
/* We perform the filtering for the '--contains' option... */
|
|
||||||
if (filter->with_commit &&
|
|
||||||
!commit_contains(filter, commit, filter->with_commit, &filter->internal.contains_cache))
|
|
||||||
return 0;
|
|
||||||
/* ...or for the `--no-contains' option */
|
|
||||||
if (filter->no_commit &&
|
|
||||||
commit_contains(filter, commit, filter->no_commit, &filter->internal.no_contains_cache))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We do not open the object yet; sort may only need refname
|
|
||||||
* to do its job and the resulting list may yet to be pruned
|
|
||||||
* by maxcount logic.
|
|
||||||
*/
|
|
||||||
ref = ref_array_push(ref_cbdata->array, refname, oid);
|
|
||||||
ref->commit = commit;
|
|
||||||
ref->flag = flag;
|
|
||||||
ref->kind = kind;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2883,26 +2897,12 @@ void filter_ahead_behind(struct repository *r,
|
|||||||
free(commits);
|
free(commits);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static int do_filter_refs(struct ref_filter *filter, unsigned int type, each_ref_fn fn, void *cb_data)
|
||||||
* API for filtering a set of refs. Based on the type of refs the user
|
|
||||||
* has requested, we iterate through those refs and apply filters
|
|
||||||
* as per the given ref_filter structure and finally store the
|
|
||||||
* filtered refs in the ref_array structure.
|
|
||||||
*/
|
|
||||||
int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int type)
|
|
||||||
{
|
{
|
||||||
struct ref_filter_cbdata ref_cbdata;
|
|
||||||
int save_commit_buffer_orig;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
ref_cbdata.array = array;
|
|
||||||
ref_cbdata.filter = filter;
|
|
||||||
|
|
||||||
filter->kind = type & FILTER_REFS_KIND_MASK;
|
filter->kind = type & FILTER_REFS_KIND_MASK;
|
||||||
|
|
||||||
save_commit_buffer_orig = save_commit_buffer;
|
|
||||||
save_commit_buffer = 0;
|
|
||||||
|
|
||||||
init_contains_cache(&filter->internal.contains_cache);
|
init_contains_cache(&filter->internal.contains_cache);
|
||||||
init_contains_cache(&filter->internal.no_contains_cache);
|
init_contains_cache(&filter->internal.no_contains_cache);
|
||||||
|
|
||||||
@ -2917,20 +2917,43 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int
|
|||||||
* of filter_ref_kind().
|
* of filter_ref_kind().
|
||||||
*/
|
*/
|
||||||
if (filter->kind == FILTER_REFS_BRANCHES)
|
if (filter->kind == FILTER_REFS_BRANCHES)
|
||||||
ret = for_each_fullref_in("refs/heads/", filter_one, &ref_cbdata);
|
ret = for_each_fullref_in("refs/heads/", fn, cb_data);
|
||||||
else if (filter->kind == FILTER_REFS_REMOTES)
|
else if (filter->kind == FILTER_REFS_REMOTES)
|
||||||
ret = for_each_fullref_in("refs/remotes/", filter_one, &ref_cbdata);
|
ret = for_each_fullref_in("refs/remotes/", fn, cb_data);
|
||||||
else if (filter->kind == FILTER_REFS_TAGS)
|
else if (filter->kind == FILTER_REFS_TAGS)
|
||||||
ret = for_each_fullref_in("refs/tags/", filter_one, &ref_cbdata);
|
ret = for_each_fullref_in("refs/tags/", fn, cb_data);
|
||||||
else if (filter->kind & FILTER_REFS_ALL)
|
else if (filter->kind & FILTER_REFS_ALL)
|
||||||
ret = for_each_fullref_in_pattern(filter, filter_one, &ref_cbdata);
|
ret = for_each_fullref_in_pattern(filter, fn, cb_data);
|
||||||
if (!ret && (filter->kind & FILTER_REFS_DETACHED_HEAD))
|
if (!ret && (filter->kind & FILTER_REFS_DETACHED_HEAD))
|
||||||
head_ref(filter_one, &ref_cbdata);
|
head_ref(fn, cb_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_contains_cache(&filter->internal.contains_cache);
|
clear_contains_cache(&filter->internal.contains_cache);
|
||||||
clear_contains_cache(&filter->internal.no_contains_cache);
|
clear_contains_cache(&filter->internal.no_contains_cache);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* API for filtering a set of refs. Based on the type of refs the user
|
||||||
|
* has requested, we iterate through those refs and apply filters
|
||||||
|
* as per the given ref_filter structure and finally store the
|
||||||
|
* filtered refs in the ref_array structure.
|
||||||
|
*/
|
||||||
|
int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int type)
|
||||||
|
{
|
||||||
|
struct ref_filter_cbdata ref_cbdata;
|
||||||
|
int save_commit_buffer_orig;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ref_cbdata.array = array;
|
||||||
|
ref_cbdata.filter = filter;
|
||||||
|
|
||||||
|
save_commit_buffer_orig = save_commit_buffer;
|
||||||
|
save_commit_buffer = 0;
|
||||||
|
|
||||||
|
ret = do_filter_refs(filter, type, filter_one, &ref_cbdata);
|
||||||
|
|
||||||
/* Filters that need revision walking */
|
/* Filters that need revision walking */
|
||||||
reach_filter(array, &filter->reachable_from, INCLUDE_REACHED);
|
reach_filter(array, &filter->reachable_from, INCLUDE_REACHED);
|
||||||
reach_filter(array, &filter->unreachable_from, EXCLUDE_REACHED);
|
reach_filter(array, &filter->unreachable_from, EXCLUDE_REACHED);
|
||||||
|
Reference in New Issue
Block a user