{"thread":{"id":"32562","subject":"[PATCH] commit: make default of \"cleanup\" option configurable","startedAt":"2013-01-08T20:16:16Z","lastAt":"2013-01-16T21:02:27Z","messageCount":18,"participants":["Ralf Thielow","Junio C Hamano","Jonathan Nieder","Jens Lehmann"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"206329","messageId":"1357676176-30019-1-git-send-email-ralf.thielow@gmail.com","threadId":"32562","inReplyTo":null,"subject":"[PATCH] commit: make default of \"cleanup\" option configurable","fromName":"Ralf Thielow","fromEmail":"ralf.thielow@gmail.com","sentAt":"2013-01-08T20:16:16Z","receivedAt":"2013-01-08T20:16:16Z","isPatch":true,"sender":{"key":"ralf.thielow@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1275832?v=4"},"body":"The default of the \"cleanup\" option in \"git commit\"\nis not configurable. Users who don't want to use the\ndefault have to pass this option on every commit since\nthere's no way to configure it. This commit introduces\na new config option \"commit.cleanup\" which can be used\nto change the default of the \"cleanup\" option in\n\"git commit\".\n\nSigned-off-by: Ralf Thielow <ralf.thielow@gmail.com>\n---\n Documentation/config.txt |  4 ++++\n builtin/commit.c         | 29 ++++++++++++++++++-----------\n 2 files changed, 22 insertions(+), 11 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 53c4ca1..3f76cd1 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -917,6 +917,10 @@ column.tag::\n \tSpecify whether to output tag listing in `git tag` in columns.\n \tSee `column.ui` for details.\n \n+commit.cleanup::\n+\tThis setting overrides the default of the `--cleanup` option in\n+\t`git commit`. See linkgit:git-commit[1] for details.\n+\n commit.status::\n \tA boolean to enable/disable inclusion of status information in the\n \tcommit message template when using an editor to prepare the commit\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex d6dd3df..42acde7 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -103,7 +103,7 @@ static enum {\n \tCLEANUP_NONE,\n \tCLEANUP_ALL\n } cleanup_mode;\n-static char *cleanup_arg;\n+const static char *cleanup_arg;\n \n static enum commit_whence whence;\n static int use_editor = 1, include_status = 1;\n@@ -966,6 +966,20 @@ static const char *read_commit_message(const char *name)\n \treturn out;\n }\n \n+static void parse_cleanup_arg()\n+{\n+\tif (!cleanup_arg || !strcmp(cleanup_arg, \"default\"))\n+\t\tcleanup_mode = use_editor ? CLEANUP_ALL : CLEANUP_SPACE;\n+\telse if (!strcmp(cleanup_arg, \"verbatim\"))\n+\t\tcleanup_mode = CLEANUP_NONE;\n+\telse if (!strcmp(cleanup_arg, \"whitespace\"))\n+\t\tcleanup_mode = CLEANUP_SPACE;\n+\telse if (!strcmp(cleanup_arg, \"strip\"))\n+\t\tcleanup_mode = CLEANUP_ALL;\n+\telse\n+\t\tdie(_(\"Invalid cleanup mode %s\"), cleanup_arg);\n+}\n+\n static int parse_and_validate_options(int argc, const char *argv[],\n \t\t\t\t      const struct option *options,\n \t\t\t\t      const char * const usage[],\n@@ -1044,18 +1058,9 @@ static int parse_and_validate_options(int argc, const char *argv[],\n \t\tonly_include_assumed = _(\"Clever... amending the last one with dirty index.\");\n \tif (argc > 0 && !also && !only)\n \t\tonly_include_assumed = _(\"Explicit paths specified without -i nor -o; assuming --only paths...\");\n-\tif (!cleanup_arg || !strcmp(cleanup_arg, \"default\"))\n-\t\tcleanup_mode = use_editor ? CLEANUP_ALL : CLEANUP_SPACE;\n-\telse if (!strcmp(cleanup_arg, \"verbatim\"))\n-\t\tcleanup_mode = CLEANUP_NONE;\n-\telse if (!strcmp(cleanup_arg, \"whitespace\"))\n-\t\tcleanup_mode = CLEANUP_SPACE;\n-\telse if (!strcmp(cleanup_arg, \"strip\"))\n-\t\tcleanup_mode = CLEANUP_ALL;\n-\telse\n-\t\tdie(_(\"Invalid cleanup mode %s\"), cleanup_arg);\n \n \thandle_untracked_files_arg(s);\n+\tparse_cleanup_arg();\n \n \tif (all && argc > 0)\n \t\tdie(_(\"Paths with -a does not make sense.\"));\n@@ -1320,6 +1325,8 @@ static int git_commit_config(const char *k, const char *v, void *cb)\n \t\tinclude_status = git_config_bool(k, v);\n \t\treturn 0;\n \t}\n+\tif (!strcmp(k, \"commit.cleanup\"))\n+\t\treturn git_config_string(&cleanup_arg, k, v);\n \n \tstatus = git_gpg_config(k, v, NULL);\n \tif (status)\n-- \n1.8.1.165.gd94bd4e.dirty\n"},{"id":"206333","messageId":"7vlic3cr1g.fsf@alter.siamese.dyndns.org","threadId":"32562","inReplyTo":"1357676176-30019-1-git-send-email-ralf.thielow@gmail.com","subject":"Re: [PATCH] commit: make default of \"cleanup\" option configurable","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-01-08T21:18:19Z","receivedAt":"2013-01-08T21:18:19Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ralf Thielow <ralf.thielow@gmail.com> writes:\n\n> The default of the \"cleanup\" option in \"git commit\"\n> is not configurable. Users who don't want to use the\n> default have to pass this option on every commit since\n> there's no way to configure it. This commit introduces\n> a new config option \"commit.cleanup\" which can be used\n> to change the default of the \"cleanup\" option in\n> \"git commit\".\n>\n> Signed-off-by: Ralf Thielow <ralf.thielow@gmail.com>\n> ---\n\nThe idea makes sense, but I am not sure the implementation is\ncorrect.  Does the code already know the final value of use_editor\nat the point where it calls git_commit_config?  I think you do not\nknow at least until you call parse_and_validate_options().\n\nOnce you got the implementation right, we would want to make sure\nthat future changes will not break it by adding some tests that\nverify:\n\n - Without configuration and without option, the command keeps the\n   built-in default;\n\n - Without configuration but with option, the command uses the\n   command line option (we may already have this test, I didn't\n   check);\n\n - With configuration and without option, the command uses the\n   configured default (what this patch adds); and\n\n - With configuration and with option, the command uses the command\n   line option.\n\nThe latter two probably needs a few variants, one with --edit (with\nEDITOR set to something like \"true\"), another with --no-edit, one\nwithout --edit nor --no-edit but with -m \"$msg\" to implicitly turn\nuse_editor off, and one without --edit, --no-edit, nor -m but with\nEDITOR set to a scriptlet that writes a message to the file to\nimplicitly turn use_editor on.\n\nAlso, the readers of the documentation for \"commit --cleanup\" will\nwonder the same thing you wondered before you wrote this patch;\nmentioning the configuration variable in its documentation will help\nthem.\n\nThanks.\n\n>  Documentation/config.txt |  4 ++++\n>  builtin/commit.c         | 29 ++++++++++++++++++-----------\n>  2 files changed, 22 insertions(+), 11 deletions(-)\n>\n> diff --git a/Documentation/config.txt b/Documentation/config.txt\n> index 53c4ca1..3f76cd1 100644\n> --- a/Documentation/config.txt\n> +++ b/Documentation/config.txt\n> @@ -917,6 +917,10 @@ column.tag::\n>  \tSpecify whether to output tag listing in `git tag` in columns.\n>  \tSee `column.ui` for details.\n>  \n> +commit.cleanup::\n> +\tThis setting overrides the default of the `--cleanup` option in\n> +\t`git commit`. See linkgit:git-commit[1] for details.\n> +\n>  commit.status::\n>  \tA boolean to enable/disable inclusion of status information in the\n>  \tcommit message template when using an editor to prepare the commit\n> diff --git a/builtin/commit.c b/builtin/commit.c\n> index d6dd3df..42acde7 100644\n> --- a/builtin/commit.c\n> +++ b/builtin/commit.c\n> @@ -103,7 +103,7 @@ static enum {\n>  \tCLEANUP_NONE,\n>  \tCLEANUP_ALL\n>  } cleanup_mode;\n> -static char *cleanup_arg;\n> +const static char *cleanup_arg;\n>  \n>  static enum commit_whence whence;\n>  static int use_editor = 1, include_status = 1;\n> @@ -966,6 +966,20 @@ static const char *read_commit_message(const char *name)\n>  \treturn out;\n>  }\n>  \n> +static void parse_cleanup_arg()\n> +{\n> +\tif (!cleanup_arg || !strcmp(cleanup_arg, \"default\"))\n> +\t\tcleanup_mode = use_editor ? CLEANUP_ALL : CLEANUP_SPACE;\n> +\telse if (!strcmp(cleanup_arg, \"verbatim\"))\n> +\t\tcleanup_mode = CLEANUP_NONE;\n> +\telse if (!strcmp(cleanup_arg, \"whitespace\"))\n> +\t\tcleanup_mode = CLEANUP_SPACE;\n> +\telse if (!strcmp(cleanup_arg, \"strip\"))\n> +\t\tcleanup_mode = CLEANUP_ALL;\n> +\telse\n> +\t\tdie(_(\"Invalid cleanup mode %s\"), cleanup_arg);\n> +}\n> +\n>  static int parse_and_validate_options(int argc, const char *argv[],\n>  \t\t\t\t      const struct option *options,\n>  \t\t\t\t      const char * const usage[],\n> @@ -1044,18 +1058,9 @@ static int parse_and_validate_options(int argc, const char *argv[],\n>  \t\tonly_include_assumed = _(\"Clever... amending the last one with dirty index.\");\n>  \tif (argc > 0 && !also && !only)\n>  \t\tonly_include_assumed = _(\"Explicit paths specified without -i nor -o; assuming --only paths...\");\n> -\tif (!cleanup_arg || !strcmp(cleanup_arg, \"default\"))\n> -\t\tcleanup_mode = use_editor ? CLEANUP_ALL : CLEANUP_SPACE;\n> -\telse if (!strcmp(cleanup_arg, \"verbatim\"))\n> -\t\tcleanup_mode = CLEANUP_NONE;\n> -\telse if (!strcmp(cleanup_arg, \"whitespace\"))\n> -\t\tcleanup_mode = CLEANUP_SPACE;\n> -\telse if (!strcmp(cleanup_arg, \"strip\"))\n> -\t\tcleanup_mode = CLEANUP_ALL;\n> -\telse\n> -\t\tdie(_(\"Invalid cleanup mode %s\"), cleanup_arg);\n>  \n>  \thandle_untracked_files_arg(s);\n> +\tparse_cleanup_arg();\n>  \n>  \tif (all && argc > 0)\n>  \t\tdie(_(\"Paths with -a does not make sense.\"));\n> @@ -1320,6 +1325,8 @@ static int git_commit_config(const char *k, const char *v, void *cb)\n>  \t\tinclude_status = git_config_bool(k, v);\n>  \t\treturn 0;\n>  \t}\n> +\tif (!strcmp(k, \"commit.cleanup\"))\n> +\t\treturn git_config_string(&cleanup_arg, k, v);\n>  \n>  \tstatus = git_gpg_config(k, v, NULL);\n>  \tif (status)\n"},{"id":"206353","messageId":"20130109072952.GC6503@elie.Belkin","threadId":"32562","inReplyTo":"1357676176-30019-1-git-send-email-ralf.thielow@gmail.com","subject":"Re: [PATCH] commit: make default of \"cleanup\" option configurable","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2013-01-09T07:29:52Z","receivedAt":"2013-01-09T07:29:52Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Hi,\n\nRalf Thielow wrote:\n\n> The default of the \"cleanup\" option in \"git commit\"\n> is not configurable. Users who don't want to use the\n> default have to pass this option on every commit since\n> there's no way to configure it.\n\nCould you give an example?  I'm trying to get a sense of whether these\nhabitual --cleanup= passers would use --cleanup=verbatim or\n--cleanup=strip.\n\nI'm a bit worried that a setting like 'commit.cleanup = strip' would\nbe likely to break scripts.  Yes, scripts using \"git commit\" instead\nof commit-tree while caring about detailed semantics are asking for\ntrouble, but I'm worried about importers, for example, which are\nsometimes written by new git users.  Some scripts might assume that\n\"git commit\" preserves the entire change description from their source\ndata, even when some lines happen to start by listing the ways the\nauthor is #1.\n\nI don't think that necessarily rules out this change, but:\n\n 1. We need more of an explanation of the purpose than \"this lets\n    people type less\".  What workflow does setting this option fit\n    into?\n\n 2. I would prefer to see a little thought about whether it's possible\n    to avoid silently impacting scripts.  E.g., depending on the\n    answer to (1), maybe supporting \"verbatim\" but not \"strip\" would be\n    ok?  Or alternatively, maybe a search of public code repositories\n    would reveal that new git users tend to write their importers in a\n    way that this doesn't break.\n\nAs a side effect, the information gathered to answer (1) and (2) could\nhave the potential to make the user-level documentation more useful,\nby adding context to the description of the configuration item.\n\n[...]\n> --- a/builtin/commit.c\n> +++ b/builtin/commit.c\n> @@ -103,7 +103,7 @@ static enum {\n>  \tCLEANUP_NONE,\n>  \tCLEANUP_ALL\n>  } cleanup_mode;\n> -static char *cleanup_arg;\n> +const static char *cleanup_arg;\n\nStyle nit: storage class comes first, then the type.  Otherwise the\ntypename \"const char *\" is split up.\n\nHope that helps,\nJonathan\n"},{"id":"206354","messageId":"CAN0XMO+t2gu9UKJFVXAxt91-hUUhMqqmMoop88KYp0vo3x6c_g@mail.gmail.com","threadId":"32562","inReplyTo":"20130109072952.GC6503@elie.Belkin","subject":"Re: [PATCH] commit: make default of \"cleanup\" option configurable","fromName":"Ralf Thielow","fromEmail":"ralf.thielow@gmail.com","sentAt":"2013-01-09T08:16:17Z","receivedAt":"2013-01-09T08:16:17Z","isPatch":true,"sender":{"key":"ralf.thielow@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1275832?v=4"},"body":"Hi,\n\n2013/1/9 Jonathan Nieder <jrnieder@gmail.com>:\n> Hi,\n>\n> Ralf Thielow wrote:\n>\n>> The default of the \"cleanup\" option in \"git commit\"\n>> is not configurable. Users who don't want to use the\n>> default have to pass this option on every commit since\n>> there's no way to configure it.\n>\n> Could you give an example?  I'm trying to get a sense of whether these\n> habitual --cleanup= passers would use --cleanup=verbatim or\n> --cleanup=strip.\n>\n\nIt's actually my own usecase :). The bugtracker I'm using is able\nto create relationships between issues and related commits. It\nexpects that a part of the commit message contains the issue number\nin format \"#<issueId>\". So I need to use a cleanup mode different\nfrom \"default\" to keep the commentary. The mode I'd use is \"whitespace\",\n\"verbatim\" is also possible.\n\n> I'm a bit worried that a setting like 'commit.cleanup = strip' would\n> be likely to break scripts.  Yes, scripts using \"git commit\" instead\n> of commit-tree while caring about detailed semantics are asking for\n> trouble, but I'm worried about importers, for example, which are\n> sometimes written by new git users.  Some scripts might assume that\n> \"git commit\" preserves the entire change description from their source\n> data, even when some lines happen to start by listing the ways the\n> author is #1.\n>\n\nWhen a user uses a script/importer which expects that the \"default\" option\nis used without setting it explicitly, and then the user changes the default,\nisn't it the users fault if that would break things?\n\n> I don't think that necessarily rules out this change, but:\n>\n>  1. We need more of an explanation of the purpose than \"this lets\n>     people type less\".  What workflow does setting this option fit\n>     into?\n>\n>  2. I would prefer to see a little thought about whether it's possible\n>     to avoid silently impacting scripts.  E.g., depending on the\n>     answer to (1), maybe supporting \"verbatim\" but not \"strip\" would be\n>     ok?  Or alternatively, maybe a search of public code repositories\n>     would reveal that new git users tend to write their importers in a\n>     way that this doesn't break.\n>\n> As a side effect, the information gathered to answer (1) and (2) could\n> have the potential to make the user-level documentation more useful,\n> by adding context to the description of the configuration item.\n>\n\nI'll add a sentence of my bugtracker example to it. I think many developers\nare using such a tool, so it'd makes sense.\n\n> [...]\n>> --- a/builtin/commit.c\n>> +++ b/builtin/commit.c\n>> @@ -103,7 +103,7 @@ static enum {\n>>       CLEANUP_NONE,\n>>       CLEANUP_ALL\n>>  } cleanup_mode;\n>> -static char *cleanup_arg;\n>> +const static char *cleanup_arg;\n>\n> Style nit: storage class comes first, then the type.  Otherwise the\n> typename \"const char *\" is split up.\n>\n\nThanks.\nI'll send a new version of the patch including changes of your and\nJunios comments.\n\nRalf\n"},{"id":"206375","messageId":"20130109082858.GG6503@elie.Belkin","threadId":"32562","inReplyTo":"CAN0XMO+t2gu9UKJFVXAxt91-hUUhMqqmMoop88KYp0vo3x6c_g@mail.gmail.com","subject":"Re: [PATCH] commit: make default of \"cleanup\" option configurable","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2013-01-09T08:28:58Z","receivedAt":"2013-01-09T08:28:58Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Ralf Thielow wrote:\n\n> It's actually my own usecase :). The bugtracker I'm using is able\n> to create relationships between issues and related commits. It\n> expects that a part of the commit message contains the issue number\n> in format \"#<issueId>\". So I need to use a cleanup mode different\n> from \"default\" to keep the commentary. The mode I'd use is \"whitespace\",\n> \"verbatim\" is also possible.\n\nHm, so \"whitespace-when-editing\" would be the ideal setting.\n\nWould it be confusing if the '[commit] cleanup' setting only took\neffect when launching an editor (and not with -F, -C, or -m)?  My\nfirst impression is that I'd like that behavior better, even though\nit's harder to explain.\n\n[...]\n> When a user uses a script/importer which expects that the \"default\" option\n> is used without setting it explicitly, and then the user changes the default,\n> isn't it the users fault if that would break things?\n\nConsider the following series of events.\n\n 1. My friend writes an importer that uses the \"git commit\" command.\n    I like it and start using it.\n\n 2. Another friend writes a blog post about the '[commit] cleanup'\n    setting.  I like it and start using it.\n\n 3. I try to use the importer again.\n\n 4. Years later, I notice the commit messages are corrupted in the\n    imported history.\n\nIt's hard to assign blame.  I guess it's my fault. ;)\n\n[...]\n> I'll add a sentence of my bugtracker example to it. I think many developers\n> are using such a tool, so it'd makes sense.\n\nThanks, sounds good.\n\nRegards,\nJonathan\n"},{"id":"206383","messageId":"7vlic28ivl.fsf@alter.siamese.dyndns.org","threadId":"32562","inReplyTo":"CAN0XMO+t2gu9UKJFVXAxt91-hUUhMqqmMoop88KYp0vo3x6c_g@mail.gmail.com","subject":"Re: [PATCH] commit: make default of \"cleanup\" option configurable","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-01-09T15:40:30Z","receivedAt":"2013-01-09T15:40:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ralf Thielow <ralf.thielow@gmail.com> writes:\n\n> When a user uses a script/importer which expects that the \"default\" option\n> is used without setting it explicitly, and then the user changes the default,\n> isn't it the users fault if that would break things?\n\nNot necessarily.  There are many people who use scripts written by\nothers, without knowing how they work.  You could blame that the\nscript is broken, but not the poor user of that script.\n"},{"id":"206386","messageId":"7vhamq8i44.fsf@alter.siamese.dyndns.org","threadId":"32562","inReplyTo":"CAN0XMO+t2gu9UKJFVXAxt91-hUUhMqqmMoop88KYp0vo3x6c_g@mail.gmail.com","subject":"Re: [PATCH] commit: make default of \"cleanup\" option configurable","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-01-09T15:56:59Z","receivedAt":"2013-01-09T15:56:59Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ralf Thielow <ralf.thielow@gmail.com> writes:\n\n> It's actually my own usecase :). The bugtracker I'm using is able\n> to create relationships between issues and related commits. It\n> expects that a part of the commit message contains the issue number\n> in format \"#<issueId>\". So I need to use a cleanup mode different\n> from \"default\" to keep the commentary.\n\nThis is orthogonal to the patch in question, but in your particular\ncase, I wonder if it is a workable solution to indent #<bugid> in\nyour message, which won't be stripped away.\n\nI also wonder, as a longer term alternative (which would require a\nlot of code auditing and some refactoring), if it is useful to have\nan option and/or configuration that lets you configure the \"comment\nin log message editor\" character from the default \"#\" to something\nelse.  \"git -c log.commentchar=% commit\" may start the log message\neditor with something like this in it:\n\n    % Please enter the commit message for your changes. Lines starting\n    % with '%' will be ignored, and an empty message aborts the commit.\n\nNaturally, setting log.commentchar to \"none\" would disable stripping\nof any commented lines if such a feature existed, and stop issuing\nthese helpful comments altogether, but still strip excess blank\nlines and trailing whitespaces.\n\nI wouldn't seriously suggest it as I am not sure if the usefulness\nof such a feature would outweigh the cost of coding it, though; at\nleast not at this point yet.\n"},{"id":"206406","messageId":"1357760209-3407-1-git-send-email-ralf.thielow@gmail.com","threadId":"32562","inReplyTo":"1357676176-30019-1-git-send-email-ralf.thielow@gmail.com","subject":"[PATCHv2] commit: make default of \"cleanup\" option configurable","fromName":"Ralf Thielow","fromEmail":"ralf.thielow@gmail.com","sentAt":"2013-01-09T19:36:49Z","receivedAt":"2013-01-09T19:36:49Z","isPatch":false,"sender":{"key":"ralf.thielow@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1275832?v=4"},"body":"The default of the \"cleanup\" option in \"git commit\"\nis not configurable. Users who don't want to use the\ndefault have to pass this option on every commit since\nthere's no way to configure it. This commit introduces\na new config option \"commit.cleanup\" which can be used\nto change the default of the \"cleanup\" option in\n\"git commit\".\n\nSigned-off-by: Ralf Thielow <ralf.thielow@gmail.com>\n---\n\nChanges in v2:\n- simplify implementation\n- mention configuration variable in documentation of \"git commit --cleanup\"\n- add an example usecase to documention of commit.cleanup configuration variable\n- add tests\n\n Documentation/config.txt        |  7 ++++\n Documentation/git-commit.txt    |  4 +-\n builtin/commit.c                |  5 ++-\n t/t7500/add-content-and-comment |  4 ++\n t/t7502-commit.sh               | 84 +++++++++++++++++++++++++++++++++++++----\n 5 files changed, 95 insertions(+), 9 deletions(-)\n create mode 100755 t/t7500/add-content-and-comment\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 53c4ca1..0452d56 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -917,6 +917,13 @@ column.tag::\n \tSpecify whether to output tag listing in `git tag` in columns.\n \tSee `column.ui` for details.\n \n+commit.cleanup::\n+\tThis setting overrides the default of the `--cleanup` option in\n+\t`git commit`. See linkgit:git-commit[1] for details. Changing the\n+\tdefault can be useful if you want to use the comment character (#)\n+\tconsistently within your commit messages, in which case you would\n+\tlike to change the default to 'whitespace'.\n+\n commit.status::\n \tA boolean to enable/disable inclusion of status information in the\n \tcommit message template when using an editor to prepare the commit\ndiff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\nindex 7bdb039..41b27da 100644\n--- a/Documentation/git-commit.txt\n+++ b/Documentation/git-commit.txt\n@@ -179,7 +179,9 @@ OPTIONS\n \tonly if the message is to be edited. Otherwise only whitespace\n \tremoved. The 'verbatim' mode does not change message at all,\n \t'whitespace' removes just leading/trailing whitespace lines\n-\tand 'strip' removes both whitespace and commentary.\n+\tand 'strip' removes both whitespace and commentary. The default\n+\tcan be changed by the 'commit.cleanup' configuration variable\n+\t(see linkgit:git-config[1]).\n \n -e::\n --edit::\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex d6dd3df..4d55f8f 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -103,7 +103,7 @@ static enum {\n \tCLEANUP_NONE,\n \tCLEANUP_ALL\n } cleanup_mode;\n-static char *cleanup_arg;\n+static const char *cleanup_arg;\n \n static enum commit_whence whence;\n static int use_editor = 1, include_status = 1;\n@@ -966,6 +966,7 @@ static const char *read_commit_message(const char *name)\n \treturn out;\n }\n \n+\n static int parse_and_validate_options(int argc, const char *argv[],\n \t\t\t\t      const struct option *options,\n \t\t\t\t      const char * const usage[],\n@@ -1320,6 +1321,8 @@ static int git_commit_config(const char *k, const char *v, void *cb)\n \t\tinclude_status = git_config_bool(k, v);\n \t\treturn 0;\n \t}\n+\tif (!strcmp(k, \"commit.cleanup\"))\n+\t\treturn git_config_string(&cleanup_arg, k, v);\n \n \tstatus = git_gpg_config(k, v, NULL);\n \tif (status)\ndiff --git a/t/t7500/add-content-and-comment b/t/t7500/add-content-and-comment\nnew file mode 100755\nindex 0000000..988f5e9\n--- /dev/null\n+++ b/t/t7500/add-content-and-comment\n@@ -0,0 +1,4 @@\n+#!/bin/sh\n+echo \"commit message\" >> \"$1\"\n+echo \"# comment\" >> \"$1\"\n+exit 0\n\\ No newline at end of file\ndiff --git a/t/t7502-commit.sh b/t/t7502-commit.sh\nindex 1a5cb69..b1c7648 100755\n--- a/t/t7502-commit.sh\n+++ b/t/t7502-commit.sh\n@@ -4,6 +4,15 @@ test_description='git commit porcelain-ish'\n \n . ./test-lib.sh\n \n+commit_msg_is () {\n+\texpect=commit_msg_is.expect\n+\tactual=commit_msg_is.actual\n+\n+\tprintf \"%s\" \"$(git log --pretty=format:%s%b -1)\" >$actual &&\n+\tprintf \"%s\" \"$1\" >$expect &&\n+\ttest_i18ncmp $expect $actual\n+}\n+\n # Arguments: [<prefix] [<commit message>] [<commit options>]\n check_summary_oneline() {\n \ttest_tick &&\n@@ -168,7 +177,7 @@ test_expect_success 'verbose respects diff config' '\n \tgit config --unset color.diff\n '\n \n-test_expect_success 'cleanup commit messages (verbatim,-t)' '\n+test_expect_success 'cleanup commit messages (verbatim option,-t)' '\n \n \techo >>negative &&\n \t{ echo;echo \"# text\";echo; } >expect &&\n@@ -178,7 +187,7 @@ test_expect_success 'cleanup commit messages (verbatim,-t)' '\n \n '\n \n-test_expect_success 'cleanup commit messages (verbatim,-F)' '\n+test_expect_success 'cleanup commit messages (verbatim option,-F)' '\n \n \techo >>negative &&\n \tgit commit --cleanup=verbatim -F expect -a &&\n@@ -187,7 +196,7 @@ test_expect_success 'cleanup commit messages (verbatim,-F)' '\n \n '\n \n-test_expect_success 'cleanup commit messages (verbatim,-m)' '\n+test_expect_success 'cleanup commit messages (verbatim option,-m)' '\n \n \techo >>negative &&\n \tgit commit --cleanup=verbatim -m \"$(cat expect)\" -a &&\n@@ -196,7 +205,7 @@ test_expect_success 'cleanup commit messages (verbatim,-m)' '\n \n '\n \n-test_expect_success 'cleanup commit messages (whitespace,-F)' '\n+test_expect_success 'cleanup commit messages (whitespace option,-F)' '\n \n \techo >>negative &&\n \t{ echo;echo \"# text\";echo; } >text &&\n@@ -207,7 +216,7 @@ test_expect_success 'cleanup commit messages (whitespace,-F)' '\n \n '\n \n-test_expect_success 'cleanup commit messages (strip,-F)' '\n+test_expect_success 'cleanup commit messages (strip option,-F)' '\n \n \techo >>negative &&\n \t{ echo;echo \"# text\";echo sample;echo; } >text &&\n@@ -218,7 +227,7 @@ test_expect_success 'cleanup commit messages (strip,-F)' '\n \n '\n \n-test_expect_success 'cleanup commit messages (strip,-F,-e)' '\n+test_expect_success 'cleanup commit messages (strip option,-F,-e)' '\n \n \techo >>negative &&\n \t{ echo;echo sample;echo; } >text &&\n@@ -231,10 +240,71 @@ echo \"sample\n # Please enter the commit message for your changes. Lines starting\n # with '#' will be ignored, and an empty message aborts the commit.\" >expect\n \n-test_expect_success 'cleanup commit messages (strip,-F,-e): output' '\n+test_expect_success 'cleanup commit messages (strip option,-F,-e): output' '\n \ttest_i18ncmp expect actual\n '\n \n+test_expect_success 'cleanup commit message (fail on invalid cleanup mode option)' '\n+\ttest_must_fail git commit --cleanup=non-existent\n+'\n+\n+test_expect_success 'cleanup commit message (fail on invalid cleanup mode configuration)' '\n+\ttest_must_fail git -c commit.cleanup=non-existent commit\n+'\n+\n+test_expect_success 'cleanup commit message (no config and no option uses default)' '\n+\techo content >>file &&\n+\tgit add file &&\n+\ttest_set_editor \"$TEST_DIRECTORY\"/t7500/add-content-and-comment &&\n+\tgit commit --no-status &&\n+\tcommit_msg_is \"commit message\"\n+'\n+\n+test_expect_success 'cleanup commit message (option overrides default)' '\n+\techo content >>file &&\n+\tgit add file &&\n+\ttest_set_editor \"$TEST_DIRECTORY\"/t7500/add-content-and-comment &&\n+\tgit commit --cleanup=whitespace --no-status &&\n+\tcommit_msg_is \"commit message # comment\"\n+'\n+\n+test_expect_success 'cleanup commit message (config overrides default)' '\n+\techo content >>file &&\n+\tgit add file &&\n+\ttest_set_editor \"$TEST_DIRECTORY\"/t7500/add-content-and-comment &&\n+\tgit -c commit.cleanup=whitespace commit --no-status &&\n+\tcommit_msg_is \"commit message # comment\"\n+'\n+\n+test_expect_success 'cleanup commit message (option overrides config)' '\n+\techo content >>file &&\n+\tgit add file &&\n+\ttest_set_editor \"$TEST_DIRECTORY\"/t7500/add-content-and-comment &&\n+\tgit -c commit.cleanup=whitespace commit --cleanup=default &&\n+\tcommit_msg_is \"commit message\"\n+'\n+\n+test_expect_success 'cleanup commit message (default, -m)' '\n+\techo content >>file &&\n+\tgit add file &&\n+\tgit commit -m \"message #comment \" &&\n+\tcommit_msg_is \"message #comment\"\n+'\n+\n+test_expect_success 'cleanup commit message (whitespace option, -m)' '\n+\techo content >>file &&\n+\tgit add file &&\n+\tgit commit --cleanup=whitespace --no-status -m \"message #comment \" &&\n+\tcommit_msg_is \"message #comment\"\n+'\n+\n+test_expect_success 'cleanup commit message (whitespace config, -m)' '\n+\techo content >>file &&\n+\tgit add file &&\n+\tgit -c commit.cleanup=whitespace commit --no-status -m \"message #comment \" &&\n+\tcommit_msg_is \"message #comment\"\n+'\n+\n test_expect_success 'message shows author when it is not equal to committer' '\n \techo >>negative &&\n \tgit commit -e -m \"sample\" -a &&\n-- \n1.8.1.165.g0eb732d.dirty\n"},{"id":"206435","messageId":"7vwqvl3n9a.fsf@alter.siamese.dyndns.org","threadId":"32562","inReplyTo":"1357760209-3407-1-git-send-email-ralf.thielow@gmail.com","subject":"Re: [PATCHv2] commit: make default of \"cleanup\" option configurable","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-01-10T00:17:05Z","receivedAt":"2013-01-10T00:17:05Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ralf Thielow <ralf.thielow@gmail.com> writes:\n\n> The default of the \"cleanup\" option in \"git commit\"\n> is not configurable. Users who don't want to use the\n> default have to pass this option on every commit since\n> there's no way to configure it. This commit introduces\n> a new config option \"commit.cleanup\" which can be used\n> to change the default of the \"cleanup\" option in\n> \"git commit\".\n>\n> Signed-off-by: Ralf Thielow <ralf.thielow@gmail.com>\n> ---\n\nThanks.\n\n> Changes in v2:\n> - simplify implementation\n> - mention configuration variable in documentation of \"git commit --cleanup\"\n> - add an example usecase to documention of commit.cleanup configuration variable\n> - add tests\n>\n>  Documentation/config.txt        |  7 ++++\n>  Documentation/git-commit.txt    |  4 +-\n>  builtin/commit.c                |  5 ++-\n>  t/t7500/add-content-and-comment |  4 ++\n>  t/t7502-commit.sh               | 84 +++++++++++++++++++++++++++++++++++++----\n>  5 files changed, 95 insertions(+), 9 deletions(-)\n>  create mode 100755 t/t7500/add-content-and-comment\n>\n> diff --git a/Documentation/config.txt b/Documentation/config.txt\n> index 53c4ca1..0452d56 100644\n> --- a/Documentation/config.txt\n> +++ b/Documentation/config.txt\n> @@ -917,6 +917,13 @@ column.tag::\n>  \tSpecify whether to output tag listing in `git tag` in columns.\n>  \tSee `column.ui` for details.\n>  \n> +commit.cleanup::\n> +\tThis setting overrides the default of the `--cleanup` option in\n> +\t`git commit`. See linkgit:git-commit[1] for details. Changing the\n> +\tdefault can be useful if you want to use the comment character (#)\n> +\tconsistently within your commit messages, in which case you would\n> +\tlike to change the default to 'whitespace'.\n\nWhen the documentation suggests to use 'whitespace', it would be\nhelpful to warn the readers that hints Git produces in '#'-commented\nsection need to be removed, if they are not ment to be kept (which\nis 99.99% of the case).  Perhaps:\n\n\tThis setting overrides the default of the `--cleanup` option\n\tin `git commit`. Changing the default can be useful when you\n\talways want to keep lines that begin with comment character\n\t`#` in your log message, in which case you would do `git\n\tconfig commit.cleanup whitespace` (note that you will have\n\tto remove the help lines that begin with '#' in the commit\n\tlog template yourself, if you do this).\n\nor something?\n\n> diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\n> index 7bdb039..41b27da 100644\n> --- a/Documentation/git-commit.txt\n> +++ b/Documentation/git-commit.txt\n> @@ -179,7 +179,9 @@ OPTIONS\n>  \tonly if the message is to be edited. Otherwise only whitespace\n>  \tremoved. The 'verbatim' mode does not change message at all,\n>  \t'whitespace' removes just leading/trailing whitespace lines\n> -\tand 'strip' removes both whitespace and commentary.\n> +\tand 'strip' removes both whitespace and commentary. The default\n> +\tcan be changed by the 'commit.cleanup' configuration variable\n> +\t(see linkgit:git-config[1]).\n\nNicely written.\n\n> --- a/builtin/commit.c\n> +++ b/builtin/commit.c\n> @@ -103,7 +103,7 @@ static enum {\n>  \tCLEANUP_NONE,\n>  \tCLEANUP_ALL\n>  } cleanup_mode;\n> -static char *cleanup_arg;\n> +static const char *cleanup_arg;\n>  \n>  static enum commit_whence whence;\n>  static int use_editor = 1, include_status = 1;\n> @@ -966,6 +966,7 @@ static const char *read_commit_message(const char *name)\n>  \treturn out;\n>  }\n>  \n> +\n>  static int parse_and_validate_options(int argc, const char *argv[],\n>  \t\t\t\t      const struct option *options,\n>  \t\t\t\t      const char * const usage[],\n\nDon't add an extra blank line, please.\n\n> @@ -1320,6 +1321,8 @@ static int git_commit_config(const char *k, const char *v, void *cb)\n>  \t\tinclude_status = git_config_bool(k, v);\n>  \t\treturn 0;\n>  \t}\n> +\tif (!strcmp(k, \"commit.cleanup\"))\n> +\t\treturn git_config_string(&cleanup_arg, k, v);\n\nNice.\n\n> diff --git a/t/t7500/add-content-and-comment b/t/t7500/add-content-and-comment\n> new file mode 100755\n> index 0000000..988f5e9\n> --- /dev/null\n> +++ b/t/t7500/add-content-and-comment\n> @@ -0,0 +1,4 @@\n> +#!/bin/sh\n> +echo \"commit message\" >> \"$1\"\n> +echo \"# comment\" >> \"$1\"\n> +exit 0\n> \\ No newline at end of file\n\nHave newline at end of file, please.\n\n> diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh\n> index 1a5cb69..b1c7648 100755\n> --- a/t/t7502-commit.sh\n> +++ b/t/t7502-commit.sh\n> @@ -4,6 +4,15 @@ test_description='git commit porcelain-ish'\n> +...\n> +'\n> +\n\nNicely done.\n\nThanks.\n"},{"id":"206460","messageId":"1357839959-18193-1-git-send-email-ralf.thielow@gmail.com","threadId":"32562","inReplyTo":"1357760209-3407-1-git-send-email-ralf.thielow@gmail.com","subject":"[PATCHv3] commit: make default of \"cleanup\" option configurable","fromName":"Ralf Thielow","fromEmail":"ralf.thielow@gmail.com","sentAt":"2013-01-10T17:45:59Z","receivedAt":"2013-01-10T17:45:59Z","isPatch":false,"sender":{"key":"ralf.thielow@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1275832?v=4"},"body":"The default of the \"cleanup\" option in \"git commit\"\nis not configurable. Users who don't want to use the\ndefault have to pass this option on every commit since\nthere's no way to configure it. This commit introduces\na new config option \"commit.cleanup\" which can be used\nto change the default of the \"cleanup\" option in\n\"git commit\".\n\nSigned-off-by: Ralf Thielow <ralf.thielow@gmail.com>\n---\nchanges in v3:\n- remove extra blank line in builtin/commit.c\n- add newline at end of t/t7500/add-content-and-comment\n- improve documentation of commit.cleanup configuration variable\nas Junio suggested (makes a lot of sense)\n\nThanks\n\n Documentation/config.txt        |  9 +++++\n Documentation/git-commit.txt    |  4 +-\n builtin/commit.c                |  4 +-\n t/t7500/add-content-and-comment |  5 +++\n t/t7502-commit.sh               | 84 +++++++++++++++++++++++++++++++++++++----\n 5 files changed, 97 insertions(+), 9 deletions(-)\n create mode 100755 t/t7500/add-content-and-comment\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 53c4ca1..c92a308 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -917,6 +917,15 @@ column.tag::\n \tSpecify whether to output tag listing in `git tag` in columns.\n \tSee `column.ui` for details.\n \n+commit.cleanup::\n+\tThis setting overrides the default of the `--cleanup` option in\n+\t`git commit`. See linkgit:git-commit[1] for details. Changing the\n+\tdefault can be useful when you always want to keep lines that begin\n+\twith comment character `#` in your log message, in which case you\n+\twould do `git config commit.cleanup whitespace` (note that you will\n+\thave to remove the help lines that begin with `#` in the commit log\n+\ttemplate yourself, if you do this).\n+\n commit.status::\n \tA boolean to enable/disable inclusion of status information in the\n \tcommit message template when using an editor to prepare the commit\ndiff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\nindex 7bdb039..41b27da 100644\n--- a/Documentation/git-commit.txt\n+++ b/Documentation/git-commit.txt\n@@ -179,7 +179,9 @@ OPTIONS\n \tonly if the message is to be edited. Otherwise only whitespace\n \tremoved. The 'verbatim' mode does not change message at all,\n \t'whitespace' removes just leading/trailing whitespace lines\n-\tand 'strip' removes both whitespace and commentary.\n+\tand 'strip' removes both whitespace and commentary. The default\n+\tcan be changed by the 'commit.cleanup' configuration variable\n+\t(see linkgit:git-config[1]).\n \n -e::\n --edit::\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex d6dd3df..7c2a3d4 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -103,7 +103,7 @@ static enum {\n \tCLEANUP_NONE,\n \tCLEANUP_ALL\n } cleanup_mode;\n-static char *cleanup_arg;\n+static const char *cleanup_arg;\n \n static enum commit_whence whence;\n static int use_editor = 1, include_status = 1;\n@@ -1320,6 +1320,8 @@ static int git_commit_config(const char *k, const char *v, void *cb)\n \t\tinclude_status = git_config_bool(k, v);\n \t\treturn 0;\n \t}\n+\tif (!strcmp(k, \"commit.cleanup\"))\n+\t\treturn git_config_string(&cleanup_arg, k, v);\n \n \tstatus = git_gpg_config(k, v, NULL);\n \tif (status)\ndiff --git a/t/t7500/add-content-and-comment b/t/t7500/add-content-and-comment\nnew file mode 100755\nindex 0000000..c4dccff\n--- /dev/null\n+++ b/t/t7500/add-content-and-comment\n@@ -0,0 +1,5 @@\n+#!/bin/sh\n+echo \"commit message\" >> \"$1\"\n+echo \"# comment\" >> \"$1\"\n+exit 0\n+\ndiff --git a/t/t7502-commit.sh b/t/t7502-commit.sh\nindex 1a5cb69..b1c7648 100755\n--- a/t/t7502-commit.sh\n+++ b/t/t7502-commit.sh\n@@ -4,6 +4,15 @@ test_description='git commit porcelain-ish'\n \n . ./test-lib.sh\n \n+commit_msg_is () {\n+\texpect=commit_msg_is.expect\n+\tactual=commit_msg_is.actual\n+\n+\tprintf \"%s\" \"$(git log --pretty=format:%s%b -1)\" >$actual &&\n+\tprintf \"%s\" \"$1\" >$expect &&\n+\ttest_i18ncmp $expect $actual\n+}\n+\n # Arguments: [<prefix] [<commit message>] [<commit options>]\n check_summary_oneline() {\n \ttest_tick &&\n@@ -168,7 +177,7 @@ test_expect_success 'verbose respects diff config' '\n \tgit config --unset color.diff\n '\n \n-test_expect_success 'cleanup commit messages (verbatim,-t)' '\n+test_expect_success 'cleanup commit messages (verbatim option,-t)' '\n \n \techo >>negative &&\n \t{ echo;echo \"# text\";echo; } >expect &&\n@@ -178,7 +187,7 @@ test_expect_success 'cleanup commit messages (verbatim,-t)' '\n \n '\n \n-test_expect_success 'cleanup commit messages (verbatim,-F)' '\n+test_expect_success 'cleanup commit messages (verbatim option,-F)' '\n \n \techo >>negative &&\n \tgit commit --cleanup=verbatim -F expect -a &&\n@@ -187,7 +196,7 @@ test_expect_success 'cleanup commit messages (verbatim,-F)' '\n \n '\n \n-test_expect_success 'cleanup commit messages (verbatim,-m)' '\n+test_expect_success 'cleanup commit messages (verbatim option,-m)' '\n \n \techo >>negative &&\n \tgit commit --cleanup=verbatim -m \"$(cat expect)\" -a &&\n@@ -196,7 +205,7 @@ test_expect_success 'cleanup commit messages (verbatim,-m)' '\n \n '\n \n-test_expect_success 'cleanup commit messages (whitespace,-F)' '\n+test_expect_success 'cleanup commit messages (whitespace option,-F)' '\n \n \techo >>negative &&\n \t{ echo;echo \"# text\";echo; } >text &&\n@@ -207,7 +216,7 @@ test_expect_success 'cleanup commit messages (whitespace,-F)' '\n \n '\n \n-test_expect_success 'cleanup commit messages (strip,-F)' '\n+test_expect_success 'cleanup commit messages (strip option,-F)' '\n \n \techo >>negative &&\n \t{ echo;echo \"# text\";echo sample;echo; } >text &&\n@@ -218,7 +227,7 @@ test_expect_success 'cleanup commit messages (strip,-F)' '\n \n '\n \n-test_expect_success 'cleanup commit messages (strip,-F,-e)' '\n+test_expect_success 'cleanup commit messages (strip option,-F,-e)' '\n \n \techo >>negative &&\n \t{ echo;echo sample;echo; } >text &&\n@@ -231,10 +240,71 @@ echo \"sample\n # Please enter the commit message for your changes. Lines starting\n # with '#' will be ignored, and an empty message aborts the commit.\" >expect\n \n-test_expect_success 'cleanup commit messages (strip,-F,-e): output' '\n+test_expect_success 'cleanup commit messages (strip option,-F,-e): output' '\n \ttest_i18ncmp expect actual\n '\n \n+test_expect_success 'cleanup commit message (fail on invalid cleanup mode option)' '\n+\ttest_must_fail git commit --cleanup=non-existent\n+'\n+\n+test_expect_success 'cleanup commit message (fail on invalid cleanup mode configuration)' '\n+\ttest_must_fail git -c commit.cleanup=non-existent commit\n+'\n+\n+test_expect_success 'cleanup commit message (no config and no option uses default)' '\n+\techo content >>file &&\n+\tgit add file &&\n+\ttest_set_editor \"$TEST_DIRECTORY\"/t7500/add-content-and-comment &&\n+\tgit commit --no-status &&\n+\tcommit_msg_is \"commit message\"\n+'\n+\n+test_expect_success 'cleanup commit message (option overrides default)' '\n+\techo content >>file &&\n+\tgit add file &&\n+\ttest_set_editor \"$TEST_DIRECTORY\"/t7500/add-content-and-comment &&\n+\tgit commit --cleanup=whitespace --no-status &&\n+\tcommit_msg_is \"commit message # comment\"\n+'\n+\n+test_expect_success 'cleanup commit message (config overrides default)' '\n+\techo content >>file &&\n+\tgit add file &&\n+\ttest_set_editor \"$TEST_DIRECTORY\"/t7500/add-content-and-comment &&\n+\tgit -c commit.cleanup=whitespace commit --no-status &&\n+\tcommit_msg_is \"commit message # comment\"\n+'\n+\n+test_expect_success 'cleanup commit message (option overrides config)' '\n+\techo content >>file &&\n+\tgit add file &&\n+\ttest_set_editor \"$TEST_DIRECTORY\"/t7500/add-content-and-comment &&\n+\tgit -c commit.cleanup=whitespace commit --cleanup=default &&\n+\tcommit_msg_is \"commit message\"\n+'\n+\n+test_expect_success 'cleanup commit message (default, -m)' '\n+\techo content >>file &&\n+\tgit add file &&\n+\tgit commit -m \"message #comment \" &&\n+\tcommit_msg_is \"message #comment\"\n+'\n+\n+test_expect_success 'cleanup commit message (whitespace option, -m)' '\n+\techo content >>file &&\n+\tgit add file &&\n+\tgit commit --cleanup=whitespace --no-status -m \"message #comment \" &&\n+\tcommit_msg_is \"message #comment\"\n+'\n+\n+test_expect_success 'cleanup commit message (whitespace config, -m)' '\n+\techo content >>file &&\n+\tgit add file &&\n+\tgit -c commit.cleanup=whitespace commit --no-status -m \"message #comment \" &&\n+\tcommit_msg_is \"message #comment\"\n+'\n+\n test_expect_success 'message shows author when it is not equal to committer' '\n \techo >>negative &&\n \tgit commit -e -m \"sample\" -a &&\n-- \n1.8.1.227.g44fe835\n"},{"id":"206465","messageId":"7vk3rk25iw.fsf_-_@alter.siamese.dyndns.org","threadId":"32562","inReplyTo":"7vhamq8i44.fsf@alter.siamese.dyndns.org","subject":"Re* [PATCH] commit: make default of \"cleanup\" option configurable","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-01-10T19:37:43Z","receivedAt":"2013-01-10T19:37:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> I also wonder, as a longer term alternative (which would require a\n> lot of code auditing and some refactoring), if it is useful to have\n> an option and/or configuration that lets you configure the \"comment\n> in log message editor\" character from the default \"#\" to something\n> else.  \"git -c log.commentchar=% commit\" may start the log message\n> editor with something like this in it:\n>\n>     % Please enter the commit message for your changes. Lines starting\n>     % with '%' will be ignored, and an empty message aborts the commit.\n>\n> Naturally, setting log.commentchar to \"none\" would disable stripping\n> of any commented lines if such a feature existed, and stop issuing\n> these helpful comments altogether, but still strip excess blank\n> lines and trailing whitespaces.\n>\n> I wouldn't seriously suggest it as I am not sure if the usefulness\n> of such a feature would outweigh the cost of coding it, though; at\n> least not at this point yet.\n\nA beginning of a patch to do would be like this, which does not look\ntoo bad.  There are some low hanging fruits I didn't bother to do in\nthis illustration (see NEEDSWORK comment in builtin/branch.c if some\nof you are interested in pursuing it).\n\n-- >8 --\nFrom: Junio C Hamano <gitster@pobox.com>\nDate: Thu, 10 Jan 2013 11:17:21 -0800\nSubject: [PATCH] Allow custom \"comment char\"\n\nSome users do want to write a line that begin with a pound sign,\n#, in their commit log message.  Many tracking system recognise\na token of #<bugid> form, for example.\n\nThe support we offer these use cases is not very friendly to the end\nusers.  They have a choice between\n\n - Don't do it.  Avoid such a line by rewrapping or indenting; and\n\n - Use --cleanup=whitespace but remove all the hint lines we add.\n\nGive them a way to set a custom comment char, e.g.\n\n    $ git -c core.commentchar=\"%\" commit\n\nso that they do not have to do either of the two workarounds.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/config.txt |  6 ++++++\n builtin/branch.c         | 16 ++++++++++++----\n builtin/commit.c         | 15 ++++++++-------\n builtin/fmt-merge-msg.c  |  4 +++-\n builtin/merge.c          | 15 +++++++++++----\n builtin/stripspace.c     |  2 +-\n cache.h                  |  6 ++++++\n config.c                 |  8 ++++++++\n environment.c            |  6 ++++++\n wt-status.c              | 10 ++++++----\n 10 files changed, 67 insertions(+), 21 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex d5809e0..e99b9f2 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -528,6 +528,12 @@ core.editor::\n \tvariable when it is set, and the environment variable\n \t`GIT_EDITOR` is not set.  See linkgit:git-var[1].\n \n+core.commentchar::\n+\tCommands such as `commit` and `tag` that lets you edit\n+\tmessages consider a line that begins with this character\n+\tcommented, and removes them after the editor returns\n+\t(default '#').\n+\n sequence.editor::\n \tText editor used by `git rebase -i` for editing the rebase insn file.\n \tThe value is meant to be interpreted by the shell when it is used.\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex 873f624..7f8865a 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -706,11 +706,19 @@ static int edit_branch_description(const char *branch_name)\n \tread_branch_desc(&buf, branch_name);\n \tif (!buf.len || buf.buf[buf.len-1] != '\\n')\n \t\tstrbuf_addch(&buf, '\\n');\n+\t/*\n+\t * NEEDSWORK: introduce a strbuf_commented_addf(), possibly\n+\t * sharing code with status_vprintf(), that makes each line\n+\t * commented with comment_line_char, and use it here and from\n+\t * other places (e.g. write_commented_object() and create_note()\n+\t * in builtin/notes.c and create_tag() in builtin/tag.c).\n+\t */\n \tstrbuf_addf(&buf,\n-\t\t    \"# Please edit the description for the branch\\n\"\n-\t\t    \"#   %s\\n\"\n-\t\t    \"# Lines starting with '#' will be stripped.\\n\",\n-\t\t    branch_name);\n+\t\t    \"%c Please edit the description for the branch\\n\"\n+\t\t    \"%c   %s\\n\"\n+\t\t    \"%c Lines starting with '%c' will be stripped.\\n\",\n+\t\t    comment_line_char, comment_line_char,\n+\t\t    branch_name, comment_line_char, comment_line_char);\n \tfp = fopen(git_path(edit_description), \"w\");\n \tif ((fwrite(buf.buf, 1, buf.len, fp) < buf.len) || fclose(fp)) {\n \t\tstrbuf_release(&buf);\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex d6dd3df..a946a13 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -733,15 +733,16 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \t\tif (cleanup_mode == CLEANUP_ALL)\n \t\t\tstatus_printf(s, GIT_COLOR_NORMAL,\n \t\t\t\t_(\"Please enter the commit message for your changes.\"\n-\t\t\t\t\" Lines starting\\nwith '#' will be ignored, and an empty\"\n-\t\t\t\t\" message aborts the commit.\\n\"));\n+\t\t\t\t  \" Lines starting\\nwith '%c' will be ignored, and an empty\"\n+\t\t\t\t  \" message aborts the commit.\\n\"), comment_line_char);\n \t\telse /* CLEANUP_SPACE, that is. */\n \t\t\tstatus_printf(s, GIT_COLOR_NORMAL,\n-\t\t\t\t_(\"Please enter the commit message for your changes.\"\n-\t\t\t\t\" Lines starting\\n\"\n-\t\t\t\t\"with '#' will be kept; you may remove them\"\n-\t\t\t\t\" yourself if you want to.\\n\"\n-\t\t\t\t\"An empty message aborts the commit.\\n\"));\n+\t\t\t\t      _(\"Please enter the commit message for your changes.\"\n+\t\t\t\t\t\" Lines starting\\n\"\n+\t\t\t\t\t\"with '%c' will be kept; you may remove them\"\n+\t\t\t\t\t\" yourself if you want to.\\n\"\n+\t\t\t\t\t\"An empty message aborts the commit.\\n\"),\n+\t\t\t\t      comment_line_char);\n \t\tif (only_include_assumed)\n \t\t\tstatus_printf_ln(s, GIT_COLOR_NORMAL,\n \t\t\t\t\t\"%s\", only_include_assumed);\ndiff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c\nindex e2e27b2..2261e1f 100644\n--- a/builtin/fmt-merge-msg.c\n+++ b/builtin/fmt-merge-msg.c\n@@ -463,8 +463,10 @@ static void fmt_tag_signature(struct strbuf *tagbuf,\n \t}\n \tstrbuf_complete_line(tagbuf);\n \tif (sig->len) {\n+\t\tchar comment_head[3];\n+\t\tsprintf(comment_head, \"%c \", comment_line_char);\n \t\tstrbuf_addch(tagbuf, '\\n');\n-\t\tstrbuf_add_lines(tagbuf, \"# \", sig->buf, sig->len);\n+\t\tstrbuf_add_lines(tagbuf, comment_head, sig->buf, sig->len);\n \t}\n }\n \ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 3a31c4b..632d860 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -788,17 +788,24 @@ static const char merge_editor_comment[] =\n N_(\"Please enter a commit message to explain why this merge is necessary,\\n\"\n    \"especially if it merges an updated upstream into a topic branch.\\n\"\n    \"\\n\"\n-   \"Lines starting with '#' will be ignored, and an empty message aborts\\n\"\n+   \"Lines starting with '%c' will be ignored, and an empty message aborts\\n\"\n    \"the commit.\\n\");\n \n static void prepare_to_commit(struct commit_list *remoteheads)\n {\n \tstruct strbuf msg = STRBUF_INIT;\n-\tconst char *comment = _(merge_editor_comment);\n+\tconst char *commentf = _(merge_editor_comment);\n \tstrbuf_addbuf(&msg, &merge_msg);\n \tstrbuf_addch(&msg, '\\n');\n-\tif (0 < option_edit)\n-\t\tstrbuf_add_lines(&msg, \"# \", comment, strlen(comment));\n+\tif (0 < option_edit) {\n+\t\tstruct strbuf hint = STRBUF_INIT;\n+\t\tchar comment_head[3];\n+\n+\t\tsprintf(comment_head, \"%c \", comment_line_char);\n+\t\tstrbuf_addf(&hint, commentf, comment_line_char);\n+\t\tstrbuf_add_lines(&msg, comment_head, hint.buf, hint.len);\n+\t\tstrbuf_release(&hint);\n+\t}\n \twrite_merge_msg(&msg);\n \tif (run_hook(get_index_file(), \"prepare-commit-msg\",\n \t\t     git_path(\"MERGE_MSG\"), \"merge\", NULL, NULL))\ndiff --git a/builtin/stripspace.c b/builtin/stripspace.c\nindex f16986c..600ca66 100644\n--- a/builtin/stripspace.c\n+++ b/builtin/stripspace.c\n@@ -45,7 +45,7 @@ void stripspace(struct strbuf *sb, int skip_comments)\n \t\teol = memchr(sb->buf + i, '\\n', sb->len - i);\n \t\tlen = eol ? eol - (sb->buf + i) + 1 : sb->len - i;\n \n-\t\tif (skip_comments && len && sb->buf[i] == '#') {\n+\t\tif (skip_comments && len && sb->buf[i] == comment_line_char) {\n \t\t\tnewlen = 0;\n \t\t\tcontinue;\n \t\t}\ndiff --git a/cache.h b/cache.h\nindex c257953..0b435a4 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -562,6 +562,12 @@ extern int core_preload_index;\n extern int core_apply_sparse_checkout;\n extern int precomposed_unicode;\n \n+/*\n+ * The character that begins a commented line in user-editable file\n+ * that is subject to stripspace.\n+ */\n+extern char comment_line_char;\n+\n enum branch_track {\n \tBRANCH_TRACK_UNSPECIFIED = -1,\n \tBRANCH_TRACK_NEVER = 0,\ndiff --git a/config.c b/config.c\nindex 7b444b6..d873c59 100644\n--- a/config.c\n+++ b/config.c\n@@ -717,6 +717,14 @@ static int git_default_core_config(const char *var, const char *value)\n \tif (!strcmp(var, \"core.editor\"))\n \t\treturn git_config_string(&editor_program, var, value);\n \n+\tif (!strcmp(var, \"core.commentchar\")) {\n+\t\tconst char *comment;\n+\t\tint ret = git_config_string(&comment, var, value);\n+\t\tif (!ret)\n+\t\t\tcomment_line_char = comment[0];\n+\t\treturn ret;\n+\t}\n+\n \tif (!strcmp(var, \"core.askpass\"))\n \t\treturn git_config_string(&askpass_program, var, value);\n \ndiff --git a/environment.c b/environment.c\nindex 85edd7f..a40c38b 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -62,6 +62,12 @@ int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */\n struct startup_info *startup_info;\n unsigned long pack_size_limit_cfg;\n \n+/*\n+ * The character that begins a commented line in user-editable file\n+ * that is subject to stripspace.\n+ */\n+char comment_line_char = '#';\n+\n /* Parallel index stat data preload? */\n int core_preload_index = 0;\n \ndiff --git a/wt-status.c b/wt-status.c\nindex 2a9658b..f6f197e 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -45,7 +45,7 @@ static void status_vprintf(struct wt_status *s, int at_bol, const char *color,\n \n \tstrbuf_vaddf(&sb, fmt, ap);\n \tif (!sb.len) {\n-\t\tstrbuf_addch(&sb, '#');\n+\t\tstrbuf_addch(&sb, comment_line_char);\n \t\tif (!trail)\n \t\t\tstrbuf_addch(&sb, ' ');\n \t\tcolor_print_strbuf(s->fp, color, &sb);\n@@ -59,7 +59,7 @@ static void status_vprintf(struct wt_status *s, int at_bol, const char *color,\n \n \t\tstrbuf_reset(&linebuf);\n \t\tif (at_bol) {\n-\t\t\tstrbuf_addch(&linebuf, '#');\n+\t\t\tstrbuf_addch(&linebuf, comment_line_char);\n \t\t\tif (*line != '\\n' && *line != '\\t')\n \t\t\t\tstrbuf_addch(&linebuf, ' ');\n \t\t}\n@@ -760,8 +760,10 @@ static void wt_status_print_tracking(struct wt_status *s)\n \n \tfor (cp = sb.buf; (ep = strchr(cp, '\\n')) != NULL; cp = ep + 1)\n \t\tcolor_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s),\n-\t\t\t\t \"# %.*s\", (int)(ep - cp), cp);\n-\tcolor_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), \"#\");\n+\t\t\t\t \"%c %.*s\", comment_line_char,\n+\t\t\t\t (int)(ep - cp), cp);\n+\tcolor_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), \"%c\",\n+\t\t\t comment_line_char);\n }\n \n static int has_unmerged(struct wt_status *s)\n-- \n1.8.1.351.g191b7b1\n"},{"id":"206958","messageId":"1358275827-5244-1-git-send-email-ralf.thielow@gmail.com","threadId":"32562","inReplyTo":"7vk3rk25iw.fsf_-_@alter.siamese.dyndns.org","subject":"[PATCH] Allow custom \"comment char\"","fromName":"Ralf Thielow","fromEmail":"ralf.thielow@gmail.com","sentAt":"2013-01-15T18:50:27Z","receivedAt":"2013-01-15T18:50:27Z","isPatch":true,"sender":{"key":"ralf.thielow@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1275832?v=4"},"body":"From: Junio C Hamano <gitster@pobox.com>\n\nSome users do want to write a line that begin with a pound sign, #,\nin their commit log message.  Many tracking system recognise\na token of #<bugid> form, for example.\n\nThe support we offer these use cases is not very friendly to the end\nusers.  They have a choice between\n\n - Don't do it.  Avoid such a line by rewrapping or indenting; and\n\n - Use --cleanup=whitespace but remove all the hint lines we add.\n\nGive them a way to set a custom comment char, e.g.\n\n    $ git -c core.commentchar=\"%\" commit\n\nso that they do not have to do either of the two workarounds.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Ralf Thielow <ralf.thielow@gmail.com>\n---\n Documentation/config.txt               |  6 ++++\n Documentation/technical/api-strbuf.txt | 10 +++++++\n builtin/branch.c                       | 10 +++----\n builtin/commit.c                       | 12 ++++----\n builtin/fmt-merge-msg.c                |  2 +-\n builtin/merge.c                        |  5 ++--\n builtin/notes.c                        | 34 ++++++++++-------------\n builtin/stripspace.c                   |  2 +-\n builtin/tag.c                          | 35 ++++++++++++------------\n cache.h                                |  6 ++++\n config.c                               |  8 ++++++\n environment.c                          |  6 ++++\n git-submodule.sh                       | 14 +++++++---\n strbuf.c                               | 38 ++++++++++++++++++++++++++\n strbuf.h                               |  4 +++\n t/t7502-commit.sh                      |  7 +++++\n t/t7508-status.sh                      | 50 ++++++++++++++++++++++++++++++++++\n wt-status.c                            | 10 ++++---\n 18 files changed, 198 insertions(+), 61 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex d5809e0..e99b9f2 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -528,6 +528,12 @@ core.editor::\n \tvariable when it is set, and the environment variable\n \t`GIT_EDITOR` is not set.  See linkgit:git-var[1].\n \n+core.commentchar::\n+\tCommands such as `commit` and `tag` that lets you edit\n+\tmessages consider a line that begins with this character\n+\tcommented, and removes them after the editor returns\n+\t(default '#').\n+\n sequence.editor::\n \tText editor used by `git rebase -i` for editing the rebase insn file.\n \tThe value is meant to be interpreted by the shell when it is used.\ndiff --git a/Documentation/technical/api-strbuf.txt b/Documentation/technical/api-strbuf.txt\nindex 84686b5..6767102 100644\n--- a/Documentation/technical/api-strbuf.txt\n+++ b/Documentation/technical/api-strbuf.txt\n@@ -156,6 +156,11 @@ then they will free() it.\n \tRemove the bytes between `pos..pos+len` and replace it with the given\n \tdata.\n \n+`strbuf_commented_addstr`::\n+\n+\tAdd a NUL-terminated string prepended by a comment character and a blank\n+\tto the buffer.\n+\n `strbuf_add`::\n \n \tAdd data of given length to the buffer.\n@@ -229,6 +234,11 @@ which can be used by the programmer of the callback as she sees fit.\n \n \tAdd a formatted string to the buffer.\n \n+`strbuf_commented_addf`::\n+\n+\tAdd a formatted string prepended by a comment character and a\n+\tblank to the buffer.\n+\n `strbuf_fread`::\n \n \tRead a given size of data from a FILE* pointer to the buffer.\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex 873f624..3548271 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -706,11 +706,11 @@ static int edit_branch_description(const char *branch_name)\n \tread_branch_desc(&buf, branch_name);\n \tif (!buf.len || buf.buf[buf.len-1] != '\\n')\n \t\tstrbuf_addch(&buf, '\\n');\n-\tstrbuf_addf(&buf,\n-\t\t    \"# Please edit the description for the branch\\n\"\n-\t\t    \"#   %s\\n\"\n-\t\t    \"# Lines starting with '#' will be stripped.\\n\",\n-\t\t    branch_name);\n+\tstrbuf_commented_addf(&buf,\n+\t\t    \"Please edit the description for the branch\\n\"\n+\t\t    \"  %s\\n\"\n+\t\t    \"Lines starting with '%c' will be stripped.\\n\",\n+\t\t    branch_name, comment_line_char);\n \tfp = fopen(git_path(edit_description), \"w\");\n \tif ((fwrite(buf.buf, 1, buf.len, fp) < buf.len) || fclose(fp)) {\n \t\tstrbuf_release(&buf);\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex d6dd3df..f95f64a 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -733,15 +733,15 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \t\tif (cleanup_mode == CLEANUP_ALL)\n \t\t\tstatus_printf(s, GIT_COLOR_NORMAL,\n \t\t\t\t_(\"Please enter the commit message for your changes.\"\n-\t\t\t\t\" Lines starting\\nwith '#' will be ignored, and an empty\"\n-\t\t\t\t\" message aborts the commit.\\n\"));\n+\t\t\t\t  \" Lines starting\\nwith '%c' will be ignored, and an empty\"\n+\t\t\t\t  \" message aborts the commit.\\n\"), comment_line_char);\n \t\telse /* CLEANUP_SPACE, that is. */\n \t\t\tstatus_printf(s, GIT_COLOR_NORMAL,\n \t\t\t\t_(\"Please enter the commit message for your changes.\"\n-\t\t\t\t\" Lines starting\\n\"\n-\t\t\t\t\"with '#' will be kept; you may remove them\"\n-\t\t\t\t\" yourself if you want to.\\n\"\n-\t\t\t\t\"An empty message aborts the commit.\\n\"));\n+\t\t\t\t  \" Lines starting\\n\"\n+\t\t\t\t  \"with '%c' will be kept; you may remove them\"\n+\t\t\t\t  \" yourself if you want to.\\n\"\n+\t\t\t\t  \"An empty message aborts the commit.\\n\"), comment_line_char);\n \t\tif (only_include_assumed)\n \t\t\tstatus_printf_ln(s, GIT_COLOR_NORMAL,\n \t\t\t\t\t\"%s\", only_include_assumed);\ndiff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c\nindex d9af43c..d0fcd34 100644\n--- a/builtin/fmt-merge-msg.c\n+++ b/builtin/fmt-merge-msg.c\n@@ -470,7 +470,7 @@ static void fmt_tag_signature(struct strbuf *tagbuf,\n \tstrbuf_complete_line(tagbuf);\n \tif (sig->len) {\n \t\tstrbuf_addch(tagbuf, '\\n');\n-\t\tstrbuf_add_lines(tagbuf, \"# \", sig->buf, sig->len);\n+\t\tstrbuf_commented_addstr(tagbuf, sig->buf);\n \t}\n }\n \ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 9307e9c..7c8922c 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -788,17 +788,16 @@ static const char merge_editor_comment[] =\n N_(\"Please enter a commit message to explain why this merge is necessary,\\n\"\n    \"especially if it merges an updated upstream into a topic branch.\\n\"\n    \"\\n\"\n-   \"Lines starting with '#' will be ignored, and an empty message aborts\\n\"\n+   \"Lines starting with '%c' will be ignored, and an empty message aborts\\n\"\n    \"the commit.\\n\");\n \n static void prepare_to_commit(struct commit_list *remoteheads)\n {\n \tstruct strbuf msg = STRBUF_INIT;\n-\tconst char *comment = _(merge_editor_comment);\n \tstrbuf_addbuf(&msg, &merge_msg);\n \tstrbuf_addch(&msg, '\\n');\n \tif (0 < option_edit)\n-\t\tstrbuf_add_lines(&msg, \"# \", comment, strlen(comment));\n+\t\tstrbuf_commented_addf(&msg, _(merge_editor_comment), comment_line_char);\n \twrite_merge_msg(&msg);\n \tif (run_hook(get_index_file(), \"prepare-commit-msg\",\n \t\t     git_path(\"MERGE_MSG\"), \"merge\", NULL, NULL))\ndiff --git a/builtin/notes.c b/builtin/notes.c\nindex 453457a..5e84e35 100644\n--- a/builtin/notes.c\n+++ b/builtin/notes.c\n@@ -92,10 +92,7 @@ static const char * const git_notes_get_ref_usage[] = {\n };\n \n static const char note_template[] =\n-\t\"\\n\"\n-\t\"#\\n\"\n-\t\"# Write/edit the notes for the following object:\\n\"\n-\t\"#\\n\";\n+\t\"Write/edit the notes for the following object:\";\n \n struct msg_arg {\n \tint given;\n@@ -129,7 +126,7 @@ static void write_commented_object(int fd, const unsigned char *object)\n \t\t{\"show\", \"--stat\", \"--no-notes\", sha1_to_hex(object), NULL};\n \tstruct child_process show;\n \tstruct strbuf buf = STRBUF_INIT;\n-\tFILE *show_out;\n+\tstruct strbuf cbuf = STRBUF_INIT;\n \n \t/* Invoke \"git show --stat --no-notes $object\" */\n \tmemset(&show, 0, sizeof(show));\n@@ -142,21 +139,14 @@ static void write_commented_object(int fd, const unsigned char *object)\n \t\tdie(_(\"unable to start 'show' for object '%s'\"),\n \t\t    sha1_to_hex(object));\n \n-\t/* Open the output as FILE* so strbuf_getline() can be used. */\n-\tshow_out = xfdopen(show.out, \"r\");\n-\tif (show_out == NULL)\n-\t\tdie_errno(_(\"can't fdopen 'show' output fd\"));\n+\tif (strbuf_read(&buf, show.out, 0) < 0)\n+\t\tdie_errno(_(\"could not read 'show' output\"));\n+\tstrbuf_commented_addstr(&cbuf, buf.buf);\n+\twrite_or_die(fd, cbuf.buf, cbuf.len);\n \n-\t/* Prepend \"# \" to each output line and write result to 'fd' */\n-\twhile (strbuf_getline(&buf, show_out, '\\n') != EOF) {\n-\t\twrite_or_die(fd, \"# \", 2);\n-\t\twrite_or_die(fd, buf.buf, buf.len);\n-\t\twrite_or_die(fd, \"\\n\", 1);\n-\t}\n+\tstrbuf_release(&cbuf);\n \tstrbuf_release(&buf);\n-\tif (fclose(show_out))\n-\t\tdie_errno(_(\"failed to close pipe to 'show' for object '%s'\"),\n-\t\t\t  sha1_to_hex(object));\n+\n \tif (finish_command(&show))\n \t\tdie(_(\"failed to finish 'show' for object '%s'\"),\n \t\t    sha1_to_hex(object));\n@@ -170,6 +160,7 @@ static void create_note(const unsigned char *object, struct msg_arg *msg,\n \n \tif (msg->use_editor || !msg->given) {\n \t\tint fd;\n+\t\tstruct strbuf buf = STRBUF_INIT;\n \n \t\t/* write the template message before editing: */\n \t\tpath = git_pathdup(\"NOTES_EDITMSG\");\n@@ -181,11 +172,16 @@ static void create_note(const unsigned char *object, struct msg_arg *msg,\n \t\t\twrite_or_die(fd, msg->buf.buf, msg->buf.len);\n \t\telse if (prev && !append_only)\n \t\t\twrite_note_data(fd, prev);\n-\t\twrite_or_die(fd, note_template, strlen(note_template));\n+\n+\t\tstrbuf_addf(&buf, \"\\n%c\\n\", comment_line_char);\n+\t\tstrbuf_commented_addstr(&buf, note_template);\n+\t\tstrbuf_addf(&buf, \"\\n%c\\n\", comment_line_char);\n+\t\twrite_or_die(fd, buf.buf, buf.len);\n \n \t\twrite_commented_object(fd, object);\n \n \t\tclose(fd);\n+\t\tstrbuf_release(&buf);\n \t\tstrbuf_reset(&(msg->buf));\n \n \t\tif (launch_editor(path, &(msg->buf), NULL)) {\ndiff --git a/builtin/stripspace.c b/builtin/stripspace.c\nindex f16986c..600ca66 100644\n--- a/builtin/stripspace.c\n+++ b/builtin/stripspace.c\n@@ -45,7 +45,7 @@ void stripspace(struct strbuf *sb, int skip_comments)\n \t\teol = memchr(sb->buf + i, '\\n', sb->len - i);\n \t\tlen = eol ? eol - (sb->buf + i) + 1 : sb->len - i;\n \n-\t\tif (skip_comments && len && sb->buf[i] == '#') {\n+\t\tif (skip_comments && len && sb->buf[i] == comment_line_char) {\n \t\t\tnewlen = 0;\n \t\t\tcontinue;\n \t\t}\ndiff --git a/builtin/tag.c b/builtin/tag.c\nindex 9c3e067..e1b72be 100644\n--- a/builtin/tag.c\n+++ b/builtin/tag.c\n@@ -246,19 +246,13 @@ static int do_sign(struct strbuf *buffer)\n }\n \n static const char tag_template[] =\n-\tN_(\"\\n\"\n-\t\"#\\n\"\n-\t\"# Write a tag message\\n\"\n-\t\"# Lines starting with '#' will be ignored.\\n\"\n-\t\"#\\n\");\n+\tN_(\"Write a tag message\\n\"\n+\t\"Lines starting with '%c' will be ignored.\");\n \n static const char tag_template_nocleanup[] =\n-\tN_(\"\\n\"\n-\t\"#\\n\"\n-\t\"# Write a tag message\\n\"\n-\t\"# Lines starting with '#' will be kept; you may remove them\"\n-\t\" yourself if you want to.\\n\"\n-\t\"#\\n\");\n+\tN_(\"Write a tag message\\n\"\n+\t\"Lines starting with '%c' will be kept; you may remove them\"\n+\t\" yourself if you want to.\");\n \n static int git_tag_config(const char *var, const char *value, void *cb)\n {\n@@ -346,14 +340,19 @@ static void create_tag(const unsigned char *object, const char *tag,\n \t\tif (fd < 0)\n \t\t\tdie_errno(_(\"could not create file '%s'\"), path);\n \n-\t\tif (!is_null_sha1(prev))\n+\t\tif (!is_null_sha1(prev)) {\n \t\t\twrite_tag_body(fd, prev);\n-\t\telse if (opt->cleanup_mode == CLEANUP_ALL)\n-\t\t\twrite_or_die(fd, _(tag_template),\n-\t\t\t\t\tstrlen(_(tag_template)));\n-\t\telse\n-\t\t\twrite_or_die(fd, _(tag_template_nocleanup),\n-\t\t\t\t\tstrlen(_(tag_template_nocleanup)));\n+\t\t} else {\n+\t\t\tstruct strbuf buf = STRBUF_INIT;\n+\t\t\tstrbuf_addf(&buf, \"\\n%c\\n\", comment_line_char);\n+\t\t\tif (opt->cleanup_mode == CLEANUP_ALL)\n+\t\t\t\tstrbuf_commented_addf(&buf, _(tag_template), comment_line_char);\n+\t\t\telse\n+\t\t\t\tstrbuf_commented_addf(&buf, _(tag_template_nocleanup), comment_line_char);\n+\t\t\tstrbuf_addf(&buf, \"\\n%c\\n\", comment_line_char);\n+\t\t\twrite_or_die(fd, buf.buf, buf.len);\n+\t\t\tstrbuf_release(&buf);\n+\t\t}\n \t\tclose(fd);\n \n \t\tif (launch_editor(path, buf, NULL)) {\ndiff --git a/cache.h b/cache.h\nindex c257953..0b435a4 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -562,6 +562,12 @@ extern int core_preload_index;\n extern int core_apply_sparse_checkout;\n extern int precomposed_unicode;\n \n+/*\n+ * The character that begins a commented line in user-editable file\n+ * that is subject to stripspace.\n+ */\n+extern char comment_line_char;\n+\n enum branch_track {\n \tBRANCH_TRACK_UNSPECIFIED = -1,\n \tBRANCH_TRACK_NEVER = 0,\ndiff --git a/config.c b/config.c\nindex 7b444b6..d873c59 100644\n--- a/config.c\n+++ b/config.c\n@@ -717,6 +717,14 @@ static int git_default_core_config(const char *var, const char *value)\n \tif (!strcmp(var, \"core.editor\"))\n \t\treturn git_config_string(&editor_program, var, value);\n \n+\tif (!strcmp(var, \"core.commentchar\")) {\n+\t\tconst char *comment;\n+\t\tint ret = git_config_string(&comment, var, value);\n+\t\tif (!ret)\n+\t\t\tcomment_line_char = comment[0];\n+\t\treturn ret;\n+\t}\n+\n \tif (!strcmp(var, \"core.askpass\"))\n \t\treturn git_config_string(&askpass_program, var, value);\n \ndiff --git a/environment.c b/environment.c\nindex 85edd7f..a40c38b 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -62,6 +62,12 @@ int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */\n struct startup_info *startup_info;\n unsigned long pack_size_limit_cfg;\n \n+/*\n+ * The character that begins a commented line in user-editable file\n+ * that is subject to stripspace.\n+ */\n+char comment_line_char = '#';\n+\n /* Parallel index stat data preload? */\n int core_preload_index = 0;\n \ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 22ec5b6..1b8d95f 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -975,13 +975,19 @@ cmd_summary() {\n \t\techo\n \tdone |\n \tif test -n \"$for_status\"; then\n+\t\tcomment_char=`git config core.commentchar`\n+\t\tif [ ! -n \"$comment_char\" ]; then\n+\t\t\tcomment_char='#'\n+\t\telif [ ${#comment_char} -gt 1 ]; then\n+\t\t\tcomment_char=`expr substr $comment_char 1 1`\n+\t\tfi\n \t\tif [ -n \"$files\" ]; then\n-\t\t\tgettextln \"# Submodules changed but not updated:\"\n+\t\t\teval_gettextln \"\\$comment_char Submodules changed but not updated:\"\n \t\telse\n-\t\t\tgettextln \"# Submodule changes to be committed:\"\n+\t\t\teval_gettextln \"\\$comment_char Submodule changes to be committed:\"\n \t\tfi\n-\t\techo \"#\"\n-\t\tsed -e 's|^|# |' -e 's|^# $|#|'\n+\t\techo \"$comment_char\"\n+\t\tsed -e \"s|^|$comment_char |\" -e \"s|^$comment_char $|$comment_char|\"\n \telse\n \t\tcat\n \tfi\ndiff --git a/strbuf.c b/strbuf.c\nindex 9a373be..8af4b4f 100644\n--- a/strbuf.c\n+++ b/strbuf.c\n@@ -204,6 +204,44 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...)\n \tva_end(ap);\n }\n \n+void strbuf_commented_addstr(struct strbuf *sb, const char *s)\n+{\n+\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct strbuf prefix = STRBUF_INIT;\n+\n+\tstrbuf_addf(&prefix, \"%c \", comment_line_char);\n+\tstrbuf_addstr(&buf, s);\n+\tstrbuf_add_lines(sb, prefix.buf, buf.buf, buf.len);\n+\n+\t// remove additional '\\n' added by strbuf_add_lines()\n+\tif (sb->len && sb->buf[sb->len - 1] != buf.buf[buf.len - 1])\n+\t\tstrbuf_remove(sb, sb->len - 1, 1);\n+\n+\tstrbuf_release(&prefix);\n+\tstrbuf_release(&buf);\n+}\n+\n+void strbuf_commented_addf(struct strbuf *sb, const char *fmt, ...)\n+{\n+\tva_list params;\n+\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct strbuf prefix = STRBUF_INIT;\n+\n+\tva_start(params, fmt);\n+\tstrbuf_vaddf(&buf, fmt, params);\n+\tva_end(params);\n+\n+\tstrbuf_addf(&prefix, \"%c \", comment_line_char);\n+\tstrbuf_add_lines(sb, prefix.buf, buf.buf, buf.len);\n+\n+\t// remove additional '\\n' added by strbuf_add_lines()\n+\tif (sb->len && sb->buf[sb->len - 1] != buf.buf[buf.len - 1])\n+\t\tstrbuf_remove(sb, sb->len - 1, 1);\n+\n+\tstrbuf_release(&prefix);\n+\tstrbuf_release(&buf);\n+}\n+\n void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap)\n {\n \tint len;\ndiff --git a/strbuf.h b/strbuf.h\nindex ecae4e2..8d5afd5 100644\n--- a/strbuf.h\n+++ b/strbuf.h\n@@ -110,6 +110,8 @@ extern void strbuf_remove(struct strbuf *, size_t pos, size_t len);\n extern void strbuf_splice(struct strbuf *, size_t pos, size_t len,\n                           const void *, size_t);\n \n+extern void strbuf_commented_addstr(struct strbuf *sb, const char *s);\n+\n extern void strbuf_add(struct strbuf *, const void *, size_t);\n static inline void strbuf_addstr(struct strbuf *sb, const char *s) {\n \tstrbuf_add(sb, s, strlen(s));\n@@ -131,6 +133,8 @@ extern void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *\n \n __attribute__((format (printf,2,3)))\n extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);\n+__attribute__((format (printf, 2, 3)))\n+extern void strbuf_commented_addf(struct strbuf *sb, const char *fmt, ...);\n __attribute__((format (printf,2,0)))\n extern void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap);\n \ndiff --git a/t/t7502-commit.sh b/t/t7502-commit.sh\nindex 1a5cb69..6a2c67c 100755\n--- a/t/t7502-commit.sh\n+++ b/t/t7502-commit.sh\n@@ -447,4 +447,11 @@ use_template=\"-t template\"\n \n try_commit_status_combo\n \n+test_expect_success 'commit --status with custom comment character' '\n+\ttest_when_finished \"git config --unset core.commentchar\" &&\n+\tgit config core.commentchar \";\" &&\n+\ttry_commit --status &&\n+\ttest_i18ngrep \"^; Changes to be committed:\" .git/COMMIT_EDITMSG\n+'\n+\n test_done\ndiff --git a/t/t7508-status.sh b/t/t7508-status.sh\nindex e313ef1..a79c032 100755\n--- a/t/t7508-status.sh\n+++ b/t/t7508-status.sh\n@@ -1254,6 +1254,56 @@ test_expect_success \".git/config ignore=dirty doesn't suppress submodule summary\n '\n \n cat > expect << EOF\n+; On branch master\n+; Changes to be committed:\n+;   (use \"git reset HEAD <file>...\" to unstage)\n+;\n+;\tmodified:   sm\n+;\n+; Changes not staged for commit:\n+;   (use \"git add <file>...\" to update what will be committed)\n+;   (use \"git checkout -- <file>...\" to discard changes in working directory)\n+;\n+;\tmodified:   dir1/modified\n+;\tmodified:   sm (new commits)\n+;\n+; Submodule changes to be committed:\n+;\n+; * sm $head...$new_head (1):\n+;   > Add bar\n+;\n+; Submodules changed but not updated:\n+;\n+; * sm $new_head...$head2 (1):\n+;   > 2nd commit\n+;\n+; Untracked files:\n+;   (use \"git add <file>...\" to include in what will be committed)\n+;\n+;\t.gitmodules\n+;\tdir1/untracked\n+;\tdir2/modified\n+;\tdir2/untracked\n+;\texpect\n+;\toutput\n+;\tuntracked\n+EOF\n+\n+test_expect_success \"status (core.commentchar with submodule summary)\" '\n+\ttest_when_finished \"git config --unset core.commentchar\" &&\n+\tgit config core.commentchar \";\" &&\n+\tgit status >output &&\n+\ttest_i18ncmp expect output\n+'\n+\n+test_expect_success \"status (core.commentchar with two chars with submodule summary)\" '\n+\ttest_when_finished \"git config --unset core.commentchar\" &&\n+\tgit config core.commentchar \";;\" &&\n+\tgit status >output &&\n+\ttest_i18ncmp expect output\n+'\n+\n+cat > expect << EOF\n # On branch master\n # Changes not staged for commit:\n #   (use \"git add <file>...\" to update what will be committed)\ndiff --git a/wt-status.c b/wt-status.c\nindex 2a9658b..f6f197e 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -45,7 +45,7 @@ static void status_vprintf(struct wt_status *s, int at_bol, const char *color,\n \n \tstrbuf_vaddf(&sb, fmt, ap);\n \tif (!sb.len) {\n-\t\tstrbuf_addch(&sb, '#');\n+\t\tstrbuf_addch(&sb, comment_line_char);\n \t\tif (!trail)\n \t\t\tstrbuf_addch(&sb, ' ');\n \t\tcolor_print_strbuf(s->fp, color, &sb);\n@@ -59,7 +59,7 @@ static void status_vprintf(struct wt_status *s, int at_bol, const char *color,\n \n \t\tstrbuf_reset(&linebuf);\n \t\tif (at_bol) {\n-\t\t\tstrbuf_addch(&linebuf, '#');\n+\t\t\tstrbuf_addch(&linebuf, comment_line_char);\n \t\t\tif (*line != '\\n' && *line != '\\t')\n \t\t\t\tstrbuf_addch(&linebuf, ' ');\n \t\t}\n@@ -760,8 +760,10 @@ static void wt_status_print_tracking(struct wt_status *s)\n \n \tfor (cp = sb.buf; (ep = strchr(cp, '\\n')) != NULL; cp = ep + 1)\n \t\tcolor_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s),\n-\t\t\t\t \"# %.*s\", (int)(ep - cp), cp);\n-\tcolor_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), \"#\");\n+\t\t\t\t \"%c %.*s\", comment_line_char,\n+\t\t\t\t (int)(ep - cp), cp);\n+\tcolor_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), \"%c\",\n+\t\t\t comment_line_char);\n }\n \n static int has_unmerged(struct wt_status *s)\n-- \n1.8.1.291.g185e8f6\n"},{"id":"206962","messageId":"7v622y45wy.fsf@alter.siamese.dyndns.org","threadId":"32562","inReplyTo":"1358275827-5244-1-git-send-email-ralf.thielow@gmail.com","subject":"Re: [PATCH] Allow custom \"comment char\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-01-15T19:12:13Z","receivedAt":"2013-01-15T19:12:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ralf Thielow <ralf.thielow@gmail.com> writes:\n\n> From: Junio C Hamano <gitster@pobox.com>\n>\n> Some users do want to write a line that begin with a pound sign, #,\n> in their commit log message.  Many tracking system recognise\n> a token of #<bugid> form, for example.\n>\n> The support we offer these use cases is not very friendly to the end\n> users.  They have a choice between\n>\n>  - Don't do it.  Avoid such a line by rewrapping or indenting; and\n>\n>  - Use --cleanup=whitespace but remove all the hint lines we add.\n>\n> Give them a way to set a custom comment char, e.g.\n>\n>     $ git -c core.commentchar=\"%\" commit\n>\n> so that they do not have to do either of the two workarounds.\n>\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> Signed-off-by: Ralf Thielow <ralf.thielow@gmail.com>\n> ---\n\nIt would have helped if you said you finished the NEEDSWORK: in\nbuiltin/branch.c in the earlier draft with strbuf_commented_*\nfunctions ;-)\n\nLooks like a good progress overall, except for nits here and there.\n\n> diff --git a/builtin/notes.c b/builtin/notes.c\n> index 453457a..5e84e35 100644\n> --- a/builtin/notes.c\n> +++ b/builtin/notes.c\n> @@ -92,10 +92,7 @@ static const char * const git_notes_get_ref_usage[] = {\n>  };\n>  \n>  static const char note_template[] =\n> -\t\"\\n\"\n> -\t\"#\\n\"\n> -\t\"# Write/edit the notes for the following object:\\n\"\n> -\t\"#\\n\";\n> +\t\"Write/edit the notes for the following object:\";\n\nI think this (and its use site that manually adds \"\\n#\\n\") is a\nsymptom of strbuf_commented_add*() function not designed right.\nWhen it iterates over lines and adds each of them in a commented out\nform, it could check if the line is an empty one and refrain from\nadding a trailing SP if that is the case.  Then this can become\n\n    \"\\nWrite/edit the notes...\\n\\n\";\n\nYou have to create the \"\\n\" blank line at the beginning manually,\nbut that is logically outside the commented out block, so it is not\na problem.\n\n> @@ -181,11 +172,16 @@ static void create_note(const unsigned char *object, struct msg_arg *msg,\n>  \t\t\twrite_or_die(fd, msg->buf.buf, msg->buf.len);\n>  \t\telse if (prev && !append_only)\n>  \t\t\twrite_note_data(fd, prev);\n> -\t\twrite_or_die(fd, note_template, strlen(note_template));\n> +\n> +\t\tstrbuf_addf(&buf, \"\\n%c\\n\", comment_line_char);\n> +\t\tstrbuf_commented_addstr(&buf, note_template);\n> +\t\tstrbuf_addf(&buf, \"\\n%c\\n\", comment_line_char);\n> +\t\twrite_or_die(fd, buf.buf, buf.len);\n\n> diff --git a/builtin/tag.c b/builtin/tag.c\n> index 9c3e067..e1b72be 100644\n> --- a/builtin/tag.c\n> +++ b/builtin/tag.c\n> @@ -246,19 +246,13 @@ static int do_sign(struct strbuf *buffer)\n>  }\n>  \n>  static const char tag_template[] =\n> -\tN_(\"\\n\"\n> -\t\"#\\n\"\n> -\t\"# Write a tag message\\n\"\n> -\t\"# Lines starting with '#' will be ignored.\\n\"\n> -\t\"#\\n\");\n> +\tN_(\"Write a tag message\\n\"\n> +\t\"Lines starting with '%c' will be ignored.\");\n> ...\n> +\t\t\telse\n> +\t\t\t\tstrbuf_commented_addf(&buf, _(tag_template_nocleanup), comment_line_char);\n> +\t\t\tstrbuf_addf(&buf, \"\\n%c\\n\", comment_line_char);\n> +\t\t\twrite_or_die(fd, buf.buf, buf.len);\n\nSame here.\n\n> diff --git a/git-submodule.sh b/git-submodule.sh\n> index 22ec5b6..1b8d95f 100755\n> --- a/git-submodule.sh\n> +++ b/git-submodule.sh\n> @@ -975,13 +975,19 @@ cmd_summary() {\n>  \t\techo\n>  \tdone |\n>  \tif test -n \"$for_status\"; then\n> +\t\tcomment_char=`git config core.commentchar`\n> +\t\tif [ ! -n \"$comment_char\" ]; then\n> +\t\t\tcomment_char='#'\n> +\t\telif [ ${#comment_char} -gt 1 ]; then\n\nNot portable, I think.\n\n> +\t\techo \"$comment_char\"\n> +\t\tsed -e \"s|^|$comment_char |\" -e \"s|^$comment_char $|$comment_char|\"\n\nCan $comment_char be a '|'?\n\n> diff --git a/strbuf.c b/strbuf.c\n> index 9a373be..8af4b4f 100644\n> --- a/strbuf.c\n> +++ b/strbuf.c\n> @@ -204,6 +204,44 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...)\n>  \tva_end(ap);\n>  }\n>  \n> +void strbuf_commented_addstr(struct strbuf *sb, const char *s)\n> +{\n> +\tstruct strbuf buf = STRBUF_INIT;\n> +\tstruct strbuf prefix = STRBUF_INIT;\n> +\n> +\tstrbuf_addf(&prefix, \"%c \", comment_line_char);\n> +\tstrbuf_addstr(&buf, s);\n> +\tstrbuf_add_lines(sb, prefix.buf, buf.buf, buf.len);\n> +\n> +\t// remove additional '\\n' added by strbuf_add_lines()\n\nNo C++ comments.\n"},{"id":"207031","messageId":"7vmww9zlwj.fsf@alter.siamese.dyndns.org","threadId":"32562","inReplyTo":"7v622y45wy.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] Allow custom \"comment char\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-01-16T06:23:24Z","receivedAt":"2013-01-16T06:23:24Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Ralf Thielow <ralf.thielow@gmail.com> writes:\n> ...\n> Looks like a good progress overall, except for nits here and there.\n>\n>> diff --git a/builtin/notes.c b/builtin/notes.c\n>> index 453457a..5e84e35 100644\n>> --- a/builtin/notes.c\n>> +++ b/builtin/notes.c\n>> @@ -92,10 +92,7 @@ static const char * const git_notes_get_ref_usage[] = {\n>>  };\n>>  \n>>  static const char note_template[] =\n>> -\t\"\\n\"\n>> -\t\"#\\n\"\n>> -\t\"# Write/edit the notes for the following object:\\n\"\n>> -\t\"#\\n\";\n>> +\t\"Write/edit the notes for the following object:\";\n>\n> I think this (and its use site that manually adds \"\\n#\\n\") is a\n> symptom of strbuf_commented_add*() function not designed right.\n> When it iterates over lines and adds each of them in a commented out\n> form, it could check if the line is an empty one and refrain from\n> adding a trailing SP if that is the case.  Then this can become\n>\n>     \"\\nWrite/edit the notes...\\n\\n\";\n>\n> You have to create the \"\\n\" blank line at the beginning manually,\n> but that is logically outside the commented out block, so it is not\n> a problem.\n\n>> diff --git a/git-submodule.sh b/git-submodule.sh\n>> index 22ec5b6..1b8d95f 100755\n>> --- a/git-submodule.sh\n>> +++ b/git-submodule.sh\n>> @@ -975,13 +975,19 @@ cmd_summary() {\n>>  \t\techo\n>>  \tdone |\n>>  \tif test -n \"$for_status\"; then\n>> +\t\tcomment_char=`git config core.commentchar`\n>> +\t\tif [ ! -n \"$comment_char\" ]; then\n>> +\t\t\tcomment_char='#'\n>> +\t\telif [ ${#comment_char} -gt 1 ]; then\n>\n> Not portable, I think.\n>\n>> +\t\techo \"$comment_char\"\n>> +\t\tsed -e \"s|^|$comment_char |\" -e \"s|^$comment_char $|$comment_char|\"\n>\n> Can $comment_char be a '|'?\n\nI think it may be the easiest to teach one of the pure-helper\ncommands, e.g. \"git stripspace\", to do this kind of thing for you\nwith a new option.\n\nTo summarize, along the lines of the attached patch (on top of\njc/custom-comment-char topic).\n\n builtin/branch.c     | 20 +++++++++-----------\n builtin/stripspace.c | 35 +++++++++++++++++++++++++++++------\n strbuf.c             | 42 +++++++++++++++++++++++++++++++++++++++++-\n strbuf.h             |  4 ++++\n 4 files changed, 83 insertions(+), 18 deletions(-)\n\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex 7f8865a..42de4c5 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -707,18 +707,16 @@ static int edit_branch_description(const char *branch_name)\n \tif (!buf.len || buf.buf[buf.len-1] != '\\n')\n \t\tstrbuf_addch(&buf, '\\n');\n \t/*\n-\t * NEEDSWORK: introduce a strbuf_commented_addf(), possibly\n-\t * sharing code with status_vprintf(), that makes each line\n-\t * commented with comment_line_char, and use it here and from\n-\t * other places (e.g. write_commented_object() and create_note()\n-\t * in builtin/notes.c and create_tag() in builtin/tag.c).\n+\t * NEEDSWORK: convert more code to use this:\n+\t * (e.g. write_commented_object() and create_note() in\n+\t * builtin/notes.c and create_tag() in builtin/tag.c).\n \t */\n-\tstrbuf_addf(&buf,\n-\t\t    \"%c Please edit the description for the branch\\n\"\n-\t\t    \"%c   %s\\n\"\n-\t\t    \"%c Lines starting with '%c' will be stripped.\\n\",\n-\t\t    comment_line_char, comment_line_char,\n-\t\t    branch_name, comment_line_char, comment_line_char);\n+\tstrbuf_commented_addf(&buf,\n+\t\t\t      \"Please edit the description for the branch\\n\"\n+\t\t\t      \"  %s\\n\"\n+\t\t\t      \"Lines starting with '%c' will be stripped.\\n\",\n+\t\t\t      branch_name, comment_line_char);\n+\n \tfp = fopen(git_path(edit_description), \"w\");\n \tif ((fwrite(buf.buf, 1, buf.len, fp) < buf.len) || fclose(fp)) {\n \t\tstrbuf_release(&buf);\ndiff --git a/builtin/stripspace.c b/builtin/stripspace.c\nindex 600ca66..790b500 100644\n--- a/builtin/stripspace.c\n+++ b/builtin/stripspace.c\n@@ -66,21 +66,44 @@ void stripspace(struct strbuf *sb, int skip_comments)\n \tstrbuf_setlen(sb, j);\n }\n \n+static void comment_lines(struct strbuf *buf)\n+{\n+\tchar *msg;\n+\tsize_t len;\n+\n+\tmsg = strbuf_detach(buf, &len);\n+\tstrbuf_add_commented_lines(buf, msg, len);\n+}\n+\n int cmd_stripspace(int argc, const char **argv, const char *prefix)\n {\n \tstruct strbuf buf = STRBUF_INIT;\n \tint strip_comments = 0;\n+\tenum { INVAL = 0, STRIP_SPACE = 1, COMMENT_LINES = 2 } mode = STRIP_SPACE;\n+\n+\tif (argc == 2) {\n+\t\tif (!strcmp(argv[1], \"-s\") ||\n+\t\t    !strcmp(argv[1], \"--strip-comments\")) {\n+\t\t\tstrip_comments = 1;\n+\t\t} else if (!strcmp(argv[1], \"-c\")) {\n+\t\t\tmode = COMMENT_LINES;\n+\t\t\tgit_config(git_default_config, NULL);\n+\t\t} else {\n+\t\t\tmode = INVAL;\n+\t\t}\n+\t} else if (argc > 1)\n+\t\tmode = INVAL;\n \n-\tif (argc == 2 && (!strcmp(argv[1], \"-s\") ||\n-\t\t\t\t!strcmp(argv[1], \"--strip-comments\")))\n-\t\tstrip_comments = 1;\n-\telse if (argc > 1)\n-\t\tusage(\"git stripspace [-s | --strip-comments] < input\");\n+\tif (mode == INVAL)\n+\t\tusage(\"git stripspace [-s|-c] <input\");\n \n \tif (strbuf_read(&buf, 0, 1024) < 0)\n \t\tdie_errno(\"could not read the input\");\n \n-\tstripspace(&buf, strip_comments);\n+\tif (mode == STRIP_SPACE)\n+\t\tstripspace(&buf, strip_comments);\n+\telse /* i.e. COMMENT_LINES */\n+\t\tcomment_lines(&buf);\n \n \twrite_or_die(1, buf.buf, buf.len);\n \tstrbuf_release(&buf);\ndiff --git a/strbuf.c b/strbuf.c\nindex 9a373be..d0525c8 100644\n--- a/strbuf.c\n+++ b/strbuf.c\n@@ -411,12 +411,17 @@ int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)\n \treturn len;\n }\n \n-void strbuf_add_lines(struct strbuf *out, const char *prefix,\n+static void add_lines(struct strbuf *out,\n+\t\t      const char *prefix1,\n+\t\t      const char *prefix2,\n \t\t      const char *buf, size_t size)\n {\n \twhile (size) {\n+\t\tconst char *prefix;\n \t\tconst char *next = memchr(buf, '\\n', size);\n \t\tnext = next ? (next + 1) : (buf + size);\n+\n+\t\tprefix = (prefix2 && buf[0] == '\\n') ? prefix2 : prefix1;\n \t\tstrbuf_addstr(out, prefix);\n \t\tstrbuf_add(out, buf, next - buf);\n \t\tsize -= next - buf;\n@@ -425,6 +430,41 @@ void strbuf_add_lines(struct strbuf *out, const char *prefix,\n \tstrbuf_complete_line(out);\n }\n \n+void strbuf_add_lines(struct strbuf *out, const char *prefix,\n+\t\t      const char *buf, size_t size)\n+{\n+\tadd_lines(out, prefix, NULL, buf, size);\n+}\n+\n+void strbuf_add_commented_lines(struct strbuf *out,\n+\t\t\t\tconst char *buf, size_t size)\n+{\n+\tstatic char prefix1[3];\n+\tstatic char prefix2[2];\n+\n+\tif (prefix1[0] != comment_line_char) {\n+\t\tsprintf(prefix1, \"%c \", comment_line_char);\n+\t\tsprintf(prefix2, \"%c\", comment_line_char);\n+\t}\n+\tadd_lines(out, prefix1, prefix2, buf, size);\n+}\n+\n+void strbuf_commented_addf(struct strbuf *sb, const char *fmt, ...)\n+{\n+\tva_list params;\n+\tstruct strbuf buf = STRBUF_INIT;\n+\tint incomplete_line = sb->len && sb->buf[sb->len - 1] != '\\n';\n+\n+\tva_start(params, fmt);\n+\tstrbuf_vaddf(&buf, fmt, params);\n+\tva_end(params);\n+\n+\tstrbuf_add_commented_lines(sb, buf.buf, buf.len);\n+\tif (incomplete_line)\n+\t\tsb->buf[--sb->len] = '\\0';\n+\tstrbuf_release(&buf);\n+}\n+\n void strbuf_addstr_xml_quoted(struct strbuf *buf, const char *s)\n {\n \twhile (*s) {\ndiff --git a/strbuf.h b/strbuf.h\nindex ecae4e2..1eb0c75 100644\n--- a/strbuf.h\n+++ b/strbuf.h\n@@ -131,10 +131,14 @@ extern void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *\n \n __attribute__((format (printf,2,3)))\n extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);\n+__attribute__((format (printf,2,3)))\n+extern void strbuf_commented_addf(struct strbuf *sb, const char *fmt, ...);\n __attribute__((format (printf,2,0)))\n extern void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap);\n \n extern void strbuf_add_lines(struct strbuf *sb, const char *prefix, const char *buf, size_t size);\n+extern void strbuf_add_commented_lines(struct strbuf *out, const char *buf, size_t size);\n+\n \n /*\n  * Append s to sb, with the characters '<', '>', '&' and '\"' converted\n"},{"id":"207036","messageId":"CAN0XMOJPgGXUeOBC=ubO0d7NweEihJvQbf2O6wxazh4juLi02g@mail.gmail.com","threadId":"32562","inReplyTo":"7vmww9zlwj.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] Allow custom \"comment char\"","fromName":"Ralf Thielow","fromEmail":"ralf.thielow@gmail.com","sentAt":"2013-01-16T08:17:40Z","receivedAt":"2013-01-16T08:17:40Z","isPatch":true,"sender":{"key":"ralf.thielow@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1275832?v=4"},"body":"2013/1/16 Junio C Hamano <gitster@pobox.com>:\n>>> diff --git a/git-submodule.sh b/git-submodule.sh\n>>> index 22ec5b6..1b8d95f 100755\n>>> --- a/git-submodule.sh\n>>> +++ b/git-submodule.sh\n>>> @@ -975,13 +975,19 @@ cmd_summary() {\n>>>              echo\n>>>      done |\n>>>      if test -n \"$for_status\"; then\n>>> +            comment_char=`git config core.commentchar`\n>>> +            if [ ! -n \"$comment_char\" ]; then\n>>> +                    comment_char='#'\n>>> +            elif [ ${#comment_char} -gt 1 ]; then\n>>\n>> Not portable, I think.\n>>\n>>> +            echo \"$comment_char\"\n>>> +            sed -e \"s|^|$comment_char |\" -e \"s|^$comment_char $|$comment_char|\"\n>>\n>> Can $comment_char be a '|'?\n>\n> I think it may be the easiest to teach one of the pure-helper\n> commands, e.g. \"git stripspace\", to do this kind of thing for you\n> with a new option.\n>\n> To summarize, along the lines of the attached patch (on top of\n> jc/custom-comment-char topic).\n\nVery good idea. I'll integrate.\nThanks\n"},{"id":"207096","messageId":"1358363928-16729-1-git-send-email-ralf.thielow@gmail.com","threadId":"32562","inReplyTo":"1358275827-5244-1-git-send-email-ralf.thielow@gmail.com","subject":"[PATCH v2] Allow custom \"comment char\"","fromName":"Ralf Thielow","fromEmail":"ralf.thielow@gmail.com","sentAt":"2013-01-16T19:18:48Z","receivedAt":"2013-01-16T19:18:48Z","isPatch":true,"sender":{"key":"ralf.thielow@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1275832?v=4"},"body":"From: Junio C Hamano <gitster@pobox.com>\n\nSome users do want to write a line that begin with a pound sign, #,\nin their commit log message.  Many tracking system recognise\na token of #<bugid> form, for example.\n\nThe support we offer these use cases is not very friendly to the end\nusers.  They have a choice between\n\n - Don't do it.  Avoid such a line by rewrapping or indenting; and\n\n - Use --cleanup=whitespace but remove all the hint lines we add.\n\nGive them a way to set a custom comment char, e.g.\n\n    $ git -c core.commentchar=\"%\" commit\n\nso that they do not have to do either of the two workarounds.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Ralf Thielow <ralf.thielow@gmail.com>\n---\nJunio, thanks for the code in your reply to the\nfirst version. It works very well and looks nice.\nI was also unhappy about this \"\\n%c\\n\" thing and\npretty unsure with the code in \"git-submodule.sh\".\nBut with this, it looks good to me. Thanks.\n\nChanges in v2:\n- extend \"git stripspace\" with an option to make\n  it's input being converted to commented lines\n- teach git-submodule.sh using this\n- rename strbuf_commented_addstr to strbuf_add_commented_lines\n  and improve it's design\n\n Documentation/config.txt               |  6 ++++\n Documentation/git-stripspace.txt       |  8 ++++-\n Documentation/technical/api-strbuf.txt | 10 ++++++\n builtin/branch.c                       | 10 +++---\n builtin/commit.c                       | 12 +++----\n builtin/fmt-merge-msg.c                |  2 +-\n builtin/merge.c                        |  5 ++-\n builtin/notes.c                        | 34 +++++++++-----------\n builtin/stripspace.c                   | 48 +++++++++++++++++++++++-----\n builtin/tag.c                          | 34 ++++++++++----------\n cache.h                                |  6 ++++\n config.c                               |  8 +++++\n environment.c                          |  6 ++++\n git-submodule.sh                       |  8 ++---\n strbuf.c                               | 58 ++++++++++++++++++++++++++++------\n strbuf.h                               |  4 +++\n t/t0030-stripspace.sh                  | 35 ++++++++++++++++++++\n t/t7502-commit.sh                      |  7 ++++\n t/t7508-status.sh                      | 50 +++++++++++++++++++++++++++++\n wt-status.c                            | 10 +++---\n 20 files changed, 283 insertions(+), 78 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex d5809e0..e99b9f2 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -528,6 +528,12 @@ core.editor::\n \tvariable when it is set, and the environment variable\n \t`GIT_EDITOR` is not set.  See linkgit:git-var[1].\n \n+core.commentchar::\n+\tCommands such as `commit` and `tag` that lets you edit\n+\tmessages consider a line that begins with this character\n+\tcommented, and removes them after the editor returns\n+\t(default '#').\n+\n sequence.editor::\n \tText editor used by `git rebase -i` for editing the rebase insn file.\n \tThe value is meant to be interpreted by the shell when it is used.\ndiff --git a/Documentation/git-stripspace.txt b/Documentation/git-stripspace.txt\nindex a80d946..e6fdfcb 100644\n--- a/Documentation/git-stripspace.txt\n+++ b/Documentation/git-stripspace.txt\n@@ -35,7 +35,13 @@ OPTIONS\n -------\n -s::\n --strip-comments::\n-\tSkip and remove all lines starting with '#'.\n+\tSkip and remove all lines starting with comment character (default '#').\n+\n+-c::\n+--comment-lines::\n+\tPrepend comment character and blank to each line. Lines will automatically\n+\tbe terminated with a newline. On empty lines, only the comment character\n+\twill be prepended.\n \n EXAMPLES\n --------\ndiff --git a/Documentation/technical/api-strbuf.txt b/Documentation/technical/api-strbuf.txt\nindex 84686b5..2c59cb2 100644\n--- a/Documentation/technical/api-strbuf.txt\n+++ b/Documentation/technical/api-strbuf.txt\n@@ -156,6 +156,11 @@ then they will free() it.\n \tRemove the bytes between `pos..pos+len` and replace it with the given\n \tdata.\n \n+`strbuf_add_commented_lines`::\n+\n+\tAdd a NUL-terminated string to the buffer. Each line will be prepended\n+\tby a comment character and a blank.\n+\n `strbuf_add`::\n \n \tAdd data of given length to the buffer.\n@@ -229,6 +234,11 @@ which can be used by the programmer of the callback as she sees fit.\n \n \tAdd a formatted string to the buffer.\n \n+`strbuf_commented_addf`::\n+\n+\tAdd a formatted string prepended by a comment character and a\n+\tblank to the buffer.\n+\n `strbuf_fread`::\n \n \tRead a given size of data from a FILE* pointer to the buffer.\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex 873f624..3548271 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -706,11 +706,11 @@ static int edit_branch_description(const char *branch_name)\n \tread_branch_desc(&buf, branch_name);\n \tif (!buf.len || buf.buf[buf.len-1] != '\\n')\n \t\tstrbuf_addch(&buf, '\\n');\n-\tstrbuf_addf(&buf,\n-\t\t    \"# Please edit the description for the branch\\n\"\n-\t\t    \"#   %s\\n\"\n-\t\t    \"# Lines starting with '#' will be stripped.\\n\",\n-\t\t    branch_name);\n+\tstrbuf_commented_addf(&buf,\n+\t\t    \"Please edit the description for the branch\\n\"\n+\t\t    \"  %s\\n\"\n+\t\t    \"Lines starting with '%c' will be stripped.\\n\",\n+\t\t    branch_name, comment_line_char);\n \tfp = fopen(git_path(edit_description), \"w\");\n \tif ((fwrite(buf.buf, 1, buf.len, fp) < buf.len) || fclose(fp)) {\n \t\tstrbuf_release(&buf);\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex d6dd3df..f95f64a 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -733,15 +733,15 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \t\tif (cleanup_mode == CLEANUP_ALL)\n \t\t\tstatus_printf(s, GIT_COLOR_NORMAL,\n \t\t\t\t_(\"Please enter the commit message for your changes.\"\n-\t\t\t\t\" Lines starting\\nwith '#' will be ignored, and an empty\"\n-\t\t\t\t\" message aborts the commit.\\n\"));\n+\t\t\t\t  \" Lines starting\\nwith '%c' will be ignored, and an empty\"\n+\t\t\t\t  \" message aborts the commit.\\n\"), comment_line_char);\n \t\telse /* CLEANUP_SPACE, that is. */\n \t\t\tstatus_printf(s, GIT_COLOR_NORMAL,\n \t\t\t\t_(\"Please enter the commit message for your changes.\"\n-\t\t\t\t\" Lines starting\\n\"\n-\t\t\t\t\"with '#' will be kept; you may remove them\"\n-\t\t\t\t\" yourself if you want to.\\n\"\n-\t\t\t\t\"An empty message aborts the commit.\\n\"));\n+\t\t\t\t  \" Lines starting\\n\"\n+\t\t\t\t  \"with '%c' will be kept; you may remove them\"\n+\t\t\t\t  \" yourself if you want to.\\n\"\n+\t\t\t\t  \"An empty message aborts the commit.\\n\"), comment_line_char);\n \t\tif (only_include_assumed)\n \t\t\tstatus_printf_ln(s, GIT_COLOR_NORMAL,\n \t\t\t\t\t\"%s\", only_include_assumed);\ndiff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c\nindex d9af43c..b49612f 100644\n--- a/builtin/fmt-merge-msg.c\n+++ b/builtin/fmt-merge-msg.c\n@@ -470,7 +470,7 @@ static void fmt_tag_signature(struct strbuf *tagbuf,\n \tstrbuf_complete_line(tagbuf);\n \tif (sig->len) {\n \t\tstrbuf_addch(tagbuf, '\\n');\n-\t\tstrbuf_add_lines(tagbuf, \"# \", sig->buf, sig->len);\n+\t\tstrbuf_add_commented_lines(tagbuf, sig->buf, sig->len);\n \t}\n }\n \ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 9307e9c..7c8922c 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -788,17 +788,16 @@ static const char merge_editor_comment[] =\n N_(\"Please enter a commit message to explain why this merge is necessary,\\n\"\n    \"especially if it merges an updated upstream into a topic branch.\\n\"\n    \"\\n\"\n-   \"Lines starting with '#' will be ignored, and an empty message aborts\\n\"\n+   \"Lines starting with '%c' will be ignored, and an empty message aborts\\n\"\n    \"the commit.\\n\");\n \n static void prepare_to_commit(struct commit_list *remoteheads)\n {\n \tstruct strbuf msg = STRBUF_INIT;\n-\tconst char *comment = _(merge_editor_comment);\n \tstrbuf_addbuf(&msg, &merge_msg);\n \tstrbuf_addch(&msg, '\\n');\n \tif (0 < option_edit)\n-\t\tstrbuf_add_lines(&msg, \"# \", comment, strlen(comment));\n+\t\tstrbuf_commented_addf(&msg, _(merge_editor_comment), comment_line_char);\n \twrite_merge_msg(&msg);\n \tif (run_hook(get_index_file(), \"prepare-commit-msg\",\n \t\t     git_path(\"MERGE_MSG\"), \"merge\", NULL, NULL))\ndiff --git a/builtin/notes.c b/builtin/notes.c\nindex 453457a..57748a6 100644\n--- a/builtin/notes.c\n+++ b/builtin/notes.c\n@@ -92,10 +92,7 @@ static const char * const git_notes_get_ref_usage[] = {\n };\n \n static const char note_template[] =\n-\t\"\\n\"\n-\t\"#\\n\"\n-\t\"# Write/edit the notes for the following object:\\n\"\n-\t\"#\\n\";\n+\t\"\\nWrite/edit the notes for the following object:\\n\";\n \n struct msg_arg {\n \tint given;\n@@ -129,7 +126,7 @@ static void write_commented_object(int fd, const unsigned char *object)\n \t\t{\"show\", \"--stat\", \"--no-notes\", sha1_to_hex(object), NULL};\n \tstruct child_process show;\n \tstruct strbuf buf = STRBUF_INIT;\n-\tFILE *show_out;\n+\tstruct strbuf cbuf = STRBUF_INIT;\n \n \t/* Invoke \"git show --stat --no-notes $object\" */\n \tmemset(&show, 0, sizeof(show));\n@@ -142,21 +139,14 @@ static void write_commented_object(int fd, const unsigned char *object)\n \t\tdie(_(\"unable to start 'show' for object '%s'\"),\n \t\t    sha1_to_hex(object));\n \n-\t/* Open the output as FILE* so strbuf_getline() can be used. */\n-\tshow_out = xfdopen(show.out, \"r\");\n-\tif (show_out == NULL)\n-\t\tdie_errno(_(\"can't fdopen 'show' output fd\"));\n+\tif (strbuf_read(&buf, show.out, 0) < 0)\n+\t\tdie_errno(_(\"could not read 'show' output\"));\n+\tstrbuf_add_commented_lines(&cbuf, buf.buf, buf.len);\n+\twrite_or_die(fd, cbuf.buf, cbuf.len);\n \n-\t/* Prepend \"# \" to each output line and write result to 'fd' */\n-\twhile (strbuf_getline(&buf, show_out, '\\n') != EOF) {\n-\t\twrite_or_die(fd, \"# \", 2);\n-\t\twrite_or_die(fd, buf.buf, buf.len);\n-\t\twrite_or_die(fd, \"\\n\", 1);\n-\t}\n+\tstrbuf_release(&cbuf);\n \tstrbuf_release(&buf);\n-\tif (fclose(show_out))\n-\t\tdie_errno(_(\"failed to close pipe to 'show' for object '%s'\"),\n-\t\t\t  sha1_to_hex(object));\n+\n \tif (finish_command(&show))\n \t\tdie(_(\"failed to finish 'show' for object '%s'\"),\n \t\t    sha1_to_hex(object));\n@@ -170,6 +160,7 @@ static void create_note(const unsigned char *object, struct msg_arg *msg,\n \n \tif (msg->use_editor || !msg->given) {\n \t\tint fd;\n+\t\tstruct strbuf buf = STRBUF_INIT;\n \n \t\t/* write the template message before editing: */\n \t\tpath = git_pathdup(\"NOTES_EDITMSG\");\n@@ -181,11 +172,16 @@ static void create_note(const unsigned char *object, struct msg_arg *msg,\n \t\t\twrite_or_die(fd, msg->buf.buf, msg->buf.len);\n \t\telse if (prev && !append_only)\n \t\t\twrite_note_data(fd, prev);\n-\t\twrite_or_die(fd, note_template, strlen(note_template));\n+\n+\t\tstrbuf_addch(&buf, '\\n');\n+\t\tstrbuf_add_commented_lines(&buf, note_template, strlen(note_template));\n+\t\tstrbuf_addch(&buf, '\\n');\n+\t\twrite_or_die(fd, buf.buf, buf.len);\n \n \t\twrite_commented_object(fd, object);\n \n \t\tclose(fd);\n+\t\tstrbuf_release(&buf);\n \t\tstrbuf_reset(&(msg->buf));\n \n \t\tif (launch_editor(path, &(msg->buf), NULL)) {\ndiff --git a/builtin/stripspace.c b/builtin/stripspace.c\nindex f16986c..234248b 100644\n--- a/builtin/stripspace.c\n+++ b/builtin/stripspace.c\n@@ -30,7 +30,8 @@ static size_t cleanup(char *line, size_t len)\n  *\n  * If last line does not have a newline at the end, one is added.\n  *\n- * Enable skip_comments to skip every line starting with \"#\".\n+ * Enable skip_comments to skip every line starting with comment\n+ * character.\n  */\n void stripspace(struct strbuf *sb, int skip_comments)\n {\n@@ -45,7 +46,7 @@ void stripspace(struct strbuf *sb, int skip_comments)\n \t\teol = memchr(sb->buf + i, '\\n', sb->len - i);\n \t\tlen = eol ? eol - (sb->buf + i) + 1 : sb->len - i;\n \n-\t\tif (skip_comments && len && sb->buf[i] == '#') {\n+\t\tif (skip_comments && len && sb->buf[i] == comment_line_char) {\n \t\t\tnewlen = 0;\n \t\t\tcontinue;\n \t\t}\n@@ -66,21 +67,52 @@ void stripspace(struct strbuf *sb, int skip_comments)\n \tstrbuf_setlen(sb, j);\n }\n \n+static void comment_lines(struct strbuf *buf)\n+{\n+\tchar *msg;\n+\tsize_t len;\n+\n+\tmsg = strbuf_detach(buf, &len);\n+\tstrbuf_add_commented_lines(buf, msg, len);\n+}\n+\n+static const char *usage_msg = \"\\n\"\n+\"  git stripspace [-s | --strip-comments] < input\\n\"\n+\"  git stripspace [-c | --comment-lines] < input\";\n+\n int cmd_stripspace(int argc, const char **argv, const char *prefix)\n {\n \tstruct strbuf buf = STRBUF_INIT;\n \tint strip_comments = 0;\n+\tenum { INVAL = 0, STRIP_SPACE = 1, COMMENT_LINES = 2 } mode = STRIP_SPACE;\n+\n+\tif (argc == 2) {\n+\t\tif (!strcmp(argv[1], \"-s\") ||\n+\t\t\t!strcmp(argv[1], \"--strip-comments\")) {\n+\t\t\t strip_comments = 1;\n+\t\t} else if (!strcmp(argv[1], \"-c\") ||\n+\t\t\t\t\t !strcmp(argv[1], \"--comment-lines\")) {\n+\t\t\t mode = COMMENT_LINES;\n+\t\t} else {\n+\t\t\tmode = INVAL;\n+\t\t}\n+\t} else if (argc > 1) {\n+\t\tmode = INVAL;\n+\t}\n+\n+\tif (mode == INVAL)\n+\t\tusage(usage_msg);\n \n-\tif (argc == 2 && (!strcmp(argv[1], \"-s\") ||\n-\t\t\t\t!strcmp(argv[1], \"--strip-comments\")))\n-\t\tstrip_comments = 1;\n-\telse if (argc > 1)\n-\t\tusage(\"git stripspace [-s | --strip-comments] < input\");\n+\tif (strip_comments || mode == COMMENT_LINES)\n+\t\tgit_config(git_default_config, NULL);\n \n \tif (strbuf_read(&buf, 0, 1024) < 0)\n \t\tdie_errno(\"could not read the input\");\n \n-\tstripspace(&buf, strip_comments);\n+\tif (mode == STRIP_SPACE)\n+\t\tstripspace(&buf, strip_comments);\n+\telse\n+\t\tcomment_lines(&buf);\n \n \twrite_or_die(1, buf.buf, buf.len);\n \tstrbuf_release(&buf);\ndiff --git a/builtin/tag.c b/builtin/tag.c\nindex 9c3e067..f826688 100644\n--- a/builtin/tag.c\n+++ b/builtin/tag.c\n@@ -246,19 +246,13 @@ static int do_sign(struct strbuf *buffer)\n }\n \n static const char tag_template[] =\n-\tN_(\"\\n\"\n-\t\"#\\n\"\n-\t\"# Write a tag message\\n\"\n-\t\"# Lines starting with '#' will be ignored.\\n\"\n-\t\"#\\n\");\n+\tN_(\"\\nWrite a tag message\\n\"\n+\t\"Lines starting with '%c' will be ignored.\\n\");\n \n static const char tag_template_nocleanup[] =\n-\tN_(\"\\n\"\n-\t\"#\\n\"\n-\t\"# Write a tag message\\n\"\n-\t\"# Lines starting with '#' will be kept; you may remove them\"\n-\t\" yourself if you want to.\\n\"\n-\t\"#\\n\");\n+\tN_(\"\\nWrite a tag message\\n\"\n+\t\"Lines starting with '%c' will be kept; you may remove them\"\n+\t\" yourself if you want to.\\n\");\n \n static int git_tag_config(const char *var, const char *value, void *cb)\n {\n@@ -346,14 +340,18 @@ static void create_tag(const unsigned char *object, const char *tag,\n \t\tif (fd < 0)\n \t\t\tdie_errno(_(\"could not create file '%s'\"), path);\n \n-\t\tif (!is_null_sha1(prev))\n+\t\tif (!is_null_sha1(prev)) {\n \t\t\twrite_tag_body(fd, prev);\n-\t\telse if (opt->cleanup_mode == CLEANUP_ALL)\n-\t\t\twrite_or_die(fd, _(tag_template),\n-\t\t\t\t\tstrlen(_(tag_template)));\n-\t\telse\n-\t\t\twrite_or_die(fd, _(tag_template_nocleanup),\n-\t\t\t\t\tstrlen(_(tag_template_nocleanup)));\n+\t\t} else {\n+\t\t\tstruct strbuf buf = STRBUF_INIT;\n+\t\t\tstrbuf_addch(&buf, '\\n');\n+\t\t\tif (opt->cleanup_mode == CLEANUP_ALL)\n+\t\t\t\tstrbuf_commented_addf(&buf, _(tag_template), comment_line_char);\n+\t\t\telse\n+\t\t\t\tstrbuf_commented_addf(&buf, _(tag_template_nocleanup), comment_line_char);\n+\t\t\twrite_or_die(fd, buf.buf, buf.len);\n+\t\t\tstrbuf_release(&buf);\n+\t\t}\n \t\tclose(fd);\n \n \t\tif (launch_editor(path, buf, NULL)) {\ndiff --git a/cache.h b/cache.h\nindex c257953..0b435a4 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -562,6 +562,12 @@ extern int core_preload_index;\n extern int core_apply_sparse_checkout;\n extern int precomposed_unicode;\n \n+/*\n+ * The character that begins a commented line in user-editable file\n+ * that is subject to stripspace.\n+ */\n+extern char comment_line_char;\n+\n enum branch_track {\n \tBRANCH_TRACK_UNSPECIFIED = -1,\n \tBRANCH_TRACK_NEVER = 0,\ndiff --git a/config.c b/config.c\nindex 7b444b6..d873c59 100644\n--- a/config.c\n+++ b/config.c\n@@ -717,6 +717,14 @@ static int git_default_core_config(const char *var, const char *value)\n \tif (!strcmp(var, \"core.editor\"))\n \t\treturn git_config_string(&editor_program, var, value);\n \n+\tif (!strcmp(var, \"core.commentchar\")) {\n+\t\tconst char *comment;\n+\t\tint ret = git_config_string(&comment, var, value);\n+\t\tif (!ret)\n+\t\t\tcomment_line_char = comment[0];\n+\t\treturn ret;\n+\t}\n+\n \tif (!strcmp(var, \"core.askpass\"))\n \t\treturn git_config_string(&askpass_program, var, value);\n \ndiff --git a/environment.c b/environment.c\nindex 85edd7f..a40c38b 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -62,6 +62,12 @@ int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */\n struct startup_info *startup_info;\n unsigned long pack_size_limit_cfg;\n \n+/*\n+ * The character that begins a commented line in user-editable file\n+ * that is subject to stripspace.\n+ */\n+char comment_line_char = '#';\n+\n /* Parallel index stat data preload? */\n int core_preload_index = 0;\n \ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 22ec5b6..004c034 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -976,12 +976,12 @@ cmd_summary() {\n \tdone |\n \tif test -n \"$for_status\"; then\n \t\tif [ -n \"$files\" ]; then\n-\t\t\tgettextln \"# Submodules changed but not updated:\"\n+\t\t\tgettextln \"Submodules changed but not updated:\" | git stripspace -c\n \t\telse\n-\t\t\tgettextln \"# Submodule changes to be committed:\"\n+\t\t\tgettextln \"Submodule changes to be committed:\" | git stripspace -c\n \t\tfi\n-\t\techo \"#\"\n-\t\tsed -e 's|^|# |' -e 's|^# $|#|'\n+\t\tprintf \"\\n\" | git stripspace -c\n+\t\tgit stripspace -c\n \telse\n \t\tcat\n \tfi\ndiff --git a/strbuf.c b/strbuf.c\nindex 9a373be..48e9abb 100644\n--- a/strbuf.c\n+++ b/strbuf.c\n@@ -204,6 +204,54 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...)\n \tva_end(ap);\n }\n \n+static void add_lines(struct strbuf *out,\n+\t\t\tconst char *prefix1,\n+\t\t\tconst char *prefix2,\n+\t\t\tconst char *buf, size_t size)\n+{\n+\twhile (size) {\n+\t\tconst char *prefix;\n+\t\tconst char *next = memchr(buf, '\\n', size);\n+\t\tnext = next ? (next + 1) : (buf + size);\n+\n+\t\tprefix = (prefix2 && buf[0] == '\\n') ? prefix2 : prefix1;\n+\t\tstrbuf_addstr(out, prefix);\n+\t\tstrbuf_add(out, buf, next - buf);\n+\t\tsize -= next - buf;\n+\t\tbuf = next;\n+\t}\n+\tstrbuf_complete_line(out);\n+}\n+\n+void strbuf_add_commented_lines(struct strbuf *out, const char *buf, size_t size)\n+{\n+\tstatic char prefix1[3];\n+\tstatic char prefix2[2];\n+\n+\tif (prefix1[0] != comment_line_char) {\n+\t\tsprintf(prefix1, \"%c \", comment_line_char);\n+\t\tsprintf(prefix2, \"%c\", comment_line_char);\n+\t}\n+\tadd_lines(out, prefix1, prefix2, buf, size);\n+}\n+\n+void strbuf_commented_addf(struct strbuf *sb, const char *fmt, ...)\n+{\n+\tva_list params;\n+\tstruct strbuf buf = STRBUF_INIT;\n+\tint incomplete_line = sb->len && sb->buf[sb->len - 1] != '\\n';\n+\n+\tva_start(params, fmt);\n+\tstrbuf_vaddf(&buf, fmt, params);\n+\tva_end(params);\n+\n+\tstrbuf_add_commented_lines(sb, buf.buf, buf.len);\n+\tif (incomplete_line)\n+\t\tsb->buf[--sb->len] = '\\0';\n+\n+\tstrbuf_release(&buf);\n+}\n+\n void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap)\n {\n \tint len;\n@@ -414,15 +462,7 @@ int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)\n void strbuf_add_lines(struct strbuf *out, const char *prefix,\n \t\t      const char *buf, size_t size)\n {\n-\twhile (size) {\n-\t\tconst char *next = memchr(buf, '\\n', size);\n-\t\tnext = next ? (next + 1) : (buf + size);\n-\t\tstrbuf_addstr(out, prefix);\n-\t\tstrbuf_add(out, buf, next - buf);\n-\t\tsize -= next - buf;\n-\t\tbuf = next;\n-\t}\n-\tstrbuf_complete_line(out);\n+\tadd_lines(out, prefix, NULL, buf, size);\n }\n \n void strbuf_addstr_xml_quoted(struct strbuf *buf, const char *s)\ndiff --git a/strbuf.h b/strbuf.h\nindex ecae4e2..958822c 100644\n--- a/strbuf.h\n+++ b/strbuf.h\n@@ -110,6 +110,8 @@ extern void strbuf_remove(struct strbuf *, size_t pos, size_t len);\n extern void strbuf_splice(struct strbuf *, size_t pos, size_t len,\n                           const void *, size_t);\n \n+extern void strbuf_add_commented_lines(struct strbuf *out, const char *buf, size_t size);\n+\n extern void strbuf_add(struct strbuf *, const void *, size_t);\n static inline void strbuf_addstr(struct strbuf *sb, const char *s) {\n \tstrbuf_add(sb, s, strlen(s));\n@@ -131,6 +133,8 @@ extern void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *\n \n __attribute__((format (printf,2,3)))\n extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);\n+__attribute__((format (printf, 2, 3)))\n+extern void strbuf_commented_addf(struct strbuf *sb, const char *fmt, ...);\n __attribute__((format (printf,2,0)))\n extern void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap);\n \ndiff --git a/t/t0030-stripspace.sh b/t/t0030-stripspace.sh\nindex ccb0a3c..a8e84d8 100755\n--- a/t/t0030-stripspace.sh\n+++ b/t/t0030-stripspace.sh\n@@ -397,4 +397,39 @@ test_expect_success 'strip comments, too' '\n \ttest -z \"$(echo \"# comment\" | git stripspace -s)\"\n '\n \n+test_expect_success 'strip comments with changed comment char' '\n+\ttest ! -z \"$(echo \"; comment\" | git -c core.commentchar=\";\" stripspace)\" &&\n+\ttest -z \"$(echo \"; comment\" | git -c core.commentchar=\";\" stripspace -s)\"\n+'\n+\n+test_expect_success '-c with single line' '\n+\tprintf \"# foo\\n\" >expect &&\n+\tprintf \"foo\" | git stripspace -c >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success '-c with single line followed by empty line' '\n+\tprintf \"# foo\\n#\\n\" >expect &&\n+\tprintf \"foo\\n\\n\" | git stripspace -c >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success '-c with newline only' '\n+\tprintf \"#\\n\" >expect &&\n+\tprintf \"\\n\" | git stripspace -c >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success '--comment-lines with single line' '\n+\tprintf \"# foo\\n\" >expect &&\n+\tprintf \"foo\" | git stripspace -c >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success '-c with changed comment char' '\n+\tprintf \"; foo\\n\" >expect &&\n+\tprintf \"foo\" | git -c core.commentchar=\";\" stripspace -c >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\ndiff --git a/t/t7502-commit.sh b/t/t7502-commit.sh\nindex 1a5cb69..6a2c67c 100755\n--- a/t/t7502-commit.sh\n+++ b/t/t7502-commit.sh\n@@ -447,4 +447,11 @@ use_template=\"-t template\"\n \n try_commit_status_combo\n \n+test_expect_success 'commit --status with custom comment character' '\n+\ttest_when_finished \"git config --unset core.commentchar\" &&\n+\tgit config core.commentchar \";\" &&\n+\ttry_commit --status &&\n+\ttest_i18ngrep \"^; Changes to be committed:\" .git/COMMIT_EDITMSG\n+'\n+\n test_done\ndiff --git a/t/t7508-status.sh b/t/t7508-status.sh\nindex e313ef1..a79c032 100755\n--- a/t/t7508-status.sh\n+++ b/t/t7508-status.sh\n@@ -1254,6 +1254,56 @@ test_expect_success \".git/config ignore=dirty doesn't suppress submodule summary\n '\n \n cat > expect << EOF\n+; On branch master\n+; Changes to be committed:\n+;   (use \"git reset HEAD <file>...\" to unstage)\n+;\n+;\tmodified:   sm\n+;\n+; Changes not staged for commit:\n+;   (use \"git add <file>...\" to update what will be committed)\n+;   (use \"git checkout -- <file>...\" to discard changes in working directory)\n+;\n+;\tmodified:   dir1/modified\n+;\tmodified:   sm (new commits)\n+;\n+; Submodule changes to be committed:\n+;\n+; * sm $head...$new_head (1):\n+;   > Add bar\n+;\n+; Submodules changed but not updated:\n+;\n+; * sm $new_head...$head2 (1):\n+;   > 2nd commit\n+;\n+; Untracked files:\n+;   (use \"git add <file>...\" to include in what will be committed)\n+;\n+;\t.gitmodules\n+;\tdir1/untracked\n+;\tdir2/modified\n+;\tdir2/untracked\n+;\texpect\n+;\toutput\n+;\tuntracked\n+EOF\n+\n+test_expect_success \"status (core.commentchar with submodule summary)\" '\n+\ttest_when_finished \"git config --unset core.commentchar\" &&\n+\tgit config core.commentchar \";\" &&\n+\tgit status >output &&\n+\ttest_i18ncmp expect output\n+'\n+\n+test_expect_success \"status (core.commentchar with two chars with submodule summary)\" '\n+\ttest_when_finished \"git config --unset core.commentchar\" &&\n+\tgit config core.commentchar \";;\" &&\n+\tgit status >output &&\n+\ttest_i18ncmp expect output\n+'\n+\n+cat > expect << EOF\n # On branch master\n # Changes not staged for commit:\n #   (use \"git add <file>...\" to update what will be committed)\ndiff --git a/wt-status.c b/wt-status.c\nindex 2a9658b..f6f197e 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -45,7 +45,7 @@ static void status_vprintf(struct wt_status *s, int at_bol, const char *color,\n \n \tstrbuf_vaddf(&sb, fmt, ap);\n \tif (!sb.len) {\n-\t\tstrbuf_addch(&sb, '#');\n+\t\tstrbuf_addch(&sb, comment_line_char);\n \t\tif (!trail)\n \t\t\tstrbuf_addch(&sb, ' ');\n \t\tcolor_print_strbuf(s->fp, color, &sb);\n@@ -59,7 +59,7 @@ static void status_vprintf(struct wt_status *s, int at_bol, const char *color,\n \n \t\tstrbuf_reset(&linebuf);\n \t\tif (at_bol) {\n-\t\t\tstrbuf_addch(&linebuf, '#');\n+\t\t\tstrbuf_addch(&linebuf, comment_line_char);\n \t\t\tif (*line != '\\n' && *line != '\\t')\n \t\t\t\tstrbuf_addch(&linebuf, ' ');\n \t\t}\n@@ -760,8 +760,10 @@ static void wt_status_print_tracking(struct wt_status *s)\n \n \tfor (cp = sb.buf; (ep = strchr(cp, '\\n')) != NULL; cp = ep + 1)\n \t\tcolor_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s),\n-\t\t\t\t \"# %.*s\", (int)(ep - cp), cp);\n-\tcolor_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), \"#\");\n+\t\t\t\t \"%c %.*s\", comment_line_char,\n+\t\t\t\t (int)(ep - cp), cp);\n+\tcolor_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), \"%c\",\n+\t\t\t comment_line_char);\n }\n \n static int has_unmerged(struct wt_status *s)\n-- \n1.8.1.291.g056e2eb\n"},{"id":"207104","messageId":"7vip6wx440.fsf@alter.siamese.dyndns.org","threadId":"32562","inReplyTo":"1358363928-16729-1-git-send-email-ralf.thielow@gmail.com","subject":"Re: [PATCH v2] Allow custom \"comment char\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-01-16T20:30:39Z","receivedAt":"2013-01-16T20:30:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ralf Thielow <ralf.thielow@gmail.com> writes:\n\n> From: Junio C Hamano <gitster@pobox.com>\n>\n> Some users do want to write a line that begin with a pound sign, #,\n> in their commit log message.  Many tracking system recognise\n> a token of #<bugid> form, for example.\n>\n> The support we offer these use cases is not very friendly to the end\n> users.  They have a choice between\n>\n>  - Don't do it.  Avoid such a line by rewrapping or indenting; and\n>\n>  - Use --cleanup=whitespace but remove all the hint lines we add.\n>\n> Give them a way to set a custom comment char, e.g.\n>\n>     $ git -c core.commentchar=\"%\" commit\n>\n> so that they do not have to do either of the two workarounds.\n>\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> Signed-off-by: Ralf Thielow <ralf.thielow@gmail.com>\n> ---\n> Junio, thanks for the code in your reply to the\n> first version. It works very well and looks nice.\n> I was also unhappy about this \"\\n%c\\n\" thing and\n> pretty unsure with the code in \"git-submodule.sh\".\n> But with this, it looks good to me. Thanks.\n>\n> Changes in v2:\n> - extend \"git stripspace\" with an option to make\n>   it's input being converted to commented lines\n> - teach git-submodule.sh using this\n> - rename strbuf_commented_addstr to strbuf_add_commented_lines\n>   and improve it's design\n\nOh, I love it when something like this happens.  Throw a \"perhaps\nalong these lines\" patch and then a finished product that fills the\ngaps I didn't bother to fill magically appears, even with tests and\nupdates to comments and documentation.\n\nWhat good things did I do recently to deserve such a luck? ;-)\n\n> @@ -66,21 +67,52 @@ void stripspace(struct strbuf *sb, int skip_comments)\n>  \tstrbuf_setlen(sb, j);\n>  }\n>  \n> +static void comment_lines(struct strbuf *buf)\n> +{\n> +\tchar *msg;\n> +\tsize_t len;\n> +\n> +\tmsg = strbuf_detach(buf, &len);\n> +\tstrbuf_add_commented_lines(buf, msg, len);\n> +}\n\nThis leaks msg (inherited from my \"perhaps along these lines\"\npatch).  I think I can just add free(msg) at the end.\n\n> +\tif (strip_comments || mode == COMMENT_LINES)\n> +\t\tgit_config(git_default_config, NULL);\n\nNice spotting.  The \"along these lines\" patch broke \"stripspace -s\"\nunder custom comment line char; this fixes it.\n\nThanks.\n"},{"id":"207106","messageId":"50F71563.20406@web.de","threadId":"32562","inReplyTo":"1358363928-16729-1-git-send-email-ralf.thielow@gmail.com","subject":"Re: [PATCH v2] Allow custom \"comment char\"","fromName":"Jens Lehmann","fromEmail":"jens.lehmann@web.de","sentAt":"2013-01-16T21:02:27Z","receivedAt":"2013-01-16T21:02:27Z","isPatch":true,"sender":{"key":"jens.lehmann@web.de","avatar":"https://avatars.githubusercontent.com/u/135220?v=4"},"body":"Am 16.01.2013 20:18, schrieb Ralf Thielow:\n> From: Junio C Hamano <gitster@pobox.com>\n> \n> Some users do want to write a line that begin with a pound sign, #,\n> in their commit log message.  Many tracking system recognise\n> a token of #<bugid> form, for example.\n> \n> The support we offer these use cases is not very friendly to the end\n> users.  They have a choice between\n> \n>  - Don't do it.  Avoid such a line by rewrapping or indenting; and\n> \n>  - Use --cleanup=whitespace but remove all the hint lines we add.\n> \n> Give them a way to set a custom comment char, e.g.\n> \n>     $ git -c core.commentchar=\"%\" commit\n> \n> so that they do not have to do either of the two workarounds.\n> \n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> Signed-off-by: Ralf Thielow <ralf.thielow@gmail.com>\n> ---\n> Junio, thanks for the code in your reply to the\n> first version. It works very well and looks nice.\n> I was also unhappy about this \"\\n%c\\n\" thing and\n> pretty unsure with the code in \"git-submodule.sh\".\n\nI can't see anything wrong with it (but didn't have the time to\ntest it). On my todo list (but *way* down) is the task to replace\nthe call to \"git submodule summary --for-status ...\" in\nwt_status_print_submodule_summary() with a call to \"git diff\n--submodule\" (and - at least in the long term - rip out the\n--for-status option from the submodule script). Maybe now is a\ngood time for someone else to tackle that? (especially as the new\nstrbuf_commented_add*() functions should make that rather easy)\n"}]}