var: add broken-out identity variables

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>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
next
Andrew Pleeter 2026-09-26 12:20:48 -04:00 committed by Junio C Hamano
parent 09726e777e
commit 598588c155
3 changed files with 178 additions and 4 deletions

View File

@ -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

View File

@ -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,

View File

@ -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