Merge branch 'jc/commit-unedited-template' into maint
authorJunio C Hamano <gitster@pobox.com>
Thu, 26 Apr 2012 17:35:15 +0000 (10:35 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 26 Apr 2012 17:35:15 +0000 (10:35 -0700)
When "git commit --template F" errors out because the user did not
touch the message, it claimed that it aborts due to "empty message",
which was utterly wrong.

By Junio C Hamano (4) and Adam Monsen (1)
* jc/commit-unedited-template:
Documentation/git-commit: rephrase the "initial-ness" of templates
git-commit.txt: clarify -t requires editing message
commit: rephrase the error when user did not touch templated log message
commit: do not trigger bogus "has templated message edited" check
t7501: test the right kind of breakage

1  2 
builtin/commit.c
diff --combined builtin/commit.c
index 7808be30e181e9cc4f031cdfea3b155f32970da8,847d3635984e5def562b94fa10606638da8a058e..b257ae87740fb0887d285e88476a6ba423e6c25c
@@@ -196,16 -196,16 +196,16 @@@ static void determine_whence(struct wt_
  
  static const char *whence_s(void)
  {
 -      char *s = "";
 +      const char *s = "";
  
        switch (whence) {
        case FROM_COMMIT:
                break;
        case FROM_MERGE:
 -              s = "merge";
 +              s = _("merge");
                break;
        case FROM_CHERRY_PICK:
 -              s = "cherry-pick";
 +              s = _("cherry-pick");
                break;
        }
  
@@@ -400,7 -400,7 +400,7 @@@ static char *prepare_index(int argc, co
                fd = hold_locked_index(&index_lock, 1);
                add_files_to_cache(also ? prefix : NULL, pathspec, 0);
                refresh_cache_or_die(refresh_flags);
 -              update_main_cache_tree(1);
 +              update_main_cache_tree(WRITE_TREE_SILENT);
                if (write_cache(fd, active_cache, active_nr) ||
                    close_lock_file(&index_lock))
                        die(_("unable to write new_index file"));
                fd = hold_locked_index(&index_lock, 1);
                refresh_cache_or_die(refresh_flags);
                if (active_cache_changed) {
 -                      update_main_cache_tree(1);
 +                      update_main_cache_tree(WRITE_TREE_SILENT);
                        if (write_cache(fd, active_cache, active_nr) ||
                            commit_locked_index(&index_lock))
                                die(_("unable to write new_index file"));
@@@ -533,20 -533,9 +533,20 @@@ static int is_a_merge(const struct comm
  
  static const char sign_off_header[] = "Signed-off-by: ";
  
 +static void export_one(const char *var, const char *s, const char *e, int hack)
 +{
 +      struct strbuf buf = STRBUF_INIT;
 +      if (hack)
 +              strbuf_addch(&buf, hack);
 +      strbuf_addf(&buf, "%.*s", (int)(e - s), s);
 +      setenv(var, buf.buf, 1);
 +      strbuf_release(&buf);
 +}
 +
  static void determine_author_info(struct strbuf *author_ident)
  {
        char *name, *email, *date;
 +      struct ident_split author;
  
        name = getenv("GIT_AUTHOR_NAME");
        email = getenv("GIT_AUTHOR_EMAIL");
  
        if (author_message) {
                const char *a, *lb, *rb, *eol;
 +              size_t len;
  
                a = strstr(author_message_buffer, "\nauthor ");
                if (!a)
                                         (a + strlen("\nauthor "))));
                email = xmemdupz(lb + strlen("<"), rb - (lb + strlen("<")));
                date = xmemdupz(rb + strlen("> "), eol - (rb + strlen("> ")));
 +              len = eol - (rb + strlen("> "));
 +              date = xmalloc(len + 2);
 +              *date = '@';
 +              memcpy(date + 1, rb + strlen("> "), len);
 +              date[len + 1] = '\0';
        }
  
        if (force_author) {
                date = force_date;
        strbuf_addstr(author_ident, fmt_ident(name, email, date,
                                              IDENT_ERROR_ON_NO_NAME));
 +      if (!split_ident_line(&author, author_ident->buf, author_ident->len)) {
 +              export_one("GIT_AUTHOR_NAME", author.name_begin, author.name_end, 0);
 +              export_one("GIT_AUTHOR_EMAIL", author.mail_begin, author.mail_end, 0);
 +              export_one("GIT_AUTHOR_DATE", author.date_begin, author.tz_end, '@');
 +      }
  }
  
  static int ends_rfc2822_footer(struct strbuf *sb)
@@@ -668,9 -646,6 +668,9 @@@ static int prepare_to_commit(const cha
        int ident_shown = 0;
        int clean_message_contents = (cleanup_mode != CLEANUP_NONE);
  
 +      /* This checks and barfs if author is badly specified */
 +      determine_author_info(author_ident);
 +
        if (!no_verify && run_hook(index_file, "pre-commit", NULL))
                return 0;
  
  
        strbuf_release(&sb);
  
 -      /* This checks and barfs if author is badly specified */
 -      determine_author_info(author_ident);
 -
        /* This checks if committer ident is explicitly given */
        strbuf_addstr(&committer_ident, git_committer_info(0));
        if (use_editor && include_status) {
        return 1;
  }
  
- /*
-  * Find out if the message in the strbuf contains only whitespace and
-  * Signed-off-by lines.
-  */
- static int message_is_empty(struct strbuf *sb)
+ static int rest_is_empty(struct strbuf *sb, int start)
  {
-       struct strbuf tmpl = STRBUF_INIT;
+       int i, eol;
        const char *nl;
-       int eol, i, start = 0;
-       if (cleanup_mode == CLEANUP_NONE && sb->len)
-               return 0;
-       /* See if the template is just a prefix of the message. */
-       if (template_file && strbuf_read_file(&tmpl, template_file, 0) > 0) {
-               stripspace(&tmpl, cleanup_mode == CLEANUP_ALL);
-               if (start + tmpl.len <= sb->len &&
-                   memcmp(tmpl.buf, sb->buf + start, tmpl.len) == 0)
-                       start += tmpl.len;
-       }
-       strbuf_release(&tmpl);
  
        /* Check if the rest is just whitespace and Signed-of-by's. */
        for (i = start; i < sb->len; i++) {
        return 1;
  }
  
+ /*
+  * Find out if the message in the strbuf contains only whitespace and
+  * Signed-off-by lines.
+  */
+ static int message_is_empty(struct strbuf *sb)
+ {
+       if (cleanup_mode == CLEANUP_NONE && sb->len)
+               return 0;
+       return rest_is_empty(sb, 0);
+ }
+ /*
+  * See if the user edited the message in the editor or left what
+  * was in the template intact
+  */
+ static int template_untouched(struct strbuf *sb)
+ {
+       struct strbuf tmpl = STRBUF_INIT;
+       char *start;
+       if (cleanup_mode == CLEANUP_NONE && sb->len)
+               return 0;
+       if (!template_file || strbuf_read_file(&tmpl, template_file, 0) <= 0)
+               return 0;
+       stripspace(&tmpl, cleanup_mode == CLEANUP_ALL);
+       start = (char *)skip_prefix(sb->buf, tmpl.buf);
+       if (!start)
+               start = sb->buf;
+       strbuf_release(&tmpl);
+       return rest_is_empty(sb, start - sb->buf);
+ }
  static const char *find_author_by_nickname(const char *name)
  {
        struct rev_info revs;
@@@ -1071,6 -1066,8 +1088,8 @@@ static int parse_and_validate_options(i
                die(_("Only one of -c/-C/-F/--fixup can be used."));
        if (message.len && f > 0)
                die((_("Option -m cannot be combined with -c/-C/-F/--fixup.")));
+       if (f || message.len)
+               template_file = NULL;
        if (edit_message)
                use_message = edit_message;
        if (amend && !use_message && !fixup_message)
@@@ -1510,6 -1507,11 +1529,11 @@@ int cmd_commit(int argc, const char **a
  
        if (cleanup_mode != CLEANUP_NONE)
                stripspace(&sb, cleanup_mode == CLEANUP_ALL);
+       if (template_untouched(&sb) && !allow_empty_message) {
+               rollback_index_files();
+               fprintf(stderr, _("Aborting commit; you did not edit the message.\n"));
+               exit(1);
+       }
        if (message_is_empty(&sb) && !allow_empty_message) {
                rollback_index_files();
                fprintf(stderr, _("Aborting commit due to empty commit message.\n"));