mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-05 07:54:05 +00:00
Merge pull request #2138 from ethomson/sysdir
Move system directory cache out of utils
This commit is contained in:
commit
cb81c3a764
@ -1,6 +1,6 @@
|
||||
#include "common.h"
|
||||
#include "repository.h"
|
||||
#include "fileops.h"
|
||||
#include "sysdir.h"
|
||||
#include "config.h"
|
||||
#include "attr.h"
|
||||
#include "ignore.h"
|
||||
@ -589,7 +589,7 @@ static int collect_attr_files(
|
||||
}
|
||||
|
||||
if ((flags & GIT_ATTR_CHECK_NO_SYSTEM) == 0) {
|
||||
error = git_futils_find_system_file(&dir, GIT_ATTR_FILE_SYSTEM);
|
||||
error = git_sysdir_find_system_file(&dir, GIT_ATTR_FILE_SYSTEM);
|
||||
if (!error)
|
||||
error = push_attr_file(repo, files, NULL, dir.ptr);
|
||||
else if (error == GIT_ENOTFOUND) {
|
||||
@ -623,13 +623,13 @@ static int attr_cache__lookup_path(
|
||||
|
||||
/* expand leading ~/ as needed */
|
||||
if (cfgval && cfgval[0] == '~' && cfgval[1] == '/' &&
|
||||
!git_futils_find_global_file(&buf, &cfgval[2]))
|
||||
!git_sysdir_find_global_file(&buf, &cfgval[2]))
|
||||
*out = git_buf_detach(&buf);
|
||||
else if (cfgval)
|
||||
*out = git__strdup(cfgval);
|
||||
|
||||
}
|
||||
else if (!git_futils_find_xdg_file(&buf, fallback))
|
||||
else if (!git_sysdir_find_xdg_file(&buf, fallback))
|
||||
*out = git_buf_detach(&buf);
|
||||
|
||||
git_buf_free(&buf);
|
||||
|
10
src/config.c
10
src/config.c
@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "fileops.h"
|
||||
#include "sysdir.h"
|
||||
#include "config.h"
|
||||
#include "git2/config.h"
|
||||
#include "git2/sys/config.h"
|
||||
@ -937,17 +937,17 @@ void git_config_iterator_free(git_config_iterator *iter)
|
||||
|
||||
int git_config_find_global(git_buf *path)
|
||||
{
|
||||
return git_futils_find_global_file(path, GIT_CONFIG_FILENAME_GLOBAL);
|
||||
return git_sysdir_find_global_file(path, GIT_CONFIG_FILENAME_GLOBAL);
|
||||
}
|
||||
|
||||
int git_config_find_xdg(git_buf *path)
|
||||
{
|
||||
return git_futils_find_xdg_file(path, GIT_CONFIG_FILENAME_XDG);
|
||||
return git_sysdir_find_xdg_file(path, GIT_CONFIG_FILENAME_XDG);
|
||||
}
|
||||
|
||||
int git_config_find_system(git_buf *path)
|
||||
{
|
||||
return git_futils_find_system_file(path, GIT_CONFIG_FILENAME_SYSTEM);
|
||||
return git_sysdir_find_system_file(path, GIT_CONFIG_FILENAME_SYSTEM);
|
||||
}
|
||||
|
||||
int git_config__global_location(git_buf *buf)
|
||||
@ -956,7 +956,7 @@ int git_config__global_location(git_buf *buf)
|
||||
const char *sep, *start;
|
||||
size_t len;
|
||||
|
||||
if (git_futils_dirs_get(&paths, GIT_FUTILS_DIR_GLOBAL) < 0)
|
||||
if (git_sysdir_get(&paths, GIT_SYSDIR_GLOBAL) < 0)
|
||||
return -1;
|
||||
|
||||
/* no paths, so give up */
|
||||
|
@ -7,8 +7,8 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "config.h"
|
||||
#include "fileops.h"
|
||||
#include "filebuf.h"
|
||||
#include "sysdir.h"
|
||||
#include "buffer.h"
|
||||
#include "buf_text.h"
|
||||
#include "git2/config.h"
|
||||
@ -1003,7 +1003,7 @@ static int included_path(git_buf *out, const char *dir, const char *path)
|
||||
{
|
||||
/* From the user's home */
|
||||
if (path[0] == '~' && path[1] == '/')
|
||||
return git_futils_find_global_file(out, &path[1]);
|
||||
return git_sysdir_find_global_file(out, &path[1]);
|
||||
|
||||
return git_path_join_unrooted(out, path, dir, NULL);
|
||||
}
|
||||
|
220
src/fileops.c
220
src/fileops.c
@ -558,226 +558,6 @@ int git_futils_rmdir_r(
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static int git_futils_guess_system_dirs(git_buf *out)
|
||||
{
|
||||
#ifdef GIT_WIN32
|
||||
return git_win32__find_system_dirs(out, L"etc\\");
|
||||
#else
|
||||
return git_buf_sets(out, "/etc");
|
||||
#endif
|
||||
}
|
||||
|
||||
static int git_futils_guess_global_dirs(git_buf *out)
|
||||
{
|
||||
#ifdef GIT_WIN32
|
||||
return git_win32__find_global_dirs(out);
|
||||
#else
|
||||
return git_buf_sets(out, getenv("HOME"));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int git_futils_guess_xdg_dirs(git_buf *out)
|
||||
{
|
||||
#ifdef GIT_WIN32
|
||||
return git_win32__find_xdg_dirs(out);
|
||||
#else
|
||||
const char *env = NULL;
|
||||
|
||||
if ((env = getenv("XDG_CONFIG_HOME")) != NULL)
|
||||
return git_buf_joinpath(out, env, "git");
|
||||
else if ((env = getenv("HOME")) != NULL)
|
||||
return git_buf_joinpath(out, env, ".config/git");
|
||||
|
||||
git_buf_clear(out);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int git_futils_guess_template_dirs(git_buf *out)
|
||||
{
|
||||
#ifdef GIT_WIN32
|
||||
return git_win32__find_system_dirs(out, L"share\\git-core\\templates");
|
||||
#else
|
||||
return git_buf_sets(out, "/usr/share/git-core/templates");
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef int (*git_futils_dirs_guess_cb)(git_buf *out);
|
||||
|
||||
static git_buf git_futils__dirs[GIT_FUTILS_DIR__MAX] =
|
||||
{ GIT_BUF_INIT, GIT_BUF_INIT, GIT_BUF_INIT, GIT_BUF_INIT };
|
||||
|
||||
static git_futils_dirs_guess_cb git_futils__dir_guess[GIT_FUTILS_DIR__MAX] = {
|
||||
git_futils_guess_system_dirs,
|
||||
git_futils_guess_global_dirs,
|
||||
git_futils_guess_xdg_dirs,
|
||||
git_futils_guess_template_dirs,
|
||||
};
|
||||
|
||||
static int git_futils__dirs_shutdown_set = 0;
|
||||
|
||||
void git_futils_dirs_global_shutdown(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < GIT_FUTILS_DIR__MAX; ++i)
|
||||
git_buf_free(&git_futils__dirs[i]);
|
||||
}
|
||||
|
||||
int git_futils_dirs_global_init(void)
|
||||
{
|
||||
git_futils_dir_t i;
|
||||
const git_buf *path;
|
||||
int error = 0;
|
||||
|
||||
for (i = 0; !error && i < GIT_FUTILS_DIR__MAX; i++)
|
||||
error = git_futils_dirs_get(&path, i);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int git_futils_check_selector(git_futils_dir_t which)
|
||||
{
|
||||
if (which < GIT_FUTILS_DIR__MAX)
|
||||
return 0;
|
||||
giterr_set(GITERR_INVALID, "config directory selector out of range");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int git_futils_dirs_get(const git_buf **out, git_futils_dir_t which)
|
||||
{
|
||||
assert(out);
|
||||
|
||||
*out = NULL;
|
||||
|
||||
GITERR_CHECK_ERROR(git_futils_check_selector(which));
|
||||
|
||||
if (!git_buf_len(&git_futils__dirs[which])) {
|
||||
/* prepare shutdown if we're going to need it */
|
||||
if (!git_futils__dirs_shutdown_set) {
|
||||
git__on_shutdown(git_futils_dirs_global_shutdown);
|
||||
git_futils__dirs_shutdown_set = 1;
|
||||
}
|
||||
|
||||
GITERR_CHECK_ERROR(
|
||||
git_futils__dir_guess[which](&git_futils__dirs[which]));
|
||||
}
|
||||
|
||||
*out = &git_futils__dirs[which];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_futils_dirs_get_str(char *out, size_t outlen, git_futils_dir_t which)
|
||||
{
|
||||
const git_buf *path = NULL;
|
||||
|
||||
GITERR_CHECK_ERROR(git_futils_check_selector(which));
|
||||
GITERR_CHECK_ERROR(git_futils_dirs_get(&path, which));
|
||||
|
||||
if (!out || path->size >= outlen) {
|
||||
giterr_set(GITERR_NOMEMORY, "Buffer is too short for the path");
|
||||
return GIT_EBUFS;
|
||||
}
|
||||
|
||||
git_buf_copy_cstr(out, outlen, path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PATH_MAGIC "$PATH"
|
||||
|
||||
int git_futils_dirs_set(git_futils_dir_t which, const char *search_path)
|
||||
{
|
||||
const char *expand_path = NULL;
|
||||
git_buf merge = GIT_BUF_INIT;
|
||||
|
||||
GITERR_CHECK_ERROR(git_futils_check_selector(which));
|
||||
|
||||
if (search_path != NULL)
|
||||
expand_path = strstr(search_path, PATH_MAGIC);
|
||||
|
||||
/* init with default if not yet done and needed (ignoring error) */
|
||||
if ((!search_path || expand_path) &&
|
||||
!git_buf_len(&git_futils__dirs[which]))
|
||||
git_futils__dir_guess[which](&git_futils__dirs[which]);
|
||||
|
||||
/* if $PATH is not referenced, then just set the path */
|
||||
if (!expand_path)
|
||||
return git_buf_sets(&git_futils__dirs[which], search_path);
|
||||
|
||||
/* otherwise set to join(before $PATH, old value, after $PATH) */
|
||||
if (expand_path > search_path)
|
||||
git_buf_set(&merge, search_path, expand_path - search_path);
|
||||
|
||||
if (git_buf_len(&git_futils__dirs[which]))
|
||||
git_buf_join(&merge, GIT_PATH_LIST_SEPARATOR,
|
||||
merge.ptr, git_futils__dirs[which].ptr);
|
||||
|
||||
expand_path += strlen(PATH_MAGIC);
|
||||
if (*expand_path)
|
||||
git_buf_join(&merge, GIT_PATH_LIST_SEPARATOR, merge.ptr, expand_path);
|
||||
|
||||
git_buf_swap(&git_futils__dirs[which], &merge);
|
||||
git_buf_free(&merge);
|
||||
|
||||
return git_buf_oom(&git_futils__dirs[which]) ? -1 : 0;
|
||||
}
|
||||
|
||||
static int git_futils_find_in_dirlist(
|
||||
git_buf *path, const char *name, git_futils_dir_t which, const char *label)
|
||||
{
|
||||
size_t len;
|
||||
const char *scan, *next = NULL;
|
||||
const git_buf *syspath;
|
||||
|
||||
GITERR_CHECK_ERROR(git_futils_dirs_get(&syspath, which));
|
||||
|
||||
for (scan = git_buf_cstr(syspath); scan; scan = next) {
|
||||
for (next = strchr(scan, GIT_PATH_LIST_SEPARATOR);
|
||||
next && next > scan && next[-1] == '\\';
|
||||
next = strchr(next + 1, GIT_PATH_LIST_SEPARATOR))
|
||||
/* find unescaped separator or end of string */;
|
||||
|
||||
len = next ? (size_t)(next++ - scan) : strlen(scan);
|
||||
if (!len)
|
||||
continue;
|
||||
|
||||
GITERR_CHECK_ERROR(git_buf_set(path, scan, len));
|
||||
if (name)
|
||||
GITERR_CHECK_ERROR(git_buf_joinpath(path, path->ptr, name));
|
||||
|
||||
if (git_path_exists(path->ptr))
|
||||
return 0;
|
||||
}
|
||||
|
||||
git_buf_clear(path);
|
||||
giterr_set(GITERR_OS, "The %s file '%s' doesn't exist", label, name);
|
||||
return GIT_ENOTFOUND;
|
||||
}
|
||||
|
||||
int git_futils_find_system_file(git_buf *path, const char *filename)
|
||||
{
|
||||
return git_futils_find_in_dirlist(
|
||||
path, filename, GIT_FUTILS_DIR_SYSTEM, "system");
|
||||
}
|
||||
|
||||
int git_futils_find_global_file(git_buf *path, const char *filename)
|
||||
{
|
||||
return git_futils_find_in_dirlist(
|
||||
path, filename, GIT_FUTILS_DIR_GLOBAL, "global");
|
||||
}
|
||||
|
||||
int git_futils_find_xdg_file(git_buf *path, const char *filename)
|
||||
{
|
||||
return git_futils_find_in_dirlist(
|
||||
path, filename, GIT_FUTILS_DIR_XDG, "global/xdg");
|
||||
}
|
||||
|
||||
int git_futils_find_template_dir(git_buf *path)
|
||||
{
|
||||
return git_futils_find_in_dirlist(
|
||||
path, NULL, GIT_FUTILS_DIR_TEMPLATE, "template");
|
||||
}
|
||||
|
||||
int git_futils_fake_symlink(const char *old, const char *new)
|
||||
{
|
||||
int retcode = GIT_ERROR;
|
||||
|
@ -267,89 +267,6 @@ extern int git_futils_mmap_ro_file(
|
||||
*/
|
||||
extern void git_futils_mmap_free(git_map *map);
|
||||
|
||||
/**
|
||||
* Find a "global" file (i.e. one in a user's home directory).
|
||||
*
|
||||
* @param path buffer to write the full path into
|
||||
* @param filename name of file to find in the home directory
|
||||
* @return 0 if found, GIT_ENOTFOUND if not found, or -1 on other OS error
|
||||
*/
|
||||
extern int git_futils_find_global_file(git_buf *path, const char *filename);
|
||||
|
||||
/**
|
||||
* Find an "XDG" file (i.e. one in user's XDG config path).
|
||||
*
|
||||
* @param path buffer to write the full path into
|
||||
* @param filename name of file to find in the home directory
|
||||
* @return 0 if found, GIT_ENOTFOUND if not found, or -1 on other OS error
|
||||
*/
|
||||
extern int git_futils_find_xdg_file(git_buf *path, const char *filename);
|
||||
|
||||
/**
|
||||
* Find a "system" file (i.e. one shared for all users of the system).
|
||||
*
|
||||
* @param path buffer to write the full path into
|
||||
* @param filename name of file to find in the home directory
|
||||
* @return 0 if found, GIT_ENOTFOUND if not found, or -1 on other OS error
|
||||
*/
|
||||
extern int git_futils_find_system_file(git_buf *path, const char *filename);
|
||||
|
||||
/**
|
||||
* Find template directory.
|
||||
*
|
||||
* @param path buffer to write the full path into
|
||||
* @return 0 if found, GIT_ENOTFOUND if not found, or -1 on other OS error
|
||||
*/
|
||||
extern int git_futils_find_template_dir(git_buf *path);
|
||||
|
||||
typedef enum {
|
||||
GIT_FUTILS_DIR_SYSTEM = 0,
|
||||
GIT_FUTILS_DIR_GLOBAL = 1,
|
||||
GIT_FUTILS_DIR_XDG = 2,
|
||||
GIT_FUTILS_DIR_TEMPLATE = 3,
|
||||
GIT_FUTILS_DIR__MAX = 4,
|
||||
} git_futils_dir_t;
|
||||
|
||||
/**
|
||||
* Configures global data for configuration file search paths.
|
||||
*
|
||||
* @return 0 on success, <0 on failure
|
||||
*/
|
||||
extern int git_futils_dirs_global_init(void);
|
||||
|
||||
/**
|
||||
* Get the search path for global/system/xdg files
|
||||
*
|
||||
* @param out pointer to git_buf containing search path
|
||||
* @param which which list of paths to return
|
||||
* @return 0 on success, <0 on failure
|
||||
*/
|
||||
extern int git_futils_dirs_get(const git_buf **out, git_futils_dir_t which);
|
||||
|
||||
/**
|
||||
* Get search path into a preallocated buffer
|
||||
*
|
||||
* @param out String buffer to write into
|
||||
* @param outlen Size of string buffer
|
||||
* @param which Which search path to return
|
||||
* @return 0 on success, GIT_EBUFS if out is too small, <0 on other failure
|
||||
*/
|
||||
|
||||
extern int git_futils_dirs_get_str(
|
||||
char *out, size_t outlen, git_futils_dir_t which);
|
||||
|
||||
/**
|
||||
* Set search paths for global/system/xdg files
|
||||
*
|
||||
* The first occurrence of the magic string "$PATH" in the new value will
|
||||
* be replaced with the old value of the search path.
|
||||
*
|
||||
* @param which Which search path to modify
|
||||
* @param paths New search path (separated by GIT_PATH_LIST_SEPARATOR)
|
||||
* @return 0 on success, <0 on failure (allocation error)
|
||||
*/
|
||||
extern int git_futils_dirs_set(git_futils_dir_t which, const char *paths);
|
||||
|
||||
/**
|
||||
* Create a "fake" symlink (text file containing the target path).
|
||||
*
|
||||
@ -399,9 +316,4 @@ extern int git_futils_filestamp_check(
|
||||
extern void git_futils_filestamp_set(
|
||||
git_futils_filestamp *tgt, const git_futils_filestamp *src);
|
||||
|
||||
/**
|
||||
* Free the configuration file search paths.
|
||||
*/
|
||||
extern void git_futils_dirs_global_shutdown(void);
|
||||
|
||||
#endif /* INCLUDE_fileops_h__ */
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "common.h"
|
||||
#include "global.h"
|
||||
#include "hash.h"
|
||||
#include "fileops.h"
|
||||
#include "sysdir.h"
|
||||
#include "git2/threads.h"
|
||||
#include "thread-utils.h"
|
||||
|
||||
@ -86,7 +86,7 @@ static int synchronized_threads_init()
|
||||
|
||||
/* Initialize any other subsystems that have global state */
|
||||
if ((error = git_hash_global_init()) >= 0)
|
||||
error = git_futils_dirs_global_init();
|
||||
error = git_sysdir_global_init();
|
||||
|
||||
win32_pthread_initialize();
|
||||
|
||||
@ -169,7 +169,7 @@ static void init_once(void)
|
||||
|
||||
/* Initialize any other subsystems that have global state */
|
||||
if ((init_error = git_hash_global_init()) >= 0)
|
||||
init_error = git_futils_dirs_global_init();
|
||||
init_error = git_sysdir_global_init();
|
||||
|
||||
GIT_MEMORY_BARRIER;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "tag.h"
|
||||
#include "blob.h"
|
||||
#include "fileops.h"
|
||||
#include "sysdir.h"
|
||||
#include "filebuf.h"
|
||||
#include "index.h"
|
||||
#include "config.h"
|
||||
@ -1264,7 +1265,7 @@ static int repo_init_structure(
|
||||
}
|
||||
|
||||
if (!tdir) {
|
||||
if (!(error = git_futils_find_template_dir(&template_buf)))
|
||||
if (!(error = git_sysdir_find_template_dir(&template_buf)))
|
||||
tdir = template_buf.ptr;
|
||||
default_template = true;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include <git2.h>
|
||||
#include "common.h"
|
||||
#include "fileops.h"
|
||||
#include "sysdir.h"
|
||||
#include "cache.h"
|
||||
|
||||
void git_libgit2_version(int *major, int *minor, int *rev)
|
||||
@ -36,14 +36,14 @@ int git_libgit2_capabilities()
|
||||
extern size_t git_mwindow__window_size;
|
||||
extern size_t git_mwindow__mapped_limit;
|
||||
|
||||
static int config_level_to_futils_dir(int config_level)
|
||||
static int config_level_to_sysdir(int config_level)
|
||||
{
|
||||
int val = -1;
|
||||
|
||||
switch (config_level) {
|
||||
case GIT_CONFIG_LEVEL_SYSTEM: val = GIT_FUTILS_DIR_SYSTEM; break;
|
||||
case GIT_CONFIG_LEVEL_XDG: val = GIT_FUTILS_DIR_XDG; break;
|
||||
case GIT_CONFIG_LEVEL_GLOBAL: val = GIT_FUTILS_DIR_GLOBAL; break;
|
||||
case GIT_CONFIG_LEVEL_SYSTEM: val = GIT_SYSDIR_SYSTEM; break;
|
||||
case GIT_CONFIG_LEVEL_XDG: val = GIT_SYSDIR_XDG; break;
|
||||
case GIT_CONFIG_LEVEL_GLOBAL: val = GIT_SYSDIR_GLOBAL; break;
|
||||
default:
|
||||
giterr_set(
|
||||
GITERR_INVALID, "Invalid config path selector %d", config_level);
|
||||
@ -77,17 +77,17 @@ int git_libgit2_opts(int key, ...)
|
||||
break;
|
||||
|
||||
case GIT_OPT_GET_SEARCH_PATH:
|
||||
if ((error = config_level_to_futils_dir(va_arg(ap, int))) >= 0) {
|
||||
if ((error = config_level_to_sysdir(va_arg(ap, int))) >= 0) {
|
||||
char *out = va_arg(ap, char *);
|
||||
size_t outlen = va_arg(ap, size_t);
|
||||
|
||||
error = git_futils_dirs_get_str(out, outlen, error);
|
||||
error = git_sysdir_get_str(out, outlen, error);
|
||||
}
|
||||
break;
|
||||
|
||||
case GIT_OPT_SET_SEARCH_PATH:
|
||||
if ((error = config_level_to_futils_dir(va_arg(ap, int))) >= 0)
|
||||
error = git_futils_dirs_set(error, va_arg(ap, const char *));
|
||||
if ((error = config_level_to_sysdir(va_arg(ap, int))) >= 0)
|
||||
error = git_sysdir_set(error, va_arg(ap, const char *));
|
||||
break;
|
||||
|
||||
case GIT_OPT_SET_CACHE_OBJECT_LIMIT:
|
||||
@ -116,12 +116,12 @@ int git_libgit2_opts(int key, ...)
|
||||
char *out = va_arg(ap, char *);
|
||||
size_t outlen = va_arg(ap, size_t);
|
||||
|
||||
error = git_futils_dirs_get_str(out, outlen, GIT_FUTILS_DIR_TEMPLATE);
|
||||
error = git_sysdir_get_str(out, outlen, GIT_SYSDIR_TEMPLATE);
|
||||
}
|
||||
break;
|
||||
|
||||
case GIT_OPT_SET_TEMPLATE_PATH:
|
||||
error = git_futils_dirs_set(GIT_FUTILS_DIR_TEMPLATE, va_arg(ap, const char *));
|
||||
error = git_sysdir_set(GIT_SYSDIR_TEMPLATE, va_arg(ap, const char *));
|
||||
break;
|
||||
}
|
||||
|
||||
|
244
src/sysdir.c
Normal file
244
src/sysdir.c
Normal file
@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (C) the libgit2 contributors. All rights reserved.
|
||||
*
|
||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "sysdir.h"
|
||||
#include "global.h"
|
||||
#include "buffer.h"
|
||||
#include "path.h"
|
||||
#include <ctype.h>
|
||||
#if GIT_WIN32
|
||||
#include "win32/findfile.h"
|
||||
#endif
|
||||
|
||||
static int git_sysdir_guess_system_dirs(git_buf *out)
|
||||
{
|
||||
#ifdef GIT_WIN32
|
||||
return git_win32__find_system_dirs(out, L"etc\\");
|
||||
#else
|
||||
return git_buf_sets(out, "/etc");
|
||||
#endif
|
||||
}
|
||||
|
||||
static int git_sysdir_guess_global_dirs(git_buf *out)
|
||||
{
|
||||
#ifdef GIT_WIN32
|
||||
return git_win32__find_global_dirs(out);
|
||||
#else
|
||||
return git_buf_sets(out, getenv("HOME"));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int git_sysdir_guess_xdg_dirs(git_buf *out)
|
||||
{
|
||||
#ifdef GIT_WIN32
|
||||
return git_win32__find_xdg_dirs(out);
|
||||
#else
|
||||
const char *env = NULL;
|
||||
|
||||
if ((env = getenv("XDG_CONFIG_HOME")) != NULL)
|
||||
return git_buf_joinpath(out, env, "git");
|
||||
else if ((env = getenv("HOME")) != NULL)
|
||||
return git_buf_joinpath(out, env, ".config/git");
|
||||
|
||||
git_buf_clear(out);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int git_sysdir_guess_template_dirs(git_buf *out)
|
||||
{
|
||||
#ifdef GIT_WIN32
|
||||
return git_win32__find_system_dirs(out, L"share\\git-core\\templates");
|
||||
#else
|
||||
return git_buf_sets(out, "/usr/share/git-core/templates");
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef int (*git_sysdir_guess_cb)(git_buf *out);
|
||||
|
||||
static git_buf git_sysdir__dirs[GIT_SYSDIR__MAX] =
|
||||
{ GIT_BUF_INIT, GIT_BUF_INIT, GIT_BUF_INIT, GIT_BUF_INIT };
|
||||
|
||||
static git_sysdir_guess_cb git_sysdir__dir_guess[GIT_SYSDIR__MAX] = {
|
||||
git_sysdir_guess_system_dirs,
|
||||
git_sysdir_guess_global_dirs,
|
||||
git_sysdir_guess_xdg_dirs,
|
||||
git_sysdir_guess_template_dirs,
|
||||
};
|
||||
|
||||
static int git_sysdir__dirs_shutdown_set = 0;
|
||||
|
||||
int git_sysdir_global_init(void)
|
||||
{
|
||||
git_sysdir_t i;
|
||||
const git_buf *path;
|
||||
int error = 0;
|
||||
|
||||
for (i = 0; !error && i < GIT_SYSDIR__MAX; i++)
|
||||
error = git_sysdir_get(&path, i);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void git_sysdir_global_shutdown(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < GIT_SYSDIR__MAX; ++i)
|
||||
git_buf_free(&git_sysdir__dirs[i]);
|
||||
}
|
||||
|
||||
static int git_sysdir_check_selector(git_sysdir_t which)
|
||||
{
|
||||
if (which < GIT_SYSDIR__MAX)
|
||||
return 0;
|
||||
|
||||
giterr_set(GITERR_INVALID, "config directory selector out of range");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int git_sysdir_get(const git_buf **out, git_sysdir_t which)
|
||||
{
|
||||
assert(out);
|
||||
|
||||
*out = NULL;
|
||||
|
||||
GITERR_CHECK_ERROR(git_sysdir_check_selector(which));
|
||||
|
||||
if (!git_buf_len(&git_sysdir__dirs[which])) {
|
||||
/* prepare shutdown if we're going to need it */
|
||||
if (!git_sysdir__dirs_shutdown_set) {
|
||||
git__on_shutdown(git_sysdir_global_shutdown);
|
||||
git_sysdir__dirs_shutdown_set = 1;
|
||||
}
|
||||
|
||||
GITERR_CHECK_ERROR(
|
||||
git_sysdir__dir_guess[which](&git_sysdir__dirs[which]));
|
||||
}
|
||||
|
||||
*out = &git_sysdir__dirs[which];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_sysdir_get_str(
|
||||
char *out,
|
||||
size_t outlen,
|
||||
git_sysdir_t which)
|
||||
{
|
||||
const git_buf *path = NULL;
|
||||
|
||||
GITERR_CHECK_ERROR(git_sysdir_check_selector(which));
|
||||
GITERR_CHECK_ERROR(git_sysdir_get(&path, which));
|
||||
|
||||
if (!out || path->size >= outlen) {
|
||||
giterr_set(GITERR_NOMEMORY, "Buffer is too short for the path");
|
||||
return GIT_EBUFS;
|
||||
}
|
||||
|
||||
git_buf_copy_cstr(out, outlen, path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PATH_MAGIC "$PATH"
|
||||
|
||||
int git_sysdir_set(git_sysdir_t which, const char *search_path)
|
||||
{
|
||||
const char *expand_path = NULL;
|
||||
git_buf merge = GIT_BUF_INIT;
|
||||
|
||||
GITERR_CHECK_ERROR(git_sysdir_check_selector(which));
|
||||
|
||||
if (search_path != NULL)
|
||||
expand_path = strstr(search_path, PATH_MAGIC);
|
||||
|
||||
/* init with default if not yet done and needed (ignoring error) */
|
||||
if ((!search_path || expand_path) &&
|
||||
!git_buf_len(&git_sysdir__dirs[which]))
|
||||
git_sysdir__dir_guess[which](&git_sysdir__dirs[which]);
|
||||
|
||||
/* if $PATH is not referenced, then just set the path */
|
||||
if (!expand_path)
|
||||
return git_buf_sets(&git_sysdir__dirs[which], search_path);
|
||||
|
||||
/* otherwise set to join(before $PATH, old value, after $PATH) */
|
||||
if (expand_path > search_path)
|
||||
git_buf_set(&merge, search_path, expand_path - search_path);
|
||||
|
||||
if (git_buf_len(&git_sysdir__dirs[which]))
|
||||
git_buf_join(&merge, GIT_PATH_LIST_SEPARATOR,
|
||||
merge.ptr, git_sysdir__dirs[which].ptr);
|
||||
|
||||
expand_path += strlen(PATH_MAGIC);
|
||||
if (*expand_path)
|
||||
git_buf_join(&merge, GIT_PATH_LIST_SEPARATOR, merge.ptr, expand_path);
|
||||
|
||||
git_buf_swap(&git_sysdir__dirs[which], &merge);
|
||||
git_buf_free(&merge);
|
||||
|
||||
return git_buf_oom(&git_sysdir__dirs[which]) ? -1 : 0;
|
||||
}
|
||||
|
||||
static int git_sysdir_find_in_dirlist(
|
||||
git_buf *path,
|
||||
const char *name,
|
||||
git_sysdir_t which,
|
||||
const char *label)
|
||||
{
|
||||
size_t len;
|
||||
const char *scan, *next = NULL;
|
||||
const git_buf *syspath;
|
||||
|
||||
GITERR_CHECK_ERROR(git_sysdir_get(&syspath, which));
|
||||
|
||||
for (scan = git_buf_cstr(syspath); scan; scan = next) {
|
||||
for (next = strchr(scan, GIT_PATH_LIST_SEPARATOR);
|
||||
next && next > scan && next[-1] == '\\';
|
||||
next = strchr(next + 1, GIT_PATH_LIST_SEPARATOR))
|
||||
/* find unescaped separator or end of string */;
|
||||
|
||||
len = next ? (size_t)(next++ - scan) : strlen(scan);
|
||||
if (!len)
|
||||
continue;
|
||||
|
||||
GITERR_CHECK_ERROR(git_buf_set(path, scan, len));
|
||||
if (name)
|
||||
GITERR_CHECK_ERROR(git_buf_joinpath(path, path->ptr, name));
|
||||
|
||||
if (git_path_exists(path->ptr))
|
||||
return 0;
|
||||
}
|
||||
|
||||
git_buf_clear(path);
|
||||
giterr_set(GITERR_OS, "The %s file '%s' doesn't exist", label, name);
|
||||
return GIT_ENOTFOUND;
|
||||
}
|
||||
|
||||
int git_sysdir_find_system_file(git_buf *path, const char *filename)
|
||||
{
|
||||
return git_sysdir_find_in_dirlist(
|
||||
path, filename, GIT_SYSDIR_SYSTEM, "system");
|
||||
}
|
||||
|
||||
int git_sysdir_find_global_file(git_buf *path, const char *filename)
|
||||
{
|
||||
return git_sysdir_find_in_dirlist(
|
||||
path, filename, GIT_SYSDIR_GLOBAL, "global");
|
||||
}
|
||||
|
||||
int git_sysdir_find_xdg_file(git_buf *path, const char *filename)
|
||||
{
|
||||
return git_sysdir_find_in_dirlist(
|
||||
path, filename, GIT_SYSDIR_XDG, "global/xdg");
|
||||
}
|
||||
|
||||
int git_sysdir_find_template_dir(git_buf *path)
|
||||
{
|
||||
return git_sysdir_find_in_dirlist(
|
||||
path, NULL, GIT_SYSDIR_TEMPLATE, "template");
|
||||
}
|
||||
|
101
src/sysdir.h
Normal file
101
src/sysdir.h
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (C) the libgit2 contributors. All rights reserved.
|
||||
*
|
||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
#ifndef INCLUDE_sysdir_h__
|
||||
#define INCLUDE_sysdir_h__
|
||||
|
||||
#include "common.h"
|
||||
#include "posix.h"
|
||||
#include "buffer.h"
|
||||
|
||||
/**
|
||||
* Find a "global" file (i.e. one in a user's home directory).
|
||||
*
|
||||
* @param path buffer to write the full path into
|
||||
* @param filename name of file to find in the home directory
|
||||
* @return 0 if found, GIT_ENOTFOUND if not found, or -1 on other OS error
|
||||
*/
|
||||
extern int git_sysdir_find_global_file(git_buf *path, const char *filename);
|
||||
|
||||
/**
|
||||
* Find an "XDG" file (i.e. one in user's XDG config path).
|
||||
*
|
||||
* @param path buffer to write the full path into
|
||||
* @param filename name of file to find in the home directory
|
||||
* @return 0 if found, GIT_ENOTFOUND if not found, or -1 on other OS error
|
||||
*/
|
||||
extern int git_sysdir_find_xdg_file(git_buf *path, const char *filename);
|
||||
|
||||
/**
|
||||
* Find a "system" file (i.e. one shared for all users of the system).
|
||||
*
|
||||
* @param path buffer to write the full path into
|
||||
* @param filename name of file to find in the home directory
|
||||
* @return 0 if found, GIT_ENOTFOUND if not found, or -1 on other OS error
|
||||
*/
|
||||
extern int git_sysdir_find_system_file(git_buf *path, const char *filename);
|
||||
|
||||
/**
|
||||
* Find template directory.
|
||||
*
|
||||
* @param path buffer to write the full path into
|
||||
* @return 0 if found, GIT_ENOTFOUND if not found, or -1 on other OS error
|
||||
*/
|
||||
extern int git_sysdir_find_template_dir(git_buf *path);
|
||||
|
||||
typedef enum {
|
||||
GIT_SYSDIR_SYSTEM = 0,
|
||||
GIT_SYSDIR_GLOBAL = 1,
|
||||
GIT_SYSDIR_XDG = 2,
|
||||
GIT_SYSDIR_TEMPLATE = 3,
|
||||
GIT_SYSDIR__MAX = 4,
|
||||
} git_sysdir_t;
|
||||
|
||||
/**
|
||||
* Configures global data for configuration file search paths.
|
||||
*
|
||||
* @return 0 on success, <0 on failure
|
||||
*/
|
||||
extern int git_sysdir_global_init(void);
|
||||
|
||||
/**
|
||||
* Get the search path for global/system/xdg files
|
||||
*
|
||||
* @param out pointer to git_buf containing search path
|
||||
* @param which which list of paths to return
|
||||
* @return 0 on success, <0 on failure
|
||||
*/
|
||||
extern int git_sysdir_get(const git_buf **out, git_sysdir_t which);
|
||||
|
||||
/**
|
||||
* Get search path into a preallocated buffer
|
||||
*
|
||||
* @param out String buffer to write into
|
||||
* @param outlen Size of string buffer
|
||||
* @param which Which search path to return
|
||||
* @return 0 on success, GIT_EBUFS if out is too small, <0 on other failure
|
||||
*/
|
||||
|
||||
extern int git_sysdir_get_str(char *out, size_t outlen, git_sysdir_t which);
|
||||
|
||||
/**
|
||||
* Set search paths for global/system/xdg files
|
||||
*
|
||||
* The first occurrence of the magic string "$PATH" in the new value will
|
||||
* be replaced with the old value of the search path.
|
||||
*
|
||||
* @param which Which search path to modify
|
||||
* @param paths New search path (separated by GIT_PATH_LIST_SEPARATOR)
|
||||
* @return 0 on success, <0 on failure (allocation error)
|
||||
*/
|
||||
extern int git_sysdir_set(git_sysdir_t which, const char *paths);
|
||||
|
||||
/**
|
||||
* Free the configuration file search paths.
|
||||
*/
|
||||
extern void git_sysdir_global_shutdown(void);
|
||||
|
||||
#endif /* INCLUDE_sysdir_h__ */
|
@ -1,5 +1,6 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "fileops.h"
|
||||
#include "sysdir.h"
|
||||
#include "path.h"
|
||||
|
||||
#ifdef GIT_WIN32
|
||||
@ -41,12 +42,12 @@ void test_core_env__initialize(void)
|
||||
|
||||
static void reset_global_search_path(void)
|
||||
{
|
||||
cl_git_pass(git_futils_dirs_set(GIT_FUTILS_DIR_GLOBAL, NULL));
|
||||
cl_git_pass(git_sysdir_set(GIT_SYSDIR_GLOBAL, NULL));
|
||||
}
|
||||
|
||||
static void reset_system_search_path(void)
|
||||
{
|
||||
cl_git_pass(git_futils_dirs_set(GIT_FUTILS_DIR_SYSTEM, NULL));
|
||||
cl_git_pass(git_sysdir_set(GIT_SYSDIR_SYSTEM, NULL));
|
||||
}
|
||||
|
||||
void test_core_env__cleanup(void)
|
||||
@ -120,18 +121,18 @@ void test_core_env__0(void)
|
||||
git_buf_rtruncate_at_char(&path, '/');
|
||||
|
||||
cl_assert_equal_i(
|
||||
GIT_ENOTFOUND, git_futils_find_global_file(&found, testfile));
|
||||
GIT_ENOTFOUND, git_sysdir_find_global_file(&found, testfile));
|
||||
|
||||
setenv_and_check("HOME", path.ptr);
|
||||
reset_global_search_path();
|
||||
|
||||
cl_git_pass(git_futils_find_global_file(&found, testfile));
|
||||
cl_git_pass(git_sysdir_find_global_file(&found, testfile));
|
||||
|
||||
cl_setenv("HOME", env_save[0]);
|
||||
reset_global_search_path();
|
||||
|
||||
cl_assert_equal_i(
|
||||
GIT_ENOTFOUND, git_futils_find_global_file(&found, testfile));
|
||||
GIT_ENOTFOUND, git_sysdir_find_global_file(&found, testfile));
|
||||
|
||||
#ifdef GIT_WIN32
|
||||
setenv_and_check("HOMEDRIVE", NULL);
|
||||
@ -139,7 +140,7 @@ void test_core_env__0(void)
|
||||
setenv_and_check("USERPROFILE", path.ptr);
|
||||
reset_global_search_path();
|
||||
|
||||
cl_git_pass(git_futils_find_global_file(&found, testfile));
|
||||
cl_git_pass(git_sysdir_find_global_file(&found, testfile));
|
||||
|
||||
{
|
||||
int root = git_path_root(path.ptr);
|
||||
@ -150,7 +151,7 @@ void test_core_env__0(void)
|
||||
reset_global_search_path();
|
||||
|
||||
cl_assert_equal_i(
|
||||
GIT_ENOTFOUND, git_futils_find_global_file(&found, testfile));
|
||||
GIT_ENOTFOUND, git_sysdir_find_global_file(&found, testfile));
|
||||
|
||||
old = path.ptr[root];
|
||||
path.ptr[root] = '\0';
|
||||
@ -159,7 +160,7 @@ void test_core_env__0(void)
|
||||
setenv_and_check("HOMEPATH", &path.ptr[root]);
|
||||
reset_global_search_path();
|
||||
|
||||
cl_git_pass(git_futils_find_global_file(&found, testfile));
|
||||
cl_git_pass(git_sysdir_find_global_file(&found, testfile));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -177,7 +178,7 @@ void test_core_env__1(void)
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
|
||||
cl_assert_equal_i(
|
||||
GIT_ENOTFOUND, git_futils_find_global_file(&path, "nonexistentfile"));
|
||||
GIT_ENOTFOUND, git_sysdir_find_global_file(&path, "nonexistentfile"));
|
||||
|
||||
cl_git_pass(cl_setenv("HOME", "doesnotexist"));
|
||||
#ifdef GIT_WIN32
|
||||
@ -187,7 +188,7 @@ void test_core_env__1(void)
|
||||
reset_global_search_path();
|
||||
|
||||
cl_assert_equal_i(
|
||||
GIT_ENOTFOUND, git_futils_find_global_file(&path, "nonexistentfile"));
|
||||
GIT_ENOTFOUND, git_sysdir_find_global_file(&path, "nonexistentfile"));
|
||||
|
||||
cl_git_pass(cl_setenv("HOME", NULL));
|
||||
#ifdef GIT_WIN32
|
||||
@ -198,17 +199,17 @@ void test_core_env__1(void)
|
||||
reset_system_search_path();
|
||||
|
||||
cl_assert_equal_i(
|
||||
GIT_ENOTFOUND, git_futils_find_global_file(&path, "nonexistentfile"));
|
||||
GIT_ENOTFOUND, git_sysdir_find_global_file(&path, "nonexistentfile"));
|
||||
|
||||
cl_assert_equal_i(
|
||||
GIT_ENOTFOUND, git_futils_find_system_file(&path, "nonexistentfile"));
|
||||
GIT_ENOTFOUND, git_sysdir_find_system_file(&path, "nonexistentfile"));
|
||||
|
||||
#ifdef GIT_WIN32
|
||||
cl_git_pass(cl_setenv("PROGRAMFILES", NULL));
|
||||
reset_system_search_path();
|
||||
|
||||
cl_assert_equal_i(
|
||||
GIT_ENOTFOUND, git_futils_find_system_file(&path, "nonexistentfile"));
|
||||
GIT_ENOTFOUND, git_sysdir_find_system_file(&path, "nonexistentfile"));
|
||||
#endif
|
||||
|
||||
git_buf_free(&path);
|
||||
@ -242,13 +243,13 @@ static void check_global_searchpath(
|
||||
cl_assert_equal_s(out, path);
|
||||
|
||||
/* find file using new path */
|
||||
cl_git_pass(git_futils_find_global_file(temp, file));
|
||||
cl_git_pass(git_sysdir_find_global_file(temp, file));
|
||||
|
||||
/* reset path and confirm file not found */
|
||||
cl_git_pass(git_libgit2_opts(
|
||||
GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, NULL));
|
||||
cl_assert_equal_i(
|
||||
GIT_ENOTFOUND, git_futils_find_global_file(temp, file));
|
||||
GIT_ENOTFOUND, git_sysdir_find_global_file(temp, file));
|
||||
}
|
||||
|
||||
void test_core_env__2(void)
|
||||
@ -285,7 +286,7 @@ void test_core_env__2(void)
|
||||
|
||||
/* default should be NOTFOUND */
|
||||
cl_assert_equal_i(
|
||||
GIT_ENOTFOUND, git_futils_find_global_file(&found, testfile));
|
||||
GIT_ENOTFOUND, git_sysdir_find_global_file(&found, testfile));
|
||||
|
||||
/* try plain, append $PATH, and prepend $PATH */
|
||||
check_global_searchpath(path.ptr, 0, testfile, &found);
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "sysdir.h"
|
||||
#include "fileops.h"
|
||||
#include <ctype.h>
|
||||
|
||||
@ -47,7 +48,7 @@ void test_repo_config__open_missing_global(void)
|
||||
git_config_free(config);
|
||||
git_repository_free(repo);
|
||||
|
||||
git_futils_dirs_global_shutdown();
|
||||
git_sysdir_global_shutdown();
|
||||
}
|
||||
|
||||
void test_repo_config__open_missing_global_with_separators(void)
|
||||
@ -76,7 +77,7 @@ void test_repo_config__open_missing_global_with_separators(void)
|
||||
git_config_free(config);
|
||||
git_repository_free(repo);
|
||||
|
||||
git_futils_dirs_global_shutdown();
|
||||
git_sysdir_global_shutdown();
|
||||
}
|
||||
|
||||
#include "repository.h"
|
||||
@ -105,7 +106,7 @@ void test_repo_config__read_no_configs(void)
|
||||
cl_assert_equal_i(GIT_ABBREV_DEFAULT, val);
|
||||
git_repository_free(repo);
|
||||
|
||||
git_futils_dirs_global_shutdown();
|
||||
git_sysdir_global_shutdown();
|
||||
|
||||
/* with just system */
|
||||
|
||||
@ -204,5 +205,5 @@ void test_repo_config__read_no_configs(void)
|
||||
cl_assert(!git_path_exists("empty_standard_repo/.git/config"));
|
||||
cl_assert(!git_path_exists("alternate/3/.gitconfig"));
|
||||
|
||||
git_futils_dirs_global_shutdown();
|
||||
git_sysdir_global_shutdown();
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "fileops.h"
|
||||
#include "sysdir.h"
|
||||
#include <ctype.h>
|
||||
|
||||
void test_repo_open__cleanup(void)
|
||||
@ -323,7 +324,7 @@ void test_repo_open__no_config(void)
|
||||
git_repository_free(repo);
|
||||
cl_fixture_cleanup("empty_standard_repo");
|
||||
|
||||
git_futils_dirs_global_shutdown();
|
||||
git_sysdir_global_shutdown();
|
||||
}
|
||||
|
||||
void test_repo_open__force_bare(void)
|
||||
|
Loading…
Reference in New Issue
Block a user