On Tue, Mar 04, 2025 at 12:38:50PM +0100, Patrick Steinhardt wrote: > On Tue, Mar 04, 2025 at 02:51:46AM -0500, Jeff King wrote: > > On Tue, Mar 04, 2025 at 02:51:14AM -0500, Jeff King wrote: > > > > > From your reproduction, it looks like the issue is that for loose refs, > > > asking for_each_ref() to exclude "refs/heads/foo" will not yield > > > "refs/heads/foo/bar", but will yield "refs/heads/foo-bar". > > > > > > And that was true for packed-refs, too, before 59c35fac54 > > > (refs/packed-backend.c: implement jump lists to avoid excluded > > > pattern(s), 2023-07-10). After that, packed-refs exclude both. > > > > Oh, and of course it would be interesting to know how reftables behave > > here, too, as I think they recently learned about exclusions. > > Well, we have tests that explicitly verify that prefixes cause us to > exclude such refs in t1419, "overlapping exclude regions". So the > reftable backend is bug-compatible :) > > Guess we'll need something similar to the following: > > diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c > index 7e90e13f745..45462f2ce6d 100644 > --- a/refs/reftable-backend.c > +++ b/refs/reftable-backend.c > @@ -594,6 +594,16 @@ static int should_exclude_current_ref(struct reftable_ref_iterator *iter) > if (cmp < 0) > return 0; > > + /* > + * The exclude pattern needs to either match exactly, or, if it > + * is a prefix of the given reference, it must be a containing > + * directory. > + */ > + if (iter->ref.refname[iter->exclude_patterns_strlen] && > + pattern[iter->exclude_patterns_strlen - 1] != '/' && > + iter->ref.refname[iter->exclude_patterns_strlen] != '/') > + return 0; > + > /* > * The reference shares a prefix with the exclude pattern and > * shall thus be omitted. We skip all references that match the Ah, makes sense. Thanks, both, for looking a little deeper. I can work on a fix shortly... Thanks, Taylor