|
Packit Service |
20376f |
/*
|
|
Packit Service |
20376f |
* Copyright (C) the libgit2 contributors. All rights reserved.
|
|
Packit Service |
20376f |
*
|
|
Packit Service |
20376f |
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
|
Packit Service |
20376f |
* a Linking Exception. For full terms see the included COPYING file.
|
|
Packit Service |
20376f |
*/
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
#include "common.h"
|
|
Packit Service |
20376f |
#include "sysdir.h"
|
|
Packit Service |
20376f |
#include "config.h"
|
|
Packit Service |
20376f |
#include "git2/config.h"
|
|
Packit Service |
20376f |
#include "git2/sys/config.h"
|
|
Packit Service |
20376f |
#include "vector.h"
|
|
Packit Service |
20376f |
#include "buf_text.h"
|
|
Packit Service |
20376f |
#include "config_file.h"
|
|
Packit Service |
20376f |
#include "transaction.h"
|
|
Packit Service |
20376f |
#if GIT_WIN32
|
|
Packit Service |
20376f |
# include <windows.h>
|
|
Packit Service |
20376f |
#endif
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
#include <ctype.h>
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
void git_config_entry_free(git_config_entry *entry)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
if (!entry)
|
|
Packit Service |
20376f |
return;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
entry->free(entry);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
typedef struct {
|
|
Packit Service |
20376f |
git_refcount rc;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git_config_backend *file;
|
|
Packit Service |
20376f |
git_config_level_t level;
|
|
Packit Service |
20376f |
} file_internal;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static void file_internal_free(file_internal *internal)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_config_backend *file;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
file = internal->file;
|
|
Packit Service |
20376f |
file->free(file);
|
|
Packit Service |
20376f |
git__free(internal);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static void config_free(git_config *cfg)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
size_t i;
|
|
Packit Service |
20376f |
file_internal *internal;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
for (i = 0; i < cfg->files.length; ++i) {
|
|
Packit Service |
20376f |
internal = git_vector_get(&cfg->files, i);
|
|
Packit Service |
20376f |
GIT_REFCOUNT_DEC(internal, file_internal_free);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git_vector_free(&cfg->files);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git__memzero(cfg, sizeof(*cfg));
|
|
Packit Service |
20376f |
git__free(cfg);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
void git_config_free(git_config *cfg)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
if (cfg == NULL)
|
|
Packit Service |
20376f |
return;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
GIT_REFCOUNT_DEC(cfg, config_free);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static int config_backend_cmp(const void *a, const void *b)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
const file_internal *bk_a = (const file_internal *)(a);
|
|
Packit Service |
20376f |
const file_internal *bk_b = (const file_internal *)(b);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return bk_b->level - bk_a->level;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_new(git_config **out)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_config *cfg;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
cfg = git__malloc(sizeof(git_config));
|
|
Packit Service |
20376f |
GITERR_CHECK_ALLOC(cfg);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
memset(cfg, 0x0, sizeof(git_config));
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (git_vector_init(&cfg->files, 3, config_backend_cmp) < 0) {
|
|
Packit Service |
20376f |
git__free(cfg);
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
*out = cfg;
|
|
Packit Service |
20376f |
GIT_REFCOUNT_INC(cfg);
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_add_file_ondisk(
|
|
Packit Service |
20376f |
git_config *cfg,
|
|
Packit Service |
20376f |
const char *path,
|
|
Packit Service |
20376f |
git_config_level_t level,
|
|
Packit Service |
20376f |
int force)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_config_backend *file = NULL;
|
|
Packit Service |
20376f |
struct stat st;
|
|
Packit Service |
20376f |
int res;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
assert(cfg && path);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
res = p_stat(path, &st);
|
|
Packit Service |
20376f |
if (res < 0 && errno != ENOENT) {
|
|
Packit Service |
20376f |
giterr_set(GITERR_CONFIG, "failed to stat '%s'", path);
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (git_config_file__ondisk(&file, path) < 0)
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((res = git_config_add_backend(cfg, file, level, force)) < 0) {
|
|
Packit Service |
20376f |
/*
|
|
Packit Service |
20376f |
* free manually; the file is not owned by the config
|
|
Packit Service |
20376f |
* instance yet and will not be freed on cleanup
|
|
Packit Service |
20376f |
*/
|
|
Packit Service |
20376f |
file->free(file);
|
|
Packit Service |
20376f |
return res;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_open_ondisk(git_config **out, const char *path)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
int error;
|
|
Packit Service |
20376f |
git_config *config;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
*out = NULL;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (git_config_new(&config) < 0)
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((error = git_config_add_file_ondisk(config, path, GIT_CONFIG_LEVEL_LOCAL, 0)) < 0)
|
|
Packit Service |
20376f |
git_config_free(config);
|
|
Packit Service |
20376f |
else
|
|
Packit Service |
20376f |
*out = config;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_snapshot(git_config **out, git_config *in)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
int error = 0;
|
|
Packit Service |
20376f |
size_t i;
|
|
Packit Service |
20376f |
file_internal *internal;
|
|
Packit Service |
20376f |
git_config *config;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
*out = NULL;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (git_config_new(&config) < 0)
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git_vector_foreach(&in->files, i, internal) {
|
|
Packit Service |
20376f |
git_config_backend *b;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((error = internal->file->snapshot(&b, internal->file)) < 0)
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((error = git_config_add_backend(config, b, internal->level, 0)) < 0) {
|
|
Packit Service |
20376f |
b->free(b);
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (error < 0)
|
|
Packit Service |
20376f |
git_config_free(config);
|
|
Packit Service |
20376f |
else
|
|
Packit Service |
20376f |
*out = config;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static int find_internal_file_by_level(
|
|
Packit Service |
20376f |
file_internal **internal_out,
|
|
Packit Service |
20376f |
const git_config *cfg,
|
|
Packit Service |
20376f |
git_config_level_t level)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
int pos = -1;
|
|
Packit Service |
20376f |
file_internal *internal;
|
|
Packit Service |
20376f |
size_t i;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/* when passing GIT_CONFIG_HIGHEST_LEVEL, the idea is to get the config file
|
|
Packit Service |
20376f |
* which has the highest level. As config files are stored in a vector
|
|
Packit Service |
20376f |
* sorted by decreasing order of level, getting the file at position 0
|
|
Packit Service |
20376f |
* will do the job.
|
|
Packit Service |
20376f |
*/
|
|
Packit Service |
20376f |
if (level == GIT_CONFIG_HIGHEST_LEVEL) {
|
|
Packit Service |
20376f |
pos = 0;
|
|
Packit Service |
20376f |
} else {
|
|
Packit Service |
20376f |
git_vector_foreach(&cfg->files, i, internal) {
|
|
Packit Service |
20376f |
if (internal->level == level)
|
|
Packit Service |
20376f |
pos = (int)i;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (pos == -1) {
|
|
Packit Service |
20376f |
giterr_set(GITERR_CONFIG,
|
|
Packit Service |
20376f |
"no config file exists for the given level '%i'", (int)level);
|
|
Packit Service |
20376f |
return GIT_ENOTFOUND;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
*internal_out = git_vector_get(&cfg->files, pos);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static int duplicate_level(void **old_raw, void *new_raw)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
file_internal **old = (file_internal **)old_raw;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
GIT_UNUSED(new_raw);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
giterr_set(GITERR_CONFIG, "a file with the same level (%i) has already been added to the config", (int)(*old)->level);
|
|
Packit Service |
20376f |
return GIT_EEXISTS;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static void try_remove_existing_file_internal(
|
|
Packit Service |
20376f |
git_config *cfg,
|
|
Packit Service |
20376f |
git_config_level_t level)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
int pos = -1;
|
|
Packit Service |
20376f |
file_internal *internal;
|
|
Packit Service |
20376f |
size_t i;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git_vector_foreach(&cfg->files, i, internal) {
|
|
Packit Service |
20376f |
if (internal->level == level)
|
|
Packit Service |
20376f |
pos = (int)i;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (pos == -1)
|
|
Packit Service |
20376f |
return;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
internal = git_vector_get(&cfg->files, pos);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (git_vector_remove(&cfg->files, pos) < 0)
|
|
Packit Service |
20376f |
return;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
GIT_REFCOUNT_DEC(internal, file_internal_free);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static int git_config__add_internal(
|
|
Packit Service |
20376f |
git_config *cfg,
|
|
Packit Service |
20376f |
file_internal *internal,
|
|
Packit Service |
20376f |
git_config_level_t level,
|
|
Packit Service |
20376f |
int force)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
int result;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/* delete existing config file for level if it exists */
|
|
Packit Service |
20376f |
if (force)
|
|
Packit Service |
20376f |
try_remove_existing_file_internal(cfg, level);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((result = git_vector_insert_sorted(&cfg->files,
|
|
Packit Service |
20376f |
internal, &duplicate_level)) < 0)
|
|
Packit Service |
20376f |
return result;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git_vector_sort(&cfg->files);
|
|
Packit Service |
20376f |
internal->file->cfg = cfg;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
GIT_REFCOUNT_INC(internal);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_open_global(git_config **cfg_out, git_config *cfg)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
if (!git_config_open_level(cfg_out, cfg, GIT_CONFIG_LEVEL_XDG))
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return git_config_open_level(cfg_out, cfg, GIT_CONFIG_LEVEL_GLOBAL);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_open_level(
|
|
Packit Service |
20376f |
git_config **cfg_out,
|
|
Packit Service |
20376f |
const git_config *cfg_parent,
|
|
Packit Service |
20376f |
git_config_level_t level)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_config *cfg;
|
|
Packit Service |
20376f |
file_internal *internal;
|
|
Packit Service |
20376f |
int res;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((res = find_internal_file_by_level(&internal, cfg_parent, level)) < 0)
|
|
Packit Service |
20376f |
return res;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((res = git_config_new(&cfg)) < 0)
|
|
Packit Service |
20376f |
return res;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((res = git_config__add_internal(cfg, internal, level, true)) < 0) {
|
|
Packit Service |
20376f |
git_config_free(cfg);
|
|
Packit Service |
20376f |
return res;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
*cfg_out = cfg;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_add_backend(
|
|
Packit Service |
20376f |
git_config *cfg,
|
|
Packit Service |
20376f |
git_config_backend *file,
|
|
Packit Service |
20376f |
git_config_level_t level,
|
|
Packit Service |
20376f |
int force)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
file_internal *internal;
|
|
Packit Service |
20376f |
int result;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
assert(cfg && file);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
GITERR_CHECK_VERSION(file, GIT_CONFIG_BACKEND_VERSION, "git_config_backend");
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((result = file->open(file, level)) < 0)
|
|
Packit Service |
20376f |
return result;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
internal = git__malloc(sizeof(file_internal));
|
|
Packit Service |
20376f |
GITERR_CHECK_ALLOC(internal);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
memset(internal, 0x0, sizeof(file_internal));
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
internal->file = file;
|
|
Packit Service |
20376f |
internal->level = level;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((result = git_config__add_internal(cfg, internal, level, force)) < 0) {
|
|
Packit Service |
20376f |
git__free(internal);
|
|
Packit Service |
20376f |
return result;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/*
|
|
Packit Service |
20376f |
* Loop over all the variables
|
|
Packit Service |
20376f |
*/
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
typedef struct {
|
|
Packit Service |
20376f |
git_config_iterator parent;
|
|
Packit Service |
20376f |
git_config_iterator *current;
|
|
Packit Service |
20376f |
const git_config *cfg;
|
|
Packit Service |
20376f |
regex_t regex;
|
|
Packit Service |
20376f |
size_t i;
|
|
Packit Service |
20376f |
} all_iter;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static int find_next_backend(size_t *out, const git_config *cfg, size_t i)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
file_internal *internal;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
for (; i > 0; --i) {
|
|
Packit Service |
20376f |
internal = git_vector_get(&cfg->files, i - 1);
|
|
Packit Service |
20376f |
if (!internal || !internal->file)
|
|
Packit Service |
20376f |
continue;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
*out = i;
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static int all_iter_next(git_config_entry **entry, git_config_iterator *_iter)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
all_iter *iter = (all_iter *) _iter;
|
|
Packit Service |
20376f |
file_internal *internal;
|
|
Packit Service |
20376f |
git_config_backend *backend;
|
|
Packit Service |
20376f |
size_t i;
|
|
Packit Service |
20376f |
int error = 0;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (iter->current != NULL &&
|
|
Packit Service |
20376f |
(error = iter->current->next(entry, iter->current)) == 0) {
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (error < 0 && error != GIT_ITEROVER)
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
do {
|
|
Packit Service |
20376f |
if (find_next_backend(&i, iter->cfg, iter->i) < 0)
|
|
Packit Service |
20376f |
return GIT_ITEROVER;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
internal = git_vector_get(&iter->cfg->files, i - 1);
|
|
Packit Service |
20376f |
backend = internal->file;
|
|
Packit Service |
20376f |
iter->i = i - 1;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (iter->current)
|
|
Packit Service |
20376f |
iter->current->free(iter->current);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
iter->current = NULL;
|
|
Packit Service |
20376f |
error = backend->iterator(&iter->current, backend);
|
|
Packit Service |
20376f |
if (error == GIT_ENOTFOUND)
|
|
Packit Service |
20376f |
continue;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (error < 0)
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
error = iter->current->next(entry, iter->current);
|
|
Packit Service |
20376f |
/* If this backend is empty, then keep going */
|
|
Packit Service |
20376f |
if (error == GIT_ITEROVER)
|
|
Packit Service |
20376f |
continue;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
} while(1);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return GIT_ITEROVER;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static int all_iter_glob_next(git_config_entry **entry, git_config_iterator *_iter)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
int error;
|
|
Packit Service |
20376f |
all_iter *iter = (all_iter *) _iter;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/*
|
|
Packit Service |
20376f |
* We use the "normal" function to grab the next one across
|
|
Packit Service |
20376f |
* backends and then apply the regex
|
|
Packit Service |
20376f |
*/
|
|
Packit Service |
20376f |
while ((error = all_iter_next(entry, _iter)) == 0) {
|
|
Packit Service |
20376f |
/* skip non-matching keys if regexp was provided */
|
|
Packit Service |
20376f |
if (regexec(&iter->regex, (*entry)->name, 0, NULL, 0) != 0)
|
|
Packit Service |
20376f |
continue;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/* and simply return if we like the entry's name */
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static void all_iter_free(git_config_iterator *_iter)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
all_iter *iter = (all_iter *) _iter;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (iter->current)
|
|
Packit Service |
20376f |
iter->current->free(iter->current);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git__free(iter);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static void all_iter_glob_free(git_config_iterator *_iter)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
all_iter *iter = (all_iter *) _iter;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
regfree(&iter->regex);
|
|
Packit Service |
20376f |
all_iter_free(_iter);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_iterator_new(git_config_iterator **out, const git_config *cfg)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
all_iter *iter;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
iter = git__calloc(1, sizeof(all_iter));
|
|
Packit Service |
20376f |
GITERR_CHECK_ALLOC(iter);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
iter->parent.free = all_iter_free;
|
|
Packit Service |
20376f |
iter->parent.next = all_iter_next;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
iter->i = cfg->files.length;
|
|
Packit Service |
20376f |
iter->cfg = cfg;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
*out = (git_config_iterator *) iter;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_iterator_glob_new(git_config_iterator **out, const git_config *cfg, const char *regexp)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
all_iter *iter;
|
|
Packit Service |
20376f |
int result;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (regexp == NULL)
|
|
Packit Service |
20376f |
return git_config_iterator_new(out, cfg);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
iter = git__calloc(1, sizeof(all_iter));
|
|
Packit Service |
20376f |
GITERR_CHECK_ALLOC(iter);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((result = p_regcomp(&iter->regex, regexp, REG_EXTENDED)) != 0) {
|
|
Packit Service |
20376f |
giterr_set_regex(&iter->regex, result);
|
|
Packit Service |
20376f |
git__free(iter);
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
iter->parent.next = all_iter_glob_next;
|
|
Packit Service |
20376f |
iter->parent.free = all_iter_glob_free;
|
|
Packit Service |
20376f |
iter->i = cfg->files.length;
|
|
Packit Service |
20376f |
iter->cfg = cfg;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
*out = (git_config_iterator *) iter;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_foreach(
|
|
Packit Service |
20376f |
const git_config *cfg, git_config_foreach_cb cb, void *payload)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
return git_config_foreach_match(cfg, NULL, cb, payload);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_backend_foreach_match(
|
|
Packit Service |
20376f |
git_config_backend *backend,
|
|
Packit Service |
20376f |
const char *regexp,
|
|
Packit Service |
20376f |
git_config_foreach_cb cb,
|
|
Packit Service |
20376f |
void *payload)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_config_entry *entry;
|
|
Packit Service |
20376f |
git_config_iterator* iter;
|
|
Packit Service |
20376f |
regex_t regex;
|
|
Packit Service |
20376f |
int error = 0;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (regexp != NULL) {
|
|
Packit Service |
20376f |
if ((error = p_regcomp(®ex, regexp, REG_EXTENDED)) != 0) {
|
|
Packit Service |
20376f |
giterr_set_regex(®ex, error);
|
|
Packit Service |
20376f |
regfree(®ex);
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((error = backend->iterator(&iter, backend)) < 0) {
|
|
Packit Service |
20376f |
iter = NULL;
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
while (!(iter->next(&entry, iter) < 0)) {
|
|
Packit Service |
20376f |
/* skip non-matching keys if regexp was provided */
|
|
Packit Service |
20376f |
if (regexp && regexec(®ex, entry->name, 0, NULL, 0) != 0)
|
|
Packit Service |
20376f |
continue;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/* abort iterator on non-zero return value */
|
|
Packit Service |
20376f |
if ((error = cb(entry, payload)) != 0) {
|
|
Packit Service |
20376f |
giterr_set_after_callback(error);
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (regexp != NULL)
|
|
Packit Service |
20376f |
regfree(®ex);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
iter->free(iter);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_foreach_match(
|
|
Packit Service |
20376f |
const git_config *cfg,
|
|
Packit Service |
20376f |
const char *regexp,
|
|
Packit Service |
20376f |
git_config_foreach_cb cb,
|
|
Packit Service |
20376f |
void *payload)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
int error;
|
|
Packit Service |
20376f |
git_config_iterator *iter;
|
|
Packit Service |
20376f |
git_config_entry *entry;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((error = git_config_iterator_glob_new(&iter, cfg, regexp)) < 0)
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
while (!(error = git_config_next(&entry, iter))) {
|
|
Packit Service |
20376f |
if ((error = cb(entry, payload)) != 0) {
|
|
Packit Service |
20376f |
giterr_set_after_callback(error);
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git_config_iterator_free(iter);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (error == GIT_ITEROVER)
|
|
Packit Service |
20376f |
error = 0;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/**************
|
|
Packit Service |
20376f |
* Setters
|
|
Packit Service |
20376f |
**************/
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
typedef enum {
|
|
Packit Service |
20376f |
BACKEND_USE_SET,
|
|
Packit Service |
20376f |
BACKEND_USE_DELETE
|
|
Packit Service |
20376f |
} backend_use;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static const char *uses[] = {
|
|
Packit Service |
20376f |
"set",
|
|
Packit Service |
20376f |
"delete"
|
|
Packit Service |
20376f |
};
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static int get_backend_for_use(git_config_backend **out,
|
|
Packit Service |
20376f |
git_config *cfg, const char *name, backend_use use)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
size_t i;
|
|
Packit Service |
20376f |
file_internal *f;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
*out = NULL;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (git_vector_length(&cfg->files) == 0) {
|
|
Packit Service |
20376f |
giterr_set(GITERR_CONFIG,
|
|
Packit Service |
20376f |
"cannot %s value for '%s' when no config files exist",
|
|
Packit Service |
20376f |
uses[use], name);
|
|
Packit Service |
20376f |
return GIT_ENOTFOUND;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git_vector_foreach(&cfg->files, i, f) {
|
|
Packit Service |
20376f |
if (!f->file->readonly) {
|
|
Packit Service |
20376f |
*out = f->file;
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
giterr_set(GITERR_CONFIG,
|
|
Packit Service |
20376f |
"cannot %s value for '%s' when all config files are readonly",
|
|
Packit Service |
20376f |
uses[use], name);
|
|
Packit Service |
20376f |
return GIT_ENOTFOUND;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_delete_entry(git_config *cfg, const char *name)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_config_backend *file;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (get_backend_for_use(&file, cfg, name, BACKEND_USE_DELETE) < 0)
|
|
Packit Service |
20376f |
return GIT_ENOTFOUND;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return file->del(file, name);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_set_int64(git_config *cfg, const char *name, int64_t value)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
char str_value[32]; /* All numbers should fit in here */
|
|
Packit Service |
20376f |
p_snprintf(str_value, sizeof(str_value), "%" PRId64, value);
|
|
Packit Service |
20376f |
return git_config_set_string(cfg, name, str_value);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_set_int32(git_config *cfg, const char *name, int32_t value)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
return git_config_set_int64(cfg, name, (int64_t)value);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_set_bool(git_config *cfg, const char *name, int value)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
return git_config_set_string(cfg, name, value ? "true" : "false");
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_set_string(git_config *cfg, const char *name, const char *value)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
int error;
|
|
Packit Service |
20376f |
git_config_backend *file;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (!value) {
|
|
Packit Service |
20376f |
giterr_set(GITERR_CONFIG, "the value to set cannot be NULL");
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (get_backend_for_use(&file, cfg, name, BACKEND_USE_SET) < 0)
|
|
Packit Service |
20376f |
return GIT_ENOTFOUND;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
error = file->set(file, name, value);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (!error && GIT_REFCOUNT_OWNER(cfg) != NULL)
|
|
Packit Service |
20376f |
git_repository__cvar_cache_clear(GIT_REFCOUNT_OWNER(cfg));
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config__update_entry(
|
|
Packit Service |
20376f |
git_config *config,
|
|
Packit Service |
20376f |
const char *key,
|
|
Packit Service |
20376f |
const char *value,
|
|
Packit Service |
20376f |
bool overwrite_existing,
|
|
Packit Service |
20376f |
bool only_if_existing)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
int error = 0;
|
|
Packit Service |
20376f |
git_config_entry *ce = NULL;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((error = git_config__lookup_entry(&ce, config, key, false)) < 0)
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (!ce && only_if_existing) /* entry doesn't exist */
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
if (ce && !overwrite_existing) /* entry would be overwritten */
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
if (value && ce && ce->value && !strcmp(ce->value, value)) /* no change */
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
if (!value && (!ce || !ce->value)) /* asked to delete absent entry */
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (!value)
|
|
Packit Service |
20376f |
error = git_config_delete_entry(config, key);
|
|
Packit Service |
20376f |
else
|
|
Packit Service |
20376f |
error = git_config_set_string(config, key, value);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git_config_entry_free(ce);
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/***********
|
|
Packit Service |
20376f |
* Getters
|
|
Packit Service |
20376f |
***********/
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static int config_error_notfound(const char *name)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
giterr_set(GITERR_CONFIG, "config value '%s' was not found", name);
|
|
Packit Service |
20376f |
return GIT_ENOTFOUND;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
enum {
|
|
Packit Service |
20376f |
GET_ALL_ERRORS = 0,
|
|
Packit Service |
20376f |
GET_NO_MISSING = 1,
|
|
Packit Service |
20376f |
GET_NO_ERRORS = 2
|
|
Packit Service |
20376f |
};
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static int get_entry(
|
|
Packit Service |
20376f |
git_config_entry **out,
|
|
Packit Service |
20376f |
const git_config *cfg,
|
|
Packit Service |
20376f |
const char *name,
|
|
Packit Service |
20376f |
bool normalize_name,
|
|
Packit Service |
20376f |
int want_errors)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
int res = GIT_ENOTFOUND;
|
|
Packit Service |
20376f |
const char *key = name;
|
|
Packit Service |
20376f |
char *normalized = NULL;
|
|
Packit Service |
20376f |
size_t i;
|
|
Packit Service |
20376f |
file_internal *internal;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
*out = NULL;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (normalize_name) {
|
|
Packit Service |
20376f |
if ((res = git_config__normalize_name(name, &normalized)) < 0)
|
|
Packit Service |
20376f |
goto cleanup;
|
|
Packit Service |
20376f |
key = normalized;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
res = GIT_ENOTFOUND;
|
|
Packit Service |
20376f |
git_vector_foreach(&cfg->files, i, internal) {
|
|
Packit Service |
20376f |
if (!internal || !internal->file)
|
|
Packit Service |
20376f |
continue;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
res = internal->file->get(internal->file, key, out);
|
|
Packit Service |
20376f |
if (res != GIT_ENOTFOUND)
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git__free(normalized);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
cleanup:
|
|
Packit Service |
20376f |
if (res == GIT_ENOTFOUND)
|
|
Packit Service |
20376f |
res = (want_errors > GET_ALL_ERRORS) ? 0 : config_error_notfound(name);
|
|
Packit Service |
20376f |
else if (res && (want_errors == GET_NO_ERRORS)) {
|
|
Packit Service |
20376f |
giterr_clear();
|
|
Packit Service |
20376f |
res = 0;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return res;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_get_entry(
|
|
Packit Service |
20376f |
git_config_entry **out, const git_config *cfg, const char *name)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
return get_entry(out, cfg, name, true, GET_ALL_ERRORS);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config__lookup_entry(
|
|
Packit Service |
20376f |
git_config_entry **out,
|
|
Packit Service |
20376f |
const git_config *cfg,
|
|
Packit Service |
20376f |
const char *key,
|
|
Packit Service |
20376f |
bool no_errors)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
return get_entry(
|
|
Packit Service |
20376f |
out, cfg, key, false, no_errors ? GET_NO_ERRORS : GET_NO_MISSING);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_get_mapped(
|
|
Packit Service |
20376f |
int *out,
|
|
Packit Service |
20376f |
const git_config *cfg,
|
|
Packit Service |
20376f |
const char *name,
|
|
Packit Service |
20376f |
const git_cvar_map *maps,
|
|
Packit Service |
20376f |
size_t map_n)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_config_entry *entry;
|
|
Packit Service |
20376f |
int ret;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0)
|
|
Packit Service |
20376f |
return ret;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
ret = git_config_lookup_map_value(out, maps, map_n, entry->value);
|
|
Packit Service |
20376f |
git_config_entry_free(entry);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return ret;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_get_int64(int64_t *out, const git_config *cfg, const char *name)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_config_entry *entry;
|
|
Packit Service |
20376f |
int ret;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0)
|
|
Packit Service |
20376f |
return ret;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
ret = git_config_parse_int64(out, entry->value);
|
|
Packit Service |
20376f |
git_config_entry_free(entry);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return ret;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_get_int32(int32_t *out, const git_config *cfg, const char *name)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_config_entry *entry;
|
|
Packit Service |
20376f |
int ret;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0)
|
|
Packit Service |
20376f |
return ret;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
ret = git_config_parse_int32(out, entry->value);
|
|
Packit Service |
20376f |
git_config_entry_free(entry);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return ret;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_get_bool(int *out, const git_config *cfg, const char *name)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_config_entry *entry;
|
|
Packit Service |
20376f |
int ret;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0)
|
|
Packit Service |
20376f |
return ret;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
ret = git_config_parse_bool(out, entry->value);
|
|
Packit Service |
20376f |
git_config_entry_free(entry);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return ret;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static int is_readonly(const git_config *cfg)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
size_t i;
|
|
Packit Service |
20376f |
file_internal *internal;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git_vector_foreach(&cfg->files, i, internal) {
|
|
Packit Service |
20376f |
if (!internal || !internal->file)
|
|
Packit Service |
20376f |
continue;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (!internal->file->readonly)
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return 1;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_get_path(git_buf *out, const git_config *cfg, const char *name)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_config_entry *entry;
|
|
Packit Service |
20376f |
int error;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((error = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0)
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
error = git_config_parse_path(out, entry->value);
|
|
Packit Service |
20376f |
git_config_entry_free(entry);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_get_string(
|
|
Packit Service |
20376f |
const char **out, const git_config *cfg, const char *name)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_config_entry *entry;
|
|
Packit Service |
20376f |
int ret;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (!is_readonly(cfg)) {
|
|
Packit Service |
20376f |
giterr_set(GITERR_CONFIG, "get_string called on a live config object");
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS);
|
|
Packit Service |
20376f |
*out = !ret ? (entry->value ? entry->value : "") : NULL;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git_config_entry_free(entry);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return ret;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_get_string_buf(
|
|
Packit Service |
20376f |
git_buf *out, const git_config *cfg, const char *name)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_config_entry *entry;
|
|
Packit Service |
20376f |
int ret;
|
|
Packit Service |
20376f |
const char *str;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git_buf_sanitize(out);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS);
|
|
Packit Service |
20376f |
str = !ret ? (entry->value ? entry->value : "") : NULL;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (str)
|
|
Packit Service |
20376f |
ret = git_buf_puts(out, str);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git_config_entry_free(entry);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return ret;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
char *git_config__get_string_force(
|
|
Packit Service |
20376f |
const git_config *cfg, const char *key, const char *fallback_value)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_config_entry *entry;
|
|
Packit Service |
20376f |
char *ret;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
get_entry(&entry, cfg, key, false, GET_NO_ERRORS);
|
|
Packit Service |
20376f |
ret = (entry && entry->value) ? git__strdup(entry->value) : fallback_value ? git__strdup(fallback_value) : NULL;
|
|
Packit Service |
20376f |
git_config_entry_free(entry);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return ret;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config__get_bool_force(
|
|
Packit Service |
20376f |
const git_config *cfg, const char *key, int fallback_value)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
int val = fallback_value;
|
|
Packit Service |
20376f |
git_config_entry *entry;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
get_entry(&entry, cfg, key, false, GET_NO_ERRORS);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (entry && git_config_parse_bool(&val, entry->value) < 0)
|
|
Packit Service |
20376f |
giterr_clear();
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git_config_entry_free(entry);
|
|
Packit Service |
20376f |
return val;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config__get_int_force(
|
|
Packit Service |
20376f |
const git_config *cfg, const char *key, int fallback_value)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
int32_t val = (int32_t)fallback_value;
|
|
Packit Service |
20376f |
git_config_entry *entry;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
get_entry(&entry, cfg, key, false, GET_NO_ERRORS);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (entry && git_config_parse_int32(&val, entry->value) < 0)
|
|
Packit Service |
20376f |
giterr_clear();
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git_config_entry_free(entry);
|
|
Packit Service |
20376f |
return (int)val;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_get_multivar_foreach(
|
|
Packit Service |
20376f |
const git_config *cfg, const char *name, const char *regexp,
|
|
Packit Service |
20376f |
git_config_foreach_cb cb, void *payload)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
int err, found;
|
|
Packit Service |
20376f |
git_config_iterator *iter;
|
|
Packit Service |
20376f |
git_config_entry *entry;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((err = git_config_multivar_iterator_new(&iter, cfg, name, regexp)) < 0)
|
|
Packit Service |
20376f |
return err;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
found = 0;
|
|
Packit Service |
20376f |
while ((err = iter->next(&entry, iter)) == 0) {
|
|
Packit Service |
20376f |
found = 1;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((err = cb(entry, payload)) != 0) {
|
|
Packit Service |
20376f |
giterr_set_after_callback(err);
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
iter->free(iter);
|
|
Packit Service |
20376f |
if (err == GIT_ITEROVER)
|
|
Packit Service |
20376f |
err = 0;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (found == 0 && err == 0)
|
|
Packit Service |
20376f |
err = config_error_notfound(name);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return err;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
typedef struct {
|
|
Packit Service |
20376f |
git_config_iterator parent;
|
|
Packit Service |
20376f |
git_config_iterator *iter;
|
|
Packit Service |
20376f |
char *name;
|
|
Packit Service |
20376f |
regex_t regex;
|
|
Packit Service |
20376f |
int have_regex;
|
|
Packit Service |
20376f |
} multivar_iter;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static int multivar_iter_next(git_config_entry **entry, git_config_iterator *_iter)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
multivar_iter *iter = (multivar_iter *) _iter;
|
|
Packit Service |
20376f |
int error = 0;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
while ((error = iter->iter->next(entry, iter->iter)) == 0) {
|
|
Packit Service |
20376f |
if (git__strcmp(iter->name, (*entry)->name))
|
|
Packit Service |
20376f |
continue;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (!iter->have_regex)
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (regexec(&iter->regex, (*entry)->value, 0, NULL, 0) == 0)
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
void multivar_iter_free(git_config_iterator *_iter)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
multivar_iter *iter = (multivar_iter *) _iter;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
iter->iter->free(iter->iter);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git__free(iter->name);
|
|
Packit Service |
20376f |
if (iter->have_regex)
|
|
Packit Service |
20376f |
regfree(&iter->regex);
|
|
Packit Service |
20376f |
git__free(iter);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_multivar_iterator_new(git_config_iterator **out, const git_config *cfg, const char *name, const char *regexp)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
multivar_iter *iter = NULL;
|
|
Packit Service |
20376f |
git_config_iterator *inner = NULL;
|
|
Packit Service |
20376f |
int error;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((error = git_config_iterator_new(&inner, cfg)) < 0)
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
iter = git__calloc(1, sizeof(multivar_iter));
|
|
Packit Service |
20376f |
GITERR_CHECK_ALLOC(iter);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((error = git_config__normalize_name(name, &iter->name)) < 0)
|
|
Packit Service |
20376f |
goto on_error;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (regexp != NULL) {
|
|
Packit Service |
20376f |
error = p_regcomp(&iter->regex, regexp, REG_EXTENDED);
|
|
Packit Service |
20376f |
if (error != 0) {
|
|
Packit Service |
20376f |
giterr_set_regex(&iter->regex, error);
|
|
Packit Service |
20376f |
error = -1;
|
|
Packit Service |
20376f |
regfree(&iter->regex);
|
|
Packit Service |
20376f |
goto on_error;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
iter->have_regex = 1;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
iter->iter = inner;
|
|
Packit Service |
20376f |
iter->parent.free = multivar_iter_free;
|
|
Packit Service |
20376f |
iter->parent.next = multivar_iter_next;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
*out = (git_config_iterator *) iter;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
on_error:
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
inner->free(inner);
|
|
Packit Service |
20376f |
git__free(iter);
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_set_multivar(git_config *cfg, const char *name, const char *regexp, const char *value)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_config_backend *file;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (get_backend_for_use(&file, cfg, name, BACKEND_USE_DELETE) < 0)
|
|
Packit Service |
20376f |
return GIT_ENOTFOUND;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return file->set_multivar(file, name, regexp, value);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_delete_multivar(git_config *cfg, const char *name, const char *regexp)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_config_backend *file;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (get_backend_for_use(&file, cfg, name, BACKEND_USE_DELETE) < 0)
|
|
Packit Service |
20376f |
return GIT_ENOTFOUND;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return file->del_multivar(file, name, regexp);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_next(git_config_entry **entry, git_config_iterator *iter)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
return iter->next(entry, iter);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
void git_config_iterator_free(git_config_iterator *iter)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
if (iter == NULL)
|
|
Packit Service |
20376f |
return;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
iter->free(iter);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_find_global(git_buf *path)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_buf_sanitize(path);
|
|
Packit Service |
20376f |
return git_sysdir_find_global_file(path, GIT_CONFIG_FILENAME_GLOBAL);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_find_xdg(git_buf *path)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_buf_sanitize(path);
|
|
Packit Service |
20376f |
return git_sysdir_find_xdg_file(path, GIT_CONFIG_FILENAME_XDG);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_find_system(git_buf *path)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_buf_sanitize(path);
|
|
Packit Service |
20376f |
return git_sysdir_find_system_file(path, GIT_CONFIG_FILENAME_SYSTEM);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_find_programdata(git_buf *path)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_buf_sanitize(path);
|
|
Packit Service |
20376f |
return git_sysdir_find_programdata_file(path, GIT_CONFIG_FILENAME_PROGRAMDATA);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config__global_location(git_buf *buf)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
const git_buf *paths;
|
|
Packit Service |
20376f |
const char *sep, *start;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (git_sysdir_get(&paths, GIT_SYSDIR_GLOBAL) < 0)
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/* no paths, so give up */
|
|
Packit Service |
20376f |
if (!paths || !git_buf_len(paths))
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/* find unescaped separator or end of string */
|
|
Packit Service |
20376f |
for (sep = start = git_buf_cstr(paths); *sep; ++sep) {
|
|
Packit Service |
20376f |
if (*sep == GIT_PATH_LIST_SEPARATOR &&
|
|
Packit Service |
20376f |
(sep <= start || sep[-1] != '\\'))
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (git_buf_set(buf, start, (size_t)(sep - start)) < 0)
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return git_buf_joinpath(buf, buf->ptr, GIT_CONFIG_FILENAME_GLOBAL);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_open_default(git_config **out)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
int error;
|
|
Packit Service |
20376f |
git_config *cfg = NULL;
|
|
Packit Service |
20376f |
git_buf buf = GIT_BUF_INIT;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((error = git_config_new(&cfg)) < 0)
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (!git_config_find_global(&buf) || !git_config__global_location(&buf)) {
|
|
Packit Service |
20376f |
error = git_config_add_file_ondisk(cfg, buf.ptr,
|
|
Packit Service |
20376f |
GIT_CONFIG_LEVEL_GLOBAL, 0);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (!error && !git_config_find_xdg(&buf))
|
|
Packit Service |
20376f |
error = git_config_add_file_ondisk(cfg, buf.ptr,
|
|
Packit Service |
20376f |
GIT_CONFIG_LEVEL_XDG, 0);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (!error && !git_config_find_system(&buf))
|
|
Packit Service |
20376f |
error = git_config_add_file_ondisk(cfg, buf.ptr,
|
|
Packit Service |
20376f |
GIT_CONFIG_LEVEL_SYSTEM, 0);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (!error && !git_config_find_programdata(&buf))
|
|
Packit Service |
20376f |
error = git_config_add_file_ondisk(cfg, buf.ptr,
|
|
Packit Service |
20376f |
GIT_CONFIG_LEVEL_PROGRAMDATA, 0);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git_buf_free(&buf;;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (error) {
|
|
Packit Service |
20376f |
git_config_free(cfg);
|
|
Packit Service |
20376f |
cfg = NULL;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
*out = cfg;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_lock(git_transaction **out, git_config *cfg)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
int error;
|
|
Packit Service |
20376f |
git_config_backend *file;
|
|
Packit Service |
20376f |
file_internal *internal;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
internal = git_vector_get(&cfg->files, 0);
|
|
Packit Service |
20376f |
if (!internal || !internal->file) {
|
|
Packit Service |
20376f |
giterr_set(GITERR_CONFIG, "cannot lock; the config has no backends/files");
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
file = internal->file;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((error = file->lock(file)) < 0)
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return git_transaction_config_new(out, cfg);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_unlock(git_config *cfg, int commit)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_config_backend *file;
|
|
Packit Service |
20376f |
file_internal *internal;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
internal = git_vector_get(&cfg->files, 0);
|
|
Packit Service |
20376f |
if (!internal || !internal->file) {
|
|
Packit Service |
20376f |
giterr_set(GITERR_CONFIG, "cannot lock; the config has no backends/files");
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
file = internal->file;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return file->unlock(file, commit);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/***********
|
|
Packit Service |
20376f |
* Parsers
|
|
Packit Service |
20376f |
***********/
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_lookup_map_value(
|
|
Packit Service |
20376f |
int *out,
|
|
Packit Service |
20376f |
const git_cvar_map *maps,
|
|
Packit Service |
20376f |
size_t map_n,
|
|
Packit Service |
20376f |
const char *value)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
size_t i;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (!value)
|
|
Packit Service |
20376f |
goto fail_parse;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
for (i = 0; i < map_n; ++i) {
|
|
Packit Service |
20376f |
const git_cvar_map *m = maps + i;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
switch (m->cvar_type) {
|
|
Packit Service |
20376f |
case GIT_CVAR_FALSE:
|
|
Packit Service |
20376f |
case GIT_CVAR_TRUE: {
|
|
Packit Service |
20376f |
int bool_val;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (git__parse_bool(&bool_val, value) == 0 &&
|
|
Packit Service |
20376f |
bool_val == (int)m->cvar_type) {
|
|
Packit Service |
20376f |
*out = m->map_value;
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
case GIT_CVAR_INT32:
|
|
Packit Service |
20376f |
if (git_config_parse_int32(out, value) == 0)
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
case GIT_CVAR_STRING:
|
|
Packit Service |
20376f |
if (strcasecmp(value, m->str_match) == 0) {
|
|
Packit Service |
20376f |
*out = m->map_value;
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
break;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
fail_parse:
|
|
Packit Service |
20376f |
giterr_set(GITERR_CONFIG, "failed to map '%s'", value);
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_lookup_map_enum(git_cvar_t *type_out, const char **str_out,
|
|
Packit Service |
20376f |
const git_cvar_map *maps, size_t map_n, int enum_val)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
size_t i;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
for (i = 0; i < map_n; i++) {
|
|
Packit Service |
20376f |
const git_cvar_map *m = &maps[i];
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (m->map_value != enum_val)
|
|
Packit Service |
20376f |
continue;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
*type_out = m->cvar_type;
|
|
Packit Service |
20376f |
*str_out = m->str_match;
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
giterr_set(GITERR_CONFIG, "invalid enum value");
|
|
Packit Service |
20376f |
return GIT_ENOTFOUND;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_parse_bool(int *out, const char *value)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
if (git__parse_bool(out, value) == 0)
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (git_config_parse_int32(out, value) == 0) {
|
|
Packit Service |
20376f |
*out = !!(*out);
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
giterr_set(GITERR_CONFIG, "failed to parse '%s' as a boolean value", value);
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_parse_int64(int64_t *out, const char *value)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
const char *num_end;
|
|
Packit Service |
20376f |
int64_t num;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (!value || git__strntol64(&num, value, strlen(value), &num_end, 0) < 0)
|
|
Packit Service |
20376f |
goto fail_parse;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
switch (*num_end) {
|
|
Packit Service |
20376f |
case 'g':
|
|
Packit Service |
20376f |
case 'G':
|
|
Packit Service |
20376f |
num *= 1024;
|
|
Packit Service |
20376f |
/* fallthrough */
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
case 'm':
|
|
Packit Service |
20376f |
case 'M':
|
|
Packit Service |
20376f |
num *= 1024;
|
|
Packit Service |
20376f |
/* fallthrough */
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
case 'k':
|
|
Packit Service |
20376f |
case 'K':
|
|
Packit Service |
20376f |
num *= 1024;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/* check that that there are no more characters after the
|
|
Packit Service |
20376f |
* given modifier suffix */
|
|
Packit Service |
20376f |
if (num_end[1] != '\0')
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/* fallthrough */
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
case '\0':
|
|
Packit Service |
20376f |
*out = num;
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
default:
|
|
Packit Service |
20376f |
goto fail_parse;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
fail_parse:
|
|
Packit Service |
20376f |
giterr_set(GITERR_CONFIG, "failed to parse '%s' as an integer", value ? value : "(null)");
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_parse_int32(int32_t *out, const char *value)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
int64_t tmp;
|
|
Packit Service |
20376f |
int32_t truncate;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (git_config_parse_int64(&tmp, value) < 0)
|
|
Packit Service |
20376f |
goto fail_parse;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
truncate = tmp & 0xFFFFFFFF;
|
|
Packit Service |
20376f |
if (truncate != tmp)
|
|
Packit Service |
20376f |
goto fail_parse;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
*out = truncate;
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
fail_parse:
|
|
Packit Service |
20376f |
giterr_set(GITERR_CONFIG, "failed to parse '%s' as a 32-bit integer", value ? value : "(null)");
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_parse_path(git_buf *out, const char *value)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
assert(out && value);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git_buf_sanitize(out);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (value[0] == '~') {
|
|
Packit Service |
20376f |
if (value[1] != '\0' && value[1] != '/') {
|
|
Packit Service |
20376f |
giterr_set(GITERR_CONFIG, "retrieving a homedir by name is not supported");
|
|
Packit Service |
20376f |
return -1;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return git_sysdir_expand_global_file(out, value[1] ? &value[2] : NULL);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return git_buf_sets(out, value);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/* Take something the user gave us and make it nice for our hash function */
|
|
Packit Service |
20376f |
int git_config__normalize_name(const char *in, char **out)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
char *name, *fdot, *ldot;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
assert(in && out);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
name = git__strdup(in);
|
|
Packit Service |
20376f |
GITERR_CHECK_ALLOC(name);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
fdot = strchr(name, '.');
|
|
Packit Service |
20376f |
ldot = strrchr(name, '.');
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (fdot == NULL || fdot == name || ldot == NULL || !ldot[1])
|
|
Packit Service |
20376f |
goto invalid;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/* Validate and downcase up to first dot and after last dot */
|
|
Packit Service |
20376f |
if (git_config_file_normalize_section(name, fdot) < 0 ||
|
|
Packit Service |
20376f |
git_config_file_normalize_section(ldot + 1, NULL) < 0)
|
|
Packit Service |
20376f |
goto invalid;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
/* If there is a middle range, make sure it doesn't have newlines */
|
|
Packit Service |
20376f |
while (fdot < ldot)
|
|
Packit Service |
20376f |
if (*fdot++ == '\n')
|
|
Packit Service |
20376f |
goto invalid;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
*out = name;
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
invalid:
|
|
Packit Service |
20376f |
git__free(name);
|
|
Packit Service |
20376f |
giterr_set(GITERR_CONFIG, "invalid config item name '%s'", in);
|
|
Packit Service |
20376f |
return GIT_EINVALIDSPEC;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
struct rename_data {
|
|
Packit Service |
20376f |
git_config *config;
|
|
Packit Service |
20376f |
git_buf *name;
|
|
Packit Service |
20376f |
size_t old_len;
|
|
Packit Service |
20376f |
};
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
static int rename_config_entries_cb(
|
|
Packit Service |
20376f |
const git_config_entry *entry,
|
|
Packit Service |
20376f |
void *payload)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
int error = 0;
|
|
Packit Service |
20376f |
struct rename_data *data = (struct rename_data *)payload;
|
|
Packit Service |
20376f |
size_t base_len = git_buf_len(data->name);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (base_len > 0 &&
|
|
Packit Service |
20376f |
!(error = git_buf_puts(data->name, entry->name + data->old_len)))
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
error = git_config_set_string(
|
|
Packit Service |
20376f |
data->config, git_buf_cstr(data->name), entry->value);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git_buf_truncate(data->name, base_len);
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (!error)
|
|
Packit Service |
20376f |
error = git_config_delete_entry(data->config, entry->name);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_rename_section(
|
|
Packit Service |
20376f |
git_repository *repo,
|
|
Packit Service |
20376f |
const char *old_section_name,
|
|
Packit Service |
20376f |
const char *new_section_name)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
git_config *config;
|
|
Packit Service |
20376f |
git_buf pattern = GIT_BUF_INIT, replace = GIT_BUF_INIT;
|
|
Packit Service |
20376f |
int error = 0;
|
|
Packit Service |
20376f |
struct rename_data data;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
git_buf_text_puts_escape_regex(&pattern, old_section_name);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((error = git_buf_puts(&pattern, "\\..+")) < 0)
|
|
Packit Service |
20376f |
goto cleanup;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((error = git_repository_config__weakptr(&config, repo)) < 0)
|
|
Packit Service |
20376f |
goto cleanup;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
data.config = config;
|
|
Packit Service |
20376f |
data.name = &replace;
|
|
Packit Service |
20376f |
data.old_len = strlen(old_section_name) + 1;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if ((error = git_buf_join(&replace, '.', new_section_name, "")) < 0)
|
|
Packit Service |
20376f |
goto cleanup;
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
if (new_section_name != NULL &&
|
|
Packit Service |
20376f |
(error = git_config_file_normalize_section(
|
|
Packit Service |
20376f |
replace.ptr, strchr(replace.ptr, '.'))) < 0)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
giterr_set(
|
|
Packit Service |
20376f |
GITERR_CONFIG, "invalid config section '%s'", new_section_name);
|
|
Packit Service |
20376f |
goto cleanup;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
error = git_config_foreach_match(
|
|
Packit Service |
20376f |
config, git_buf_cstr(&pattern), rename_config_entries_cb, &data);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
cleanup:
|
|
Packit Service |
20376f |
git_buf_free(&pattern);
|
|
Packit Service |
20376f |
git_buf_free(&replace);
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
return error;
|
|
Packit Service |
20376f |
}
|
|
Packit Service |
20376f |
|
|
Packit Service |
20376f |
int git_config_init_backend(git_config_backend *backend, unsigned int version)
|
|
Packit Service |
20376f |
{
|
|
Packit Service |
20376f |
GIT_INIT_STRUCTURE_FROM_TEMPLATE(
|
|
Packit Service |
20376f |
backend, version, git_config_backend, GIT_CONFIG_BACKEND_INIT);
|
|
Packit Service |
20376f |
return 0;
|
|
Packit Service |
20376f |
}
|