When core.commentChar is "auto", the comment char starts with '#' as in default but if it's already in the prepared message, find another char in a small subset. This should stop surprises because git strips some lines unexpectedly. Note that git is not smart enough to recognize '#' as the comment char in custom templates and convert it if the final comment char is different. It thinks '#' lines in custom templates as part of the commit message. So don't use this with custom templates. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- Documentation/config.txt | 3 +++ builtin/commit.c | 32 ++++++++++++++++++++++++++++++++ cache.h | 1 + config.c | 3 +++ environment.c | 1 + t/t7502-commit.sh | 26 ++++++++++++++++++++++++++ 6 files changed, 66 insertions(+) diff --git a/Documentation/config.txt b/Documentation/config.txt index 1932e9b..9f3ce06 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 9cfef6c..515c4c4 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -594,6 +594,36 @@ static char *cut_ident_timestamp_part(char *string) return ket; } +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, @@ -748,6 +778,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 107ac61..646fb81 100644 --- a/cache.h +++ b/cache.h @@ -602,6 +602,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 491a905..d29c733 100644 --- a/config.c +++ b/config.c @@ -828,8 +828,11 @@ static int git_default_core_config(const char *var, const char *value) int ret = git_config_string(&comment, var, value); 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]; + auto_comment_line_char = 0; } else return error("core.commentChar should only be one character"); return 0; diff --git a/environment.c b/environment.c index 5c4815d..f2de1ee 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 9a3f3a1..30e4688 100755 --- a/t/t7502-commit.sh +++ b/t/t7502-commit.sh @@ -563,4 +563,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 -- 1.9.1.346.ga2b5940 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html