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