aboutsummaryrefslogtreecommitdiffstats
path: root/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'config.c')
-rw-r--r--config.c80
1 files changed, 72 insertions, 8 deletions
diff --git a/config.c b/config.c
index 5072f12e62..dab92e581b 100644
--- a/config.c
+++ b/config.c
@@ -3006,6 +3006,7 @@ static ssize_t write_section(int fd, const char *key,
}
static ssize_t write_pair(int fd, const char *key, const char *value,
+ const char *comment,
const struct config_store_data *store)
{
int i;
@@ -3046,7 +3047,11 @@ static ssize_t write_pair(int fd, const char *key, const char *value,
strbuf_addch(&sb, value[i]);
break;
}
- strbuf_addf(&sb, "%s\n", quote);
+
+ if (comment)
+ strbuf_addf(&sb, "%s%s\n", quote, comment);
+ else
+ strbuf_addf(&sb, "%s\n", quote);
ret = write_in_full(fd, sb.buf, sb.len);
strbuf_release(&sb);
@@ -3135,9 +3140,9 @@ static void maybe_remove_section(struct config_store_data *store,
}
int git_config_set_in_file_gently(const char *config_filename,
- const char *key, const char *value)
+ const char *key, const char *comment, const char *value)
{
- return git_config_set_multivar_in_file_gently(config_filename, key, value, NULL, 0);
+ return git_config_set_multivar_in_file_gently(config_filename, key, value, NULL, comment, 0);
}
void git_config_set_in_file(const char *config_filename,
@@ -3158,7 +3163,7 @@ int repo_config_set_worktree_gently(struct repository *r,
if (r->repository_format_worktree_config) {
char *file = repo_git_path(r, "config.worktree");
int ret = git_config_set_multivar_in_file_gently(
- file, key, value, NULL, 0);
+ file, key, value, NULL, NULL, 0);
free(file);
return ret;
}
@@ -3173,6 +3178,62 @@ void git_config_set(const char *key, const char *value)
}
/*
+ * The ownership rule is that the caller will own the string
+ * if it receives a piece of memory different from what it passed
+ * as the parameter.
+ */
+const char *git_config_prepare_comment_string(const char *comment)
+{
+ size_t leading_blanks;
+
+ if (!comment)
+ return NULL;
+
+ if (strchr(comment, '\n'))
+ die(_("no multi-line comment allowed: '%s'"), comment);
+
+ /*
+ * If it begins with one or more leading whitespace characters
+ * followed by '#", the comment string is used as-is.
+ *
+ * If it begins with '#', a SP is inserted between the comment
+ * and the value the comment is about.
+ *
+ * Otherwise, the value is followed by a SP followed by '#'
+ * followed by SP and then the comment string comes.
+ */
+
+ leading_blanks = strspn(comment, " \t");
+ if (leading_blanks && comment[leading_blanks] == '#')
+ ; /* use it as-is */
+ else if (comment[0] == '#')
+ comment = xstrfmt(" %s", comment);
+ else
+ comment = xstrfmt(" # %s", comment);
+
+ return comment;
+}
+
+static void validate_comment_string(const char *comment)
+{
+ size_t leading_blanks;
+
+ if (!comment)
+ return;
+ /*
+ * The front-end must have massaged the comment string
+ * properly before calling us.
+ */
+ if (strchr(comment, '\n'))
+ BUG("multi-line comments are not permitted: '%s'", comment);
+
+ leading_blanks = strspn(comment, " \t");
+ if (!leading_blanks || comment[leading_blanks] != '#')
+ BUG("comment must begin with one or more SP followed by '#': '%s'",
+ comment);
+}
+
+/*
* If value==NULL, unset in (remove from) config,
* if value_pattern!=NULL, disregard key/value pairs where value does not match.
* if value_pattern==CONFIG_REGEX_NONE, do not match any existing values
@@ -3200,6 +3261,7 @@ void git_config_set(const char *key, const char *value)
int git_config_set_multivar_in_file_gently(const char *config_filename,
const char *key, const char *value,
const char *value_pattern,
+ const char *comment,
unsigned flags)
{
int fd = -1, in_fd = -1;
@@ -3210,6 +3272,8 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
size_t contents_sz;
struct config_store_data store = CONFIG_STORE_INIT;
+ validate_comment_string(comment);
+
/* parse-key returns negative; flip the sign to feed exit(3) */
ret = 0 - git_config_parse_key(key, &store.key, &store.baselen);
if (ret)
@@ -3250,7 +3314,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
free(store.key);
store.key = xstrdup(key);
if (write_section(fd, key, &store) < 0 ||
- write_pair(fd, key, value, &store) < 0)
+ write_pair(fd, key, value, comment, &store) < 0)
goto write_err_out;
} else {
struct stat st;
@@ -3404,7 +3468,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
if (write_section(fd, key, &store) < 0)
goto write_err_out;
}
- if (write_pair(fd, key, value, &store) < 0)
+ if (write_pair(fd, key, value, comment, &store) < 0)
goto write_err_out;
}
@@ -3449,7 +3513,7 @@ void git_config_set_multivar_in_file(const char *config_filename,
const char *value_pattern, unsigned flags)
{
if (!git_config_set_multivar_in_file_gently(config_filename, key, value,
- value_pattern, flags))
+ value_pattern, NULL, flags))
return;
if (value)
die(_("could not set '%s' to '%s'"), key, value);
@@ -3472,7 +3536,7 @@ int repo_config_set_multivar_gently(struct repository *r, const char *key,
int res = git_config_set_multivar_in_file_gently(file,
key, value,
value_pattern,
- flags);
+ NULL, flags);
free(file);
return res;
}