Commit 8ec806d7485219c4f495bc55dd80d2acae220b56

Carlos Martín Nieto 2017-10-30T06:23:31

config: preserve the original case when writing out new sections and vars For sections we will still use the existing one even if the case disagrees, but the variable always gets written with the case given by the caller.

diff --git a/src/config_file.c b/src/config_file.c
index 00d6d9e..73c9000 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -120,7 +120,7 @@ typedef struct {
 } diskfile_readonly_backend;
 
 static int config_read(git_strmap *values, struct config_file *file, git_config_level_t level, int depth);
-static int config_write(diskfile_backend *cfg, const char *key, const regex_t *preg, const char *value);
+static int config_write(diskfile_backend *cfg, const char *orig_key, const char *key, const regex_t *preg, const char *value);
 static char *escape_value(const char *ptr);
 
 int git_config_file__snapshot(git_config_backend **out, diskfile_backend *in);
@@ -513,7 +513,7 @@ static int config_set(git_config_backend *cfg, const char *name, const char *val
 		GITERR_CHECK_ALLOC(esc_value);
 	}
 
-	if ((ret = config_write(b, key, NULL, esc_value)) < 0)
+	if ((ret = config_write(b, name, key, NULL, esc_value)) < 0)
 		goto out;
 
 	ret = config_refresh(cfg);
@@ -591,7 +591,7 @@ static int config_set_multivar(
 	}
 
 	/* If we do have it, set call config_write() and reload */
-	if ((result = config_write(b, key, &preg, value)) < 0)
+	if ((result = config_write(b, name, key, &preg, value)) < 0)
 		goto out;
 
 	result = config_refresh(cfg);
@@ -641,7 +641,7 @@ static int config_delete(git_config_backend *cfg, const char *name)
 		return -1;
 	}
 
-	if ((result = config_write(b, var->entry->name, NULL, NULL)) < 0)
+	if ((result = config_write(b, name, var->entry->name, NULL, NULL)) < 0)
 		return result;
 
 	return config_refresh(cfg);
@@ -682,7 +682,7 @@ static int config_delete_multivar(git_config_backend *cfg, const char *name, con
 		goto out;
 	}
 
-	if ((result = config_write(b, key, &preg, NULL)) < 0)
+	if ((result = config_write(b, name, key, &preg, NULL)) < 0)
 		goto out;
 
 	result = config_refresh(cfg);
@@ -1739,7 +1739,9 @@ struct write_data {
 	git_buf buffered_comment;
 	unsigned int in_section : 1,
 		preg_replaced : 1;
+	const char *orig_section;
 	const char *section;
+	const char *orig_name;
 	const char *name;
 	const regex_t *preg;
 	const char *value;
@@ -1767,7 +1769,7 @@ static int write_value(struct write_data *write_data)
 
 	q = quotes_for_value(write_data->value);
 	result = git_buf_printf(write_data->buf,
-		"\t%s = %s%s%s\n", write_data->name, q, write_data->value, q);
+		"\t%s = %s%s%s\n", write_data->orig_name, q, write_data->value, q);
 
 	/* If we are updating a single name/value, we're done.  Setting `value`
 	 * to `NULL` will prevent us from trying to write it again later (in
@@ -1898,7 +1900,7 @@ static int write_on_eof(
 	if ((!write_data->preg || !write_data->preg_replaced) && write_data->value) {
 		/* write the section header unless we're already in it */
 		if (!current_section || strcmp(current_section, write_data->section))
-			result = write_section(write_data->buf, write_data->section);
+			result = write_section(write_data->buf, write_data->orig_section);
 
 		if (!result)
 			result = write_value(write_data);
@@ -1910,10 +1912,10 @@ static int write_on_eof(
 /*
  * This is pretty much the parsing, except we write out anything we don't have
  */
-static int config_write(diskfile_backend *cfg, const char *key, const regex_t *preg, const char* value)
+static int config_write(diskfile_backend *cfg, const char *orig_key, const char *key, const regex_t *preg, const char* value)
 {
 	int result;
-	char *section, *name, *ldot;
+	char *orig_section, *section, *orig_name, *name, *ldot;
 	git_filebuf file = GIT_FILEBUF_INIT;
 	git_buf buf = GIT_BUF_INIT;
 	struct reader reader;
@@ -1954,17 +1956,24 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
 	name = ldot + 1;
 	section = git__strndup(key, ldot - key);
 
+	ldot = strrchr(orig_key, '.');
+	orig_name = ldot + 1;
+	orig_section = git__strndup(orig_key, ldot - orig_key);
+
 	write_data.buf = &buf;
 	git_buf_init(&write_data.buffered_comment, 0);
+	write_data.orig_section = orig_section;
 	write_data.section = section;
 	write_data.in_section = 0;
 	write_data.preg_replaced = 0;
+	write_data.orig_name = orig_name;
 	write_data.name = name;
 	write_data.preg = preg;
 	write_data.value = value;
 
 	result = config_parse(&reader, write_on_section, write_on_variable, write_on_comment, write_on_eof, &write_data);
 	git__free(section);
+	git__free(orig_section);
 	git_buf_free(&write_data.buffered_comment);
 
 	if (result < 0) {