]>
Commit | Line | Data |
---|---|---|
ac3d33df JK |
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_backend.h" | |
11 | #include "config_parse.h" | |
12 | #include "config_entries.h" | |
13 | ||
14 | typedef struct { | |
15 | git_config_backend parent; | |
16 | git_config_entries *entries; | |
17 | git_buf cfg; | |
18 | } config_memory_backend; | |
19 | ||
20 | typedef struct { | |
21 | git_config_entries *entries; | |
22 | git_config_level_t level; | |
23 | } config_memory_parse_data; | |
24 | ||
25 | static int config_error_readonly(void) | |
26 | { | |
27 | git_error_set(GIT_ERROR_CONFIG, "this backend is read-only"); | |
28 | return -1; | |
29 | } | |
30 | ||
31 | static int read_variable_cb( | |
32 | git_config_parser *reader, | |
33 | const char *current_section, | |
34 | const char *var_name, | |
35 | const char *var_value, | |
36 | const char *line, | |
37 | size_t line_len, | |
38 | void *payload) | |
39 | { | |
40 | config_memory_parse_data *parse_data = (config_memory_parse_data *) payload; | |
41 | git_buf buf = GIT_BUF_INIT; | |
42 | git_config_entry *entry; | |
43 | const char *c; | |
44 | int result; | |
45 | ||
46 | GIT_UNUSED(reader); | |
47 | GIT_UNUSED(line); | |
48 | GIT_UNUSED(line_len); | |
49 | ||
50 | if (current_section) { | |
51 | /* TODO: Once warnings land, we should likely warn | |
52 | * here. Git appears to warn in most cases if it sees | |
53 | * un-namespaced config options. | |
54 | */ | |
55 | git_buf_puts(&buf, current_section); | |
56 | git_buf_putc(&buf, '.'); | |
57 | } | |
58 | ||
59 | for (c = var_name; *c; c++) | |
60 | git_buf_putc(&buf, git__tolower(*c)); | |
61 | ||
62 | if (git_buf_oom(&buf)) | |
63 | return -1; | |
64 | ||
65 | entry = git__calloc(1, sizeof(git_config_entry)); | |
66 | GIT_ERROR_CHECK_ALLOC(entry); | |
67 | entry->name = git_buf_detach(&buf); | |
68 | entry->value = var_value ? git__strdup(var_value) : NULL; | |
69 | entry->level = parse_data->level; | |
70 | entry->include_depth = 0; | |
71 | ||
72 | if ((result = git_config_entries_append(parse_data->entries, entry)) < 0) | |
73 | return result; | |
74 | ||
75 | return result; | |
76 | } | |
77 | ||
78 | static int config_memory_open(git_config_backend *backend, git_config_level_t level, const git_repository *repo) | |
79 | { | |
80 | config_memory_backend *memory_backend = (config_memory_backend *) backend; | |
22a2d3d5 | 81 | git_config_parser parser = GIT_PARSE_CTX_INIT; |
ac3d33df | 82 | config_memory_parse_data parse_data; |
22a2d3d5 | 83 | int error; |
ac3d33df JK |
84 | |
85 | GIT_UNUSED(repo); | |
86 | ||
22a2d3d5 UG |
87 | if ((error = git_config_parser_init(&parser, "in-memory", memory_backend->cfg.ptr, |
88 | memory_backend->cfg.size)) < 0) | |
89 | goto out; | |
ac3d33df JK |
90 | parse_data.entries = memory_backend->entries; |
91 | parse_data.level = level; | |
92 | ||
22a2d3d5 UG |
93 | if ((error = git_config_parse(&parser, NULL, read_variable_cb, NULL, NULL, &parse_data)) < 0) |
94 | goto out; | |
95 | ||
96 | out: | |
97 | git_config_parser_dispose(&parser); | |
98 | return error; | |
ac3d33df JK |
99 | } |
100 | ||
101 | static int config_memory_get(git_config_backend *backend, const char *key, git_config_entry **out) | |
102 | { | |
103 | config_memory_backend *memory_backend = (config_memory_backend *) backend; | |
104 | return git_config_entries_get(out, memory_backend->entries, key); | |
105 | } | |
106 | ||
107 | static int config_memory_iterator( | |
108 | git_config_iterator **iter, | |
109 | git_config_backend *backend) | |
110 | { | |
111 | config_memory_backend *memory_backend = (config_memory_backend *) backend; | |
112 | git_config_entries *entries; | |
113 | int error; | |
114 | ||
115 | if ((error = git_config_entries_dup(&entries, memory_backend->entries)) < 0) | |
116 | goto out; | |
117 | ||
118 | if ((error = git_config_entries_iterator_new(iter, entries)) < 0) | |
119 | goto out; | |
120 | ||
121 | out: | |
122 | /* Let iterator delete duplicated entries when it's done */ | |
123 | git_config_entries_free(entries); | |
124 | return error; | |
125 | } | |
126 | ||
127 | static int config_memory_set(git_config_backend *backend, const char *name, const char *value) | |
128 | { | |
129 | GIT_UNUSED(backend); | |
130 | GIT_UNUSED(name); | |
131 | GIT_UNUSED(value); | |
132 | return config_error_readonly(); | |
133 | } | |
134 | ||
135 | static int config_memory_set_multivar( | |
136 | git_config_backend *backend, const char *name, const char *regexp, const char *value) | |
137 | { | |
138 | GIT_UNUSED(backend); | |
139 | GIT_UNUSED(name); | |
140 | GIT_UNUSED(regexp); | |
141 | GIT_UNUSED(value); | |
142 | return config_error_readonly(); | |
143 | } | |
144 | ||
145 | static int config_memory_delete(git_config_backend *backend, const char *name) | |
146 | { | |
147 | GIT_UNUSED(backend); | |
148 | GIT_UNUSED(name); | |
149 | return config_error_readonly(); | |
150 | } | |
151 | ||
152 | static int config_memory_delete_multivar(git_config_backend *backend, const char *name, const char *regexp) | |
153 | { | |
154 | GIT_UNUSED(backend); | |
155 | GIT_UNUSED(name); | |
156 | GIT_UNUSED(regexp); | |
157 | return config_error_readonly(); | |
158 | } | |
159 | ||
160 | static int config_memory_lock(git_config_backend *backend) | |
161 | { | |
162 | GIT_UNUSED(backend); | |
163 | return config_error_readonly(); | |
164 | } | |
165 | ||
166 | static int config_memory_unlock(git_config_backend *backend, int success) | |
167 | { | |
168 | GIT_UNUSED(backend); | |
169 | GIT_UNUSED(success); | |
170 | return config_error_readonly(); | |
171 | } | |
172 | ||
ac3d33df JK |
173 | static void config_memory_free(git_config_backend *_backend) |
174 | { | |
175 | config_memory_backend *backend = (config_memory_backend *)_backend; | |
176 | ||
177 | if (backend == NULL) | |
178 | return; | |
179 | ||
180 | git_config_entries_free(backend->entries); | |
181 | git_buf_dispose(&backend->cfg); | |
182 | git__free(backend); | |
183 | } | |
184 | ||
185 | int git_config_backend_from_string(git_config_backend **out, const char *cfg, size_t len) | |
186 | { | |
187 | config_memory_backend *backend; | |
188 | ||
189 | backend = git__calloc(1, sizeof(config_memory_backend)); | |
190 | GIT_ERROR_CHECK_ALLOC(backend); | |
191 | ||
192 | if (git_config_entries_new(&backend->entries) < 0) { | |
193 | git__free(backend); | |
194 | return -1; | |
195 | } | |
196 | ||
197 | if (git_buf_set(&backend->cfg, cfg, len) < 0) { | |
198 | git_config_entries_free(backend->entries); | |
199 | git__free(backend); | |
200 | return -1; | |
201 | } | |
202 | ||
203 | backend->parent.version = GIT_CONFIG_BACKEND_VERSION; | |
204 | backend->parent.readonly = 1; | |
205 | backend->parent.open = config_memory_open; | |
206 | backend->parent.get = config_memory_get; | |
207 | backend->parent.set = config_memory_set; | |
208 | backend->parent.set_multivar = config_memory_set_multivar; | |
209 | backend->parent.del = config_memory_delete; | |
210 | backend->parent.del_multivar = config_memory_delete_multivar; | |
211 | backend->parent.iterator = config_memory_iterator; | |
212 | backend->parent.lock = config_memory_lock; | |
213 | backend->parent.unlock = config_memory_unlock; | |
22a2d3d5 | 214 | backend->parent.snapshot = git_config_backend_snapshot; |
ac3d33df JK |
215 | backend->parent.free = config_memory_free; |
216 | ||
217 | *out = (git_config_backend *)backend; | |
218 | ||
219 | return 0; | |
220 | } |