From: Hariom Verma <hariom18599@xxxxxxxxx> Currently, ref-filter only supports printing email with angle brackets. Let's add support for two more email options. - trim : for email without angle brackets. - localpart : for the part before the @ sign out of trimmed email Mentored-by: Christian Couder <chriscool@xxxxxxxxxxxxx> Mentored-by: Heba Waly <heba.waly@xxxxxxxxx> Signed-off-by: Hariom Verma <hariom18599@xxxxxxxxx> --- Documentation/git-for-each-ref.txt | 5 ++- ref-filter.c | 54 +++++++++++++++++++++++++----- t/t6300-for-each-ref.sh | 16 +++++++++ 3 files changed, 65 insertions(+), 10 deletions(-) diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt index 2ea71c5f6c..e6ce8af612 100644 --- a/Documentation/git-for-each-ref.txt +++ b/Documentation/git-for-each-ref.txt @@ -230,7 +230,10 @@ These are intended for working on a mix of annotated and lightweight tags. Fields that have name-email-date tuple as its value (`author`, `committer`, and `tagger`) can be suffixed with `name`, `email`, -and `date` to extract the named component. +and `date` to extract the named component. For email fields (`authoremail`, +`committeremail` and `taggeremail`), `:trim` can be appended to get the email +without angle brackets, and `:localpart` to get the part before the `@` symbol +out of the trimmed email. The message in a commit or a tag object is `contents`, from which `contents:<part>` can be used to extract various parts out of: diff --git a/ref-filter.c b/ref-filter.c index ba85869755..e60765f156 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -140,6 +140,9 @@ static struct used_atom { enum { O_FULL, O_LENGTH, O_SHORT } option; unsigned int length; } objectname; + struct email_option { + enum { EO_RAW, EO_TRIM, EO_LOCALPART } option; + } email_option; struct refname_atom refname; char *head; } u; @@ -377,6 +380,20 @@ static int objectname_atom_parser(const struct ref_format *format, struct used_a return 0; } +static int person_email_atom_parser(const struct ref_format *format, struct used_atom *atom, + const char *arg, struct strbuf *err) +{ + if (!arg) + atom->u.email_option.option = EO_RAW; + else if (!strcmp(arg, "trim")) + atom->u.email_option.option = EO_TRIM; + else if (!strcmp(arg, "localpart")) + atom->u.email_option.option = EO_LOCALPART; + else + return strbuf_addf_ret(err, -1, _("unrecognized email option: %s"), arg); + return 0; +} + static int refname_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg, struct strbuf *err) { @@ -488,15 +505,15 @@ static struct { { "tag", SOURCE_OBJ }, { "author", SOURCE_OBJ }, { "authorname", SOURCE_OBJ }, - { "authoremail", SOURCE_OBJ }, + { "authoremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser }, { "authordate", SOURCE_OBJ, FIELD_TIME }, { "committer", SOURCE_OBJ }, { "committername", SOURCE_OBJ }, - { "committeremail", SOURCE_OBJ }, + { "committeremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser }, { "committerdate", SOURCE_OBJ, FIELD_TIME }, { "tagger", SOURCE_OBJ }, { "taggername", SOURCE_OBJ }, - { "taggeremail", SOURCE_OBJ }, + { "taggeremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser }, { "taggerdate", SOURCE_OBJ, FIELD_TIME }, { "creator", SOURCE_OBJ }, { "creatordate", SOURCE_OBJ, FIELD_TIME }, @@ -1037,16 +1054,35 @@ static const char *copy_name(const char *buf) return xstrdup(""); } -static const char *copy_email(const char *buf) +static const char *copy_email(const char *buf, struct used_atom *atom) { const char *email = strchr(buf, '<'); const char *eoemail; if (!email) return xstrdup(""); - eoemail = strchr(email, '>'); + switch (atom->u.email_option.option) { + case EO_RAW: + eoemail = strchr(email, '>'); + if (eoemail) + eoemail++; + break; + case EO_TRIM: + email++; + eoemail = strchr(email, '>'); + break; + case EO_LOCALPART: + email++; + eoemail = strchr(email, '@'); + if (!eoemail) + eoemail = strchr(email, '>'); + break; + default: + BUG("unknown email option"); + } + if (!eoemail) return xstrdup(""); - return xmemdupz(email, eoemail + 1 - email); + return xmemdupz(email, eoemail - email); } static char *copy_subject(const char *buf, unsigned long len) @@ -1116,7 +1152,7 @@ static void grab_person(const char *who, struct atom_value *val, int deref, void continue; if (name[wholen] != 0 && strcmp(name + wholen, "name") && - strcmp(name + wholen, "email") && + !starts_with(name + wholen, "email") && !starts_with(name + wholen, "date")) continue; if (!wholine) @@ -1127,8 +1163,8 @@ static void grab_person(const char *who, struct atom_value *val, int deref, void v->s = copy_line(wholine); else if (!strcmp(name + wholen, "name")) v->s = copy_name(wholine); - else if (!strcmp(name + wholen, "email")) - v->s = copy_email(wholine); + else if (starts_with(name + wholen, "email")) + v->s = copy_email(wholine, &used_atom[i]); else if (starts_with(name + wholen, "date")) grab_date(wholine, v, name); } diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index a83579fbdf..64fbc91146 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -125,15 +125,21 @@ test_atom head '*objecttype' '' test_atom head author 'A U Thor <author@xxxxxxxxxxx> 1151968724 +0200' test_atom head authorname 'A U Thor' test_atom head authoremail '<author@xxxxxxxxxxx>' +test_atom head authoremail:trim 'author@xxxxxxxxxxx' +test_atom head authoremail:localpart 'author' test_atom head authordate 'Tue Jul 4 01:18:44 2006 +0200' test_atom head committer 'C O Mitter <committer@xxxxxxxxxxx> 1151968723 +0200' test_atom head committername 'C O Mitter' test_atom head committeremail '<committer@xxxxxxxxxxx>' +test_atom head committeremail:trim 'committer@xxxxxxxxxxx' +test_atom head committeremail:localpart 'committer' test_atom head committerdate 'Tue Jul 4 01:18:43 2006 +0200' test_atom head tag '' test_atom head tagger '' test_atom head taggername '' test_atom head taggeremail '' +test_atom head taggeremail:trim '' +test_atom head taggeremail:localpart '' test_atom head taggerdate '' test_atom head creator 'C O Mitter <committer@xxxxxxxxxxx> 1151968723 +0200' test_atom head creatordate 'Tue Jul 4 01:18:43 2006 +0200' @@ -170,15 +176,21 @@ test_atom tag '*objecttype' 'commit' test_atom tag author '' test_atom tag authorname '' test_atom tag authoremail '' +test_atom tag authoremail:trim '' +test_atom tag authoremail:localpart '' test_atom tag authordate '' test_atom tag committer '' test_atom tag committername '' test_atom tag committeremail '' +test_atom tag committeremail:trim '' +test_atom tag committeremail:localpart '' test_atom tag committerdate '' test_atom tag tag 'testtag' test_atom tag tagger 'C O Mitter <committer@xxxxxxxxxxx> 1151968725 +0200' test_atom tag taggername 'C O Mitter' test_atom tag taggeremail '<committer@xxxxxxxxxxx>' +test_atom tag taggeremail:trim 'committer@xxxxxxxxxxx' +test_atom tag taggeremail:localpart 'committer' test_atom tag taggerdate 'Tue Jul 4 01:18:45 2006 +0200' test_atom tag creator 'C O Mitter <committer@xxxxxxxxxxx> 1151968725 +0200' test_atom tag creatordate 'Tue Jul 4 01:18:45 2006 +0200' @@ -564,10 +576,14 @@ test_atom refs/tags/taggerless tag 'taggerless' test_atom refs/tags/taggerless tagger '' test_atom refs/tags/taggerless taggername '' test_atom refs/tags/taggerless taggeremail '' +test_atom refs/tags/taggerless taggeremail:trim '' +test_atom refs/tags/taggerless taggeremail:localpart '' test_atom refs/tags/taggerless taggerdate '' test_atom refs/tags/taggerless committer '' test_atom refs/tags/taggerless committername '' test_atom refs/tags/taggerless committeremail '' +test_atom refs/tags/taggerless committeremail:trim '' +test_atom refs/tags/taggerless committeremail:localpart '' test_atom refs/tags/taggerless committerdate '' test_atom refs/tags/taggerless subject 'Broken tag' -- gitgitgadget