{"thread":{"id":"34426","subject":"[PATCH v3 0/2] add git-check-mailmap command","startedAt":"2013-07-13T00:53:09Z","lastAt":"2013-07-13T00:53:11Z","messageCount":3,"participants":["Eric Sunshine"],"isPatch":true,"patchVersion":3,"patchTotal":2},"messages":[{"id":"223234","messageId":"1373676791-42758-1-git-send-email-sunshine@sunshineco.com","threadId":"34426","inReplyTo":null,"subject":"[PATCH v3 0/2] add git-check-mailmap command","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2013-07-13T00:53:09Z","receivedAt":"2013-07-13T00:53:09Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"This is a re-roll of v2 [1] which introduces git-check-mailmap. The\nprimary motivation for this command is to expose git's stable,\nwell-tested C-implementation of .mailmap functionality to scripts and\nporcelains, thus relieving them of the need to re-implement support\nthemselves. The git-contacts [2] script (currently at es/contacts in\n'pu') would be one such client.\n\nv3 addresses comments from reviewers [1].\n\nChanges since v2:\n\n* Drop -z/--null option.\n\n* Simplify grammar of DESCRIPTION and OUTPUT sections of\n  Documentation/git-check-mailmap.txt.\n\n* Normalize wrapped code indentation to match standard Git style.\n\n* Drop v2 patches [3/4] and [4/4] which convert t4203-mailmap.sh to test\n  low-level mailmap functionality directly via git-check-mailmap rather\n  than indirectly via git-shortlog.\n\n[1]: http://thread.gmane.org/gmane.comp.version-control.git/230105/\n[2]: http://thread.gmane.org/gmane.comp.version-control.git/229533/\n\nEric Sunshine (2):\n  builtin: add git-check-mailmap command\n  t4203: test check-mailmap command invocation\n\n .gitignore                             |  1 +\n Documentation/git-check-mailmap.txt    | 47 ++++++++++++++++++++++++\n Makefile                               |  1 +\n builtin.h                              |  1 +\n builtin/check-mailmap.c                | 66 ++++++++++++++++++++++++++++++++++\n command-list.txt                       |  1 +\n contrib/completion/git-completion.bash |  1 +\n git.c                                  |  1 +\n t/t4203-mailmap.sh                     | 43 ++++++++++++++++++++++\n 9 files changed, 162 insertions(+)\n create mode 100644 Documentation/git-check-mailmap.txt\n create mode 100644 builtin/check-mailmap.c\n\n-- \n1.8.3.2.804.g0da7a53\n"},{"id":"223236","messageId":"1373676791-42758-2-git-send-email-sunshine@sunshineco.com","threadId":"34426","inReplyTo":"1373676791-42758-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 1/2] builtin: add git-check-mailmap command","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2013-07-13T00:53:10Z","receivedAt":"2013-07-13T00:53:10Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"Introduce command check-mailmap, similar to check-attr and check-ignore,\nwhich allows direct testing of .mailmap configuration.\n\nAs plumbing accessible to scripts and other porcelain, check-mailmap\npublishes the stable, well-tested .mailmap functionality employed by\nbuilt-in Git commands.  Consequently, script authors need not\nre-implement .mailmap functionality manually, thus avoiding potential\nquirks and behavioral differences.\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n .gitignore                             |  1 +\n Documentation/git-check-mailmap.txt    | 47 ++++++++++++++++++++++++\n Makefile                               |  1 +\n builtin.h                              |  1 +\n builtin/check-mailmap.c                | 66 ++++++++++++++++++++++++++++++++++\n command-list.txt                       |  1 +\n contrib/completion/git-completion.bash |  1 +\n git.c                                  |  1 +\n 8 files changed, 119 insertions(+)\n create mode 100644 Documentation/git-check-mailmap.txt\n create mode 100644 builtin/check-mailmap.c\n\ndiff --git a/.gitignore b/.gitignore\nindex efa8db0..6b1fd1b 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -23,6 +23,7 @@\n /git-cat-file\n /git-check-attr\n /git-check-ignore\n+/git-check-mailmap\n /git-check-ref-format\n /git-checkout\n /git-checkout-index\ndiff --git a/Documentation/git-check-mailmap.txt b/Documentation/git-check-mailmap.txt\nnew file mode 100644\nindex 0000000..39028ee\n--- /dev/null\n+++ b/Documentation/git-check-mailmap.txt\n@@ -0,0 +1,47 @@\n+git-check-mailmap(1)\n+====================\n+\n+NAME\n+----\n+git-check-mailmap - Show canonical names and email addresses of contacts\n+\n+\n+SYNOPSIS\n+--------\n+[verse]\n+'git check-mailmap' [options] <contact>...\n+\n+\n+DESCRIPTION\n+-----------\n+\n+For each ``Name $$<user@host>$$'' or ``$$<user@host>$$'' from the command-line\n+or standard input (when using `--stdin`), look up the person's canonical name\n+and email address (see \"Mapping Authors\" below). If found, print them;\n+otherwise print the input as-is.\n+\n+\n+OPTIONS\n+-------\n+--stdin::\n+\tRead contacts, one per line, from the standard input after exhausting\n+\tcontacts provided on the command-line.\n+\n+\n+OUTPUT\n+------\n+\n+For each contact, a single line is output, terminated by a newline.  If the\n+name is provided or known to the 'mailmap', ``Name $$<user@host>$$'' is\n+printed; otherwise only ``$$<user@host>$$'' is printed.\n+\n+\n+MAPPING AUTHORS\n+---------------\n+\n+include::mailmap.txt[]\n+\n+\n+GIT\n+---\n+Part of the linkgit:git[1] suite\ndiff --git a/Makefile b/Makefile\nindex 0600eb4..ef442eb 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -912,6 +912,7 @@ BUILTIN_OBJS += builtin/bundle.o\n BUILTIN_OBJS += builtin/cat-file.o\n BUILTIN_OBJS += builtin/check-attr.o\n BUILTIN_OBJS += builtin/check-ignore.o\n+BUILTIN_OBJS += builtin/check-mailmap.o\n BUILTIN_OBJS += builtin/check-ref-format.o\n BUILTIN_OBJS += builtin/checkout-index.o\n BUILTIN_OBJS += builtin/checkout.o\ndiff --git a/builtin.h b/builtin.h\nindex 1ed8edb..8afa2de 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -40,6 +40,7 @@ extern int cmd_checkout(int argc, const char **argv, const char *prefix);\n extern int cmd_checkout_index(int argc, const char **argv, const char *prefix);\n extern int cmd_check_attr(int argc, const char **argv, const char *prefix);\n extern int cmd_check_ignore(int argc, const char **argv, const char *prefix);\n+extern int cmd_check_mailmap(int argc, const char **argv, const char *prefix);\n extern int cmd_check_ref_format(int argc, const char **argv, const char *prefix);\n extern int cmd_cherry(int argc, const char **argv, const char *prefix);\n extern int cmd_cherry_pick(int argc, const char **argv, const char *prefix);\ndiff --git a/builtin/check-mailmap.c b/builtin/check-mailmap.c\nnew file mode 100644\nindex 0000000..8f4d809\n--- /dev/null\n+++ b/builtin/check-mailmap.c\n@@ -0,0 +1,66 @@\n+#include \"builtin.h\"\n+#include \"mailmap.h\"\n+#include \"parse-options.h\"\n+#include \"string-list.h\"\n+\n+static int use_stdin;\n+static const char * const check_mailmap_usage[] = {\n+N_(\"git check-mailmap [options] <contact>...\"),\n+NULL\n+};\n+\n+static const struct option check_mailmap_options[] = {\n+\tOPT_BOOL(0, \"stdin\", &use_stdin, N_(\"also read contacts from stdin\")),\n+\tOPT_END()\n+};\n+\n+static void check_mailmap(struct string_list *mailmap, const char *contact)\n+{\n+\tconst char *name, *mail;\n+\tsize_t namelen, maillen;\n+\tstruct ident_split ident;\n+\n+\tif (split_ident_line(&ident, contact, strlen(contact)))\n+\t\tdie(_(\"unable to parse contact: %s\"), contact);\n+\n+\tname = ident.name_begin;\n+\tnamelen = ident.name_end - ident.name_begin;\n+\tmail = ident.mail_begin;\n+\tmaillen = ident.mail_end - ident.mail_begin;\n+\n+\tmap_user(mailmap, &mail, &maillen, &name, &namelen);\n+\n+\tif (namelen)\n+\t\tprintf(\"%.*s \", (int)namelen, name);\n+\tprintf(\"<%.*s>\\n\", (int)maillen, mail);\n+}\n+\n+int cmd_check_mailmap(int argc, const char **argv, const char *prefix)\n+{\n+\tint i;\n+\tstruct string_list mailmap = STRING_LIST_INIT_NODUP;\n+\n+\tgit_config(git_default_config, NULL);\n+\targc = parse_options(argc, argv, prefix, check_mailmap_options,\n+\t\t\t     check_mailmap_usage, 0);\n+\tif (argc == 0 && !use_stdin)\n+\t\tdie(_(\"no contacts specified\"));\n+\n+\tread_mailmap(&mailmap, NULL);\n+\n+\tfor (i = 0; i < argc; ++i)\n+\t\tcheck_mailmap(&mailmap, argv[i]);\n+\tmaybe_flush_or_die(stdout, \"stdout\");\n+\n+\tif (use_stdin) {\n+\t\tstruct strbuf buf = STRBUF_INIT;\n+\t\twhile (strbuf_getline(&buf, stdin, '\\n') != EOF) {\n+\t\t\tcheck_mailmap(&mailmap, buf.buf);\n+\t\t\tmaybe_flush_or_die(stdout, \"stdout\");\n+\t\t}\n+\t\tstrbuf_release(&buf);\n+\t}\n+\n+\tclear_mailmap(&mailmap);\n+\treturn 0;\n+}\ndiff --git a/command-list.txt b/command-list.txt\nindex bf83303..08b04e2 100644\n--- a/command-list.txt\n+++ b/command-list.txt\n@@ -13,6 +13,7 @@ git-bundle                              mainporcelain\n git-cat-file                            plumbinginterrogators\n git-check-attr                          purehelpers\n git-check-ignore                        purehelpers\n+git-check-mailmap                       purehelpers\n git-checkout                            mainporcelain common\n git-checkout-index                      plumbingmanipulators\n git-check-ref-format                    purehelpers\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex fa3ae1e..cd509a5 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -648,6 +648,7 @@ __git_list_porcelain_commands ()\n \t\tcat-file)         : plumbing;;\n \t\tcheck-attr)       : plumbing;;\n \t\tcheck-ignore)     : plumbing;;\n+\t\tcheck-mailmap)    : plumbing;;\n \t\tcheck-ref-format) : plumbing;;\n \t\tcheckout-index)   : plumbing;;\n \t\tcommit-tree)      : plumbing;;\ndiff --git a/git.c b/git.c\nindex 4359086..02c3035 100644\n--- a/git.c\n+++ b/git.c\n@@ -324,6 +324,7 @@ static void handle_internal_command(int argc, const char **argv)\n \t\t{ \"cat-file\", cmd_cat_file, RUN_SETUP },\n \t\t{ \"check-attr\", cmd_check_attr, RUN_SETUP },\n \t\t{ \"check-ignore\", cmd_check_ignore, RUN_SETUP | NEED_WORK_TREE },\n+\t\t{ \"check-mailmap\", cmd_check_mailmap, RUN_SETUP },\n \t\t{ \"check-ref-format\", cmd_check_ref_format },\n \t\t{ \"checkout\", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },\n \t\t{ \"checkout-index\", cmd_checkout_index,\n-- \n1.8.3.2.804.g0da7a53\n"},{"id":"223235","messageId":"1373676791-42758-3-git-send-email-sunshine@sunshineco.com","threadId":"34426","inReplyTo":"1373676791-42758-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v3 2/2] t4203: test check-mailmap command invocation","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2013-07-13T00:53:11Z","receivedAt":"2013-07-13T00:53:11Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"Test the command-line interface of check-mailmap.\n\n(Actual .mailmap functionality is already covered by existing tests.)\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n t/t4203-mailmap.sh | 43 +++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 43 insertions(+)\n\ndiff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh\nindex 842b754..b7476f2 100755\n--- a/t/t4203-mailmap.sh\n+++ b/t/t4203-mailmap.sh\n@@ -13,6 +13,11 @@ fuzz_blame () {\n }\n \n test_expect_success setup '\n+\tcat >contacts <<-\\EOF &&\n+\tA U Thor <author@example.com>\n+\tnick1 <bugs@company.xx>\n+\tEOF\n+\n \techo one >one &&\n \tgit add one &&\n \ttest_tick &&\n@@ -23,6 +28,44 @@ test_expect_success setup '\n \tgit commit --author \"nick1 <bugs@company.xx>\" -m second\n '\n \n+test_expect_success 'check-mailmap no arguments' '\n+\ttest_must_fail git check-mailmap\n+'\n+\n+test_expect_success 'check-mailmap arguments' '\n+\tcat >expect <<-\\EOF &&\n+\tA U Thor <author@example.com>\n+\tnick1 <bugs@company.xx>\n+\tEOF\n+\tgit check-mailmap \\\n+\t\t\"A U Thor <author@example.com>\" \\\n+\t\t\"nick1 <bugs@company.xx>\" >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'check-mailmap --stdin' '\n+\tcat >expect <<-\\EOF &&\n+\tA U Thor <author@example.com>\n+\tnick1 <bugs@company.xx>\n+\tEOF\n+\tgit check-mailmap --stdin <contacts >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'check-mailmap --stdin arguments' '\n+\tcat >expect <<-\\EOF &&\n+\tInternal Guy <bugs@company.xy>\n+\tEOF\n+\tcat <contacts >>expect &&\n+\tgit check-mailmap --stdin \"Internal Guy <bugs@company.xy>\" \\\n+\t\t<contacts >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'check-mailmap bogus contact' '\n+\ttest_must_fail git check-mailmap bogus\n+'\n+\n cat >expect <<\\EOF\n A U Thor (1):\n       initial\n-- \n1.8.3.2.804.g0da7a53\n"}]}