commit: pass author/committer info to hooks

When lying the author name via GIT_AUTHOR_NAME environment variable to "git commit", the hooks run by the command saw it and could act on the name that will be recorded in the final commit. When the user uses the "--author" option from the command line, the command should give the same information to the hook, and back when "git command" was a scripted Porcelain, it did set the environment variable and hooks can learn the author name from it. However, when the command was reimplemented in C, the rewritten code was not very faithful to the original, and hooks stopped getting the authorship information given with "--author". Fix this by exporting the necessary environment variables. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Mar 11, 2012 at 03:12 UTC 7dfe8ad6006c105989e4e8cfb196aa4ecda3c21d
2 files changed +20 -4
builtin/commit.c
+19 -3
@@ -533,9 +533,20 @@ static int is_a_merge(const struct commit *current_head)
533
534 static const char sign_off_header[] = "Signed-off-by: ";
535
536 +static void export_one(const char *var, const char *s, const char *e, int hack)
537 +{
538 + struct strbuf buf = STRBUF_INIT;
539 + if (hack)
540 + strbuf_addch(&buf, hack);
541 + strbuf_addf(&buf, "%.*s", (int)(e - s), s);
542 + setenv(var, buf.buf, 1);
543 + strbuf_release(&buf);
544 +}
545 +
546 static void determine_author_info(struct strbuf *author_ident)
547 {
548 char *name, *email, *date;
549 + struct ident_split author;
550
551 name = getenv("GIT_AUTHOR_NAME");
552 email = getenv("GIT_AUTHOR_EMAIL");
@@ -585,6 +596,11 @@ static void determine_author_info(struct strbuf *author_ident)
596 date = force_date;
597 strbuf_addstr(author_ident, fmt_ident(name, email, date,
598 IDENT_ERROR_ON_NO_NAME));
599 + if (!split_ident_line(&author, author_ident->buf, author_ident->len)) {
600 + export_one("GIT_AUTHOR_NAME", author.name_begin, author.name_end, 0);
601 + export_one("GIT_AUTHOR_EMAIL", author.mail_begin, author.mail_end, 0);
602 + export_one("GIT_AUTHOR_DATE", author.date_begin, author.tz_end, '@');
603 + }
604 }
605
606 static int ends_rfc2822_footer(struct strbuf *sb)
@@ -652,6 +668,9 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
668 int ident_shown = 0;
669 int clean_message_contents = (cleanup_mode != CLEANUP_NONE);
670
671 + /* This checks and barfs if author is badly specified */
672 + determine_author_info(author_ident);
673 +
674 if (!no_verify && run_hook(index_file, "pre-commit", NULL))
675 return 0;
676
@@ -771,9 +790,6 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
790
791 strbuf_release(&sb);
792
774 - /* This checks and barfs if author is badly specified */
775 - determine_author_info(author_ident);
776 -
793 /* This checks if committer ident is explicitly given */
794 strbuf_addstr(&committer_ident, git_committer_info(0));
795 if (use_editor && include_status) {
t/t7503-pre-commit-hook.sh
+1 -1
@@ -118,7 +118,7 @@ test_expect_success 'with failing hook requiring GIT_PREFIX' '
118 git checkout -- file
119 '
120
121 -test_expect_failure 'check the author in hook' '
121 +test_expect_success 'check the author in hook' '
122 write_script "$HOOK" <<-\EOF &&
123 test "$GIT_AUTHOR_NAME" = "New Author" &&
124 test "$GIT_AUTHOR_EMAIL" = "newauthor@example.com"