diff options
| author | Carlos Martín Nieto <cmn@dwim.me> | 2013-08-08 16:18:07 +0200 | 
|---|---|---|
| committer | Carlos Martín Nieto <cmn@dwim.me> | 2013-08-08 16:18:07 +0200 | 
| commit | 3a7ffc29c9416c5d182835c7f18c04437366f218 (patch) | |
| tree | b977e17df23436ebb15521bbfc280ec102be6ee0 | |
| parent | eba7399251cfa95d9346b9b41ca78dc5d43a840d (diff) | |
| download | libgit2-3a7ffc29c9416c5d182835c7f18c04437366f218.tar.gz | |
config: initial multivar iterator
| -rw-r--r-- | include/git2/sys/config.h | 6 | ||||
| -rw-r--r-- | src/config.c | 18 | ||||
| -rw-r--r-- | src/config_file.c | 90 | 
3 files changed, 112 insertions, 2 deletions
| diff --git a/include/git2/sys/config.h b/include/git2/sys/config.h index 45599dc69..477d47271 100644 --- a/include/git2/sys/config.h +++ b/include/git2/sys/config.h @@ -36,9 +36,10 @@ struct git_config_iterator {  	unsigned int flags;  	/** -	 * Return the current entry and advance the iterator +	 * Return the current entry and advance the iterator. The +	 * memory belongs to the library.  	 */ -	int (*next)(git_config_entry *entry, git_config_iterator *iter); +	int (*next)(const git_config_entry *entry, git_config_iterator *iter);  	/**  	 * Free the iterator @@ -58,6 +59,7 @@ struct git_config_backend {  	int (*open)(struct git_config_backend *, git_config_level_t level);  	int (*get)(const struct git_config_backend *, const char *key, const git_config_entry **entry);  	int (*get_multivar_foreach)(struct git_config_backend *, const char *key, const char *regexp, git_config_foreach_cb callback, void *payload); +	int (*get_multivar)(git_config_iterator **, struct git_config_backend *, const char *name, const char *regexp);  	int (*set)(struct git_config_backend *, const char *key, const char *value);  	int (*set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value);  	int (*del)(struct git_config_backend *, const char *key); diff --git a/src/config.c b/src/config.c index 5bec0f040..77c558022 100644 --- a/src/config.c +++ b/src/config.c @@ -602,6 +602,24 @@ int git_config_get_multivar_foreach(  	return (ret == GIT_ENOTFOUND) ? config_error_notfound(name) : 0;  } +struct config_multivar_iter { +	git_config_iterator parent; +}; + +int git_config_get_multivar(git_config_iterator **out, const git_config *cfg, const char *name, const char *regexp) +{ +	struct config_multivar_iter *iter; + +	iter = git__calloc(1, sizeof(struct config_multivar_iter)); +	GITERR_CHECK_ALLOC(iter); + +	/* get multivar from each */ + +	*out = (git_config_iterator *) iter; + +	return 0; +} +  int git_config_set_multivar(git_config *cfg, const char *name, const char *regexp, const char *value)  {  	git_config_backend *file; diff --git a/src/config_file.c b/src/config_file.c index 3e0c6cc0b..5559bd406 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -416,6 +416,95 @@ static int config_get(const git_config_backend *cfg, const char *name, const git  	return 0;  } +typedef struct { +	git_config_iterator parent; +	cvar_t *var; +	regex_t regex; +	int have_regex; +} foreach_iter; + +static void foreach_iter_free(git_config_iterator *_iter) +{ +	foreach_iter *iter = (foreach_iter *) _iter; + +	if (iter->have_regex) +		regfree(&iter->regex); + +	git__free(iter); +} + +static int foreach_iter_next(git_config_entry **out, git_config_iterator *_iter) +{ +	foreach_iter *iter = (foreach_iter *) _iter; + +	cvar_t* var = iter->var; + +	if (var == NULL) +		return GIT_ITEROVER; + +	if (!iter->have_regex) { +		*out = var->entry; +		iter->var = var->next; +		return 0; +	} + +	/* For the regex case, we must loop until we find something we like */ +	do { +		git_config_entry *entry = var->entry; +		regex_t *regex = &iter->regex;; +		if (regexec(regex, entry->value, 0, NULL, 0) == 0) { +			*out = entry; +			return 0; +		} +	} while(var != NULL); + +	return GIT_ITEROVER; +} + +static int config_get_multivar(git_config_iterator **out, git_config_backend *_backend, +			       const char *name, const char *regexp) +{ +	foreach_iter *iter; +	diskfile_backend *b = (diskfile_backend *) _backend; + +	char *key; +	khiter_t pos; +	int error = 0; + +	if ((error = normalize_name(name, &key)) < 0) +		return error; + +	pos = git_strmap_lookup_index(b->values, key); +	git__free(key); + +	if (!git_strmap_valid_index(b->values, pos)) +		return GIT_ENOTFOUND; + +	iter = git__calloc(1, sizeof(foreach_iter)); +	GITERR_CHECK_ALLOC(iter); + +	iter->var = git_strmap_value_at(b->values, pos); + +	if (regexp != NULL) { +		int result; + +		result = regcomp(&iter->regex, regexp, REG_EXTENDED); +		if (result < 0) { +			giterr_set_regex(&iter->regex, result); +			regfree(&iter->regex); +			return -1; +		} +		iter->have_regex = 1; +	} + +	iter->parent.free = foreach_iter_free; +	iter->parent.next = foreach_iter_next; + +	*out = (git_config_iterator *) iter; + +	return 0; + } +  static int config_get_multivar_foreach(  	git_config_backend *cfg,  	const char *name, @@ -607,6 +696,7 @@ int git_config_file__ondisk(git_config_backend **out, const char *path)  	backend->parent.open = config_open;  	backend->parent.get = config_get;  	backend->parent.get_multivar_foreach = config_get_multivar_foreach; +	backend->parent.get_multivar = config_get_multivar;  	backend->parent.set = config_set;  	backend->parent.set_multivar = config_set_multivar;  	backend->parent.del = config_delete; | 
