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:
Junio C Hamano
2021-02-05 16:40:45 -08:00
4 changed files with 103 additions and 73 deletions

View File

@ -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);
}
/*