File Coverage

deps/libgit2/src/config_snapshot.c
Criterion Covered Total %
statement 66 87 75.8
branch 14 24 58.3
condition n/a
subroutine n/a
pod n/a
total 80 111 72.0


line stmt bran cond sub pod time code
1             /*
2             * Copyright (C) the libgit2 contributors. All rights reserved.
3             *
4             * This file is part of libgit2, distributed under the GNU GPL v2 with
5             * a Linking Exception. For full terms see the included COPYING file.
6             */
7              
8             #include "config_backend.h"
9              
10             #include "config.h"
11             #include "config_entries.h"
12              
13             typedef struct {
14             git_config_backend parent;
15             git_mutex values_mutex;
16             git_config_entries *entries;
17             git_config_backend *source;
18             } config_snapshot_backend;
19              
20 0           static int config_error_readonly(void)
21             {
22 0           git_error_set(GIT_ERROR_CONFIG, "this backend is read-only");
23 0           return -1;
24             }
25              
26 76           static int config_snapshot_iterator(
27             git_config_iterator **iter,
28             struct git_config_backend *backend)
29             {
30 76           config_snapshot_backend *b = GIT_CONTAINER_OF(backend, config_snapshot_backend, parent);
31 76           git_config_entries *entries = NULL;
32             int error;
33              
34 76 50         if ((error = git_config_entries_dup(&entries, b->entries)) < 0 ||
35 76           (error = git_config_entries_iterator_new(iter, entries)) < 0)
36             goto out;
37              
38             out:
39             /* Let iterator delete duplicated entries when it's done */
40 76           git_config_entries_free(entries);
41 76           return error;
42             }
43              
44             /* release the map containing the entry as an equivalent to freeing it */
45 824           static void config_snapshot_entry_free(git_config_entry *entry)
46             {
47 824           git_config_entries *entries = (git_config_entries *) entry->payload;
48 824           git_config_entries_free(entries);
49 824           }
50              
51 4322           static int config_snapshot_get(git_config_backend *cfg, const char *key, git_config_entry **out)
52             {
53 4322           config_snapshot_backend *b = GIT_CONTAINER_OF(cfg, config_snapshot_backend, parent);
54 4322           git_config_entries *entries = NULL;
55             git_config_entry *entry;
56 4322           int error = 0;
57              
58 4322 50         if (git_mutex_lock(&b->values_mutex) < 0) {
59 0           git_error_set(GIT_ERROR_OS, "failed to lock config backend");
60 0           return -1;
61             }
62              
63 4322           entries = b->entries;
64 4322           git_config_entries_incref(entries);
65             git_mutex_unlock(&b->values_mutex);
66              
67 4322 100         if ((error = (git_config_entries_get(&entry, entries, key))) < 0) {
68 3498           git_config_entries_free(entries);
69 3498           return error;
70             }
71              
72 824           entry->free = config_snapshot_entry_free;
73 824           entry->payload = entries;
74 824           *out = entry;
75              
76 4322           return 0;
77             }
78              
79 0           static int config_snapshot_set(git_config_backend *cfg, const char *name, const char *value)
80             {
81             GIT_UNUSED(cfg);
82             GIT_UNUSED(name);
83             GIT_UNUSED(value);
84              
85 0           return config_error_readonly();
86             }
87              
88 0           static int config_snapshot_set_multivar(
89             git_config_backend *cfg, const char *name, const char *regexp, const char *value)
90             {
91             GIT_UNUSED(cfg);
92             GIT_UNUSED(name);
93             GIT_UNUSED(regexp);
94             GIT_UNUSED(value);
95              
96 0           return config_error_readonly();
97             }
98              
99 0           static int config_snapshot_delete_multivar(git_config_backend *cfg, const char *name, const char *regexp)
100             {
101             GIT_UNUSED(cfg);
102             GIT_UNUSED(name);
103             GIT_UNUSED(regexp);
104              
105 0           return config_error_readonly();
106             }
107              
108 0           static int config_snapshot_delete(git_config_backend *cfg, const char *name)
109             {
110             GIT_UNUSED(cfg);
111             GIT_UNUSED(name);
112              
113 0           return config_error_readonly();
114             }
115              
116 0           static int config_snapshot_lock(git_config_backend *_cfg)
117             {
118             GIT_UNUSED(_cfg);
119              
120 0           return config_error_readonly();
121             }
122              
123 0           static int config_snapshot_unlock(git_config_backend *_cfg, int success)
124             {
125             GIT_UNUSED(_cfg);
126             GIT_UNUSED(success);
127              
128 0           return config_error_readonly();
129             }
130              
131 1004           static void config_snapshot_free(git_config_backend *_backend)
132             {
133 1004           config_snapshot_backend *backend = GIT_CONTAINER_OF(_backend, config_snapshot_backend, parent);
134              
135 1004 50         if (backend == NULL)
136 0           return;
137              
138 1004           git_config_entries_free(backend->entries);
139             git_mutex_free(&backend->values_mutex);
140 1004           git__free(backend);
141             }
142              
143 1004           static int config_snapshot_open(git_config_backend *cfg, git_config_level_t level, const git_repository *repo)
144             {
145 1004           config_snapshot_backend *b = GIT_CONTAINER_OF(cfg, config_snapshot_backend, parent);
146 1004           git_config_entries *entries = NULL;
147 1004           git_config_iterator *it = NULL;
148             git_config_entry *entry;
149             int error;
150              
151             /* We're just copying data, don't care about the level or repo*/
152             GIT_UNUSED(level);
153             GIT_UNUSED(repo);
154              
155 1004 50         if ((error = git_config_entries_new(&entries)) < 0 ||
    50          
156 1004           (error = b->source->iterator(&it, b->source)) < 0)
157             goto out;
158              
159 7909 100         while ((error = git_config_next(&entry, it)) == 0)
160 6905 50         if ((error = git_config_entries_dup_entry(entries, entry)) < 0)
161 0           goto out;
162              
163 1004 50         if (error < 0) {
164 1004 50         if (error != GIT_ITEROVER)
165 0           goto out;
166 1004           error = 0;
167             }
168              
169 1004           b->entries = entries;
170              
171             out:
172 1004           git_config_iterator_free(it);
173 1004 50         if (error)
174 0           git_config_entries_free(entries);
175 1004           return error;
176             }
177              
178 1004           int git_config_backend_snapshot(git_config_backend **out, git_config_backend *source)
179             {
180             config_snapshot_backend *backend;
181              
182 1004           backend = git__calloc(1, sizeof(config_snapshot_backend));
183 1004 50         GIT_ERROR_CHECK_ALLOC(backend);
184              
185 1004           backend->parent.version = GIT_CONFIG_BACKEND_VERSION;
186 1004           git_mutex_init(&backend->values_mutex);
187              
188 1004           backend->source = source;
189              
190 1004           backend->parent.readonly = 1;
191 1004           backend->parent.version = GIT_CONFIG_BACKEND_VERSION;
192 1004           backend->parent.open = config_snapshot_open;
193 1004           backend->parent.get = config_snapshot_get;
194 1004           backend->parent.set = config_snapshot_set;
195 1004           backend->parent.set_multivar = config_snapshot_set_multivar;
196 1004           backend->parent.snapshot = git_config_backend_snapshot;
197 1004           backend->parent.del = config_snapshot_delete;
198 1004           backend->parent.del_multivar = config_snapshot_delete_multivar;
199 1004           backend->parent.iterator = config_snapshot_iterator;
200 1004           backend->parent.lock = config_snapshot_lock;
201 1004           backend->parent.unlock = config_snapshot_unlock;
202 1004           backend->parent.free = config_snapshot_free;
203              
204 1004           *out = &backend->parent;
205              
206 1004           return 0;
207             }