config: hopefully get the iterator to work on multivars
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
diff --git a/include/git2/sys/config.h b/include/git2/sys/config.h
index 477d472..d5b450a 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 77c5580..f34d5dd 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 5559bd4..74b2000 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);