From: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
To: git@vger.kernel.org
Cc: jltobler@gmail.com, lucasseikioshiro@gmail.com,
K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
Subject: [GSoC Patch] repo: support category-based prefix querying for info keys
Date: Fri, 3 Jul 2026 22:17:09 +0530 [thread overview]
Message-ID: <20260703164709.22723-1-jayatheerthkulkarni2005@gmail.com> (raw)
Currently, git repo info relies on an all-or-nothing query model
where users must either know the exact, fully-qualified key name or use
the --all flag to dump the entire repository state.
As the number of supported keys expands, dumping all metadata and
relying on external filters like grep becomes an inefficient bottleneck
for a plumbing command.
Enable category-based prefix querying so users can request
entire groups of related keys natively
Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
Hi!
This patch adds category-based prefix querying to
`git repo info` as part of my GSoC project.
A quick note on the implementation: I replaced the `bsearch` with
a linear search to find the initial prefix match.
I discussed this with my mentors, and we decided to fall back
to a linear search because the overhead of a custom binary search
(to find the *first* match in a block) wasn't justified given
the currently small size of the `repo_info_field` array.
Since the array is strictly sorted alphabetically,
the loop safely short-circuits via `strncmp`
once it steps outside the matching prefix block.
Looking forward to feedback!
Documentation/git-repo.adoc | 12 ++++++++
builtin/repo.c | 58 +++++++++++++++++++++++--------------
t/t1900-repo-info.sh | 16 ++++++++++
3 files changed, 64 insertions(+), 22 deletions(-)
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 42262c1983..3e840d6323 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -25,6 +25,12 @@ COMMANDS
the requested data will be returned based on their keys (see "INFO KEYS"
section below).
+
+If a `<key>` argument matches a category prefix (i.e. a namespace that ends at
+a `.` boundary), all keys within that namespace are returned. For example,
+`layout` returns both `layout.bare` and `layout.shallow`. The prefix must
+align with a namespace boundary; partial prefixes that do not end at a `.`
+separator (e.g. `lay`) are treated as unknown keys and will produce an error.
++
The values are returned in the same order in which their respective keys were
requested. The `--all` flag requests the values for all the available keys.
+
@@ -126,6 +132,12 @@ using the `nul` format:
git repo info --format=nul layout.bare layout.shallow
------------
+* Retrieves all keys under the `layout` category prefix:
++
+------------
+git repo info layout
+------------
+
SEE ALSO
--------
linkgit:git-rev-parse[1]
diff --git a/builtin/repo.c b/builtin/repo.c
index 71a5c1c29c..91ea5b5459 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -90,24 +90,27 @@ static const struct repo_info_field repo_info_field[] = {
{ "references.format", get_references_format },
};
-static int repo_info_field_cmp(const void *va, const void *vb)
+static int is_valid_prefix_match(const char *key, const char *prefix)
{
- const struct repo_info_field *a = va;
- const struct repo_info_field *b = vb;
+ size_t prefix_len = strlen(prefix);
- return strcmp(a->key, b->key);
+ if (!prefix_len)
+ return 0;
+
+ if (strncmp(key, prefix, prefix_len))
+ return 0;
+
+ return key[prefix_len] == '\0' || prefix[prefix_len - 1] == '.' || key[prefix_len] == '.';
}
-static const struct repo_info_field *get_repo_info_field(const char *key)
+static size_t find_first_repo_info_field_match(const char *prefix)
{
- const struct repo_info_field search_key = { key, NULL };
- const struct repo_info_field *found = bsearch(&search_key,
- repo_info_field,
- ARRAY_SIZE(repo_info_field),
- sizeof(*found),
- repo_info_field_cmp);
-
- return found;
+ for (size_t i = 0; i < ARRAY_SIZE(repo_info_field); i++) {
+ if (is_valid_prefix_match(repo_info_field[i].key, prefix)) {
+ return i;
+ }
+ }
+ return SIZE_MAX;
}
static void print_field(enum output_format format, const char *key,
@@ -135,17 +138,28 @@ static int print_fields(int argc, const char **argv,
struct strbuf valbuf = STRBUF_INIT;
for (int i = 0; i < argc; i++) {
- const char *key = argv[i];
- const struct repo_info_field *field = get_repo_info_field(key);
-
- if (!field) {
- ret = error(_("key '%s' not found"), key);
- continue;
+ const char *prefix = argv[i];
+ size_t prefix_len = strlen(prefix);
+ size_t idx = find_first_repo_info_field_match(prefix);
+ int found = 0;
+
+ for (; idx < ARRAY_SIZE(repo_info_field); idx++) {
+ const struct repo_info_field *field = &repo_info_field[idx];
+
+ if (strncmp(field->key, prefix, prefix_len))
+ break;
+
+ if (is_valid_prefix_match(field->key, prefix)) {
+ strbuf_reset(&valbuf);
+ field->get_value(repo, &valbuf);
+ print_field(format, field->key, valbuf.buf);
+ found = 1;
+ }
}
- strbuf_reset(&valbuf);
- field->get_value(repo, &valbuf);
- print_field(format, key, valbuf.buf);
+ if (!found) {
+ ret = error(_("key '%s' not found"), prefix);
+ }
}
strbuf_release(&valbuf);
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 39bb77dda0..80ae8f8396 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -149,6 +149,22 @@ test_expect_success 'git repo info --keys uses lines as its default output forma
test_cmp expect actual
'
+test_expect_success 'git repo info with category prefix returns all keys in namespace' '
+ cat >expect <<-\EOF &&
+ layout.bare=false
+ layout.shallow=false
+ EOF
+ git init prefix-repo &&
+ git -C prefix-repo repo info layout >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git repo info with invalid partial boundary fails' '
+ echo "error: key ${SQ}lay${SQ} not found" >expect &&
+ test_must_fail git -C prefix-repo repo info lay 2>actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'git repo info -h shows only repo info usage' '
test_must_fail git repo info -h >actual &&
test_grep "git repo info" actual &&
--
2.55.0-rc1
next reply other threads:[~2026-07-03 16:47 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-03 16:47 K Jayatheerth [this message]
2026-07-03 22:49 ` [GSoC Patch] repo: support category-based prefix querying for info keys Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260703164709.22723-1-jayatheerthkulkarni2005@gmail.com \
--to=jayatheerthkulkarni2005@gmail.com \
--cc=git@vger.kernel.org \
--cc=jltobler@gmail.com \
--cc=lucasseikioshiro@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox