mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-03 17:57:25 +00:00
config: working multivar iterator
Implement the foreach version as a wrapper around the iterator.
This commit is contained in:
parent
cca5df6376
commit
99dfb538ad
@ -341,6 +341,16 @@ GIT_EXTERN(int) git_config_get_string(const char **out, const git_config *cfg, c
|
|||||||
*/
|
*/
|
||||||
GIT_EXTERN(int) git_config_get_multivar_foreach(const git_config *cfg, const char *name, const char *regexp, git_config_foreach_cb callback, void *payload);
|
GIT_EXTERN(int) git_config_get_multivar_foreach(const git_config *cfg, const char *name, const char *regexp, git_config_foreach_cb callback, void *payload);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get each value of a multivar
|
||||||
|
*
|
||||||
|
* @param out pointer to store the iterator
|
||||||
|
* @param cfg where to look for the variable
|
||||||
|
* @param name the variable's name
|
||||||
|
* @param regexp regular expression to filter which variables we're
|
||||||
|
* interested in. Use NULL to indicate all
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_config_get_multivar(git_config_iterator **out, const git_config *cfg, const char *name, const char *regexp);
|
||||||
/**
|
/**
|
||||||
* Set the value of an integer config variable in the config file
|
* Set the value of an integer config variable in the config file
|
||||||
* with the highest level (usually the local one).
|
* with the highest level (usually the local one).
|
||||||
|
@ -39,7 +39,7 @@ struct git_config_iterator {
|
|||||||
* Return the current entry and advance the iterator. The
|
* Return the current entry and advance the iterator. The
|
||||||
* memory belongs to the library.
|
* memory belongs to the library.
|
||||||
*/
|
*/
|
||||||
int (*next)(git_config_entry *entry, git_config_iterator *iter);
|
int (*next)(git_config_entry **entry, git_config_iterator *iter);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Free the iterator
|
* Free the iterator
|
||||||
|
89
src/config.c
89
src/config.c
@ -327,7 +327,7 @@ int git_config_backend_foreach_match(
|
|||||||
int (*fn)(const git_config_entry *, void *),
|
int (*fn)(const git_config_entry *, void *),
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
git_config_entry entry;
|
git_config_entry *entry;
|
||||||
git_config_iterator* iter;
|
git_config_iterator* iter;
|
||||||
regex_t regex;
|
regex_t regex;
|
||||||
int result = 0;
|
int result = 0;
|
||||||
@ -347,11 +347,11 @@ int git_config_backend_foreach_match(
|
|||||||
|
|
||||||
while(!(iter->next(&entry, iter) < 0)) {
|
while(!(iter->next(&entry, iter) < 0)) {
|
||||||
/* skip non-matching keys if regexp was provided */
|
/* skip non-matching keys if regexp was provided */
|
||||||
if (regexp && regexec(®ex, entry.name, 0, NULL, 0) != 0)
|
if (regexp && regexec(®ex, entry->name, 0, NULL, 0) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* abort iterator on non-zero return value */
|
/* abort iterator on non-zero return value */
|
||||||
if (fn(&entry, data)) {
|
if (fn(entry, data)) {
|
||||||
giterr_clear();
|
giterr_clear();
|
||||||
result = GIT_EUSER;
|
result = GIT_EUSER;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -578,35 +578,36 @@ int git_config_get_multivar_foreach(
|
|||||||
const git_config *cfg, const char *name, const char *regexp,
|
const git_config *cfg, const char *name, const char *regexp,
|
||||||
git_config_foreach_cb cb, void *payload)
|
git_config_foreach_cb cb, void *payload)
|
||||||
{
|
{
|
||||||
file_internal *internal;
|
int err, found;
|
||||||
git_config_backend *file;
|
git_config_iterator *iter;
|
||||||
int ret = GIT_ENOTFOUND, err;
|
git_config_entry *entry;
|
||||||
size_t i;
|
|
||||||
|
|
||||||
/*
|
if ((err = git_config_get_multivar(&iter, cfg, name, regexp)) < 0)
|
||||||
* This loop runs the "wrong" way 'round because we need to
|
return err;
|
||||||
* look at every value from the most general to most specific
|
|
||||||
*/
|
|
||||||
for (i = cfg->files.length; i > 0; --i) {
|
|
||||||
internal = git_vector_get(&cfg->files, i - 1);
|
|
||||||
if (!internal || !internal->file)
|
|
||||||
continue;
|
|
||||||
file = internal->file;
|
|
||||||
|
|
||||||
if (!(err = file->get_multivar_foreach(file, name, regexp, cb, payload)))
|
found = 0;
|
||||||
ret = 0;
|
while ((err = iter->next(&entry, iter)) == 0) {
|
||||||
else if (err != GIT_ENOTFOUND)
|
found = 1;
|
||||||
return err;
|
if(cb(entry, payload)) {
|
||||||
|
iter->free(iter);
|
||||||
|
return GIT_EUSER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ret == GIT_ENOTFOUND) ? config_error_notfound(name) : 0;
|
if (err == GIT_ITEROVER)
|
||||||
|
err = 0;
|
||||||
|
|
||||||
|
if (found == 0 && err == 0)
|
||||||
|
err = config_error_notfound(name);
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
git_config_iterator parent;
|
git_config_iterator parent;
|
||||||
git_config_iterator *current;
|
git_config_iterator *current;
|
||||||
const char *name;
|
char *name;
|
||||||
const char *regexp;
|
char *regexp;
|
||||||
const git_config *cfg;
|
const git_config *cfg;
|
||||||
size_t i;
|
size_t i;
|
||||||
} multivar_iter;
|
} multivar_iter;
|
||||||
@ -627,7 +628,7 @@ static int find_next_backend(size_t *out, const git_config *cfg, size_t i)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int multivar_iter_next_empty(git_config_entry *entry, git_config_iterator *_iter)
|
static int multivar_iter_next_empty(git_config_entry **entry, git_config_iterator *_iter)
|
||||||
{
|
{
|
||||||
GIT_UNUSED(entry);
|
GIT_UNUSED(entry);
|
||||||
GIT_UNUSED(_iter);
|
GIT_UNUSED(_iter);
|
||||||
@ -635,20 +636,21 @@ static int multivar_iter_next_empty(git_config_entry *entry, git_config_iterator
|
|||||||
return GIT_ITEROVER;
|
return GIT_ITEROVER;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int multivar_iter_next(git_config_entry *entry, git_config_iterator *_iter)
|
static int multivar_iter_next(git_config_entry **entry, git_config_iterator *_iter)
|
||||||
{
|
{
|
||||||
multivar_iter *iter = (multivar_iter *) _iter;
|
multivar_iter *iter = (multivar_iter *) _iter;
|
||||||
git_config_iterator *current = iter->current;
|
git_config_iterator *current = iter->current;
|
||||||
file_internal *internal;
|
file_internal *internal;
|
||||||
git_config_backend *backend;
|
git_config_backend *backend;
|
||||||
size_t i;
|
size_t i;
|
||||||
int error;
|
int error = 0;
|
||||||
|
|
||||||
if (current != NULL &&
|
if (current != NULL &&
|
||||||
(error = current->next(entry, current)) == 0)
|
(error = current->next(entry, current)) == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (error != GIT_ITEROVER)
|
if (error < 0 && error != GIT_ITEROVER)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@ -657,10 +659,15 @@ static int multivar_iter_next(git_config_entry *entry, git_config_iterator *_ite
|
|||||||
|
|
||||||
internal = git_vector_get(&iter->cfg->files, i - 1);
|
internal = git_vector_get(&iter->cfg->files, i - 1);
|
||||||
backend = internal->file;
|
backend = internal->file;
|
||||||
if ((error = backend->get_multivar(&iter->current, backend, iter->name, iter->regexp)) < 0)
|
iter->i = i - 1;
|
||||||
return -1;
|
|
||||||
|
error = backend->get_multivar(&iter->current, backend, iter->name, iter->regexp);
|
||||||
|
if (error == GIT_ENOTFOUND)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (error < 0)
|
||||||
|
return error;
|
||||||
|
|
||||||
iter->i = i;
|
|
||||||
return iter->current->next(entry, iter->current);
|
return iter->current->next(entry, iter->current);
|
||||||
|
|
||||||
} while(1);
|
} while(1);
|
||||||
@ -668,6 +675,15 @@ static int multivar_iter_next(git_config_entry *entry, git_config_iterator *_ite
|
|||||||
return GIT_ITEROVER;
|
return GIT_ITEROVER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void multivar_iter_free(git_config_iterator *_iter)
|
||||||
|
{
|
||||||
|
multivar_iter *iter = (multivar_iter *) _iter;
|
||||||
|
|
||||||
|
git__free(iter->name);
|
||||||
|
git__free(iter->regexp);
|
||||||
|
git__free(iter);
|
||||||
|
}
|
||||||
|
|
||||||
int git_config_get_multivar(git_config_iterator **out, const git_config *cfg, const char *name, const char *regexp)
|
int git_config_get_multivar(git_config_iterator **out, const git_config *cfg, const char *name, const char *regexp)
|
||||||
{
|
{
|
||||||
multivar_iter *iter;
|
multivar_iter *iter;
|
||||||
@ -676,6 +692,15 @@ int git_config_get_multivar(git_config_iterator **out, const git_config *cfg, co
|
|||||||
iter = git__calloc(1, sizeof(multivar_iter));
|
iter = git__calloc(1, sizeof(multivar_iter));
|
||||||
GITERR_CHECK_ALLOC(iter);
|
GITERR_CHECK_ALLOC(iter);
|
||||||
|
|
||||||
|
iter->name = git__strdup(name);
|
||||||
|
GITERR_CHECK_ALLOC(iter->name);
|
||||||
|
|
||||||
|
if (regexp != NULL) {
|
||||||
|
iter->regexp = git__strdup(regexp);
|
||||||
|
GITERR_CHECK_ALLOC(iter->regexp);
|
||||||
|
}
|
||||||
|
|
||||||
|
iter->parent.free = multivar_iter_free;
|
||||||
if (find_next_backend(&i, cfg, cfg->files.length) < 0)
|
if (find_next_backend(&i, cfg, cfg->files.length) < 0)
|
||||||
iter->parent.next = multivar_iter_next_empty;
|
iter->parent.next = multivar_iter_next_empty;
|
||||||
else
|
else
|
||||||
@ -683,8 +708,6 @@ int git_config_get_multivar(git_config_iterator **out, const git_config *cfg, co
|
|||||||
|
|
||||||
iter->i = cfg->files.length;
|
iter->i = cfg->files.length;
|
||||||
iter->cfg = cfg;
|
iter->cfg = cfg;
|
||||||
iter->name = name;
|
|
||||||
iter->regexp = regexp;
|
|
||||||
|
|
||||||
*out = (git_config_iterator *) iter;
|
*out = (git_config_iterator *) iter;
|
||||||
|
|
||||||
|
@ -261,7 +261,7 @@ static void config_iterator_free(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int config_iterator_next(
|
static int config_iterator_next(
|
||||||
git_config_entry *entry,
|
git_config_entry **entry,
|
||||||
git_config_iterator *iter)
|
git_config_iterator *iter)
|
||||||
{
|
{
|
||||||
git_config_file_iter *it = (git_config_file_iter *) iter;
|
git_config_file_iter *it = (git_config_file_iter *) iter;
|
||||||
@ -282,9 +282,7 @@ static int config_iterator_next(
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
entry->name = key;
|
*entry = var->entry;
|
||||||
entry->value = var->entry->value;
|
|
||||||
entry->level = var->entry->level;
|
|
||||||
it->next_var = CVAR_LIST_NEXT(var);
|
it->next_var = CVAR_LIST_NEXT(var);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -433,19 +431,18 @@ static void foreach_iter_free(git_config_iterator *_iter)
|
|||||||
git__free(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;
|
foreach_iter *iter = (foreach_iter *) _iter;
|
||||||
|
|
||||||
cvar_t* var = iter->var;
|
cvar_t* var = iter->var;
|
||||||
|
|
||||||
|
|
||||||
if (var == NULL)
|
if (var == NULL)
|
||||||
return GIT_ITEROVER;
|
return GIT_ITEROVER;
|
||||||
|
|
||||||
if (!iter->have_regex) {
|
if (!iter->have_regex) {
|
||||||
out->name = var->entry->name;
|
*out = var->entry;
|
||||||
out->value = var->entry->value;
|
|
||||||
|
|
||||||
iter->var = var->next;
|
iter->var = var->next;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -455,10 +452,11 @@ static int foreach_iter_next(git_config_entry *out, git_config_iterator *_iter)
|
|||||||
git_config_entry *entry = var->entry;
|
git_config_entry *entry = var->entry;
|
||||||
regex_t *regex = &iter->regex;;
|
regex_t *regex = &iter->regex;;
|
||||||
if (regexec(regex, entry->value, 0, NULL, 0) == 0) {
|
if (regexec(regex, entry->value, 0, NULL, 0) == 0) {
|
||||||
out->name = entry->name;
|
*out = entry;
|
||||||
out->value = entry->value;
|
iter->var = var->next;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
var = var->next;
|
||||||
} while(var != NULL);
|
} while(var != NULL);
|
||||||
|
|
||||||
return GIT_ITEROVER;
|
return GIT_ITEROVER;
|
||||||
@ -550,7 +548,7 @@ static int config_get_multivar_foreach(
|
|||||||
if (regexec(®ex, var->entry->value, 0, NULL, 0) == 0) {
|
if (regexec(®ex, var->entry->value, 0, NULL, 0) == 0) {
|
||||||
/* early termination by the user is not an error;
|
/* early termination by the user is not an error;
|
||||||
* just break and return successfully */
|
* just break and return successfully */
|
||||||
if (fn(var->entry, data) < 0)
|
if (fn(var->entry, data))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,11 +114,11 @@ void test_config_multivar__add(void)
|
|||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n));
|
cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n));
|
||||||
cl_assert(n == 3);
|
cl_assert_equal_i(n, 3);
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n));
|
cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n));
|
||||||
cl_assert(n == 1);
|
cl_assert_equal_i(n, 1);
|
||||||
|
|
||||||
git_config_free(cfg);
|
git_config_free(cfg);
|
||||||
|
|
||||||
@ -128,11 +128,11 @@ void test_config_multivar__add(void)
|
|||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n));
|
cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n));
|
||||||
cl_assert(n == 3);
|
cl_assert_equal_i(n, 3);
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n));
|
cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n));
|
||||||
cl_assert(n == 1);
|
cl_assert_equal_i(n, 1);
|
||||||
|
|
||||||
git_config_free(cfg);
|
git_config_free(cfg);
|
||||||
}
|
}
|
||||||
@ -148,7 +148,7 @@ void test_config_multivar__add_new(void)
|
|||||||
cl_git_pass(git_config_set_multivar(cfg, var, "", "variable"));
|
cl_git_pass(git_config_set_multivar(cfg, var, "", "variable"));
|
||||||
n = 0;
|
n = 0;
|
||||||
cl_git_pass(git_config_get_multivar_foreach(cfg, var, NULL, cb, &n));
|
cl_git_pass(git_config_get_multivar_foreach(cfg, var, NULL, cb, &n));
|
||||||
cl_assert(n == 1);
|
cl_assert_equal_i(n, 1);
|
||||||
|
|
||||||
git_config_free(cfg);
|
git_config_free(cfg);
|
||||||
}
|
}
|
||||||
@ -191,7 +191,7 @@ void test_config_multivar__replace_multiple(void)
|
|||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n));
|
cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n));
|
||||||
cl_assert(n == 2);
|
cl_assert_equal_i(n, 2);
|
||||||
|
|
||||||
git_config_free(cfg);
|
git_config_free(cfg);
|
||||||
|
|
||||||
@ -199,7 +199,7 @@ void test_config_multivar__replace_multiple(void)
|
|||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n));
|
cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n));
|
||||||
cl_assert(n == 2);
|
cl_assert_equal_i(n, 2);
|
||||||
|
|
||||||
git_config_free(cfg);
|
git_config_free(cfg);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user