mirror of
https://git.proxmox.com/git/libgit2
synced 2025-08-14 15:30:43 +00:00
Support getting multivars
This commit is contained in:
parent
78d65f390f
commit
5e0dc4af01
@ -29,6 +29,7 @@ struct git_config_file {
|
|||||||
/* Open means open the file/database and parse if necessary */
|
/* Open means open the file/database and parse if necessary */
|
||||||
int (*open)(struct git_config_file *);
|
int (*open)(struct git_config_file *);
|
||||||
int (*get)(struct git_config_file *, const char *key, const char **value);
|
int (*get)(struct git_config_file *, const char *key, const char **value);
|
||||||
|
int (*get_multivar)(struct git_config_file *, const char *key, const char *regexp, int (*fn)(const char *, void *), void *data);
|
||||||
int (*set)(struct git_config_file *, const char *key, const char *value);
|
int (*set)(struct git_config_file *, const char *key, const char *value);
|
||||||
int (*del)(struct git_config_file *, const char *key);
|
int (*del)(struct git_config_file *, const char *key);
|
||||||
int (*foreach)(struct git_config_file *, int (*fn)(const char *, const char *, void *), void *data);
|
int (*foreach)(struct git_config_file *, int (*fn)(const char *, const char *, void *), void *data);
|
||||||
@ -205,6 +206,12 @@ GIT_EXTERN(int) git_config_get_bool(git_config *cfg, const char *name, int *out)
|
|||||||
*/
|
*/
|
||||||
GIT_EXTERN(int) git_config_get_string(git_config *cfg, const char *name, const char **out);
|
GIT_EXTERN(int) git_config_get_string(git_config *cfg, const char *name, const char **out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get each value of a multivar. The callback will be called on each
|
||||||
|
* variable found
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_config_get_multivar(git_config *cfg, const char *name, const char *regexp, int (*fn)(const char *, void *), void *data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the value of an integer config variable.
|
* Set the value of an integer config variable.
|
||||||
*
|
*
|
||||||
|
27
src/config.c
27
src/config.c
@ -337,6 +337,33 @@ int git_config_get_string(git_config *cfg, const char *name, const char **out)
|
|||||||
return git__throw(error, "Config value '%s' not found", name);
|
return git__throw(error, "Config value '%s' not found", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int git_config_get_multivar(git_config *cfg, const char *name, const char *regexp,
|
||||||
|
int (*fn)(const char *value, void *data), void *data)
|
||||||
|
{
|
||||||
|
file_internal *internal;
|
||||||
|
git_config_file *file;
|
||||||
|
int error = GIT_ENOTFOUND;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
|
||||||
|
if (cfg->files.length == 0)
|
||||||
|
return git__throw(GIT_EINVALIDARGS, "Cannot get variable value; no files open in the `git_config` instance");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This loop runs the "wrong" way 'round because we need to
|
||||||
|
* 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);
|
||||||
|
file = internal->file;
|
||||||
|
error = file->get_multivar(file, name, regexp, fn, data);
|
||||||
|
if (error < GIT_SUCCESS && error != GIT_ENOTFOUND)
|
||||||
|
git__rethrow(error, "Failed to get multivar");
|
||||||
|
}
|
||||||
|
|
||||||
|
return GIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
int git_config_find_global_r(git_buf *path)
|
int git_config_find_global_r(git_buf *path)
|
||||||
{
|
{
|
||||||
return git_futils_find_global_file(path, GIT_CONFIG_FILENAME);
|
return git_futils_find_global_file(path, GIT_CONFIG_FILENAME);
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <regex.h>
|
||||||
|
|
||||||
typedef struct cvar_t {
|
typedef struct cvar_t {
|
||||||
struct cvar_t *next;
|
struct cvar_t *next;
|
||||||
@ -294,6 +296,45 @@ static int config_get(git_config_file *cfg, const char *name, const char **out)
|
|||||||
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to get config value for %s", name);
|
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to get config value for %s", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int config_get_multivar(git_config_file *cfg, const char *name, const char *regexp, int (*fn)(const char *, void *), void *data)
|
||||||
|
{
|
||||||
|
cvar_t *var;
|
||||||
|
int error = GIT_SUCCESS;
|
||||||
|
diskfile_backend *b = (diskfile_backend *)cfg;
|
||||||
|
char *key;
|
||||||
|
regex_t preg;
|
||||||
|
|
||||||
|
if ((error = normalize_name(name, &key)) < GIT_SUCCESS)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
var = git_hashtable_lookup(b->values, key);
|
||||||
|
git__free(key);
|
||||||
|
|
||||||
|
if (var == NULL)
|
||||||
|
return git__throw(GIT_ENOTFOUND, "Variable '%s' not found", name);
|
||||||
|
|
||||||
|
if (regexp != NULL) {
|
||||||
|
error = regcomp(&preg, regexp, 0);
|
||||||
|
if (error < 0)
|
||||||
|
return git__throw(GIT_EINVALIDARGS, "Failed to compile regex");
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (regexp == NULL || !regexec(&preg, var->value, 0, NULL, 0)) {
|
||||||
|
error = fn(var->value, data);
|
||||||
|
if (error < GIT_SUCCESS)
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
var = var->next;
|
||||||
|
} while (var != NULL);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (regexp != NULL)
|
||||||
|
regfree(&preg);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
static int config_delete(git_config_file *cfg, const char *name)
|
static int config_delete(git_config_file *cfg, const char *name)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
@ -342,6 +383,7 @@ int git_config_file__ondisk(git_config_file **out, const char *path)
|
|||||||
|
|
||||||
backend->parent.open = config_open;
|
backend->parent.open = config_open;
|
||||||
backend->parent.get = config_get;
|
backend->parent.get = config_get;
|
||||||
|
backend->parent.get_multivar = config_get_multivar;
|
||||||
backend->parent.set = config_set;
|
backend->parent.set = config_set;
|
||||||
backend->parent.del = config_delete;
|
backend->parent.del = config_delete;
|
||||||
backend->parent.foreach = file_foreach;
|
backend->parent.foreach = file_foreach;
|
||||||
|
@ -22,3 +22,31 @@ void test_config_multivar__foreach(void)
|
|||||||
|
|
||||||
git_config_free(cfg);
|
git_config_free(cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cb(const char *GIT_UNUSED(val), void *data)
|
||||||
|
{
|
||||||
|
int *n = (int *) data;
|
||||||
|
|
||||||
|
(*n)++;
|
||||||
|
|
||||||
|
return GIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_config_multivar__get(void)
|
||||||
|
{
|
||||||
|
git_config *cfg;
|
||||||
|
const char *name = "remote.fancy.fetch";
|
||||||
|
int n;
|
||||||
|
|
||||||
|
cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config11")));
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
cl_git_pass(git_config_get_multivar(cfg, name, NULL, cb, &n));
|
||||||
|
cl_assert(n == 2);
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
cl_git_pass(git_config_get_multivar(cfg, name, "example", cb, &n));
|
||||||
|
cl_assert(n == 1);
|
||||||
|
|
||||||
|
git_config_free(cfg);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user