-
Notifications
You must be signed in to change notification settings - Fork 27.8k
repo info: add category/path keys and --path-format #2208
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
eslam-reda-div
wants to merge
6
commits into
git:master
Choose a base branch
from
eslam-reda-div:gsoc-contribute
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
bddea1a
repo: introduce repo_info context plumbing
eslam-reda-div 2369608
repo: support category requests in repo info
eslam-reda-div 477333a
repo: add path keys to repo info
eslam-reda-div 2a7afe4
repo: add --path-format for info path output
eslam-reda-div 1e52e7b
t1900: cover repo info path keys and path-format
eslam-reda-div b98490a
docs: describe repo info path keys
eslam-reda-div File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,7 +8,7 @@ git-repo - Retrieve information about the repository | |
| SYNOPSIS | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Justin Tobler wrote on the Git mailing list (how to reply to this email): On 26/02/22 06:28PM, eslam-reda-div via GitGitGadget wrote:
> From: eslam-reda-div <eslam.reda.div@gmail.com>
>
> Improve git repo info by adding path-oriented keys that match values
> users currently obtain from git rev-parse, including common directory,
> git directory, top-level, superproject working tree, and additional
> git-path based locations.
>
> Teach git repo info to accept category keys like layout and path,
> and add --path-format=(absolute|relative) so scripts can request the
> desired path style explicitly. The command now uses repository context
> passed to the command path instead of relying on global state.
>
> Extend git repo structure with deeper repository metrics inspired by
> git-sizer, including per-type maximum inflated and on-disk object sizes,
> maximum commit parent count, maximum tree entry count, longest/deepest
> blob path, and deepest annotated tag chain.
Hello,
Just FYI, there is already a series on the list I'm currently working on
that is extending the "structure" output for git-repo [1] similar to
what is being done here. This series collects largest inflated object
info, max commit parents, and max tree entries. It does look like this
series is collecting a couple of other data points too, but maybe we
could do so it a separate followup series to the one I'm working on? :)
Thanks,
-Justin
[1]: https://lore.kernel.org/git/20260203221758.1164434-1-jltobler@gmail.com/ |
||
| -------- | ||
| [synopsis] | ||
| git repo info [--format=(lines|nul) | -z] [--all | <key>...] | ||
| git repo info [--format=(lines|nul) | -z] [--path-format=(absolute|relative)] [--all | <key>...] | ||
| git repo info --keys [--format=(lines|nul) | -z] | ||
| git repo structure [--format=(table|lines|nul) | -z] | ||
|
|
||
|
|
@@ -56,6 +56,11 @@ supported: | |
| `nul`::: | ||
| Similar to `lines`, but using a _NUL_ character after each value. | ||
|
|
||
| `--path-format=(absolute|relative)`::: | ||
| Controls formatting for keys in the `path` category. The default is | ||
| `absolute`. This option may be specified multiple times; the last one | ||
| specified takes effect. | ||
|
|
||
| `structure [--format=(table|lines|nul) | -z]`:: | ||
| Retrieve statistics about the current repository structure. The | ||
| following kinds of information are reported: | ||
|
|
@@ -64,6 +69,12 @@ supported: | |
| * Reachable object counts categorized by type | ||
| * Total inflated size of reachable objects by type | ||
| * Total disk size of reachable objects by type | ||
| * Largest inflated reachable object size by type | ||
| * Largest disk size of a reachable object by type | ||
| * Largest parent count among reachable commits | ||
| * Largest entry count among reachable trees | ||
| * Longest and deepest path among reachable blobs | ||
| * Deepest annotated tag chain | ||
| + | ||
| The output format can be chosen through the flag `--format`. Three formats are | ||
| supported: | ||
|
|
@@ -76,6 +87,7 @@ supported: | |
| `lines`::: | ||
| Each line of output contains a key-value pair for a repository stat. | ||
| The '=' character is used to delimit between the key and the value. | ||
| Both aggregate metrics and per-type metrics are included. | ||
| Values containing "unusual" characters are quoted as explained for the | ||
| configuration variable `core.quotePath` (see linkgit:git-config[1]). | ||
|
|
||
|
|
@@ -90,9 +102,11 @@ supported: | |
|
|
||
| INFO KEYS | ||
| --------- | ||
| In order to obtain a set of values from `git repo info`, you should provide | ||
| the keys that identify them. Here's a list of the available keys and the | ||
| values that they return: | ||
| In order to obtain values from `git repo info`, provide either individual keys | ||
| or category names. A category returns all keys within that category. For | ||
| example, `layout` returns both `layout.bare` and `layout.shallow`. | ||
|
|
||
| Here's a list of the available keys and the values that they return: | ||
|
|
||
| `layout.bare`:: | ||
| `true` if this is a bare repository, otherwise `false`. | ||
|
|
@@ -103,6 +117,42 @@ values that they return: | |
| `object.format`:: | ||
| The object format (hash algorithm) used in the repository. | ||
|
|
||
| `path.common-dir`:: | ||
| The path to the common git directory. | ||
|
|
||
| `path.config-file`:: | ||
| The path to the `config` file in the git directory. | ||
|
|
||
| `path.git-dir`:: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Phillip Wood wrote on the Git mailing list (how to reply to this email): Hi Eslam
On 27/02/2026 19:30, Eslam reda ragheb via GitGitGadget wrote:
> From: Eslam reda ragheb <eslam.reda.div@gmail.com>
> > Rename path.git-prefix to path.prefix, add path.work-tree as an alias
> for path.toplevel, and drop reflog/ref-file-oriented path keys.
> > This narrows the path surface to keys that are less tied to direct
> file access while keeping tests and documentation in sync.
> > Also normalize prefix handling in repo_info context so path.prefix has
> a stable empty-string behavior.
When you change a patch series based on a reviewer's feedback, you should use "git rebase -i" to edit or fixup the existing commits rather than adding new changes on top. That keeps the history cleaner as we don't need to know "I implemented it like this and than changed it to that". It also makes the patch series easier to review as reviewers don't waste their time commenting on changes in one patch that are then deleted in a later patch.
Thanks
Phillip
> Signed-off-by: Eslam reda ragheb <eslam.reda.div@gmail.com>
> ---
> Documentation/git-repo.adoc | 14 ++++-------
> builtin/repo.c | 45 ++++++++--------------------------
> t/t1900-repo.sh | 48 +++++++++++++++++--------------------
> 3 files changed, 36 insertions(+), 71 deletions(-)
> > diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
> index b575977a4b..3d34c6edca 100644
> --- a/Documentation/git-repo.adoc
> +++ b/Documentation/git-repo.adoc
> @@ -114,7 +114,7 @@ Here's a list of the available keys and the values that they return:
> `path.git-dir`::
> The path to the git directory.
> > -`path.git-prefix`::
> +`path.prefix`::
> The path of the current working directory relative to the top-level
> directory.
> > @@ -127,18 +127,9 @@ Here's a list of the available keys and the values that they return:
> `path.index-file`::
> The path to the index file.
> > -`path.logs-directory`::
> - The path to the `logs` directory.
> -
> `path.objects-directory`::
> The path to the objects directory.
> > -`path.packed-refs-file`::
> - The path to the `packed-refs` file.
> -
> -`path.refs-directory`::
> - The path to the `refs` directory.
> -
> `path.shallow-file`::
> The path to the `shallow` file.
> > @@ -150,6 +141,9 @@ Here's a list of the available keys and the values that they return:
> The path to the top-level working tree directory, or an empty string
> for bare repositories.
> > +`path.work-tree`::
> + Alias for `path.toplevel`.
> +
> `references.format`::
> The reference storage format. The valid values are:
> +
> diff --git a/builtin/repo.c b/builtin/repo.c
> index ecd9d3aee5..9fbd13a358 100644
> --- a/builtin/repo.c
> +++ b/builtin/repo.c
> @@ -109,10 +109,9 @@ static int get_path_git_dir(struct repo_info *info, struct strbuf *buf)
> return 0;
> }
> > -static int get_path_git_prefix(struct repo_info *info, struct strbuf *buf)
> +static int get_path_prefix(struct repo_info *info, struct strbuf *buf)
> {
> - if (info->prefix)
> - strbuf_addstr(buf, info->prefix);
> + strbuf_addstr(buf, info->prefix);
> return 0;
> }
> > @@ -137,39 +136,12 @@ static int get_path_index_file(struct repo_info *info, struct strbuf *buf)
> return 0;
> }
> > -static int get_path_logs_directory(struct repo_info *info, struct strbuf *buf)
> -{
> - struct strbuf path = STRBUF_INIT;
> -
> - repo_info_add_path(info, buf, repo_git_path_replace(info->repo, &path, "logs"));
> - strbuf_release(&path);
> - return 0;
> -}
> -
> static int get_path_objects_directory(struct repo_info *info, struct strbuf *buf)
> {
> repo_info_add_path(info, buf, repo_get_object_directory(info->repo));
> return 0;
> }
> > -static int get_path_packed_refs_file(struct repo_info *info, struct strbuf *buf)
> -{
> - struct strbuf path = STRBUF_INIT;
> -
> - repo_info_add_path(info, buf, repo_git_path_replace(info->repo, &path, "packed-refs"));
> - strbuf_release(&path);
> - return 0;
> -}
> -
> -static int get_path_refs_directory(struct repo_info *info, struct strbuf *buf)
> -{
> - struct strbuf path = STRBUF_INIT;
> -
> - repo_info_add_path(info, buf, repo_git_path_replace(info->repo, &path, "refs"));
> - strbuf_release(&path);
> - return 0;
> -}
> -
> static int get_path_shallow_file(struct repo_info *info, struct strbuf *buf)
> {
> struct strbuf path = STRBUF_INIT;
> @@ -201,6 +173,11 @@ static int get_path_toplevel(struct repo_info *info, struct strbuf *buf)
> return 0;
> }
> > +static int get_path_work_tree(struct repo_info *info, struct strbuf *buf)
> +{
> + return get_path_toplevel(info, buf);
> +}
> +
> static int get_references_format(struct repo_info *info, struct strbuf *buf)
> {
> struct repository *repo = info->repo;
> @@ -217,17 +194,15 @@ static const struct field repo_info_fields[] = {
> { "path.common-dir", get_path_common_dir },
> { "path.config-file", get_path_config_file },
> { "path.git-dir", get_path_git_dir },
> - { "path.git-prefix", get_path_git_prefix },
> { "path.grafts-file", get_path_grafts_file },
> { "path.hooks-directory", get_path_hooks_directory },
> { "path.index-file", get_path_index_file },
> - { "path.logs-directory", get_path_logs_directory },
> { "path.objects-directory", get_path_objects_directory },
> - { "path.packed-refs-file", get_path_packed_refs_file },
> - { "path.refs-directory", get_path_refs_directory },
> + { "path.prefix", get_path_prefix },
> { "path.shallow-file", get_path_shallow_file },
> { "path.superproject-working-tree", get_path_superproject_working_tree },
> { "path.toplevel", get_path_toplevel },
> + { "path.work-tree", get_path_work_tree },
> { "references.format", get_references_format },
> };
> > @@ -378,7 +353,7 @@ static int cmd_repo_info(int argc, const char **argv, const char *prefix,
> enum output_format format = FORMAT_KEYVALUE;
> struct repo_info info = {
> .repo = repo,
> - .prefix = prefix,
> + .prefix = prefix ? prefix : "",
> .path_format = PATH_FORMAT_ABSOLUTE,
> };
> int all_keys = 0;
> diff --git a/t/t1900-repo.sh b/t/t1900-repo.sh
> index dcacf84cc3..2351b772b2 100755
> --- a/t/t1900-repo.sh
> +++ b/t/t1900-repo.sh
> @@ -13,17 +13,15 @@ REPO_INFO_KEYS='
> path.common-dir
> path.config-file
> path.git-dir
> - path.git-prefix
> path.grafts-file
> path.hooks-directory
> path.index-file
> - path.logs-directory
> path.objects-directory
> - path.packed-refs-file
> - path.refs-directory
> + path.prefix
> path.shallow-file
> path.superproject-working-tree
> path.toplevel
> + path.work-tree
> references.format
> '
> > @@ -31,17 +29,15 @@ REPO_INFO_PATH_KEYS='
> path.common-dir
> path.config-file
> path.git-dir
> - path.git-prefix
> path.grafts-file
> path.hooks-directory
> path.index-file
> - path.logs-directory
> path.objects-directory
> - path.packed-refs-file
> - path.refs-directory
> + path.prefix
> path.shallow-file
> path.superproject-working-tree
> path.toplevel
> + path.work-tree
> '
> > # Test whether a key-value pair is correctly returned
> @@ -172,12 +168,12 @@ test_expect_success 'path.toplevel is empty in bare repository' '
> test_cmp expect actual
> '
> > -test_expect_success 'path.git-prefix matches rev-parse --show-prefix' '
> +test_expect_success 'path.prefix matches rev-parse --show-prefix' '
> git init path-prefix &&
> mkdir -p path-prefix/a/b &&
> expected_value=$(git -C path-prefix/a/b rev-parse --show-prefix) &&
> - echo "path.git-prefix=$expected_value" >expect &&
> - git -C path-prefix/a/b repo info path.git-prefix >actual &&
> + echo "path.prefix=$expected_value" >expect &&
> + git -C path-prefix/a/b repo info path.prefix >actual &&
> test_cmp expect actual
> '
> > @@ -209,27 +205,27 @@ test_expect_success 'git-path style keys match rev-parse --git-path' '
> git -C path-git-path repo info path.config-file >actual &&
> test_cmp expect actual &&
> > - expected_value=$(git -C path-git-path rev-parse --path-format=absolute --git-path logs) &&
> - echo "path.logs-directory=$expected_value" >expect &&
> - git -C path-git-path repo info path.logs-directory >actual &&
> - test_cmp expect actual &&
> -
> - expected_value=$(git -C path-git-path rev-parse --path-format=absolute --git-path packed-refs) &&
> - echo "path.packed-refs-file=$expected_value" >expect &&
> - git -C path-git-path repo info path.packed-refs-file >actual &&
> - test_cmp expect actual &&
> -
> - expected_value=$(git -C path-git-path rev-parse --path-format=absolute --git-path refs) &&
> - echo "path.refs-directory=$expected_value" >expect &&
> - git -C path-git-path repo info path.refs-directory >actual &&
> - test_cmp expect actual &&
> -
> expected_value=$(git -C path-git-path rev-parse --path-format=absolute --git-path shallow) &&
> echo "path.shallow-file=$expected_value" >expect &&
> git -C path-git-path repo info path.shallow-file >actual &&
> test_cmp expect actual
> '
> > +test_expect_success 'path.work-tree matches path.toplevel' '
> + git init path-work-tree &&
> + expected_value=$(git -C path-work-tree rev-parse --show-toplevel) &&
> + echo "path.work-tree=$expected_value" >expect &&
> + git -C path-work-tree repo info path.work-tree >actual &&
> + test_cmp expect actual
> +'
> +
> +test_expect_success 'path.work-tree is empty in bare repository' '
> + git init --bare bare-path-work-tree &&
> + echo "path.work-tree=" >expect &&
> + git -C bare-path-work-tree repo info path.work-tree >actual &&
> + test_cmp expect actual
> +'
> +
> test_expect_success 'path.superproject-working-tree is empty when not a submodule' '
> git init path-superproject &&
> echo "path.superproject-working-tree=" >expect && |
||
| The path to the git directory. | ||
|
|
||
| `path.prefix`:: | ||
| The path of the current working directory relative to the top-level | ||
| directory. | ||
|
|
||
| `path.grafts-file`:: | ||
| The path to the `info/grafts` file. | ||
|
|
||
| `path.hooks-directory`:: | ||
| The path to the `hooks` directory. | ||
|
|
||
| `path.index-file`:: | ||
| The path to the index file. | ||
|
|
||
| `path.objects-directory`:: | ||
| The path to the objects directory. | ||
|
|
||
| `path.superproject-working-tree`:: | ||
| The path to the superproject's working tree root, or an empty string | ||
| when the repository is not used as a submodule. | ||
|
|
||
| `path.toplevel`:: | ||
| The path to the top-level working tree directory, or an empty string | ||
| for bare repositories. | ||
|
|
||
| `path.working-tree`:: | ||
| Alias for `path.toplevel`. | ||
|
|
||
| `references.format`:: | ||
| The reference storage format. The valid values are: | ||
| + | ||
|
|
||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lucas Seiki Oshiro wrote on the Git mailing list (how to reply to this email):
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the detailed feedback.
I will start right away on preparing a thorough and detailed explanation for each key that was added, clearly describing what it does and the specific reason for introducing it. I’ll make sure every addition is properly justified and documented.
Regarding the patch structure, would it be acceptable to keep it as a single series without splitting it into many smaller patches? I completely understand the concern, but since the changes are closely related, I’m hoping it might still be reasonable to keep them grouped.
That said, I’m fully prepared to follow the recommended approach if splitting is strictly required. I’m ready to put in the work and will begin refining the explanations immediately.
Thank you again for your guidance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@eslam-reda-div please note that this reply should not be sent as a PR comment, but instead as an email.