Unverified Commit 6f8a6c33 by Carlos Martín Nieto Committed by GitHub

Merge pull request #4392 from libgit2/cmn/config-write-preserve-case

Preserve the input casing when writing config files
parents 9e3fb594 94e30d9b
...@@ -6,6 +6,10 @@ v0.26 + 1 ...@@ -6,6 +6,10 @@ v0.26 + 1
* Improved `p_unlink` in `posix_w32.c` to try and make a file writable * 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. 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 ### API additions
* `git_remote_create_detached()` creates a remote that is not associated * `git_remote_create_detached()` creates a remote that is not associated
......
...@@ -120,7 +120,7 @@ typedef struct { ...@@ -120,7 +120,7 @@ typedef struct {
} diskfile_readonly_backend; } diskfile_readonly_backend;
static int config_read(git_strmap *values, struct config_file *file, git_config_level_t level, int depth); 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); static char *escape_value(const char *ptr);
int git_config_file__snapshot(git_config_backend **out, diskfile_backend *in); 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 ...@@ -513,7 +513,7 @@ static int config_set(git_config_backend *cfg, const char *name, const char *val
GITERR_CHECK_ALLOC(esc_value); 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; goto out;
ret = config_refresh(cfg); ret = config_refresh(cfg);
...@@ -591,7 +591,7 @@ static int config_set_multivar( ...@@ -591,7 +591,7 @@ static int config_set_multivar(
} }
/* If we do have it, set call config_write() and reload */ /* 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; goto out;
result = config_refresh(cfg); result = config_refresh(cfg);
...@@ -641,7 +641,7 @@ static int config_delete(git_config_backend *cfg, const char *name) ...@@ -641,7 +641,7 @@ static int config_delete(git_config_backend *cfg, const char *name)
return -1; 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 result;
return config_refresh(cfg); return config_refresh(cfg);
...@@ -682,7 +682,7 @@ static int config_delete_multivar(git_config_backend *cfg, const char *name, con ...@@ -682,7 +682,7 @@ static int config_delete_multivar(git_config_backend *cfg, const char *name, con
goto out; goto out;
} }
if ((result = config_write(b, key, &preg, NULL)) < 0) if ((result = config_write(b, name, key, &preg, NULL)) < 0)
goto out; goto out;
result = config_refresh(cfg); result = config_refresh(cfg);
...@@ -1739,7 +1739,9 @@ struct write_data { ...@@ -1739,7 +1739,9 @@ struct write_data {
git_buf buffered_comment; git_buf buffered_comment;
unsigned int in_section : 1, unsigned int in_section : 1,
preg_replaced : 1; preg_replaced : 1;
const char *orig_section;
const char *section; const char *section;
const char *orig_name;
const char *name; const char *name;
const regex_t *preg; const regex_t *preg;
const char *value; const char *value;
...@@ -1767,7 +1769,7 @@ static int write_value(struct write_data *write_data) ...@@ -1767,7 +1769,7 @@ static int write_value(struct write_data *write_data)
q = quotes_for_value(write_data->value); q = quotes_for_value(write_data->value);
result = git_buf_printf(write_data->buf, 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` /* 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 * to `NULL` will prevent us from trying to write it again later (in
...@@ -1898,7 +1900,7 @@ static int write_on_eof( ...@@ -1898,7 +1900,7 @@ static int write_on_eof(
if ((!write_data->preg || !write_data->preg_replaced) && write_data->value) { if ((!write_data->preg || !write_data->preg_replaced) && write_data->value) {
/* write the section header unless we're already in it */ /* write the section header unless we're already in it */
if (!current_section || strcmp(current_section, write_data->section)) 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) if (!result)
result = write_value(write_data); result = write_value(write_data);
...@@ -1910,10 +1912,10 @@ static int write_on_eof( ...@@ -1910,10 +1912,10 @@ static int write_on_eof(
/* /*
* This is pretty much the parsing, except we write out anything we don't have * 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; int result;
char *section, *name, *ldot; char *orig_section, *section, *orig_name, *name, *ldot;
git_filebuf file = GIT_FILEBUF_INIT; git_filebuf file = GIT_FILEBUF_INIT;
git_buf buf = GIT_BUF_INIT; git_buf buf = GIT_BUF_INIT;
struct reader reader; struct reader reader;
...@@ -1953,18 +1955,27 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p ...@@ -1953,18 +1955,27 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
ldot = strrchr(key, '.'); ldot = strrchr(key, '.');
name = ldot + 1; name = ldot + 1;
section = git__strndup(key, ldot - key); 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; write_data.buf = &buf;
git_buf_init(&write_data.buffered_comment, 0); git_buf_init(&write_data.buffered_comment, 0);
write_data.orig_section = orig_section;
write_data.section = section; write_data.section = section;
write_data.in_section = 0; write_data.in_section = 0;
write_data.preg_replaced = 0; write_data.preg_replaced = 0;
write_data.orig_name = orig_name;
write_data.name = name; write_data.name = name;
write_data.preg = preg; write_data.preg = preg;
write_data.value = value; write_data.value = value;
result = config_parse(&reader, write_on_section, write_on_variable, write_on_comment, write_on_eof, &write_data); result = config_parse(&reader, write_on_section, write_on_variable, write_on_comment, write_on_eof, &write_data);
git__free(section); git__free(section);
git__free(orig_section);
git_buf_free(&write_data.buffered_comment); git_buf_free(&write_data.buffered_comment);
if (result < 0) { if (result < 0) {
......
...@@ -722,3 +722,26 @@ void test_config_write__repeated(void) ...@@ -722,3 +722,26 @@ void test_config_write__repeated(void)
git_config_free(cfg); 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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment