summaryrefslogtreecommitdiff
path: root/src/config.c
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2013-11-25 14:21:34 -0800
committerRussell Belfer <rb@github.com>2013-12-11 10:57:49 -0800
commit9f77b3f6f5ce6944ec49dfc666ef6b8df0af0c6b (patch)
tree1c5405663a7bcc505f098b375c7ff5dc872af3ea /src/config.c
parent0eedacb06ae07fd0d784066ad41383276e05d92e (diff)
downloadlibgit2-9f77b3f6f5ce6944ec49dfc666ef6b8df0af0c6b.tar.gz
Add config read fns with controlled error behavior
This adds `git_config__lookup_entry` which will look up a key in a config and return either the entry or NULL if the key was not present. Optionally, it can either suppress all errors or can return them (although not finding the key is not an error for this function). Unlike other accessors, this does not normalize the config key string, so it must only be used when the key is known to be in normalized form (i.e. all lower-case before the first dot and after the last dot, with no invalid characters). This also adds three high-level helper functions to look up config values with no errors and a fallback value. The three functions are for string, bool, and int values, and will resort to the fallback value for any error that arises. They are: * `git_config__get_string_force` * `git_config__get_bool_force` * `git_config__get_int_force` None of them normalize the config `key` either, so they can only be used for internal cases where the key is known to be in normal format.
Diffstat (limited to 'src/config.c')
-rw-r--r--src/config.c181
1 files changed, 114 insertions, 67 deletions
diff --git a/src/config.c b/src/config.c
index 0d9471383..227adbc9b 100644
--- a/src/config.c
+++ b/src/config.c
@@ -620,6 +620,78 @@ int git_config_set_string(git_config *cfg, const char *name, const char *value)
/***********
* Getters
***********/
+
+static int config_error_notfound(const char *name)
+{
+ giterr_set(GITERR_CONFIG, "Config value '%s' was not found", name);
+ return GIT_ENOTFOUND;
+}
+
+enum {
+ GET_ALL_ERRORS = 0,
+ GET_NO_MISSING = 1,
+ GET_NO_ERRORS = 2
+};
+
+static int get_entry(
+ const git_config_entry **out,
+ const git_config *cfg,
+ const char *name,
+ bool normalize_name,
+ int want_errors)
+{
+ int res = GIT_ENOTFOUND;
+ const char *key = name;
+ char *normalized = NULL;
+ size_t i;
+ file_internal *internal;
+
+ *out = NULL;
+
+ if (normalize_name) {
+ if ((res = git_config__normalize_name(name, &normalized)) < 0)
+ goto cleanup;
+ key = normalized;
+ }
+
+ git_vector_foreach(&cfg->files, i, internal) {
+ if (!internal || !internal->file)
+ continue;
+
+ res = internal->file->get(internal->file, key, out);
+ if (res != GIT_ENOTFOUND)
+ break;
+ }
+
+ git__free(normalized);
+
+cleanup:
+ if (res == GIT_ENOTFOUND)
+ res = (want_errors > GET_ALL_ERRORS) ? 0 : config_error_notfound(name);
+ else if (res && (want_errors == GET_NO_ERRORS)) {
+ giterr_clear();
+ res = 0;
+ }
+
+ return res;
+}
+
+int git_config_get_entry(
+ const git_config_entry **out, const git_config *cfg, const char *name)
+{
+ return get_entry(out, cfg, name, true, GET_ALL_ERRORS);
+}
+
+int git_config__lookup_entry(
+ const git_config_entry **out,
+ const git_config *cfg,
+ const char *key,
+ bool no_errors)
+{
+ return get_entry(
+ out, cfg, key, false, no_errors ? GET_NO_ERRORS : GET_NO_MISSING);
+}
+
int git_config_get_mapped(
int *out,
const git_config *cfg,
@@ -627,116 +699,91 @@ int git_config_get_mapped(
const git_cvar_map *maps,
size_t map_n)
{
- const char *value;
+ const git_config_entry *entry;
int ret;
- if ((ret = git_config_get_string(&value, cfg, name)) < 0)
+ if ((ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0)
return ret;
- return git_config_lookup_map_value(out, maps, map_n, value);
+ return git_config_lookup_map_value(out, maps, map_n, entry->value);
}
int git_config_get_int64(int64_t *out, const git_config *cfg, const char *name)
{
- const char *value;
+ const git_config_entry *entry;
int ret;
- if ((ret = git_config_get_string(&value, cfg, name)) < 0)
+ if ((ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0)
return ret;
- return git_config_parse_int64(out, value);
+ return git_config_parse_int64(out, entry->value);
}
int git_config_get_int32(int32_t *out, const git_config *cfg, const char *name)
{
- const char *value;
+ const git_config_entry *entry;
int ret;
- if ((ret = git_config_get_string(&value, cfg, name)) < 0)
+ if ((ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0)
return ret;
- return git_config_parse_int32(out, value);
+ return git_config_parse_int32(out, entry->value);
}
-static int get_string_at_file(const char **out, const git_config_backend *file, const char *name)
+int git_config_get_bool(int *out, const git_config *cfg, const char *name)
{
const git_config_entry *entry;
- int res;
+ int ret;
- res = file->get(file, name, &entry);
- if (!res)
- *out = entry->value;
+ if ((ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0)
+ return ret;
- return res;
+ return git_config_parse_bool(out, entry->value);
}
-static int config_error_notfound(const char *name)
+int git_config_get_string(
+ const char **out, const git_config *cfg, const char *name)
{
- giterr_set(GITERR_CONFIG, "Config value '%s' was not found", name);
- return GIT_ENOTFOUND;
+ const git_config_entry *entry;
+ int ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS);
+ *out = !ret ? (entry->value ? entry->value : "") : NULL;
+ return ret;
}
-static int get_string(const char **out, const git_config *cfg, const char *name)
+const char *git_config__get_string_force(
+ const git_config *cfg, const char *key, const char *fallback_value)
{
- file_internal *internal;
- unsigned int i;
- int res;
-
- git_vector_foreach(&cfg->files, i, internal) {
- if (!internal || !internal->file)
- continue;
-
- res = get_string_at_file(out, internal->file, name);
- if (res != GIT_ENOTFOUND)
- return res;
- }
-
- return config_error_notfound(name);
+ const git_config_entry *entry;
+ get_entry(&entry, cfg, key, false, GET_NO_ERRORS);
+ return (entry && entry->value) ? entry->value : fallback_value;
}
-int git_config_get_bool(int *out, const git_config *cfg, const char *name)
+int git_config__get_bool_force(
+ const git_config *cfg, const char *key, int fallback_value)
{
- const char *value = NULL;
- int ret;
-
- if ((ret = get_string(&value, cfg, name)) < 0)
- return ret;
-
- return git_config_parse_bool(out, value);
-}
+ int val = fallback_value;
+ const git_config_entry *entry;
-int git_config_get_string(const char **out, const git_config *cfg, const char *name)
-{
- int ret;
- const char *str = NULL;
+ get_entry(&entry, cfg, key, false, GET_NO_ERRORS);
- if ((ret = get_string(&str, cfg, name)) < 0)
- return ret;
+ if (entry && git_config_parse_bool(&val, entry->value) < 0)
+ giterr_clear();
- *out = str == NULL ? "" : str;
- return 0;
+ return val;
}
-int git_config_get_entry(const git_config_entry **out, const git_config *cfg, const char *name)
+int git_config__get_int_force(
+ const git_config *cfg, const char *key, int fallback_value)
{
- file_internal *internal;
- unsigned int i;
- git_config_backend *file;
- int ret;
-
- *out = NULL;
+ int32_t val = (int32_t)fallback_value;
+ const git_config_entry *entry;
- git_vector_foreach(&cfg->files, i, internal) {
- if (!internal || !internal->file)
- continue;
- file = internal->file;
+ get_entry(&entry, cfg, key, false, GET_NO_ERRORS);
- ret = file->get(file, name, out);
- if (ret != GIT_ENOTFOUND)
- return ret;
- }
+ if (entry && git_config_parse_int32(&val, entry->value) < 0)
+ giterr_clear();
- return config_error_notfound(name);
+ return (int)val;
}
int git_config_get_multivar_foreach(
@@ -1070,7 +1117,7 @@ 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)
+ if (!value || git__strtol64(&num, value, &num_end, 0) < 0)
goto fail_parse;
switch (*num_end) {