refs.h: implement `hidden_refs_to_excludes()`

In subsequent commits, we'll teach `receive-pack` and `upload-pack` to use the new jump list feature in the packed-refs iterator by ignoring references which are mentioned via its respective hideRefs lists. However, the packed-ref jump lists cannot handle un-hiding rules (that begin with '!'), or namespace comparisons (that begin with '^'). Add a convenience function to the refs.h API to detect when either of these conditions are met, and returns an appropriate value to pass as excluded patterns. Suggested-by: Jeff King <peff@peff.net> Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Taylor Blau committed Jul 10, 2023 at 17:12 UTC 15af64dcfd176b65cdb938e9b7f27adb8aabffa4
2 files changed +30
refs.c
+24
@@ -1480,6 +1480,30 @@ int ref_is_hidden(const char *refname, const char *refname_full,
1480 return 0;
1481 }
1482
1483 +const char **hidden_refs_to_excludes(const struct strvec *hide_refs)
1484 +{
1485 + const char **pattern;
1486 + for (pattern = hide_refs->v; *pattern; pattern++) {
1487 + /*
1488 + * We can't feed any excludes from hidden refs config
1489 + * sections, since later rules may override previous
1490 + * ones. For example, with rules "refs/foo" and
1491 + * "!refs/foo/bar", we should show "refs/foo/bar" (and
1492 + * everything underneath it), but the earlier exclusion
1493 + * would cause us to skip all of "refs/foo". We
1494 + * likewise don't implement the namespace stripping
1495 + * required for '^' rules.
1496 + *
1497 + * Both are possible to do, but complicated, so avoid
1498 + * populating the jump list at all if we see either of
1499 + * these patterns.
1500 + */
1501 + if (**pattern == '!' || **pattern == '^')
1502 + return NULL;
1503 + }
1504 + return hide_refs->v;
1505 +}
1506 +
1507 const char *find_descendant_ref(const char *dirname,
1508 const struct string_list *extras,
1509 const struct string_list *skip)
refs.h
+6
@@ -831,6 +831,12 @@ int parse_hide_refs_config(const char *var, const char *value, const char *,
831 */
832 int ref_is_hidden(const char *, const char *, const struct strvec *);
833
834 +/*
835 + * Returns an array of patterns to use as excluded_patterns, if none of the
836 + * hidden references use the token '!' or '^'.
837 + */
838 +const char **hidden_refs_to_excludes(const struct strvec *hide_refs);
839 +
840 /* Is this a per-worktree ref living in the refs/ namespace? */
841 int is_per_worktree_ref(const char *refname);
842