Merge branch 'tb/refs-exclude-fixes'

The refname exclusion logic in the packed-ref backend has been
broken for some time, which confused upload-pack to advertise
different set of refs.  This has been corrected.

* tb/refs-exclude-fixes:
  refs.c: stop matching non-directory prefixes in exclude patterns
  refs.c: remove empty '--exclude' patterns
maint
Junio C Hamano 2025-03-26 16:26:10 +09:00
commit def5e32bc5
2 changed files with 44 additions and 2 deletions

20
refs.c
View File

@ -1699,6 +1699,24 @@ struct ref_iterator *refs_ref_iterator_begin(
enum do_for_each_ref_flags flags)
{
struct ref_iterator *iter;
struct strvec normalized_exclude_patterns = STRVEC_INIT;

if (exclude_patterns) {
for (size_t i = 0; exclude_patterns[i]; i++) {
const char *pattern = exclude_patterns[i];
size_t len = strlen(pattern);
if (!len)
continue;

if (pattern[len - 1] == '/')
strvec_push(&normalized_exclude_patterns, pattern);
else
strvec_pushf(&normalized_exclude_patterns, "%s/",
pattern);
}

exclude_patterns = normalized_exclude_patterns.v;
}

if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
static int ref_paranoia = -1;
@ -1719,6 +1737,8 @@ struct ref_iterator *refs_ref_iterator_begin(
if (trim)
iter = prefix_ref_iterator_begin(iter, "", trim);

strvec_clear(&normalized_exclude_patterns);

return iter;
}


View File

@ -46,6 +46,10 @@ test_expect_success 'setup' '
echo "create refs/heads/$name/$i $base" || return 1
done || return 1
done >in &&
for i in 5 6 7
do
echo "create refs/heads/bar/4/$i $base" || return 1
done >>in &&
echo "delete refs/heads/main" >>in &&

git update-ref --stdin <in &&
@ -99,9 +103,17 @@ test_expect_success 'adjacent, non-overlapping excluded regions' '
esac
'

test_expect_success 'overlapping excluded regions' '
test_expect_success 'non-directory excluded regions' '
for_each_ref__exclude refs/heads refs/heads/ba refs/heads/baz >actual 2>perf &&
for_each_ref refs/heads/foo refs/heads/quux >expect &&
for_each_ref refs/heads/bar refs/heads/foo refs/heads/quux >expect &&

test_cmp expect actual &&
assert_jumps 1 perf
'

test_expect_success 'overlapping excluded regions' '
for_each_ref__exclude refs/heads refs/heads/bar refs/heads/bar/4 >actual 2>perf &&
for_each_ref refs/heads/baz refs/heads/foo refs/heads/quux >expect &&

test_cmp expect actual &&
assert_jumps 1 perf
@ -155,4 +167,14 @@ test_expect_success 'meta-characters are discarded' '
assert_no_jumps perf
'

test_expect_success 'empty string exclude pattern is ignored' '
git update-ref refs/heads/loose $(git rev-parse refs/heads/foo/1) &&

for_each_ref__exclude refs/heads "" >actual 2>perf &&
for_each_ref >expect &&

test_cmp expect actual &&
assert_no_jumps perf
'

test_done