mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-29 06:20:56 +00:00
Merge pull request #1552 from carlosmn/config-helpers
Config helpers for global/xdg config files
This commit is contained in:
commit
af795759a7
@ -194,6 +194,21 @@ GIT_EXTERN(int) git_config_open_level(
|
||||
const git_config *parent,
|
||||
unsigned int level);
|
||||
|
||||
/**
|
||||
* Open the global/XDG configuration file according to git's rules
|
||||
*
|
||||
* Git allows you to store your global configuration at
|
||||
* `$HOME/.config` or `$XDG_CONFIG_HOME/git/config`. For backwards
|
||||
* compatability, the XDG file shouldn't be used unless the use has
|
||||
* created it explicitly. With this function you'll open the correct
|
||||
* one to write to.
|
||||
*
|
||||
* @param out pointer in which to store the config object
|
||||
* @param config the config object in which to look
|
||||
*/
|
||||
GIT_EXTERN(int) git_config_open_global(git_config **out, git_config *config);
|
||||
|
||||
|
||||
/**
|
||||
* Reload changed config files
|
||||
*
|
||||
|
49
src/config.c
49
src/config.c
@ -91,13 +91,15 @@ int git_config_add_file_ondisk(
|
||||
int force)
|
||||
{
|
||||
git_config_backend *file = NULL;
|
||||
struct stat st;
|
||||
int res;
|
||||
|
||||
assert(cfg && path);
|
||||
|
||||
if (!git_path_isfile(path)) {
|
||||
giterr_set(GITERR_CONFIG, "Cannot find config file '%s'", path);
|
||||
return GIT_ENOTFOUND;
|
||||
res = p_stat(path, &st);
|
||||
if (res < 0 && errno != ENOENT) {
|
||||
giterr_set(GITERR_CONFIG, "Error stat'ing config file '%s'", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (git_config_file__ondisk(&file, path) < 0)
|
||||
@ -225,6 +227,14 @@ static int git_config__add_internal(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_config_open_global(git_config **cfg_out, git_config *cfg)
|
||||
{
|
||||
if (!git_config_open_level(cfg_out, cfg, GIT_CONFIG_LEVEL_XDG))
|
||||
return 0;
|
||||
|
||||
return git_config_open_level(cfg_out, cfg, GIT_CONFIG_LEVEL_GLOBAL);
|
||||
}
|
||||
|
||||
int git_config_open_level(
|
||||
git_config **cfg_out,
|
||||
const git_config *cfg_parent,
|
||||
@ -381,7 +391,6 @@ int git_config_set_string(git_config *cfg, const char *name, const char *value)
|
||||
|
||||
internal = git_vector_get(&cfg->files, 0);
|
||||
if (!internal)
|
||||
/* Should we auto-vivify .git/config? Tricky from this location */
|
||||
return config_error_nofiles(name);
|
||||
file = internal->file;
|
||||
|
||||
@ -598,6 +607,33 @@ int git_config_find_system(char *system_config_path, size_t length)
|
||||
system_config_path, length, git_config_find_system_r);
|
||||
}
|
||||
|
||||
int git_config__global_location(git_buf *buf)
|
||||
{
|
||||
const git_buf *paths;
|
||||
const char *sep, *start;
|
||||
size_t len;
|
||||
|
||||
if (git_futils_dirs_get(&paths, GIT_FUTILS_DIR_GLOBAL) < 0)
|
||||
return -1;
|
||||
|
||||
/* no paths, so give up */
|
||||
if (git_buf_len(paths) == 0)
|
||||
return -1;
|
||||
|
||||
start = git_buf_cstr(paths);
|
||||
sep = strchr(start, GIT_PATH_LIST_SEPARATOR);
|
||||
|
||||
if (sep)
|
||||
len = sep - start;
|
||||
else
|
||||
len = paths->size;
|
||||
|
||||
if (git_buf_set(buf, start, len) < 0)
|
||||
return -1;
|
||||
|
||||
return git_buf_joinpath(buf, buf->ptr, GIT_CONFIG_FILENAME_GLOBAL);
|
||||
}
|
||||
|
||||
int git_config_open_default(git_config **out)
|
||||
{
|
||||
int error;
|
||||
@ -606,9 +642,12 @@ int git_config_open_default(git_config **out)
|
||||
|
||||
error = git_config_new(&cfg);
|
||||
|
||||
if (!error && !git_config_find_global_r(&buf))
|
||||
if (!error && (!git_config_find_global_r(&buf) ||
|
||||
!git_config__global_location(&buf))) {
|
||||
error = git_config_add_file_ondisk(cfg, buf.ptr,
|
||||
GIT_CONFIG_LEVEL_GLOBAL, 0);
|
||||
} else {
|
||||
}
|
||||
|
||||
if (!error && !git_config_find_xdg_r(&buf))
|
||||
error = git_config_add_file_ondisk(cfg, buf.ptr,
|
||||
|
@ -28,6 +28,9 @@ extern int git_config_find_global_r(git_buf *global_config_path);
|
||||
extern int git_config_find_xdg_r(git_buf *system_config_path);
|
||||
extern int git_config_find_system_r(git_buf *system_config_path);
|
||||
|
||||
|
||||
extern int git_config__global_location(git_buf *buf);
|
||||
|
||||
extern int git_config_rename_section(
|
||||
git_repository *repo,
|
||||
const char *old_section_name, /* eg "branch.dummy" */
|
||||
|
@ -594,6 +594,10 @@ int git_repository_config__weakptr(git_config **out, git_repository *repo)
|
||||
git_config_find_xdg_r(&xdg_buf);
|
||||
git_config_find_system_r(&system_buf);
|
||||
|
||||
/* If there is no global file, open a backend for it anyway */
|
||||
if (git_buf_len(&global_buf) == 0)
|
||||
git_config__global_location(&global_buf);
|
||||
|
||||
error = load_config(
|
||||
&config, repo,
|
||||
path_unless_empty(&global_buf),
|
||||
|
67
tests-clar/config/global.c
Normal file
67
tests-clar/config/global.c
Normal file
@ -0,0 +1,67 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "buffer.h"
|
||||
#include "fileops.h"
|
||||
|
||||
void test_config_global__initialize(void)
|
||||
{
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
|
||||
cl_must_pass(p_mkdir("home", 0777));
|
||||
cl_git_pass(git_path_prettify(&path, "home", NULL));
|
||||
cl_git_pass(git_libgit2_opts(
|
||||
GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr));
|
||||
|
||||
cl_must_pass(p_mkdir("xdg", 0777));
|
||||
cl_git_pass(git_path_prettify(&path, "xdg", NULL));
|
||||
cl_git_pass(git_libgit2_opts(
|
||||
GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr));
|
||||
|
||||
cl_git_pass(git_libgit2_opts(
|
||||
GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, NULL));
|
||||
|
||||
git_buf_free(&path);
|
||||
}
|
||||
|
||||
void test_config_global__cleanup(void)
|
||||
{
|
||||
cl_git_pass(git_futils_rmdir_r("home", NULL, GIT_RMDIR_REMOVE_FILES));
|
||||
cl_git_pass(git_futils_rmdir_r("xdg", NULL, GIT_RMDIR_REMOVE_FILES));
|
||||
}
|
||||
|
||||
void test_config_global__open_global(void)
|
||||
{
|
||||
git_config *cfg, *global, *selected, *dummy;
|
||||
|
||||
cl_git_pass(git_config_open_default(&cfg));
|
||||
cl_git_pass(git_config_open_level(&global, cfg, GIT_CONFIG_LEVEL_GLOBAL));
|
||||
cl_git_fail(git_config_open_level(&dummy, cfg, GIT_CONFIG_LEVEL_XDG));
|
||||
cl_git_pass(git_config_open_global(&selected, cfg));
|
||||
|
||||
git_config_free(selected);
|
||||
git_config_free(global);
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
void test_config_global__open_xdg(void)
|
||||
{
|
||||
git_config *cfg, *xdg, *selected;
|
||||
const char *val, *str = "teststring";
|
||||
const char *key = "this.variable";
|
||||
|
||||
p_setenv("XDG_CONFIG_HOME", "xdg", 1);
|
||||
|
||||
cl_must_pass(p_mkdir("xdg/git/", 0777));
|
||||
cl_git_mkfile("xdg/git/config", "");
|
||||
|
||||
cl_git_pass(git_config_open_default(&cfg));
|
||||
cl_git_pass(git_config_open_level(&xdg, cfg, GIT_CONFIG_LEVEL_XDG));
|
||||
cl_git_pass(git_config_open_global(&selected, cfg));
|
||||
|
||||
cl_git_pass(git_config_set_string(xdg, key, str));
|
||||
cl_git_pass(git_config_get_string(&val, selected, key));
|
||||
cl_assert_equal_s(str, val);
|
||||
|
||||
git_config_free(selected);
|
||||
git_config_free(xdg);
|
||||
git_config_free(cfg);
|
||||
}
|
@ -449,10 +449,3 @@ void test_config_read__can_load_and_parse_an_empty_config_file(void)
|
||||
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
void test_config_read__cannot_load_a_non_existing_config_file(void)
|
||||
{
|
||||
git_config *cfg;
|
||||
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, git_config_open_ondisk(&cfg, "./no.config"));
|
||||
}
|
||||
|
75
tests-clar/repo/config.c
Normal file
75
tests-clar/repo/config.c
Normal file
@ -0,0 +1,75 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "fileops.h"
|
||||
#include <ctype.h>
|
||||
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
|
||||
void test_repo_config__initialize(void)
|
||||
{
|
||||
cl_fixture_sandbox("empty_standard_repo");
|
||||
cl_git_pass(cl_rename("empty_standard_repo/.gitted", "empty_standard_repo/.git"));
|
||||
|
||||
git_buf_clear(&path);
|
||||
|
||||
cl_must_pass(p_mkdir("alternate", 0777));
|
||||
cl_git_pass(git_path_prettify(&path, "alternate", NULL));
|
||||
|
||||
}
|
||||
|
||||
void test_repo_config__cleanup(void)
|
||||
{
|
||||
cl_git_pass(git_futils_rmdir_r(path.ptr, NULL, GIT_RMDIR_REMOVE_FILES));
|
||||
|
||||
git_buf_free(&path);
|
||||
cl_fixture_cleanup("empty_standard_repo");
|
||||
}
|
||||
|
||||
void test_repo_config__open_missing_global(void)
|
||||
{
|
||||
git_repository *repo;
|
||||
git_config *config, *global;
|
||||
|
||||
cl_git_pass(git_libgit2_opts(
|
||||
GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr));
|
||||
cl_git_pass(git_libgit2_opts(
|
||||
GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr));
|
||||
cl_git_pass(git_libgit2_opts(
|
||||
GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, path.ptr));
|
||||
|
||||
cl_git_pass(git_repository_open(&repo, "empty_standard_repo"));
|
||||
cl_git_pass(git_repository_config(&config, repo));
|
||||
cl_git_pass(git_config_open_level(&global, config, GIT_CONFIG_LEVEL_GLOBAL));
|
||||
|
||||
cl_git_pass(git_config_set_string(global, "test.set", "42"));
|
||||
|
||||
git_config_free(global);
|
||||
git_config_free(config);
|
||||
git_repository_free(repo);
|
||||
}
|
||||
|
||||
void test_repo_config__open_missing_global_with_separators(void)
|
||||
{
|
||||
git_repository *repo;
|
||||
git_config *config, *global;
|
||||
|
||||
cl_git_pass(git_buf_printf(&path, "%c%s", GIT_PATH_LIST_SEPARATOR, "dummy"));
|
||||
|
||||
cl_git_pass(git_libgit2_opts(
|
||||
GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr));
|
||||
cl_git_pass(git_libgit2_opts(
|
||||
GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr));
|
||||
cl_git_pass(git_libgit2_opts(
|
||||
GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, path.ptr));
|
||||
|
||||
git_buf_free(&path);
|
||||
|
||||
cl_git_pass(git_repository_open(&repo, "empty_standard_repo"));
|
||||
cl_git_pass(git_repository_config(&config, repo));
|
||||
cl_git_pass(git_config_open_level(&global, config, GIT_CONFIG_LEVEL_GLOBAL));
|
||||
|
||||
cl_git_pass(git_config_set_string(global, "test.set", "42"));
|
||||
|
||||
git_config_free(global);
|
||||
git_config_free(config);
|
||||
git_repository_free(repo);
|
||||
}
|
@ -309,7 +309,7 @@ void test_repo_open__no_config(void)
|
||||
cl_git_pass(git_repository_open(&repo, "empty_standard_repo"));
|
||||
cl_git_pass(git_repository_config(&config, repo));
|
||||
|
||||
cl_git_fail(git_config_set_string(config, "test.set", "42"));
|
||||
cl_git_pass(git_config_set_string(config, "test.set", "42"));
|
||||
|
||||
git_config_free(config);
|
||||
git_repository_free(repo);
|
||||
|
Loading…
Reference in New Issue
Block a user