config_file: reimplement `config_readonly_open` generically The `config_readonly_open` function currently receives as input a diskfile backend and will copy its entries to a new snapshot. This is rather intimate, as we need to assume that the source config backend is in fact a diskfile entry. We can do better than this though by using generic methods to copy contents of the provided backend, e.g. by using a config iterator. This also allows us to decouple the read-only backend from the read-write backend.
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
diff --git a/src/config_file.c b/src/config_file.c
index 88bba90..72f75c8 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -57,7 +57,7 @@ typedef struct {
typedef struct {
diskfile_header header;
- diskfile_backend *snapshot_from;
+ git_config_backend *source;
} diskfile_readonly_backend;
typedef struct {
@@ -595,26 +595,39 @@ static void backend_readonly_free(git_config_backend *_backend)
static int config_readonly_open(git_config_backend *cfg, git_config_level_t level, const git_repository *repo)
{
diskfile_readonly_backend *b = GIT_CONTAINER_OF(cfg, diskfile_readonly_backend, header.parent);
- diskfile_backend *src = b->snapshot_from;
- diskfile_header *src_header = &src->header;
- git_config_entries *entries;
+ git_config_entries *entries = NULL;
+ git_config_iterator *it = NULL;
+ git_config_entry *entry;
int error;
- if (!src_header->parent.readonly && (error = config_refresh(&src_header->parent)) < 0)
- return error;
-
/* We're just copying data, don't care about the level or repo*/
GIT_UNUSED(level);
GIT_UNUSED(repo);
- if ((entries = diskfile_entries_take(src_header)) == NULL)
- return -1;
+ if ((error = git_config_entries_new(&entries)) < 0 ||
+ (error = b->source->iterator(&it, b->source)) < 0)
+ goto out;
+
+ while ((error = git_config_next(&entry, it)) == 0)
+ if ((error = git_config_entries_dup_entry(entries, entry)) < 0)
+ goto out;
+
+ if (error < 0) {
+ if (error != GIT_ITEROVER)
+ goto out;
+ error = 0;
+ }
+
b->header.entries = entries;
- return 0;
+out:
+ git_config_iterator_free(it);
+ if (error)
+ git_config_entries_free(entries);
+ return error;
}
-static int config_snapshot(git_config_backend **out, git_config_backend *in)
+static int config_snapshot(git_config_backend **out, git_config_backend *source)
{
diskfile_readonly_backend *backend;
@@ -624,7 +637,7 @@ static int config_snapshot(git_config_backend **out, git_config_backend *in)
backend->header.parent.version = GIT_CONFIG_BACKEND_VERSION;
git_mutex_init(&backend->header.values_mutex);
- backend->snapshot_from = GIT_CONTAINER_OF(in, diskfile_backend, header.parent);
+ backend->source = source;
backend->header.parent.readonly = 1;
backend->header.parent.version = GIT_CONFIG_BACKEND_VERSION;