Commit 3e72809b5ec73b3aa416f3b12d6fd066f83dcb79

Vicent Martí 2011-12-16T01:06:01

Merge pull request #513 from carlosmn/development Really delete variables

diff --git a/include/git2/config.h b/include/git2/config.h
index 3664759..f78fe40 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 2e341d2..ed7c947 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 45b43b7..207bd2b 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;