Merge branch 'tb/ls-refs-optim'
The ls-refs protocol operation has been optimized to narrow the sub-hierarchy of refs/ it walks to produce response. * tb/ls-refs-optim: ls-refs.c: traverse prefixes of disjoint "ref-prefix" sets ls-refs.c: initialize 'prefixes' before using it refs: expose 'for_each_fullref_in_prefixes'
This commit is contained in:
74
ref-filter.c
74
ref-filter.c
@ -1920,64 +1920,6 @@ static int filter_pattern_match(struct ref_filter *filter, const char *refname)
|
||||
return match_pattern(filter, refname);
|
||||
}
|
||||
|
||||
static int qsort_strcmp(const void *va, const void *vb)
|
||||
{
|
||||
const char *a = *(const char **)va;
|
||||
const char *b = *(const char **)vb;
|
||||
|
||||
return strcmp(a, b);
|
||||
}
|
||||
|
||||
static void find_longest_prefixes_1(struct string_list *out,
|
||||
struct strbuf *prefix,
|
||||
const char **patterns, size_t nr)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
char c = patterns[i][prefix->len];
|
||||
if (!c || is_glob_special(c)) {
|
||||
string_list_append(out, prefix->buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (i < nr) {
|
||||
size_t end;
|
||||
|
||||
/*
|
||||
* Set "end" to the index of the element _after_ the last one
|
||||
* in our group.
|
||||
*/
|
||||
for (end = i + 1; end < nr; end++) {
|
||||
if (patterns[i][prefix->len] != patterns[end][prefix->len])
|
||||
break;
|
||||
}
|
||||
|
||||
strbuf_addch(prefix, patterns[i][prefix->len]);
|
||||
find_longest_prefixes_1(out, prefix, patterns + i, end - i);
|
||||
strbuf_setlen(prefix, prefix->len - 1);
|
||||
|
||||
i = end;
|
||||
}
|
||||
}
|
||||
|
||||
static void find_longest_prefixes(struct string_list *out,
|
||||
const char **patterns)
|
||||
{
|
||||
struct strvec sorted = STRVEC_INIT;
|
||||
struct strbuf prefix = STRBUF_INIT;
|
||||
|
||||
strvec_pushv(&sorted, patterns);
|
||||
QSORT(sorted.v, sorted.nr, qsort_strcmp);
|
||||
|
||||
find_longest_prefixes_1(out, &prefix, sorted.v, sorted.nr);
|
||||
|
||||
strvec_clear(&sorted);
|
||||
strbuf_release(&prefix);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the same as for_each_fullref_in(), but it tries to iterate
|
||||
* only over the patterns we'll care about. Note that it _doesn't_ do a full
|
||||
@ -1988,10 +1930,6 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
|
||||
void *cb_data,
|
||||
int broken)
|
||||
{
|
||||
struct string_list prefixes = STRING_LIST_INIT_DUP;
|
||||
struct string_list_item *prefix;
|
||||
int ret;
|
||||
|
||||
if (!filter->match_as_path) {
|
||||
/*
|
||||
* in this case, the patterns are applied after
|
||||
@ -2015,16 +1953,8 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
|
||||
return for_each_fullref_in("", cb, cb_data, broken);
|
||||
}
|
||||
|
||||
find_longest_prefixes(&prefixes, filter->name_patterns);
|
||||
|
||||
for_each_string_list_item(prefix, &prefixes) {
|
||||
ret = for_each_fullref_in(prefix->string, cb, cb_data, broken);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
string_list_clear(&prefixes, 0);
|
||||
return ret;
|
||||
return for_each_fullref_in_prefixes(NULL, filter->name_patterns,
|
||||
cb, cb_data, broken);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user