Skip to content

Commit 16b1985

Browse files
ttaylorrgitster
authored andcommitted
refs: expose 'for_each_fullref_in_prefixes'
This function was used in the ref-filter.c code to find the longest common prefix of among a set of refspecs, and then to iterate all of the references that descend from that prefix. A future patch will want to use that same code from ls-refs.c, so prepare by exposing and moving it to refs.c. Since there is nothing specific to the ref-filter code here (other than that it was previously the only caller of this function), this really belongs in the more generic refs.h header. The code moved in this patch is identical before and after, with the one exception of renaming some arguments to be consistent with other functions exposed in refs.h. Signed-off-by: Taylor Blau <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 71ca53e commit 16b1985

File tree

3 files changed

+98
-72
lines changed

3 files changed

+98
-72
lines changed

ref-filter.c

Lines changed: 2 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,64 +1929,6 @@ static int filter_pattern_match(struct ref_filter *filter, const char *refname)
19291929
return match_pattern(filter, refname);
19301930
}
19311931

1932-
static int qsort_strcmp(const void *va, const void *vb)
1933-
{
1934-
const char *a = *(const char **)va;
1935-
const char *b = *(const char **)vb;
1936-
1937-
return strcmp(a, b);
1938-
}
1939-
1940-
static void find_longest_prefixes_1(struct string_list *out,
1941-
struct strbuf *prefix,
1942-
const char **patterns, size_t nr)
1943-
{
1944-
size_t i;
1945-
1946-
for (i = 0; i < nr; i++) {
1947-
char c = patterns[i][prefix->len];
1948-
if (!c || is_glob_special(c)) {
1949-
string_list_append(out, prefix->buf);
1950-
return;
1951-
}
1952-
}
1953-
1954-
i = 0;
1955-
while (i < nr) {
1956-
size_t end;
1957-
1958-
/*
1959-
* Set "end" to the index of the element _after_ the last one
1960-
* in our group.
1961-
*/
1962-
for (end = i + 1; end < nr; end++) {
1963-
if (patterns[i][prefix->len] != patterns[end][prefix->len])
1964-
break;
1965-
}
1966-
1967-
strbuf_addch(prefix, patterns[i][prefix->len]);
1968-
find_longest_prefixes_1(out, prefix, patterns + i, end - i);
1969-
strbuf_setlen(prefix, prefix->len - 1);
1970-
1971-
i = end;
1972-
}
1973-
}
1974-
1975-
static void find_longest_prefixes(struct string_list *out,
1976-
const char **patterns)
1977-
{
1978-
struct strvec sorted = STRVEC_INIT;
1979-
struct strbuf prefix = STRBUF_INIT;
1980-
1981-
strvec_pushv(&sorted, patterns);
1982-
QSORT(sorted.v, sorted.nr, qsort_strcmp);
1983-
1984-
find_longest_prefixes_1(out, &prefix, sorted.v, sorted.nr);
1985-
1986-
strvec_clear(&sorted);
1987-
strbuf_release(&prefix);
1988-
}
1989-
19901932
/*
19911933
* This is the same as for_each_fullref_in(), but it tries to iterate
19921934
* only over the patterns we'll care about. Note that it _doesn't_ do a full
@@ -1997,10 +1939,6 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
19971939
void *cb_data,
19981940
int broken)
19991941
{
2000-
struct string_list prefixes = STRING_LIST_INIT_DUP;
2001-
struct string_list_item *prefix;
2002-
int ret;
2003-
20041942
if (!filter->match_as_path) {
20051943
/*
20061944
* in this case, the patterns are applied after
@@ -2024,16 +1962,8 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
20241962
return for_each_fullref_in("", cb, cb_data, broken);
20251963
}
20261964

2027-
find_longest_prefixes(&prefixes, filter->name_patterns);
2028-
2029-
for_each_string_list_item(prefix, &prefixes) {
2030-
ret = for_each_fullref_in(prefix->string, cb, cb_data, broken);
2031-
if (ret)
2032-
break;
2033-
}
2034-
2035-
string_list_clear(&prefixes, 0);
2036-
return ret;
1965+
return for_each_fullref_in_prefixes(NULL, filter->name_patterns,
1966+
cb, cb_data, broken);
20371967
}
20381968

20391969
/*

refs.c

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,6 +1546,93 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
15461546
return refs_for_each_rawref(get_main_ref_store(the_repository), fn, cb_data);
15471547
}
15481548

1549+
static int qsort_strcmp(const void *va, const void *vb)
1550+
{
1551+
const char *a = *(const char **)va;
1552+
const char *b = *(const char **)vb;
1553+
1554+
return strcmp(a, b);
1555+
}
1556+
1557+
static void find_longest_prefixes_1(struct string_list *out,
1558+
struct strbuf *prefix,
1559+
const char **patterns, size_t nr)
1560+
{
1561+
size_t i;
1562+
1563+
for (i = 0; i < nr; i++) {
1564+
char c = patterns[i][prefix->len];
1565+
if (!c || is_glob_special(c)) {
1566+
string_list_append(out, prefix->buf);
1567+
return;
1568+
}
1569+
}
1570+
1571+
i = 0;
1572+
while (i < nr) {
1573+
size_t end;
1574+
1575+
/*
1576+
* Set "end" to the index of the element _after_ the last one
1577+
* in our group.
1578+
*/
1579+
for (end = i + 1; end < nr; end++) {
1580+
if (patterns[i][prefix->len] != patterns[end][prefix->len])
1581+
break;
1582+
}
1583+
1584+
strbuf_addch(prefix, patterns[i][prefix->len]);
1585+
find_longest_prefixes_1(out, prefix, patterns + i, end - i);
1586+
strbuf_setlen(prefix, prefix->len - 1);
1587+
1588+
i = end;
1589+
}
1590+
}
1591+
1592+
static void find_longest_prefixes(struct string_list *out,
1593+
const char **patterns)
1594+
{
1595+
struct strvec sorted = STRVEC_INIT;
1596+
struct strbuf prefix = STRBUF_INIT;
1597+
1598+
strvec_pushv(&sorted, patterns);
1599+
QSORT(sorted.v, sorted.nr, qsort_strcmp);
1600+
1601+
find_longest_prefixes_1(out, &prefix, sorted.v, sorted.nr);
1602+
1603+
strvec_clear(&sorted);
1604+
strbuf_release(&prefix);
1605+
}
1606+
1607+
int for_each_fullref_in_prefixes(const char *namespace,
1608+
const char **patterns,
1609+
each_ref_fn fn, void *cb_data,
1610+
unsigned int broken)
1611+
{
1612+
struct string_list prefixes = STRING_LIST_INIT_DUP;
1613+
struct string_list_item *prefix;
1614+
struct strbuf buf = STRBUF_INIT;
1615+
int ret = 0, namespace_len;
1616+
1617+
find_longest_prefixes(&prefixes, patterns);
1618+
1619+
if (namespace)
1620+
strbuf_addstr(&buf, namespace);
1621+
namespace_len = buf.len;
1622+
1623+
for_each_string_list_item(prefix, &prefixes) {
1624+
strbuf_addstr(&buf, prefix->string);
1625+
ret = for_each_fullref_in(buf.buf, fn, cb_data, broken);
1626+
if (ret)
1627+
break;
1628+
strbuf_setlen(&buf, namespace_len);
1629+
}
1630+
1631+
string_list_clear(&prefixes, 0);
1632+
strbuf_release(&buf);
1633+
return ret;
1634+
}
1635+
15491636
static int refs_read_special_head(struct ref_store *ref_store,
15501637
const char *refname, struct object_id *oid,
15511638
struct strbuf *referent, unsigned int *type)

refs.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,15 @@ int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
347347
int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data,
348348
unsigned int broken);
349349

350+
/**
351+
* iterate all refs in "patterns" by partitioning patterns into disjoint sets
352+
* and iterating the longest-common prefix of each set.
353+
*
354+
* callers should be prepared to ignore references that they did not ask for.
355+
*/
356+
int for_each_fullref_in_prefixes(const char *namespace, const char **patterns,
357+
each_ref_fn fn, void *cb_data,
358+
unsigned int broken);
350359
/**
351360
* iterate refs from the respective area.
352361
*/

0 commit comments

Comments
 (0)