diff options
author | Carlos MartÃn Nieto <carlosmn@github.com> | 2017-10-31 00:02:52 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-31 00:02:52 +0100 |
commit | 6f8a6c333659fda34b12eeabd2519b0f119aacbf (patch) | |
tree | 63b55b7a2a589d20a1f6ebac86444ca9e90139a2 | |
parent | 9e3fb594d644955decd3ce815e94a8e627acf83d (diff) | |
parent | 94e30d9b14b96283295b107268a862d37a96894f (diff) | |
download | libgit2-6f8a6c333659fda34b12eeabd2519b0f119aacbf.tar.gz |
Merge pull request #4392 from libgit2/cmn/config-write-preserve-case
Preserve the input casing when writing config files
-rw-r--r-- | CHANGELOG.md | 4 | ||||
-rw-r--r-- | src/config_file.c | 29 | ||||
-rw-r--r-- | tests/config/write.c | 23 |
3 files changed, 47 insertions, 9 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 43724b5f3..b07a0a050 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ v0.26 + 1 * Improved `p_unlink` in `posix_w32.c` to try and make a file writable before sleeping in the retry loop to prevent unnecessary calls to sleep. +* Writing to a configuration file now preserves the case of the key given by the + caller for the case-insensitive portions of the key (existing sections are + used even if they don't match). + ### API additions * `git_remote_create_detached()` creates a remote that is not associated diff --git a/src/config_file.c b/src/config_file.c index 00d6d9e13..9a6d81516 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; @@ -1953,18 +1955,27 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p ldot = strrchr(key, '.'); name = ldot + 1; section = git__strndup(key, ldot - key); + GITERR_CHECK_ALLOC(section); + + ldot = strrchr(orig_key, '.'); + orig_name = ldot + 1; + orig_section = git__strndup(orig_key, ldot - orig_key); + GITERR_CHECK_ALLOC(orig_section); 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) { diff --git a/tests/config/write.c b/tests/config/write.c index 56ef2e9fb..01b018b12 100644 --- a/tests/config/write.c +++ b/tests/config/write.c @@ -722,3 +722,26 @@ void test_config_write__repeated(void) git_config_free(cfg); } + +void test_config_write__preserve_case(void) +{ + const char *filename = "config-preserve-case"; + git_config *cfg; + git_buf result = GIT_BUF_INIT; + const char *expected = "[sOMe]\n" \ + "\tThInG = foo\n" \ + "\tOtheR = thing\n"; + + cl_git_pass(git_config_open_ondisk(&cfg, filename)); + cl_git_pass(git_config_set_string(cfg, "sOMe.ThInG", "foo")); + cl_git_pass(git_config_set_string(cfg, "SomE.OtheR", "thing")); + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, filename)); + + cl_git_pass(git_futils_readbuffer(&result, filename)); + cl_assert_equal_s(expected, result.ptr); + git_buf_free(&result); + + git_config_free(cfg); +} |