[PATCH v9 4/4] var: add broken-out identity variables
- From
- Andrew Pleeter <andrewpleeter@gmail.com>
- Date
- Sep 26, 2026, 16:20 UTC
- Message-ID
- <20260926162048.30853-5-andrewpleeter@gmail.com>
- In-Reply-To
- <xmqq33va1lcg.fsf@gitster.g>
A script that wants only the author's name has to ask for GIT_AUTHOR_IDENT and take the result apart itself, which means reimplementing the rules split_ident_line() already knows, and getting them subtly wrong for names that contain an e-mail address or other awkward characters.
Add GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL and GIT_AUTHOR_DATE, together with their GIT_COMMITTER_* counterparts, which give the individual pieces of the corresponding *_IDENT variable. They are derived from the same ident string, so they are strict in the same way: asking for one of them fails if the identity cannot be determined.
Signed-off-by: Andrew Pleeter <andrewpleeter@gmail.com> --- Documentation/git-var.adoc | 36 +++++++++++++-- builtin/var.c | 90 ++++++++++++++++++++++++++++++++++++++ t/t0007-git-var.sh | 56 ++++++++++++++++++++++++ 3 files changed, 178 insertions(+), 4 deletions(-)
diff --git a/Documentation/git-var.adoc b/Documentation/git-var.adoc index d0772d9743..6982228f97 100644 --- a/Documentation/git-var.adoc +++ b/Documentation/git-var.adoc @@ -43,17 +43,45 @@ OPTIONS EXAMPLES -------- - $ git var GIT_AUTHOR_IDENT - Eric W. Biederman <ebiederm@lnxi.com> 1121223278 -0600 +* Get the author identity: ++ +------------ +$ git var GIT_AUTHOR_IDENT +Eric W. Biederman <ebiederm@lnxi.com> 1121223278 -0600 +------------ + +* Get the author name and email: ++ +------------ +$ git var GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL +GIT_AUTHOR_NAME=Eric W. Biederman +GIT_AUTHOR_EMAIL=ebiederm@lnxi.com +------------ VARIABLES --------- `GIT_AUTHOR_IDENT`:: - The author of a piece of code. +`GIT_AUTHOR_NAME`:: +`GIT_AUTHOR_EMAIL`:: +`GIT_AUTHOR_DATE`:: + The authorship information that would be recorded in the + resulting commit object if you ran `git commit` right now. + `GIT_AUTHOR_IDENT` consists of the author's name, e-mail + address, and timestamp+timezone. These three pieces of + information are available separately as `GIT_AUTHOR_NAME`, + `GIT_AUTHOR_EMAIL`, and `GIT_AUTHOR_DATE`. `GIT_COMMITTER_IDENT`:: - The person who put a piece of code into Git. +`GIT_COMMITTER_NAME`:: +`GIT_COMMITTER_EMAIL`:: +`GIT_COMMITTER_DATE`:: + The committer information that would be recorded in the + resulting commit object if you ran `git commit` right now. + `GIT_COMMITTER_IDENT` consists of the committer's name, e-mail + address, and timestamp+timezone. These three pieces of + information are available separately as `GIT_COMMITTER_NAME`, + `GIT_COMMITTER_EMAIL`, and `GIT_COMMITTER_DATE`. `GIT_EDITOR`:: Text editor for use by Git commands. The value is meant to be diff --git a/builtin/var.c b/builtin/var.c index 5fbebc62e2..dd4325e5b5 100644 --- a/builtin/var.c +++ b/builtin/var.c @@ -27,16 +27,82 @@ static const char * const var_usage[] = { NULL }; +enum ident_part { + IDENT_NAME, + IDENT_MAIL, + IDENT_DATE, +}; + +static char *ident_part(const char *ident, enum ident_part part) +{ + struct ident_split split; + + if (!ident) + return NULL; + if (split_ident_line(&split, ident, strlen(ident))) + return NULL; + + switch (part) { + case IDENT_NAME: + if (!split.name_begin || !split.name_end) + BUG("split_ident_line() gave NULL names???"); + return xmemdupz(split.name_begin, + split.name_end - split.name_begin); + case IDENT_MAIL: + if (!split.mail_begin || !split.mail_end) + BUG("split_ident_line() gave NULL mail???"); + return xmemdupz(split.mail_begin, + split.mail_end - split.mail_begin); + case IDENT_DATE: + if (!split.date_begin || !split.tz_end) + BUG("split_ident_line() gave NULL date/tz???"); + return xmemdupz(split.date_begin, + split.tz_end - split.date_begin); + default: + BUG("unknown ident_part %d", part); + } +} + static char *committer(int ident_flag) { return xstrdup_or_null(git_committer_info(ident_flag)); } +static char *committer_name(int ident_flag) +{ + return ident_part(git_committer_info(ident_flag), IDENT_NAME); +} + +static char *committer_email(int ident_flag) +{ + return ident_part(git_committer_info(ident_flag), IDENT_MAIL); +} + +static char *committer_date(int ident_flag) +{ + return ident_part(git_committer_info(ident_flag), IDENT_DATE); +} + static char *author(int ident_flag) { return xstrdup_or_null(git_author_info(ident_flag)); } +static char *author_name(int ident_flag) +{ + return ident_part(git_author_info(ident_flag), IDENT_NAME); +} + +static char *author_email(int ident_flag) +{ + return ident_part(git_author_info(ident_flag), IDENT_MAIL); +} + +static char *author_date(int ident_flag) +{ + return ident_part(git_author_info(ident_flag), IDENT_DATE); +} + static char *editor(int ident_flag UNUSED) { return xstrdup_or_null(git_editor()); @@ -123,10 +189,34 @@ static struct git_var git_vars[] = { .name = "GIT_COMMITTER_IDENT", .read = committer, }, + { + .name = "GIT_COMMITTER_NAME", + .read = committer_name, + }, + { + .name = "GIT_COMMITTER_EMAIL", + .read = committer_email, + }, + { + .name = "GIT_COMMITTER_DATE", + .read = committer_date, + }, { .name = "GIT_AUTHOR_IDENT", .read = author, }, + { + .name = "GIT_AUTHOR_NAME", + .read = author_name, + }, + { + .name = "GIT_AUTHOR_EMAIL", + .read = author_email, + }, + { + .name = "GIT_AUTHOR_DATE", + .read = author_date, + }, { .name = "GIT_EDITOR", .read = editor, diff --git a/t/t0007-git-var.sh b/t/t0007-git-var.sh index 593610300a..e43becff1c 100755 --- a/t/t0007-git-var.sh +++ b/t/t0007-git-var.sh @@ -373,4 +373,60 @@ test_expect_success 'unknown variable is a usage error' ' test_grep usage err ' +test_expect_success 'get author identity components' ' + test_tick && + echo "$GIT_AUTHOR_NAME" >expect.name && + echo "$GIT_AUTHOR_EMAIL" >expect.email && + echo "$GIT_AUTHOR_DATE" >expect.date && + git var GIT_AUTHOR_NAME >actual.name && + git var GIT_AUTHOR_EMAIL >actual.email && + git var GIT_AUTHOR_DATE >actual.date && + test_cmp expect.name actual.name && + test_cmp expect.email actual.email && + test_cmp expect.date actual.date +' + +test_expect_success 'get committer identity components' ' + test_tick && + echo "$GIT_COMMITTER_NAME" >expect.name && + echo "$GIT_COMMITTER_EMAIL" >expect.email && + echo "$GIT_COMMITTER_DATE" >expect.date && + git var GIT_COMMITTER_NAME >actual.name && + git var GIT_COMMITTER_EMAIL >actual.email && + git var GIT_COMMITTER_DATE >actual.date && + test_cmp expect.name actual.name && + test_cmp expect.email actual.email && + test_cmp expect.date actual.date +' + +test_expect_success !FAIL_PREREQS,!AUTOIDENT 'identity components are strict' ' + ( + sane_unset GIT_COMMITTER_NAME && + sane_unset GIT_COMMITTER_EMAIL && + test_must_fail git var GIT_COMMITTER_NAME + ) +' + +test_expect_success 'get several identity components at once' ' + test_tick && + cat >expect <<-EOF && + GIT_AUTHOR_NAME=$GIT_AUTHOR_NAME + GIT_AUTHOR_EMAIL=$GIT_AUTHOR_EMAIL + GIT_COMMITTER_NAME=$GIT_COMMITTER_NAME + GIT_COMMITTER_EMAIL=$GIT_COMMITTER_EMAIL + EOF + git var GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL >actual && + test_cmp expect actual +' + +test_expect_success 'git var -l lists the identity components' ' + git var -l >actual && + test_grep "^GIT_AUTHOR_NAME=" actual && + test_grep "^GIT_AUTHOR_EMAIL=" actual && + test_grep "^GIT_AUTHOR_DATE=" actual && + test_grep "^GIT_COMMITTER_NAME=" actual && + test_grep "^GIT_COMMITTER_EMAIL=" actual && + test_grep "^GIT_COMMITTER_DATE=" actual +' + test_done
-- 2.54.0 (Apple Git-157)