Merge branch 'tb/refs-exclusion-and-packed-refs'
Enumerating refs in the packed-refs file, while excluding refs that match certain patterns, has been optimized. * tb/refs-exclusion-and-packed-refs: ls-refs.c: avoid enumerating hidden refs where possible upload-pack.c: avoid enumerating hidden refs where possible builtin/receive-pack.c: avoid enumerating hidden references refs.h: implement `hidden_refs_to_excludes()` refs.h: let `for_each_namespaced_ref()` take excluded patterns revision.h: store hidden refs in a `strvec` refs/packed-backend.c: add trace2 counters for jump list refs/packed-backend.c: implement jump lists to avoid excluded pattern(s) refs/packed-backend.c: refactor `find_reference_location()` refs: plumb `exclude_patterns` argument throughout builtin/for-each-ref.c: add `--exclude` option ref-filter.c: parameterize match functions over patterns ref-filter: add `ref_filter_clear()` ref-filter: clear reachable list pointers after freeing ref-filter.h: provide `REF_FILTER_INIT` refs.c: rename `ref_filter`
This commit is contained in:
66
ref-filter.c
66
ref-filter.c
@ -2225,12 +2225,12 @@ static int get_ref_atom_value(struct ref_array_item *ref, int atom,
|
||||
* matches a pattern "refs/heads/mas") or a wildcard (e.g. the same ref
|
||||
* matches "refs/heads/mas*", too).
|
||||
*/
|
||||
static int match_pattern(const struct ref_filter *filter, const char *refname)
|
||||
static int match_pattern(const char **patterns, const char *refname,
|
||||
int ignore_case)
|
||||
{
|
||||
const char **patterns = filter->name_patterns;
|
||||
unsigned flags = 0;
|
||||
|
||||
if (filter->ignore_case)
|
||||
if (ignore_case)
|
||||
flags |= WM_CASEFOLD;
|
||||
|
||||
/*
|
||||
@ -2255,13 +2255,13 @@ static int match_pattern(const struct ref_filter *filter, const char *refname)
|
||||
* matches a pattern "refs/heads/" but not "refs/heads/m") or a
|
||||
* wildcard (e.g. the same ref matches "refs/heads/m*", too).
|
||||
*/
|
||||
static int match_name_as_path(const struct ref_filter *filter, const char *refname)
|
||||
static int match_name_as_path(const char **pattern, const char *refname,
|
||||
int ignore_case)
|
||||
{
|
||||
const char **pattern = filter->name_patterns;
|
||||
int namelen = strlen(refname);
|
||||
unsigned flags = WM_PATHNAME;
|
||||
|
||||
if (filter->ignore_case)
|
||||
if (ignore_case)
|
||||
flags |= WM_CASEFOLD;
|
||||
|
||||
for (; *pattern; pattern++) {
|
||||
@ -2286,8 +2286,20 @@ static int filter_pattern_match(struct ref_filter *filter, const char *refname)
|
||||
if (!*filter->name_patterns)
|
||||
return 1; /* No pattern always matches */
|
||||
if (filter->match_as_path)
|
||||
return match_name_as_path(filter, refname);
|
||||
return match_pattern(filter, refname);
|
||||
return match_name_as_path(filter->name_patterns, refname,
|
||||
filter->ignore_case);
|
||||
return match_pattern(filter->name_patterns, refname,
|
||||
filter->ignore_case);
|
||||
}
|
||||
|
||||
static int filter_exclude_match(struct ref_filter *filter, const char *refname)
|
||||
{
|
||||
if (!filter->exclude.nr)
|
||||
return 0;
|
||||
if (filter->match_as_path)
|
||||
return match_name_as_path(filter->exclude.v, refname,
|
||||
filter->ignore_case);
|
||||
return match_pattern(filter->exclude.v, refname, filter->ignore_case);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2319,11 +2331,13 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
|
||||
|
||||
if (!filter->name_patterns[0]) {
|
||||
/* no patterns; we have to look at everything */
|
||||
return for_each_fullref_in("", cb, cb_data);
|
||||
return refs_for_each_fullref_in(get_main_ref_store(the_repository),
|
||||
"", filter->exclude.v, cb, cb_data);
|
||||
}
|
||||
|
||||
return refs_for_each_fullref_in_prefixes(get_main_ref_store(the_repository),
|
||||
NULL, filter->name_patterns,
|
||||
filter->exclude.v,
|
||||
cb, cb_data);
|
||||
}
|
||||
|
||||
@ -2457,6 +2471,9 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid,
|
||||
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;
|
||||
|
||||
@ -2539,13 +2556,13 @@ void ref_array_clear(struct ref_array *array)
|
||||
#define EXCLUDE_REACHED 0
|
||||
#define INCLUDE_REACHED 1
|
||||
static void reach_filter(struct ref_array *array,
|
||||
struct commit_list *check_reachable,
|
||||
struct commit_list **check_reachable,
|
||||
int include_reached)
|
||||
{
|
||||
int i, old_nr;
|
||||
struct commit **to_clear;
|
||||
|
||||
if (!check_reachable)
|
||||
if (!*check_reachable)
|
||||
return;
|
||||
|
||||
CALLOC_ARRAY(to_clear, array->nr);
|
||||
@ -2555,7 +2572,7 @@ static void reach_filter(struct ref_array *array,
|
||||
}
|
||||
|
||||
tips_reachable_from_bases(the_repository,
|
||||
check_reachable,
|
||||
*check_reachable,
|
||||
to_clear, array->nr,
|
||||
UNINTERESTING);
|
||||
|
||||
@ -2576,8 +2593,8 @@ static void reach_filter(struct ref_array *array,
|
||||
|
||||
clear_commit_marks_many(old_nr, to_clear, ALL_REV_FLAGS);
|
||||
|
||||
while (check_reachable) {
|
||||
struct commit *merge_commit = pop_commit(&check_reachable);
|
||||
while (*check_reachable) {
|
||||
struct commit *merge_commit = pop_commit(check_reachable);
|
||||
clear_commit_marks(merge_commit, ALL_REV_FLAGS);
|
||||
}
|
||||
|
||||
@ -2674,8 +2691,8 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int
|
||||
clear_contains_cache(&ref_cbdata.no_contains_cache);
|
||||
|
||||
/* Filters that need revision walking */
|
||||
reach_filter(array, filter->reachable_from, INCLUDE_REACHED);
|
||||
reach_filter(array, filter->unreachable_from, EXCLUDE_REACHED);
|
||||
reach_filter(array, &filter->reachable_from, INCLUDE_REACHED);
|
||||
reach_filter(array, &filter->unreachable_from, EXCLUDE_REACHED);
|
||||
|
||||
save_commit_buffer = save_commit_buffer_orig;
|
||||
return ret;
|
||||
@ -2987,3 +3004,20 @@ int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ref_filter_init(struct ref_filter *filter)
|
||||
{
|
||||
struct ref_filter blank = REF_FILTER_INIT;
|
||||
memcpy(filter, &blank, sizeof(blank));
|
||||
}
|
||||
|
||||
void ref_filter_clear(struct ref_filter *filter)
|
||||
{
|
||||
strvec_clear(&filter->exclude);
|
||||
oid_array_clear(&filter->points_at);
|
||||
free_commit_list(filter->with_commit);
|
||||
free_commit_list(filter->no_commit);
|
||||
free_commit_list(filter->reachable_from);
|
||||
free_commit_list(filter->unreachable_from);
|
||||
ref_filter_init(filter);
|
||||
}
|
||||
|
Reference in New Issue
Block a user