Thread (6 messages) 6 messages, 1 author, 2016-06-15

[PATCH/RFC 3/5] add "unset.variable" for unsetting previously set variables

flat view
DORMANTno replies

From: Tanay Abhra <hidden>
Date: 2016-06-15 23:02:38
Subsystem: the rest · Maintainer: Linus Torvalds

Add a new config variable "unset.variable" which unsets previously set
variables. It affects `git_config()` and `git_config_get_*()` family
of functions. It removes the matching variables from the `configset`
which were added previously. Those matching variables which come after
the "unset.variable" in parsing order will not be deleted and will
be left untouched.

It affects the result of "git config -l" and similar calls.
It may be used in cases where the user can not access the config files,
for example, the system wide config files may be only accessible to
the system administrator. We can unset an unwanted variable declared in
the system config file by using "unset.variable" in a local config file.

for example, /etc/gitconfig may look like this,
	[foo]
		bar = baz

in the repo config file, we will write,
	[unset]
		variable  = foo.bar
to unset foo.bar previously declared in system wide config file.

Helped-by: Matthieu Moy [off-list ref]
Signed-off-by: Tanay Abhra <redacted>
---
 config.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)
diff --git a/config.c b/config.c
index 09cf009..a80832d 100644
--- a/config.c
+++ b/config.c
@@ -1311,6 +1311,38 @@ static struct config_set_element *configset_find_element(struct config_set *cs,
 	return found_entry;
 }
 
+static void delete_config_variable(struct config_set *cs, const char *key, const char *value)
+{
+	char *normalized_value;
+	struct config_set_element *e = NULL;
+	int ret, current = 0, updated = 0;
+	struct configset_list *list = &cs->list;
+	/*
+	 * if we find a key value pair with key as "unset.variable", unset all variables
+	 * in the configset with keys equivalent to the value in "unset.variable".
+	 * unsetting a variable means that the variable is permanently deleted from the
+	 * configset.
+	 */
+	ret = git_config_parse_key(value, &normalized_value, NULL);
+	if (!ret) {
+		/* first remove matching variables from the configset_list */
+		while (current < list->nr) {
+			if (!strcmp(list->items[current].e->key, normalized_value))
+				current++;
+			else
+				list->items[updated++] = list->items[current++];
+		}
+		list->nr = updated;
+		/* then delete the matching entry from the configset hashmap */
+		e = configset_find_element(cs, normalized_value);
+		if (e) {
+			free(e->key);
+			string_list_clear(&e->value_list, 1);
+			hashmap_remove(&cs->config_hash, e, NULL);
+		}
+	}
+}
+
 static int configset_add_value(struct config_set *cs, const char *key, const char *value)
 {
 	struct config_set_element *e;
@@ -1331,6 +1363,8 @@ static int configset_add_value(struct config_set *cs, const char *key, const cha
 		hashmap_add(&cs->config_hash, e);
 	}
 	si = string_list_append_nodup(&e->value_list, value ? xstrdup(value) : NULL);
+	if (!strcmp(key, "unset.variable"))
+		delete_config_variable(cs, key, value);
 
 	ALLOC_GROW(cs->list.items, cs->list.nr + 1, cs->list.alloc);
 	l_item = &cs->list.items[cs->list.nr++];
-- 
1.9.0.GIT
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help