diff --git a/include/git2/config.h b/include/git2/config.h index c43d27fa8..c91482636 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -26,11 +26,12 @@ #define INCLUDE_git_config_h__ #include "common.h" +#include "types.h" /** - * @file git2/refs.h + * @file git2/config.h * @brief Git config management routines - * @defgroup git_reference Git config management routines + * @defgroup git_config Git config management routines * @ingroup Git * @{ */ @@ -40,14 +41,137 @@ GIT_BEGIN_DECL * 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); /** * Free the configuration and its associated memory + * + * @param cfg the configuration to free */ GIT_EXTERN(void) git_config_free(git_config *cfg); +/** + * Get the value of an integer or boolean config variable. + * + * This is a more general function to retrieve the value of a integer + * or boolean variable. + * + * @param cfg where to look for the variable + * @param name the variable's name + * @param out pointer to the variable where the value should be stored + * @param type either GIT_VAR_INT or GIT_VAR_BOOL + * @return GIT_SUCCESS on success; error code otherwise + */ +GIT_EXTERN(int) git_config_get(git_config *cfg, const char *name, int *out, git_cvar_type type); + +/** + * Get the value of an integer config variable. + * + * @param cfg where to look for the variable + * @param name the variable's name + * @param out pointer to the variable where the value should be stored + * @return GIT_SUCCESS on success; error code otherwise + */ +GIT_INLINE(int) git_config_get_int(git_config *cfg, const char *name, int *out) +{ + return git_config_get(cfg, name, out, GIT_VAR_INT); +} + +/** + * Get the value of a boolean config variable. + * + * @param cfg where to look for the variable + * @param name the variable's name + * @param out pointer to the variable where the value should be stored + * @return GIT_SUCCESS on success; error code otherwise + */ +GIT_INLINE(int) git_config_get_bool(git_config *cfg, const char *name, int *out) +{ + return git_config_get(cfg, name, out, GIT_VAR_BOOL); +} + +/** + * Get the value of a string config variable. + * + * The string is owned by the variable and should not be freed by the + * user. + * + * @param cfg where to look for the variable + * @param name the variable's name + * @param out pointer to the variable's value + * @return GIT_SUCCESS on success; error code otherwise + */ +GIT_EXTERN(int) git_config_get_string(git_config *cfg, const char *name, const char **out); +/** + * Set the value of an integer or boolean config variable. + * + * This is a more general function to set the value of a integer or + * boolean variable. + * + * @param cfg where to look for the variable + * @param name the variable's name + * @param value the value to store + * @param type either GIT_VAR_INT or GIT_VAR_BOOL + * @return GIT_SUCCESS on success; error code otherwise + */ +GIT_EXTERN(int) git_config_set(git_config *cfg, const char *name, int value, git_cvar_type type); + +/** + * Set the value of an integer config variable. + * + * @param cfg where to look for the variable + * @param name the variable's name + * @param out pointer to the variable where the value should be stored + * @return GIT_SUCCESS on success; error code otherwise + */ +GIT_INLINE(int) git_config_set_int(git_config *cfg, const char *name, int value) +{ + return git_config_set(cfg, name, value, GIT_VAR_INT); +} + +/** + * Set the value of a boolean config variable. + * + * @param cfg where to look for the variable + * @param name the variable's name + * @param value the value to store + * @return GIT_SUCCESS on success; error code otherwise + */ +GIT_INLINE(int) git_config_set_bool(git_config *cfg, const char *name, int value) +{ + return git_config_set(cfg, name, value, GIT_VAR_BOOL); +} + +/** + * Set the value of a string config variable. + * + * A copy of the string is made and the user is free to use it + * afterwards. + * + * @param cfg where to look for the variable + * @param name the variable's name + * @param value the string to store. + * @return GIT_SUCCESS on success; error code otherwise + */ +GIT_EXTERN(int) git_config_set_string(git_config *cfg, const char *name, const char *value); + +/** + * Perform an operation on each config variable. + * + * The callback is passed a pointer to a config variable and the data + * pointer passed to this function. As soon as one of the callback + * functions returns something other than 0, this function returns + * that value. + * + * @param cfg where to get the variables from + * @param callback the function to call on each variable + * @param data the data to pass to the callback + * @return GIT_SUCCESS or the return value of the callback which didn't return 0 + */ +GIT_EXTERN(int) git_config_foreach(git_config *cfg, int (*callback)(git_cvar *, void *data), void *data); + /** @} */ GIT_END_DECL #endif diff --git a/src/config.c b/src/config.c index 5f0c34ab7..f9dbda7e9 100644 --- a/src/config.c +++ b/src/config.c @@ -129,6 +129,139 @@ void git_config_free(git_config *cfg) free(cfg); } +/* + * Loop over all the variables + */ + +int git_config_foreach(git_config *cfg, int (*fn)(git_cvar *, void *), void *data) +{ + int ret = GIT_SUCCESS; + git_cvar *var; + void *_unused; + + GIT_HASHTABLE_FOREACH(cfg->vars, _unused, var, + ret = fn(var, data); + if(ret) break; + ); + + return ret; +} + +/* + * Setters + */ + +int git_config_set(git_config *cfg, const char *name, + int value, git_cvar_type type) +{ + git_cvar *var = NULL; + int error = GIT_SUCCESS; + + var = git__malloc(sizeof(git_cvar)); + if(var == NULL){ + error = GIT_ENOMEM; + goto out; + } + + var->name = git__strdup(name); + if(var->name == NULL){ + error = GIT_ENOMEM; + free(var); + goto out; + } + + var->type = type; + if(type == GIT_VAR_BOOL) + var->value.boolean = value; + else + var->value.integer = value; + + error = git_hashtable_insert(cfg->vars, var->name, var); + if(error < GIT_SUCCESS) + cvar_free(var); + + out: + return error; +} + +int git_config_set_string(git_config *cfg, const char *name, const char *value) +{ + git_cvar *var = NULL; + int error = GIT_SUCCESS; + + var = git__malloc(sizeof(git_cvar)); + if(var == NULL){ + error = GIT_ENOMEM; + goto out; + } + + var->name = git__strdup(name); + if(var->name == NULL){ + error = GIT_ENOMEM; + free(var); + goto out; + } + + var->value.string = git__strdup(value); + if(var->value.string == NULL){ + error = GIT_ENOMEM; + cvar_free(var); + goto out; + } + + var->type = GIT_VAR_STR; + + error = git_hashtable_insert(cfg->vars, var->name, var); + if(error < GIT_SUCCESS) + cvar_free(var); + + out: + return error; +} + + +/* + * Get a config variable's data. + */ +int git_config_get(git_config *cfg, const char *name, + int *out, git_cvar_type type) +{ + git_cvar *var; + int error = GIT_SUCCESS; + + var = git_hashtable_lookup(cfg->vars, name); + if (var == NULL) { + error = GIT_ENOTFOUND; + } else { + if (var->type == type) + *out = type == GIT_VAR_INT ? + var->value.integer : var->value.boolean; + else + error = GIT_EINVALIDTYPE; + } + return error; +} + +int git_config_get_string(git_config *cfg, const char *name, const char **out) +{ + git_cvar *var; + int error = GIT_SUCCESS; + + var = git_hashtable_lookup(cfg->vars, name); + if (var == NULL) { + error = GIT_ENOTFOUND; + goto out; + } else if (var->type != GIT_VAR_STR) { + error = GIT_EINVALIDTYPE; + goto out; + } + + *out = var->value.string; + + out: + return error; +} + static int cfg_getchar_raw(git_config *cfg) { int c;