mirror of
https://github.com/libgit2/libgit2.git
synced 2026-06-22 06:26:26 +00:00
@@ -36,7 +36,7 @@ static int strip_comments(char *line, int in_quotes)
|
||||
char *ptr;
|
||||
|
||||
for (ptr = line; *ptr; ++ptr) {
|
||||
if (ptr[0] == '"' && ptr > line && ptr[-1] != '\\')
|
||||
if (ptr[0] == '"' && ((ptr > line && ptr[-1] != '\\') || ptr == line))
|
||||
quote_count++;
|
||||
|
||||
if ((ptr[0] == ';' || ptr[0] == '#') &&
|
||||
@@ -325,7 +325,7 @@ done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_multiline_variable(git_config_parser *reader, git_str *value, int in_quotes)
|
||||
static int parse_multiline_variable(git_config_parser *reader, git_str *value, int in_quotes, size_t *line_len)
|
||||
{
|
||||
int quote_count;
|
||||
bool multiline = true;
|
||||
@@ -338,6 +338,10 @@ static int parse_multiline_variable(git_config_parser *reader, git_str *value, i
|
||||
git_parse_advance_line(&reader->ctx);
|
||||
line = git__strndup(reader->ctx.line, reader->ctx.line_len);
|
||||
GIT_ERROR_CHECK_ALLOC(line);
|
||||
if (GIT_ADD_SIZET_OVERFLOW(line_len, *line_len, reader->ctx.line_len)) {
|
||||
error = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* We've reached the end of the file, there is no continuation.
|
||||
@@ -415,7 +419,7 @@ static int parse_name(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_variable(git_config_parser *reader, char **var_name, char **var_value)
|
||||
static int parse_variable(git_config_parser *reader, char **var_name, char **var_value, size_t *line_len)
|
||||
{
|
||||
const char *value_start = NULL;
|
||||
char *line = NULL, *name = NULL, *value = NULL;
|
||||
@@ -449,7 +453,7 @@ static int parse_variable(git_config_parser *reader, char **var_name, char **var
|
||||
git_str_attach(&multi_value, value, 0);
|
||||
value = NULL;
|
||||
|
||||
if (parse_multiline_variable(reader, &multi_value, quote_count % 2) < 0 ||
|
||||
if (parse_multiline_variable(reader, &multi_value, quote_count % 2, line_len) < 0 ||
|
||||
git_str_oom(&multi_value)) {
|
||||
error = -1;
|
||||
git_str_dispose(&multi_value);
|
||||
@@ -554,7 +558,7 @@ int git_config_parse(
|
||||
break;
|
||||
|
||||
default: /* assume variable declaration */
|
||||
if ((result = parse_variable(parser, &var_name, &var_value)) == 0 && on_variable) {
|
||||
if ((result = parse_variable(parser, &var_name, &var_value, &line_len)) == 0 && on_variable) {
|
||||
result = on_variable(parser, current_section, var_name, var_value, line_start, line_len, payload);
|
||||
git__free(var_name);
|
||||
git__free(var_value);
|
||||
|
||||
@@ -209,6 +209,21 @@ void test_config_read__symbol_headers(void)
|
||||
{
|
||||
git_config *cfg;
|
||||
cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config20")));
|
||||
cl_git_pass(git_config_get_string_buf(&buf, cfg, "valid.[subsection].something"));
|
||||
cl_assert_equal_s("a", buf.ptr);
|
||||
git_buf_dispose(&buf);
|
||||
cl_git_pass(git_config_get_string_buf(&buf, cfg, "sec.[subsec]/child.parent"));
|
||||
cl_assert_equal_s("grand", buf.ptr);
|
||||
git_buf_dispose(&buf);
|
||||
cl_git_pass(git_config_get_string_buf(&buf, cfg, "sec2.[subsec2]/child2.type"));
|
||||
cl_assert_equal_s("dvcs", buf.ptr);
|
||||
git_buf_dispose(&buf);
|
||||
cl_git_pass(git_config_get_string_buf(&buf, cfg, "sec3.escape\"quote.vcs"));
|
||||
cl_assert_equal_s("git", buf.ptr);
|
||||
git_buf_dispose(&buf);
|
||||
cl_git_pass(git_config_get_string_buf(&buf, cfg, "sec4.escaping\\slash.lib"));
|
||||
cl_assert_equal_s("git2", buf.ptr);
|
||||
git_buf_dispose(&buf);
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
@@ -219,6 +234,19 @@ void test_config_read__multiline_multiple_quoted_comment_chars(void)
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
void test_config_read__multiline_multiple_quoted_quote_at_beginning_of_line(void)
|
||||
{
|
||||
git_config* cfg;
|
||||
cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config22")));
|
||||
cl_git_pass(git_config_get_string_buf(&buf, cfg, "alias.m"));
|
||||
cl_assert_equal_s("cmd ;; ;; bar", buf.ptr);
|
||||
git_buf_dispose(&buf);
|
||||
cl_git_pass(git_config_get_string_buf(&buf, cfg, "alias.m2"));
|
||||
cl_assert_equal_s("'; ; something '", buf.ptr);
|
||||
git_buf_dispose(&buf);
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
void test_config_read__header_in_last_line(void)
|
||||
{
|
||||
git_config *cfg;
|
||||
|
||||
@@ -8,6 +8,7 @@ void test_config_write__initialize(void)
|
||||
cl_fixture_sandbox("config/config9");
|
||||
cl_fixture_sandbox("config/config15");
|
||||
cl_fixture_sandbox("config/config17");
|
||||
cl_fixture_sandbox("config/config22");
|
||||
}
|
||||
|
||||
void test_config_write__cleanup(void)
|
||||
@@ -15,6 +16,7 @@ void test_config_write__cleanup(void)
|
||||
cl_fixture_cleanup("config9");
|
||||
cl_fixture_cleanup("config15");
|
||||
cl_fixture_cleanup("config17");
|
||||
cl_fixture_cleanup("config22");
|
||||
}
|
||||
|
||||
void test_config_write__replace_value(void)
|
||||
@@ -743,3 +745,20 @@ void test_config_write__preserve_case(void)
|
||||
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
void test_config_write__write_config_file_with_multi_line_value(void)
|
||||
{
|
||||
git_config* cfg;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
cl_git_pass(git_config_open_ondisk(&cfg, "config22"));
|
||||
cl_git_pass(git_config_get_string_buf(&buf, cfg, "alias.m"));
|
||||
cl_assert_equal_s("cmd ;; ;; bar", buf.ptr);
|
||||
cl_git_pass(git_config_set_string(cfg, "sOMe.ThInG", "foo"));
|
||||
git_buf_dispose(&buf);
|
||||
cl_git_pass(git_config_get_string_buf(&buf, cfg, "alias.m"));
|
||||
cl_assert_equal_s("cmd ;; ;; bar", buf.ptr);
|
||||
git_buf_dispose(&buf);
|
||||
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
10
tests/resources/config/config22
vendored
Normal file
10
tests/resources/config/config22
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
[alias]
|
||||
m = cmd \
|
||||
";;" \
|
||||
";;" \
|
||||
bar
|
||||
m2 = '\
|
||||
";" \
|
||||
";" \
|
||||
something \
|
||||
'
|
||||
Reference in New Issue
Block a user