Skip to content

Commit 2bff84b

Browse files
committed
config_file: separate out read-only backend
To further distinguish the file writeable and readonly backends, separate the readonly backend into its own "config_snapshot.c" implementation. The snapshot backend can be generically used to snapshot any type of backend.
1 parent f0b1006 commit 2bff84b

File tree

3 files changed

+230
-200
lines changed

3 files changed

+230
-200
lines changed

src/config_backend.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@
2525
*/
2626
extern int git_config_backend_from_file(git_config_backend **out, const char *path);
2727

28+
/**
29+
* Create a readonly configuration file backend from another backend
30+
*
31+
* This copies the complete contents of the source backend to the
32+
* new backend. The new backend will be completely read-only and
33+
* cannot be modified.
34+
*
35+
* @param out the new snapshotted backend
36+
* @param source the backend to copy
37+
*/
38+
extern int git_config_backend_snapshot(git_config_backend **out, git_config_backend *source);
39+
2840
/**
2941
* Create an in-memory configuration file backend
3042
*

src/config_file.c

Lines changed: 13 additions & 200 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,19 @@
77

88
#include "config.h"
99

10-
#include "filebuf.h"
11-
#include "sysdir.h"
12-
#include "buffer.h"
13-
#include "buf_text.h"
1410
#include "git2/config.h"
1511
#include "git2/sys/config.h"
1612
#include "git2/types.h"
17-
#include "strmap.h"
13+
1814
#include "array.h"
19-
#include "config_parse.h"
15+
#include "buf_text.h"
16+
#include "buffer.h"
17+
#include "config_backend.h"
2018
#include "config_entries.h"
19+
#include "config_parse.h"
20+
#include "filebuf.h"
21+
#include "strmap.h"
22+
#include "sysdir.h"
2123
#include "wildmatch.h"
2224

2325
#include <ctype.h>
@@ -49,13 +51,6 @@ typedef struct {
4951
diskfile file;
5052
} diskfile_backend;
5153

52-
typedef struct {
53-
git_config_backend parent;
54-
git_mutex values_mutex;
55-
git_config_entries *entries;
56-
git_config_backend *source;
57-
} diskfile_readonly_backend;
58-
5954
typedef struct {
6055
const git_repository *repo;
6156
diskfile *file;
@@ -69,14 +64,6 @@ static int config_read_buffer(git_config_entries *entries, const git_repository
6964
static int config_write(diskfile_backend *cfg, const char *orig_key, const char *key, const p_regex_t *preg, const char *value);
7065
static char *escape_value(const char *ptr);
7166

72-
static int config_snapshot(git_config_backend **out, git_config_backend *in);
73-
74-
static int config_error_readonly(void)
75-
{
76-
git_error_set(GIT_ERROR_CONFIG, "this backend is read-only");
77-
return -1;
78-
}
79-
8067
/**
8168
* Take the current values map from the backend and increase its
8269
* refcount. This is its own function to make sure we use the mutex to
@@ -181,8 +168,10 @@ static int config_set_entries(git_config_backend *cfg, git_config_entries *entri
181168
int error;
182169
uint32_t i;
183170

184-
if (b->parent.readonly)
185-
return config_error_readonly();
171+
if (b->parent.readonly) {
172+
git_error_set(GIT_ERROR_CONFIG, "this backend is read-only");
173+
return -1;
174+
}
186175

187176
git_array_foreach(b->file.includes, i, include)
188177
config_file_clear(include);
@@ -280,25 +269,6 @@ static int config_iterator_new(
280269
return error;
281270
}
282271

283-
static int config_iterator_new_readonly(
284-
git_config_iterator **iter,
285-
struct git_config_backend *backend)
286-
{
287-
diskfile_readonly_backend *b = GIT_CONTAINER_OF(backend, diskfile_readonly_backend, parent);
288-
git_config_entries *entries = NULL;
289-
int error;
290-
291-
if ((error = git_config_entries_dup(&entries, b->entries)) < 0 ||
292-
(error = git_config_entries_iterator_new(iter, entries)) < 0)
293-
goto out;
294-
295-
out:
296-
/* Let iterator delete duplicated entries when it's done */
297-
git_config_entries_free(entries);
298-
return error;
299-
}
300-
301-
302272
static int config_set(git_config_backend *cfg, const char *name, const char *value)
303273
{
304274
diskfile_backend *b = GIT_CONTAINER_OF(cfg, diskfile_backend, parent);
@@ -376,34 +346,6 @@ static int config_get(git_config_backend *cfg, const char *key, git_config_entry
376346
return 0;
377347
}
378348

379-
static int config_get_readonly(git_config_backend *cfg, const char *key, git_config_entry **out)
380-
{
381-
diskfile_readonly_backend *b = GIT_CONTAINER_OF(cfg, diskfile_readonly_backend, parent);
382-
git_config_entries *entries = NULL;
383-
git_config_entry *entry;
384-
int error = 0;
385-
386-
if (git_mutex_lock(&b->values_mutex) < 0) {
387-
git_error_set(GIT_ERROR_OS, "failed to lock config backend");
388-
return -1;
389-
}
390-
391-
entries = b->entries;
392-
git_config_entries_incref(entries);
393-
git_mutex_unlock(&b->values_mutex);
394-
395-
if ((error = (git_config_entries_get(&entry, entries, key))) < 0) {
396-
git_config_entries_free(entries);
397-
return error;
398-
}
399-
400-
entry->free = free_diskfile_entry;
401-
entry->payload = entries;
402-
*out = entry;
403-
404-
return 0;
405-
}
406-
407349
static int config_set_multivar(
408350
git_config_backend *cfg, const char *name, const char *regexp, const char *value)
409351
{
@@ -561,7 +503,7 @@ int git_config_backend_from_file(git_config_backend **out, const char *path)
561503
backend->parent.del = config_delete;
562504
backend->parent.del_multivar = config_delete_multivar;
563505
backend->parent.iterator = config_iterator_new;
564-
backend->parent.snapshot = config_snapshot;
506+
backend->parent.snapshot = git_config_backend_snapshot;
565507
backend->parent.lock = config_lock;
566508
backend->parent.unlock = config_unlock;
567509
backend->parent.free = backend_free;
@@ -571,135 +513,6 @@ int git_config_backend_from_file(git_config_backend **out, const char *path)
571513
return 0;
572514
}
573515

574-
static int config_set_readonly(git_config_backend *cfg, const char *name, const char *value)
575-
{
576-
GIT_UNUSED(cfg);
577-
GIT_UNUSED(name);
578-
GIT_UNUSED(value);
579-
580-
return config_error_readonly();
581-
}
582-
583-
static int config_set_multivar_readonly(
584-
git_config_backend *cfg, const char *name, const char *regexp, const char *value)
585-
{
586-
GIT_UNUSED(cfg);
587-
GIT_UNUSED(name);
588-
GIT_UNUSED(regexp);
589-
GIT_UNUSED(value);
590-
591-
return config_error_readonly();
592-
}
593-
594-
static int config_delete_multivar_readonly(git_config_backend *cfg, const char *name, const char *regexp)
595-
{
596-
GIT_UNUSED(cfg);
597-
GIT_UNUSED(name);
598-
GIT_UNUSED(regexp);
599-
600-
return config_error_readonly();
601-
}
602-
603-
static int config_delete_readonly(git_config_backend *cfg, const char *name)
604-
{
605-
GIT_UNUSED(cfg);
606-
GIT_UNUSED(name);
607-
608-
return config_error_readonly();
609-
}
610-
611-
static int config_lock_readonly(git_config_backend *_cfg)
612-
{
613-
GIT_UNUSED(_cfg);
614-
615-
return config_error_readonly();
616-
}
617-
618-
static int config_unlock_readonly(git_config_backend *_cfg, int success)
619-
{
620-
GIT_UNUSED(_cfg);
621-
GIT_UNUSED(success);
622-
623-
return config_error_readonly();
624-
}
625-
626-
static void backend_readonly_free(git_config_backend *_backend)
627-
{
628-
diskfile_readonly_backend *backend = GIT_CONTAINER_OF(_backend, diskfile_readonly_backend, parent);
629-
630-
if (backend == NULL)
631-
return;
632-
633-
git_config_entries_free(backend->entries);
634-
git_mutex_free(&backend->values_mutex);
635-
git__free(backend);
636-
}
637-
638-
static int config_readonly_open(git_config_backend *cfg, git_config_level_t level, const git_repository *repo)
639-
{
640-
diskfile_readonly_backend *b = GIT_CONTAINER_OF(cfg, diskfile_readonly_backend, parent);
641-
git_config_entries *entries = NULL;
642-
git_config_iterator *it = NULL;
643-
git_config_entry *entry;
644-
int error;
645-
646-
/* We're just copying data, don't care about the level or repo*/
647-
GIT_UNUSED(level);
648-
GIT_UNUSED(repo);
649-
650-
if ((error = git_config_entries_new(&entries)) < 0 ||
651-
(error = b->source->iterator(&it, b->source)) < 0)
652-
goto out;
653-
654-
while ((error = git_config_next(&entry, it)) == 0)
655-
if ((error = git_config_entries_dup_entry(entries, entry)) < 0)
656-
goto out;
657-
658-
if (error < 0) {
659-
if (error != GIT_ITEROVER)
660-
goto out;
661-
error = 0;
662-
}
663-
664-
b->entries = entries;
665-
666-
out:
667-
git_config_iterator_free(it);
668-
if (error)
669-
git_config_entries_free(entries);
670-
return error;
671-
}
672-
673-
static int config_snapshot(git_config_backend **out, git_config_backend *source)
674-
{
675-
diskfile_readonly_backend *backend;
676-
677-
backend = git__calloc(1, sizeof(diskfile_readonly_backend));
678-
GIT_ERROR_CHECK_ALLOC(backend);
679-
680-
backend->parent.version = GIT_CONFIG_BACKEND_VERSION;
681-
git_mutex_init(&backend->values_mutex);
682-
683-
backend->source = source;
684-
685-
backend->parent.readonly = 1;
686-
backend->parent.version = GIT_CONFIG_BACKEND_VERSION;
687-
backend->parent.open = config_readonly_open;
688-
backend->parent.get = config_get_readonly;
689-
backend->parent.set = config_set_readonly;
690-
backend->parent.set_multivar = config_set_multivar_readonly;
691-
backend->parent.del = config_delete_readonly;
692-
backend->parent.del_multivar = config_delete_multivar_readonly;
693-
backend->parent.iterator = config_iterator_new_readonly;
694-
backend->parent.lock = config_lock_readonly;
695-
backend->parent.unlock = config_unlock_readonly;
696-
backend->parent.free = backend_readonly_free;
697-
698-
*out = &backend->parent;
699-
700-
return 0;
701-
}
702-
703516
static int included_path(git_buf *out, const char *dir, const char *path)
704517
{
705518
/* From the user's home */

0 commit comments

Comments
 (0)