* [PATCH 1/4] rev-parse: prepend `path_` to path-related enums
2026-02-28 22:05 [PATCH 0/4] repo: add support for path-related fields Lucas Seiki Oshiro
@ 2026-02-28 22:05 ` Lucas Seiki Oshiro
2026-02-28 22:05 ` [PATCH 2/4] path: add new function strbuf_add_path Lucas Seiki Oshiro
` (5 subsequent siblings)
6 siblings, 0 replies; 26+ messages in thread
From: Lucas Seiki Oshiro @ 2026-02-28 22:05 UTC (permalink / raw)
To: git
Cc: sandals, kumarayushjha123, a3205153416, jayatheerthkulkarni2005,
valusoutrik, pushkarkumarsingh1970, Lucas Seiki Oshiro
There are two enums used in rev-parse for deciding how paths will
be printed by the function `print_path`: `format_type` and
`default_type`. Even though there aren't any ambiguities yet, their
names aren't clear that those "types" are path types.
Rename both enums and their values by prepending the word `path_`,
to clarify that they are used for choosing path types.
Signed-off-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
---
builtin/rev-parse.c | 56 ++++++++++++++++++++++-----------------------
1 file changed, 28 insertions(+), 28 deletions(-)
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 9032cc6327..a2162ff39e 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -623,27 +623,27 @@ static void handle_ref_opt(const char *pattern, const char *prefix)
clear_ref_exclusions(&ref_excludes);
}
-enum format_type {
+enum path_format_type {
/* We would like a relative path. */
- FORMAT_RELATIVE,
+ PATH_FORMAT_RELATIVE,
/* We would like a canonical absolute path. */
- FORMAT_CANONICAL,
+ PATH_FORMAT_CANONICAL,
/* We would like the default behavior. */
- FORMAT_DEFAULT,
+ PATH_FORMAT_DEFAULT,
};
-enum default_type {
+enum path_default_type {
/* Our default is a relative path. */
- DEFAULT_RELATIVE,
+ PATH_DEFAULT_RELATIVE,
/* Our default is a relative path if there's a shared root. */
- DEFAULT_RELATIVE_IF_SHARED,
+ PATH_DEFAULT_RELATIVE_IF_SHARED,
/* Our default is a canonical absolute path. */
- DEFAULT_CANONICAL,
+ PATH_DEFAULT_CANONICAL,
/* Our default is not to modify the item. */
- DEFAULT_UNMODIFIED,
+ PATH_DEFAULT_UNMODIFIED,
};
-static void print_path(const char *path, const char *prefix, enum format_type format, enum default_type def)
+static void print_path(const char *path, const char *prefix, enum path_format_type format, enum path_default_type def)
{
char *cwd = NULL;
/*
@@ -654,12 +654,12 @@ static void print_path(const char *path, const char *prefix, enum format_type fo
* set it in that case, since doing so causes a relative path to always
* be produced if possible.
*/
- if (!prefix && (format != FORMAT_DEFAULT || def != DEFAULT_RELATIVE_IF_SHARED))
+ if (!prefix && (format != PATH_FORMAT_DEFAULT || def != PATH_DEFAULT_RELATIVE_IF_SHARED))
prefix = cwd = xgetcwd();
- if (format == FORMAT_DEFAULT && def == DEFAULT_UNMODIFIED) {
+ if (format == PATH_FORMAT_DEFAULT && def == PATH_DEFAULT_UNMODIFIED) {
puts(path);
- } else if (format == FORMAT_RELATIVE ||
- (format == FORMAT_DEFAULT && def == DEFAULT_RELATIVE)) {
+ } else if (format == PATH_FORMAT_RELATIVE ||
+ (format == PATH_FORMAT_DEFAULT && def == PATH_DEFAULT_RELATIVE)) {
/*
* In order for relative_path to work as expected, we need to
* make sure that both paths are absolute paths. If we don't,
@@ -679,7 +679,7 @@ static void print_path(const char *path, const char *prefix, enum format_type fo
strbuf_release(&buf);
strbuf_release(&realbuf);
strbuf_release(&prefixbuf);
- } else if (format == FORMAT_DEFAULT && def == DEFAULT_RELATIVE_IF_SHARED) {
+ } else if (format == PATH_FORMAT_DEFAULT && def == PATH_DEFAULT_RELATIVE_IF_SHARED) {
struct strbuf buf = STRBUF_INIT;
puts(relative_path(path, prefix, &buf));
strbuf_release(&buf);
@@ -708,7 +708,7 @@ int cmd_rev_parse(int argc,
const char *name = NULL;
struct strbuf buf = STRBUF_INIT;
int seen_end_of_options = 0;
- enum format_type format = FORMAT_DEFAULT;
+ enum path_format_type format = PATH_FORMAT_DEFAULT;
show_usage_if_asked(argc, argv, builtin_rev_parse_usage);
@@ -789,7 +789,7 @@ int cmd_rev_parse(int argc,
print_path(repo_git_path_replace(the_repository, &buf,
"%s", argv[i + 1]), prefix,
format,
- DEFAULT_RELATIVE_IF_SHARED);
+ PATH_DEFAULT_RELATIVE_IF_SHARED);
i++;
continue;
}
@@ -811,9 +811,9 @@ int cmd_rev_parse(int argc,
if (!arg)
die(_("--path-format requires an argument"));
if (!strcmp(arg, "absolute")) {
- format = FORMAT_CANONICAL;
+ format = PATH_FORMAT_CANONICAL;
} else if (!strcmp(arg, "relative")) {
- format = FORMAT_RELATIVE;
+ format = PATH_FORMAT_RELATIVE;
} else {
die(_("unknown argument to --path-format: %s"), arg);
}
@@ -977,7 +977,7 @@ int cmd_rev_parse(int argc,
if (!strcmp(arg, "--show-toplevel")) {
const char *work_tree = repo_get_work_tree(the_repository);
if (work_tree)
- print_path(work_tree, prefix, format, DEFAULT_UNMODIFIED);
+ print_path(work_tree, prefix, format, PATH_DEFAULT_UNMODIFIED);
else
die(_("this operation must be run in a work tree"));
continue;
@@ -985,7 +985,7 @@ int cmd_rev_parse(int argc,
if (!strcmp(arg, "--show-superproject-working-tree")) {
struct strbuf superproject = STRBUF_INIT;
if (get_superproject_working_tree(&superproject))
- print_path(superproject.buf, prefix, format, DEFAULT_UNMODIFIED);
+ print_path(superproject.buf, prefix, format, PATH_DEFAULT_UNMODIFIED);
strbuf_release(&superproject);
continue;
}
@@ -1020,18 +1020,18 @@ int cmd_rev_parse(int argc,
const char *gitdir = getenv(GIT_DIR_ENVIRONMENT);
char *cwd;
int len;
- enum format_type wanted = format;
+ enum path_format_type wanted = format;
if (arg[2] == 'g') { /* --git-dir */
if (gitdir) {
- print_path(gitdir, prefix, format, DEFAULT_UNMODIFIED);
+ print_path(gitdir, prefix, format, PATH_DEFAULT_UNMODIFIED);
continue;
}
if (!prefix) {
- print_path(".git", prefix, format, DEFAULT_UNMODIFIED);
+ print_path(".git", prefix, format, PATH_DEFAULT_UNMODIFIED);
continue;
}
} else { /* --absolute-git-dir */
- wanted = FORMAT_CANONICAL;
+ wanted = PATH_FORMAT_CANONICAL;
if (!gitdir && !prefix)
gitdir = ".git";
if (gitdir) {
@@ -1047,11 +1047,11 @@ int cmd_rev_parse(int argc,
strbuf_reset(&buf);
strbuf_addf(&buf, "%s%s.git", cwd, len && cwd[len-1] != '/' ? "/" : "");
free(cwd);
- print_path(buf.buf, prefix, wanted, DEFAULT_CANONICAL);
+ print_path(buf.buf, prefix, wanted, PATH_DEFAULT_CANONICAL);
continue;
}
if (!strcmp(arg, "--git-common-dir")) {
- print_path(repo_get_common_dir(the_repository), prefix, format, DEFAULT_RELATIVE_IF_SHARED);
+ print_path(repo_get_common_dir(the_repository), prefix, format, PATH_DEFAULT_RELATIVE_IF_SHARED);
continue;
}
if (!strcmp(arg, "--is-inside-git-dir")) {
@@ -1081,7 +1081,7 @@ int cmd_rev_parse(int argc,
if (the_repository->index->split_index) {
const struct object_id *oid = &the_repository->index->split_index->base_oid;
const char *path = repo_git_path_replace(the_repository, &buf, "sharedindex.%s", oid_to_hex(oid));
- print_path(path, prefix, format, DEFAULT_RELATIVE);
+ print_path(path, prefix, format, PATH_DEFAULT_RELATIVE);
}
continue;
}
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH 2/4] path: add new function strbuf_add_path
2026-02-28 22:05 [PATCH 0/4] repo: add support for path-related fields Lucas Seiki Oshiro
2026-02-28 22:05 ` [PATCH 1/4] rev-parse: prepend `path_` to path-related enums Lucas Seiki Oshiro
@ 2026-02-28 22:05 ` Lucas Seiki Oshiro
2026-02-28 22:05 ` [PATCH 3/4] repo: add the --format-path flag Lucas Seiki Oshiro
` (4 subsequent siblings)
6 siblings, 0 replies; 26+ messages in thread
From: Lucas Seiki Oshiro @ 2026-02-28 22:05 UTC (permalink / raw)
To: git
Cc: sandals, kumarayushjha123, a3205153416, jayatheerthkulkarni2005,
valusoutrik, pushkarkumarsingh1970, Lucas Seiki Oshiro
The function `print_path`, introduced in fac60b8925 (rev-parse: add
option for absolute or relative path formatting, 2020-12-13), is used
by git-rev-parse for printing paths, deciding between using relative
or absolute paths. This decision, however, could benefit other
commands, notably git-repo-info.
Encapsulate this logic into a new function called `strbuf_add_path`,
located in `path.c`. Move to path.c the two enums used for deciding
the path format, i.e. `path_default_type` and `path_format_type`.
Signed-off-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
---
builtin/rev-parse.c | 72 ++++-----------------------------------------
path.c | 51 ++++++++++++++++++++++++++++++++
path.h | 23 +++++++++++++++
3 files changed, 80 insertions(+), 66 deletions(-)
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index a2162ff39e..024a9e7d5f 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -623,73 +623,13 @@ static void handle_ref_opt(const char *pattern, const char *prefix)
clear_ref_exclusions(&ref_excludes);
}
-enum path_format_type {
- /* We would like a relative path. */
- PATH_FORMAT_RELATIVE,
- /* We would like a canonical absolute path. */
- PATH_FORMAT_CANONICAL,
- /* We would like the default behavior. */
- PATH_FORMAT_DEFAULT,
-};
-
-enum path_default_type {
- /* Our default is a relative path. */
- PATH_DEFAULT_RELATIVE,
- /* Our default is a relative path if there's a shared root. */
- PATH_DEFAULT_RELATIVE_IF_SHARED,
- /* Our default is a canonical absolute path. */
- PATH_DEFAULT_CANONICAL,
- /* Our default is not to modify the item. */
- PATH_DEFAULT_UNMODIFIED,
-};
-
-static void print_path(const char *path, const char *prefix, enum path_format_type format, enum path_default_type def)
+static void print_path(const char *path, const char *prefix,
+ enum path_format_type format, enum path_default_type def)
{
- char *cwd = NULL;
- /*
- * We don't ever produce a relative path if prefix is NULL, so set the
- * prefix to the current directory so that we can produce a relative
- * path whenever possible. If we're using RELATIVE_IF_SHARED mode, then
- * we want an absolute path unless the two share a common prefix, so don't
- * set it in that case, since doing so causes a relative path to always
- * be produced if possible.
- */
- if (!prefix && (format != PATH_FORMAT_DEFAULT || def != PATH_DEFAULT_RELATIVE_IF_SHARED))
- prefix = cwd = xgetcwd();
- if (format == PATH_FORMAT_DEFAULT && def == PATH_DEFAULT_UNMODIFIED) {
- puts(path);
- } else if (format == PATH_FORMAT_RELATIVE ||
- (format == PATH_FORMAT_DEFAULT && def == PATH_DEFAULT_RELATIVE)) {
- /*
- * In order for relative_path to work as expected, we need to
- * make sure that both paths are absolute paths. If we don't,
- * we can end up with an unexpected absolute path that the user
- * didn't want.
- */
- struct strbuf buf = STRBUF_INIT, realbuf = STRBUF_INIT, prefixbuf = STRBUF_INIT;
- if (!is_absolute_path(path)) {
- strbuf_realpath_forgiving(&realbuf, path, 1);
- path = realbuf.buf;
- }
- if (!is_absolute_path(prefix)) {
- strbuf_realpath_forgiving(&prefixbuf, prefix, 1);
- prefix = prefixbuf.buf;
- }
- puts(relative_path(path, prefix, &buf));
- strbuf_release(&buf);
- strbuf_release(&realbuf);
- strbuf_release(&prefixbuf);
- } else if (format == PATH_FORMAT_DEFAULT && def == PATH_DEFAULT_RELATIVE_IF_SHARED) {
- struct strbuf buf = STRBUF_INIT;
- puts(relative_path(path, prefix, &buf));
- strbuf_release(&buf);
- } else {
- struct strbuf buf = STRBUF_INIT;
- strbuf_realpath_forgiving(&buf, path, 1);
- puts(buf.buf);
- strbuf_release(&buf);
- }
- free(cwd);
+ struct strbuf sb = STRBUF_INIT;
+ strbuf_add_path(&sb, path, prefix, format, def);
+ puts(sb.buf);
+ strbuf_release(&sb);
}
int cmd_rev_parse(int argc,
diff --git a/path.c b/path.c
index d726537622..ab9669abff 100644
--- a/path.c
+++ b/path.c
@@ -1574,6 +1574,57 @@ char *xdg_cache_home(const char *filename)
return NULL;
}
+void strbuf_add_path(struct strbuf *sb, const char *path, const char *prefix,
+ enum path_format_type format, enum path_default_type def)
+{
+ char *cwd = NULL;
+ /*
+ * We don't ever produce a relative path if prefix is NULL, so set the
+ * prefix to the current directory so that we can produce a relative
+ * path whenever possible. If we're using RELATIVE_IF_SHARED mode, then
+ * we want an absolute path unless the two share a common prefix, so don't
+ * set it in that case, since doing so causes a relative path to always
+ * be produced if possible.
+ */
+ if (!prefix && (format != PATH_FORMAT_DEFAULT || def != PATH_DEFAULT_RELATIVE_IF_SHARED))
+ prefix = cwd = xgetcwd();
+ if (format == PATH_FORMAT_DEFAULT && def == PATH_DEFAULT_UNMODIFIED) {
+ strbuf_addstr(sb, path);
+ } else if (format == PATH_FORMAT_RELATIVE ||
+ (format == PATH_FORMAT_DEFAULT && def == PATH_DEFAULT_RELATIVE)) {
+ /*
+ * In order for relative_path to work as expected, we need to
+ * make sure that both paths are absolute paths. If we don't,
+ * we can end up with an unexpected absolute path that the user
+ * didn't want.
+ */
+ struct strbuf buf = STRBUF_INIT, realbuf = STRBUF_INIT, prefixbuf = STRBUF_INIT;
+ if (!is_absolute_path(path)) {
+ strbuf_realpath_forgiving(&realbuf, path, 1);
+ path = realbuf.buf;
+ }
+ if (!is_absolute_path(prefix)) {
+ strbuf_realpath_forgiving(&prefixbuf, prefix, 1);
+ prefix = prefixbuf.buf;
+ }
+ strbuf_addstr(sb, relative_path(path, prefix, &buf));
+ strbuf_release(&buf);
+ strbuf_release(&realbuf);
+ strbuf_release(&prefixbuf);
+ } else if (format == PATH_FORMAT_DEFAULT && def == PATH_DEFAULT_RELATIVE_IF_SHARED) {
+ struct strbuf buf = STRBUF_INIT;
+ strbuf_addstr(sb, relative_path(path, prefix, &buf));
+ strbuf_release(&buf);
+ } else {
+ struct strbuf buf = STRBUF_INIT;
+ strbuf_realpath_forgiving(&buf, path, 1);
+ strbuf_addbuf(sb, &buf);
+ strbuf_release(&buf);
+ }
+ free(cwd);
+}
+
+
REPO_GIT_PATH_FUNC(squash_msg, "SQUASH_MSG")
REPO_GIT_PATH_FUNC(merge_msg, "MERGE_MSG")
REPO_GIT_PATH_FUNC(merge_rr, "MERGE_RR")
diff --git a/path.h b/path.h
index 0ec95a0b07..c152d20c71 100644
--- a/path.h
+++ b/path.h
@@ -258,6 +258,29 @@ enum scld_error safe_create_leading_directories_no_share(char *path);
int safe_create_file_with_leading_directories(struct repository *repo,
const char *path);
+enum path_format_type {
+ /* We would like a relative path. */
+ PATH_FORMAT_RELATIVE,
+ /* We would like a canonical absolute path. */
+ PATH_FORMAT_CANONICAL,
+ /* We would like the default behavior. */
+ PATH_FORMAT_DEFAULT,
+};
+
+enum path_default_type {
+ /* Our default is a relative path. */
+ PATH_DEFAULT_RELATIVE,
+ /* Our default is a relative path if there's a shared root. */
+ PATH_DEFAULT_RELATIVE_IF_SHARED,
+ /* Our default is a canonical absolute path. */
+ PATH_DEFAULT_CANONICAL,
+ /* Our default is not to modify the item. */
+ PATH_DEFAULT_UNMODIFIED,
+};
+
+void strbuf_add_path(struct strbuf *buf, const char *path, const char *prefix,
+ enum path_format_type format, enum path_default_type def);
+
# ifdef USE_THE_REPOSITORY_VARIABLE
# include "strbuf.h"
# include "repository.h"
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH 3/4] repo: add the --format-path flag
2026-02-28 22:05 [PATCH 0/4] repo: add support for path-related fields Lucas Seiki Oshiro
2026-02-28 22:05 ` [PATCH 1/4] rev-parse: prepend `path_` to path-related enums Lucas Seiki Oshiro
2026-02-28 22:05 ` [PATCH 2/4] path: add new function strbuf_add_path Lucas Seiki Oshiro
@ 2026-02-28 22:05 ` Lucas Seiki Oshiro
2026-02-28 22:05 ` [PATCH 4/4] repo: add the field path.toplevel Lucas Seiki Oshiro
` (3 subsequent siblings)
6 siblings, 0 replies; 26+ messages in thread
From: Lucas Seiki Oshiro @ 2026-02-28 22:05 UTC (permalink / raw)
To: git
Cc: sandals, kumarayushjha123, a3205153416, jayatheerthkulkarni2005,
valusoutrik, pushkarkumarsingh1970, Lucas Seiki Oshiro
Some paths handled by Git are better presented in their absolute format
and others are better presented relative to the current working
directory.
Add a `--format-path` flag to git-repo-info, allowing the user to force
the outputted paths to be either in the absolute or in the relative
format. This flag is similar to its homonymous in git-rev-parse, introduced in
fac60b8925 (rev-parse: add option for absolute or relative path
formatting, 2020-12-13).
Signed-off-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
---
Documentation/git-repo.adoc | 8 ++++++--
builtin/repo.c | 24 +++++++++++++++++++-----
t/t1900-repo-info.sh | 7 +++++++
3 files changed, 32 insertions(+), 7 deletions(-)
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 5e2968b707..478737b8ff 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -8,7 +8,7 @@ git-repo - Retrieve information about the repository
SYNOPSIS
--------
[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]
@@ -20,7 +20,7 @@ THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
COMMANDS
--------
-`info [--format=(lines|nul) | -z] [--all | <key>...]`::
+`info [--format=(lines|nul) | -z] [--path-format=(absolute|relative)] [--all | <key>...]`::
Retrieve metadata-related information about the current repository. Only
the requested data will be returned based on their keys (see "INFO KEYS"
section below).
@@ -45,6 +45,10 @@ supported:
`lines`. Unlike in the `lines` format, the values are never quoted.
+
`-z` is an alias for `--format=nul`.
++
+By default, the path values may be in the absolute or relative path, depending
+on the requested keys. However, the format can be forced by using the flag
+`--path-format`.
`info --keys [--format=(lines|nul) | -z]`::
List all the available keys, one per line. The output format can be chosen
diff --git a/builtin/repo.c b/builtin/repo.c
index f943be7451..cff4c6db9b 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -7,17 +7,16 @@
#include "parse-options.h"
#include "path-walk.h"
#include "progress.h"
+#include "path.h"
#include "quote.h"
#include "ref-filter.h"
#include "refs.h"
#include "revision.h"
-#include "strbuf.h"
-#include "string-list.h"
#include "shallow.h"
#include "utf8.h"
static const char *const repo_usage[] = {
- "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]",
NULL
@@ -109,7 +108,8 @@ static void print_field(enum output_format format, const char *key,
static int print_fields(int argc, const char **argv,
struct repository *repo,
- enum output_format format)
+ enum output_format format,
+ enum path_format_type path_format UNUSED)
{
int ret = 0;
struct strbuf valbuf = STRBUF_INIT;
@@ -197,6 +197,9 @@ static int cmd_repo_info(int argc, const char **argv, const char *prefix,
enum output_format format = FORMAT_NEWLINE_TERMINATED;
int all_keys = 0;
int show_keys = 0;
+ const char *path_format_str = NULL;
+ enum path_format_type path_format = PATH_FORMAT_DEFAULT;
+
struct option options[] = {
OPT_CALLBACK_F(0, "format", &format, N_("format"),
N_("output format"),
@@ -207,6 +210,8 @@ static int cmd_repo_info(int argc, const char **argv, const char *prefix,
parse_format_cb),
OPT_BOOL(0, "all", &all_keys, N_("print all keys/values")),
OPT_BOOL(0, "keys", &show_keys, N_("show keys")),
+ OPT_STRING(0, "path-format", &path_format_str,
+ N_("path-format"), N_("path format")),
OPT_END()
};
@@ -221,13 +226,22 @@ static int cmd_repo_info(int argc, const char **argv, const char *prefix,
if (format != FORMAT_NEWLINE_TERMINATED && format != FORMAT_NUL_TERMINATED)
die(_("unsupported output format"));
+ if (path_format_str) {
+ if (!strcmp(path_format_str, "absolute"))
+ path_format = PATH_FORMAT_CANONICAL;
+ else if (!strcmp(path_format_str, "relative"))
+ path_format = PATH_FORMAT_RELATIVE;
+ else
+ die(_("invalid path format '%s'"), path_format_str);
+ }
+
if (all_keys && argc)
die(_("--all and <key> cannot be used together"));
if (all_keys)
return print_all_fields(repo, format);
else
- return print_fields(argc, argv, repo, format);
+ return print_fields(argc, argv, repo, format, path_format);
}
struct ref_stats {
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index a9eb07abe8..f5c76067cb 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -149,4 +149,11 @@ test_expect_success 'git repo info --keys uses lines as its default output forma
test_cmp expect actual
'
+test_expect_success 'git-repo-info aborts when requesting an invalid path format' '
+ test_when_finished "rm -f err expected" &&
+ echo "fatal: invalid path format '\'foo\''" >expected &&
+ test_must_fail git repo info --path-format=foo 2>err &&
+ test_cmp expected err
+'
+
test_done
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH 4/4] repo: add the field path.toplevel
2026-02-28 22:05 [PATCH 0/4] repo: add support for path-related fields Lucas Seiki Oshiro
` (2 preceding siblings ...)
2026-02-28 22:05 ` [PATCH 3/4] repo: add the --format-path flag Lucas Seiki Oshiro
@ 2026-02-28 22:05 ` Lucas Seiki Oshiro
2026-03-01 4:24 ` Tian Yuchen
2026-03-01 2:58 ` [PATCH 0/4] repo: add support for path-related fields JAYATHEERTH K
` (2 subsequent siblings)
6 siblings, 1 reply; 26+ messages in thread
From: Lucas Seiki Oshiro @ 2026-02-28 22:05 UTC (permalink / raw)
To: git
Cc: sandals, kumarayushjha123, a3205153416, jayatheerthkulkarni2005,
valusoutrik, pushkarkumarsingh1970, Lucas Seiki Oshiro
The flag `--show-toplevel` from git-rev-parse is used for retrieving
the top level directory path of the repository. This way, it is used for
querying repository metadata, fitting in the purpose of git-repo-info.
Add a new field `path.toplevel` to the git-repo-info subcommand
containing that information.
Signed-off-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
---
builtin/repo.c | 47 +++++++++++++++++++++++++--------
t/t1900-repo-info.sh | 62 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 98 insertions(+), 11 deletions(-)
diff --git a/builtin/repo.c b/builtin/repo.c
index cff4c6db9b..61cd539e05 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -22,7 +22,8 @@ static const char *const repo_usage[] = {
NULL
};
-typedef int get_value_fn(struct repository *repo, struct strbuf *buf);
+typedef int get_value_fn(struct repository *repo, struct strbuf *buf,
+ const char *prefix, enum path_format_type format);
enum output_format {
FORMAT_TABLE,
@@ -35,26 +36,46 @@ struct repo_info_field {
get_value_fn *get_value;
};
-static int get_layout_bare(struct repository *repo UNUSED, struct strbuf *buf)
+static int get_layout_bare(struct repository *repo UNUSED, struct strbuf *buf,
+ const char *prefix UNUSED,
+ enum path_format_type format UNUSED)
{
strbuf_addstr(buf, is_bare_repository() ? "true" : "false");
return 0;
}
-static int get_layout_shallow(struct repository *repo, struct strbuf *buf)
+static int get_layout_shallow(struct repository *repo, struct strbuf *buf,
+ const char *prefix UNUSED,
+ enum path_format_type format UNUSED)
{
strbuf_addstr(buf,
is_repository_shallow(repo) ? "true" : "false");
return 0;
}
-static int get_object_format(struct repository *repo, struct strbuf *buf)
+static int get_object_format(struct repository *repo, struct strbuf *buf,
+ const char *prefix UNUSED,
+ enum path_format_type format UNUSED)
{
strbuf_addstr(buf, repo->hash_algo->name);
return 0;
}
-static int get_references_format(struct repository *repo, struct strbuf *buf)
+static int get_path_toplevel(struct repository *repo, struct strbuf *buf,
+ const char *prefix, enum path_format_type format)
+{
+ const char *work_tree = repo_get_work_tree(repo);
+ if (work_tree)
+ strbuf_add_path(buf, work_tree, prefix, format,
+ PATH_DEFAULT_UNMODIFIED);
+ else
+ return error(_("this operation must be run in a work tree"));
+ return 0;
+}
+
+static int get_references_format(struct repository *repo, struct strbuf *buf,
+ const char *prefix UNUSED,
+ enum path_format_type format UNUSED)
{
strbuf_addstr(buf,
ref_storage_format_to_name(repo->ref_storage_format));
@@ -66,6 +87,7 @@ static const struct repo_info_field repo_info_field[] = {
{ "layout.bare", get_layout_bare },
{ "layout.shallow", get_layout_shallow },
{ "object.format", get_object_format },
+ { "path.toplevel", get_path_toplevel },
{ "references.format", get_references_format },
};
@@ -108,8 +130,9 @@ static void print_field(enum output_format format, const char *key,
static int print_fields(int argc, const char **argv,
struct repository *repo,
+ const char *prefix,
enum output_format format,
- enum path_format_type path_format UNUSED)
+ enum path_format_type path_format)
{
int ret = 0;
struct strbuf valbuf = STRBUF_INIT;
@@ -124,7 +147,7 @@ static int print_fields(int argc, const char **argv,
}
strbuf_reset(&valbuf);
- field->get_value(repo, &valbuf);
+ field->get_value(repo, &valbuf, prefix, path_format);
print_field(format, key, valbuf.buf);
}
@@ -133,7 +156,9 @@ static int print_fields(int argc, const char **argv,
}
static int print_all_fields(struct repository *repo,
- enum output_format format)
+ const char *prefix,
+ enum output_format format,
+ enum path_format_type path_format)
{
struct strbuf valbuf = STRBUF_INIT;
@@ -141,7 +166,7 @@ static int print_all_fields(struct repository *repo,
const struct repo_info_field *field = &repo_info_field[i];
strbuf_reset(&valbuf);
- field->get_value(repo, &valbuf);
+ field->get_value(repo, &valbuf, prefix, path_format);
print_field(format, field->key, valbuf.buf);
}
@@ -239,9 +264,9 @@ static int cmd_repo_info(int argc, const char **argv, const char *prefix,
die(_("--all and <key> cannot be used together"));
if (all_keys)
- return print_all_fields(repo, format);
+ return print_all_fields(repo, prefix, format, path_format);
else
- return print_fields(argc, argv, repo, format, path_format);
+ return print_fields(argc, argv, repo, prefix, format, path_format);
}
struct ref_stats {
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index f5c76067cb..4985a9cc70 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -38,6 +38,53 @@ test_repo_info () {
'
}
+test_repo_info_path () {
+ label=$1
+ repo_name=$2
+ key=$3
+ relative_path=$4
+ default=$5
+
+ absolute_path=$(cd "$relative_path"; pwd)/"$repo_name"
+
+ case $default in
+ absolute)
+ expected_value="$absolute_path"
+ ;;
+ relative)
+ expected_value="$relative_path"
+ ;;
+ esac
+
+ test_expect_success "setup: $label" '
+ git init "$repo_name"
+ '
+
+ test_expect_success "nul: $label" '
+ printf "%s\n%s\0" "$key" "$expected_value" >expected &&
+ git -C "$repo_name" repo info --format=nul "$key" >actual &&
+ test_cmp expected actual
+ '
+
+ test_expect_success "default: $label" '
+ echo "$key=$expected_value" > expected &&
+ git -C "$repo_name" repo info "$key" >actual &&
+ test_cmp expected actual
+ '
+
+ test_expect_success "absolute: $label" '
+ echo "$key=$absolute_path" > expected &&
+ git -C "$repo_name" repo info --path-format=absolute "$key" >actual &&
+ test_cmp expected actual
+ '
+
+ test_expect_success "relative: $label" '
+ echo "$key=$relative_path" > expected &&
+ git -C "$repo_name" repo info --path-format=relative "$key" >actual &&
+ test_cmp expected actual
+ '
+}
+
test_repo_info 'ref format files is retrieved correctly' \
'git init --ref-format=files' 'format-files' 'references.format' 'files'
@@ -69,6 +116,21 @@ test_repo_info 'object.format = sha1 is retrieved correctly' \
test_repo_info 'object.format = sha256 is retrieved correctly' \
'git init --object-format=sha256' 'sha256' 'object.format' 'sha256'
+test_repo_info_path 'toplevel is retrieved correctly' \
+ 'toplevel' 'path.toplevel' './' 'absolute'
+
+test_expect_success 'git-repo-info fails if an invalid key is requested' '
+ echo "error: key ${SQ}foo${SQ} not found" >expected_err &&
+ test_must_fail git repo info foo 2>actual_err &&
+ test_cmp expected_err actual_err
+'
+
+test_expect_success 'git-repo-info outputs data even if there is an invalid field' '
+ echo "references.format=$(test_detect_ref_format)" >expected &&
+ test_must_fail git repo info foo references.format bar >actual &&
+ test_cmp expected actual
+'
+
test_expect_success 'values returned in order requested' '
cat >expect <<-\EOF &&
layout.bare=false
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 26+ messages in thread* Re: [PATCH 4/4] repo: add the field path.toplevel
2026-02-28 22:05 ` [PATCH 4/4] repo: add the field path.toplevel Lucas Seiki Oshiro
@ 2026-03-01 4:24 ` Tian Yuchen
2026-03-01 20:21 ` Lucas Seiki Oshiro
0 siblings, 1 reply; 26+ messages in thread
From: Tian Yuchen @ 2026-03-01 4:24 UTC (permalink / raw)
To: Lucas Seiki Oshiro, git
Cc: sandals, kumarayushjha123, jayatheerthkulkarni2005, valusoutrik,
pushkarkumarsingh1970
Hi Lucas,
> I'm CC'ing here:
>
> - brian, who was the original author of the `print_path` [1]
> - Ayush, Tian, Jayatheerth, Soutrik and Pushkar, since they expressed
> interested in contributing to git-repo-info in GSoC. (I hope that I
> didn't forget anyone)
Thank you for your thoughtful consideration!
> 1. Add --path-format, just like we have in git-rev-parse
> 2. Use what rev-parse uses by default
> 3. Add keys for both relative and absolute formats
It makes me wonder if we can use Format Modifiers as in ref-filter.c...
https://git-scm.com/docs/git-for-each-ref
...which allow us to control the output precisely. For example:
%(path:relative)
%(path:absolute)
%(path:short)
%(path:strip=2)...
Just a thought.
> There are two enums used in rev-parse for deciding how paths will
> be printed by the function `print_path`: `format_type` and
> `default_type`. Even though there aren't any ambiguities yet, their
> names aren't clear that those "types" are path types.
This one makes sense to me. Also reduce naming conflicts.
> +void strbuf_add_path(struct strbuf *sb, const char *path, const char
> *prefix, enum path_format_type format, enum path_default_type def)
Isn't it a bit inappropriate for a generic character concatenation
function to know about format and def? I don't think this should be the
responsibility of a low-level function, at least not str_buf_add_path().
All functions starting with strbuf_add.. listed by git grep strbuf_add
are mostly pure string concatenation operations. I believe this should
be the case here as well.
> + if (!prefix && (format != PATH_FORMAT_DEFAULT || def !=
PATH_DEFAULT_RELATIVE_IF_SHARED))
> + prefix = cwd = xgetcwd();
I think the logic here shouldn't be tied to
PATH_DEFAULT_RELATIVE_IF_SHARED, I believe the attribution here is the
same as above.
> + prefix = cwd = xgetcwd()
Will there be a performance regression? Since xgetcwd() here is a system
call, right? If prefix == NULL and the get repo info command is used to
locate the top-level path among a large number of submodules, and this
command will be executed multiple times.
In my opinion, upper-level commands should call xgetcwd() only once
before entering the loop, then pass the obtained prefix as an argument
to the underlying implementation.
> -typedef int get_value_fn(struct repository *repo, struct strbuf *buf);
> +typedef int get_value_fn(struct repository *repo, struct strbuf *buf,
> + const char *prefix, enum path_format_type format);
>
> enum output_format {
> FORMAT_TABLE,
> @@ -35,26 +36,46 @@ struct repo_info_field {
> get_value_fn *get_value;
> };
>
> -static int get_layout_bare(struct repository *repo UNUSED, struct strbuf *buf)
> +static int get_layout_bare(struct repository *repo UNUSED, struct strbuf *buf,
> + const char *prefix UNUSED,
> + enum path_format_type format UNUSED)
> {
> strbuf_addstr(buf, is_bare_repository() ? "true" : "false");
> return 0;
> }
>
> -static int get_layout_shallow(struct repository *repo, struct strbuf *buf)
> +static int get_layout_shallow(struct repository *repo, struct strbuf *buf,
> + const char *prefix UNUSED,
> + enum path_format_type format UNUSED)
> {
> strbuf_addstr(buf,
> is_repository_shallow(repo) ? "true" : "false");
> return 0;
> }
>
> -static int get_object_format(struct repository *repo, struct strbuf *buf)
> +static int get_object_format(struct repository *repo, struct strbuf *buf,
> + const char *prefix UNUSED,
> + enum path_format_type format UNUSED)
> {
> strbuf_addstr(buf, repo->hash_algo->name);
> return 0;
> }
>
> -static int get_references_format(struct repository *repo, struct strbuf *buf)
> +static int get_path_toplevel(struct repository *repo, struct strbuf *buf,
> + const char *prefix, enum path_format_type format)
> +{
> + const char *work_tree = repo_get_work_tree(repo);
> + if (work_tree)
> + strbuf_add_path(buf, work_tree, prefix, format,
> + PATH_DEFAULT_UNMODIFIED);
> + else
> + return error(_("this operation must be run in a work tree"));
> + return 0;
> +}
> +
> +static int get_references_format(struct repository *repo, struct strbuf *buf,
> + const char *prefix UNUSED,
> +
I don't think we should add the two new parameters to all get_ functions
here. As changed in your patch, functions like get_object_format don't
really, need to know about prefix or format, so the corresponding
parameters are marked as UNUSED. Imagine if more and more data needs to
be retrieved by these get_ series functions in the future — is it really
advisable to add unnecessary parameters to all remaining functions just
for the sake of a few?
I'm not entirely sure about the above content either; I'm just throwing
out ideas to spark discussion. (´~`)
Thanks again for starting this discussion!
Regards,
Yuchen
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH 4/4] repo: add the field path.toplevel
2026-03-01 4:24 ` Tian Yuchen
@ 2026-03-01 20:21 ` Lucas Seiki Oshiro
2026-03-02 4:54 ` Tian Yuchen
0 siblings, 1 reply; 26+ messages in thread
From: Lucas Seiki Oshiro @ 2026-03-01 20:21 UTC (permalink / raw)
To: Tian Yuchen
Cc: git, sandals, kumarayushjha123, jayatheerthkulkarni2005,
valusoutrik, pushkarkumarsingh1970
> Hi Lucas,
Hi, Tian!
> > +void strbuf_add_path(struct strbuf *sb, const char *path, const char > *prefix, enum path_format_type format, enum path_default_type def)
>
> Isn't it a bit inappropriate for a generic character concatenation
> function to know about format and def? I don't think this should be
> the responsibility of a low-level function, at least not
> str_buf_add_path().
I don't think it can be considered a low-level function, but I
agree that its name can be misleading.
> > + prefix = cwd = xgetcwd()
>
> Will there be a performance regression? Since xgetcwd() here is a
> system call, right?
In this case, no, it is defined in wrapper.h.
> I don't think we should add the two new parameters to all get_
> functions here. As changed in your patch, functions like
> get_object_format don't really, need to know about prefix or format,
> so the corresponding parameters are marked as UNUSED. Imagine if
> more and more data needs to be retrieved by these get_ series
> functions in the future — is it really advisable to add unnecessary
> parameters to all remaining functions just for the sake of a few?
In this case, we need to add them to match the signature of
get_value_fn. Those values will be useful for all the path.*, but
if we start to add more than that I agree that we'll need to think
in a better solution.
> I'm not entirely sure about the above content either; I'm just
> throwing out ideas to spark discussion. (´~`)
Thanks, it's also good to see more points of view. I'm also not
sure about it :-)
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 4/4] repo: add the field path.toplevel
2026-03-01 20:21 ` Lucas Seiki Oshiro
@ 2026-03-02 4:54 ` Tian Yuchen
0 siblings, 0 replies; 26+ messages in thread
From: Tian Yuchen @ 2026-03-02 4:54 UTC (permalink / raw)
To: Lucas Seiki Oshiro
Cc: git, sandals, kumarayushjha123, jayatheerthkulkarni2005,
valusoutrik, pushkarkumarsingh1970
Hi Lucas
> I don't think it can be considered a low-level function, but I
> agree that its name can be misleading.
Hummm...If a function is solely responsible for string concatenation and
resides in like path.c, why isn't it a low level function?
I think the key issue lies in the fact that this function's
responsibilities are not quite appropriate, rather than merely the
name. Does a string buffer need to understand Git's path formatting
rules? It should only know how to append bytes, right? Maybe it would be
better suited as a domain-specific formatter like 'format_path_output()'
in a higher level module? I am quite uncertain about it.
> In this case, no, it is defined in wrapper.h.
Yes it is defined in wrapper.h. However in wrapper.c we have:
char *xgetcwd(void)
{
struct strbuf sb = STRBUF_INIT;
if (strbuf_getcwd(&sb))
die_errno(_("unable to get current working directory"));
return strbuf_detach(&sb, NULL);
}
and the for the stfbuf_getcwd(), in strbuf.c we have:
int strbuf_getcwd(struct strbuf *sb)
{
size_t oldalloc = sb->alloc;
size_t guessed_len = 128;
for (;; guessed_len *= 2) {
strbuf_grow(sb, guessed_len);
if (getcwd(sb->buf, sb->alloc)) {
strbuf_setlen(sb, strlen(sb->buf));
return 0;
...
Notice the getcwd() function, which is indeed a system call, which you
can check with 'man 2 getcwd' in terminal. Wrapping it in wrapper.c is
just providing a shortcut, right?
But I don't think using system calls is inherently problematic. The
issue lies in where this xgetbuf() is placed:
In builtin/rev-parse.c, the print_path() function is inside of
cmd_rev_parse(), which is like:
int cmd_rev_parse(....){
for (i = 1; i < argc; i++){
...
if (....){
print_path(....)
}
...
}
And your print_path() implement was:
> +static void print_path(const char *path, const char *prefix,
> + enum path_format_type format, enum path_default_type def)
> {
> + struct strbuf sb = STRBUF_INIT;
> + strbuf_add_path(&sb, path, prefix, format, def);
> + puts(sb.buf);
> + strbuf_release(&sb);
> }
So this system call is indeed invoked in the loop. Specifically, it gets
called every time 'git rev-parse' is invoked, and as far as I know it
should be a command used extensively in like shell scripts...?
Maybe cache-up approach is more robust? For example in builtin/rev-parse.c:
const char *cached_cwd = ...->original_cwd;
if (!cached_cwd)
cached_cwd = xgetcwd();
for (...) {
if (...) {
print_path_with_cwd(..., cached_cwd, ...);
}
}
> In this case, we need to add them to match the signature of
> get_value_fn. Those values will be useful for all the path.*, but
> if we start to add more than that I agree that we'll need to think
> in a better solution.
Yes indeed.
> Thanks, it's also good to see more points of view. I'm also not
> sure about it :-)
Thank you for the patch again!
Regards,
Yuchen
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 0/4] repo: add support for path-related fields
2026-02-28 22:05 [PATCH 0/4] repo: add support for path-related fields Lucas Seiki Oshiro
` (3 preceding siblings ...)
2026-02-28 22:05 ` [PATCH 4/4] repo: add the field path.toplevel Lucas Seiki Oshiro
@ 2026-03-01 2:58 ` JAYATHEERTH K
2026-03-01 5:45 ` Ayush Jha
2026-03-01 19:49 ` Lucas Seiki Oshiro
2026-03-01 10:44 ` Phillip Wood
2026-03-01 21:25 ` brian m. carlson
6 siblings, 2 replies; 26+ messages in thread
From: JAYATHEERTH K @ 2026-03-01 2:58 UTC (permalink / raw)
To: Lucas Seiki Oshiro
Cc: git, sandals, kumarayushjha123, a3205153416, valusoutrik,
pushkarkumarsingh1970
On Sun, Mar 1, 2026 at 4:14 AM Lucas Seiki Oshiro
<lucasseikioshiro@gmail.com> wrote:
>
> Hi!
>
Hey Lucas,
> This patch series adds support for path-related fields in repo-info, based on
> what we already have in git-rev-parse:
>
> 1. The two first patches moves the path formatting used by git-rev-parse to
> path.c. This will allow us to reuse this code in git-repo-info
> 2. The second patch add a new flag --path-format to git-repo-info, similar to
> the flag of git-rev-parse with the same name
> 3. Add the new field `path.toplevel` as a proof of concept.
>
> This arises from the fact that I didn't know what should be the default behavior
> of git-repo-info when dealing with paths. Some ideas were:
>
> 1. Add --path-format, just like we have in git-rev-parse
> 2. Use what rev-parse uses by default
> 3. Add keys for both relative and absolute formats
>
> In this case, I'm using 1, but I'm not sure if it's the best option. One
> downside that I see here is that git-repo-info won't be able to return
> a relative and an absolute path for different keys in the same call.
>
Option 1 feels like the cleanest approach.
Even though it means git-repo-info can't return both a relative and
absolute path in the exact same call, it keeps the API highly predictable
for scripting without bloating the key namespace (which Option 3 would do).
The behaviour is different when compared to the command itself where we
have to use --all, but I think in this area this is the right approach.
> Since there are many people interested in contributing to git-repo-info, I'll
> leave the remaining path-related fields to them :-)
>
Thank you ;)
> I'm CC'ing here:
>
> - brian, who was the original author of the `print_path` [1]
> - Ayush, Tian, Jayatheerth, Soutrik and Pushkar, since they expressed interested
> in contributing to git-repo-info in GSoC. (I hope that I didn't forget anyone)
>
> This patch is based on top of master 2cc7191751 (The 8th batch, 2026-02-27) with
> lo/repo-leftover-bits merged.
This provides a fantastic foundation.
I have updated my GSoC proposal based on these patches to build out
the remaining path.* keys, alongside category-based querying and
global state removal.
I will be sending that in a completely new thread shortly.
Regards
- Jayatheerth
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH 0/4] repo: add support for path-related fields
2026-03-01 2:58 ` [PATCH 0/4] repo: add support for path-related fields JAYATHEERTH K
@ 2026-03-01 5:45 ` Ayush Jha
2026-03-01 6:50 ` JAYATHEERTH K
2026-03-01 19:55 ` Lucas Seiki Oshiro
2026-03-01 19:49 ` Lucas Seiki Oshiro
1 sibling, 2 replies; 26+ messages in thread
From: Ayush Jha @ 2026-03-01 5:45 UTC (permalink / raw)
To: JAYATHEERTH K
Cc: Lucas Seiki Oshiro, git, sandals, a3205153416, valusoutrik,
pushkarkumarsingh1970
Hi Lucas,
Thanks for sharing this series — moving the path formatting logic into
path.c makes a lot of sense and avoids duplication with rev-parse.
Regarding the limitation you mentioned about not being able to mix
relative and absolute paths within the same invocation, I was
wondering whether it might be worth considering making the path format
part of the key itself, rather than controlled by a global flag.
For example, something along the lines of:
path.toplevel
path.absolute.toplevel
path.relative.toplevel
This could allow users to request different formats in a single call
without introducing global state into the command output.
That said, I’m not sure whether this would complicate the key
namespace too much, or whether maintaining parity with rev-parse
semantics is preferable for consistency.
I’d be interested to hear your thoughts on this trade-off.
Best,
Ayush
On Sun, Mar 1, 2026 at 8:28 AM JAYATHEERTH K
<jayatheerthkulkarni2005@gmail.com> wrote:
>
> On Sun, Mar 1, 2026 at 4:14 AM Lucas Seiki Oshiro
> <lucasseikioshiro@gmail.com> wrote:
> >
> > Hi!
> >
>
> Hey Lucas,
>
> > This patch series adds support for path-related fields in repo-info, based on
> > what we already have in git-rev-parse:
> >
> > 1. The two first patches moves the path formatting used by git-rev-parse to
> > path.c. This will allow us to reuse this code in git-repo-info
> > 2. The second patch add a new flag --path-format to git-repo-info, similar to
> > the flag of git-rev-parse with the same name
> > 3. Add the new field `path.toplevel` as a proof of concept.
> >
> > This arises from the fact that I didn't know what should be the default behavior
> > of git-repo-info when dealing with paths. Some ideas were:
> >
> > 1. Add --path-format, just like we have in git-rev-parse
> > 2. Use what rev-parse uses by default
> > 3. Add keys for both relative and absolute formats
> >
> > In this case, I'm using 1, but I'm not sure if it's the best option. One
> > downside that I see here is that git-repo-info won't be able to return
> > a relative and an absolute path for different keys in the same call.
> >
>
> Option 1 feels like the cleanest approach.
> Even though it means git-repo-info can't return both a relative and
> absolute path in the exact same call, it keeps the API highly predictable
> for scripting without bloating the key namespace (which Option 3 would do).
>
> The behaviour is different when compared to the command itself where we
> have to use --all, but I think in this area this is the right approach.
>
> > Since there are many people interested in contributing to git-repo-info, I'll
> > leave the remaining path-related fields to them :-)
> >
>
> Thank you ;)
>
> > I'm CC'ing here:
> >
> > - brian, who was the original author of the `print_path` [1]
> > - Ayush, Tian, Jayatheerth, Soutrik and Pushkar, since they expressed interested
> > in contributing to git-repo-info in GSoC. (I hope that I didn't forget anyone)
> >
> > This patch is based on top of master 2cc7191751 (The 8th batch, 2026-02-27) with
> > lo/repo-leftover-bits merged.
>
>
> This provides a fantastic foundation.
> I have updated my GSoC proposal based on these patches to build out
> the remaining path.* keys, alongside category-based querying and
> global state removal.
>
> I will be sending that in a completely new thread shortly.
>
> Regards
> - Jayatheerth
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 0/4] repo: add support for path-related fields
2026-03-01 5:45 ` Ayush Jha
@ 2026-03-01 6:50 ` JAYATHEERTH K
2026-03-01 19:55 ` Lucas Seiki Oshiro
1 sibling, 0 replies; 26+ messages in thread
From: JAYATHEERTH K @ 2026-03-01 6:50 UTC (permalink / raw)
To: Ayush Jha
Cc: Lucas Seiki Oshiro, git, sandals, a3205153416, valusoutrik,
pushkarkumarsingh1970
Hi Ayush,
On Sun, Mar 1, 2026 at 11:15 AM Ayush Jha <kumarayushjha123@gmail.com> wrote:
>
> Hi Lucas,
>
> Thanks for sharing this series — moving the path formatting logic into
> path.c makes a lot of sense and avoids duplication with rev-parse.
>
> Regarding the limitation you mentioned about not being able to mix
> relative and absolute paths within the same invocation, I was
> wondering whether it might be worth considering making the path format
> part of the key itself, rather than controlled by a global flag.
>
> For example, something along the lines of:
> path.toplevel
> path.absolute.toplevel
> path.relative.toplevel
>
> This could allow users to request different formats in a single call
> without introducing global state into the command output.
> That said, I’m not sure whether this would complicate the key
> namespace too much, or whether maintaining parity with rev-parse
> semantics is preferable for consistency.
I think this idea works for individual retrieval
It still won't work when the request is for --all
The main problem of absolute vs relative would arrive from the --all
perspective, no?
If a script specifically needs both formats for a set of paths, the
caller can easily just invoke the command twice:
i.e git repo info --path-format=absolute <keys...>
git repo info --path-format=relative <keys...>
It would still work for individual path terms
I think adding the absolute or relative terms in key is more of a
"user" friendly one.
What do you think about it?
Regards,
- Jayatheerth
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 0/4] repo: add support for path-related fields
2026-03-01 5:45 ` Ayush Jha
2026-03-01 6:50 ` JAYATHEERTH K
@ 2026-03-01 19:55 ` Lucas Seiki Oshiro
2026-03-03 3:27 ` Ayush Jha
1 sibling, 1 reply; 26+ messages in thread
From: Lucas Seiki Oshiro @ 2026-03-01 19:55 UTC (permalink / raw)
To: Ayush Jha
Cc: JAYATHEERTH K, git, sandals, a3205153416, valusoutrik,
pushkarkumarsingh1970
> Hi Lucas,
Hi, Ayush!
> Thanks for sharing this series — moving the path formatting logic into
> path.c makes a lot of sense and avoids duplication with rev-parse.
Yeah, but since git-repo-info was written as a better home for
some features currently in git-rev-parse, now we can think in
better solutions.
> For example, something along the lines of:
> path.toplevel
> path.absolute.toplevel
> path.relative.toplevel
I also thought about that, but what would happen with --all?
If --all returns both absolute and relative, then we would
have the third solution.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 0/4] repo: add support for path-related fields
2026-03-01 19:55 ` Lucas Seiki Oshiro
@ 2026-03-03 3:27 ` Ayush Jha
0 siblings, 0 replies; 26+ messages in thread
From: Ayush Jha @ 2026-03-03 3:27 UTC (permalink / raw)
To: Lucas Seiki Oshiro
Cc: JAYATHEERTH K, git, sandals, a3205153416, valusoutrik,
pushkarkumarsingh1970
Hi Lucas,
I completely agree that having --all dump three variants of every path
(default, relative, absolute) would be far too noisy and defeat the
purpose of a clean metadata dump.
My thought is that the path.absolute.* and path.relative.* keys could
be treated as "virtual" or computed keys.
If a user runs --all, the command would only iterate over and print
the base keys (e.g., path.toplevel, path.git-dir). The specific format
variants would simply be hidden from the iteration list, much like how
some APIs only return expensive or highly-specific fields if they are
explicitly requested.
This way, --all stays perfectly clean and concise, but scripts that
need mixed granular control can still invoke git repo info
path.absolute.git-dir path.relative.toplevel in a single pass without
relying on global state flags.
Do you think treating them as explicit-request-only fields strikes the
right balance between a clean --all output and a stateless API?
On Mon, Mar 2, 2026 at 1:25 AM Lucas Seiki Oshiro
<lucasseikioshiro@gmail.com> wrote:
>
>
> > Hi Lucas,
>
> Hi, Ayush!
>
> > Thanks for sharing this series — moving the path formatting logic into
> > path.c makes a lot of sense and avoids duplication with rev-parse.
>
> Yeah, but since git-repo-info was written as a better home for
> some features currently in git-rev-parse, now we can think in
> better solutions.
>
> > For example, something along the lines of:
> > path.toplevel
> > path.absolute.toplevel
> > path.relative.toplevel
>
> I also thought about that, but what would happen with --all?
> If --all returns both absolute and relative, then we would
> have the third solution.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 0/4] repo: add support for path-related fields
2026-03-01 2:58 ` [PATCH 0/4] repo: add support for path-related fields JAYATHEERTH K
2026-03-01 5:45 ` Ayush Jha
@ 2026-03-01 19:49 ` Lucas Seiki Oshiro
1 sibling, 0 replies; 26+ messages in thread
From: Lucas Seiki Oshiro @ 2026-03-01 19:49 UTC (permalink / raw)
To: JAYATHEERTH K
Cc: git, sandals, kumarayushjha123, a3205153416, valusoutrik,
pushkarkumarsingh1970
> Option 1 feels like the cleanest approach.
> Even though it means git-repo-info can't return both a relative and
> absolute path in the exact same call, it keeps the API highly predictable
> for scripting without bloating the key namespace (which Option 3 would do).
Yeah. I think that in the future most of them will be
path.*, and 3 would double them...
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 0/4] repo: add support for path-related fields
2026-02-28 22:05 [PATCH 0/4] repo: add support for path-related fields Lucas Seiki Oshiro
` (4 preceding siblings ...)
2026-03-01 2:58 ` [PATCH 0/4] repo: add support for path-related fields JAYATHEERTH K
@ 2026-03-01 10:44 ` Phillip Wood
2026-03-01 19:40 ` Lucas Seiki Oshiro
2026-03-01 21:25 ` brian m. carlson
6 siblings, 1 reply; 26+ messages in thread
From: Phillip Wood @ 2026-03-01 10:44 UTC (permalink / raw)
To: Lucas Seiki Oshiro, git
Cc: sandals, kumarayushjha123, a3205153416, jayatheerthkulkarni2005,
valusoutrik, pushkarkumarsingh1970
Hi Lucas
On 28/02/2026 22:05, Lucas Seiki Oshiro wrote:
> Hi!
>
> This patch series adds support for path-related fields in repo-info, based on
> what we already have in git-rev-parse:
>
> 1. The two first patches moves the path formatting used by git-rev-parse to
> path.c. This will allow us to reuse this code in git-repo-info
> 2. The second patch add a new flag --path-format to git-repo-info, similar to
> the flag of git-rev-parse with the same name
> 3. Add the new field `path.toplevel` as a proof of concept.
How does this effort relate to similar effort at at
https://lore.kernel.org/pull.2208.v5.git.git.1772220640.gitgitgadget@gmail.com
?
Also note the suggestion from Junio in that thread to use
"path.working-tree" rather than copying the name from "git rev-parse"
> This arises from the fact that I didn't know what should be the default behavior
> of git-repo-info when dealing with paths. Some ideas were:
>
> 1. Add --path-format, just like we have in git-rev-parse
I think that's the best solution. Having different defaults for
different paths like rev-parse is confusing and having different keys
for absolute and relative versions of the same path gets rather verbose.
Thanks
Phillip
> 2. Use what rev-parse uses by default
> 3. Add keys for both relative and absolute formats
>
> In this case, I'm using 1, but I'm not sure if it's the best option. One
> downside that I see here is that git-repo-info won't be able to return
> a relative and an absolute path for different keys in the same call.
>
> Since there are many people interested in contributing to git-repo-info, I'll
> leave the remaining path-related fields to them :-)
>
> I'm CC'ing here:
>
> - brian, who was the original author of the `print_path` [1]
> - Ayush, Tian, Jayatheerth, Soutrik and Pushkar, since they expressed interested
> in contributing to git-repo-info in GSoC. (I hope that I didn't forget anyone)
>
> This patch is based on top of master 2cc7191751 (The 8th batch, 2026-02-27) with
> lo/repo-leftover-bits merged.
>
> [1] fac60b8925 (rev-parse: add option for absolute or relative path formatting, 2020-12-13)
>
> Lucas Seiki Oshiro (4):
> rev-parse: prepend `path_` to path-related enums
> path: add new function strbuf_add_path
> repo: add the --format-path flag
> repo: add the field path.toplevel
>
> Documentation/git-repo.adoc | 8 ++-
> builtin/repo.c | 67 +++++++++++++++++++------
> builtin/rev-parse.c | 98 +++++++------------------------------
> path.c | 51 +++++++++++++++++++
> path.h | 23 +++++++++
> t/t1900-repo-info.sh | 69 ++++++++++++++++++++++++++
> 6 files changed, 221 insertions(+), 95 deletions(-)
>
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH 0/4] repo: add support for path-related fields
2026-03-01 10:44 ` Phillip Wood
@ 2026-03-01 19:40 ` Lucas Seiki Oshiro
0 siblings, 0 replies; 26+ messages in thread
From: Lucas Seiki Oshiro @ 2026-03-01 19:40 UTC (permalink / raw)
To: phillip.wood
Cc: git, sandals, kumarayushjha123, a3205153416,
jayatheerthkulkarni2005, valusoutrik, pushkarkumarsingh1970,
eslam reda, karthik.188, jltobler, ayu.chandekar,
Patrick Steinhardt
> Hi Lucas
Hi, Phillip!
> How does this effort relate to similar effort at at
> https://lore.kernel.org/pull.2208.v5.git.git.1772220640.gitgitgadget@gmail.com ?
I have this patch series started since July, but I could only
send this after having my two previous changes in git-repo-info
accepted.
I think that patch series you mentioned is based on some
previous message (or the GSoC project ideas) where I listed
what was still need to be implemented. It uses a similar
--path-format flag, but without dealing with the multiple
possibilities currently used by git-rev-parse (see [1]).
The original print_path from git-rev-parse has four possible
default formats (relative, relative if there's a shared root,
canonical (absolute), and unmodified), and we can force it
to use the relative or absolute formats. If I understood it
correctly, this complex logic was added ([1]) to allow the
user to force one of these two formats without breaking the
default behavior. Since git-repo-info is a new command, we are
free from being compatible with that, and perhaps this doesn't
make sense.
Since there are many people interested in contributing to
git-repo-info, especially in the path-* fields, I just wanted
to finish what I have here and leave the rest for them :-)
>> 1. Add --path-format, just like we have in git-rev-parse
>
> I think that's the best solution. Having different defaults
> for different paths like rev-parse is confusing and having
> different keys for absolute and relative versions of the
> same path gets rather verbose.
I agree, but I still think that it feels weird that we won't
be able return absolute and relative paths in a single
git-repo-info call. But it also won't cost too much to call
it twice.
> Thanks
Thanks, Phillip!
Phillip
PS: I'm also CC'ing:
- Eslam (the author of the patch mentioned by Phillip)
- Karthik, Justin, Ayush, and Siddhart (possible mentors for
"Improve the new git repo command")
- Patrick, who was my GSoC mentor and the person I first
discussed with about --path-format
[1] fac60b8925 (rev-parse: add option for absolute or relative path formatting, 2020-12-13)
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 0/4] repo: add support for path-related fields
2026-02-28 22:05 [PATCH 0/4] repo: add support for path-related fields Lucas Seiki Oshiro
` (5 preceding siblings ...)
2026-03-01 10:44 ` Phillip Wood
@ 2026-03-01 21:25 ` brian m. carlson
2026-03-02 16:38 ` Junio C Hamano
2026-03-08 0:29 ` Lucas Seiki Oshiro
6 siblings, 2 replies; 26+ messages in thread
From: brian m. carlson @ 2026-03-01 21:25 UTC (permalink / raw)
To: Lucas Seiki Oshiro
Cc: git, kumarayushjha123, a3205153416, jayatheerthkulkarni2005,
valusoutrik, pushkarkumarsingh1970
[-- Attachment #1: Type: text/plain, Size: 2174 bytes --]
On 2026-02-28 at 22:05:54, Lucas Seiki Oshiro wrote:
> Hi!
>
> This patch series adds support for path-related fields in repo-info, based on
> what we already have in git-rev-parse:
>
> 1. The two first patches moves the path formatting used by git-rev-parse to
> path.c. This will allow us to reuse this code in git-repo-info
> 2. The second patch add a new flag --path-format to git-repo-info, similar to
> the flag of git-rev-parse with the same name
> 3. Add the new field `path.toplevel` as a proof of concept.
>
> This arises from the fact that I didn't know what should be the default behavior
> of git-repo-info when dealing with paths. Some ideas were:
>
> 1. Add --path-format, just like we have in git-rev-parse
> 2. Use what rev-parse uses by default
> 3. Add keys for both relative and absolute formats
>
> In this case, I'm using 1, but I'm not sure if it's the best option. One
> downside that I see here is that git-repo-info won't be able to return
> a relative and an absolute path for different keys in the same call.
I think you should provide both. I originally added this for things
like `--git-common-dir`, which Git LFS would really like to have as an
absolute path in the way that Git canonicalizes it, as well as
potentially a relative path.
The reason is that the way Git canonicalizes things on Windows is not
easily accessible on all systems or in all languages. For instance, Go
has steadfastly refused to provide functionality for
`GetFinalPathnameByHandle`, despite that being necessary to canonicalize
the way Git does, so it's important to be able to get that information
both in a relative way and as an absolute path.
On Unix, things are easier since there are fewer special file system
objects and `realpath` or its equivalent are usually present in most
languages.
With `git rev-parse`, you can change `--path-format` on the command line
between options, so if you want both, you just request one thing, use
`--path-format`, and then request the other. However, that can't be
done with `git repo` and `--path-format`.
--
brian m. carlson (they/them)
Toronto, Ontario, CA
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 262 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH 0/4] repo: add support for path-related fields
2026-03-01 21:25 ` brian m. carlson
@ 2026-03-02 16:38 ` Junio C Hamano
2026-03-02 18:51 ` Tian Yuchen
2026-03-08 0:29 ` Lucas Seiki Oshiro
1 sibling, 1 reply; 26+ messages in thread
From: Junio C Hamano @ 2026-03-02 16:38 UTC (permalink / raw)
To: brian m. carlson
Cc: Lucas Seiki Oshiro, git, kumarayushjha123, a3205153416,
jayatheerthkulkarni2005, valusoutrik, pushkarkumarsingh1970
"brian m. carlson" <sandals@crustytoothpaste.net> writes:
> With `git rev-parse`, you can change `--path-format` on the command line
> between options, so if you want both, you just request one thing, use
> `--path-format`, and then request the other. However, that can't be
> done with `git repo` and `--path-format`.
Hmph, that is one advantage of that incremental option handling done
by "rev-parse", which often is a source of confusion and complaints,
though ;-)
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 0/4] repo: add support for path-related fields
2026-03-02 16:38 ` Junio C Hamano
@ 2026-03-02 18:51 ` Tian Yuchen
2026-03-02 21:34 ` Junio C Hamano
2026-03-03 2:48 ` JAYATHEERTH K
0 siblings, 2 replies; 26+ messages in thread
From: Tian Yuchen @ 2026-03-02 18:51 UTC (permalink / raw)
To: Junio C Hamano, brian m. carlson
Cc: Lucas Seiki Oshiro, git, kumarayushjha123,
jayatheerthkulkarni2005, valusoutrik, pushkarkumarsingh1970
On 3/3/26 00:38, Junio C Hamano wrote:
> "brian m. carlson" <sandals@crustytoothpaste.net> writes:
>
>> With `git rev-parse`, you can change `--path-format` on the command line
>> between options, so if you want both, you just request one thing, use
>> `--path-format`, and then request the other. However, that can't be
>> done with `git repo` and `--path-format`.
>
> Hmph, that is one advantage of that incremental option handling done
> by "rev-parse", which often is a source of confusion and complaints,
> though ;-)
Short question: Is using format modifier like (%path:relative),
(%path:absolute) a good solution here? I think it can be implemented by
simply adding a path parsing function in ref-filter.c (and some other
work that aren't particularly challenging).
It should be user-friendly, readable and free of global flags, right? :-]
Regards,
Yuchen
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 0/4] repo: add support for path-related fields
2026-03-02 18:51 ` Tian Yuchen
@ 2026-03-02 21:34 ` Junio C Hamano
2026-03-03 2:48 ` JAYATHEERTH K
1 sibling, 0 replies; 26+ messages in thread
From: Junio C Hamano @ 2026-03-02 21:34 UTC (permalink / raw)
To: Tian Yuchen
Cc: brian m. carlson, Lucas Seiki Oshiro, git, kumarayushjha123,
jayatheerthkulkarni2005, valusoutrik, pushkarkumarsingh1970
Tian Yuchen <a3205153416@gmail.com> writes:
> On 3/3/26 00:38, Junio C Hamano wrote:
>> "brian m. carlson" <sandals@crustytoothpaste.net> writes:
>>
>>> With `git rev-parse`, you can change `--path-format` on the command line
>>> between options, so if you want both, you just request one thing, use
>>> `--path-format`, and then request the other. However, that can't be
>>> done with `git repo` and `--path-format`.
>>
>> Hmph, that is one advantage of that incremental option handling done
>> by "rev-parse", which often is a source of confusion and complaints,
>> though ;-)
>
> Short question: Is using format modifier like (%path:relative),
> (%path:absolute) a good solution here? I think it can be implemented by
> simply adding a path parsing function in ref-filter.c (and some other
> work that aren't particularly challenging).
>
> It should be user-friendly, readable and free of global flags, right? :-]
What command are we talking about now? Is it a plumbing where
predictability, simplicity and performance matters more than
end-user friendliness?
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 0/4] repo: add support for path-related fields
2026-03-02 18:51 ` Tian Yuchen
2026-03-02 21:34 ` Junio C Hamano
@ 2026-03-03 2:48 ` JAYATHEERTH K
2026-03-03 4:32 ` Tian Yuchen
1 sibling, 1 reply; 26+ messages in thread
From: JAYATHEERTH K @ 2026-03-03 2:48 UTC (permalink / raw)
To: Tian Yuchen
Cc: Junio C Hamano, brian m. carlson, Lucas Seiki Oshiro, git,
kumarayushjha123, valusoutrik, pushkarkumarsingh1970
>
> Short question: Is using format modifier like (%path:relative),
> (%path:absolute) a good solution here? I think it can be implemented by
> simply adding a path parsing function in ref-filter.c (and some other
> work that aren't particularly challenging).
>
I see your point here.
but wouldn't this effectively be the same as Ayush's suggestion, just
with a different syntax?
Whether we use distinct keys (path.absolute.toplevel) or format
modifiers (%(path:absolute))
It would still result in almost the same internals.
>
> Short question: Is using format modifier like (%path:relative),
> (%path:absolute) a good solution here? I think it can be implemented by
> simply adding a path parsing function in ref-filter.c (and some other
> work that aren't particularly challenging).
>
> It should be user-friendly, readable and free of global flags, right? :-]
I don't think the syntax is a concern, even if both of them are equally verbose.
Coming to user friendliness
I believe Junio has already raised an appropriate question.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 0/4] repo: add support for path-related fields
2026-03-03 2:48 ` JAYATHEERTH K
@ 2026-03-03 4:32 ` Tian Yuchen
2026-03-03 7:23 ` JAYATHEERTH K
0 siblings, 1 reply; 26+ messages in thread
From: Tian Yuchen @ 2026-03-03 4:32 UTC (permalink / raw)
To: JAYATHEERTH K
Cc: Junio C Hamano, brian m. carlson, Lucas Seiki Oshiro, git,
kumarayushjha123, valusoutrik, pushkarkumarsingh1970
Hi JAYATHEERTH,
> I see your point here.
> but wouldn't this effectively be the same as Ayush's suggestion, just
> with a different syntax?
In my view, this issue is actually to choose the most suitable tool for
the job. After all, we don't want to use something like rev-parse, which
is riddled with *ancient* technical debt, nor do we want to write an
even more verbose parsing function from scratch for what you call
verbose user input, right?
If I'm not mistaken, using different parsing functions to parse input is
absolutely not just a matter of syntax differences. Instead, this will
directly result in differences in data structures.
In ref-filter.c, we can easily see how Git parses format modifiers.
After the user input is parse by parse_ref_filter_atom(), it is then
passed to the atom_valid[] static registry, which is like;
static struct {
const char *name;
info_source source;
cmp_type cmp_type;
int (*parser)(struct ref_format *format, struct used_atom *atom,
const char *arg, struct strbuf *err);
} valid_atom[] = {
[ATOM_REFNAME] = { "refname", SOURCE_NONE, FIELD_STR,
refname_atom_parser },
[ATOM_OBJECTTYPE] = { "objecttype", SOURCE_OTHER, FIELD_STR,
objecttype_atom_parser },
[ATOM_OBJECTSIZE] = { "objectsize", SOURCE_OTHER, FIELD_ULONG,
objectsize_atom_parser },
[ATOM_OBJECTNAME] = { "objectname", SOURCE_OTHER, FIELD_STR,
oid_atom_parser },
...
As you can see, each mapping relationship points to a parsing function
(..._parser()). This parsing function is solely responsible for handling
the state arg, fundamentally resolving the issue of function
responsibility/naming confusion.
The reason I recommend this approach is because its implementation is
incredibly clear and concise. To achieve the functionality we desire,
all we need to do is add the following to the registry:
[ATOM_PATH] = { "path", SOURCE_NONE, FIELD_STR, path_atom_parser }
And the corresponding path_atom_parser().
This approach also offers strong scalability: If one day I decide to add
a new feature like %(path:commondir,relative) output, all it would take
is adding a switch statement in the parser() function (along with a few
other minor tweaks).
*I'm not saying this approach is better than the solution you've
discussed. I'm simply presenting a possible implementation for
reference. (´~`)
> Coming to user friendliness
> I believe Junio has already raised an appropriate question.
This isn't a case of “you can't have your cake and eat it too,” right? I
think user-friendliness can be achieved without compromising
maintainability, predictability, or high performance in this case.
Regards,
Yuchen
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH 0/4] repo: add support for path-related fields
2026-03-03 4:32 ` Tian Yuchen
@ 2026-03-03 7:23 ` JAYATHEERTH K
2026-03-03 9:28 ` Tian Yuchen
0 siblings, 1 reply; 26+ messages in thread
From: JAYATHEERTH K @ 2026-03-03 7:23 UTC (permalink / raw)
To: Tian Yuchen
Cc: Junio C Hamano, brian m. carlson, Lucas Seiki Oshiro, git,
kumarayushjha123, valusoutrik, pushkarkumarsingh1970
On Tue, Mar 3, 2026 at 10:02 AM Tian Yuchen <a3205153416@gmail.com> wrote:
>
> Hi JAYATHEERTH,
Hi Tian,
>
> > I see your point here.
> > but wouldn't this effectively be the same as Ayush's suggestion, just
> > with a different syntax?
>
> In my view, this issue is actually to choose the most suitable tool for
> the job. After all, we don't want to use something like rev-parse, which
> is riddled with *ancient* technical debt, nor do we want to write an
> even more verbose parsing function from scratch for what you call
> verbose user input, right?
>
I agree that it provides a clean and scalable mechanism,
especially in terms of extensibility and per-field formatting without
relying on global flags.
To clarify my earlier comment: I wasn't arguing against ref-filter.
In fact, I’m more inclined toward using the best tool for the job.
My earlier point was mainly about behavioral similarity and how both
belong to the same camp even though they might seem different.
> If I'm not mistaken, using different parsing functions to parse input is
> absolutely not just a matter of syntax differences. Instead, this will
> directly result in differences in data structures.
>
> The reason I recommend this approach is because its implementation is
> incredibly clear and concise. To achieve the functionality we desire,
> all we need to do is add the following to the registry:
>
> [ATOM_PATH] = { "path", SOURCE_NONE, FIELD_STR, path_atom_parser }
>
> And the corresponding path_atom_parser().
>
> This approach also offers strong scalability: If one day I decide to add
> a new feature like %(path:commondir,relative) output, all it would take
> is adding a switch statement in the parser() function (along with a few
> other minor tweaks).
>
> *I'm not saying this approach is better than the solution you've
> discussed. I'm simply presenting a possible implementation for
> reference. (´~`)
That is a detailed mail, thanks for taking time
When I said similar
I meant
something like this:
static const struct repo_info_field repo_info_field[] = {
{ "layout.bare", get_layout_bare },
{ "layout.shallow", get_layout_shallow },
{ "object.format", get_object_format },
{ "path.toplevel", get_path_toplevel },
};
This array contains all the keys
You do not need to hardcode path.absolute.toplevel,
path.relative.toplevel, etc., in the array...
Instead,
If the user asks for path.absolute.toplevel:
You detect the absolute. middle part. strip it out to find the base
key path.toplevel.
You find path.toplevel in the aray, the array works with default
values when entered --all
/*
* Helper to parse the key variant.
* Takes "path.absolute.git-dir" -> returns "path.git-dir" and sets
opts->format.
*/
static char *normalize_key(const char *raw_key, struct repo_info_opts *opts)
{
const char *suffix;
/* Check for "path.absolute." prefix */
if (skip_prefix(raw_key, "path.absolute.", &suffix)) {
opts->path_format = PATH_FORMAT_ABSOLUTE;
return xstrfmt("path.%s", suffix);
}
/* Check for "path.relative." prefix */
if (skip_prefix(raw_key, "path.relative.", &suffix)) {
opts->path_format = PATH_FORMAT_RELATIVE;
return xstrfmt("path.%s", suffix);
}
/* No variant found, return raw key as-is */
return xstrdup(raw_key);
}
Structurally, this mimics the ref-filter parsing phase almost exactly.
Just as ref-filter splits a compound atom like %(refname:short) into an identity
(refname) and a modifier (short) to populate the handler's state,
normalize_key splits path.absolute.git-dir into the identity
(path.git-dir) and the modifier (absolute).
I just meant both the ideas are in the same camp just unrealized.
What do you think?
Regards
- Jayatheerth
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH 0/4] repo: add support for path-related fields
2026-03-03 7:23 ` JAYATHEERTH K
@ 2026-03-03 9:28 ` Tian Yuchen
2026-03-03 10:31 ` JAYATHEERTH K
0 siblings, 1 reply; 26+ messages in thread
From: Tian Yuchen @ 2026-03-03 9:28 UTC (permalink / raw)
To: JAYATHEERTH K
Cc: Junio C Hamano, brian m. carlson, Lucas Seiki Oshiro, git,
kumarayushjha123, valusoutrik, pushkarkumarsingh1970
Hi JAYATHEERTH,
Thanks for the reply.
> To clarify my earlier comment: I wasn't arguing against ref-filter.
> In fact, I’m more inclined toward using the best tool for the job.
> My earlier point was mainly about behavioral similarity and how both
> belong to the same camp even though they might seem different.
> I just meant both the ideas are in the same camp just unrealized.
That's exactly right. I was just reminding that there's a ready-made
solution available that seems to work very well. Wouldn't reinventing
something that already exists, with only minor differences, cause
confusion? (´;ω;`)
> something like this:
>
> static const struct repo_info_field repo_info_field[] = {
> { "layout.bare", get_layout_bare },
> { "layout.shallow", get_layout_shallow },
> { "object.format", get_object_format },
> { "path.toplevel", get_path_toplevel },
> };
>
> This array contains all the keys
> You do not need to hardcode path.absolute.toplevel,
> path.relative.toplevel, etc., in the array...
>
> Instead,
>
> If the user asks for path.absolute.toplevel:
> You detect the absolute. middle part. strip it out to find the base
> key path.toplevel.
> You find path.toplevel in the aray, the array works with default
> values when entered --all
>
> /*
> * Helper to parse the key variant.
> * Takes "path.absolute.git-dir" -> returns "path.git-dir" and sets
> opts->format.
> */
> static char *normalize_key(const char *raw_key, struct repo_info_opts *opts)
> {
> const char *suffix;
>
> /* Check for "path.absolute." prefix */
> if (skip_prefix(raw_key, "path.absolute.", &suffix)) {
> opts->path_format = PATH_FORMAT_ABSOLUTE;
> return xstrfmt("path.%s", suffix);
> }
>
> /* Check for "path.relative." prefix */
> if (skip_prefix(raw_key, "path.relative.", &suffix)) {
> opts->path_format = PATH_FORMAT_RELATIVE;
> return xstrfmt("path.%s", suffix);
> }
>
> /* No variant found, return raw key as-is */
> return xstrdup(raw_key);
> }
I see. What you've written matches what you described — it essentially
replicates the functionality of ref-filter.c. While I understand this is
just a simple code implementation demo:
> opts->path_format = PATH_FORMAT_ABSOLUTE;
This implementation appears unable to support input like 'git repo-info
--keys=path.absolute.toplevel,path.relative.gitdir', meaning it cannot
handle multiple paths output from a single call as previously mentioned
by Brain. The 'opts' here should be a global shared state, right?
I think it's better for the parser to allocate a separate memory for
each arg it encounters. But then we'd be back to implementing something
like struct used_atom, hahaha (ゝ∀・)
Thank you again for your email.
Yuchen
(I feel like we've been on this topic for too long. If you don't want to
reply, you don't have to :-)
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH 0/4] repo: add support for path-related fields
2026-03-03 9:28 ` Tian Yuchen
@ 2026-03-03 10:31 ` JAYATHEERTH K
0 siblings, 0 replies; 26+ messages in thread
From: JAYATHEERTH K @ 2026-03-03 10:31 UTC (permalink / raw)
To: Tian Yuchen
Cc: Junio C Hamano, brian m. carlson, Lucas Seiki Oshiro, git,
kumarayushjha123, valusoutrik, pushkarkumarsingh1970
>
> I see. What you've written matches what you described — it essentially
> replicates the functionality of ref-filter.c. While I understand this is
> just a simple code implementation demo:
>
> > opts->path_format = PATH_FORMAT_ABSOLUTE;
>
> This implementation appears unable to support input like 'git repo-info
> --keys=path.absolute.toplevel,path.relative.gitdir', meaning it cannot
> handle multiple paths output from a single call as previously mentioned
> by Brain. The 'opts' here should be a global shared state, right?
>
> I think it's better for the parser to allocate a separate memory for
> each arg it encounters. But then we'd be back to implementing something
> like struct used_atom, hahaha (ゝ∀・)
>
> Thank you again for your email.
>
> Yuchen
We create a fresh local_opts copy from the global_opts defaults for
every single key:
for (int i = 0; i < argc; i++) {
struct repo_info_opts local_opts = global_opts; /* Fresh reset */
char *base_key = normalize_key(argv[i], &local_opts);
/* ... find_field and get_value logic ... */
}
Since local_opts is local to the loop iteration,
path.absolute.toplevel only modifies the state for that specific turn.
When the loop moves to path.relative.gitdir, it gets a brand-new
local_opts and starts over.
It handles mixed formats in a single call perfectly, without any
persistent _pollution_ or the need for complex heap allocations.
>
> (I feel like we've been on this topic for too long. If you don't want to
> reply, you don't have to :-)
>
I agree we've covered a lot of ground here, so I'll leave it at that.
Thanks for the great discussion ;)
Regards,
Jayatheerth
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 0/4] repo: add support for path-related fields
2026-03-01 21:25 ` brian m. carlson
2026-03-02 16:38 ` Junio C Hamano
@ 2026-03-08 0:29 ` Lucas Seiki Oshiro
1 sibling, 0 replies; 26+ messages in thread
From: Lucas Seiki Oshiro @ 2026-03-08 0:29 UTC (permalink / raw)
To: brian m. carlson
Cc: git, kumarayushjha123, a3205153416, jayatheerthkulkarni2005,
valusoutrik, pushkarkumarsingh1970, jtobler, karthik nayak,
Patrick Steinhardt
> I think you should provide both. I originally added this for things
> like `--git-common-dir`, which Git LFS would really like to have as an
> absolute path in the way that Git canonicalizes it, as well as
> potentially a relative path.
Thanks for your input, brian!
> With `git rev-parse`, you can change `--path-format` on the command line
> between options, so if you want both, you just request one thing, use
> `--path-format`, and then request the other. However, that can't be
> done with `git repo` and `--path-format`.
It makes sense. If we use the key format suggested by Ayush [1]
we could retrieve both values with something like
$ git repo info path.git-dir.absolute path.git-dir.relative
I'll stop by now. Since many people are interested in contributing to
git-repo-info in GSoC, I'll leave this decision to the person who will
work on it, if there is one.
[1] B46AA932-28EF-4A2C-96B9-0F05D9641C1C@gmail.com
^ permalink raw reply [flat|nested] 26+ messages in thread