mirror of
https://git.proxmox.com/git/libgit2
synced 2026-01-04 17:30:38 +00:00
config: introduce _iterator_new()
As the name suggests, it iterates over all the entries
This commit is contained in:
parent
a319ffaead
commit
5880962d90
@ -452,6 +452,17 @@ GIT_EXTERN(int) git_config_foreach(
|
||||
git_config_foreach_cb callback,
|
||||
void *payload);
|
||||
|
||||
/**
|
||||
* Iterate over all the config variables
|
||||
*
|
||||
* Use `git_config_next` to advance the iteration and
|
||||
* `git_config_iterator_free` when done.
|
||||
*
|
||||
* @param out pointer to store the iterator
|
||||
* @param cfg where to ge the variables from
|
||||
*/
|
||||
GIT_EXTERN(int) git_config_iterator_new(git_config_iterator **out, const git_config *cfg);
|
||||
|
||||
/**
|
||||
* Perform an operation on each config variable matching a regular expression.
|
||||
*
|
||||
|
||||
123
src/config.c
123
src/config.c
@ -315,6 +315,99 @@ int git_config_refresh(git_config *cfg)
|
||||
* Loop over all the variables
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
git_config_iterator parent;
|
||||
git_config_iterator *current;
|
||||
const git_config *cfg;
|
||||
size_t i;
|
||||
} all_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 all_iter_next(git_config_entry **entry, git_config_iterator *_iter)
|
||||
{
|
||||
all_iter *iter = (all_iter *) _iter;
|
||||
file_internal *internal;
|
||||
git_config_backend *backend;
|
||||
size_t i;
|
||||
int error = 0;
|
||||
|
||||
if (iter->current != NULL &&
|
||||
(error = iter->current->next(entry, iter->current)) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (error < 0 && 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;
|
||||
iter->i = i - 1;
|
||||
|
||||
if (iter->current)
|
||||
iter->current->free(iter->current);
|
||||
|
||||
iter->current = NULL;
|
||||
error = backend->iterator(&iter->current, backend);
|
||||
if (error == GIT_ENOTFOUND)
|
||||
continue;
|
||||
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
return iter->current->next(entry, iter->current);
|
||||
|
||||
} while(1);
|
||||
|
||||
return GIT_ITEROVER;
|
||||
}
|
||||
|
||||
static void all_iter_free(git_config_iterator *_iter)
|
||||
{
|
||||
all_iter *iter = (all_iter *) _iter;
|
||||
|
||||
if (iter->current)
|
||||
iter->current->free(iter->current);
|
||||
|
||||
git__free(iter);
|
||||
}
|
||||
|
||||
int git_config_iterator_new(git_config_iterator **out, const git_config *cfg)
|
||||
{
|
||||
all_iter *iter;
|
||||
|
||||
iter = git__calloc(1, sizeof(all_iter));
|
||||
GITERR_CHECK_ALLOC(iter);
|
||||
|
||||
iter->parent.free = all_iter_free;
|
||||
iter->parent.next = all_iter_next;
|
||||
|
||||
iter->i = cfg->files.length;
|
||||
iter->cfg = cfg;
|
||||
|
||||
*out = (git_config_iterator *) iter;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_config_foreach(
|
||||
const git_config *cfg, git_config_foreach_cb cb, void *payload)
|
||||
{
|
||||
@ -613,30 +706,6 @@ typedef struct {
|
||||
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;
|
||||
@ -695,7 +764,6 @@ void multivar_iter_free(git_config_iterator *_iter)
|
||||
int git_config_get_multivar(git_config_iterator **out, const git_config *cfg, const char *name, const char *regexp)
|
||||
{
|
||||
multivar_iter *iter;
|
||||
size_t i;
|
||||
|
||||
iter = git__calloc(1, sizeof(multivar_iter));
|
||||
GITERR_CHECK_ALLOC(iter);
|
||||
@ -709,10 +777,7 @@ int git_config_get_multivar(git_config_iterator **out, const git_config *cfg, co
|
||||
}
|
||||
|
||||
iter->parent.free = multivar_iter_free;
|
||||
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->parent.next = multivar_iter_next;
|
||||
|
||||
iter->i = cfg->files.length;
|
||||
iter->cfg = cfg;
|
||||
|
||||
@ -279,7 +279,7 @@ static int config_iterator_next(
|
||||
|
||||
if (err < 0) {
|
||||
it->next_var = NULL;
|
||||
return -1;
|
||||
return err;
|
||||
}
|
||||
|
||||
*entry = var->entry;
|
||||
|
||||
@ -245,6 +245,36 @@ void test_config_read__foreach(void)
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
void test_config_read__iterator(void)
|
||||
{
|
||||
git_config *cfg;
|
||||
git_config_iterator *iter;
|
||||
git_config_entry *entry;
|
||||
int count, ret;
|
||||
|
||||
cl_git_pass(git_config_new(&cfg));
|
||||
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"),
|
||||
GIT_CONFIG_LEVEL_SYSTEM, 0));
|
||||
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"),
|
||||
GIT_CONFIG_LEVEL_GLOBAL, 0));
|
||||
|
||||
count = 0;
|
||||
cl_git_pass(git_config_iterator_new(&iter, cfg));
|
||||
|
||||
while ((ret = git_config_next(&entry, iter)) == 0) {
|
||||
count++;
|
||||
}
|
||||
|
||||
cl_assert_equal_i(GIT_ITEROVER, ret);
|
||||
cl_assert_equal_i(7, count);
|
||||
|
||||
count = 3;
|
||||
cl_git_pass(git_config_iterator_new(&iter, cfg));
|
||||
|
||||
git_config_iterator_free(iter);
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
static int count_cfg_entries(const git_config_entry *entry, void *payload)
|
||||
{
|
||||
int *count = payload;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user