]> git.proxmox.com Git - libgit2.git/blame - src/libgit2/config_snapshot.c
Merge https://salsa.debian.org/debian/libgit2 into proxmox/bullseye
[libgit2.git] / src / libgit2 / config_snapshot.c
CommitLineData
22a2d3d5
UG
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
13typedef 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
20static int config_error_readonly(void)
21{
22 git_error_set(GIT_ERROR_CONFIG, "this backend is read-only");
23 return -1;
24}
25
26static int config_snapshot_iterator(
27 git_config_iterator **iter,
28 struct git_config_backend *backend)
29{
30 config_snapshot_backend *b = GIT_CONTAINER_OF(backend, config_snapshot_backend, parent);
31 git_config_entries *entries = NULL;
32 int error;
33
34 if ((error = git_config_entries_dup(&entries, b->entries)) < 0 ||
35 (error = git_config_entries_iterator_new(iter, entries)) < 0)
36 goto out;
37
38out:
39 /* Let iterator delete duplicated entries when it's done */
40 git_config_entries_free(entries);
41 return error;
42}
43
44/* release the map containing the entry as an equivalent to freeing it */
45static void config_snapshot_entry_free(git_config_entry *entry)
46{
47 git_config_entries *entries = (git_config_entries *) entry->payload;
48 git_config_entries_free(entries);
49}
50
51static int config_snapshot_get(git_config_backend *cfg, const char *key, git_config_entry **out)
52{
53 config_snapshot_backend *b = GIT_CONTAINER_OF(cfg, config_snapshot_backend, parent);
54 git_config_entries *entries = NULL;
55 git_config_entry *entry;
56 int error = 0;
57
58 if (git_mutex_lock(&b->values_mutex) < 0) {
59 git_error_set(GIT_ERROR_OS, "failed to lock config backend");
60 return -1;
61 }
62
63 entries = b->entries;
64 git_config_entries_incref(entries);
65 git_mutex_unlock(&b->values_mutex);
66
67 if ((error = (git_config_entries_get(&entry, entries, key))) < 0) {
68 git_config_entries_free(entries);
69 return error;
70 }
71
72 entry->free = config_snapshot_entry_free;
73 entry->payload = entries;
74 *out = entry;
75
76 return 0;
77}
78
79static 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 return config_error_readonly();
86}
87
88static 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 return config_error_readonly();
97}
98
99static 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 return config_error_readonly();
106}
107
108static int config_snapshot_delete(git_config_backend *cfg, const char *name)
109{
110 GIT_UNUSED(cfg);
111 GIT_UNUSED(name);
112
113 return config_error_readonly();
114}
115
116static int config_snapshot_lock(git_config_backend *_cfg)
117{
118 GIT_UNUSED(_cfg);
119
120 return config_error_readonly();
121}
122
123static int config_snapshot_unlock(git_config_backend *_cfg, int success)
124{
125 GIT_UNUSED(_cfg);
126 GIT_UNUSED(success);
127
128 return config_error_readonly();
129}
130
131static void config_snapshot_free(git_config_backend *_backend)
132{
133 config_snapshot_backend *backend = GIT_CONTAINER_OF(_backend, config_snapshot_backend, parent);
134
135 if (backend == NULL)
136 return;
137
138 git_config_entries_free(backend->entries);
139 git_mutex_free(&backend->values_mutex);
140 git__free(backend);
141}
142
143static int config_snapshot_open(git_config_backend *cfg, git_config_level_t level, const git_repository *repo)
144{
145 config_snapshot_backend *b = GIT_CONTAINER_OF(cfg, config_snapshot_backend, parent);
146 git_config_entries *entries = NULL;
147 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 if ((error = git_config_entries_new(&entries)) < 0 ||
156 (error = b->source->iterator(&it, b->source)) < 0)
157 goto out;
158
159 while ((error = git_config_next(&entry, it)) == 0)
160 if ((error = git_config_entries_dup_entry(entries, entry)) < 0)
161 goto out;
162
163 if (error < 0) {
164 if (error != GIT_ITEROVER)
165 goto out;
166 error = 0;
167 }
168
169 b->entries = entries;
170
171out:
172 git_config_iterator_free(it);
173 if (error)
174 git_config_entries_free(entries);
175 return error;
176}
177
178int git_config_backend_snapshot(git_config_backend **out, git_config_backend *source)
179{
180 config_snapshot_backend *backend;
181
182 backend = git__calloc(1, sizeof(config_snapshot_backend));
183 GIT_ERROR_CHECK_ALLOC(backend);
184
185 backend->parent.version = GIT_CONFIG_BACKEND_VERSION;
186 git_mutex_init(&backend->values_mutex);
187
188 backend->source = source;
189
190 backend->parent.readonly = 1;
191 backend->parent.version = GIT_CONFIG_BACKEND_VERSION;
192 backend->parent.open = config_snapshot_open;
193 backend->parent.get = config_snapshot_get;
194 backend->parent.set = config_snapshot_set;
195 backend->parent.set_multivar = config_snapshot_set_multivar;
196 backend->parent.snapshot = git_config_backend_snapshot;
197 backend->parent.del = config_snapshot_delete;
198 backend->parent.del_multivar = config_snapshot_delete_multivar;
199 backend->parent.iterator = config_snapshot_iterator;
200 backend->parent.lock = config_snapshot_lock;
201 backend->parent.unlock = config_snapshot_unlock;
202 backend->parent.free = config_snapshot_free;
203
204 *out = &backend->parent;
205
206 return 0;
207}