mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-04 19:50:19 +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;
|
} git_config_entry;
|
||||||
|
|
||||||
typedef int (*git_config_foreach_cb)(const git_config_entry *, void *);
|
typedef int (*git_config_foreach_cb)(const git_config_entry *, void *);
|
||||||
|
typedef struct git_config_backend_iter* git_config_backend_iter;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GIT_CVAR_FALSE = 0,
|
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);
|
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
|
GIT_END_DECL
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,7 +35,9 @@ struct git_config_backend {
|
|||||||
int (*set)(struct git_config_backend *, const char *key, const char *value);
|
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 (*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 (*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 *);
|
int (*refresh)(struct git_config_backend *);
|
||||||
void (*free)(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);
|
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(
|
int git_config_foreach_match(
|
||||||
const git_config *cfg,
|
const git_config *cfg,
|
||||||
const char *regexp,
|
const char *regexp,
|
||||||
@ -335,7 +379,7 @@ int git_config_foreach_match(
|
|||||||
for (i = 0; i < cfg->files.length && ret == 0; ++i) {
|
for (i = 0; i < cfg->files.length && ret == 0; ++i) {
|
||||||
internal = git_vector_get(&cfg->files, i);
|
internal = git_vector_get(&cfg->files, i);
|
||||||
file = internal->file;
|
file = internal->file;
|
||||||
ret = file->foreach(file, regexp, cb, payload);
|
ret = git_config_backend_foreach_match(file, regexp, cb, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -27,6 +27,12 @@ typedef struct cvar_t {
|
|||||||
git_config_entry *entry;
|
git_config_entry *entry;
|
||||||
} cvar_t;
|
} 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_HEAD(list) ((list)->head)
|
||||||
|
|
||||||
#define CVAR_LIST_TAIL(list) ((list)->tail)
|
#define CVAR_LIST_TAIL(list) ((list)->tail)
|
||||||
@ -247,52 +253,60 @@ static void backend_free(git_config_backend *_backend)
|
|||||||
git__free(backend);
|
git__free(backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int file_foreach(
|
static int config_iterator_new(
|
||||||
git_config_backend *backend,
|
git_config_backend_iter *iter,
|
||||||
const char *regexp,
|
struct git_config_backend* backend)
|
||||||
int (*fn)(const git_config_entry *, void *),
|
|
||||||
void *data)
|
|
||||||
{
|
{
|
||||||
diskfile_backend *b = (diskfile_backend *)backend;
|
diskfile_backend *b = (diskfile_backend *)backend;
|
||||||
cvar_t *var, *next_var;
|
git_config_file_iter **it= ((git_config_file_iter**) iter);
|
||||||
const char *key;
|
|
||||||
regex_t regex;
|
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
if (!b->values)
|
if (!b->values || git_strmap_num_entries(b->values) < 1)
|
||||||
return 0;
|
return -1;
|
||||||
|
|
||||||
if (regexp != NULL) {
|
*it = git__calloc(1, sizeof(git_config_file_iter));
|
||||||
if ((result = regcomp(®ex, regexp, REG_EXTENDED)) < 0) {
|
GITERR_CHECK_ALLOC(it);
|
||||||
giterr_set_regex(®ex, result);
|
|
||||||
regfree(®ex);
|
(*it)->iter = git_strmap_begin(b->values);
|
||||||
return -1;
|
(*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);
|
if (err < 0) {
|
||||||
while (!(git_strmap_next(&key, (void**) &var, &iter, b->values) < 0)) {
|
it->next = NULL;
|
||||||
for (; var != NULL; var = next_var) {
|
return -1;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
entry->name = key;
|
||||||
if (regexp != NULL)
|
entry->value = var->entry->value;
|
||||||
regfree(®ex);
|
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)
|
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 = config_set;
|
||||||
backend->parent.set_multivar = config_set_multivar;
|
backend->parent.set_multivar = config_set_multivar;
|
||||||
backend->parent.del = config_delete;
|
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.refresh = config_refresh;
|
||||||
backend->parent.free = backend_free;
|
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),
|
int (*fn)(const git_config_entry *entry, void *data),
|
||||||
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(
|
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),
|
int (*fn)(const git_config_entry *entry, void *data),
|
||||||
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);
|
extern int git_config_file_normalize_section(char *start, char *end);
|
||||||
|
Loading…
Reference in New Issue
Block a user