diff --git a/include/git2/config.h b/include/git2/config.h index 36647591a..f78fe40a0 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -30,6 +30,7 @@ struct git_config_file { int (*open)(struct git_config_file *); int (*get)(struct git_config_file *, const char *key, const char **value); int (*set)(struct git_config_file *, const char *key, const char *value); + int (*delete)(struct git_config_file *, const char *key); int (*foreach)(struct git_config_file *, int (*fn)(const char *, const char *, void *), void *data); void (*free)(struct git_config_file *); }; diff --git a/src/config.c b/src/config.c index 2e341d256..ed7c947ed 100644 --- a/src/config.c +++ b/src/config.c @@ -162,7 +162,16 @@ int git_config_foreach(git_config *cfg, int (*fn)(const char *, const char *, vo int git_config_delete(git_config *cfg, const char *name) { - return git_config_set_string(cfg, name, NULL); + file_internal *internal; + git_config_file *file; + + if (cfg->files.length == 0) + return git__throw(GIT_EINVALIDARGS, "Cannot delete variable; no files open in the `git_config` instance"); + + internal = git_vector_get(&cfg->files, 0); + file = internal->file; + + return file->delete(file, name); } /************** diff --git a/src/config_file.c b/src/config_file.c index 45b43b7b8..207bd2bdd 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -391,15 +391,43 @@ static int config_set(git_config_file *cfg, const char *name, const char *value) static int config_get(git_config_file *cfg, const char *name, const char **out) { cvar_t *var; + int error = GIT_SUCCESS; diskfile_backend *b = (diskfile_backend *)cfg; var = cvar_list_find(&b->var_list, name); - if (var == NULL || var->value == NULL) + if (var == NULL) return git__throw(GIT_ENOTFOUND, "Variable '%s' not found", name); *out = var->value; - return GIT_SUCCESS; + + return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to get config value for %s", name); +} + +static int config_delete(git_config_file *cfg, const char *name) +{ + cvar_t *iter, *prev; + diskfile_backend *b = (diskfile_backend *)cfg; + + CVAR_LIST_FOREACH (&b->var_list, iter) { + /* This is a bit hacky because we use a singly-linked list */ + if (cvar_match_name(iter, name)) { + if (CVAR_LIST_HEAD(&b->var_list) == iter) + CVAR_LIST_HEAD(&b->var_list) = CVAR_LIST_NEXT(iter); + else + CVAR_LIST_REMOVE_AFTER(prev); + + git__free(iter->value); + iter->value = NULL; + config_write(b, iter); + cvar_free(iter); + return GIT_SUCCESS; + } + /* Store it for the next round */ + prev = iter; + } + + return git__throw(GIT_ENOTFOUND, "Variable '%s' not found", name); } int git_config_file__ondisk(git_config_file **out, const char *path) @@ -421,6 +449,7 @@ int git_config_file__ondisk(git_config_file **out, const char *path) backend->parent.open = config_open; backend->parent.get = config_get; backend->parent.set = config_set; + backend->parent.delete = config_delete; backend->parent.foreach = file_foreach; backend->parent.free = backend_free;