Skip to content

Commit 31399a6

Browse files
committed
config: allow tweaking whitespace between value and comment
Extending the previous step, this allows the whitespace placed after the value before the "# comment message" to be tweaked by tweaking the preprocessing rule to: * If the given comment string begins with one or more whitespace characters followed by '#', it is passed intact. * If the given comment string begins with '#', a Space is prepended. * Otherwise, " # " (Space, '#', Space) is prefixed. * A string with LF in it cannot be used as a comment string. Unlike the previous step, which unconditionally added a space after the value before writing the "# comment string", because the above preprocessing already gives a whitespace before the '#', the resulting string is written immediately after copying the value. And the sanity checking rule becomes * comment string after the above massaging that comes into git_config_set_multivar_in_file_gently() must - begin with zero or more whitespace characters followed by '#'. - not have a LF in it. I personally think this is over-engineered, but since I thought things through anyway, here it is in the patch form. The logic to tweak end-user supplied comment string is encapsulated in a new helper function, git_config_prepare_comment_string(), so if new front-end callers would want to use the same massaging rules, it is easily reused. Unfortunately I do not think of a way to tweak the preprocessing rules further to optionally allow having no blank after the value, i.e. to produce [section] variable = value#comment (which is a valid way to say section.variable=value, by the way) without sacrificing the ergonomics for the more usual case, so this time I really stop here. Signed-off-by: Junio C Hamano <[email protected]>
1 parent fbad334 commit 31399a6

File tree

5 files changed

+76
-20
lines changed

5 files changed

+76
-20
lines changed

Documentation/git-config.txt

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,15 @@ OPTIONS
8989

9090
--comment <message>::
9191
Append a comment at the end of new or modified lines.
92-
Unless _<message>_ begins with "#", a string "# " (hash
93-
followed by a space) is prepended to it. The _<message>_ must not
94-
contain linefeed characters (no multi-line comments are permitted).
92+
93+
If _<message>_ begins with one or more whitespaces followed
94+
by "#", it is used as-is. If it begins with "#", a space is
95+
prepended before it is used. Otherwise, a string " # " (a
96+
space followed by a hash followed by a space) is prepended
97+
to it. And the resulting string is placed immediately after
98+
the value defined for the variable. The _<message>_ must
99+
not contain linefeed characters (no multi-line comments are
100+
permitted).
95101

96102
--get::
97103
Get the value for a given key (optionally filtered by a regex

builtin/config.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -841,12 +841,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
841841
flags |= CONFIG_FLAGS_FIXED_VALUE;
842842
}
843843

844-
if (comment) {
845-
if (strchr(comment, '\n'))
846-
die(_("no multi-line comment allowed: '%s'"), comment);
847-
if (comment[0] != '#')
848-
comment = xstrfmt("# %s", comment);
849-
}
844+
comment = git_config_prepare_comment_string(comment);
850845

851846
if (actions & PAGING_ACTIONS)
852847
setup_auto_pager("config", 1);

config.c

Lines changed: 58 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3044,7 +3044,7 @@ static ssize_t write_pair(int fd, const char *key, const char *value,
30443044
}
30453045

30463046
if (comment)
3047-
strbuf_addf(&sb, "%s %s\n", quote, comment);
3047+
strbuf_addf(&sb, "%s%s\n", quote, comment);
30483048
else
30493049
strbuf_addf(&sb, "%s\n", quote);
30503050

@@ -3172,6 +3172,62 @@ void git_config_set(const char *key, const char *value)
31723172
trace2_cmd_set_config(key, value);
31733173
}
31743174

3175+
/*
3176+
* The ownership rule is that the caller will own the string
3177+
* if it receives a piece of memory different from what it passed
3178+
* as the parameter.
3179+
*/
3180+
const char *git_config_prepare_comment_string(const char *comment)
3181+
{
3182+
size_t leading_blanks;
3183+
3184+
if (!comment)
3185+
return NULL;
3186+
3187+
if (strchr(comment, '\n'))
3188+
die(_("no multi-line comment allowed: '%s'"), comment);
3189+
3190+
/*
3191+
* If it begins with one or more leading whitespace characters
3192+
* followed by '#", the comment string is used as-is.
3193+
*
3194+
* If it begins with '#', a SP is inserted between the comment
3195+
* and the value the comment is about.
3196+
*
3197+
* Otherwise, the value is followed by a SP followed by '#'
3198+
* followed by SP and then the comment string comes.
3199+
*/
3200+
3201+
leading_blanks = strspn(comment, " \t");
3202+
if (leading_blanks && comment[leading_blanks] == '#')
3203+
; /* use it as-is */
3204+
else if (comment[0] == '#')
3205+
comment = xstrfmt(" %s", comment);
3206+
else
3207+
comment = xstrfmt(" # %s", comment);
3208+
3209+
return comment;
3210+
}
3211+
3212+
static void validate_comment_string(const char *comment)
3213+
{
3214+
size_t leading_blanks;
3215+
3216+
if (!comment)
3217+
return;
3218+
/*
3219+
* The front-end must have massaged the comment string
3220+
* properly before calling us.
3221+
*/
3222+
if (strchr(comment, '\n'))
3223+
BUG("multi-line comments are not permitted: '%s'", comment);
3224+
3225+
leading_blanks = strspn(comment, " \t");
3226+
if (!leading_blanks || comment[leading_blanks] != '#')
3227+
BUG("comment must begin with one or more SP followed by '#': '%s'",
3228+
comment);
3229+
}
3230+
31753231
/*
31763232
* If value==NULL, unset in (remove from) config,
31773233
* if value_pattern!=NULL, disregard key/value pairs where value does not match.
@@ -3211,16 +3267,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
32113267
size_t contents_sz;
32123268
struct config_store_data store = CONFIG_STORE_INIT;
32133269

3214-
if (comment) {
3215-
/*
3216-
* The front-end must have massaged the comment string
3217-
* properly before calling us.
3218-
*/
3219-
if (strchr(comment, '\n'))
3220-
BUG("multi-line comments are not permitted: '%s'", comment);
3221-
if (comment[0] != '#')
3222-
BUG("comment should begin with '#': '%s'", comment);
3223-
}
3270+
validate_comment_string(comment);
32243271

32253272
/* parse-key returns negative; flip the sign to feed exit(3) */
32263273
ret = 0 - git_config_parse_key(key, &store.key, &store.baselen);

config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,8 @@ void git_config_set_multivar(const char *, const char *, const char *, unsigned)
338338
int repo_config_set_multivar_gently(struct repository *, const char *, const char *, const char *, unsigned);
339339
int git_config_set_multivar_in_file_gently(const char *, const char *, const char *, const char *, const char *, unsigned);
340340

341+
const char *git_config_prepare_comment_string(const char *);
342+
341343
/**
342344
* takes four parameters:
343345
*

t/t1300-config.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ cat > expect << EOF
7474
penguin = gentoo # Pygoscelis papua
7575
disposition = peckish # find fish
7676
foo = bar #abc
77+
spsp = value # and comment
78+
htsp = value # and comment
7779
[Sections]
7880
WhatEver = Second
7981
EOF
@@ -82,6 +84,10 @@ test_expect_success 'append comments' '
8284
git config --replace-all --comment="Pygoscelis papua" section.penguin gentoo &&
8385
git config --comment="find fish" section.disposition peckish &&
8486
git config --comment="#abc" section.foo bar &&
87+
88+
git config --comment="and comment" section.spsp value &&
89+
git config --comment=" # and comment" section.htsp value &&
90+
8591
test_cmp expect .git/config
8692
'
8793

0 commit comments

Comments
 (0)