mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-03 00:43:41 +00:00
replaced foreach() with non callback based iterations in git_config_backend
new functions in struct git_config_backend: * iterator_new(...) * iterator_free(...) * next(...) The old callback based foreach style can still be used with `git_config_backend_foreach_match`
This commit is contained in:
parent
6385fc5ff5
commit
a603c19157
@ -61,6 +61,7 @@ typedef struct {
|
||||
} git_config_entry;
|
||||
|
||||
typedef int (*git_config_foreach_cb)(const git_config_entry *, void *);
|
||||
typedef struct git_config_backend_iter* git_config_backend_iter;
|
||||
|
||||
typedef enum {
|
||||
GIT_CVAR_FALSE = 0,
|
||||
@ -535,6 +536,25 @@ GIT_EXTERN(int) git_config_parse_int32(int32_t *out, const char *value);
|
||||
GIT_EXTERN(int) git_config_parse_int64(int64_t *out, const char *value);
|
||||
|
||||
|
||||
/**
|
||||
* Perform an operation on each config variable in given config backend
|
||||
* matching a regular expression.
|
||||
*
|
||||
* This behaviors like `git_config_foreach_match` except instead of all config
|
||||
* entries it just enumerates through the given backend entry.
|
||||
*
|
||||
* @param backend where to get the variables from
|
||||
* @param regexp regular expression to match against config names (can be NULL)
|
||||
* @param callback the function to call on each variable
|
||||
* @param payload the data to pass to the callback
|
||||
*/
|
||||
GIT_EXTERN(int) git_config_backend_foreach_match(
|
||||
git_config_backend *backend,
|
||||
const char *regexp,
|
||||
int (*fn)(const git_config_entry *, void *),
|
||||
void *data);
|
||||
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
#endif
|
||||
|
@ -35,7 +35,9 @@ struct git_config_backend {
|
||||
int (*set)(struct git_config_backend *, const char *key, const char *value);
|
||||
int (*set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value);
|
||||
int (*del)(struct git_config_backend *, const char *key);
|
||||
int (*foreach)(struct git_config_backend *, const char *, git_config_foreach_cb callback, void *payload);
|
||||
int (*iterator_new)(git_config_backend_iter **, struct git_config_backend *);
|
||||
void (*iterator_free)(git_config_backend_iter *);
|
||||
int (*next)(git_config_backend_iter *, git_config_entry *, struct git_config_backend *);
|
||||
int (*refresh)(struct git_config_backend *);
|
||||
void (*free)(struct git_config_backend *);
|
||||
};
|
||||
|
46
src/config.c
46
src/config.c
@ -321,6 +321,50 @@ int git_config_foreach(
|
||||
return git_config_foreach_match(cfg, NULL, cb, payload);
|
||||
}
|
||||
|
||||
int git_config_backend_foreach_match(
|
||||
git_config_backend *backend,
|
||||
const char *regexp,
|
||||
int (*fn)(const git_config_entry *, void *),
|
||||
void *data)
|
||||
{
|
||||
git_config_entry entry;
|
||||
git_config_backend_iter iter;
|
||||
regex_t regex;
|
||||
int result = 0;
|
||||
|
||||
if (regexp != NULL) {
|
||||
if ((result = regcomp(®ex, regexp, REG_EXTENDED)) < 0) {
|
||||
giterr_set_regex(®ex, result);
|
||||
regfree(®ex);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (backend->iterator_new(&iter, backend) < 0)
|
||||
return 0;
|
||||
|
||||
while(!(backend->next(&iter, &entry, backend) < 0)) {
|
||||
/* skip non-matching keys if regexp was provided */
|
||||
if (regexp && regexec(®ex, entry.name, 0, NULL, 0) != 0)
|
||||
continue;
|
||||
|
||||
/* abort iterator on non-zero return value */
|
||||
if (fn(&entry, data)) {
|
||||
giterr_clear();
|
||||
result = GIT_EUSER;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (regexp != NULL)
|
||||
regfree(®ex);
|
||||
|
||||
backend->iterator_free(iter);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int git_config_foreach_match(
|
||||
const git_config *cfg,
|
||||
const char *regexp,
|
||||
@ -335,7 +379,7 @@ int git_config_foreach_match(
|
||||
for (i = 0; i < cfg->files.length && ret == 0; ++i) {
|
||||
internal = git_vector_get(&cfg->files, i);
|
||||
file = internal->file;
|
||||
ret = file->foreach(file, regexp, cb, payload);
|
||||
ret = git_config_backend_foreach_match(file, regexp, cb, payload);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -27,6 +27,12 @@ typedef struct cvar_t {
|
||||
git_config_entry *entry;
|
||||
} cvar_t;
|
||||
|
||||
typedef struct git_config_file_iter {
|
||||
git_strmap_iter iter;
|
||||
cvar_t* next;
|
||||
} git_config_file_iter;
|
||||
|
||||
|
||||
#define CVAR_LIST_HEAD(list) ((list)->head)
|
||||
|
||||
#define CVAR_LIST_TAIL(list) ((list)->tail)
|
||||
@ -247,52 +253,60 @@ static void backend_free(git_config_backend *_backend)
|
||||
git__free(backend);
|
||||
}
|
||||
|
||||
static int file_foreach(
|
||||
git_config_backend *backend,
|
||||
const char *regexp,
|
||||
int (*fn)(const git_config_entry *, void *),
|
||||
void *data)
|
||||
static int config_iterator_new(
|
||||
git_config_backend_iter *iter,
|
||||
struct git_config_backend* backend)
|
||||
{
|
||||
diskfile_backend *b = (diskfile_backend *)backend;
|
||||
cvar_t *var, *next_var;
|
||||
const char *key;
|
||||
regex_t regex;
|
||||
int result = 0;
|
||||
git_config_file_iter **it= ((git_config_file_iter**) iter);
|
||||
|
||||
if (!b->values)
|
||||
return 0;
|
||||
if (!b->values || git_strmap_num_entries(b->values) < 1)
|
||||
return -1;
|
||||
|
||||
if (regexp != NULL) {
|
||||
if ((result = regcomp(®ex, regexp, REG_EXTENDED)) < 0) {
|
||||
giterr_set_regex(®ex, result);
|
||||
regfree(®ex);
|
||||
return -1;
|
||||
}
|
||||
*it = git__calloc(1, sizeof(git_config_file_iter));
|
||||
GITERR_CHECK_ALLOC(it);
|
||||
|
||||
(*it)->iter = git_strmap_begin(b->values);
|
||||
(*it)->next = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void config_iterator_free(
|
||||
git_config_backend_iter iter)
|
||||
{
|
||||
git__free(iter);
|
||||
}
|
||||
|
||||
static int config_next(
|
||||
git_config_backend_iter *iter,
|
||||
git_config_entry* entry,
|
||||
struct git_config_backend* backend)
|
||||
{
|
||||
diskfile_backend *b = (diskfile_backend *)backend;
|
||||
git_config_file_iter *it = *((git_config_file_iter**) iter);
|
||||
int err;
|
||||
cvar_t * var;
|
||||
const char* key;
|
||||
|
||||
if (it->next == NULL) {
|
||||
err = git_strmap_next(&key, (void**) &var, &(it->iter), b->values);
|
||||
} else {
|
||||
key = it->next->entry->name;
|
||||
var = it->next;
|
||||
}
|
||||
|
||||
git_strmap_iter iter = git_strmap_begin(b->values);
|
||||
while (!(git_strmap_next(&key, (void**) &var, &iter, b->values) < 0)) {
|
||||
for (; var != NULL; var = next_var) {
|
||||
next_var = CVAR_LIST_NEXT(var);
|
||||
|
||||
/* skip non-matching keys if regexp was provided */
|
||||
if (regexp && regexec(®ex, key, 0, NULL, 0) != 0)
|
||||
continue;
|
||||
|
||||
/* abort iterator on non-zero return value */
|
||||
if (fn(var->entry, data)) {
|
||||
giterr_clear();
|
||||
result = GIT_EUSER;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
if (err < 0) {
|
||||
it->next = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (regexp != NULL)
|
||||
regfree(®ex);
|
||||
entry->name = key;
|
||||
entry->value = var->entry->value;
|
||||
entry->level = var->entry->level;
|
||||
it->next = CVAR_LIST_NEXT(var);
|
||||
|
||||
return result;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config_set(git_config_backend *cfg, const char *name, const char *value)
|
||||
@ -595,7 +609,9 @@ int git_config_file__ondisk(git_config_backend **out, const char *path)
|
||||
backend->parent.set = config_set;
|
||||
backend->parent.set_multivar = config_set_multivar;
|
||||
backend->parent.del = config_delete;
|
||||
backend->parent.foreach = file_foreach;
|
||||
backend->parent.iterator_new = config_iterator_new;
|
||||
backend->parent.iterator_free = config_iterator_free;
|
||||
backend->parent.next = config_next;
|
||||
backend->parent.refresh = config_refresh;
|
||||
backend->parent.free = backend_free;
|
||||
|
||||
|
@ -42,7 +42,7 @@ GIT_INLINE(int) git_config_file_foreach(
|
||||
int (*fn)(const git_config_entry *entry, void *data),
|
||||
void *data)
|
||||
{
|
||||
return cfg->foreach(cfg, NULL, fn, data);
|
||||
return git_config_backend_foreach_match(cfg, NULL, fn, data);
|
||||
}
|
||||
|
||||
GIT_INLINE(int) git_config_file_foreach_match(
|
||||
@ -51,7 +51,7 @@ GIT_INLINE(int) git_config_file_foreach_match(
|
||||
int (*fn)(const git_config_entry *entry, void *data),
|
||||
void *data)
|
||||
{
|
||||
return cfg->foreach(cfg, regexp, fn, data);
|
||||
return git_config_backend_foreach_match(cfg, regexp, fn, data);
|
||||
}
|
||||
|
||||
extern int git_config_file_normalize_section(char *start, char *end);
|
||||
|
Loading…
Reference in New Issue
Block a user