summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2019-07-11 14:03:21 +0200
committerGitHub <noreply@github.com>2019-07-11 14:03:21 +0200
commita6ad9e8a4edc75a3bcf404be636329082f80d1bb (patch)
tree5b60f577ce6de9f6e371684f707b1ef095f55529
parentba9725a28f351e52c8054e543298f78d4d5f2cf0 (diff)
parentdbeadf8a9e9cb66f65b894e4dfd1fb23f9f31d5b (diff)
downloadlibgit2-a6ad9e8a4edc75a3bcf404be636329082f80d1bb.tar.gz
Merge pull request #5134 from pks-t/pks/config-parser-separation
Config parser separation
-rw-r--r--src/config_file.c123
-rw-r--r--src/config_mem.c18
-rw-r--r--src/config_parse.c27
-rw-r--r--src/config_parse.h24
-rw-r--r--src/parse.h2
5 files changed, 98 insertions, 96 deletions
diff --git a/src/config_file.c b/src/config_file.c
index 38653274f..51a3e93e2 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -26,6 +26,13 @@
/* Max depth for [include] directives */
#define MAX_INCLUDE_DEPTH 10
+typedef struct diskfile {
+ git_futils_filestamp stamp;
+ git_oid checksum;
+ char *path;
+ git_array_t(struct diskfile) includes;
+} diskfile;
+
typedef struct {
git_config_backend parent;
/* mutex to coordinate accessing the values */
@@ -44,7 +51,7 @@ typedef struct {
git_filebuf locked_buf;
git_buf locked_content;
- git_config_file file;
+ diskfile file;
} diskfile_backend;
typedef struct {
@@ -55,14 +62,14 @@ typedef struct {
typedef struct {
const git_repository *repo;
- const char *file_path;
+ diskfile *file;
git_config_entries *entries;
git_config_level_t level;
unsigned int depth;
} diskfile_parse_state;
-static int config_read(git_config_entries *entries, const git_repository *repo, git_config_file *file, git_config_level_t level, int depth);
-static int config_read_buffer(git_config_entries *entries, const git_repository *repo, git_config_file *file, git_config_level_t level, int depth, const char *buf, size_t buflen);
+static int config_read(git_config_entries *entries, const git_repository *repo, diskfile *file, git_config_level_t level, int depth);
+static int config_read_buffer(git_config_entries *entries, const git_repository *repo, diskfile *file, git_config_level_t level, int depth, const char *buf, size_t buflen);
static int config_write(diskfile_backend *cfg, const char *orig_key, const char *key, const p_regex_t *preg, const char *value);
static char *escape_value(const char *ptr);
@@ -96,9 +103,9 @@ static git_config_entries *diskfile_entries_take(diskfile_header *h)
return entries;
}
-static void config_file_clear(git_config_file *file)
+static void config_file_clear(diskfile *file)
{
- git_config_file *include;
+ diskfile *include;
uint32_t i;
if (file == NULL)
@@ -134,9 +141,9 @@ static int config_open(git_config_backend *cfg, git_config_level_t level, const
return res;
}
-static int config_is_modified(int *modified, git_config_file *file)
+static int config_is_modified(int *modified, diskfile *file)
{
- git_config_file *include;
+ diskfile *include;
git_buf buf = GIT_BUF_INIT;
git_oid hash;
uint32_t i;
@@ -174,9 +181,9 @@ static int config_set_entries(git_config_backend *cfg, git_config_entries *entri
{
diskfile_backend *b = (diskfile_backend *)cfg;
git_config_entries *old = NULL;
- git_config_file *include;
+ diskfile *include;
int error;
- size_t i;
+ uint32_t i;
if (b->header.parent.readonly)
return config_error_readonly();
@@ -677,10 +684,9 @@ static char *escape_value(const char *ptr)
return git_buf_detach(&buf);
}
-static int parse_include(git_config_parser *reader,
- diskfile_parse_state *parse_data, const char *file)
+static int parse_include(diskfile_parse_state *parse_data, const char *file)
{
- git_config_file *include;
+ diskfile *include;
git_buf path = GIT_BUF_INIT;
char *dir;
int result;
@@ -688,7 +694,7 @@ static int parse_include(git_config_parser *reader,
if (!file)
return 0;
- if ((result = git_path_dirname_r(&path, reader->file->path)) < 0)
+ if ((result = git_path_dirname_r(&path, parse_data->file->path)) < 0)
return result;
dir = git_buf_detach(&path);
@@ -698,7 +704,7 @@ static int parse_include(git_config_parser *reader,
if (result < 0)
return result;
- include = git_array_alloc(reader->file->includes);
+ include = git_array_alloc(parse_data->file->includes);
GIT_ERROR_CHECK_ALLOC(include);
memset(include, 0, sizeof(*include));
git_array_init(include->includes);
@@ -783,8 +789,7 @@ static const struct {
{ "gitdir/i:", conditional_match_gitdir_i }
};
-static int parse_conditional_include(git_config_parser *reader,
- diskfile_parse_state *parse_data, const char *section, const char *file)
+static int parse_conditional_include(diskfile_parse_state *parse_data, const char *section, const char *file)
{
char *condition;
size_t i;
@@ -802,12 +807,12 @@ static int parse_conditional_include(git_config_parser *reader,
if ((error = conditions[i].matches(&matches,
parse_data->repo,
- parse_data->file_path,
+ parse_data->file->path,
condition + strlen(conditions[i].prefix))) < 0)
break;
if (matches)
- error = parse_include(reader, parse_data, file);
+ error = parse_include(parse_data, file);
break;
}
@@ -831,6 +836,7 @@ static int read_on_variable(
const char *c;
int result = 0;
+ GIT_UNUSED(reader);
GIT_UNUSED(line);
GIT_UNUSED(line_len);
@@ -863,11 +869,10 @@ static int read_on_variable(
/* Add or append the new config option */
if (!git__strcmp(entry->name, "include.path"))
- result = parse_include(reader, parse_data, entry->value);
+ result = parse_include(parse_data, entry->value);
else if (!git__prefixcmp(entry->name, "includeif.") &&
!git__suffixcmp(entry->name, ".path"))
- result = parse_conditional_include(reader, parse_data,
- entry->name, entry->value);
+ result = parse_conditional_include(parse_data, entry->name, entry->value);
return result;
}
@@ -875,7 +880,7 @@ static int read_on_variable(
static int config_read_buffer(
git_config_entries *entries,
const git_repository *repo,
- git_config_file *file,
+ diskfile *file,
git_config_level_t level,
int depth,
const char *buf,
@@ -891,7 +896,7 @@ static int config_read_buffer(
}
/* Initialize the reading position */
- reader.file = file;
+ reader.path = file->path;
git_parse_ctx_init(&reader.ctx, buf, buflen);
/* If the file is empty, there's nothing for us to do */
@@ -901,7 +906,7 @@ static int config_read_buffer(
}
parse_data.repo = repo;
- parse_data.file_path = file->path;
+ parse_data.file = file;
parse_data.entries = entries;
parse_data.level = level;
parse_data.depth = depth;
@@ -915,7 +920,7 @@ out:
static int config_read(
git_config_entries *entries,
const git_repository *repo,
- git_config_file *file,
+ diskfile *file,
git_config_level_t level,
int depth)
{
@@ -1169,37 +1174,30 @@ static int write_on_eof(
*/
static int config_write(diskfile_backend *cfg, const char *orig_key, const char *key, const p_regex_t *preg, const char* value)
{
- int result;
- char *orig_section, *section, *orig_name, *name, *ldot;
- git_filebuf file = GIT_FILEBUF_INIT;
+ char *orig_section = NULL, *section = NULL, *orig_name, *name, *ldot;
git_buf buf = GIT_BUF_INIT, contents = GIT_BUF_INIT;
- git_config_parser reader;
+ git_config_parser parser = GIT_CONFIG_PARSER_INIT;
+ git_filebuf file = GIT_FILEBUF_INIT;
struct write_data write_data;
+ int error;
- memset(&reader, 0, sizeof(reader));
- reader.file = &cfg->file;
+ memset(&write_data, 0, sizeof(write_data));
if (cfg->locked) {
- result = git_buf_puts(&contents, git_buf_cstr(&cfg->locked_content) == NULL ? "" : git_buf_cstr(&cfg->locked_content));
+ error = git_buf_puts(&contents, git_buf_cstr(&cfg->locked_content) == NULL ? "" : git_buf_cstr(&cfg->locked_content));
} else {
- /* Lock the file */
- if ((result = git_filebuf_open(
- &file, cfg->file.path, GIT_FILEBUF_HASH_CONTENTS, GIT_CONFIG_FILE_MODE)) < 0) {
- git_buf_dispose(&contents);
- return result;
- }
+ if ((error = git_filebuf_open(&file, cfg->file.path, GIT_FILEBUF_HASH_CONTENTS,
+ GIT_CONFIG_FILE_MODE)) < 0)
+ goto done;
/* We need to read in our own config file */
- result = git_futils_readbuffer(&contents, cfg->file.path);
+ error = git_futils_readbuffer(&contents, cfg->file.path);
}
+ if (error < 0 && error != GIT_ENOTFOUND)
+ goto done;
- /* Initialise the reading position */
- if (result == 0 || result == GIT_ENOTFOUND) {
- git_parse_ctx_init(&reader.ctx, contents.ptr, contents.size);
- } else {
- git_filebuf_cleanup(&file);
- return -1; /* OS error when reading the file */
- }
+ if ((git_config_parser_init(&parser, cfg->file.path, contents.ptr, contents.size)) < 0)
+ goto done;
ldot = strrchr(key, '.');
name = ldot + 1;
@@ -1212,30 +1210,16 @@ static int config_write(diskfile_backend *cfg, const char *orig_key, const char
GIT_ERROR_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 = git_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_dispose(&write_data.buffered_comment);
-
- if (result < 0) {
- git_filebuf_cleanup(&file);
+ if ((error = git_config_parse(&parser, write_on_section, write_on_variable,
+ write_on_comment, write_on_eof, &write_data)) < 0)
goto done;
- }
if (cfg->locked) {
size_t len = buf.asize;
@@ -1245,16 +1229,21 @@ static int config_write(diskfile_backend *cfg, const char *orig_key, const char
} else {
git_filebuf_write(&file, git_buf_cstr(&buf), git_buf_len(&buf));
- if ((result = git_filebuf_commit(&file)) < 0)
+ if ((error = git_filebuf_commit(&file)) < 0)
goto done;
- if ((result = config_refresh_from_buffer(&cfg->header.parent, buf.ptr, buf.size)) < 0)
+ if ((error = config_refresh_from_buffer(&cfg->header.parent, buf.ptr, buf.size)) < 0)
goto done;
}
done:
+ git__free(section);
+ git__free(orig_section);
+ git_buf_dispose(&write_data.buffered_comment);
git_buf_dispose(&buf);
git_buf_dispose(&contents);
- git_parse_ctx_clear(&reader.ctx);
- return result;
+ git_filebuf_cleanup(&file);
+ git_config_parser_dispose(&parser);
+
+ return error;
}
diff --git a/src/config_mem.c b/src/config_mem.c
index c2ecfda12..e4006db32 100644
--- a/src/config_mem.c
+++ b/src/config_mem.c
@@ -78,20 +78,24 @@ static int read_variable_cb(
static int config_memory_open(git_config_backend *backend, git_config_level_t level, const git_repository *repo)
{
config_memory_backend *memory_backend = (config_memory_backend *) backend;
+ git_config_parser parser = GIT_PARSE_CTX_INIT;
config_memory_parse_data parse_data;
- git_config_parser reader;
+ int error;
GIT_UNUSED(repo);
- if (memory_backend->cfg.size == 0)
- return 0;
-
- git_parse_ctx_init(&reader.ctx, memory_backend->cfg.ptr, memory_backend->cfg.size);
- reader.file = NULL;
+ if ((error = git_config_parser_init(&parser, "in-memory", memory_backend->cfg.ptr,
+ memory_backend->cfg.size)) < 0)
+ goto out;
parse_data.entries = memory_backend->entries;
parse_data.level = level;
- return git_config_parse(&reader, NULL, read_variable_cb, NULL, NULL, &parse_data);
+ if ((error = git_config_parse(&parser, NULL, read_variable_cb, NULL, NULL, &parse_data)) < 0)
+ goto out;
+
+out:
+ git_config_parser_dispose(&parser);
+ return error;
}
static int config_memory_get(git_config_backend *backend, const char *key, git_config_entry **out)
diff --git a/src/config_parse.c b/src/config_parse.c
index 46dce4038..48ad1164f 100644
--- a/src/config_parse.c
+++ b/src/config_parse.c
@@ -16,16 +16,14 @@ const char *git_config_escaped = "\n\t\b\"\\";
static void set_parse_error(git_config_parser *reader, int col, const char *error_str)
{
- const char *file = reader->file ? reader->file->path : "in-memory";
-
if (col)
git_error_set(GIT_ERROR_CONFIG,
"failed to parse config file: %s (in %s:%"PRIuZ", column %d)",
- error_str, file, reader->ctx.line_num, col);
+ error_str, reader->path, reader->ctx.line_num, col);
else
git_error_set(GIT_ERROR_CONFIG,
"failed to parse config file: %s (in %s:%"PRIuZ")",
- error_str, file, reader->ctx.line_num);
+ error_str, reader->path, reader->ctx.line_num);
}
@@ -476,13 +474,24 @@ out:
return error;
}
+int git_config_parser_init(git_config_parser *out, const char *path, const char *data, size_t datalen)
+{
+ out->path = path;
+ return git_parse_ctx_init(&out->ctx, data, datalen);
+}
+
+void git_config_parser_dispose(git_config_parser *parser)
+{
+ git_parse_ctx_clear(&parser->ctx);
+}
+
int git_config_parse(
git_config_parser *parser,
git_config_parser_section_cb on_section,
git_config_parser_variable_cb on_variable,
git_config_parser_comment_cb on_comment,
git_config_parser_eof_cb on_eof,
- void *data)
+ void *payload)
{
git_parse_ctx *ctx;
char *current_section = NULL, *var_name = NULL, *var_value = NULL;
@@ -522,7 +531,7 @@ int git_config_parse(
git_parse_advance_chars(ctx, result);
if (on_section)
- result = on_section(parser, current_section, line_start, line_len, data);
+ result = on_section(parser, current_section, line_start, line_len, payload);
/*
* After we've parsed the section header we may not be
* done with the line. If there's still data in there,
@@ -542,13 +551,13 @@ int git_config_parse(
case ';':
case '#':
if (on_comment) {
- result = on_comment(parser, line_start, line_len, data);
+ result = on_comment(parser, line_start, line_len, payload);
}
break;
default: /* assume variable declaration */
if ((result = parse_variable(parser, &var_name, &var_value)) == 0 && on_variable) {
- result = on_variable(parser, current_section, var_name, var_value, line_start, line_len, data);
+ result = on_variable(parser, current_section, var_name, var_value, line_start, line_len, payload);
git__free(var_name);
git__free(var_value);
}
@@ -561,7 +570,7 @@ int git_config_parse(
}
if (on_eof)
- result = on_eof(parser, current_section, data);
+ result = on_eof(parser, current_section, payload);
out:
git__free(current_section);
diff --git a/src/config_parse.h b/src/config_parse.h
index 4db31bd1f..0129ee309 100644
--- a/src/config_parse.h
+++ b/src/config_parse.h
@@ -17,24 +17,19 @@
extern const char *git_config_escapes;
extern const char *git_config_escaped;
-typedef struct config_file {
- git_futils_filestamp stamp;
- git_oid checksum;
- char *path;
- git_array_t(struct config_file) includes;
-} git_config_file;
-
typedef struct {
- git_config_file *file;
+ const char *path;
git_parse_ctx ctx;
} git_config_parser;
+#define GIT_CONFIG_PARSER_INIT { NULL, GIT_PARSE_CTX_INIT }
+
typedef int (*git_config_parser_section_cb)(
git_config_parser *parser,
const char *current_section,
const char *line,
size_t line_len,
- void *data);
+ void *payload);
typedef int (*git_config_parser_variable_cb)(
git_config_parser *parser,
@@ -43,18 +38,21 @@ typedef int (*git_config_parser_variable_cb)(
const char *var_value,
const char *line,
size_t line_len,
- void *data);
+ void *payload);
typedef int (*git_config_parser_comment_cb)(
git_config_parser *parser,
const char *line,
size_t line_len,
- void *data);
+ void *payload);
typedef int (*git_config_parser_eof_cb)(
git_config_parser *parser,
const char *current_section,
- void *data);
+ void *payload);
+
+int git_config_parser_init(git_config_parser *out, const char *path, const char *data, size_t datalen);
+void git_config_parser_dispose(git_config_parser *parser);
int git_config_parse(
git_config_parser *parser,
@@ -62,6 +60,6 @@ int git_config_parse(
git_config_parser_variable_cb on_variable,
git_config_parser_comment_cb on_comment,
git_config_parser_eof_cb on_eof,
- void *data);
+ void *payload);
#endif
diff --git a/src/parse.h b/src/parse.h
index 21dcf9bd1..42a2aff1a 100644
--- a/src/parse.h
+++ b/src/parse.h
@@ -23,6 +23,8 @@ typedef struct {
size_t line_num;
} git_parse_ctx;
+#define GIT_PARSE_CTX_INIT { 0 }
+
int git_parse_ctx_init(git_parse_ctx *ctx, const char *content, size_t content_len);
void git_parse_ctx_clear(git_parse_ctx *ctx);