Commit cdef1fad by Edward Thomson

Merge pull request #3433 from libgit2/cmn/config-comment

Keep config comments in the same place as git
parents dfe2856d cd677b8f
...@@ -1711,6 +1711,7 @@ static const char *quotes_for_value(const char *value) ...@@ -1711,6 +1711,7 @@ static const char *quotes_for_value(const char *value)
struct write_data { struct write_data {
git_buf *buf; git_buf *buf;
git_buf buffered_comment;
unsigned int in_section : 1, unsigned int in_section : 1,
preg_replaced : 1; preg_replaced : 1;
const char *section; const char *section;
...@@ -1719,16 +1720,21 @@ struct write_data { ...@@ -1719,16 +1720,21 @@ struct write_data {
const char *value; const char *value;
}; };
static int write_line(struct write_data *write_data, const char *line, size_t line_len) static int write_line_to(git_buf *buf, const char *line, size_t line_len)
{ {
int result = git_buf_put(write_data->buf, line, line_len); int result = git_buf_put(buf, line, line_len);
if (!result && line_len && line[line_len-1] != '\n') if (!result && line_len && line[line_len-1] != '\n')
result = git_buf_printf(write_data->buf, "\n"); result = git_buf_printf(buf, "\n");
return result; return result;
} }
static int write_line(struct write_data *write_data, const char *line, size_t line_len)
{
return write_line_to(write_data->buf, line, line_len);
}
static int write_value(struct write_data *write_data) static int write_value(struct write_data *write_data)
{ {
const char *q; const char *q;
...@@ -1770,6 +1776,14 @@ static int write_on_section( ...@@ -1770,6 +1776,14 @@ static int write_on_section(
write_data->in_section = strcmp(current_section, write_data->section) == 0; write_data->in_section = strcmp(current_section, write_data->section) == 0;
/*
* If there were comments just before this section, dump them as well.
*/
if (!result) {
result = git_buf_put(write_data->buf, write_data->buffered_comment.ptr, write_data->buffered_comment.size);
git_buf_clear(&write_data->buffered_comment);
}
if (!result) if (!result)
result = write_line(write_data, line, line_len); result = write_line(write_data, line, line_len);
...@@ -1787,10 +1801,19 @@ static int write_on_variable( ...@@ -1787,10 +1801,19 @@ static int write_on_variable(
{ {
struct write_data *write_data = (struct write_data *)data; struct write_data *write_data = (struct write_data *)data;
bool has_matched = false; bool has_matched = false;
int error;
GIT_UNUSED(reader); GIT_UNUSED(reader);
GIT_UNUSED(current_section); GIT_UNUSED(current_section);
/*
* If there were comments just before this variable, let's dump them as well.
*/
if ((error = git_buf_put(write_data->buf, write_data->buffered_comment.ptr, write_data->buffered_comment.size)) < 0)
return error;
git_buf_clear(&write_data->buffered_comment);
/* See if we are to update this name/value pair; first examine name */ /* See if we are to update this name/value pair; first examine name */
if (write_data->in_section && if (write_data->in_section &&
strcasecmp(write_data->name, var_name) == 0) strcasecmp(write_data->name, var_name) == 0)
...@@ -1825,7 +1848,7 @@ static int write_on_comment(struct reader **reader, const char *line, size_t lin ...@@ -1825,7 +1848,7 @@ static int write_on_comment(struct reader **reader, const char *line, size_t lin
GIT_UNUSED(reader); GIT_UNUSED(reader);
write_data = (struct write_data *)data; write_data = (struct write_data *)data;
return write_line(write_data, line, line_len); return write_line_to(&write_data->buffered_comment, line, line_len);
} }
static int write_on_eof(struct reader **reader, void *data) static int write_on_eof(struct reader **reader, void *data)
...@@ -1835,6 +1858,12 @@ static int write_on_eof(struct reader **reader, void *data) ...@@ -1835,6 +1858,12 @@ static int write_on_eof(struct reader **reader, void *data)
GIT_UNUSED(reader); GIT_UNUSED(reader);
/*
* If we've buffered comments when reaching EOF, make sure to dump them.
*/
if ((result = git_buf_put(write_data->buf, write_data->buffered_comment.ptr, write_data->buffered_comment.size)) < 0)
return result;
/* If we are at the EOF and have not written our value (again, for a /* If we are at the EOF and have not written our value (again, for a
* simple name/value set, not a multivar) then we have never seen the * simple name/value set, not a multivar) then we have never seen the
* section in question and should create a new section and write the * section in question and should create a new section and write the
...@@ -1892,6 +1921,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p ...@@ -1892,6 +1921,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
section = git__strndup(key, ldot - key); section = git__strndup(key, ldot - key);
write_data.buf = &buf; write_data.buf = &buf;
git_buf_init(&write_data.buffered_comment, 0);
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;
...@@ -1901,6 +1931,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p ...@@ -1901,6 +1931,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p
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_buf_free(&write_data.buffered_comment);
if (result < 0) { if (result < 0) {
git_filebuf_cleanup(&file); git_filebuf_cleanup(&file);
......
...@@ -530,6 +530,9 @@ void test_config_write__outside_change(void) ...@@ -530,6 +530,9 @@ void test_config_write__outside_change(void)
git_config_free(cfg); git_config_free(cfg);
} }
#define FOO_COMMENT \
"; another comment!\n"
#define SECTION_FOO \ #define SECTION_FOO \
"\n" \ "\n" \
" \n" \ " \n" \
...@@ -537,7 +540,8 @@ void test_config_write__outside_change(void) ...@@ -537,7 +540,8 @@ void test_config_write__outside_change(void)
" # here's a comment\n" \ " # here's a comment\n" \
"\tname = \"value\"\n" \ "\tname = \"value\"\n" \
" name2 = \"value2\"\n" \ " name2 = \"value2\"\n" \
"; another comment!\n"
#define SECTION_FOO_WITH_COMMENT SECTION_FOO FOO_COMMENT
#define SECTION_BAR \ #define SECTION_BAR \
"[section \"bar\"]\t\n" \ "[section \"bar\"]\t\n" \
...@@ -553,7 +557,7 @@ void test_config_write__preserves_whitespace_and_comments(void) ...@@ -553,7 +557,7 @@ void test_config_write__preserves_whitespace_and_comments(void)
git_buf newfile = GIT_BUF_INIT; git_buf newfile = GIT_BUF_INIT;
/* This config can occur after removing and re-adding the origin remote */ /* This config can occur after removing and re-adding the origin remote */
const char *file_content = SECTION_FOO SECTION_BAR; const char *file_content = SECTION_FOO_WITH_COMMENT SECTION_BAR;
/* Write the test config and make sure the expected entry exists */ /* Write the test config and make sure the expected entry exists */
cl_git_mkfile(file_name, file_content); cl_git_mkfile(file_name, file_content);
...@@ -567,9 +571,10 @@ void test_config_write__preserves_whitespace_and_comments(void) ...@@ -567,9 +571,10 @@ void test_config_write__preserves_whitespace_and_comments(void)
cl_assert_equal_strn(SECTION_FOO, n, strlen(SECTION_FOO)); cl_assert_equal_strn(SECTION_FOO, n, strlen(SECTION_FOO));
n += strlen(SECTION_FOO); n += strlen(SECTION_FOO);
cl_assert_equal_strn("\tother = otherval\n", n, strlen("\tother = otherval\n")); cl_assert_equal_strn("\tother = otherval\n", n, strlen("\tother = otherval\n"));
n += strlen("\tother = otherval\n"); n += strlen("\tother = otherval\n");
cl_assert_equal_strn(FOO_COMMENT, n, strlen(FOO_COMMENT));
n += strlen(FOO_COMMENT);
cl_assert_equal_strn(SECTION_BAR, n, strlen(SECTION_BAR)); cl_assert_equal_strn(SECTION_BAR, n, strlen(SECTION_BAR));
n += strlen(SECTION_BAR); n += strlen(SECTION_BAR);
......
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