13
#include "oid-array.h"
14
#include "repository.h"
15
#include "commit.h"
16
+#include "mailmap.h"
17
+#include "ident.h"
18
#include "remote.h"
19
#include "color.h"
20
#include "tag.h"
217
struct {
218
enum { O_SIZE, O_SIZE_DISK } option;
219
} objectsize;
218
- struct email_option {
219
- enum { EO_RAW, EO_TRIM, EO_LOCALPART } option;
220
+ struct {
221
+ enum { N_RAW, N_MAILMAP } option;
222
+ } name_option;
223
+ struct {
224
+ enum {
225
+ EO_RAW = 0,
226
+ EO_TRIM = 1<<0,
227
+ EO_LOCALPART = 1<<1,
228
+ EO_MAILMAP = 1<<2,
229
+ } option;
230
} email_option;
231
struct {
232
enum { S_BARE, S_GRADE, S_SIGNER, S_KEY,
730
return 0;
731
}
732
723
-static int person_email_atom_parser(struct ref_format *format UNUSED,
724
- struct used_atom *atom,
725
- const char *arg, struct strbuf *err)
733
+static int person_name_atom_parser(struct ref_format *format UNUSED,
734
+ struct used_atom *atom,
735
+ const char *arg, struct strbuf *err)
736
{
737
if (!arg)
728
- atom->u.email_option.option = EO_RAW;
729
- else if (!strcmp(arg, "trim"))
730
- atom->u.email_option.option = EO_TRIM;
731
- else if (!strcmp(arg, "localpart"))
732
- atom->u.email_option.option = EO_LOCALPART;
738
+ atom->u.name_option.option = N_RAW;
739
+ else if (!strcmp(arg, "mailmap"))
740
+ atom->u.name_option.option = N_MAILMAP;
741
else
742
return err_bad_arg(err, atom->name, arg);
743
return 0;
744
}
745
746
+static int email_atom_option_parser(struct used_atom *atom,
747
+ const char **arg, struct strbuf *err)
748
+{
749
+ if (!*arg)
750
+ return EO_RAW;
751
+ if (skip_prefix(*arg, "trim", arg))
752
+ return EO_TRIM;
753
+ if (skip_prefix(*arg, "localpart", arg))
754
+ return EO_LOCALPART;
755
+ if (skip_prefix(*arg, "mailmap", arg))
756
+ return EO_MAILMAP;
757
+ return -1;
758
+}
759
+
760
+static int person_email_atom_parser(struct ref_format *format UNUSED,
761
+ struct used_atom *atom,
762
+ const char *arg, struct strbuf *err)
763
+{
764
+ for (;;) {
765
+ int opt = email_atom_option_parser(atom, &arg, err);
766
+ const char *bad_arg = arg;
767
+
768
+ if (opt < 0)
769
+ return err_bad_arg(err, atom->name, bad_arg);
770
+ atom->u.email_option.option |= opt;
771
+
772
+ if (!arg || !*arg)
773
+ break;
774
+ if (*arg == ',')
775
+ arg++;
776
+ else
777
+ return err_bad_arg(err, atom->name, bad_arg);
778
+ }
779
+ return 0;
780
+}
781
+
782
static int refname_atom_parser(struct ref_format *format UNUSED,
783
struct used_atom *atom,
784
const char *arg, struct strbuf *err)
921
[ATOM_TYPE] = { "type", SOURCE_OBJ },
922
[ATOM_TAG] = { "tag", SOURCE_OBJ },
923
[ATOM_AUTHOR] = { "author", SOURCE_OBJ },
880
- [ATOM_AUTHORNAME] = { "authorname", SOURCE_OBJ },
924
+ [ATOM_AUTHORNAME] = { "authorname", SOURCE_OBJ, FIELD_STR, person_name_atom_parser },
925
[ATOM_AUTHOREMAIL] = { "authoremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
926
[ATOM_AUTHORDATE] = { "authordate", SOURCE_OBJ, FIELD_TIME },
927
[ATOM_COMMITTER] = { "committer", SOURCE_OBJ },
884
- [ATOM_COMMITTERNAME] = { "committername", SOURCE_OBJ },
928
+ [ATOM_COMMITTERNAME] = { "committername", SOURCE_OBJ, FIELD_STR, person_name_atom_parser },
929
[ATOM_COMMITTEREMAIL] = { "committeremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
930
[ATOM_COMMITTERDATE] = { "committerdate", SOURCE_OBJ, FIELD_TIME },
931
[ATOM_TAGGER] = { "tagger", SOURCE_OBJ },
888
- [ATOM_TAGGERNAME] = { "taggername", SOURCE_OBJ },
932
+ [ATOM_TAGGERNAME] = { "taggername", SOURCE_OBJ, FIELD_STR, person_name_atom_parser },
933
[ATOM_TAGGEREMAIL] = { "taggeremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser },
934
[ATOM_TAGGERDATE] = { "taggerdate", SOURCE_OBJ, FIELD_TIME },
935
[ATOM_CREATOR] = { "creator", SOURCE_OBJ },
1530
return xstrdup("");
1531
}
1532
1533
+static const char *find_end_of_email(const char *email, int opt)
1534
+{
1535
+ const char *eoemail;
1536
+
1537
+ if (opt & EO_LOCALPART) {
1538
+ eoemail = strchr(email, '@');
1539
+ if (eoemail)
1540
+ return eoemail;
1541
+ return strchr(email, '>');
1542
+ }
1543
+
1544
+ if (opt & EO_TRIM)
1545
+ return strchr(email, '>');
1546
+
1547
+ /*
1548
+ * The option here is either the raw email option or the raw
1549
+ * mailmap option (that is EO_RAW or EO_MAILMAP). In such cases,
1550
+ * we directly grab the whole email including the closing
1551
+ * angle brackets.
1552
+ *
1553
+ * If EO_MAILMAP was set with any other option (that is either
1554
+ * EO_TRIM or EO_LOCALPART), we already grab the end of email
1555
+ * above.
1556
+ */
1557
+ eoemail = strchr(email, '>');
1558
+ if (eoemail)
1559
+ eoemail++;
1560
+ return eoemail;
1561
+}
1562
+
1563
static const char *copy_email(const char *buf, struct used_atom *atom)
1564
{
1565
const char *email = strchr(buf, '<');
1566
const char *eoemail;
1567
+ int opt = atom->u.email_option.option;
1568
+
1569
if (!email)
1570
return xstrdup("");
1495
- switch (atom->u.email_option.option) {
1496
- case EO_RAW:
1497
- eoemail = strchr(email, '>');
1498
- if (eoemail)
1499
- eoemail++;
1500
- break;
1501
- case EO_TRIM:
1502
- email++;
1503
- eoemail = strchr(email, '>');
1504
- break;
1505
- case EO_LOCALPART:
1571
+
1572
+ if (opt & (EO_LOCALPART | EO_TRIM))
1573
email++;
1507
- eoemail = strchr(email, '@');
1508
- if (!eoemail)
1509
- eoemail = strchr(email, '>');
1510
- break;
1511
- default:
1512
- BUG("unknown email option");
1513
- }
1574
1575
+ eoemail = find_end_of_email(email, opt);
1576
if (!eoemail)
1577
return xstrdup("");
1578
return xmemdupz(email, eoemail - email);
1633
v->value = 0;
1634
}
1635
1636
+static struct string_list mailmap = STRING_LIST_INIT_NODUP;
1637
+
1638
/* See grab_values */
1639
static void grab_person(const char *who, struct atom_value *val, int deref, void *buf)
1640
{
1641
int i;
1642
int wholen = strlen(who);
1643
const char *wholine = NULL;
1644
+ const char *headers[] = { "author ", "committer ",
1645
+ "tagger ", NULL };
1646
1647
for (i = 0; i < used_atom_cnt; i++) {
1583
- const char *name = used_atom[i].name;
1648
+ struct used_atom *atom = &used_atom[i];
1649
+ const char *name = atom->name;
1650
struct atom_value *v = &val[i];
1651
+ struct strbuf mailmap_buf = STRBUF_INIT;
1652
+
1653
if (!!deref != (*name == '*'))
1654
continue;
1655
if (deref)
1657
if (strncmp(who, name, wholen))
1658
continue;
1659
if (name[wholen] != 0 &&
1592
- strcmp(name + wholen, "name") &&
1660
+ !starts_with(name + wholen, "name") &&
1661
!starts_with(name + wholen, "email") &&
1662
!starts_with(name + wholen, "date"))
1663
continue;
1596
- if (!wholine)
1664
+
1665
+ if ((starts_with(name + wholen, "name") &&
1666
+ (atom->u.name_option.option == N_MAILMAP)) ||
1667
+ (starts_with(name + wholen, "email") &&
1668
+ (atom->u.email_option.option & EO_MAILMAP))) {
1669
+ if (!mailmap.items)
1670
+ read_mailmap(&mailmap);
1671
+ strbuf_addstr(&mailmap_buf, buf);
1672
+ apply_mailmap_to_header(&mailmap_buf, headers, &mailmap);
1673
+ wholine = find_wholine(who, wholen, mailmap_buf.buf);
1674
+ } else {
1675
wholine = find_wholine(who, wholen, buf);
1676
+ }
1677
+
1678
if (!wholine)
1679
return; /* no point looking for it */
1680
if (name[wholen] == 0)
1681
v->s = copy_line(wholine);
1602
- else if (!strcmp(name + wholen, "name"))
1682
+ else if (starts_with(name + wholen, "name"))
1683
v->s = copy_name(wholine);
1684
else if (starts_with(name + wholen, "email"))
1685
v->s = copy_email(wholine, &used_atom[i]);
1686
else if (starts_with(name + wholen, "date"))
1687
grab_date(wholine, v, name);
1688
+
1689
+ strbuf_release(&mailmap_buf);
1690
}
1691
1692
/*