diff --git a/Documentation/config.txt b/Documentation/config.txt index a33c087cb4c448..2e3c6655f0ab45 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -544,6 +544,9 @@ core.commentchar:: messages consider a line that begins with this character commented, and removes them after the editor returns (default '#'). ++ +If set to "auto", `git-commit` would select a character that is not +the beginning character of any line in existing commit messages. sequence.editor:: Text editor used by `git rebase -i` for editing the rebase instruction file. diff --git a/builtin/commit.c b/builtin/commit.c index d28505a857dad9..99c20446352edb 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -620,6 +620,36 @@ static int author_date_is_interesting(void) return author_message || force_date; } +static void adjust_comment_line_char(const struct strbuf *sb) +{ + char candidates[] = "#;@!$%^&|:"; + char *candidate; + const char *p; + + comment_line_char = candidates[0]; + if (!memchr(sb->buf, comment_line_char, sb->len)) + return; + + p = sb->buf; + candidate = strchr(candidates, *p); + if (candidate) + *candidate = ' '; + for (p = sb->buf; *p; p++) { + if ((p[0] == '\n' || p[0] == '\r') && p[1]) { + candidate = strchr(candidates, p[1]); + if (candidate) + *candidate = ' '; + } + } + + for (p = candidates; *p == ' '; p++) + ; + if (!*p) + die(_("unable to select a comment character that is not used\n" + "in the current commit message")); + comment_line_char = *p; +} + static int prepare_to_commit(const char *index_file, const char *prefix, struct commit *current_head, struct wt_status *s, @@ -773,6 +803,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix, if (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len) die_errno(_("could not write commit template")); + if (auto_comment_line_char) + adjust_comment_line_char(&sb); strbuf_release(&sb); /* This checks if committer ident is explicitly given */ diff --git a/cache.h b/cache.h index 8c6cdc29deca2e..1e4b4f06e1ee01 100644 --- a/cache.h +++ b/cache.h @@ -618,6 +618,7 @@ extern int precomposed_unicode; * that is subject to stripspace. */ extern char comment_line_char; +extern int auto_comment_line_char; enum branch_track { BRANCH_TRACK_UNSPECIFIED = -1, diff --git a/config.c b/config.c index c227aa85177724..3c3e31448e5be3 100644 --- a/config.c +++ b/config.c @@ -826,9 +826,16 @@ static int git_default_core_config(const char *var, const char *value) if (!strcmp(var, "core.commentchar")) { const char *comment; int ret = git_config_string(&comment, var, value); - if (!ret) + if (ret) + return ret; + else if (!strcasecmp(comment, "auto")) + auto_comment_line_char = 1; + else if (comment[0] && !comment[1]) { comment_line_char = comment[0]; - return ret; + auto_comment_line_char = 0; + } else + return error("core.commentChar should only be one character"); + return 0; } if (!strcmp(var, "core.askpass")) diff --git a/environment.c b/environment.c index 37354c8d056efc..c648ac3d3af1f8 100644 --- a/environment.c +++ b/environment.c @@ -69,6 +69,7 @@ unsigned long pack_size_limit_cfg; * that is subject to stripspace. */ char comment_line_char = '#'; +int auto_comment_line_char; /* Parallel index stat data preload? */ int core_preload_index = 0; diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh index 6465cd59afb6dc..051489ea334c96 100755 --- a/t/t7502-commit.sh +++ b/t/t7502-commit.sh @@ -570,4 +570,30 @@ test_expect_success 'commit --status with custom comment character' ' test_i18ngrep "^; Changes to be committed:" .git/COMMIT_EDITMSG ' +test_expect_success 'switch core.commentchar' ' + test_commit "#foo" foo && + GIT_EDITOR=.git/FAKE_EDITOR git -c core.commentChar=auto commit --amend && + test_i18ngrep "^; Changes to be committed:" .git/COMMIT_EDITMSG +' + +test_expect_success 'switch core.commentchar but out of options' ' + cat >text <<\EOF && +# 1 +; 2 +@ 3 +! 4 +$ 5 +% 6 +^ 7 +& 8 +| 9 +: 10 +EOF + git commit --amend -F text && + ( + test_set_editor .git/FAKE_EDITOR && + test_must_fail git -c core.commentChar=auto commit --amend + ) +' + test_done diff --git a/t/t7508-status.sh b/t/t7508-status.sh index c987b5ed652b97..148ab9ebc2fe24 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -1350,8 +1350,7 @@ test_expect_success "status (core.commentchar with submodule summary)" ' test_expect_success "status (core.commentchar with two chars with submodule summary)" ' test_config core.commentchar ";;" && - git -c status.displayCommentPrefix=true status >output && - test_i18ncmp expect output + test_must_fail git -c status.displayCommentPrefix=true status ' test_expect_success "--ignore-submodules=all suppresses submodule summary" '