{"thread":{"id":"65101","subject":"[PATCH 0/4] repo: add support for path-related fields","startedAt":"2026-02-28T22:44:35Z","lastAt":"2026-03-08T00:29:16Z","messageCount":26,"participants":["Lucas Seiki Oshiro","JAYATHEERTH K","Tian Yuchen","Ayush Jha","Phillip Wood","brian m. carlson","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"537411","messageId":"20260228224252.72788-1-lucasseikioshiro@gmail.com","threadId":"65101","inReplyTo":null,"subject":"[PATCH 0/4] repo: add support for path-related fields","fromName":"Lucas Seiki Oshiro","fromEmail":"lucasseikioshiro@gmail.com","sentAt":"2026-02-28T22:05:54Z","receivedAt":"2026-02-28T22:44:35Z","isPatch":true,"sender":{"key":"lucasseikioshiro@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12701580?v=4"},"body":"Hi!\n\nThis patch series adds support for path-related fields in repo-info, based on\nwhat we already have in git-rev-parse:\n\n1. The two first patches moves the path formatting used by git-rev-parse to\n   path.c. This will allow us to reuse this code in git-repo-info\n2. The second patch add a new flag --path-format to git-repo-info, similar to\n   the flag of git-rev-parse with the same name\n3. Add the new field `path.toplevel` as a proof of concept.\n\nThis arises from the fact that I didn't know what should be the default behavior\nof git-repo-info when dealing with paths. Some ideas were:\n\n1. Add --path-format, just like we have in git-rev-parse\n2. Use what rev-parse uses by default\n3. Add keys for both relative and absolute formats\n\nIn this case, I'm using 1, but I'm not sure if it's the best option. One\ndownside that I see here is that git-repo-info won't be able to return\na relative and an absolute path for different keys in the same call.\n\nSince there are many people interested in contributing to git-repo-info, I'll\nleave the remaining path-related fields to them :-)\n\nI'm CC'ing here:\n\n- brian, who was the original author of the `print_path` [1]\n- Ayush, Tian, Jayatheerth, Soutrik and Pushkar, since they expressed interested\n  in contributing to git-repo-info in GSoC. (I hope that I didn't forget anyone)\n\nThis patch is based on top of master 2cc7191751 (The 8th batch, 2026-02-27) with\nlo/repo-leftover-bits merged.\n\n[1] fac60b8925 (rev-parse: add option for absolute or relative path formatting, 2020-12-13)\n\nLucas Seiki Oshiro (4):\n  rev-parse: prepend `path_` to path-related enums\n  path: add new function strbuf_add_path\n  repo: add the --format-path flag\n  repo: add the field path.toplevel\n\n Documentation/git-repo.adoc |  8 ++-\n builtin/repo.c              | 67 +++++++++++++++++++------\n builtin/rev-parse.c         | 98 +++++++------------------------------\n path.c                      | 51 +++++++++++++++++++\n path.h                      | 23 +++++++++\n t/t1900-repo-info.sh        | 69 ++++++++++++++++++++++++++\n 6 files changed, 221 insertions(+), 95 deletions(-)\n\n-- \n2.50.1 (Apple Git-155)\n\n"},{"id":"537412","messageId":"20260228224252.72788-2-lucasseikioshiro@gmail.com","threadId":"65101","inReplyTo":"20260228224252.72788-1-lucasseikioshiro@gmail.com","subject":"[PATCH 1/4] rev-parse: prepend `path_` to path-related enums","fromName":"Lucas Seiki Oshiro","fromEmail":"lucasseikioshiro@gmail.com","sentAt":"2026-02-28T22:05:55Z","receivedAt":"2026-02-28T22:44:38Z","isPatch":true,"sender":{"key":"lucasseikioshiro@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12701580?v=4"},"body":"There are two enums used in rev-parse for deciding how paths will\nbe printed by the function `print_path`: `format_type` and\n`default_type`. Even though there aren't any ambiguities yet, their\nnames aren't clear that those \"types\" are path types.\n\nRename both enums and their values by prepending the word `path_`,\nto clarify that they are used for choosing path types.\n\nSigned-off-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>\n---\n builtin/rev-parse.c | 56 ++++++++++++++++++++++-----------------------\n 1 file changed, 28 insertions(+), 28 deletions(-)\n\ndiff --git a/builtin/rev-parse.c b/builtin/rev-parse.c\nindex 9032cc6327..a2162ff39e 100644\n--- a/builtin/rev-parse.c\n+++ b/builtin/rev-parse.c\n@@ -623,27 +623,27 @@ static void handle_ref_opt(const char *pattern, const char *prefix)\n \tclear_ref_exclusions(&ref_excludes);\n }\n \n-enum format_type {\n+enum path_format_type {\n \t/* We would like a relative path. */\n-\tFORMAT_RELATIVE,\n+\tPATH_FORMAT_RELATIVE,\n \t/* We would like a canonical absolute path. */\n-\tFORMAT_CANONICAL,\n+\tPATH_FORMAT_CANONICAL,\n \t/* We would like the default behavior. */\n-\tFORMAT_DEFAULT,\n+\tPATH_FORMAT_DEFAULT,\n };\n \n-enum default_type {\n+enum path_default_type {\n \t/* Our default is a relative path. */\n-\tDEFAULT_RELATIVE,\n+\tPATH_DEFAULT_RELATIVE,\n \t/* Our default is a relative path if there's a shared root. */\n-\tDEFAULT_RELATIVE_IF_SHARED,\n+\tPATH_DEFAULT_RELATIVE_IF_SHARED,\n \t/* Our default is a canonical absolute path. */\n-\tDEFAULT_CANONICAL,\n+\tPATH_DEFAULT_CANONICAL,\n \t/* Our default is not to modify the item. */\n-\tDEFAULT_UNMODIFIED,\n+\tPATH_DEFAULT_UNMODIFIED,\n };\n \n-static void print_path(const char *path, const char *prefix, enum format_type format, enum default_type def)\n+static void print_path(const char *path, const char *prefix, enum path_format_type format, enum path_default_type def)\n {\n \tchar *cwd = NULL;\n \t/*\n@@ -654,12 +654,12 @@ static void print_path(const char *path, const char *prefix, enum format_type fo\n \t * set it in that case, since doing so causes a relative path to always\n \t * be produced if possible.\n \t */\n-\tif (!prefix && (format != FORMAT_DEFAULT || def != DEFAULT_RELATIVE_IF_SHARED))\n+\tif (!prefix && (format != PATH_FORMAT_DEFAULT || def != PATH_DEFAULT_RELATIVE_IF_SHARED))\n \t\tprefix = cwd = xgetcwd();\n-\tif (format == FORMAT_DEFAULT && def == DEFAULT_UNMODIFIED) {\n+\tif (format == PATH_FORMAT_DEFAULT && def == PATH_DEFAULT_UNMODIFIED) {\n \t\tputs(path);\n-\t} else if (format == FORMAT_RELATIVE ||\n-\t\t  (format == FORMAT_DEFAULT && def == DEFAULT_RELATIVE)) {\n+\t} else if (format == PATH_FORMAT_RELATIVE ||\n+\t\t  (format == PATH_FORMAT_DEFAULT && def == PATH_DEFAULT_RELATIVE)) {\n \t\t/*\n \t\t * In order for relative_path to work as expected, we need to\n \t\t * make sure that both paths are absolute paths.  If we don't,\n@@ -679,7 +679,7 @@ static void print_path(const char *path, const char *prefix, enum format_type fo\n \t\tstrbuf_release(&buf);\n \t\tstrbuf_release(&realbuf);\n \t\tstrbuf_release(&prefixbuf);\n-\t} else if (format == FORMAT_DEFAULT && def == DEFAULT_RELATIVE_IF_SHARED) {\n+\t} else if (format == PATH_FORMAT_DEFAULT && def == PATH_DEFAULT_RELATIVE_IF_SHARED) {\n \t\tstruct strbuf buf = STRBUF_INIT;\n \t\tputs(relative_path(path, prefix, &buf));\n \t\tstrbuf_release(&buf);\n@@ -708,7 +708,7 @@ int cmd_rev_parse(int argc,\n \tconst char *name = NULL;\n \tstruct strbuf buf = STRBUF_INIT;\n \tint seen_end_of_options = 0;\n-\tenum format_type format = FORMAT_DEFAULT;\n+\tenum path_format_type format = PATH_FORMAT_DEFAULT;\n \n \tshow_usage_if_asked(argc, argv, builtin_rev_parse_usage);\n \n@@ -789,7 +789,7 @@ int cmd_rev_parse(int argc,\n \t\t\t\tprint_path(repo_git_path_replace(the_repository, &buf,\n \t\t\t\t\t\t\t\t \"%s\", argv[i + 1]), prefix,\n \t\t\t\t\t\tformat,\n-\t\t\t\t\t\tDEFAULT_RELATIVE_IF_SHARED);\n+\t\t\t\t\t   PATH_DEFAULT_RELATIVE_IF_SHARED);\n \t\t\t\ti++;\n \t\t\t\tcontinue;\n \t\t\t}\n@@ -811,9 +811,9 @@ int cmd_rev_parse(int argc,\n \t\t\t\tif (!arg)\n \t\t\t\t\tdie(_(\"--path-format requires an argument\"));\n \t\t\t\tif (!strcmp(arg, \"absolute\")) {\n-\t\t\t\t\tformat = FORMAT_CANONICAL;\n+\t\t\t\t\tformat = PATH_FORMAT_CANONICAL;\n \t\t\t\t} else if (!strcmp(arg, \"relative\")) {\n-\t\t\t\t\tformat = FORMAT_RELATIVE;\n+\t\t\t\t\tformat = PATH_FORMAT_RELATIVE;\n \t\t\t\t} else {\n \t\t\t\t\tdie(_(\"unknown argument to --path-format: %s\"), arg);\n \t\t\t\t}\n@@ -977,7 +977,7 @@ int cmd_rev_parse(int argc,\n \t\t\tif (!strcmp(arg, \"--show-toplevel\")) {\n \t\t\t\tconst char *work_tree = repo_get_work_tree(the_repository);\n \t\t\t\tif (work_tree)\n-\t\t\t\t\tprint_path(work_tree, prefix, format, DEFAULT_UNMODIFIED);\n+\t\t\t\t\tprint_path(work_tree, prefix, format, PATH_DEFAULT_UNMODIFIED);\n \t\t\t\telse\n \t\t\t\t\tdie(_(\"this operation must be run in a work tree\"));\n \t\t\t\tcontinue;\n@@ -985,7 +985,7 @@ int cmd_rev_parse(int argc,\n \t\t\tif (!strcmp(arg, \"--show-superproject-working-tree\")) {\n \t\t\t\tstruct strbuf superproject = STRBUF_INIT;\n \t\t\t\tif (get_superproject_working_tree(&superproject))\n-\t\t\t\t\tprint_path(superproject.buf, prefix, format, DEFAULT_UNMODIFIED);\n+\t\t\t\t\tprint_path(superproject.buf, prefix, format, PATH_DEFAULT_UNMODIFIED);\n \t\t\t\tstrbuf_release(&superproject);\n \t\t\t\tcontinue;\n \t\t\t}\n@@ -1020,18 +1020,18 @@ int cmd_rev_parse(int argc,\n \t\t\t\tconst char *gitdir = getenv(GIT_DIR_ENVIRONMENT);\n \t\t\t\tchar *cwd;\n \t\t\t\tint len;\n-\t\t\t\tenum format_type wanted = format;\n+\t\t\t\tenum path_format_type wanted = format;\n \t\t\t\tif (arg[2] == 'g') {\t/* --git-dir */\n \t\t\t\t\tif (gitdir) {\n-\t\t\t\t\t\tprint_path(gitdir, prefix, format, DEFAULT_UNMODIFIED);\n+\t\t\t\t\t\tprint_path(gitdir, prefix, format, PATH_DEFAULT_UNMODIFIED);\n \t\t\t\t\t\tcontinue;\n \t\t\t\t\t}\n \t\t\t\t\tif (!prefix) {\n-\t\t\t\t\t\tprint_path(\".git\", prefix, format, DEFAULT_UNMODIFIED);\n+\t\t\t\t\t\tprint_path(\".git\", prefix, format, PATH_DEFAULT_UNMODIFIED);\n \t\t\t\t\t\tcontinue;\n \t\t\t\t\t}\n \t\t\t\t} else {\t\t/* --absolute-git-dir */\n-\t\t\t\t\twanted = FORMAT_CANONICAL;\n+\t\t\t\t\twanted = PATH_FORMAT_CANONICAL;\n \t\t\t\t\tif (!gitdir && !prefix)\n \t\t\t\t\t\tgitdir = \".git\";\n \t\t\t\t\tif (gitdir) {\n@@ -1047,11 +1047,11 @@ int cmd_rev_parse(int argc,\n \t\t\t\tstrbuf_reset(&buf);\n \t\t\t\tstrbuf_addf(&buf, \"%s%s.git\", cwd, len && cwd[len-1] != '/' ? \"/\" : \"\");\n \t\t\t\tfree(cwd);\n-\t\t\t\tprint_path(buf.buf, prefix, wanted, DEFAULT_CANONICAL);\n+\t\t\t\tprint_path(buf.buf, prefix, wanted, PATH_DEFAULT_CANONICAL);\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(arg, \"--git-common-dir\")) {\n-\t\t\t\tprint_path(repo_get_common_dir(the_repository), prefix, format, DEFAULT_RELATIVE_IF_SHARED);\n+\t\t\t\tprint_path(repo_get_common_dir(the_repository), prefix, format, PATH_DEFAULT_RELATIVE_IF_SHARED);\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(arg, \"--is-inside-git-dir\")) {\n@@ -1081,7 +1081,7 @@ int cmd_rev_parse(int argc,\n \t\t\t\tif (the_repository->index->split_index) {\n \t\t\t\t\tconst struct object_id *oid = &the_repository->index->split_index->base_oid;\n \t\t\t\t\tconst char *path = repo_git_path_replace(the_repository, &buf, \"sharedindex.%s\", oid_to_hex(oid));\n-\t\t\t\t\tprint_path(path, prefix, format, DEFAULT_RELATIVE);\n+\t\t\t\t\tprint_path(path, prefix, format, PATH_DEFAULT_RELATIVE);\n \t\t\t\t}\n \t\t\t\tcontinue;\n \t\t\t}\n-- \n2.50.1 (Apple Git-155)\n\n"},{"id":"537413","messageId":"20260228224252.72788-3-lucasseikioshiro@gmail.com","threadId":"65101","inReplyTo":"20260228224252.72788-1-lucasseikioshiro@gmail.com","subject":"[PATCH 2/4] path: add new function strbuf_add_path","fromName":"Lucas Seiki Oshiro","fromEmail":"lucasseikioshiro@gmail.com","sentAt":"2026-02-28T22:05:56Z","receivedAt":"2026-02-28T22:44:42Z","isPatch":true,"sender":{"key":"lucasseikioshiro@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12701580?v=4"},"body":"The function `print_path`, introduced in fac60b8925 (rev-parse: add\noption for absolute or relative path formatting, 2020-12-13), is used\nby git-rev-parse for printing paths, deciding between using relative\nor absolute paths. This decision, however, could benefit other\ncommands, notably git-repo-info.\n\nEncapsulate this logic into a new function called `strbuf_add_path`,\nlocated in `path.c`. Move to path.c the two enums used for deciding\nthe path format, i.e. `path_default_type` and `path_format_type`.\n\nSigned-off-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>\n---\n builtin/rev-parse.c | 72 ++++-----------------------------------------\n path.c              | 51 ++++++++++++++++++++++++++++++++\n path.h              | 23 +++++++++++++++\n 3 files changed, 80 insertions(+), 66 deletions(-)\n\ndiff --git a/builtin/rev-parse.c b/builtin/rev-parse.c\nindex a2162ff39e..024a9e7d5f 100644\n--- a/builtin/rev-parse.c\n+++ b/builtin/rev-parse.c\n@@ -623,73 +623,13 @@ static void handle_ref_opt(const char *pattern, const char *prefix)\n \tclear_ref_exclusions(&ref_excludes);\n }\n \n-enum path_format_type {\n-\t/* We would like a relative path. */\n-\tPATH_FORMAT_RELATIVE,\n-\t/* We would like a canonical absolute path. */\n-\tPATH_FORMAT_CANONICAL,\n-\t/* We would like the default behavior. */\n-\tPATH_FORMAT_DEFAULT,\n-};\n-\n-enum path_default_type {\n-\t/* Our default is a relative path. */\n-\tPATH_DEFAULT_RELATIVE,\n-\t/* Our default is a relative path if there's a shared root. */\n-\tPATH_DEFAULT_RELATIVE_IF_SHARED,\n-\t/* Our default is a canonical absolute path. */\n-\tPATH_DEFAULT_CANONICAL,\n-\t/* Our default is not to modify the item. */\n-\tPATH_DEFAULT_UNMODIFIED,\n-};\n-\n-static void print_path(const char *path, const char *prefix, enum path_format_type format, enum path_default_type def)\n+static void print_path(const char *path, const char *prefix,\n+\t\t       enum path_format_type format, enum path_default_type def)\n {\n-\tchar *cwd = NULL;\n-\t/*\n-\t * We don't ever produce a relative path if prefix is NULL, so set the\n-\t * prefix to the current directory so that we can produce a relative\n-\t * path whenever possible.  If we're using RELATIVE_IF_SHARED mode, then\n-\t * we want an absolute path unless the two share a common prefix, so don't\n-\t * set it in that case, since doing so causes a relative path to always\n-\t * be produced if possible.\n-\t */\n-\tif (!prefix && (format != PATH_FORMAT_DEFAULT || def != PATH_DEFAULT_RELATIVE_IF_SHARED))\n-\t\tprefix = cwd = xgetcwd();\n-\tif (format == PATH_FORMAT_DEFAULT && def == PATH_DEFAULT_UNMODIFIED) {\n-\t\tputs(path);\n-\t} else if (format == PATH_FORMAT_RELATIVE ||\n-\t\t  (format == PATH_FORMAT_DEFAULT && def == PATH_DEFAULT_RELATIVE)) {\n-\t\t/*\n-\t\t * In order for relative_path to work as expected, we need to\n-\t\t * make sure that both paths are absolute paths.  If we don't,\n-\t\t * we can end up with an unexpected absolute path that the user\n-\t\t * didn't want.\n-\t\t */\n-\t\tstruct strbuf buf = STRBUF_INIT, realbuf = STRBUF_INIT, prefixbuf = STRBUF_INIT;\n-\t\tif (!is_absolute_path(path)) {\n-\t\t\tstrbuf_realpath_forgiving(&realbuf, path,  1);\n-\t\t\tpath = realbuf.buf;\n-\t\t}\n-\t\tif (!is_absolute_path(prefix)) {\n-\t\t\tstrbuf_realpath_forgiving(&prefixbuf, prefix, 1);\n-\t\t\tprefix = prefixbuf.buf;\n-\t\t}\n-\t\tputs(relative_path(path, prefix, &buf));\n-\t\tstrbuf_release(&buf);\n-\t\tstrbuf_release(&realbuf);\n-\t\tstrbuf_release(&prefixbuf);\n-\t} else if (format == PATH_FORMAT_DEFAULT && def == PATH_DEFAULT_RELATIVE_IF_SHARED) {\n-\t\tstruct strbuf buf = STRBUF_INIT;\n-\t\tputs(relative_path(path, prefix, &buf));\n-\t\tstrbuf_release(&buf);\n-\t} else {\n-\t\tstruct strbuf buf = STRBUF_INIT;\n-\t\tstrbuf_realpath_forgiving(&buf, path, 1);\n-\t\tputs(buf.buf);\n-\t\tstrbuf_release(&buf);\n-\t}\n-\tfree(cwd);\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tstrbuf_add_path(&sb, path, prefix, format, def);\n+\tputs(sb.buf);\n+\tstrbuf_release(&sb);\n }\n \n int cmd_rev_parse(int argc,\ndiff --git a/path.c b/path.c\nindex d726537622..ab9669abff 100644\n--- a/path.c\n+++ b/path.c\n@@ -1574,6 +1574,57 @@ char *xdg_cache_home(const char *filename)\n \treturn NULL;\n }\n \n+void strbuf_add_path(struct strbuf *sb, const char *path, const char *prefix,\n+\t\t     enum path_format_type format, enum path_default_type def)\n+{\n+\tchar *cwd = NULL;\n+\t/*\n+\t * We don't ever produce a relative path if prefix is NULL, so set the\n+\t * prefix to the current directory so that we can produce a relative\n+\t * path whenever possible.  If we're using RELATIVE_IF_SHARED mode, then\n+\t * we want an absolute path unless the two share a common prefix, so don't\n+\t * set it in that case, since doing so causes a relative path to always\n+\t * be produced if possible.\n+\t */\n+\tif (!prefix && (format != PATH_FORMAT_DEFAULT || def != PATH_DEFAULT_RELATIVE_IF_SHARED))\n+\t\tprefix = cwd = xgetcwd();\n+\tif (format == PATH_FORMAT_DEFAULT && def == PATH_DEFAULT_UNMODIFIED) {\n+\t\tstrbuf_addstr(sb, path);\n+\t} else if (format == PATH_FORMAT_RELATIVE ||\n+\t\t   (format == PATH_FORMAT_DEFAULT && def == PATH_DEFAULT_RELATIVE)) {\n+\t\t/*\n+\t\t * In order for relative_path to work as expected, we need to\n+\t\t * make sure that both paths are absolute paths.  If we don't,\n+\t\t * we can end up with an unexpected absolute path that the user\n+\t\t * didn't want.\n+\t\t */\n+\t\tstruct strbuf buf = STRBUF_INIT, realbuf = STRBUF_INIT, prefixbuf = STRBUF_INIT;\n+\t\tif (!is_absolute_path(path)) {\n+\t\t\tstrbuf_realpath_forgiving(&realbuf, path,  1);\n+\t\t\tpath = realbuf.buf;\n+\t\t}\n+\t\tif (!is_absolute_path(prefix)) {\n+\t\t\tstrbuf_realpath_forgiving(&prefixbuf, prefix, 1);\n+\t\t\tprefix = prefixbuf.buf;\n+\t\t}\n+\t\tstrbuf_addstr(sb, relative_path(path, prefix, &buf));\n+\t\tstrbuf_release(&buf);\n+\t\tstrbuf_release(&realbuf);\n+\t\tstrbuf_release(&prefixbuf);\n+\t} else if (format == PATH_FORMAT_DEFAULT && def == PATH_DEFAULT_RELATIVE_IF_SHARED) {\n+\t\tstruct strbuf buf = STRBUF_INIT;\n+\t\tstrbuf_addstr(sb, relative_path(path, prefix, &buf));\n+\t\tstrbuf_release(&buf);\n+\t} else {\n+\t\tstruct strbuf buf = STRBUF_INIT;\n+\t\tstrbuf_realpath_forgiving(&buf, path, 1);\n+\t\tstrbuf_addbuf(sb, &buf);\n+\t\tstrbuf_release(&buf);\n+\t}\n+\tfree(cwd);\n+}\n+\n+\n REPO_GIT_PATH_FUNC(squash_msg, \"SQUASH_MSG\")\n REPO_GIT_PATH_FUNC(merge_msg, \"MERGE_MSG\")\n REPO_GIT_PATH_FUNC(merge_rr, \"MERGE_RR\")\ndiff --git a/path.h b/path.h\nindex 0ec95a0b07..c152d20c71 100644\n--- a/path.h\n+++ b/path.h\n@@ -258,6 +258,29 @@ enum scld_error safe_create_leading_directories_no_share(char *path);\n int safe_create_file_with_leading_directories(struct repository *repo,\n \t\t\t\t\t      const char *path);\n \n+enum path_format_type {\n+\t/* We would like a relative path. */\n+\tPATH_FORMAT_RELATIVE,\n+\t/* We would like a canonical absolute path. */\n+\tPATH_FORMAT_CANONICAL,\n+\t/* We would like the default behavior. */\n+\tPATH_FORMAT_DEFAULT,\n+};\n+\n+enum path_default_type {\n+\t/* Our default is a relative path. */\n+\tPATH_DEFAULT_RELATIVE,\n+\t/* Our default is a relative path if there's a shared root. */\n+\tPATH_DEFAULT_RELATIVE_IF_SHARED,\n+\t/* Our default is a canonical absolute path. */\n+\tPATH_DEFAULT_CANONICAL,\n+\t/* Our default is not to modify the item. */\n+\tPATH_DEFAULT_UNMODIFIED,\n+};\n+\n+void strbuf_add_path(struct strbuf *buf, const char *path, const char *prefix,\n+\t\t     enum path_format_type format, enum path_default_type def);\n+\n # ifdef USE_THE_REPOSITORY_VARIABLE\n #  include \"strbuf.h\"\n #  include \"repository.h\"\n-- \n2.50.1 (Apple Git-155)\n\n"},{"id":"537414","messageId":"20260228224252.72788-4-lucasseikioshiro@gmail.com","threadId":"65101","inReplyTo":"20260228224252.72788-1-lucasseikioshiro@gmail.com","subject":"[PATCH 3/4] repo: add the --format-path flag","fromName":"Lucas Seiki Oshiro","fromEmail":"lucasseikioshiro@gmail.com","sentAt":"2026-02-28T22:05:57Z","receivedAt":"2026-02-28T22:44:46Z","isPatch":true,"sender":{"key":"lucasseikioshiro@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12701580?v=4"},"body":"Some paths handled by Git are better presented in their absolute format\nand others are better presented relative to the current working\ndirectory.\n\nAdd a `--format-path` flag to git-repo-info, allowing the user to force\nthe outputted paths to be either in the absolute or in the relative\nformat. This flag is similar to its homonymous in git-rev-parse, introduced in\nfac60b8925 (rev-parse: add option for absolute or relative path\nformatting, 2020-12-13).\n\nSigned-off-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>\n---\n Documentation/git-repo.adoc |  8 ++++++--\n builtin/repo.c              | 24 +++++++++++++++++++-----\n t/t1900-repo-info.sh        |  7 +++++++\n 3 files changed, 32 insertions(+), 7 deletions(-)\n\ndiff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc\nindex 5e2968b707..478737b8ff 100644\n--- a/Documentation/git-repo.adoc\n+++ b/Documentation/git-repo.adoc\n@@ -8,7 +8,7 @@ git-repo - Retrieve information about the repository\n SYNOPSIS\n --------\n [synopsis]\n-git repo info [--format=(lines|nul) | -z] [--all | <key>...]\n+git repo info [--format=(lines|nul) | -z] [--path-format=(absolute|relative)] [--all | <key>...]\n git repo info --keys [--format=(lines|nul) | -z]\n git repo structure [--format=(table|lines|nul) | -z]\n \n@@ -20,7 +20,7 @@ THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.\n \n COMMANDS\n --------\n-`info [--format=(lines|nul) | -z] [--all | <key>...]`::\n+`info [--format=(lines|nul) | -z] [--path-format=(absolute|relative)] [--all | <key>...]`::\n \tRetrieve metadata-related information about the current repository. Only\n \tthe requested data will be returned based on their keys (see \"INFO KEYS\"\n \tsection below).\n@@ -45,6 +45,10 @@ supported:\n \t`lines`. Unlike in the `lines` format, the values are never quoted.\n +\n `-z` is an alias for `--format=nul`.\n++\n+By default, the path values may be in the absolute or relative path, depending\n+on the requested keys. However, the format can be forced by using the flag\n+`--path-format`.\n \n `info --keys [--format=(lines|nul) | -z]`::\n \tList all the available keys, one per line. The output format can be chosen\ndiff --git a/builtin/repo.c b/builtin/repo.c\nindex f943be7451..cff4c6db9b 100644\n--- a/builtin/repo.c\n+++ b/builtin/repo.c\n@@ -7,17 +7,16 @@\n #include \"parse-options.h\"\n #include \"path-walk.h\"\n #include \"progress.h\"\n+#include \"path.h\"\n #include \"quote.h\"\n #include \"ref-filter.h\"\n #include \"refs.h\"\n #include \"revision.h\"\n-#include \"strbuf.h\"\n-#include \"string-list.h\"\n #include \"shallow.h\"\n #include \"utf8.h\"\n \n static const char *const repo_usage[] = {\n-\t\"git repo info [--format=(lines|nul) | -z] [--all | <key>...]\",\n+\t\"git repo info [--format=(lines|nul) | -z] [--path-format=(absolute|relative)] [--all | <key>...]\",\n \t\"git repo info --keys [--format=(lines|nul) | -z]\",\n \t\"git repo structure [--format=(table|lines|nul) | -z]\",\n \tNULL\n@@ -109,7 +108,8 @@ static void print_field(enum output_format format, const char *key,\n \n static int print_fields(int argc, const char **argv,\n \t\t\tstruct repository *repo,\n-\t\t\tenum output_format format)\n+\t\t\tenum output_format format,\n+\t\t\tenum path_format_type path_format UNUSED)\n {\n \tint ret = 0;\n \tstruct strbuf valbuf = STRBUF_INIT;\n@@ -197,6 +197,9 @@ static int cmd_repo_info(int argc, const char **argv, const char *prefix,\n \tenum output_format format = FORMAT_NEWLINE_TERMINATED;\n \tint all_keys = 0;\n \tint show_keys = 0;\n+\tconst char *path_format_str = NULL;\n+\tenum path_format_type path_format = PATH_FORMAT_DEFAULT;\n+\n \tstruct option options[] = {\n \t\tOPT_CALLBACK_F(0, \"format\", &format, N_(\"format\"),\n \t\t\t       N_(\"output format\"),\n@@ -207,6 +210,8 @@ static int cmd_repo_info(int argc, const char **argv, const char *prefix,\n \t\t\t       parse_format_cb),\n \t\tOPT_BOOL(0, \"all\", &all_keys, N_(\"print all keys/values\")),\n \t\tOPT_BOOL(0, \"keys\", &show_keys, N_(\"show keys\")),\n+\t\tOPT_STRING(0, \"path-format\", &path_format_str,\n+\t\t\t   N_(\"path-format\"), N_(\"path format\")),\n \t\tOPT_END()\n \t};\n \n@@ -221,13 +226,22 @@ static int cmd_repo_info(int argc, const char **argv, const char *prefix,\n \tif (format != FORMAT_NEWLINE_TERMINATED && format != FORMAT_NUL_TERMINATED)\n \t\tdie(_(\"unsupported output format\"));\n \n+\tif (path_format_str) {\n+\t\tif (!strcmp(path_format_str, \"absolute\"))\n+\t\t\tpath_format = PATH_FORMAT_CANONICAL;\n+\t\telse if (!strcmp(path_format_str, \"relative\"))\n+\t\t\tpath_format = PATH_FORMAT_RELATIVE;\n+\t\telse\n+\t\t\tdie(_(\"invalid path format '%s'\"), path_format_str);\n+\t}\n+\n \tif (all_keys && argc)\n \t\tdie(_(\"--all and <key> cannot be used together\"));\n \n \tif (all_keys)\n \t\treturn print_all_fields(repo, format);\n \telse\n-\t\treturn print_fields(argc, argv, repo, format);\n+\t\treturn print_fields(argc, argv, repo, format, path_format);\n }\n \n struct ref_stats {\ndiff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh\nindex a9eb07abe8..f5c76067cb 100755\n--- a/t/t1900-repo-info.sh\n+++ b/t/t1900-repo-info.sh\n@@ -149,4 +149,11 @@ test_expect_success 'git repo info --keys uses lines as its default output forma\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'git-repo-info aborts when requesting an invalid path format' '\n+\ttest_when_finished \"rm -f err expected\" &&\n+\techo \"fatal: invalid path format '\\'foo\\''\" >expected &&\n+\ttest_must_fail git repo info --path-format=foo 2>err &&\n+\ttest_cmp expected err\n+'\n+\n test_done\n-- \n2.50.1 (Apple Git-155)\n\n"},{"id":"537415","messageId":"20260228224252.72788-5-lucasseikioshiro@gmail.com","threadId":"65101","inReplyTo":"20260228224252.72788-1-lucasseikioshiro@gmail.com","subject":"[PATCH 4/4] repo: add the field path.toplevel","fromName":"Lucas Seiki Oshiro","fromEmail":"lucasseikioshiro@gmail.com","sentAt":"2026-02-28T22:05:58Z","receivedAt":"2026-02-28T22:44:49Z","isPatch":true,"sender":{"key":"lucasseikioshiro@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12701580?v=4"},"body":"The flag `--show-toplevel` from git-rev-parse is used for retrieving\nthe top level directory path of the repository. This way, it is used for\nquerying repository metadata, fitting in the purpose of git-repo-info.\n\nAdd a new field `path.toplevel` to the git-repo-info subcommand\ncontaining that information.\n\nSigned-off-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>\n---\n builtin/repo.c       | 47 +++++++++++++++++++++++++--------\n t/t1900-repo-info.sh | 62 ++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 98 insertions(+), 11 deletions(-)\n\ndiff --git a/builtin/repo.c b/builtin/repo.c\nindex cff4c6db9b..61cd539e05 100644\n--- a/builtin/repo.c\n+++ b/builtin/repo.c\n@@ -22,7 +22,8 @@ static const char *const repo_usage[] = {\n \tNULL\n };\n \n-typedef int get_value_fn(struct repository *repo, struct strbuf *buf);\n+typedef int get_value_fn(struct repository *repo, struct strbuf *buf,\n+\t\t\t const char *prefix, enum path_format_type format);\n \n enum output_format {\n \tFORMAT_TABLE,\n@@ -35,26 +36,46 @@ struct repo_info_field {\n \tget_value_fn *get_value;\n };\n \n-static int get_layout_bare(struct repository *repo UNUSED, struct strbuf *buf)\n+static int get_layout_bare(struct repository *repo UNUSED, struct strbuf *buf,\n+\t\t\t   const char *prefix UNUSED,\n+\t\t\t   enum path_format_type format UNUSED)\n {\n \tstrbuf_addstr(buf, is_bare_repository() ? \"true\" : \"false\");\n \treturn 0;\n }\n \n-static int get_layout_shallow(struct repository *repo, struct strbuf *buf)\n+static int get_layout_shallow(struct repository *repo, struct strbuf *buf,\n+\t\t\t      const char *prefix UNUSED,\n+\t\t\t      enum path_format_type format UNUSED)\n {\n \tstrbuf_addstr(buf,\n \t\t      is_repository_shallow(repo) ? \"true\" : \"false\");\n \treturn 0;\n }\n \n-static int get_object_format(struct repository *repo, struct strbuf *buf)\n+static int get_object_format(struct repository *repo, struct strbuf *buf,\n+\t\t\t     const char *prefix UNUSED,\n+\t\t\t     enum path_format_type format UNUSED)\n {\n \tstrbuf_addstr(buf, repo->hash_algo->name);\n \treturn 0;\n }\n \n-static int get_references_format(struct repository *repo, struct strbuf *buf)\n+static int get_path_toplevel(struct repository *repo, struct strbuf *buf,\n+\t\t\t     const char *prefix, enum path_format_type format)\n+{\n+\tconst char *work_tree = repo_get_work_tree(repo);\n+\tif (work_tree)\n+\t\tstrbuf_add_path(buf, work_tree, prefix, format,\n+\t\t\t\tPATH_DEFAULT_UNMODIFIED);\n+\telse\n+\t\treturn error(_(\"this operation must be run in a work tree\"));\n+\treturn 0;\n+}\n+\n+static int get_references_format(struct repository *repo, struct strbuf *buf,\n+\t\t\t\t const char *prefix UNUSED,\n+\t\t\t\t enum path_format_type format UNUSED)\n {\n \tstrbuf_addstr(buf,\n \t\t      ref_storage_format_to_name(repo->ref_storage_format));\n@@ -66,6 +87,7 @@ static const struct repo_info_field repo_info_field[] = {\n \t{ \"layout.bare\", get_layout_bare },\n \t{ \"layout.shallow\", get_layout_shallow },\n \t{ \"object.format\", get_object_format },\n+\t{ \"path.toplevel\", get_path_toplevel },\n \t{ \"references.format\", get_references_format },\n };\n \n@@ -108,8 +130,9 @@ static void print_field(enum output_format format, const char *key,\n \n static int print_fields(int argc, const char **argv,\n \t\t\tstruct repository *repo,\n+\t\t\tconst char *prefix,\n \t\t\tenum output_format format,\n-\t\t\tenum path_format_type path_format UNUSED)\n+\t\t\tenum path_format_type path_format)\n {\n \tint ret = 0;\n \tstruct strbuf valbuf = STRBUF_INIT;\n@@ -124,7 +147,7 @@ static int print_fields(int argc, const char **argv,\n \t\t}\n \n \t\tstrbuf_reset(&valbuf);\n-\t\tfield->get_value(repo, &valbuf);\n+\t\tfield->get_value(repo, &valbuf, prefix, path_format);\n \t\tprint_field(format, key, valbuf.buf);\n \t}\n \n@@ -133,7 +156,9 @@ static int print_fields(int argc, const char **argv,\n }\n \n static int print_all_fields(struct repository *repo,\n-\t\t\t    enum output_format format)\n+\t\t\t    const char *prefix,\n+\t\t\t    enum output_format format,\n+\t\t\t    enum path_format_type path_format)\n {\n \tstruct strbuf valbuf = STRBUF_INIT;\n \n@@ -141,7 +166,7 @@ static int print_all_fields(struct repository *repo,\n \t\tconst struct repo_info_field *field = &repo_info_field[i];\n \n \t\tstrbuf_reset(&valbuf);\n-\t\tfield->get_value(repo, &valbuf);\n+\t\tfield->get_value(repo, &valbuf, prefix, path_format);\n \t\tprint_field(format, field->key, valbuf.buf);\n \t}\n \n@@ -239,9 +264,9 @@ static int cmd_repo_info(int argc, const char **argv, const char *prefix,\n \t\tdie(_(\"--all and <key> cannot be used together\"));\n \n \tif (all_keys)\n-\t\treturn print_all_fields(repo, format);\n+\t\treturn print_all_fields(repo, prefix, format, path_format);\n \telse\n-\t\treturn print_fields(argc, argv, repo, format, path_format);\n+\t\treturn print_fields(argc, argv, repo, prefix, format, path_format);\n }\n \n struct ref_stats {\ndiff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh\nindex f5c76067cb..4985a9cc70 100755\n--- a/t/t1900-repo-info.sh\n+++ b/t/t1900-repo-info.sh\n@@ -38,6 +38,53 @@ test_repo_info () {\n \t'\n }\n \n+test_repo_info_path () {\n+\tlabel=$1\n+\trepo_name=$2\n+\tkey=$3\n+\trelative_path=$4\n+\tdefault=$5\n+\n+\tabsolute_path=$(cd \"$relative_path\"; pwd)/\"$repo_name\"\n+\n+\tcase $default in\n+\tabsolute)\n+\t\texpected_value=\"$absolute_path\"\n+\t\t;;\n+\trelative)\n+\t\texpected_value=\"$relative_path\"\n+\t\t;;\n+\tesac\n+\n+\ttest_expect_success \"setup: $label\" '\n+\t\tgit init \"$repo_name\"\n+\t'\n+\n+\ttest_expect_success \"nul: $label\" '\n+\t\tprintf \"%s\\n%s\\0\" \"$key\" \"$expected_value\" >expected &&\n+\t\tgit -C \"$repo_name\" repo info --format=nul \"$key\" >actual &&\n+\t\ttest_cmp expected actual\n+\t'\n+\n+\ttest_expect_success \"default: $label\" '\n+\t\techo \"$key=$expected_value\" > expected &&\n+\t\tgit -C \"$repo_name\" repo info \"$key\" >actual &&\n+\t\ttest_cmp expected actual\n+\t'\n+\n+\ttest_expect_success \"absolute: $label\" '\n+\t\techo \"$key=$absolute_path\" > expected &&\n+\t\tgit -C \"$repo_name\" repo info --path-format=absolute \"$key\" >actual &&\n+\t\ttest_cmp expected actual\n+\t'\n+\n+\ttest_expect_success \"relative: $label\" '\n+\t\techo \"$key=$relative_path\" > expected &&\n+\t\tgit -C \"$repo_name\" repo info --path-format=relative \"$key\" >actual &&\n+\t\ttest_cmp expected actual\n+\t'\n+}\n+\n test_repo_info 'ref format files is retrieved correctly' \\\n \t'git init --ref-format=files' 'format-files' 'references.format' 'files'\n \n@@ -69,6 +116,21 @@ test_repo_info 'object.format = sha1 is retrieved correctly' \\\n test_repo_info 'object.format = sha256 is retrieved correctly' \\\n \t'git init --object-format=sha256' 'sha256' 'object.format' 'sha256'\n \n+test_repo_info_path 'toplevel is retrieved correctly' \\\n+\t'toplevel' 'path.toplevel' './' 'absolute'\n+\n+test_expect_success 'git-repo-info fails if an invalid key is requested' '\n+\techo \"error: key ${SQ}foo${SQ} not found\" >expected_err &&\n+\ttest_must_fail git repo info foo 2>actual_err &&\n+\ttest_cmp expected_err actual_err\n+'\n+\n+test_expect_success 'git-repo-info outputs data even if there is an invalid field' '\n+\techo \"references.format=$(test_detect_ref_format)\" >expected &&\n+\ttest_must_fail git repo info foo references.format bar >actual &&\n+\ttest_cmp expected actual\n+'\n+\n test_expect_success 'values returned in order requested' '\n \tcat >expect <<-\\EOF &&\n \tlayout.bare=false\n-- \n2.50.1 (Apple Git-155)\n\n"},{"id":"537423","messageId":"CA+rGoLdTc2caDUsQedpegL+T4MqwwiA62uuDSFSawAT5vcPvWQ@mail.gmail.com","threadId":"65101","inReplyTo":"20260228224252.72788-1-lucasseikioshiro@gmail.com","subject":"Re: [PATCH 0/4] repo: add support for path-related fields","fromName":"JAYATHEERTH K","fromEmail":"jayatheerthkulkarni2005@gmail.com","sentAt":"2026-03-01T02:58:21Z","receivedAt":"2026-03-01T02:58:33Z","isPatch":true,"sender":{"key":"jayatheerthkulkarni2005@gmail.com","avatar":"https://avatars.githubusercontent.com/u/148841023?v=4"},"body":"On Sun, Mar 1, 2026 at 4:14 AM Lucas Seiki Oshiro\n<lucasseikioshiro@gmail.com> wrote:\n>\n> Hi!\n>\n\nHey Lucas,\n\n> This patch series adds support for path-related fields in repo-info, based on\n> what we already have in git-rev-parse:\n>\n> 1. The two first patches moves the path formatting used by git-rev-parse to\n>    path.c. This will allow us to reuse this code in git-repo-info\n> 2. The second patch add a new flag --path-format to git-repo-info, similar to\n>    the flag of git-rev-parse with the same name\n> 3. Add the new field `path.toplevel` as a proof of concept.\n>\n> This arises from the fact that I didn't know what should be the default behavior\n> of git-repo-info when dealing with paths. Some ideas were:\n>\n> 1. Add --path-format, just like we have in git-rev-parse\n> 2. Use what rev-parse uses by default\n> 3. Add keys for both relative and absolute formats\n>\n> In this case, I'm using 1, but I'm not sure if it's the best option. One\n> downside that I see here is that git-repo-info won't be able to return\n> a relative and an absolute path for different keys in the same call.\n>\n\nOption 1 feels like the cleanest approach.\nEven though it means git-repo-info can't return both a relative and\nabsolute path in the exact same call, it keeps the API highly predictable\nfor scripting without bloating the key namespace (which Option 3 would do).\n\nThe behaviour is different when compared to the command itself where we\nhave to use --all, but I think in this area this is the right approach.\n\n> Since there are many people interested in contributing to git-repo-info, I'll\n> leave the remaining path-related fields to them :-)\n>\n\nThank you ;)\n\n> I'm CC'ing here:\n>\n> - brian, who was the original author of the `print_path` [1]\n> - Ayush, Tian, Jayatheerth, Soutrik and Pushkar, since they expressed interested\n>   in contributing to git-repo-info in GSoC. (I hope that I didn't forget anyone)\n>\n> This patch is based on top of master 2cc7191751 (The 8th batch, 2026-02-27) with\n> lo/repo-leftover-bits merged.\n\n\nThis provides a fantastic foundation.\nI have updated my GSoC proposal based on these patches to build out\nthe remaining path.* keys, alongside category-based querying and\nglobal state removal.\n\nI will be sending that in a completely new thread shortly.\n\nRegards\n- Jayatheerth\n"},{"id":"537425","messageId":"71e42a01-6077-48fc-876e-555431d1288f@gmail.com","threadId":"65101","inReplyTo":"20260228224252.72788-5-lucasseikioshiro@gmail.com","subject":"Re: [PATCH 4/4] repo: add the field path.toplevel","fromName":"Tian Yuchen","fromEmail":"a3205153416@gmail.com","sentAt":"2026-03-01T04:24:01Z","receivedAt":"2026-03-01T04:24:06Z","isPatch":true,"sender":{"key":"cat@malon.dev","avatar":"https://avatars.githubusercontent.com/u/232002048?v=4"},"body":"Hi Lucas,\n\n > I'm CC'ing here:\n >\n > - brian, who was the original author of the `print_path` [1]\n > - Ayush, Tian, Jayatheerth, Soutrik and Pushkar, since they expressed \n >   interested in contributing to git-repo-info in GSoC. (I hope that I\n >   didn't forget anyone)\n\nThank you for your thoughtful consideration!\n\n > 1. Add --path-format, just like we have in git-rev-parse\n > 2. Use what rev-parse uses by default\n > 3. Add keys for both relative and absolute formats\n\nIt makes me wonder if we can use Format Modifiers as in ref-filter.c...\n\n\thttps://git-scm.com/docs/git-for-each-ref\n\n...which allow us to control the output precisely. For example:\n\n\t%(path:relative)\n\t%(path:absolute)\n\t%(path:short)\n\t%(path:strip=2)...\n\nJust a thought.\n\n > There are two enums used in rev-parse for deciding how paths will\n > be printed by the function `print_path`: `format_type` and\n > `default_type`. Even though there aren't any ambiguities yet, their\n > names aren't clear that those \"types\" are path types.\n\nThis one makes sense to me. Also reduce naming conflicts.\n\n > +void strbuf_add_path(struct strbuf *sb, const char *path, const char \n > *prefix, enum path_format_type format, enum path_default_type def)\n\nIsn't it a bit inappropriate for a generic character concatenation \nfunction to know about format and def? I don't think this should be the \nresponsibility of a low-level function, at least not str_buf_add_path().\n\nAll functions starting with strbuf_add.. listed by git grep strbuf_add \nare mostly pure string concatenation operations. I believe this should \nbe the case here as well.\n\n > +\tif (!prefix && (format != PATH_FORMAT_DEFAULT || def != \nPATH_DEFAULT_RELATIVE_IF_SHARED))\n > +\t\tprefix = cwd = xgetcwd();\n\nI think the logic here shouldn't be tied to \nPATH_DEFAULT_RELATIVE_IF_SHARED, I believe the attribution here is the \nsame as above.\n\n > +\t\tprefix = cwd = xgetcwd()\n\nWill there be a performance regression? Since xgetcwd() here is a system \ncall, right? If prefix == NULL and the get repo info command is used to \nlocate the top-level path among a large number of submodules, and this \ncommand will be executed multiple times.\n\nIn my opinion, upper-level commands should call xgetcwd() only once \nbefore entering the loop, then pass the obtained prefix as an argument \nto the underlying implementation.\n\n> -typedef int get_value_fn(struct repository *repo, struct strbuf *buf);\n> +typedef int get_value_fn(struct repository *repo, struct strbuf *buf,\n> +\t\t\t const char *prefix, enum path_format_type format);\n>  \n>  enum output_format {\n>  \tFORMAT_TABLE,\n> @@ -35,26 +36,46 @@ struct repo_info_field {\n>  \tget_value_fn *get_value;\n>  };\n>  \n> -static int get_layout_bare(struct repository *repo UNUSED, struct strbuf *buf)\n> +static int get_layout_bare(struct repository *repo UNUSED, struct strbuf *buf,\n> +\t\t\t   const char *prefix UNUSED,\n> +\t\t\t   enum path_format_type format UNUSED)\n>  {\n>  \tstrbuf_addstr(buf, is_bare_repository() ? \"true\" : \"false\");\n>  \treturn 0;\n>  }\n>  \n> -static int get_layout_shallow(struct repository *repo, struct strbuf *buf)\n> +static int get_layout_shallow(struct repository *repo, struct strbuf *buf,\n> +\t\t\t      const char *prefix UNUSED,\n> +\t\t\t      enum path_format_type format UNUSED)\n>  {\n>  \tstrbuf_addstr(buf,\n>  \t\t      is_repository_shallow(repo) ? \"true\" : \"false\");\n>  \treturn 0;\n>  }\n>  \n> -static int get_object_format(struct repository *repo, struct strbuf *buf)\n> +static int get_object_format(struct repository *repo, struct strbuf *buf,\n> +\t\t\t     const char *prefix UNUSED,\n> +\t\t\t     enum path_format_type format UNUSED)\n>  {\n>  \tstrbuf_addstr(buf, repo->hash_algo->name);\n>  \treturn 0;\n>  }\n>  \n> -static int get_references_format(struct repository *repo, struct strbuf *buf)\n> +static int get_path_toplevel(struct repository *repo, struct strbuf *buf,\n> +\t\t\t     const char *prefix, enum path_format_type format)\n> +{\n> +\tconst char *work_tree = repo_get_work_tree(repo);\n> +\tif (work_tree)\n> +\t\tstrbuf_add_path(buf, work_tree, prefix, format,\n> +\t\t\t\tPATH_DEFAULT_UNMODIFIED);\n> +\telse\n> +\t\treturn error(_(\"this operation must be run in a work tree\"));\n> +\treturn 0;\n> +}\n> +\n> +static int get_references_format(struct repository *repo, struct strbuf *buf,\n> +\t\t\t\t const char *prefix UNUSED,\n> +\n\nI don't think we should add the two new parameters to all get_ functions \nhere. As changed in your patch, functions like get_object_format don't \nreally, need to know about prefix or format, so the corresponding \nparameters are marked as UNUSED. Imagine if more and more data needs to \nbe retrieved by these get_ series functions in the future — is it really \nadvisable to add unnecessary parameters to all remaining functions just \nfor the sake of a few?\n\nI'm not entirely sure about the above content either; I'm just throwing \nout ideas to spark discussion. (´～`)\n\nThanks again for starting this discussion!\n\nRegards,\n\nYuchen\n\n\n"},{"id":"537426","messageId":"CAFNBzOdCx=R3r9+m5eDyAykMAbmbcfpX3kPeEPjqXPYT-_89+g@mail.gmail.com","threadId":"65101","inReplyTo":"CA+rGoLdTc2caDUsQedpegL+T4MqwwiA62uuDSFSawAT5vcPvWQ@mail.gmail.com","subject":"Re: [PATCH 0/4] repo: add support for path-related fields","fromName":"Ayush Jha","fromEmail":"kumarayushjha123@gmail.com","sentAt":"2026-03-01T05:45:01Z","receivedAt":"2026-03-01T05:45:14Z","isPatch":true,"sender":{"key":"kumarayushjha123@gmail.com","avatar":null},"body":"Hi Lucas,\n\nThanks for sharing this series — moving the path formatting logic into\npath.c makes a lot of sense and avoids duplication with rev-parse.\n\nRegarding the limitation you mentioned about not being able to mix\nrelative and absolute paths within the same invocation, I was\nwondering whether it might be worth considering making the path format\npart of the key itself, rather than controlled by a global flag.\n\nFor example, something along the lines of:\npath.toplevel\npath.absolute.toplevel\npath.relative.toplevel\n\nThis could allow users to request different formats in a single call\nwithout introducing global state into the command output.\nThat said, I’m not sure whether this would complicate the key\nnamespace too much, or whether maintaining parity with rev-parse\nsemantics is preferable for consistency.\n\nI’d be interested to hear your thoughts on this trade-off.\n\nBest,\nAyush\n\nOn Sun, Mar 1, 2026 at 8:28 AM JAYATHEERTH K\n<jayatheerthkulkarni2005@gmail.com> wrote:\n>\n> On Sun, Mar 1, 2026 at 4:14 AM Lucas Seiki Oshiro\n> <lucasseikioshiro@gmail.com> wrote:\n> >\n> > Hi!\n> >\n>\n> Hey Lucas,\n>\n> > This patch series adds support for path-related fields in repo-info, based on\n> > what we already have in git-rev-parse:\n> >\n> > 1. The two first patches moves the path formatting used by git-rev-parse to\n> >    path.c. This will allow us to reuse this code in git-repo-info\n> > 2. The second patch add a new flag --path-format to git-repo-info, similar to\n> >    the flag of git-rev-parse with the same name\n> > 3. Add the new field `path.toplevel` as a proof of concept.\n> >\n> > This arises from the fact that I didn't know what should be the default behavior\n> > of git-repo-info when dealing with paths. Some ideas were:\n> >\n> > 1. Add --path-format, just like we have in git-rev-parse\n> > 2. Use what rev-parse uses by default\n> > 3. Add keys for both relative and absolute formats\n> >\n> > In this case, I'm using 1, but I'm not sure if it's the best option. One\n> > downside that I see here is that git-repo-info won't be able to return\n> > a relative and an absolute path for different keys in the same call.\n> >\n>\n> Option 1 feels like the cleanest approach.\n> Even though it means git-repo-info can't return both a relative and\n> absolute path in the exact same call, it keeps the API highly predictable\n> for scripting without bloating the key namespace (which Option 3 would do).\n>\n> The behaviour is different when compared to the command itself where we\n> have to use --all, but I think in this area this is the right approach.\n>\n> > Since there are many people interested in contributing to git-repo-info, I'll\n> > leave the remaining path-related fields to them :-)\n> >\n>\n> Thank you ;)\n>\n> > I'm CC'ing here:\n> >\n> > - brian, who was the original author of the `print_path` [1]\n> > - Ayush, Tian, Jayatheerth, Soutrik and Pushkar, since they expressed interested\n> >   in contributing to git-repo-info in GSoC. (I hope that I didn't forget anyone)\n> >\n> > This patch is based on top of master 2cc7191751 (The 8th batch, 2026-02-27) with\n> > lo/repo-leftover-bits merged.\n>\n>\n> This provides a fantastic foundation.\n> I have updated my GSoC proposal based on these patches to build out\n> the remaining path.* keys, alongside category-based querying and\n> global state removal.\n>\n> I will be sending that in a completely new thread shortly.\n>\n> Regards\n> - Jayatheerth\n"},{"id":"537429","messageId":"CA+rGoLcGB-iJX7U16NmONr_EhYLnsn0eNAAdcdExRLQtMv732w@mail.gmail.com","threadId":"65101","inReplyTo":"CAFNBzOdCx=R3r9+m5eDyAykMAbmbcfpX3kPeEPjqXPYT-_89+g@mail.gmail.com","subject":"Re: [PATCH 0/4] repo: add support for path-related fields","fromName":"JAYATHEERTH K","fromEmail":"jayatheerthkulkarni2005@gmail.com","sentAt":"2026-03-01T06:50:32Z","receivedAt":"2026-03-01T06:50:44Z","isPatch":true,"sender":{"key":"jayatheerthkulkarni2005@gmail.com","avatar":"https://avatars.githubusercontent.com/u/148841023?v=4"},"body":"Hi Ayush,\n\n\nOn Sun, Mar 1, 2026 at 11:15 AM Ayush Jha <kumarayushjha123@gmail.com> wrote:\n>\n> Hi Lucas,\n>\n> Thanks for sharing this series — moving the path formatting logic into\n> path.c makes a lot of sense and avoids duplication with rev-parse.\n>\n> Regarding the limitation you mentioned about not being able to mix\n> relative and absolute paths within the same invocation, I was\n> wondering whether it might be worth considering making the path format\n> part of the key itself, rather than controlled by a global flag.\n>\n> For example, something along the lines of:\n> path.toplevel\n> path.absolute.toplevel\n> path.relative.toplevel\n>\n> This could allow users to request different formats in a single call\n> without introducing global state into the command output.\n> That said, I’m not sure whether this would complicate the key\n> namespace too much, or whether maintaining parity with rev-parse\n> semantics is preferable for consistency.\n\nI think this idea works for individual retrieval\nIt still won't work when the request is for --all\nThe main problem of absolute vs relative would arrive from the --all\nperspective, no?\n\nIf a script specifically needs both formats for a set of paths, the\ncaller can easily just invoke the command twice:\ni.e git repo info --path-format=absolute <keys...>\ngit repo info --path-format=relative <keys...>\n\nIt would still work for individual path terms\n\nI think adding the absolute or relative terms in key is more of a\n\"user\" friendly one.\n\nWhat do you think about it?\n\nRegards,\n- Jayatheerth\n"},{"id":"537434","messageId":"c074cec5-eaac-49d0-89cc-d2ac9d605e59@gmail.com","threadId":"65101","inReplyTo":"20260228224252.72788-1-lucasseikioshiro@gmail.com","subject":"Re: [PATCH 0/4] repo: add support for path-related fields","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-03-01T10:44:08Z","receivedAt":"2026-03-01T10:44:11Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Lucas\n\nOn 28/02/2026 22:05, Lucas Seiki Oshiro wrote:\n> Hi!\n> \n> This patch series adds support for path-related fields in repo-info, based on\n> what we already have in git-rev-parse:\n> \n> 1. The two first patches moves the path formatting used by git-rev-parse to\n>     path.c. This will allow us to reuse this code in git-repo-info\n> 2. The second patch add a new flag --path-format to git-repo-info, similar to\n>     the flag of git-rev-parse with the same name\n> 3. Add the new field `path.toplevel` as a proof of concept.\n\nHow does this effort relate to similar effort at at \nhttps://lore.kernel.org/pull.2208.v5.git.git.1772220640.gitgitgadget@gmail.com \n?\nAlso note the suggestion from Junio in that thread to use \n\"path.working-tree\" rather than copying the name from \"git rev-parse\"\n\n> This arises from the fact that I didn't know what should be the default behavior\n> of git-repo-info when dealing with paths. Some ideas were:\n> \n> 1. Add --path-format, just like we have in git-rev-parse\n\nI think that's the best solution. Having different defaults for \ndifferent paths like rev-parse is confusing and having different keys \nfor absolute and relative versions of the same path gets rather verbose.\n\nThanks\n\nPhillip\n\n> 2. Use what rev-parse uses by default\n> 3. Add keys for both relative and absolute formats\n> \n> In this case, I'm using 1, but I'm not sure if it's the best option. One\n> downside that I see here is that git-repo-info won't be able to return\n> a relative and an absolute path for different keys in the same call.\n> \n> Since there are many people interested in contributing to git-repo-info, I'll\n> leave the remaining path-related fields to them :-)\n> \n> I'm CC'ing here:\n> \n> - brian, who was the original author of the `print_path` [1]\n> - Ayush, Tian, Jayatheerth, Soutrik and Pushkar, since they expressed interested\n>    in contributing to git-repo-info in GSoC. (I hope that I didn't forget anyone)\n> \n> This patch is based on top of master 2cc7191751 (The 8th batch, 2026-02-27) with\n> lo/repo-leftover-bits merged.\n> \n> [1] fac60b8925 (rev-parse: add option for absolute or relative path formatting, 2020-12-13)\n> \n> Lucas Seiki Oshiro (4):\n>    rev-parse: prepend `path_` to path-related enums\n>    path: add new function strbuf_add_path\n>    repo: add the --format-path flag\n>    repo: add the field path.toplevel\n> \n>   Documentation/git-repo.adoc |  8 ++-\n>   builtin/repo.c              | 67 +++++++++++++++++++------\n>   builtin/rev-parse.c         | 98 +++++++------------------------------\n>   path.c                      | 51 +++++++++++++++++++\n>   path.h                      | 23 +++++++++\n>   t/t1900-repo-info.sh        | 69 ++++++++++++++++++++++++++\n>   6 files changed, 221 insertions(+), 95 deletions(-)\n> \n\n"},{"id":"537474","messageId":"491CD222-D595-4408-B78C-72E4C3DA0A62@gmail.com","threadId":"65101","inReplyTo":"c074cec5-eaac-49d0-89cc-d2ac9d605e59@gmail.com","subject":"Re: [PATCH 0/4] repo: add support for path-related fields","fromName":"Lucas Seiki Oshiro","fromEmail":"lucasseikioshiro@gmail.com","sentAt":"2026-03-01T19:40:09Z","receivedAt":"2026-03-01T19:40:26Z","isPatch":true,"sender":{"key":"lucasseikioshiro@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12701580?v=4"},"body":"\n> Hi Lucas\n\nHi, Phillip!\n\n> How does this effort relate to similar effort at at\n> https://lore.kernel.org/pull.2208.v5.git.git.1772220640.gitgitgadget@gmail.com ?\n\nI have this patch series started since July, but I could only\nsend this after having my two previous changes in git-repo-info\naccepted.\n\nI think that patch series you mentioned is based on some\nprevious message (or the GSoC project ideas) where I listed\nwhat was still need to be implemented. It uses a similar\n--path-format flag, but without dealing with the multiple\npossibilities currently used by git-rev-parse (see [1]).\n\nThe original print_path from git-rev-parse has four possible\ndefault formats (relative, relative if there's a shared root,\ncanonical (absolute), and unmodified), and we can force it\nto use the relative or absolute formats. If I understood it\ncorrectly, this complex logic was added ([1]) to allow the\nuser to force one of these two formats without breaking the\ndefault behavior. Since git-repo-info is a new command, we are\nfree from being compatible with that, and perhaps this doesn't\nmake sense.\n\nSince there are many people interested in contributing to\ngit-repo-info, especially in the path-* fields, I just wanted\nto finish what I have here and leave the rest for them :-)\n\n>> 1. Add --path-format, just like we have in git-rev-parse\n> \n> I think that's the best solution. Having different defaults\n> for different paths like rev-parse is confusing and having\n> different keys for absolute and relative versions of the\n> same path gets rather verbose.\n\nI agree, but I still think that it feels weird that we won't\nbe able return absolute and relative paths in a single\ngit-repo-info call. But it also won't cost too much to call\nit twice.\n\n> Thanks\n\nThanks, Phillip!\nPhillip\n\nPS: I'm also CC'ing:\n\n- Eslam (the author of the patch mentioned by Phillip)\n- Karthik, Justin, Ayush, and Siddhart (possible mentors for\n  \"Improve the new git repo command\")\n- Patrick, who was my GSoC mentor and the person I first\n  discussed with about --path-format\n\n[1] fac60b8925 (rev-parse: add option for absolute or relative path formatting, 2020-12-13)\n\n"},{"id":"537475","messageId":"12F0E36B-6F42-494A-B985-E41C9C4BF92F@gmail.com","threadId":"65101","inReplyTo":"CA+rGoLdTc2caDUsQedpegL+T4MqwwiA62uuDSFSawAT5vcPvWQ@mail.gmail.com","subject":"Re: [PATCH 0/4] repo: add support for path-related fields","fromName":"Lucas Seiki Oshiro","fromEmail":"lucasseikioshiro@gmail.com","sentAt":"2026-03-01T19:49:43Z","receivedAt":"2026-03-01T19:49:58Z","isPatch":true,"sender":{"key":"lucasseikioshiro@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12701580?v=4"},"body":"\n> Option 1 feels like the cleanest approach.\n> Even though it means git-repo-info can't return both a relative and\n> absolute path in the exact same call, it keeps the API highly predictable\n> for scripting without bloating the key namespace (which Option 3 would do).\n\nYeah. I think that in the future most of them will be\npath.*, and 3 would double them...\n"},{"id":"537476","messageId":"B46AA932-28EF-4A2C-96B9-0F05D9641C1C@gmail.com","threadId":"65101","inReplyTo":"CAFNBzOdCx=R3r9+m5eDyAykMAbmbcfpX3kPeEPjqXPYT-_89+g@mail.gmail.com","subject":"Re: [PATCH 0/4] repo: add support for path-related fields","fromName":"Lucas Seiki Oshiro","fromEmail":"lucasseikioshiro@gmail.com","sentAt":"2026-03-01T19:55:11Z","receivedAt":"2026-03-01T19:55:27Z","isPatch":true,"sender":{"key":"lucasseikioshiro@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12701580?v=4"},"body":"\n> Hi Lucas,\n\nHi, Ayush!\n\n> Thanks for sharing this series — moving the path formatting logic into\n> path.c makes a lot of sense and avoids duplication with rev-parse.\n\nYeah, but since git-repo-info was written as a better home for\nsome features currently in git-rev-parse, now we can think in\nbetter solutions.\n\n> For example, something along the lines of:\n> path.toplevel\n> path.absolute.toplevel\n> path.relative.toplevel\n\nI also thought about that, but what would happen with --all?\nIf --all returns both absolute and relative, then we would\nhave the third solution.\n"},{"id":"537477","messageId":"9789E676-4DE0-4C4C-BCAC-5BD880A51CE1@gmail.com","threadId":"65101","inReplyTo":"71e42a01-6077-48fc-876e-555431d1288f@gmail.com","subject":"Re: [PATCH 4/4] repo: add the field path.toplevel","fromName":"Lucas Seiki Oshiro","fromEmail":"lucasseikioshiro@gmail.com","sentAt":"2026-03-01T20:21:13Z","receivedAt":"2026-03-01T20:21:29Z","isPatch":true,"sender":{"key":"lucasseikioshiro@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12701580?v=4"},"body":"\n> Hi Lucas,\n\nHi, Tian!\n\n> > +void strbuf_add_path(struct strbuf *sb, const char *path, const char > *prefix, enum path_format_type format, enum path_default_type def)\n> \n> Isn't it a bit inappropriate for a generic character concatenation\n> function to know about format and def? I don't think this should be\n> the responsibility of a low-level function, at least not\n> str_buf_add_path().\n\nI don't think it can be considered a low-level function, but I\nagree that its name can be misleading.\n\n> > + prefix = cwd = xgetcwd()\n> \n> Will there be a performance regression? Since xgetcwd() here is a\n> system call, right?\n\nIn this case, no, it is defined in wrapper.h.\n\n> I don't think we should add the two new parameters to all get_\n> functions here. As changed in your patch, functions like\n> get_object_format don't really, need to know about prefix or format,\n> so the corresponding parameters are marked as UNUSED. Imagine if\n> more and more data needs to be retrieved by these get_ series\n> functions in the future — is it really advisable to add unnecessary\n> parameters to all remaining functions just for the sake of a few?\n\nIn this case, we need to add them to match the signature of\nget_value_fn. Those values will be useful for all the path.*, but\nif we start to add more than that I agree that we'll need to think\nin a better solution.\n\n> I'm not entirely sure about the above content either; I'm just\n> throwing out ideas to spark discussion. (´～`)\n\nThanks, it's also good to see more points of view. I'm also not\nsure about it :-)\n"},{"id":"537482","messageId":"aaSusXil9nDHYGMR@fruit.crustytoothpaste.net","threadId":"65101","inReplyTo":"20260228224252.72788-1-lucasseikioshiro@gmail.com","subject":"Re: [PATCH 0/4] repo: add support for path-related fields","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2026-03-01T21:25:05Z","receivedAt":"2026-03-01T21:25:13Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2026-02-28 at 22:05:54, Lucas Seiki Oshiro wrote:\n> Hi!\n> \n> This patch series adds support for path-related fields in repo-info, based on\n> what we already have in git-rev-parse:\n> \n> 1. The two first patches moves the path formatting used by git-rev-parse to\n>    path.c. This will allow us to reuse this code in git-repo-info\n> 2. The second patch add a new flag --path-format to git-repo-info, similar to\n>    the flag of git-rev-parse with the same name\n> 3. Add the new field `path.toplevel` as a proof of concept.\n> \n> This arises from the fact that I didn't know what should be the default behavior\n> of git-repo-info when dealing with paths. Some ideas were:\n> \n> 1. Add --path-format, just like we have in git-rev-parse\n> 2. Use what rev-parse uses by default\n> 3. Add keys for both relative and absolute formats\n> \n> In this case, I'm using 1, but I'm not sure if it's the best option. One\n> downside that I see here is that git-repo-info won't be able to return\n> a relative and an absolute path for different keys in the same call.\n\nI think you should provide both.  I originally added this for things\nlike `--git-common-dir`, which Git LFS would really like to have as an\nabsolute path in the way that Git canonicalizes it, as well as\npotentially a relative path.\n\nThe reason is that the way Git canonicalizes things on Windows is not\neasily accessible on all systems or in all languages.  For instance, Go\nhas steadfastly refused to provide functionality for\n`GetFinalPathnameByHandle`, despite that being necessary to canonicalize\nthe way Git does, so it's important to be able to get that information\nboth in a relative way and as an absolute path.\n\nOn Unix, things are easier since there are fewer special file system\nobjects and `realpath` or its equivalent are usually present in most\nlanguages.\n\nWith `git rev-parse`, you can change `--path-format` on the command line\nbetween options, so if you want both, you just request one thing, use\n`--path-format`, and then request the other.  However, that can't be\ndone with `git repo` and `--path-format`.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"537487","messageId":"6d87ec49-6f24-42c5-86b2-6a4825607bb2@gmail.com","threadId":"65101","inReplyTo":"9789E676-4DE0-4C4C-BCAC-5BD880A51CE1@gmail.com","subject":"Re: [PATCH 4/4] repo: add the field path.toplevel","fromName":"Tian Yuchen","fromEmail":"a3205153416@gmail.com","sentAt":"2026-03-02T04:54:13Z","receivedAt":"2026-03-02T04:54:17Z","isPatch":true,"sender":{"key":"cat@malon.dev","avatar":"https://avatars.githubusercontent.com/u/232002048?v=4"},"body":"Hi Lucas\n\n> I don't think it can be considered a low-level function, but I\n> agree that its name can be misleading.\n\nHummm...If a function is solely responsible for string concatenation and \nresides in  like path.c, why isn't it a low level function?\n\nI think the key issue lies in the fact that this function's \nresponsibilities are not quite appropriate, rather than merely the \nname. Does a string buffer need to understand Git's path formatting \nrules? It should only know how to append bytes, right? Maybe it would be \nbetter suited as a domain-specific formatter like 'format_path_output()' \nin a higher level module? I am quite uncertain about it.\n\n\n> In this case, no, it is defined in wrapper.h.\n\nYes it is defined in wrapper.h. However in wrapper.c we have:\n\nchar *xgetcwd(void)\n{\n\tstruct strbuf sb = STRBUF_INIT;\n\tif (strbuf_getcwd(&sb))\n\t\tdie_errno(_(\"unable to get current working directory\"));\n\treturn strbuf_detach(&sb, NULL);\n}\n\nand the for the stfbuf_getcwd(), in strbuf.c we have:\n\nint strbuf_getcwd(struct strbuf *sb)\n{\n\tsize_t oldalloc = sb->alloc;\n\tsize_t guessed_len = 128;\n\n\tfor (;; guessed_len *= 2) {\n\t\tstrbuf_grow(sb, guessed_len);\n\t\tif (getcwd(sb->buf, sb->alloc)) {\n\t\t\tstrbuf_setlen(sb, strlen(sb->buf));\n\t\t\treturn 0;\n...\n\nNotice the getcwd() function, which is indeed a system call, which you \ncan check with 'man 2 getcwd' in terminal. Wrapping it in wrapper.c is \njust providing a shortcut, right?\n\nBut I don't think using system calls is inherently problematic. The \nissue lies in where this xgetbuf() is placed:\n\nIn builtin/rev-parse.c, the print_path() function is inside of \ncmd_rev_parse(), which is like:\n\nint cmd_rev_parse(....){\n\tfor (i = 1; i < argc; i++){\n\t...\n\tif (....){\n\t\tprint_path(....)\n\t}\n\t...\n}\n\nAnd your print_path() implement was:\n\n> +static void print_path(const char *path, const char *prefix,\n> +\t\t       enum path_format_type format, enum path_default_type def)\n>  {\n> +\tstruct strbuf sb = STRBUF_INIT;\n> +\tstrbuf_add_path(&sb, path, prefix, format, def);\n> +\tputs(sb.buf);\n> +\tstrbuf_release(&sb);\n>  }\n\nSo this system call is indeed invoked in the loop. Specifically, it gets \ncalled every time 'git rev-parse' is invoked, and as far as I know it \nshould be a command used extensively in like shell scripts...?\n\nMaybe cache-up approach is more robust? For example in builtin/rev-parse.c:\n\nconst char *cached_cwd = ...->original_cwd;\nif (!cached_cwd)\n\tcached_cwd = xgetcwd();\n\nfor (...) {\n\tif (...) {\n\t\tprint_path_with_cwd(..., cached_cwd, ...);\n\t}\n}\n\n\n> In this case, we need to add them to match the signature of\n> get_value_fn. Those values will be useful for all the path.*, but\n> if we start to add more than that I agree that we'll need to think\n> in a better solution.\n\nYes indeed.\n\n> Thanks, it's also good to see more points of view. I'm also not\n> sure about it :-)\n\nThank you for the patch again!\n\nRegards,\n\nYuchen\n\n"},{"id":"537548","messageId":"xmqqbjh64262.fsf@gitster.g","threadId":"65101","inReplyTo":"aaSusXil9nDHYGMR@fruit.crustytoothpaste.net","subject":"Re: [PATCH 0/4] repo: add support for path-related fields","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-02T16:38:29Z","receivedAt":"2026-03-02T16:38:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n\n> With `git rev-parse`, you can change `--path-format` on the command line\n> between options, so if you want both, you just request one thing, use\n> `--path-format`, and then request the other.  However, that can't be\n> done with `git repo` and `--path-format`.\n\nHmph, that is one advantage of that incremental option handling done\nby \"rev-parse\", which often is a source of confusion and complaints,\nthough ;-)\n"},{"id":"537584","messageId":"3983da40-bf2c-4665-a7d9-dfebaacb8bd3@gmail.com","threadId":"65101","inReplyTo":"xmqqbjh64262.fsf@gitster.g","subject":"Re: [PATCH 0/4] repo: add support for path-related fields","fromName":"Tian Yuchen","fromEmail":"a3205153416@gmail.com","sentAt":"2026-03-02T18:51:26Z","receivedAt":"2026-03-02T18:51:31Z","isPatch":true,"sender":{"key":"cat@malon.dev","avatar":"https://avatars.githubusercontent.com/u/232002048?v=4"},"body":"On 3/3/26 00:38, Junio C Hamano wrote:\n> \"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n> \n>> With `git rev-parse`, you can change `--path-format` on the command line\n>> between options, so if you want both, you just request one thing, use\n>> `--path-format`, and then request the other.  However, that can't be\n>> done with `git repo` and `--path-format`.\n> \n> Hmph, that is one advantage of that incremental option handling done\n> by \"rev-parse\", which often is a source of confusion and complaints,\n> though ;-)\n\nShort question: Is using format modifier like (%path:relative), \n(%path:absolute) a good solution here? I think it can be implemented by \nsimply adding a path parsing function in ref-filter.c (and some other \nwork that aren't particularly challenging).\n\nIt should be user-friendly, readable and free of global flags, right? :-]\n\nRegards,\n\nYuchen\n"},{"id":"537604","messageId":"xmqq8qc9zzix.fsf@gitster.g","threadId":"65101","inReplyTo":"3983da40-bf2c-4665-a7d9-dfebaacb8bd3@gmail.com","subject":"Re: [PATCH 0/4] repo: add support for path-related fields","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-02T21:34:30Z","receivedAt":"2026-03-02T21:34:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Tian Yuchen <a3205153416@gmail.com> writes:\n\n> On 3/3/26 00:38, Junio C Hamano wrote:\n>> \"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n>> \n>>> With `git rev-parse`, you can change `--path-format` on the command line\n>>> between options, so if you want both, you just request one thing, use\n>>> `--path-format`, and then request the other.  However, that can't be\n>>> done with `git repo` and `--path-format`.\n>> \n>> Hmph, that is one advantage of that incremental option handling done\n>> by \"rev-parse\", which often is a source of confusion and complaints,\n>> though ;-)\n>\n> Short question: Is using format modifier like (%path:relative), \n> (%path:absolute) a good solution here? I think it can be implemented by \n> simply adding a path parsing function in ref-filter.c (and some other \n> work that aren't particularly challenging).\n>\n> It should be user-friendly, readable and free of global flags, right? :-]\n\nWhat command are we talking about now?  Is it a plumbing where\npredictability, simplicity and performance matters more than\nend-user friendliness?\n"},{"id":"537641","messageId":"CA+rGoLfbzXqP1Tw+94jMmWcSGPoefMv5E_fvwriad-O5CUeKHQ@mail.gmail.com","threadId":"65101","inReplyTo":"3983da40-bf2c-4665-a7d9-dfebaacb8bd3@gmail.com","subject":"Re: [PATCH 0/4] repo: add support for path-related fields","fromName":"JAYATHEERTH K","fromEmail":"jayatheerthkulkarni2005@gmail.com","sentAt":"2026-03-03T02:48:51Z","receivedAt":"2026-03-03T02:49:03Z","isPatch":true,"sender":{"key":"jayatheerthkulkarni2005@gmail.com","avatar":"https://avatars.githubusercontent.com/u/148841023?v=4"},"body":">\n> Short question: Is using format modifier like (%path:relative),\n> (%path:absolute) a good solution here? I think it can be implemented by\n> simply adding a path parsing function in ref-filter.c (and some other\n> work that aren't particularly challenging).\n>\n\nI see your point here.\nbut wouldn't this effectively be the same as Ayush's suggestion, just\nwith a different syntax?\nWhether we use distinct keys (path.absolute.toplevel) or format\nmodifiers (%(path:absolute))\nIt would still result in almost the same internals.\n\n>\n> Short question: Is using format modifier like (%path:relative),\n> (%path:absolute) a good solution here? I think it can be implemented by\n> simply adding a path parsing function in ref-filter.c (and some other\n> work that aren't particularly challenging).\n>\n> It should be user-friendly, readable and free of global flags, right? :-]\n\nI don't think the syntax is a concern, even if both of them are equally verbose.\n\nComing to user friendliness\nI believe Junio has already raised an appropriate question.\n"},{"id":"537643","messageId":"CAFNBzOeDU3BGdZjP0edvcd6OZxrP0VgN=AHSYTFseoKdMdu70g@mail.gmail.com","threadId":"65101","inReplyTo":"B46AA932-28EF-4A2C-96B9-0F05D9641C1C@gmail.com","subject":"Re: [PATCH 0/4] repo: add support for path-related fields","fromName":"Ayush Jha","fromEmail":"kumarayushjha123@gmail.com","sentAt":"2026-03-03T03:27:38Z","receivedAt":"2026-03-03T03:27:50Z","isPatch":true,"sender":{"key":"kumarayushjha123@gmail.com","avatar":null},"body":"Hi Lucas,\n\nI completely agree that having --all dump three variants of every path\n(default, relative, absolute) would be far too noisy and defeat the\npurpose of a clean metadata dump.\n\nMy thought is that the path.absolute.* and path.relative.* keys could\nbe treated as \"virtual\" or computed keys.\n\nIf a user runs --all, the command would only iterate over and print\nthe base keys (e.g., path.toplevel, path.git-dir). The specific format\nvariants would simply be hidden from the iteration list, much like how\nsome APIs only return expensive or highly-specific fields if they are\nexplicitly requested.\n\nThis way, --all stays perfectly clean and concise, but scripts that\nneed mixed granular control can still invoke git repo info\npath.absolute.git-dir path.relative.toplevel in a single pass without\nrelying on global state flags.\n\nDo you think treating them as explicit-request-only fields strikes the\nright balance between a clean --all output and a stateless API?\n\nOn Mon, Mar 2, 2026 at 1:25 AM Lucas Seiki Oshiro\n<lucasseikioshiro@gmail.com> wrote:\n>\n>\n> > Hi Lucas,\n>\n> Hi, Ayush!\n>\n> > Thanks for sharing this series — moving the path formatting logic into\n> > path.c makes a lot of sense and avoids duplication with rev-parse.\n>\n> Yeah, but since git-repo-info was written as a better home for\n> some features currently in git-rev-parse, now we can think in\n> better solutions.\n>\n> > For example, something along the lines of:\n> > path.toplevel\n> > path.absolute.toplevel\n> > path.relative.toplevel\n>\n> I also thought about that, but what would happen with --all?\n> If --all returns both absolute and relative, then we would\n> have the third solution.\n"},{"id":"537644","messageId":"108ccc9d-5777-4c84-9dad-c2d0f5dc2e42@gmail.com","threadId":"65101","inReplyTo":"CA+rGoLfbzXqP1Tw+94jMmWcSGPoefMv5E_fvwriad-O5CUeKHQ@mail.gmail.com","subject":"Re: [PATCH 0/4] repo: add support for path-related fields","fromName":"Tian Yuchen","fromEmail":"a3205153416@gmail.com","sentAt":"2026-03-03T04:32:32Z","receivedAt":"2026-03-03T04:32:37Z","isPatch":true,"sender":{"key":"cat@malon.dev","avatar":"https://avatars.githubusercontent.com/u/232002048?v=4"},"body":"Hi JAYATHEERTH,\n\n> I see your point here.\n> but wouldn't this effectively be the same as Ayush's suggestion, just\n> with a different syntax?\n\nIn my view, this issue is actually to choose the most suitable tool for \nthe job. After all, we don't want to use something like rev-parse, which \nis riddled with *ancient* technical debt, nor do we want to write an \neven more verbose parsing function from scratch for what you call \nverbose user input, right?\n\nIf I'm not mistaken, using different parsing functions to parse input is \nabsolutely not just a matter of syntax differences. Instead, this will \ndirectly result in differences in data structures.\n\nIn ref-filter.c, we can easily see how Git parses format modifiers.\n\nAfter the user input is parse by parse_ref_filter_atom(), it is then \npassed to the atom_valid[] static registry, which is like;\n\nstatic struct {\n\tconst char *name;\n\tinfo_source source;\n\tcmp_type cmp_type;\n\tint (*parser)(struct ref_format *format, struct used_atom *atom,\n\t\t      const char *arg, struct strbuf *err);\n} valid_atom[] = {\n\t[ATOM_REFNAME] = { \"refname\", SOURCE_NONE, FIELD_STR, \nrefname_atom_parser },\n\t[ATOM_OBJECTTYPE] = { \"objecttype\", SOURCE_OTHER, FIELD_STR, \nobjecttype_atom_parser },\n\t[ATOM_OBJECTSIZE] = { \"objectsize\", SOURCE_OTHER, FIELD_ULONG, \nobjectsize_atom_parser },\n\t[ATOM_OBJECTNAME] = { \"objectname\", SOURCE_OTHER, FIELD_STR, \noid_atom_parser },\n...\n\nAs you can see, each mapping relationship points to a parsing function \n(..._parser()). This parsing function is solely responsible for handling \nthe state arg, fundamentally resolving the issue of function \nresponsibility/naming confusion.\n\nThe reason I recommend this approach is because its implementation is \nincredibly clear and concise. To achieve the functionality we desire, \nall we need to do is add the following to the registry:\n\n[ATOM_PATH] = { \"path\", SOURCE_NONE, FIELD_STR, path_atom_parser }\n\nAnd the corresponding path_atom_parser().\n\nThis approach also offers strong scalability: If one day I decide to add \na new feature like %(path:commondir,relative) output, all it would take \nis adding a switch statement in the parser() function (along with a few \nother minor tweaks).\n\n*I'm not saying this approach is better than the solution you've \ndiscussed. I'm simply presenting a possible implementation for \nreference. (´～`)\n\n> Coming to user friendliness\n> I believe Junio has already raised an appropriate question.\n\nThis isn't a case of “you can't have your cake and eat it too,” right? I \nthink user-friendliness can be achieved without compromising \nmaintainability, predictability, or high performance in this case.\n\nRegards,\n\nYuchen\n"},{"id":"537649","messageId":"CA+rGoLc+ULYUZaDCdAHxuL8T-qyjJKTRJfSe6Muhb7c6d12e_w@mail.gmail.com","threadId":"65101","inReplyTo":"108ccc9d-5777-4c84-9dad-c2d0f5dc2e42@gmail.com","subject":"Re: [PATCH 0/4] repo: add support for path-related fields","fromName":"JAYATHEERTH K","fromEmail":"jayatheerthkulkarni2005@gmail.com","sentAt":"2026-03-03T07:23:52Z","receivedAt":"2026-03-03T07:24:05Z","isPatch":true,"sender":{"key":"jayatheerthkulkarni2005@gmail.com","avatar":"https://avatars.githubusercontent.com/u/148841023?v=4"},"body":"On Tue, Mar 3, 2026 at 10:02 AM Tian Yuchen <a3205153416@gmail.com> wrote:\n>\n> Hi JAYATHEERTH,\n\nHi Tian,\n\n>\n> > I see your point here.\n> > but wouldn't this effectively be the same as Ayush's suggestion, just\n> > with a different syntax?\n>\n> In my view, this issue is actually to choose the most suitable tool for\n> the job. After all, we don't want to use something like rev-parse, which\n> is riddled with *ancient* technical debt, nor do we want to write an\n> even more verbose parsing function from scratch for what you call\n> verbose user input, right?\n>\n\nI agree that it provides a clean and scalable mechanism,\nespecially in terms of extensibility and per-field formatting without\nrelying on global flags.\n\nTo clarify my earlier comment: I wasn't arguing against ref-filter.\nIn fact, I’m more inclined toward using the best tool for the job.\nMy earlier point was mainly about behavioral similarity and how both\nbelong to the same camp even though they might seem different.\n\n> If I'm not mistaken, using different parsing functions to parse input is\n> absolutely not just a matter of syntax differences. Instead, this will\n> directly result in differences in data structures.\n>\n> The reason I recommend this approach is because its implementation is\n> incredibly clear and concise. To achieve the functionality we desire,\n> all we need to do is add the following to the registry:\n>\n> [ATOM_PATH] = { \"path\", SOURCE_NONE, FIELD_STR, path_atom_parser }\n>\n> And the corresponding path_atom_parser().\n>\n> This approach also offers strong scalability: If one day I decide to add\n> a new feature like %(path:commondir,relative) output, all it would take\n> is adding a switch statement in the parser() function (along with a few\n> other minor tweaks).\n>\n> *I'm not saying this approach is better than the solution you've\n> discussed. I'm simply presenting a possible implementation for\n> reference. (´～`)\n\n\nThat is a detailed mail, thanks for taking time\n\nWhen I said similar\nI meant\n\nsomething like this:\n\nstatic const struct repo_info_field repo_info_field[] = {\n    { \"layout.bare\", get_layout_bare },\n    { \"layout.shallow\", get_layout_shallow },\n    { \"object.format\", get_object_format },\n    { \"path.toplevel\", get_path_toplevel },\n};\n\nThis array contains all the keys\nYou do not need to hardcode path.absolute.toplevel,\npath.relative.toplevel, etc., in the array...\n\nInstead,\n\nIf the user asks for path.absolute.toplevel:\nYou detect the absolute. middle part. strip it out to find the base\nkey path.toplevel.\nYou find path.toplevel in the aray, the array works with default\nvalues when entered --all\n\n/*\n * Helper to parse the key variant.\n * Takes \"path.absolute.git-dir\" -> returns \"path.git-dir\" and sets\nopts->format.\n */\nstatic char *normalize_key(const char *raw_key, struct repo_info_opts *opts)\n{\n    const char *suffix;\n\n    /* Check for \"path.absolute.\" prefix */\n    if (skip_prefix(raw_key, \"path.absolute.\", &suffix)) {\n        opts->path_format = PATH_FORMAT_ABSOLUTE;\n        return xstrfmt(\"path.%s\", suffix);\n    }\n\n    /* Check for \"path.relative.\" prefix */\n    if (skip_prefix(raw_key, \"path.relative.\", &suffix)) {\n        opts->path_format = PATH_FORMAT_RELATIVE;\n        return xstrfmt(\"path.%s\", suffix);\n    }\n\n    /* No variant found, return raw key as-is */\n    return xstrdup(raw_key);\n}\n\nStructurally, this mimics the ref-filter parsing phase almost exactly.\nJust as ref-filter splits a compound atom like %(refname:short) into an identity\n(refname) and a modifier (short) to populate the handler's state,\nnormalize_key splits path.absolute.git-dir into the identity\n(path.git-dir) and the modifier (absolute).\n\nI just meant both the ideas are in the same camp just unrealized.\n\nWhat do you think?\n\nRegards\n- Jayatheerth\n"},{"id":"537651","messageId":"46c60949-87f1-426a-aeb9-706e97fd8e8a@gmail.com","threadId":"65101","inReplyTo":"CA+rGoLc+ULYUZaDCdAHxuL8T-qyjJKTRJfSe6Muhb7c6d12e_w@mail.gmail.com","subject":"Re: [PATCH 0/4] repo: add support for path-related fields","fromName":"Tian Yuchen","fromEmail":"a3205153416@gmail.com","sentAt":"2026-03-03T09:28:03Z","receivedAt":"2026-03-03T09:28:07Z","isPatch":true,"sender":{"key":"cat@malon.dev","avatar":"https://avatars.githubusercontent.com/u/232002048?v=4"},"body":"Hi JAYATHEERTH,\n\nThanks for the reply.\n\n> To clarify my earlier comment: I wasn't arguing against ref-filter.\n> In fact, I’m more inclined toward using the best tool for the job.\n> My earlier point was mainly about behavioral similarity and how both\n> belong to the same camp even though they might seem different.\n\n > I just meant both the ideas are in the same camp just unrealized.\n\nThat's exactly right. I was just reminding that there's a ready-made \nsolution available that seems to work very well. Wouldn't reinventing \nsomething that already exists, with only minor differences, cause \nconfusion? (´;ω;`)\n\n> something like this:\n> \n> static const struct repo_info_field repo_info_field[] = {\n>      { \"layout.bare\", get_layout_bare },\n>      { \"layout.shallow\", get_layout_shallow },\n>      { \"object.format\", get_object_format },\n>      { \"path.toplevel\", get_path_toplevel },\n> };\n> \n> This array contains all the keys\n> You do not need to hardcode path.absolute.toplevel,\n> path.relative.toplevel, etc., in the array...\n> \n> Instead,\n> \n> If the user asks for path.absolute.toplevel:\n> You detect the absolute. middle part. strip it out to find the base\n> key path.toplevel.\n> You find path.toplevel in the aray, the array works with default\n> values when entered --all\n> \n> /*\n>   * Helper to parse the key variant.\n>   * Takes \"path.absolute.git-dir\" -> returns \"path.git-dir\" and sets\n> opts->format.\n>   */\n> static char *normalize_key(const char *raw_key, struct repo_info_opts *opts)\n> {\n>      const char *suffix;\n> \n>      /* Check for \"path.absolute.\" prefix */\n>      if (skip_prefix(raw_key, \"path.absolute.\", &suffix)) {\n>          opts->path_format = PATH_FORMAT_ABSOLUTE;\n>          return xstrfmt(\"path.%s\", suffix);\n>      }\n> \n>      /* Check for \"path.relative.\" prefix */\n>      if (skip_prefix(raw_key, \"path.relative.\", &suffix)) {\n>          opts->path_format = PATH_FORMAT_RELATIVE;\n>          return xstrfmt(\"path.%s\", suffix);\n>      }\n> \n>      /* No variant found, return raw key as-is */\n>      return xstrdup(raw_key);\n> }\n\nI see. What you've written matches what you described — it essentially \nreplicates the functionality of ref-filter.c. While I understand this is \njust a simple code implementation demo:\n\n >          opts->path_format = PATH_FORMAT_ABSOLUTE;\n\nThis implementation appears unable to support input like 'git repo-info \n--keys=path.absolute.toplevel,path.relative.gitdir', meaning it cannot \nhandle multiple paths output from a single call as previously mentioned \nby Brain. The 'opts' here should be a global shared state, right?\n\nI think it's better for the parser to allocate a separate memory for \neach arg it encounters. But then we'd be back to implementing something \nlike struct used_atom, hahaha (ゝ∀･)\n\nThank you again for your email.\n\nYuchen\n\n(I feel like we've been on this topic for too long. If you don't want to \nreply, you don't have to :-)\n\n"},{"id":"537655","messageId":"CA+rGoLchSjQHn_jmHVjyOHUsYXLtmR+oOYKJc=c-ZNfpJ=S44Q@mail.gmail.com","threadId":"65101","inReplyTo":"46c60949-87f1-426a-aeb9-706e97fd8e8a@gmail.com","subject":"Re: [PATCH 0/4] repo: add support for path-related fields","fromName":"JAYATHEERTH K","fromEmail":"jayatheerthkulkarni2005@gmail.com","sentAt":"2026-03-03T10:31:03Z","receivedAt":"2026-03-03T10:31:15Z","isPatch":true,"sender":{"key":"jayatheerthkulkarni2005@gmail.com","avatar":"https://avatars.githubusercontent.com/u/148841023?v=4"},"body":">\n> I see. What you've written matches what you described — it essentially\n> replicates the functionality of ref-filter.c. While I understand this is\n> just a simple code implementation demo:\n>\n>  >          opts->path_format = PATH_FORMAT_ABSOLUTE;\n>\n> This implementation appears unable to support input like 'git repo-info\n> --keys=path.absolute.toplevel,path.relative.gitdir', meaning it cannot\n> handle multiple paths output from a single call as previously mentioned\n> by Brain. The 'opts' here should be a global shared state, right?\n>\n> I think it's better for the parser to allocate a separate memory for\n> each arg it encounters. But then we'd be back to implementing something\n> like struct used_atom, hahaha (ゝ∀･)\n>\n> Thank you again for your email.\n>\n> Yuchen\n\nWe create a fresh local_opts copy from the global_opts defaults for\nevery single key:\n\nfor (int i = 0; i < argc; i++) {\n    struct repo_info_opts local_opts = global_opts; /* Fresh reset */\n    char *base_key = normalize_key(argv[i], &local_opts);\n\n    /* ... find_field and get_value logic ... */\n}\n\nSince local_opts is local to the loop iteration,\npath.absolute.toplevel only modifies the state for that specific turn.\nWhen the loop moves to path.relative.gitdir, it gets a brand-new\nlocal_opts and starts over.\nIt handles mixed formats in a single call perfectly, without any\npersistent _pollution_ or the need for complex heap allocations.\n\n>\n> (I feel like we've been on this topic for too long. If you don't want to\n> reply, you don't have to :-)\n>\n\nI agree we've covered a lot of ground here, so I'll leave it at that.\nThanks for the great discussion ;)\n\nRegards,\nJayatheerth\n"},{"id":"538184","messageId":"041DCF2E-75FB-4B0A-9128-FDBB1A6DAC3C@gmail.com","threadId":"65101","inReplyTo":"aaSusXil9nDHYGMR@fruit.crustytoothpaste.net","subject":"Re: [PATCH 0/4] repo: add support for path-related fields","fromName":"Lucas Seiki Oshiro","fromEmail":"lucasseikioshiro@gmail.com","sentAt":"2026-03-08T00:29:00Z","receivedAt":"2026-03-08T00:29:16Z","isPatch":true,"sender":{"key":"lucasseikioshiro@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12701580?v=4"},"body":"\n> I think you should provide both.  I originally added this for things\n> like `--git-common-dir`, which Git LFS would really like to have as an\n> absolute path in the way that Git canonicalizes it, as well as\n> potentially a relative path.\n\nThanks for your input, brian!\n\n> With `git rev-parse`, you can change `--path-format` on the command line\n> between options, so if you want both, you just request one thing, use\n> `--path-format`, and then request the other.  However, that can't be\n> done with `git repo` and `--path-format`.\n\nIt makes sense. If we use the key format suggested by Ayush [1]\nwe could retrieve both values with something like\n\n   $ git repo info path.git-dir.absolute path.git-dir.relative\n\nI'll stop by now. Since many people are interested in contributing to\ngit-repo-info in GSoC, I'll leave this decision to the person who will\nwork on it, if there is one.\n\n[1] B46AA932-28EF-4A2C-96B9-0F05D9641C1C@gmail.com\n\n"}]}