Commit c0335005 by Carlos Martín Nieto

Move config to a backend structure

Configuration options can come from different sources. Currently,
there is only support for reading them from a flat file, but it might
make sense to read it from a database at some point.

Move the parsing code into src/config_file.c and create an include
file include/git2/config_backend.h to allow for other backends to be
developed.

Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
parent ca8d2dfc
......@@ -38,12 +38,22 @@
GIT_BEGIN_DECL
/**
* Allocate a new configuration
*/
GIT_EXTERN(int) git_config_new(git_config **out);
/**
* Open a configuration file
*
* @param cfg_out pointer to the configuration data
* @param path where to load the confiration from
*/
GIT_EXTERN(int) git_config_open(git_config **cfg_out, const char *path);
GIT_EXTERN(int) git_config_open_bare(git_config **cfg_out, const char *path);
/**
*
*/
GIT_EXTERN(int) git_config_add_backend(git_config *cfg, git_config_backend *backend, int priority);
/**
* Free the configuration and its associated memory
......
/*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2,
* as published by the Free Software Foundation.
*
* In addition to the permissions in the GNU General Public License,
* the authors give you unlimited permission to link the compiled
* version of this file into combinations with other programs,
* and to distribute those combinations without any restriction
* coming from the use of this file. (The General Public License
* restrictions do apply in other respects; for example, they cover
* modification of the file, and distribution when not linked into
* a combined executable.)
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDE_git_config_backend_h__
#define INCLUDE_git_config_backend_h__
#include "common.h"
#include "types.h"
#include "config.h"
GIT_BEGIN_DECL
struct git_config;
struct git_config_backend {
struct git_config *cfg;
/* Open means open the file/database and parse if necessary */
int (*open)(struct git_config_backend *);
int (* get)(struct git_config_backend *, const char *key, const char **value);
int (* set)(struct git_config_backend *, const char *key, const char *value);
int (*foreach)(struct git_config_backend *, int (*fn)(const char *, void *), void *data);
void (*free)(struct git_config_backend *);
};
/**
* Create a file-backed configuration backend
*
* @param out the new backend
* @path where the config file is located
*/
GIT_EXTERN(int) git_config_backend_file(struct git_config_backend **out, const char *path);
GIT_END_DECL
#endif
......@@ -133,6 +133,9 @@ typedef struct git_index git_index;
/** Memory representation of a config file */
typedef struct git_config git_config;
/** A specific implementation of a config backend */
typedef struct git_config_backend git_config_backend;
/** Memory representation of a config variable */
typedef struct git_cvar git_cvar;
......
#ifndef INCLUDE_config_h__
#define INCLUDE_config_h__
#include "git2.h"
#include "git2/config.h"
typedef struct {
git_cvar *head;
git_cvar *tail;
} git_cvar_list;
#include "vector.h"
struct git_config {
git_cvar_list var_list;
struct {
gitfo_buf buffer;
char *read_ptr;
int line_number;
int eof;
} reader;
char *file_path;
};
struct git_cvar {
git_cvar *next;
char *section;
char *name;
char *value;
git_vector backends;
};
#define CVAR_LIST_HEAD(list) ((list)->head)
#define CVAR_LIST_TAIL(list) ((list)->tail)
#define CVAR_LIST_NEXT(var) ((var)->next)
#define CVAR_LIST_EMPTY(list) ((list)->head == NULL)
#define CVAR_LIST_APPEND(list, var) do {\
if (CVAR_LIST_EMPTY(list)) {\
CVAR_LIST_HEAD(list) = CVAR_LIST_TAIL(list) = var;\
} else {\
CVAR_LIST_NEXT(CVAR_LIST_TAIL(list)) = var;\
CVAR_LIST_TAIL(list) = var;\
}\
} while(0)
#define CVAR_LIST_REMOVE_HEAD(list) do {\
CVAR_LIST_HEAD(list) = CVAR_LIST_NEXT(CVAR_LIST_HEAD(list));\
} while(0)
#define CVAR_LIST_REMOVE_AFTER(var) do {\
CVAR_LIST_NEXT(var) = CVAR_LIST_NEXT(CVAR_LIST_NEXT(var));\
} while(0)
#define CVAR_LIST_FOREACH(list, iter)\
for ((iter) = CVAR_LIST_HEAD(list);\
(iter) != NULL;\
(iter) = CVAR_LIST_NEXT(iter))
/*
* Inspired by the FreeBSD functions
*/
#define CVAR_LIST_FOREACH_SAFE(start, iter, tmp)\
for ((iter) = CVAR_LIST_HEAD(vars);\
(iter) && (((tmp) = CVAR_LIST_NEXT(iter) || 1));\
(iter) = (tmp))
void git__strtolower(char *str);
void git__strntolower(char *str, int len);
......
......@@ -36,7 +36,7 @@ BEGIN_TEST(config0, "read a simple configuration")
git_config *cfg;
int i;
must_pass(git_config_open(&cfg, CONFIG_BASE "/config0"));
must_pass(git_config_open_bare(&cfg, CONFIG_BASE "/config0"));
must_pass(git_config_get_int(cfg, "core.repositoryformatversion", &i));
must_be_true(i == 0);
must_pass(git_config_get_bool(cfg, "core.filemode", &i));
......@@ -58,7 +58,7 @@ BEGIN_TEST(config1, "case sensitivity")
int i;
const char *str;
must_pass(git_config_open(&cfg, CONFIG_BASE "/config1"));
must_pass(git_config_open_bare(&cfg, CONFIG_BASE "/config1"));
must_pass(git_config_get_string(cfg, "this.that.other", &str));
must_be_true(!strcmp(str, "true"));
......@@ -84,7 +84,7 @@ BEGIN_TEST(config2, "parse a multiline value")
git_config *cfg;
const char *str;
must_pass(git_config_open(&cfg, CONFIG_BASE "/config2"));
must_pass(git_config_open_bare(&cfg, CONFIG_BASE "/config2"));
must_pass(git_config_get_string(cfg, "this.That.and", &str));
must_be_true(!strcmp(str, "one one one two two three three"));
......@@ -99,7 +99,7 @@ BEGIN_TEST(config3, "parse a [section.subsection] header")
git_config *cfg;
const char *str;
must_pass(git_config_open(&cfg, CONFIG_BASE "/config3"));
must_pass(git_config_open_bare(&cfg, CONFIG_BASE "/config3"));
must_pass(git_config_get_string(cfg, "section.subsection.var", &str));
must_be_true(!strcmp(str, "hello"));
......@@ -117,7 +117,7 @@ BEGIN_TEST(config4, "a variable name on its own is valid")
const char *str;
int i;
must_pass(git_config_open(&cfg, CONFIG_BASE "/config4"));
must_pass(git_config_open_bare(&cfg, CONFIG_BASE "/config4"));
must_pass(git_config_get_string(cfg, "some.section.variable", &str));
must_be_true(str == NULL);
......@@ -134,7 +134,7 @@ BEGIN_TEST(config5, "test number suffixes")
const char *str;
long int i;
must_pass(git_config_open(&cfg, CONFIG_BASE "/config5"));
must_pass(git_config_open_bare(&cfg, CONFIG_BASE "/config5"));
must_pass(git_config_get_long(cfg, "number.simple", &i));
must_be_true(i == 1);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment