diff --git a/builtin/commit.c b/builtin/commit.c index 6c09857a60..22ba54f9bb 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -70,7 +70,6 @@ static const char *logfile, *force_author; static const char *template_file; static char *edit_message, *use_message; static char *fixup_message, *squash_message; -static char *author_name, *author_email, *author_date; static int all, edit_flag, also, interactive, only, amend, signoff; static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship; static int no_post_rewrite, allow_empty_message; @@ -462,7 +461,7 @@ static int is_a_merge(const unsigned char *sha1) static const char sign_off_header[] = "Signed-off-by: "; -static void determine_author_info(void) +static void determine_author_info(struct strbuf *author_ident) { char *name, *email, *date; @@ -506,10 +505,8 @@ static void determine_author_info(void) if (force_date) date = force_date; - - author_name = name; - author_email = email; - author_date = date; + strbuf_addstr(author_ident, fmt_ident(name, email, date, + IDENT_ERROR_ON_NO_NAME)); } static int ends_rfc2822_footer(struct strbuf *sb) @@ -553,10 +550,21 @@ static int ends_rfc2822_footer(struct strbuf *sb) return 1; } +static char *cut_ident_timestamp_part(char *string) +{ + char *ket = strrchr(string, '>'); + if (!ket || ket[1] != ' ') + die("Malformed ident string: '%s'", string); + *++ket = '\0'; + return ket; +} + static int prepare_to_commit(const char *index_file, const char *prefix, - struct wt_status *s) + struct wt_status *s, + struct strbuf *author_ident) { struct stat statbuf; + struct strbuf committer_ident = STRBUF_INIT; int commitable, saved_color_setting; struct strbuf sb = STRBUF_INIT; char *buffer; @@ -679,14 +687,13 @@ static int prepare_to_commit(const char *index_file, const char *prefix, strbuf_release(&sb); - determine_author_info(); + /* This checks and barfs if author is badly specified */ + determine_author_info(author_ident); /* This checks if committer ident is explicitly given */ - git_committer_info(0); + strbuf_addstr(&committer_ident, git_committer_info(0)); if (use_editor && include_status) { - char *author_ident; - const char *committer_ident; - + char *ai_tmp, *ci_tmp; if (in_merge) fprintf(fp, "#\n" @@ -714,23 +721,21 @@ static int prepare_to_commit(const char *index_file, const char *prefix, if (only_include_assumed) fprintf(fp, "# %s\n", only_include_assumed); - author_ident = xstrdup(fmt_name(author_name, author_email)); - committer_ident = fmt_name(getenv("GIT_COMMITTER_NAME"), - getenv("GIT_COMMITTER_EMAIL")); - if (strcmp(author_ident, committer_ident)) + ai_tmp = cut_ident_timestamp_part(author_ident->buf); + ci_tmp = cut_ident_timestamp_part(committer_ident.buf); + if (strcmp(author_ident->buf, committer_ident.buf)) fprintf(fp, "%s" "# Author: %s\n", ident_shown++ ? "" : "#\n", - author_ident); - free(author_ident); + author_ident->buf); if (!user_ident_sufficiently_given()) fprintf(fp, "%s" "# Committer: %s\n", ident_shown++ ? "" : "#\n", - committer_ident); + committer_ident.buf); if (ident_shown) fprintf(fp, "#\n"); @@ -739,6 +744,9 @@ static int prepare_to_commit(const char *index_file, const char *prefix, s->use_color = 0; commitable = run_status(fp, index_file, prefix, 1, s); s->use_color = saved_color_setting; + + *ai_tmp = ' '; + *ci_tmp = ' '; } else { unsigned char sha1[20]; const char *parent = "HEAD"; @@ -754,6 +762,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, else commitable = index_differs_from(parent, 0); } + strbuf_release(&committer_ident); fclose(fp); @@ -1278,6 +1287,7 @@ static int run_rewrite_hook(const unsigned char *oldsha1, int cmd_commit(int argc, const char **argv, const char *prefix) { struct strbuf sb = STRBUF_INIT; + struct strbuf author_ident = STRBUF_INIT; const char *index_file, *reflog_msg; char *nl, *p; unsigned char commit_sha1[20]; @@ -1308,7 +1318,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) /* Set up everything for writing the commit object. This includes running hooks, writing the trees, and interacting with the user. */ - if (!prepare_to_commit(index_file, prefix, &s)) { + if (!prepare_to_commit(index_file, prefix, &s, &author_ident)) { rollback_index_files(); return 1; } @@ -1387,11 +1397,11 @@ int cmd_commit(int argc, const char **argv, const char *prefix) } if (commit_tree(sb.buf, active_cache_tree->sha1, parents, commit_sha1, - fmt_ident(author_name, author_email, author_date, - IDENT_ERROR_ON_NO_NAME))) { + author_ident.buf)) { rollback_index_files(); die("failed to write commit object"); } + strbuf_release(&author_ident); ref_lock = lock_any_ref_for_update("HEAD", initial_commit ? NULL : head_sha1, diff --git a/ident.c b/ident.c index 9e2438826d..1c4adb0a9a 100644 --- a/ident.c +++ b/ident.c @@ -217,8 +217,10 @@ const char *fmt_ident(const char *name, const char *email, } strcpy(date, git_default_date); - if (!name_addr_only && date_str) - parse_date(date_str, date, sizeof(date)); + if (!name_addr_only && date_str && date_str[0]) { + if (parse_date(date_str, date, sizeof(date)) < 0) + die("invalid date format: %s", date_str); + } i = copy(buffer, sizeof(buffer), 0, name); i = add_raw(buffer, sizeof(buffer), i, " <"); diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh index 8297cb4f1e..8980738c75 100755 --- a/t/t7501-commit.sh +++ b/t/t7501-commit.sh @@ -230,6 +230,10 @@ test_expect_success 'amend commit to fix date' ' ' +test_expect_success 'commit complains about bogus date' ' + test_must_fail git commit --amend --date=10.11.2010 +' + test_expect_success 'sign off (1)' ' echo 1 >positive &&