Re: [PATCH 08/17] refs: generalize `refs_for_each_namespaced_ref()`
- From
Karthik Nayak <karthik.188@gmail.com>
- Date
- Feb 23, 2026, 09:02 UTC
- Message-ID
- <CAOLa=ZQjZ-YLedF=Cqn=Tb8-rhX8=+Lnd2VKv0fn_ryrO563_g@mail.gmail.com>
- In-Reply-To
- <20260220-pks-refs-for-each-unification-v1-8-17170bd99de1@pks.im>
Patrick Steinhardt <ps@pks.im> writes:
Show 54 quoted lines
> The function `refs_for_each_namespaced_ref()` iterates through all
> references that are part of the current ref namespace. This namespace
> can be configured by setting the `GIT_NAMESPACE` environment variable
> and is then retrieved by calling `get_git_namespace()`.
>
> If a namespace is configured, then we:
>
> - Obviously only yield refs that exist in this namespace.
>
> - Rewrite exclude patterns so that they work for the given namespace,
> if any namespace is currently configured.
>
> Port this logic to `refs_for_each_ref_ext()` by adding a new `namespace`
> field to the options structure. This gives callers more flexibility as
> they can decide by themselves whether they want to use the globally
> configured or an arbitrary other namespace.
>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
> refs.c | 47 +++++++++++++++++++++++++++++------------------
> refs.h | 6 ++++++
> 2 files changed, 35 insertions(+), 18 deletions(-)
>
> diff --git a/refs.c b/refs.c
> index ac34bbe6c1..99994879d9 100644
> --- a/refs.c
> +++ b/refs.c
> @@ -1845,9 +1845,13 @@ int refs_for_each_ref_ext(struct ref_store *refs,
> refs_for_each_cb cb, void *cb_data,
> const struct refs_for_each_ref_options *opts)
> {
> + struct strvec namespaced_exclude_patterns = STRVEC_INIT;
> + struct strbuf namespaced_prefix = STRBUF_INIT;
> struct strbuf real_pattern = STRBUF_INIT;
> struct for_each_ref_filter filter;
> struct ref_iterator *iter;
> + const char **exclude_patterns;
> + const char *prefix;
> int ret;
>
> if (!refs)
> @@ -1876,11 +1880,29 @@ int refs_for_each_ref_ext(struct ref_store *refs,
> cb_data = &filter;
> }
>
> - iter = refs_ref_iterator_begin(refs, opts->prefix ? opts->prefix : "",
> - opts->exclude_patterns,
> + if (opts->namespace) {
> + strbuf_addstr(&namespaced_prefix, opts->namespace);
> + if (opts->prefix)
> + strbuf_addstr(&namespaced_prefix, opts->prefix);
> + else
> + strbuf_addstr(&namespaced_prefix, "refs/");
> +So if the namespace is 'foo', we'll have the namespace folder as 'refs/namespace/foo', and a prefix of 'refs/heads/' would mean that the 'namespaced_prefix' is now 'refs/namespace/foo/refs/heads'. Looks good.
Show 60 quoted lines
> + prefix = namespaced_prefix.buf;
> + exclude_patterns = get_namespaced_exclude_patterns(opts->exclude_patterns,
> + opts->namespace,
> + &namespaced_exclude_patterns);
> + } else {
> + prefix = opts->prefix ? opts->prefix : "";
> + exclude_patterns = opts->exclude_patterns;
> + }
> +
> + iter = refs_ref_iterator_begin(refs, prefix, exclude_patterns,
> opts->trim_prefix, opts->flags);
>
> ret = do_for_each_ref_iterator(iter, cb, cb_data);
> +
> + strvec_clear(&namespaced_exclude_patterns);
> + strbuf_release(&namespaced_prefix);
> strbuf_release(&real_pattern);
> return ret;
> }
> @@ -1927,22 +1949,11 @@ int refs_for_each_namespaced_ref(struct ref_store *refs,
> const char **exclude_patterns,
> refs_for_each_cb cb, void *cb_data)
> {
> - struct refs_for_each_ref_options opts = { 0 };
> - struct strvec namespaced_exclude_patterns = STRVEC_INIT;
> - struct strbuf prefix = STRBUF_INIT;
> - int ret;
> -
> - opts.exclude_patterns = get_namespaced_exclude_patterns(exclude_patterns,
> - get_git_namespace(),
> - &namespaced_exclude_patterns);
> - strbuf_addf(&prefix, "%srefs/", get_git_namespace());
> - opts.prefix = prefix.buf;
> -
> - ret = refs_for_each_ref_ext(refs, cb, cb_data, &opts);
> -
> - strvec_clear(&namespaced_exclude_patterns);
> - strbuf_release(&prefix);
> - return ret;
> + struct refs_for_each_ref_options opts = {
> + .exclude_patterns = exclude_patterns,
> + .namespace = get_git_namespace(),
> + };
> + return refs_for_each_ref_ext(refs, cb, cb_data, &opts);
> }
>
> int refs_for_each_rawref(struct ref_store *refs, refs_for_each_cb fn, void *cb_data)
> diff --git a/refs.h b/refs.h
> index a66dbf3865..2bde60aa0e 100644
> --- a/refs.h
> +++ b/refs.h
> @@ -468,6 +468,12 @@ struct refs_for_each_ref_options {
> */
> const char *pattern;
>
> + /*
> + * If set, only yield refs part of the configured namespace. Exclude
> + * patterns will be rewritten to apply to the namespace.
> + */
> + const char *namespace;Nit: should we also mention how prefix is appended to namespace?
Show 7 quoted lines
> + > /* > * Exclude any references that match any of these patterns on a > * best-effort basis. The caller needs to be prepared for the exclude > > -- > 2.53.0.414.gf7e9f6c205.dirty