mirror of
https://git.proxmox.com/git/libgit2
synced 2026-01-04 13:37:18 +00:00
config: introduce a regex-filtering iterator
This commit is contained in:
parent
5880962d90
commit
54f3a572b4
@ -463,6 +463,18 @@ GIT_EXTERN(int) git_config_foreach(
|
||||
*/
|
||||
GIT_EXTERN(int) git_config_iterator_new(git_config_iterator **out, const git_config *cfg);
|
||||
|
||||
/**
|
||||
* Iterate over all the config variables whose name matches a pattern
|
||||
*
|
||||
* 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
|
||||
* @param regexp regular expression to match the names
|
||||
*/
|
||||
GIT_EXTERN(int) git_config_iterator_glob_new(git_config_iterator **out, const git_config *cfg, const char *regexp);
|
||||
|
||||
/**
|
||||
* Perform an operation on each config variable matching a regular expression.
|
||||
*
|
||||
|
||||
61
src/config.c
61
src/config.c
@ -319,6 +319,8 @@ typedef struct {
|
||||
git_config_iterator parent;
|
||||
git_config_iterator *current;
|
||||
const git_config *cfg;
|
||||
regex_t regex;
|
||||
int has_regex;
|
||||
size_t i;
|
||||
} all_iter;
|
||||
|
||||
@ -380,6 +382,27 @@ static int all_iter_next(git_config_entry **entry, git_config_iterator *_iter)
|
||||
return GIT_ITEROVER;
|
||||
}
|
||||
|
||||
static int all_iter_glob_next(git_config_entry **entry, git_config_iterator *_iter)
|
||||
{
|
||||
int error;
|
||||
all_iter *iter = (all_iter *) _iter;
|
||||
|
||||
/*
|
||||
* We use the "normal" function to grab the next one across
|
||||
* backends and then apply the regex
|
||||
*/
|
||||
while ((error = all_iter_next(entry, _iter)) == 0) {
|
||||
/* skip non-matching keys if regexp was provided */
|
||||
if (regexec(&iter->regex, (*entry)->name, 0, NULL, 0) != 0)
|
||||
continue;
|
||||
|
||||
/* and simply return if we like the entry's name */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void all_iter_free(git_config_iterator *_iter)
|
||||
{
|
||||
all_iter *iter = (all_iter *) _iter;
|
||||
@ -390,6 +413,14 @@ static void all_iter_free(git_config_iterator *_iter)
|
||||
git__free(iter);
|
||||
}
|
||||
|
||||
static void all_iter_glob_free(git_config_iterator *_iter)
|
||||
{
|
||||
all_iter *iter = (all_iter *) _iter;
|
||||
|
||||
regfree(&iter->regex);
|
||||
all_iter_free(_iter);
|
||||
}
|
||||
|
||||
int git_config_iterator_new(git_config_iterator **out, const git_config *cfg)
|
||||
{
|
||||
all_iter *iter;
|
||||
@ -408,6 +439,36 @@ int git_config_iterator_new(git_config_iterator **out, const git_config *cfg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_config_iterator_glob_new(git_config_iterator **out, const git_config *cfg, const char *regexp)
|
||||
{
|
||||
all_iter *iter;
|
||||
int result;
|
||||
|
||||
iter = git__calloc(1, sizeof(all_iter));
|
||||
GITERR_CHECK_ALLOC(iter);
|
||||
|
||||
if (regexp != NULL) {
|
||||
if ((result = regcomp(&iter->regex, regexp, REG_EXTENDED)) < 0) {
|
||||
giterr_set_regex(&iter->regex, result);
|
||||
regfree(&iter->regex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
iter->parent.next = all_iter_glob_next;
|
||||
} else {
|
||||
iter->parent.next = all_iter_next;
|
||||
}
|
||||
|
||||
iter->parent.free = all_iter_glob_free;
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
@ -265,6 +265,7 @@ void test_config_read__iterator(void)
|
||||
count++;
|
||||
}
|
||||
|
||||
git_config_iterator_free(iter);
|
||||
cl_assert_equal_i(GIT_ITEROVER, ret);
|
||||
cl_assert_equal_i(7, count);
|
||||
|
||||
@ -318,6 +319,38 @@ void test_config_read__foreach_match(void)
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
static void check_glob_iter(git_config *cfg, const char *regexp, int expected)
|
||||
{
|
||||
git_config_iterator *iter;
|
||||
git_config_entry *entry;
|
||||
int count, error;
|
||||
|
||||
cl_git_pass(git_config_iterator_glob_new(&iter, cfg, regexp));
|
||||
|
||||
count = 0;
|
||||
while ((error = git_config_next(&entry, iter)) == 0)
|
||||
count++;
|
||||
|
||||
cl_assert_equal_i(GIT_ITEROVER, error);
|
||||
cl_assert_equal_i(expected, count);
|
||||
git_config_iterator_free(iter);
|
||||
}
|
||||
|
||||
void test_config_read__iterator_glob(void)
|
||||
{
|
||||
git_config *cfg;
|
||||
|
||||
cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config9")));
|
||||
|
||||
check_glob_iter(cfg, "core.*", 3);
|
||||
check_glob_iter(cfg, "remote\\.ab.*", 2);
|
||||
check_glob_iter(cfg, ".*url$", 2);
|
||||
check_glob_iter(cfg, ".*dummy.*", 2);
|
||||
check_glob_iter(cfg, ".*nomatch.*", 0);
|
||||
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
void test_config_read__whitespace_not_required_around_assignment(void)
|
||||
{
|
||||
git_config *cfg;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user