From cca5df6376fd41fb4fbbb9f8a9ff87c38079dfd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 8 Aug 2013 16:59:39 +0200 Subject: [PATCH] config: hopefully get the iterator to work on multivars --- include/git2/sys/config.h | 2 +- src/config.c | 81 ++++++++++++++++++++++++++++++++++++--- src/config_file.c | 9 +++-- 3 files changed, 83 insertions(+), 9 deletions(-) diff --git a/include/git2/sys/config.h b/include/git2/sys/config.h index 477d47271..d5b450a6c 100644 --- a/include/git2/sys/config.h +++ b/include/git2/sys/config.h @@ -39,7 +39,7 @@ struct git_config_iterator { * Return the current entry and advance the iterator. The * memory belongs to the library. */ - int (*next)(const git_config_entry *entry, git_config_iterator *iter); + int (*next)(git_config_entry *entry, git_config_iterator *iter); /** * Free the iterator diff --git a/src/config.c b/src/config.c index 77c558022..f34d5dd29 100644 --- a/src/config.c +++ b/src/config.c @@ -602,18 +602,89 @@ int git_config_get_multivar_foreach( return (ret == GIT_ENOTFOUND) ? config_error_notfound(name) : 0; } -struct config_multivar_iter { +typedef struct { git_config_iterator parent; -}; + git_config_iterator *current; + const char *name; + const char *regexp; + const git_config *cfg; + size_t i; +} multivar_iter; + +static int find_next_backend(size_t *out, const git_config *cfg, size_t i) +{ + file_internal *internal; + + for (; i > 0; --i) { + internal = git_vector_get(&cfg->files, i - 1); + if (!internal || !internal->file) + continue; + + *out = i; + return 0; + } + + return -1; +} + +static int multivar_iter_next_empty(git_config_entry *entry, git_config_iterator *_iter) +{ + GIT_UNUSED(entry); + GIT_UNUSED(_iter); + + return GIT_ITEROVER; +} + +static int multivar_iter_next(git_config_entry *entry, git_config_iterator *_iter) +{ + multivar_iter *iter = (multivar_iter *) _iter; + git_config_iterator *current = iter->current; + file_internal *internal; + git_config_backend *backend; + size_t i; + int error; + + if (current != NULL && + (error = current->next(entry, current)) == 0) + return 0; + + if (error != GIT_ITEROVER) + return error; + + do { + if (find_next_backend(&i, iter->cfg, iter->i) < 0) + return GIT_ITEROVER; + + internal = git_vector_get(&iter->cfg->files, i - 1); + backend = internal->file; + if ((error = backend->get_multivar(&iter->current, backend, iter->name, iter->regexp)) < 0) + return -1; + + iter->i = i; + return iter->current->next(entry, iter->current); + + } while(1); + + return GIT_ITEROVER; +} int git_config_get_multivar(git_config_iterator **out, const git_config *cfg, const char *name, const char *regexp) { - struct config_multivar_iter *iter; + multivar_iter *iter; + size_t i; - iter = git__calloc(1, sizeof(struct config_multivar_iter)); + iter = git__calloc(1, sizeof(multivar_iter)); GITERR_CHECK_ALLOC(iter); - /* get multivar from each */ + if (find_next_backend(&i, cfg, cfg->files.length) < 0) + iter->parent.next = multivar_iter_next_empty; + else + iter->parent.next = multivar_iter_next; + + iter->i = cfg->files.length; + iter->cfg = cfg; + iter->name = name; + iter->regexp = regexp; *out = (git_config_iterator *) iter; diff --git a/src/config_file.c b/src/config_file.c index 5559bd406..74b200073 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -433,7 +433,7 @@ static void foreach_iter_free(git_config_iterator *_iter) git__free(iter); } -static int foreach_iter_next(git_config_entry **out, git_config_iterator *_iter) +static int foreach_iter_next(git_config_entry *out, git_config_iterator *_iter) { foreach_iter *iter = (foreach_iter *) _iter; @@ -443,7 +443,9 @@ static int foreach_iter_next(git_config_entry **out, git_config_iterator *_iter) return GIT_ITEROVER; if (!iter->have_regex) { - *out = var->entry; + out->name = var->entry->name; + out->value = var->entry->value; + iter->var = var->next; return 0; } @@ -453,7 +455,8 @@ static int foreach_iter_next(git_config_entry **out, git_config_iterator *_iter) git_config_entry *entry = var->entry; regex_t *regex = &iter->regex;; if (regexec(regex, entry->value, 0, NULL, 0) == 0) { - *out = entry; + out->name = entry->name; + out->value = entry->value; return 0; } } while(var != NULL);