Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoryorah <yoram.harmelin@gmail.com>2012-09-10 14:11:02 +0400
committeryorah <yoram.harmelin@gmail.com>2012-10-23 14:48:38 +0400
commita1abe66aca3625eec1cabb2e93cf8df0be1b63f0 (patch)
tree17de8c31afbdb3398a391e1fcede5010394dec85 /src
parentf8ede94808348ac12db1d5dd91e5f66624d8b40d (diff)
Add config level support in the config API
Added `struct git_config_entry`: a git_config_entry contains the key, the value, and the config file level from which a config element was found. Added `git_config_open_level`: build a single-level focused config object from a multi-level one. We are now storing `git_config_entry`s in the khash of the config_file
Diffstat (limited to 'src')
-rw-r--r--src/config.c502
-rw-r--r--src/config.h5
-rw-r--r--src/config_file.c94
-rw-r--r--src/config_file.h10
-rw-r--r--src/remote.c4
-rw-r--r--src/repository.c8
-rw-r--r--src/submodule.c11
7 files changed, 397 insertions, 237 deletions
diff --git a/src/config.c b/src/config.c
index b89c16b1c..f9bd205af 100644
--- a/src/config.c
+++ b/src/config.c
@@ -17,21 +17,29 @@
#include <ctype.h>
typedef struct {
+ git_refcount rc;
+
git_config_file *file;
- int priority;
+ unsigned int level;
} file_internal;
+static void file_internal_free(file_internal *internal)
+{
+ git_config_file *file;
+
+ file = internal->file;
+ file->free(file);
+ git__free(internal);
+}
+
static void config_free(git_config *cfg)
{
unsigned int i;
- git_config_file *file;
file_internal *internal;
for(i = 0; i < cfg->files.length; ++i){
internal = git_vector_get(&cfg->files, i);
- file = internal->file;
- file->free(file);
- git__free(internal);
+ GIT_REFCOUNT_DEC(internal, file_internal_free);
}
git_vector_free(&cfg->files);
@@ -51,7 +59,7 @@ static int config_backend_cmp(const void *a, const void *b)
const file_internal *bk_a = (const file_internal *)(a);
const file_internal *bk_b = (const file_internal *)(b);
- return bk_b->priority - bk_a->priority;
+ return bk_b->level - bk_a->level;
}
int git_config_new(git_config **out)
@@ -73,20 +81,25 @@ int git_config_new(git_config **out)
return 0;
}
-int git_config_add_file_ondisk(git_config *cfg, const char *path, int priority)
+int git_config_add_file_ondisk(
+ git_config *cfg,
+ const char *path,
+ unsigned int level,
+ int force)
{
git_config_file *file = NULL;
+ int res;
if (git_config_file__ondisk(&file, path) < 0)
return -1;
- if (git_config_add_file(cfg, file, priority) < 0) {
+ if ((res = git_config_add_file(cfg, file, level, force)) < 0) {
/*
* free manually; the file is not owned by the config
* instance yet and will not be freed on cleanup
*/
file->free(file);
- return -1;
+ return res;
}
return 0;
@@ -97,7 +110,7 @@ int git_config_open_ondisk(git_config **cfg, const char *path)
if (git_config_new(cfg) < 0)
return -1;
- if (git_config_add_file_ondisk(*cfg, path, 1) < 0) {
+ if (git_config_add_file_ondisk(*cfg, path, GIT_CONFIG_LEVEL_LOCAL, 0) < 0) {
git_config_free(*cfg);
return -1;
}
@@ -105,30 +118,152 @@ int git_config_open_ondisk(git_config **cfg, const char *path)
return 0;
}
-int git_config_add_file(git_config *cfg, git_config_file *file, int priority)
+static int find_internal_file_by_level(
+ file_internal **internal_out,
+ git_config *cfg,
+ int level)
+{
+ int pos = -1;
+ file_internal *internal;
+ unsigned int i;
+
+ assert(cfg->files.length);
+
+ /* when passing GIT_CONFIG_HIGHEST_LEVEL, the idea is to get the config file
+ * which has the highest level. As config files are stored in a vector
+ * sorted by decreasing order of level, getting the file at position 0
+ * will do the job.
+ */
+ if (level == GIT_CONFIG_HIGHEST_LEVEL) {
+ pos = 0;
+ } else {
+ git_vector_foreach(&cfg->files, i, internal) {
+ if (internal->level == (unsigned int)level)
+ pos = i;
+ }
+ }
+
+ if (pos == -1) {
+ giterr_set(GITERR_CONFIG,
+ "No config file exists for the given level '%i'", level);
+ return GIT_ENOTFOUND;
+ }
+
+ *internal_out = git_vector_get(&cfg->files, pos);
+
+ return 0;
+}
+
+static int duplicate_level(void **old_raw, void *new_raw)
+{
+ file_internal **old = (file_internal **)old_raw;
+
+ GIT_UNUSED(new_raw);
+
+ giterr_set(GITERR_CONFIG, "A file with the same level (%i) has already been added to the config", (*old)->level);
+ return GIT_EEXISTS;
+}
+
+static void try_remove_existing_file_internal(
+ git_config *cfg,
+ unsigned int level)
+{
+ int pos = -1;
+ file_internal *internal;
+ unsigned int i;
+
+ git_vector_foreach(&cfg->files, i, internal) {
+ if (internal->level == level)
+ pos = i;
+ }
+
+ if (pos == -1)
+ return;
+
+ internal = git_vector_get(&cfg->files, pos);
+
+ if (git_vector_remove(&cfg->files, pos) < 0)
+ return;
+
+ GIT_REFCOUNT_DEC(internal, file_internal_free);
+}
+
+static int git_config__add_internal(
+ git_config *cfg,
+ file_internal *internal,
+ unsigned int level,
+ int force)
+{
+ int result;
+
+ /* delete existing config file for level if it exists */
+ if (force)
+ try_remove_existing_file_internal(cfg, level);
+
+ if ((result = git_vector_insert_sorted(&cfg->files,
+ internal, &duplicate_level)) < 0)
+ return result;
+
+ git_vector_sort(&cfg->files);
+ internal->file->cfg = cfg;
+
+ GIT_REFCOUNT_INC(internal);
+
+ return 0;
+}
+
+int git_config_open_level(
+ git_config **cfg_out,
+ git_config *cfg_parent,
+ unsigned int level)
+{
+ git_config *cfg;
+ file_internal *internal;
+ int res;
+
+ if ((res = find_internal_file_by_level(&internal, cfg_parent, level)) < 0)
+ return res;
+
+ if ((res = git_config_new(&cfg)) < 0)
+ return res;
+
+ if ((res = git_config__add_internal(cfg, internal, level, true)) < 0) {
+ git_config_free(cfg);
+ return res;
+ }
+
+ *cfg_out = cfg;
+
+ return 0;
+}
+
+int git_config_add_file(
+ git_config *cfg,
+ git_config_file *file,
+ unsigned int level,
+ int force)
{
file_internal *internal;
int result;
assert(cfg && file);
- if ((result = file->open(file)) < 0)
+ if ((result = file->open(file, level)) < 0)
return result;
internal = git__malloc(sizeof(file_internal));
GITERR_CHECK_ALLOC(internal);
+ memset(internal, 0x0, sizeof(file_internal));
+
internal->file = file;
- internal->priority = priority;
+ internal->level = level;
- if (git_vector_insert(&cfg->files, internal) < 0) {
+ if ((result = git_config__add_internal(cfg, internal, level, force)) < 0) {
git__free(internal);
- return -1;
+ return result;
}
- git_vector_sort(&cfg->files);
- internal->file->cfg = cfg;
-
return 0;
}
@@ -137,7 +272,7 @@ int git_config_add_file(git_config *cfg, git_config_file *file, int priority)
*/
int git_config_foreach(
- git_config *cfg, int (*fn)(const char *, const char *, void *), void *data)
+ git_config *cfg, int (*fn)(const git_config_entry *, void *), void *data)
{
return git_config_foreach_match(cfg, NULL, fn, data);
}
@@ -145,7 +280,7 @@ int git_config_foreach(
int git_config_foreach_match(
git_config *cfg,
const char *regexp,
- int (*fn)(const char *, const char *, void *),
+ int (*fn)(const git_config_entry *, void *),
void *data)
{
int ret = 0;
@@ -164,10 +299,8 @@ int git_config_foreach_match(
int git_config_delete(git_config *cfg, const char *name)
{
- file_internal *internal;
git_config_file *file;
-
- assert(cfg->files.length);
+ file_internal *internal;
internal = git_vector_get(&cfg->files, 0);
file = internal->file;
@@ -198,10 +331,8 @@ int git_config_set_bool(git_config *cfg, const char *name, int value)
int git_config_set_string(git_config *cfg, const char *name, const char *value)
{
- file_internal *internal;
git_config_file *file;
-
- assert(cfg->files.length);
+ file_internal *internal;
internal = git_vector_get(&cfg->files, 0);
file = internal->file;
@@ -209,105 +340,9 @@ int git_config_set_string(git_config *cfg, const char *name, const char *value)
return file->set(file, name, value);
}
-static int parse_int64(int64_t *out, const char *value)
-{
- const char *num_end;
- int64_t num;
-
- if (git__strtol64(&num, value, &num_end, 0) < 0)
- return -1;
-
- switch (*num_end) {
- case 'g':
- case 'G':
- num *= 1024;
- /* fallthrough */
-
- case 'm':
- case 'M':
- num *= 1024;
- /* fallthrough */
-
- case 'k':
- case 'K':
- num *= 1024;
-
- /* check that that there are no more characters after the
- * given modifier suffix */
- if (num_end[1] != '\0')
- return -1;
-
- /* fallthrough */
-
- case '\0':
- *out = num;
- return 0;
-
- default:
- return -1;
- }
-}
-
-static int parse_int32(int32_t *out, const char *value)
-{
- int64_t tmp;
- int32_t truncate;
-
- if (parse_int64(&tmp, value) < 0)
- return -1;
-
- truncate = tmp & 0xFFFFFFFF;
- if (truncate != tmp)
- return -1;
-
- *out = truncate;
- return 0;
-}
-
/***********
* Getters
***********/
-int git_config_lookup_map_value(
- git_cvar_map *maps, size_t map_n, const char *value, int *out)
-{
- size_t i;
-
- if (!value)
- return GIT_ENOTFOUND;
-
- for (i = 0; i < map_n; ++i) {
- git_cvar_map *m = maps + i;
-
- switch (m->cvar_type) {
- case GIT_CVAR_FALSE:
- case GIT_CVAR_TRUE: {
- int bool_val;
-
- if (git__parse_bool(&bool_val, value) == 0 &&
- bool_val == (int)m->cvar_type) {
- *out = m->map_value;
- return 0;
- }
- break;
- }
-
- case GIT_CVAR_INT32:
- if (parse_int32(out, value) == 0)
- return 0;
- break;
-
- case GIT_CVAR_STRING:
- if (strcasecmp(value, m->str_match) == 0) {
- *out = m->map_value;
- return 0;
- }
- break;
- }
- }
-
- return GIT_ENOTFOUND;
-}
-
int git_config_get_mapped(
int *out,
git_config *cfg,
@@ -318,16 +353,10 @@ int git_config_get_mapped(
const char *value;
int ret;
- ret = git_config_get_string(&value, cfg, name);
- if (ret < 0)
+ if ((ret = git_config_get_string(&value, cfg, name)) < 0)
return ret;
- if (!git_config_lookup_map_value(maps, map_n, value, out))
- return 0;
-
- giterr_set(GITERR_CONFIG,
- "Failed to map the '%s' config variable with a valid value", name);
- return -1;
+ return git_config_lookup_map_value(out, maps, map_n, value);
}
int git_config_get_int64(int64_t *out, git_config *cfg, const char *name)
@@ -335,16 +364,10 @@ int git_config_get_int64(int64_t *out, git_config *cfg, const char *name)
const char *value;
int ret;
- ret = git_config_get_string(&value, cfg, name);
- if (ret < 0)
+ if ((ret = git_config_get_string(&value, cfg, name)) < 0)
return ret;
- if (parse_int64(out, value) < 0) {
- giterr_set(GITERR_CONFIG, "Failed to parse '%s' as an integer", value);
- return -1;
- }
-
- return 0;
+ return git_config_parse_int64(out, value);
}
int git_config_get_int32(int32_t *out, git_config *cfg, const char *name)
@@ -352,16 +375,10 @@ int git_config_get_int32(int32_t *out, git_config *cfg, const char *name)
const char *value;
int ret;
- ret = git_config_get_string(&value, cfg, name);
- if (ret < 0)
+ if ((ret = git_config_get_string(&value, cfg, name)) < 0)
return ret;
- if (parse_int32(out, value) < 0) {
- giterr_set(GITERR_CONFIG, "Failed to parse '%s' as a 32-bit integer", value);
- return -1;
- }
-
- return 0;
+ return git_config_parse_int32(out, value);
}
int git_config_get_bool(int *out, git_config *cfg, const char *name)
@@ -369,20 +386,24 @@ int git_config_get_bool(int *out, git_config *cfg, const char *name)
const char *value;
int ret;
- ret = git_config_get_string(&value, cfg, name);
- if (ret < 0)
+ if ((ret = git_config_get_string(&value, cfg, name)) < 0)
return ret;
- if (git__parse_bool(out, value) == 0)
- return 0;
+ return git_config_parse_bool(out, value);
+}
- if (parse_int32(out, value) == 0) {
- *out = !!(*out);
- return 0;
- }
+static int get_string_at_file(const char **out, git_config_file *file, const char *name)
+{
+ const git_config_entry *entry;
+ int res;
- giterr_set(GITERR_CONFIG, "Failed to parse '%s' as a boolean value", value);
- return -1;
+ *out = NULL;
+
+ res = file->get(file, name, &entry);
+ if (res != GIT_ENOTFOUND)
+ *out = entry->value;
+
+ return res;
}
int git_config_get_string(const char **out, git_config *cfg, const char *name)
@@ -392,6 +413,23 @@ int git_config_get_string(const char **out, git_config *cfg, const char *name)
assert(cfg->files.length);
+ git_vector_foreach(&cfg->files, i, internal) {
+ int res = get_string_at_file(out, internal->file, name);
+
+ if (res != GIT_ENOTFOUND)
+ return res;
+ }
+
+ return GIT_ENOTFOUND;
+}
+
+int git_config_get_config_entry(const git_config_entry **out, git_config *cfg, const char *name)
+{
+ file_internal *internal;
+ unsigned int i;
+
+ assert(cfg->files.length);
+
*out = NULL;
git_vector_foreach(&cfg->files, i, internal) {
@@ -405,7 +443,7 @@ int git_config_get_string(const char **out, git_config *cfg, const char *name)
}
int git_config_get_multivar(git_config *cfg, const char *name, const char *regexp,
- int (*fn)(const char *value, void *data), void *data)
+ int (*fn)(const git_config_entry *entry, void *data), void *data)
{
file_internal *internal;
git_config_file *file;
@@ -431,20 +469,13 @@ int git_config_get_multivar(git_config *cfg, const char *name, const char *regex
int git_config_set_multivar(git_config *cfg, const char *name, const char *regexp, const char *value)
{
- file_internal *internal;
git_config_file *file;
- int ret = GIT_ENOTFOUND;
- size_t i;
+ file_internal *internal;
- for (i = cfg->files.length; i > 0; --i) {
- internal = git_vector_get(&cfg->files, i - 1);
- file = internal->file;
- ret = file->set_multivar(file, name, regexp, value);
- if (ret < 0 && ret != GIT_ENOTFOUND)
- return ret;
- }
+ internal = git_vector_get(&cfg->files, 0);
+ file = internal->file;
- return 0;
+ return file->set_multivar(file, name, regexp, value);
}
int git_config_find_global_r(git_buf *path)
@@ -541,13 +572,16 @@ int git_config_open_default(git_config **out)
error = git_config_new(&cfg);
if (!error && !git_config_find_global_r(&buf))
- error = git_config_add_file_ondisk(cfg, buf.ptr, 3);
+ error = git_config_add_file_ondisk(cfg, buf.ptr,
+ GIT_CONFIG_LEVEL_GLOBAL, 0);
if (!error && !git_config_find_xdg_r(&buf))
- error = git_config_add_file_ondisk(cfg, buf.ptr, 2);
+ error = git_config_add_file_ondisk(cfg, buf.ptr,
+ GIT_CONFIG_LEVEL_XDG, 0);
if (!error && !git_config_find_system_r(&buf))
- error = git_config_add_file_ondisk(cfg, buf.ptr, 1);
+ error = git_config_add_file_ondisk(cfg, buf.ptr,
+ GIT_CONFIG_LEVEL_SYSTEM, 0);
git_buf_free(&buf);
@@ -560,3 +594,129 @@ int git_config_open_default(git_config **out)
return error;
}
+
+/***********
+ * Parsers
+ ***********/
+int git_config_lookup_map_value(
+ int *out,
+ git_cvar_map *maps,
+ size_t map_n,
+ const char *value)
+{
+ size_t i;
+
+ if (!value)
+ goto fail_parse;
+
+ for (i = 0; i < map_n; ++i) {
+ git_cvar_map *m = maps + i;
+
+ switch (m->cvar_type) {
+ case GIT_CVAR_FALSE:
+ case GIT_CVAR_TRUE: {
+ int bool_val;
+
+ if (git__parse_bool(&bool_val, value) == 0 &&
+ bool_val == (int)m->cvar_type) {
+ *out = m->map_value;
+ return 0;
+ }
+ break;
+ }
+
+ case GIT_CVAR_INT32:
+ if (git_config_parse_int32(out, value) == 0)
+ return 0;
+ break;
+
+ case GIT_CVAR_STRING:
+ if (strcasecmp(value, m->str_match) == 0) {
+ *out = m->map_value;
+ return 0;
+ }
+ break;
+ }
+ }
+
+fail_parse:
+ giterr_set(GITERR_CONFIG, "Failed to map '%s'", value);
+ return -1;
+}
+
+int git_config_parse_bool(int *out, const char *value)
+{
+ if (git__parse_bool(out, value) == 0)
+ return 0;
+
+ if (git_config_parse_int32(out, value) == 0) {
+ *out = !!(*out);
+ return 0;
+ }
+
+ giterr_set(GITERR_CONFIG, "Failed to parse '%s' as a boolean value", value);
+ return -1;
+}
+
+int git_config_parse_int64(int64_t *out, const char *value)
+{
+ const char *num_end;
+ int64_t num;
+
+ if (git__strtol64(&num, value, &num_end, 0) < 0)
+ goto fail_parse;
+
+ switch (*num_end) {
+ case 'g':
+ case 'G':
+ num *= 1024;
+ /* fallthrough */
+
+ case 'm':
+ case 'M':
+ num *= 1024;
+ /* fallthrough */
+
+ case 'k':
+ case 'K':
+ num *= 1024;
+
+ /* check that that there are no more characters after the
+ * given modifier suffix */
+ if (num_end[1] != '\0')
+ return -1;
+
+ /* fallthrough */
+
+ case '\0':
+ *out = num;
+ return 0;
+
+ default:
+ goto fail_parse;
+ }
+
+fail_parse:
+ giterr_set(GITERR_CONFIG, "Failed to parse '%s' as an integer", value);
+ return -1;
+}
+
+int git_config_parse_int32(int32_t *out, const char *value)
+{
+ int64_t tmp;
+ int32_t truncate;
+
+ if (git_config_parse_int64(&tmp, value) < 0)
+ goto fail_parse;
+
+ truncate = tmp & 0xFFFFFFFF;
+ if (truncate != tmp)
+ goto fail_parse;
+
+ *out = truncate;
+ return 0;
+
+fail_parse:
+ giterr_set(GITERR_CONFIG, "Failed to parse '%s' as a 32-bit integer", value);
+ return -1;
+}
diff --git a/src/config.h b/src/config.h
index 471b42dad..16b8413b7 100644
--- a/src/config.h
+++ b/src/config.h
@@ -27,9 +27,4 @@ extern int git_config_find_global_r(git_buf *global_config_path);
extern int git_config_find_xdg_r(git_buf *system_config_path);
extern int git_config_find_system_r(git_buf *system_config_path);
-extern int git_config_parse_bool(int *out, const char *bool_string);
-
-extern int git_config_lookup_map_value(
- git_cvar_map *maps, size_t map_n, const char *value, int *out);
-
#endif
diff --git a/src/config_file.c b/src/config_file.c
index 12ae4a214..92fe13296 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -22,15 +22,9 @@ GIT__USE_STRMAP;
typedef struct cvar_t {
struct cvar_t *next;
- char *key; /* TODO: we might be able to get rid of this */
- char *value;
+ git_config_entry *entry;
} cvar_t;
-typedef struct {
- struct cvar_t *head;
- struct cvar_t *tail;
-} cvar_t_list;
-
#define CVAR_LIST_HEAD(list) ((list)->head)
#define CVAR_LIST_TAIL(list) ((list)->tail)
@@ -84,7 +78,7 @@ typedef struct {
char *file_path;
} diskfile_backend;
-static int config_parse(diskfile_backend *cfg_file);
+static int config_parse(diskfile_backend *cfg_file, unsigned int level);
static int parse_variable(diskfile_backend *cfg, char **var_name, char **var_value);
static int config_write(diskfile_backend *cfg, const char *key, const regex_t *preg, const char *value);
static char *escape_value(const char *ptr);
@@ -100,8 +94,9 @@ static void cvar_free(cvar_t *var)
if (var == NULL)
return;
- git__free(var->key);
- git__free(var->value);
+ git__free((char*)var->entry->name);
+ git__free((char *)var->entry->value);
+ git__free(var->entry);
git__free(var);
}
@@ -150,7 +145,7 @@ static void free_vars(git_strmap *values)
git_strmap_free(values);
}
-static int config_open(git_config_file *cfg)
+static int config_open(git_config_file *cfg, unsigned int level)
{
int res;
diskfile_backend *b = (diskfile_backend *)cfg;
@@ -165,7 +160,7 @@ static int config_open(git_config_file *cfg)
if (res == GIT_ENOTFOUND)
return 0;
- if (res < 0 || config_parse(b) < 0) {
+ if (res < 0 || config_parse(b, level) < 0) {
free_vars(b->values);
b->values = NULL;
git_buf_free(&b->reader.buffer);
@@ -191,7 +186,7 @@ static void backend_free(git_config_file *_backend)
static int file_foreach(
git_config_file *backend,
const char *regexp,
- int (*fn)(const char *, const char *, void *),
+ int (*fn)(const git_config_entry *, void *),
void *data)
{
diskfile_backend *b = (diskfile_backend *)backend;
@@ -220,7 +215,7 @@ static int file_foreach(
continue;
/* abort iterator on non-zero return value */
- if (fn(key, var->value, data)) {
+ if (fn(var->entry, data)) {
giterr_clear();
result = GIT_EUSER;
goto cleanup;
@@ -263,8 +258,8 @@ static int config_set(git_config_file *cfg, const char *name, const char *value)
}
/* don't update if old and new values already match */
- if ((!existing->value && !value) ||
- (existing->value && value && !strcmp(existing->value, value)))
+ if ((!existing->entry->value && !value) ||
+ (existing->entry->value && value && !strcmp(existing->entry->value, value)))
return 0;
if (value) {
@@ -274,10 +269,10 @@ static int config_set(git_config_file *cfg, const char *name, const char *value)
GITERR_CHECK_ALLOC(esc_value);
}
- git__free(existing->value);
- existing->value = tmp;
+ git__free((void *)existing->entry->value);
+ existing->entry->value = tmp;
- ret = config_write(b, existing->key, NULL, esc_value);
+ ret = config_write(b, existing->entry->name, NULL, esc_value);
git__free(esc_value);
return ret;
@@ -285,15 +280,17 @@ static int config_set(git_config_file *cfg, const char *name, const char *value)
var = git__malloc(sizeof(cvar_t));
GITERR_CHECK_ALLOC(var);
-
memset(var, 0x0, sizeof(cvar_t));
+ var->entry = git__malloc(sizeof(git_config_entry));
+ GITERR_CHECK_ALLOC(var->entry);
+ memset(var->entry, 0x0, sizeof(git_config_entry));
- var->key = key;
- var->value = NULL;
+ var->entry->name = key;
+ var->entry->value = NULL;
if (value) {
- var->value = git__strdup(value);
- GITERR_CHECK_ALLOC(var->value);
+ var->entry->value = git__strdup(value);
+ GITERR_CHECK_ALLOC(var->entry->value);
esc_value = escape_value(value);
GITERR_CHECK_ALLOC(esc_value);
}
@@ -317,7 +314,7 @@ static int config_set(git_config_file *cfg, const char *name, const char *value)
/*
* Internal function that actually gets the value in string form
*/
-static int config_get(git_config_file *cfg, const char *name, const char **out)
+static int config_get(git_config_file *cfg, const char *name, const git_config_entry **out)
{
diskfile_backend *b = (diskfile_backend *)cfg;
char *key;
@@ -333,7 +330,7 @@ static int config_get(git_config_file *cfg, const char *name, const char **out)
if (!git_strmap_valid_index(b->values, pos))
return GIT_ENOTFOUND;
- *out = ((cvar_t *)git_strmap_value_at(b->values, pos))->value;
+ *out = ((cvar_t *)git_strmap_value_at(b->values, pos))->entry;
return 0;
}
@@ -342,7 +339,7 @@ static int config_get_multivar(
git_config_file *cfg,
const char *name,
const char *regex_str,
- int (*fn)(const char *, void *),
+ int (*fn)(const git_config_entry *, void *),
void *data)
{
cvar_t *var;
@@ -376,10 +373,10 @@ static int config_get_multivar(
/* and throw the callback only on the variables that
* match the regex */
do {
- if (regexec(&regex, var->value, 0, NULL, 0) == 0) {
+ if (regexec(&regex, var->entry->value, 0, NULL, 0) == 0) {
/* early termination by the user is not an error;
* just break and return successfully */
- if (fn(var->value, data) < 0)
+ if (fn(var->entry, data) < 0)
break;
}
@@ -391,7 +388,7 @@ static int config_get_multivar(
do {
/* early termination by the user is not an error;
* just break and return successfully */
- if (fn(var->value, data) < 0)
+ if (fn(var->entry, data) < 0)
break;
var = var->next;
@@ -434,12 +431,12 @@ static int config_set_multivar(
}
for (;;) {
- if (regexec(&preg, var->value, 0, NULL, 0) == 0) {
+ if (regexec(&preg, var->entry->value, 0, NULL, 0) == 0) {
char *tmp = git__strdup(value);
GITERR_CHECK_ALLOC(tmp);
- git__free(var->value);
- var->value = tmp;
+ git__free((void *)var->entry->value);
+ var->entry->value = tmp;
replaced = 1;
}
@@ -453,14 +450,18 @@ static int config_set_multivar(
if (!replaced) {
newvar = git__malloc(sizeof(cvar_t));
GITERR_CHECK_ALLOC(newvar);
-
memset(newvar, 0x0, sizeof(cvar_t));
+ newvar->entry = git__malloc(sizeof(git_config_entry));
+ GITERR_CHECK_ALLOC(newvar->entry);
+ memset(newvar->entry, 0x0, sizeof(git_config_entry));
+
+ newvar->entry->name = git__strdup(var->entry->name);
+ GITERR_CHECK_ALLOC(newvar->entry->name);
- newvar->key = git__strdup(var->key);
- GITERR_CHECK_ALLOC(newvar->key);
+ newvar->entry->value = git__strdup(value);
+ GITERR_CHECK_ALLOC(newvar->entry->value);
- newvar->value = git__strdup(value);
- GITERR_CHECK_ALLOC(newvar->value);
+ newvar->entry->level = var->entry->level;
var->next = newvar;
}
@@ -501,7 +502,7 @@ static int config_delete(git_config_file *cfg, const char *name)
git_strmap_delete_at(b->values, pos);
- result = config_write(b, var->key, NULL, NULL);
+ result = config_write(b, var->entry->name, NULL, NULL);
cvar_free(var);
return result;
@@ -898,7 +899,7 @@ static int strip_comments(char *line, int in_quotes)
return quote_count;
}
-static int config_parse(diskfile_backend *cfg_file)
+static int config_parse(diskfile_backend *cfg_file, unsigned int level)
{
int c;
char *current_section = NULL;
@@ -946,8 +947,10 @@ static int config_parse(diskfile_backend *cfg_file)
var = git__malloc(sizeof(cvar_t));
GITERR_CHECK_ALLOC(var);
-
memset(var, 0x0, sizeof(cvar_t));
+ var->entry = git__malloc(sizeof(git_config_entry));
+ GITERR_CHECK_ALLOC(var->entry);
+ memset(var->entry, 0x0, sizeof(git_config_entry));
git__strtolower(var_name);
git_buf_printf(&buf, "%s.%s", current_section, var_name);
@@ -956,13 +959,14 @@ static int config_parse(diskfile_backend *cfg_file)
if (git_buf_oom(&buf))
return -1;
- var->key = git_buf_detach(&buf);
- var->value = var_value;
+ var->entry->name = git_buf_detach(&buf);
+ var->entry->value = var_value;
+ var->entry->level = level;
/* Add or append the new config option */
- pos = git_strmap_lookup_index(cfg_file->values, var->key);
+ pos = git_strmap_lookup_index(cfg_file->values, var->entry->name);
if (!git_strmap_valid_index(cfg_file->values, pos)) {
- git_strmap_insert(cfg_file->values, var->key, var, result);
+ git_strmap_insert(cfg_file->values, var->entry->name, var, result);
if (result < 0)
break;
result = 0;
diff --git a/src/config_file.h b/src/config_file.h
index bf687b516..b500dd64f 100644
--- a/src/config_file.h
+++ b/src/config_file.h
@@ -9,9 +9,9 @@
#include "git2/config.h"
-GIT_INLINE(int) git_config_file_open(git_config_file *cfg)
+GIT_INLINE(int) git_config_file_open(git_config_file *cfg, unsigned int level)
{
- return cfg->open(cfg);
+ return cfg->open(cfg, level);
}
GIT_INLINE(void) git_config_file_free(git_config_file *cfg)
@@ -20,7 +20,7 @@ GIT_INLINE(void) git_config_file_free(git_config_file *cfg)
}
GIT_INLINE(int) git_config_file_get_string(
- const char **out, git_config_file *cfg, const char *name)
+ const git_config_entry **out, git_config_file *cfg, const char *name)
{
return cfg->get(cfg, name, out);
}
@@ -39,7 +39,7 @@ GIT_INLINE(int) git_config_file_delete(
GIT_INLINE(int) git_config_file_foreach(
git_config_file *cfg,
- int (*fn)(const char *key, const char *value, void *data),
+ int (*fn)(const git_config_entry *entry, void *data),
void *data)
{
return cfg->foreach(cfg, NULL, fn, data);
@@ -48,7 +48,7 @@ GIT_INLINE(int) git_config_file_foreach(
GIT_INLINE(int) git_config_file_foreach_match(
git_config_file *cfg,
const char *regexp,
- int (*fn)(const char *key, const char *value, void *data),
+ int (*fn)(const git_config_entry *entry, void *data),
void *data)
{
return cfg->foreach(cfg, regexp, fn, data);
diff --git a/src/remote.c b/src/remote.c
index 5ef791d39..e05ea059f 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -637,12 +637,12 @@ struct cb_data {
regex_t *preg;
};
-static int remote_list_cb(const char *name, const char *value, void *data_)
+static int remote_list_cb(const git_config_entry *entry, void *data_)
{
struct cb_data *data = (struct cb_data *)data_;
size_t nmatch = 2;
regmatch_t pmatch[2];
- GIT_UNUSED(value);
+ const char *name = entry->name;
if (!regexec(data->preg, name, nmatch, pmatch, 0)) {
char *remote_name = git__strndup(&name[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so);
diff --git a/src/repository.c b/src/repository.c
index db0888a89..43e0eda8f 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -461,23 +461,23 @@ static int load_config(
&config_path, repo->path_repository, GIT_CONFIG_FILENAME_INREPO) < 0)
goto on_error;
- if (git_config_add_file_ondisk(cfg, config_path.ptr, 4) < 0)
+ if (git_config_add_file_ondisk(cfg, config_path.ptr, GIT_CONFIG_LEVEL_LOCAL, 0) < 0)
goto on_error;
git_buf_free(&config_path);
if (global_config_path != NULL) {
- if (git_config_add_file_ondisk(cfg, global_config_path, 3) < 0)
+ if (git_config_add_file_ondisk(cfg, global_config_path, GIT_CONFIG_LEVEL_GLOBAL, 0) < 0)
goto on_error;
}
if (xdg_config_path != NULL) {
- if (git_config_add_file_ondisk(cfg, xdg_config_path, 2) < 0)
+ if (git_config_add_file_ondisk(cfg, xdg_config_path, GIT_CONFIG_LEVEL_XDG, 0) < 0)
goto on_error;
}
if (system_config_path != NULL) {
- if (git_config_add_file_ondisk(cfg, system_config_path, 1) < 0)
+ if (git_config_add_file_ondisk(cfg, system_config_path, GIT_CONFIG_LEVEL_SYSTEM, 0) < 0)
goto on_error;
}
diff --git a/src/submodule.c b/src/submodule.c
index 180528641..e3657f9ad 100644
--- a/src/submodule.c
+++ b/src/submodule.c
@@ -72,7 +72,7 @@ static int submodule_get(git_submodule **, git_repository *, const char *, const
static void submodule_release(git_submodule *sm, int decr);
static int submodule_load_from_index(git_repository *, const git_index_entry *);
static int submodule_load_from_head(git_repository*, const char*, const git_oid*);
-static int submodule_load_from_config(const char *, const char *, void *);
+static int submodule_load_from_config(const git_config_entry *, void *);
static int submodule_load_from_wd_lite(git_submodule *, const char *, void *);
static int submodule_update_config(git_submodule *, const char *, const char *, bool, bool);
static void submodule_mode_mismatch(git_repository *, const char *, unsigned int);
@@ -974,11 +974,12 @@ static int submodule_config_error(const char *property, const char *value)
}
static int submodule_load_from_config(
- const char *key, const char *value, void *data)
+ const git_config_entry *entry, void *data)
{
git_repository *repo = data;
git_strmap *smcfg = repo->submodules;
const char *namestart, *property, *alternate = NULL;
+ const char *key = entry->name, *value = entry->value;
git_buf name = GIT_BUF_INIT;
git_submodule *sm;
bool is_path;
@@ -1055,7 +1056,7 @@ static int submodule_load_from_config(
else if (strcasecmp(property, "update") == 0) {
int val;
if (git_config_lookup_map_value(
- _sm_update_map, ARRAY_SIZE(_sm_update_map), value, &val) < 0)
+ &val, _sm_update_map, ARRAY_SIZE(_sm_update_map), value) < 0)
return submodule_config_error("update", value);
sm->update_default = sm->update = (git_submodule_update_t)val;
}
@@ -1066,7 +1067,7 @@ static int submodule_load_from_config(
else if (strcasecmp(property, "ignore") == 0) {
int val;
if (git_config_lookup_map_value(
- _sm_ignore_map, ARRAY_SIZE(_sm_ignore_map), value, &val) < 0)
+ &val, _sm_ignore_map, ARRAY_SIZE(_sm_ignore_map), value) < 0)
return submodule_config_error("ignore", value);
sm->ignore_default = sm->ignore = (git_submodule_ignore_t)val;
}
@@ -1204,7 +1205,7 @@ static git_config_file *open_gitmodules(
if (git_config_file__ondisk(&mods, path.ptr) < 0)
mods = NULL;
/* open should only fail here if the file is malformed */
- else if (git_config_file_open(mods) < 0) {
+ else if (git_config_file_open(mods, GIT_CONFIG_LEVEL_LOCAL) < 0) {
git_config_file_free(mods);
mods = NULL;
}