summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Martí <tanoku@gmail.com>2012-03-01 00:52:21 +0100
committerVicent Martí <tanoku@gmail.com>2012-03-01 00:52:21 +0100
commitc5e944820ab50f6106ab4f86f37d087a74acc595 (patch)
treee54313767deb1c36fc66fb4bc9ec0677fa859369
parent27950fa3f40f45ede9aa2b108796fd2b73b33016 (diff)
downloadlibgit2-c5e944820ab50f6106ab4f86f37d087a74acc595.tar.gz
config: Refactor & add `git_config_get_mapped`
Sane API for real-world usage.
-rw-r--r--include/git2/config.h50
-rw-r--r--src/config.c172
2 files changed, 171 insertions, 51 deletions
diff --git a/include/git2/config.h b/include/git2/config.h
index 8a0f58937..acc45b018 100644
--- a/include/git2/config.h
+++ b/include/git2/config.h
@@ -37,6 +37,19 @@ struct git_config_file {
void (*free)(struct git_config_file *);
};
+typedef enum {
+ GIT_CVAR_FALSE = 0,
+ GIT_CVAR_TRUE = 1,
+ GIT_CVAR_INT32,
+ GIT_CVAR_STRING
+} git_cvar_t;
+
+typedef struct {
+ git_cvar_t cvar_type;
+ const char *str_match;
+ int map_value;
+} git_cvar_map;
+
/**
* Locate the path to the global configuration file
*
@@ -301,6 +314,43 @@ GIT_EXTERN(int) git_config_foreach(
int (*callback)(const char *var_name, const char *value, void *payload),
void *payload);
+
+/**
+ * Query the value of a config variable and return it mapped to
+ * an integer constant.
+ *
+ * This is a helper method to easily map different possible values
+ * to a variable to integer constants that easily identify them.
+ *
+ * A mapping array looks as follows:
+ *
+ * git_cvar_map autocrlf_mapping[3] = {
+ * {GIT_CVAR_FALSE, NULL, GIT_AUTO_CRLF_FALSE},
+ * {GIT_CVAR_TRUE, NULL, GIT_AUTO_CRLF_TRUE},
+ * {GIT_CVAR_STRING, "input", GIT_AUTO_CRLF_INPUT},
+ * {GIT_CVAR_STRING, "default", GIT_AUTO_CRLF_DEFAULT}};
+ *
+ * On any "false" value for the variable (e.g. "false", "FALSE", "no"), the
+ * mapping will store `GIT_AUTO_CRLF_FALSE` in the `out` parameter.
+ *
+ * The same thing applies for any "true" value such as "true", "yes" or "1", storing
+ * the `GIT_AUTO_CRLF_TRUE` variable.
+ *
+ * Otherwise, if the value matches the string "input" (with case insensitive comparison),
+ * the given constant will be stored in `out`, and likewise for "default".
+ *
+ * If not a single match can be made to store in `out`, an error code will be
+ * returned.
+ *
+ * @param cfg config file to get the variables from
+ * @param name name of the config variable to lookup
+ * @param maps array of `git_cvar_map` objects specifying the possible mappings
+ * @param map_n number of mapping objects in `maps`
+ * @param out place to store the result of the mapping
+ * @return GIT_SUCCESS on success, error code otherwise
+ */
+GIT_EXTERN(int) git_config_get_mapped(git_config *cfg, const char *name, git_cvar_map *maps, size_t map_n, int *out);
+
/** @} */
GIT_END_DECL
#endif
diff --git a/src/config.c b/src/config.c
index 4ff1b2e72..912224158 100644
--- a/src/config.c
+++ b/src/config.c
@@ -209,23 +209,37 @@ int git_config_set_string(git_config *cfg, const char *name, const char *value)
return file->set(file, name, value);
}
-/***********
- * Getters
- ***********/
+static int parse_bool(int *out, const char *value)
+{
+ /* A missing value means true */
+ if (value == NULL) {
+ *out = 1;
+ return GIT_SUCCESS;
+ }
-int git_config_get_int64(git_config *cfg, const char *name, int64_t *out)
+ if (!strcasecmp(value, "true") ||
+ !strcasecmp(value, "yes") ||
+ !strcasecmp(value, "on")) {
+ *out = 1;
+ return GIT_SUCCESS;
+ }
+ if (!strcasecmp(value, "false") ||
+ !strcasecmp(value, "no") ||
+ !strcasecmp(value, "off")) {
+ *out = 0;
+ return GIT_SUCCESS;
+ }
+
+ return GIT_EINVALIDTYPE;
+}
+
+static int parse_int64(int64_t *out, const char *value)
{
- const char *value, *num_end;
- int ret;
+ const char *num_end;
int64_t num;
- ret = git_config_get_string(cfg, name, &value);
- if (ret < GIT_SUCCESS)
- return git__rethrow(ret, "Failed to retrieve value for '%s'", name);
-
- ret = git__strtol64(&num, value, &num_end, 0);
- if (ret < GIT_SUCCESS)
- return git__rethrow(ret, "Failed to convert value for '%s'", name);
+ if (git__strtol64(&num, value, &num_end, 0) < 0)
+ return GIT_EINVALIDTYPE;
switch (*num_end) {
case 'g':
@@ -245,38 +259,112 @@ int git_config_get_int64(git_config *cfg, const char *name, int64_t *out)
/* check that that there are no more characters after the
* given modifier suffix */
if (num_end[1] != '\0')
- return git__throw(GIT_EINVALIDTYPE,
- "Failed to get value for '%s'. Invalid type suffix", name);
+ return GIT_EINVALIDTYPE;
/* fallthrough */
case '\0':
*out = num;
- return GIT_SUCCESS;
+ return 0;
default:
- return git__throw(GIT_EINVALIDTYPE,
- "Failed to get value for '%s'. Value is of invalid type", name);
+ return GIT_EINVALIDTYPE;
}
}
-int git_config_get_int32(git_config *cfg, const char *name, int32_t *out)
+static int parse_int32(int32_t *out, const char *value)
{
- int64_t tmp_long;
- int32_t tmp_int;
+ int64_t tmp;
+ int32_t truncate;
+
+ if (parse_int64(&tmp, value) < 0)
+ return GIT_EINVALIDTYPE;
+
+ truncate = tmp & 0xFFFFFFFF;
+ if (truncate != tmp)
+ return GIT_EOVERFLOW;
+
+ *out = truncate;
+ return 0;
+}
+
+/***********
+ * Getters
+ ***********/
+int git_config_get_mapped(git_config *cfg, const char *name, git_cvar_map *maps, size_t map_n, int *out)
+{
+ size_t i;
+ const char *value;
+ int error;
+
+ error = git_config_get_string(cfg, name, &value);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ 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 (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;
+ }
+ }
+ }
+
+ return git__throw(GIT_ENOTFOUND,
+ "Failed to map the '%s' config variable with a valid value", name);
+}
+
+int git_config_get_int64(git_config *cfg, const char *name, int64_t *out)
+{
+ const char *value;
int ret;
- ret = git_config_get_int64(cfg, name, &tmp_long);
+ ret = git_config_get_string(cfg, name, &value);
if (ret < GIT_SUCCESS)
- return git__rethrow(ret, "Failed to convert value for '%s'", name);
-
- tmp_int = tmp_long & 0xFFFFFFFF;
- if (tmp_int != tmp_long)
- return git__throw(GIT_EOVERFLOW, "Value for '%s' is too large", name);
+ return git__rethrow(ret, "Failed to retrieve value for '%s'", name);
- *out = tmp_int;
+ if (parse_int64(out, value) < 0)
+ return git__throw(GIT_EINVALIDTYPE, "Failed to parse '%s' as an integer", value);
- return ret;
+ return GIT_SUCCESS;
+}
+
+int git_config_get_int32(git_config *cfg, const char *name, int32_t *out)
+{
+ const char *value;
+ int error;
+
+ error = git_config_get_string(cfg, name, &value);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to get value for %s", name);
+
+ error = parse_int32(out, value);
+ if (error < GIT_SUCCESS)
+ return git__throw(GIT_EINVALIDTYPE, "Failed to parse '%s' as a 32-bit integer", value);
+
+ return GIT_SUCCESS;
}
int git_config_get_bool(git_config *cfg, const char *name, int *out)
@@ -288,33 +376,15 @@ int git_config_get_bool(git_config *cfg, const char *name, int *out)
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to get value for %s", name);
- /* A missing value means true */
- if (value == NULL) {
- *out = 1;
+ if (parse_bool(out, value) == 0)
return GIT_SUCCESS;
- }
- if (!strcasecmp(value, "true") ||
- !strcasecmp(value, "yes") ||
- !strcasecmp(value, "on")) {
- *out = 1;
- return GIT_SUCCESS;
- }
- if (!strcasecmp(value, "false") ||
- !strcasecmp(value, "no") ||
- !strcasecmp(value, "off")) {
- *out = 0;
+ if (parse_int32(out, value) == 0) {
+ *out = !!(*out);
return GIT_SUCCESS;
}
- /* Try to parse it as an integer */
- error = git_config_get_int32(cfg, name, out);
- if (error == GIT_SUCCESS)
- *out = !!(*out);
-
- if (error < GIT_SUCCESS)
- return git__rethrow(error, "Failed to get value for %s", name);
- return error;
+ return git__throw(GIT_EINVALIDTYPE, "Failed to parse '%s' as a boolean value", value);
}
int git_config_get_string(git_config *cfg, const char *name, const char **out)