Unverified Commit 0d723f39 by Carlos Martín Nieto Committed by GitHub

Merge pull request #4332 from pks-t/pks/conditional-includes

Conditional includes
parents 990d2b85 42627933
......@@ -199,6 +199,8 @@ GIT_EXTERN(int) git_config_new(git_config **out);
* @param path path to the configuration file to add
* @param level the priority level of the backend
* @param force replace config file at the given priority level
* @param repo optional repository to allow parsing of
* conditional includes
* @return 0 on success, GIT_EEXISTS when adding more than one file
* for a given priority level (and force_replace set to 0),
* GIT_ENOTFOUND when the file doesn't exist or error code
......@@ -207,6 +209,7 @@ GIT_EXTERN(int) git_config_add_file_ondisk(
git_config *cfg,
const char *path,
git_config_level_t level,
const git_repository *repo,
int force);
/**
......
......@@ -440,7 +440,7 @@ typedef enum {
* @param item The repository item for which to retrieve the path
* @return 0, GIT_ENOTFOUND if the path cannot exist or an error code
*/
GIT_EXTERN(int) git_repository_item_path(git_buf *out, git_repository *repo, git_repository_item_t item);
GIT_EXTERN(int) git_repository_item_path(git_buf *out, const git_repository *repo, git_repository_item_t item);
/**
* Get the path of this repository
......@@ -451,7 +451,7 @@ GIT_EXTERN(int) git_repository_item_path(git_buf *out, git_repository *repo, git
* @param repo A repository object
* @return the path to the repository
*/
GIT_EXTERN(const char *) git_repository_path(git_repository *repo);
GIT_EXTERN(const char *) git_repository_path(const git_repository *repo);
/**
* Get the path of the working directory for this repository
......@@ -462,7 +462,7 @@ GIT_EXTERN(const char *) git_repository_path(git_repository *repo);
* @param repo A repository object
* @return the path to the working dir, if it exists
*/
GIT_EXTERN(const char *) git_repository_workdir(git_repository *repo);
GIT_EXTERN(const char *) git_repository_workdir(const git_repository *repo);
/**
* Get the path of the shared common directory for this repository
......@@ -473,7 +473,7 @@ GIT_EXTERN(const char *) git_repository_workdir(git_repository *repo);
* @param repo A repository object
* @return the path to the common dir
*/
GIT_EXTERN(const char *) git_repository_commondir(git_repository *repo);
GIT_EXTERN(const char *) git_repository_commondir(const git_repository *repo);
/**
* Set the path to the working directory for this repository
......@@ -501,7 +501,7 @@ GIT_EXTERN(int) git_repository_set_workdir(
* @param repo Repo to test
* @return 1 if the repository is bare, 0 otherwise.
*/
GIT_EXTERN(int) git_repository_is_bare(git_repository *repo);
GIT_EXTERN(int) git_repository_is_bare(const git_repository *repo);
/**
* Check if a repository is a linked work tree
......@@ -509,7 +509,7 @@ GIT_EXTERN(int) git_repository_is_bare(git_repository *repo);
* @param repo Repo to test
* @return 1 if the repository is a linked work tree, 0 otherwise.
*/
GIT_EXTERN(int) git_repository_is_worktree(git_repository *repo);
GIT_EXTERN(int) git_repository_is_worktree(const git_repository *repo);
/**
* Get the configuration file for this repository.
......
......@@ -58,7 +58,7 @@ struct git_config_backend {
struct git_config *cfg;
/* Open means open the file/database and parse if necessary */
int (*open)(struct git_config_backend *, git_config_level_t level);
int (*open)(struct git_config_backend *, git_config_level_t level, const git_repository *repo);
int (*get)(struct git_config_backend *, const char *key, git_config_entry **entry);
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);
......@@ -111,6 +111,8 @@ GIT_EXTERN(int) git_config_init_backend(
* @param cfg the configuration to add the file to
* @param file the configuration file (backend) to add
* @param level the priority level of the backend
* @param repo optional repository to allow parsing of
* conditional includes
* @param force if a config file already exists for the given
* priority level, replace it
* @return 0 on success, GIT_EEXISTS when adding more than one file
......@@ -120,6 +122,7 @@ GIT_EXTERN(int) git_config_add_backend(
git_config *cfg,
git_config_backend *file,
git_config_level_t level,
const git_repository *repo,
int force);
/** @} */
......
......@@ -99,6 +99,7 @@ int git_config_add_file_ondisk(
git_config *cfg,
const char *path,
git_config_level_t level,
const git_repository *repo,
int force)
{
git_config_backend *file = NULL;
......@@ -116,7 +117,7 @@ int git_config_add_file_ondisk(
if (git_config_file__ondisk(&file, path) < 0)
return -1;
if ((res = git_config_add_backend(cfg, file, level, force)) < 0) {
if ((res = git_config_add_backend(cfg, file, level, repo, force)) < 0) {
/*
* free manually; the file is not owned by the config
* instance yet and will not be freed on cleanup
......@@ -138,7 +139,7 @@ int git_config_open_ondisk(git_config **out, const char *path)
if (git_config_new(&config) < 0)
return -1;
if ((error = git_config_add_file_ondisk(config, path, GIT_CONFIG_LEVEL_LOCAL, 0)) < 0)
if ((error = git_config_add_file_ondisk(config, path, GIT_CONFIG_LEVEL_LOCAL, NULL, 0)) < 0)
git_config_free(config);
else
*out = config;
......@@ -164,7 +165,7 @@ int git_config_snapshot(git_config **out, git_config *in)
if ((error = internal->file->snapshot(&b, internal->file)) < 0)
break;
if ((error = git_config_add_backend(config, b, internal->level, 0)) < 0) {
if ((error = git_config_add_backend(config, b, internal->level, NULL, 0)) < 0) {
b->free(b);
break;
}
......@@ -307,6 +308,7 @@ int git_config_add_backend(
git_config *cfg,
git_config_backend *file,
git_config_level_t level,
const git_repository *repo,
int force)
{
file_internal *internal;
......@@ -316,7 +318,7 @@ int git_config_add_backend(
GITERR_CHECK_VERSION(file, GIT_CONFIG_BACKEND_VERSION, "git_config_backend");
if ((result = file->open(file, level)) < 0)
if ((result = file->open(file, level, repo)) < 0)
return result;
internal = git__malloc(sizeof(file_internal));
......@@ -1147,20 +1149,20 @@ int git_config_open_default(git_config **out)
if (!git_config_find_global(&buf) || !git_config__global_location(&buf)) {
error = git_config_add_file_ondisk(cfg, buf.ptr,
GIT_CONFIG_LEVEL_GLOBAL, 0);
GIT_CONFIG_LEVEL_GLOBAL, NULL, 0);
}
if (!error && !git_config_find_xdg(&buf))
error = git_config_add_file_ondisk(cfg, buf.ptr,
GIT_CONFIG_LEVEL_XDG, 0);
GIT_CONFIG_LEVEL_XDG, NULL, 0);
if (!error && !git_config_find_system(&buf))
error = git_config_add_file_ondisk(cfg, buf.ptr,
GIT_CONFIG_LEVEL_SYSTEM, 0);
GIT_CONFIG_LEVEL_SYSTEM, NULL, 0);
if (!error && !git_config_find_programdata(&buf))
error = git_config_add_file_ondisk(cfg, buf.ptr,
GIT_CONFIG_LEVEL_PROGRAMDATA, 0);
GIT_CONFIG_LEVEL_PROGRAMDATA, NULL, 0);
git_buf_free(&buf);
......
......@@ -105,6 +105,7 @@ typedef struct {
diskfile_header header;
git_config_level_t level;
const git_repository *repo;
bool locked;
git_filebuf locked_buf;
......@@ -119,7 +120,7 @@ typedef struct {
diskfile_backend *snapshot_from;
} diskfile_readonly_backend;
static int config_read(git_strmap *values, struct config_file *file, git_config_level_t level, int depth);
static int config_read(git_strmap *values, const git_repository *repo, struct config_file *file, git_config_level_t level, int depth);
static int config_write(diskfile_backend *cfg, const char *orig_key, const char *key, const regex_t *preg, const char *value);
static char *escape_value(const char *ptr);
......@@ -281,12 +282,13 @@ static void config_file_clear(struct config_file *file)
git__free(file->path);
}
static int config_open(git_config_backend *cfg, git_config_level_t level)
static int config_open(git_config_backend *cfg, git_config_level_t level, const git_repository *repo)
{
int res;
diskfile_backend *b = (diskfile_backend *)cfg;
b->level = level;
b->repo = repo;
if ((res = refcounted_strmap_alloc(&b->header.values)) < 0)
return res;
......@@ -295,7 +297,7 @@ static int config_open(git_config_backend *cfg, git_config_level_t level)
if (!git_path_exists(b->file.path))
return 0;
if (res < 0 || (res = config_read(b->header.values->values, &b->file, level, 0)) < 0) {
if (res < 0 || (res = config_read(b->header.values->values, repo, &b->file, level, 0)) < 0) {
refcounted_strmap_free(b->header.values);
b->header.values = NULL;
}
......@@ -359,7 +361,7 @@ static int config_refresh(git_config_backend *cfg)
}
git_array_clear(b->file.includes);
if ((error = config_read(values->values, &b->file, b->level, 0)) < 0)
if ((error = config_read(values->values, b->repo, &b->file, b->level, 0)) < 0)
goto out;
if ((error = git_mutex_lock(&b->header.values_mutex)) < 0) {
......@@ -439,7 +441,7 @@ static int config_iterator_new(
if ((error = config_snapshot(&snapshot, backend)) < 0)
return error;
if ((error = snapshot->open(snapshot, b->level)) < 0)
if ((error = snapshot->open(snapshot, b->level, b->repo)) < 0)
return error;
it = git__calloc(1, sizeof(git_config_file_iter));
......@@ -831,7 +833,7 @@ static void backend_readonly_free(git_config_backend *_backend)
git__free(backend);
}
static int config_readonly_open(git_config_backend *cfg, git_config_level_t level)
static int config_readonly_open(git_config_backend *cfg, git_config_level_t level, const git_repository *repo)
{
diskfile_readonly_backend *b = (diskfile_readonly_backend *) cfg;
diskfile_backend *src = b->snapshot_from;
......@@ -842,8 +844,9 @@ static int config_readonly_open(git_config_backend *cfg, git_config_level_t leve
if (!src_header->parent.readonly && (error = config_refresh(&src_header->parent)) < 0)
return error;
/* We're just copying data, don't care about the level */
/* We're just copying data, don't care about the level or repo*/
GIT_UNUSED(level);
GIT_UNUSED(repo);
if ((src_map = refcounted_strmap_take(src_header)) == NULL)
return -1;
......@@ -1568,11 +1571,148 @@ static int config_parse(
}
struct parse_data {
const git_repository *repo;
const char *file_path;
git_strmap *values;
git_config_level_t level;
int depth;
};
static int parse_include(struct reader *reader,
struct parse_data *parse_data, const char *file)
{
struct config_file *include;
git_buf path = GIT_BUF_INIT;
char *dir;
int result;
if ((result = git_path_dirname_r(&path, reader->file->path)) < 0)
return result;
dir = git_buf_detach(&path);
result = included_path(&path, dir, file);
git__free(dir);
if (result < 0)
return result;
include = git_array_alloc(reader->file->includes);
memset(include, 0, sizeof(*include));
git_array_init(include->includes);
include->path = git_buf_detach(&path);
result = config_read(parse_data->values, parse_data->repo,
include, parse_data->level, parse_data->depth+1);
if (result == GIT_ENOTFOUND) {
giterr_clear();
result = 0;
}
return result;
}
static int do_match_gitdir(
int *matches,
const git_repository *repo,
const char *cfg_file,
const char *value,
bool case_insensitive)
{
git_buf path = GIT_BUF_INIT;
int error, fnmatch_flags;
if (value[0] == '.' && git_path_is_dirsep(value[1])) {
git_path_dirname_r(&path, cfg_file);
git_buf_joinpath(&path, path.ptr, value + 2);
} else if (value[0] == '~' && git_path_is_dirsep(value[1]))
git_sysdir_expand_global_file(&path, value + 1);
else if (!git_path_is_absolute(value))
git_buf_joinpath(&path, "**", value);
else
git_buf_sets(&path, value);
if (git_buf_oom(&path)) {
error = -1;
goto out;
}
if (git_path_is_dirsep(value[strlen(value) - 1]))
git_buf_puts(&path, "**");
fnmatch_flags = FNM_PATHNAME|FNM_LEADING_DIR;
if (case_insensitive)
fnmatch_flags |= FNM_IGNORECASE;
if ((error = p_fnmatch(path.ptr, git_repository_path(repo), fnmatch_flags)) < 0)
goto out;
*matches = (error == 0);
out:
git_buf_free(&path);
return error;
}
static int conditional_match_gitdir(
int *matches,
const git_repository *repo,
const char *cfg_file,
const char *value)
{
return do_match_gitdir(matches, repo, cfg_file, value, false);
}
static int conditional_match_gitdir_i(
int *matches,
const git_repository *repo,
const char *cfg_file,
const char *value)
{
return do_match_gitdir(matches, repo, cfg_file, value, true);
}
static const struct {
const char *prefix;
int (*matches)(int *matches, const git_repository *repo, const char *cfg, const char *value);
} conditions[] = {
{ "gitdir:", conditional_match_gitdir },
{ "gitdir/i:", conditional_match_gitdir_i }
};
static int parse_conditional_include(struct reader *reader,
struct parse_data *parse_data, const char *section, const char *file)
{
char *condition;
size_t i;
int error = 0, matches;
if (!parse_data->repo)
return 0;
condition = git__substrdup(section + strlen("includeIf."),
strlen(section) - strlen("includeIf.") - strlen(".path"));
for (i = 0; i < ARRAY_SIZE(conditions); i++) {
if (git__prefixcmp(condition, conditions[i].prefix))
continue;
if ((error = conditions[i].matches(&matches,
parse_data->repo,
parse_data->file_path,
condition + strlen(conditions[i].prefix))) < 0)
break;
if (matches)
error = parse_include(reader, parse_data, file);
break;
}
git__free(condition);
return error;
}
static int read_on_variable(
struct reader *reader,
const char *current_section,
......@@ -1615,38 +1755,23 @@ static int read_on_variable(
result = 0;
/* Add or append the new config option */
if (!git__strcmp(var->entry->name, "include.path")) {
struct config_file *include;
git_buf path = GIT_BUF_INIT;
char *dir;
if ((result = git_path_dirname_r(&path, reader->file->path)) < 0)
return result;
dir = git_buf_detach(&path);
result = included_path(&path, dir, var->entry->value);
git__free(dir);
if (result < 0)
return result;
if (!git__strcmp(var->entry->name, "include.path"))
result = parse_include(reader, parse_data, var->entry->value);
else if (!git__prefixcmp(var->entry->name, "includeif.") &&
!git__suffixcmp(var->entry->name, ".path"))
result = parse_conditional_include(reader, parse_data,
var->entry->name, var->entry->value);
include = git_array_alloc(reader->file->includes);
memset(include, 0, sizeof(*include));
git_array_init(include->includes);
include->path = git_buf_detach(&path);
result = config_read(parse_data->values, include, parse_data->level, parse_data->depth+1);
if (result == GIT_ENOTFOUND) {
giterr_clear();
result = 0;
}
}
return result;
}
static int config_read(git_strmap *values, struct config_file *file, git_config_level_t level, int depth)
static int config_read(
git_strmap *values,
const git_repository *repo,
struct config_file *file,
git_config_level_t level,
int depth)
{
struct parse_data parse_data;
struct reader reader;
......@@ -1675,6 +1800,8 @@ static int config_read(git_strmap *values, struct config_file *file, git_config_
if (*reader.read_ptr == '\0')
goto out;
parse_data.repo = repo;
parse_data.file_path = file->path;
parse_data.values = values;
parse_data.level = level;
parse_data.depth = depth;
......
......@@ -12,9 +12,9 @@
#include "git2/sys/config.h"
#include "git2/config.h"
GIT_INLINE(int) git_config_file_open(git_config_backend *cfg, unsigned int level)
GIT_INLINE(int) git_config_file_open(git_config_backend *cfg, unsigned int level, const git_repository *repo)
{
return cfg->open(cfg, level);
return cfg->open(cfg, level, repo);
}
GIT_INLINE(void) git_config_file_free(git_config_backend *cfg)
......
......@@ -105,6 +105,12 @@ GIT_INLINE(int) git_path_is_dot_or_dotdotW(const wchar_t *name)
(name[1] == L'.' && name[2] == L'\0')));
}
#define git_path_is_absolute(p) \
(git__isalpha((p)[0]) && (p)[1] == ':' && ((p)[2] == '\\' || (p)[2] == '/'))
#define git_path_is_dirsep(p) \
((p) == '/' || (p) == '\\')
/**
* Convert backslashes in path to forward slashes.
*/
......@@ -119,6 +125,13 @@ GIT_INLINE(void) git_path_mkposix(char *path)
}
#else
# define git_path_mkposix(p) /* blank */
#define git_path_is_absolute(p) \
((p)[0] == '/')
#define git_path_is_dirsep(p) \
((p) == '/')
#endif
/**
......
......@@ -946,7 +946,7 @@ static int load_config(
return error;
if ((error = git_repository_item_path(&config_path, repo, GIT_REPOSITORY_ITEM_CONFIG)) == 0)
error = git_config_add_file_ondisk(cfg, config_path.ptr, GIT_CONFIG_LEVEL_LOCAL, 0);
error = git_config_add_file_ondisk(cfg, config_path.ptr, GIT_CONFIG_LEVEL_LOCAL, repo, 0);
if (error && error != GIT_ENOTFOUND)
goto on_error;
......@@ -955,25 +955,25 @@ static int load_config(
if (global_config_path != NULL &&
(error = git_config_add_file_ondisk(
cfg, global_config_path, GIT_CONFIG_LEVEL_GLOBAL, 0)) < 0 &&
cfg, global_config_path, GIT_CONFIG_LEVEL_GLOBAL, repo, 0)) < 0 &&
error != GIT_ENOTFOUND)
goto on_error;
if (xdg_config_path != NULL &&
(error = git_config_add_file_ondisk(
cfg, xdg_config_path, GIT_CONFIG_LEVEL_XDG, 0)) < 0 &&
cfg, xdg_config_path, GIT_CONFIG_LEVEL_XDG, repo, 0)) < 0 &&
error != GIT_ENOTFOUND)
goto on_error;
if (system_config_path != NULL &&
(error = git_config_add_file_ondisk(
cfg, system_config_path, GIT_CONFIG_LEVEL_SYSTEM, 0)) < 0 &&
cfg, system_config_path, GIT_CONFIG_LEVEL_SYSTEM, repo, 0)) < 0 &&
error != GIT_ENOTFOUND)
goto on_error;
if (programdata_path != NULL &&
(error = git_config_add_file_ondisk(
cfg, programdata_path, GIT_CONFIG_LEVEL_PROGRAMDATA, 0)) < 0 &&
cfg, programdata_path, GIT_CONFIG_LEVEL_PROGRAMDATA, repo, 0)) < 0 &&
error != GIT_ENOTFOUND)
goto on_error;
......@@ -1475,7 +1475,7 @@ static int repo_local_config(
giterr_clear();
if (!(error = git_config_add_file_ondisk(
parent, cfg_path, GIT_CONFIG_LEVEL_LOCAL, false)))
parent, cfg_path, GIT_CONFIG_LEVEL_LOCAL, repo, false)))
error = git_config_open_level(out, parent, GIT_CONFIG_LEVEL_LOCAL);
}
......@@ -2256,7 +2256,7 @@ int git_repository_is_empty(git_repository *repo)
return is_empty;
}
int git_repository_item_path(git_buf *out, git_repository *repo, git_repository_item_t item)
int git_repository_item_path(git_buf *out, const git_repository *repo, git_repository_item_t item)
{
const char *parent;
......@@ -2296,13 +2296,13 @@ int git_repository_item_path(git_buf *out, git_repository *repo, git_repository_
return 0;
}
const char *git_repository_path(git_repository *repo)
const char *git_repository_path(const git_repository *repo)
{
assert(repo);
return repo->gitdir;
}
const char *git_repository_workdir(git_repository *repo)
const char *git_repository_workdir(const git_repository *repo)
{
assert(repo);
......@@ -2312,7 +2312,7 @@ const char *git_repository_workdir(git_repository *repo)
return repo->workdir;
}
const char *git_repository_commondir(git_repository *repo)
const char *git_repository_commondir(const git_repository *repo)
{
assert(repo);
return repo->commondir;
......@@ -2362,13 +2362,13 @@ int git_repository_set_workdir(
return error;
}
int git_repository_is_bare(git_repository *repo)
int git_repository_is_bare(const git_repository *repo)
{
assert(repo);
return repo->is_bare;
}
int git_repository_is_worktree(git_repository *repo)
int git_repository_is_worktree(const git_repository *repo)
{
assert(repo);
return repo->is_worktree;
......
......@@ -1960,7 +1960,7 @@ static git_config_backend *open_gitmodules(
if (git_config_file__ondisk(&mods, path.ptr) < 0)
mods = NULL;
/* open should only fail here if the file is malformed */
else if (git_config_file_open(mods, GIT_CONFIG_LEVEL_LOCAL) < 0) {
else if (git_config_file_open(mods, GIT_CONFIG_LEVEL_LOCAL, repo) < 0) {
git_config_file_free(mods);
mods = NULL;
}
......
......@@ -18,11 +18,6 @@
#define PATH__ABSOLUTE_LEN 3
#define path__is_dirsep(p) ((p) == '/' || (p) == '\\')
#define path__is_absolute(p) \
(git__isalpha((p)[0]) && (p)[1] == ':' && ((p)[2] == '\\' || (p)[2] == '/'))
#define path__is_nt_namespace(p) \
(((p)[0] == '\\' && (p)[1] == '\\' && (p)[2] == '?' && (p)[3] == '\\') || \
((p)[0] == '/' && (p)[1] == '/' && (p)[2] == '?' && (p)[3] == '/'))
......@@ -59,7 +54,7 @@ static wchar_t *path__skip_server(wchar_t *path)
wchar_t *c;
for (c = path; *c; c++) {
if (path__is_dirsep(*c))
if (git_path_is_dirsep(*c))
return c + 1;
}
......@@ -73,9 +68,9 @@ static wchar_t *path__skip_prefix(wchar_t *path)
if (wcsncmp(path, L"UNC\\", 4) == 0)
path = path__skip_server(path + 4);
else if (path__is_absolute(path))
else if (git_path_is_absolute(path))
path += PATH__ABSOLUTE_LEN;
} else if (path__is_absolute(path)) {
} else if (git_path_is_absolute(path)) {
path += PATH__ABSOLUTE_LEN;
} else if (path__is_unc(path)) {
path = path__skip_server(path + 2);
......@@ -196,7 +191,7 @@ int git_win32_path_from_utf8(git_win32_path out, const char *src)
dest += PATH__NT_NAMESPACE_LEN;
/* See if this is an absolute path (beginning with a drive letter) */
if (path__is_absolute(src)) {
if (git_path_is_absolute(src)) {
if (git__utf8_to_16(dest, MAX_PATH, src) < 0)
goto on_error;
}
......@@ -220,7 +215,7 @@ int git_win32_path_from_utf8(git_win32_path out, const char *src)
if (path__cwd(dest, MAX_PATH) < 0)
goto on_error;
if (!path__is_absolute(dest)) {
if (!git_path_is_absolute(dest)) {
errno = ENOENT;
goto on_error;
}
......
......@@ -10,13 +10,13 @@ void test_config_backend__checks_version(void)
backend.version = 1024;
cl_git_pass(git_config_new(&cfg));
cl_git_fail(git_config_add_backend(cfg, &backend, 0, false));
cl_git_fail(git_config_add_backend(cfg, &backend, 0, NULL, false));
err = giterr_last();
cl_assert_equal_i(GITERR_INVALID, err->klass);
giterr_clear();
backend.version = 1024;
cl_git_fail(git_config_add_backend(cfg, &backend, 0, false));
cl_git_fail(git_config_add_backend(cfg, &backend, 0, NULL, false));
err = giterr_last();
cl_assert_equal_i(GITERR_INVALID, err->klass);
......
#include "clar_libgit2.h"
#include "buffer.h"
#include "fileops.h"
#ifdef GIT_WIN32
# define ROOT_PREFIX "C:"
#else
# define ROOT_PREFIX
#endif
static git_repository *_repo;
void test_config_conditionals__initialize(void)
{
_repo = cl_git_sandbox_init("empty_standard_repo");
}
void test_config_conditionals__cleanup(void)
{
cl_git_sandbox_cleanup();
}
static void assert_condition_includes(const char *keyword, const char *path, bool expected)
{
git_config *cfg;
git_buf buf = GIT_BUF_INIT;
git_buf_printf(&buf, "[includeIf \"%s:%s\"]\n", keyword, path);
git_buf_puts(&buf, "path = other\n");
cl_git_mkfile("empty_standard_repo/.git/config", buf.ptr);
cl_git_mkfile("empty_standard_repo/.git/other", "[foo]\nbar=baz\n");
_repo = cl_git_sandbox_reopen();
cl_git_pass(git_repository_config(&cfg, _repo));
if (expected) {
git_buf_clear(&buf);
cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar"));
cl_assert_equal_s("baz", git_buf_cstr(&buf));
} else {
cl_git_fail_with(GIT_ENOTFOUND,
git_config_get_string_buf(&buf, cfg, "foo.bar"));
}
git_buf_free(&buf);
git_config_free(cfg);
}
void test_config_conditionals__gitdir(void)
{
git_buf path = GIT_BUF_INIT;
char *sandbox_path;
assert_condition_includes("gitdir", ROOT_PREFIX "/", true);
assert_condition_includes("gitdir", "empty_standard_repo", true);
assert_condition_includes("gitdir", "empty_standard_repo/", true);
assert_condition_includes("gitdir", "./", true);
assert_condition_includes("gitdir", ROOT_PREFIX "/nonexistent", false);
assert_condition_includes("gitdir", ROOT_PREFIX "/empty_standard_repo", false);
assert_condition_includes("gitdir", "empty_stand", false);
assert_condition_includes("gitdir", "~/empty_standard_repo", false);
sandbox_path = p_realpath(clar_sandbox_path(), NULL);
git_buf_joinpath(&path, sandbox_path, "/");
assert_condition_includes("gitdir", path.ptr, true);
git_buf_joinpath(&path, sandbox_path, "/*");
assert_condition_includes("gitdir", path.ptr, true);
git_buf_joinpath(&path, sandbox_path, "empty_standard_repo");
assert_condition_includes("gitdir", path.ptr, true);
git_buf_joinpath(&path, sandbox_path, "Empty_Standard_Repo");
assert_condition_includes("gitdir", path.ptr, false);
git__free(sandbox_path);
git_buf_free(&path);
}
void test_config_conditionals__gitdir_i(void)
{
git_buf path = GIT_BUF_INIT;
char *sandbox_path;
sandbox_path = p_realpath(clar_sandbox_path(), NULL);
git_buf_joinpath(&path, sandbox_path, "empty_standard_repo");
assert_condition_includes("gitdir/i", path.ptr, true);
git_buf_joinpath(&path, sandbox_path, "EMPTY_STANDARD_REPO");
assert_condition_includes("gitdir/i", path.ptr, true);
git__free(sandbox_path);
git_buf_free(&path);
}
void test_config_conditionals__invalid_conditional_fails(void)
{
assert_condition_includes("foobar", ".git", false);
}
......@@ -7,11 +7,11 @@ void test_config_configlevel__adding_the_same_level_twice_returns_EEXISTS(void)
cl_git_pass(git_config_new(&cfg));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"),
GIT_CONFIG_LEVEL_LOCAL, 0));
GIT_CONFIG_LEVEL_LOCAL, NULL, 0));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"),
GIT_CONFIG_LEVEL_GLOBAL, 0));
GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
error = git_config_add_file_ondisk(cfg, cl_fixture("config/config16"),
GIT_CONFIG_LEVEL_GLOBAL, 0);
GIT_CONFIG_LEVEL_GLOBAL, NULL, 0);
cl_git_fail(error);
cl_assert_equal_i(GIT_EEXISTS, error);
......@@ -26,9 +26,9 @@ void test_config_configlevel__can_replace_a_config_file_at_an_existing_level(voi
cl_git_pass(git_config_new(&cfg));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config18"),
GIT_CONFIG_LEVEL_LOCAL, 1));
GIT_CONFIG_LEVEL_LOCAL, NULL, 1));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config19"),
GIT_CONFIG_LEVEL_LOCAL, 1));
GIT_CONFIG_LEVEL_LOCAL, NULL, 1));
cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.stringglobal"));
cl_assert_equal_s("don't find me!", buf.ptr);
......@@ -45,9 +45,9 @@ void test_config_configlevel__can_read_from_a_single_level_focused_file_after_pa
cl_git_pass(git_config_new(&cfg));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config18"),
GIT_CONFIG_LEVEL_GLOBAL, 0));
GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config19"),
GIT_CONFIG_LEVEL_LOCAL, 0));
GIT_CONFIG_LEVEL_LOCAL, NULL, 0));
cl_git_pass(git_config_open_level(&single_level_cfg, cfg, GIT_CONFIG_LEVEL_LOCAL));
......
......@@ -94,27 +94,27 @@ void test_config_multivar__get(void)
check_get_multivar_foreach(cfg, 2, 1);
/* add another that has the _name entry */
cl_git_pass(git_config_add_file_ondisk(cfg, "config/config9", GIT_CONFIG_LEVEL_SYSTEM, 1));
cl_git_pass(git_config_add_file_ondisk(cfg, "config/config9", GIT_CONFIG_LEVEL_SYSTEM, NULL, 1));
check_get_multivar_foreach(cfg, 3, 2);
/* add another that does not have the _name entry */
cl_git_pass(git_config_add_file_ondisk(cfg, "config/config0", GIT_CONFIG_LEVEL_GLOBAL, 1));
cl_git_pass(git_config_add_file_ondisk(cfg, "config/config0", GIT_CONFIG_LEVEL_GLOBAL, NULL, 1));
check_get_multivar_foreach(cfg, 3, 2);
/* add another that does not have the _name entry at the end */
cl_git_pass(git_config_add_file_ondisk(cfg, "config/config1", GIT_CONFIG_LEVEL_APP, 1));
cl_git_pass(git_config_add_file_ondisk(cfg, "config/config1", GIT_CONFIG_LEVEL_APP, NULL, 1));
check_get_multivar_foreach(cfg, 3, 2);
/* drop original file */
cl_git_pass(git_config_add_file_ondisk(cfg, "config/config2", GIT_CONFIG_LEVEL_LOCAL, 1));
cl_git_pass(git_config_add_file_ondisk(cfg, "config/config2", GIT_CONFIG_LEVEL_LOCAL, NULL, 1));
check_get_multivar_foreach(cfg, 1, 1);
/* drop other file with match */
cl_git_pass(git_config_add_file_ondisk(cfg, "config/config3", GIT_CONFIG_LEVEL_SYSTEM, 1));
cl_git_pass(git_config_add_file_ondisk(cfg, "config/config3", GIT_CONFIG_LEVEL_SYSTEM, NULL, 1));
check_get_multivar_foreach(cfg, 0, 0);
/* reload original file (add different place in order) */
cl_git_pass(git_config_add_file_ondisk(cfg, "config/config11", GIT_CONFIG_LEVEL_SYSTEM, 1));
cl_git_pass(git_config_add_file_ondisk(cfg, "config/config11", GIT_CONFIG_LEVEL_SYSTEM, NULL, 1));
check_get_multivar_foreach(cfg, 2, 1);
check_get_multivar(cfg, 2);
......
......@@ -289,9 +289,9 @@ void test_config_read__foreach(void)
cl_git_pass(git_config_new(&cfg));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"),
GIT_CONFIG_LEVEL_SYSTEM, 0));
GIT_CONFIG_LEVEL_SYSTEM, NULL, 0));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"),
GIT_CONFIG_LEVEL_GLOBAL, 0));
GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
count = 0;
cl_git_pass(git_config_foreach(cfg, count_cfg_entries_and_compare_levels, &count));
......@@ -313,9 +313,9 @@ void test_config_read__iterator(void)
cl_git_pass(git_config_new(&cfg));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"),
GIT_CONFIG_LEVEL_SYSTEM, 0));
GIT_CONFIG_LEVEL_SYSTEM, NULL, 0));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"),
GIT_CONFIG_LEVEL_GLOBAL, 0));
GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
count = 0;
cl_git_pass(git_config_iterator_new(&iter, cfg));
......@@ -445,7 +445,7 @@ void test_config_read__read_git_config_entry(void)
cl_git_pass(git_config_new(&cfg));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"),
GIT_CONFIG_LEVEL_SYSTEM, 0));
GIT_CONFIG_LEVEL_SYSTEM, NULL, 0));
cl_git_pass(git_config_get_entry(&entry, cfg, "core.dummy2"));
cl_assert_equal_s("core.dummy2", entry->name);
......@@ -469,11 +469,11 @@ void test_config_read__local_config_overrides_global_config_overrides_system_con
cl_git_pass(git_config_new(&cfg));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"),
GIT_CONFIG_LEVEL_SYSTEM, 0));
GIT_CONFIG_LEVEL_SYSTEM, NULL, 0));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"),
GIT_CONFIG_LEVEL_GLOBAL, 0));
GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config16"),
GIT_CONFIG_LEVEL_LOCAL, 0));
GIT_CONFIG_LEVEL_LOCAL, NULL, 0));
cl_git_pass(git_config_get_int32(&i, cfg, "core.dummy2"));
cl_assert_equal_i(28, i);
......@@ -482,9 +482,9 @@ void test_config_read__local_config_overrides_global_config_overrides_system_con
cl_git_pass(git_config_new(&cfg));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"),
GIT_CONFIG_LEVEL_SYSTEM, 0));
GIT_CONFIG_LEVEL_SYSTEM, NULL, 0));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"),
GIT_CONFIG_LEVEL_GLOBAL, 0));
GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
cl_git_pass(git_config_get_int32(&i, cfg, "core.dummy2"));
cl_assert_equal_i(7, i);
......@@ -510,11 +510,11 @@ void test_config_read__fallback_from_local_to_global_and_from_global_to_system(v
cl_git_pass(git_config_new(&cfg));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"),
GIT_CONFIG_LEVEL_SYSTEM, 0));
GIT_CONFIG_LEVEL_SYSTEM, NULL, 0));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"),
GIT_CONFIG_LEVEL_GLOBAL, 0));
GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config16"),
GIT_CONFIG_LEVEL_LOCAL, 0));
GIT_CONFIG_LEVEL_LOCAL, NULL, 0));
cl_git_pass(git_config_get_int32(&i, cfg, "core.global"));
cl_assert_equal_i(17, i);
......@@ -546,9 +546,9 @@ void test_config_read__simple_read_from_specific_level(void)
cl_git_pass(git_config_new(&cfg));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config18"),
GIT_CONFIG_LEVEL_GLOBAL, 0));
GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config19"),
GIT_CONFIG_LEVEL_SYSTEM, 0));
GIT_CONFIG_LEVEL_SYSTEM, NULL, 0));
cl_git_pass(git_config_open_level(&cfg_specific, cfg, GIT_CONFIG_LEVEL_GLOBAL));
......
......@@ -22,7 +22,7 @@ void test_config_readonly__writing_to_readonly_fails(void)
cl_git_pass(git_config_file__ondisk(&backend, "global"));
backend->readonly = 1;
cl_git_pass(git_config_add_backend(cfg, backend, GIT_CONFIG_LEVEL_GLOBAL, 0));
cl_git_pass(git_config_add_backend(cfg, backend, GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
cl_git_fail_with(GIT_ENOTFOUND, git_config_set_string(cfg, "foo.bar", "baz"));
cl_assert(!git_path_exists("global"));
......@@ -34,10 +34,10 @@ void test_config_readonly__writing_to_cfg_with_rw_precedence_succeeds(void)
cl_git_pass(git_config_file__ondisk(&backend, "global"));
backend->readonly = 1;
cl_git_pass(git_config_add_backend(cfg, backend, GIT_CONFIG_LEVEL_GLOBAL, 0));
cl_git_pass(git_config_add_backend(cfg, backend, GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
cl_git_pass(git_config_file__ondisk(&backend, "local"));
cl_git_pass(git_config_add_backend(cfg, backend, GIT_CONFIG_LEVEL_LOCAL, 0));
cl_git_pass(git_config_add_backend(cfg, backend, GIT_CONFIG_LEVEL_LOCAL, NULL, 0));
cl_git_pass(git_config_set_string(cfg, "foo.bar", "baz"));
......@@ -52,10 +52,10 @@ void test_config_readonly__writing_to_cfg_with_ro_precedence_succeeds(void)
cl_git_pass(git_config_file__ondisk(&backend, "local"));
backend->readonly = 1;
cl_git_pass(git_config_add_backend(cfg, backend, GIT_CONFIG_LEVEL_LOCAL, 0));
cl_git_pass(git_config_add_backend(cfg, backend, GIT_CONFIG_LEVEL_LOCAL, NULL, 0));
cl_git_pass(git_config_file__ondisk(&backend, "global"));
cl_git_pass(git_config_add_backend(cfg, backend, GIT_CONFIG_LEVEL_GLOBAL, 0));
cl_git_pass(git_config_add_backend(cfg, backend, GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
cl_git_pass(git_config_set_string(cfg, "foo.bar", "baz"));
......
......@@ -93,9 +93,9 @@ void test_config_write__delete_value_at_specific_level(void)
cl_git_pass(git_config_new(&cfg));
cl_git_pass(git_config_add_file_ondisk(cfg, "config9",
GIT_CONFIG_LEVEL_LOCAL, 0));
GIT_CONFIG_LEVEL_LOCAL, NULL, 0));
cl_git_pass(git_config_add_file_ondisk(cfg, "config15",
GIT_CONFIG_LEVEL_GLOBAL, 0));
GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
cl_git_pass(git_config_open_level(&cfg_specific, cfg, GIT_CONFIG_LEVEL_GLOBAL));
......@@ -368,9 +368,9 @@ void test_config_write__add_value_at_specific_level(void)
// open config15 as global level config file
cl_git_pass(git_config_new(&cfg));
cl_git_pass(git_config_add_file_ondisk(cfg, "config9",
GIT_CONFIG_LEVEL_LOCAL, 0));
GIT_CONFIG_LEVEL_LOCAL, NULL, 0));
cl_git_pass(git_config_add_file_ondisk(cfg, "config15",
GIT_CONFIG_LEVEL_GLOBAL, 0));
GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
cl_git_pass(git_config_open_level(&cfg_specific, cfg, GIT_CONFIG_LEVEL_GLOBAL));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment