]> git.ipfire.org Git - thirdparty/git.git/commitdiff
refs: generalize `refs_for_each_namespaced_ref()`
authorPatrick Steinhardt <ps@pks.im>
Mon, 23 Feb 2026 11:59:42 +0000 (12:59 +0100)
committerJunio C Hamano <gitster@pobox.com>
Mon, 23 Feb 2026 21:21:18 +0000 (13:21 -0800)
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>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
refs.c
refs.h

diff --git a/refs.c b/refs.c
index e4402d787f51eb3a0b4b408c3d5634b34f032e0e..0d0f0edbfb114000ffc4f0886aae8c6bbf90f9e5 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -1848,10 +1848,14 @@ 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;
        size_t trim_prefix = opts->trim_prefix;
+       const char **exclude_patterns;
+       const char *prefix;
        int ret;
 
        if (!refs)
@@ -1886,11 +1890,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/");
+
+               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,
                                       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;
 }
@@ -1937,22 +1959,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 a66dbf38652def28ba07cc47c680b0dfc99f901d..5a5fb4e1e426b834295e624a2cfcc4a222f106d5 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -468,6 +468,13 @@ 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, and the prefix
+        * will be considered relative to the namespace.
+        */
+       const char *namespace;
+
        /*
         * Exclude any references that match any of these patterns on a
         * best-effort basis. The caller needs to be prepared for the exclude