config_file: split out function that reads entries from a buffer The `config_read` function currently performs both reading the on-disk config file as well as parsing the retrieved buffer contents. To optimize how we refresh our config entries from an in-memory buffer, we need to be able to directly parse buffers, though, without involving any on-disk files at all. Extract a new function `config_read_buffer` that sets up the parsing logic and then parses config entries from a buffer, only. Have `config_read` use it to avoid duplicated logic.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
diff --git a/src/config_file.c b/src/config_file.c
index 91fce1c..77edf13 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -62,6 +62,7 @@ typedef struct {
} 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_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);
@@ -845,17 +846,17 @@ static int read_on_variable(
return result;
}
-static int config_read(
+static int config_read_buffer(
git_config_entries *entries,
const git_repository *repo,
git_config_file *file,
git_config_level_t level,
- int depth)
+ int depth,
+ const char *buf,
+ size_t buflen)
{
diskfile_parse_state parse_data;
git_config_parser reader;
- git_buf contents = GIT_BUF_INIT;
- struct stat st;
int error;
if (depth >= MAX_INCLUDE_DEPTH) {
@@ -863,27 +864,15 @@ static int config_read(
return -1;
}
- if (p_stat(file->path, &st) < 0) {
- error = git_path_set_error(errno, file->path, "stat");
- goto out;
- }
-
- if ((error = git_futils_readbuffer(&contents, file->path)) < 0)
- goto out;
-
- git_parse_ctx_init(&reader.ctx, contents.ptr, contents.size);
-
- git_futils_filestamp_set_from_stat(&file->stamp, &st);
- if ((error = git_hash_buf(&file->checksum, contents.ptr, contents.size)) < 0)
- goto out;
-
/* Initialize the reading position */
reader.file = file;
- git_parse_ctx_init(&reader.ctx, contents.ptr, contents.size);
+ git_parse_ctx_init(&reader.ctx, buf, buflen);
/* If the file is empty, there's nothing for us to do */
- if (!reader.ctx.content || *reader.ctx.content == '\0')
+ if (!reader.ctx.content || *reader.ctx.content == '\0') {
+ error = 0;
goto out;
+ }
parse_data.repo = repo;
parse_data.file_path = file->path;
@@ -894,6 +883,37 @@ static int config_read(
error = git_config_parse(&reader, NULL, read_on_variable, NULL, NULL, &parse_data);
out:
+ return error;
+}
+
+static int config_read(
+ git_config_entries *entries,
+ const git_repository *repo,
+ git_config_file *file,
+ git_config_level_t level,
+ int depth)
+{
+ git_buf contents = GIT_BUF_INIT;
+ struct stat st;
+ int error;
+
+ if (p_stat(file->path, &st) < 0) {
+ error = git_path_set_error(errno, file->path, "stat");
+ goto out;
+ }
+
+ if ((error = git_futils_readbuffer(&contents, file->path)) < 0)
+ goto out;
+
+ git_futils_filestamp_set_from_stat(&file->stamp, &st);
+ if ((error = git_hash_buf(&file->checksum, contents.ptr, contents.size)) < 0)
+ goto out;
+
+ if ((error = config_read_buffer(entries, repo, file, level, depth,
+ contents.ptr, contents.size)) < 0)
+ goto out;
+
+out:
git_buf_dispose(&contents);
return error;
}