* [GSoC Patch] repo: support category-based prefix querying for info keys
@ 2026-07-03 16:47 K Jayatheerth
2026-07-03 22:49 ` Junio C Hamano
0 siblings, 1 reply; 2+ messages in thread
From: K Jayatheerth @ 2026-07-03 16:47 UTC (permalink / raw)
To: git; +Cc: jltobler, lucasseikioshiro, K Jayatheerth
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
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [GSoC Patch] repo: support category-based prefix querying for info keys
2026-07-03 16:47 [GSoC Patch] repo: support category-based prefix querying for info keys K Jayatheerth
@ 2026-07-03 22:49 ` Junio C Hamano
0 siblings, 0 replies; 2+ messages in thread
From: Junio C Hamano @ 2026-07-03 22:49 UTC (permalink / raw)
To: K Jayatheerth; +Cc: git, jltobler, lucasseikioshiro
K Jayatheerth <jayatheerthkulkarni2005@gmail.com> writes:
> 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
You mean "repo info" takes layout.bare and layout.shallow (right
now, later we may gain a lot more), so you want to say "everything
under 'layout' to grab these two values?
Why should we limit ourselves to "prefix match"? Would a glob like
"layout.*", or "path.*.absolute", work better? Especially the
latter, i.e., "I want the path variables, but am not interested in
their .relative values, only the .absolute ones." It is especially
puzzling as you are going to do a dumb linear search in this mode
anyway.
Perhaps during each iteration of the loop over argv[], you can first
look for exact match using the existing bsearch() codepath. If that
succeeds, you have a single key to return the value for. If it does
not match exactly any key, use the new "prefix" (or "glob" which I
think would make far more sense) match codepath to find which key(s)
to return values for, so iterate over them (or say "Hey, that pattern
does not match any key!" and fail).
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-07-03 22:49 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-03 16:47 [GSoC Patch] repo: support category-based prefix querying for info keys K Jayatheerth
2026-07-03 22:49 ` Junio C Hamano
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox