Commit 83634d38 by Edward Thomson Committed by Edward Thomson

Move system directory cache out of utils

parent 98b93662
#include "common.h" #include "common.h"
#include "repository.h" #include "repository.h"
#include "fileops.h" #include "sysdir.h"
#include "config.h" #include "config.h"
#include "attr.h" #include "attr.h"
#include "ignore.h" #include "ignore.h"
...@@ -589,7 +589,7 @@ static int collect_attr_files( ...@@ -589,7 +589,7 @@ static int collect_attr_files(
} }
if ((flags & GIT_ATTR_CHECK_NO_SYSTEM) == 0) { 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) if (!error)
error = push_attr_file(repo, files, NULL, dir.ptr); error = push_attr_file(repo, files, NULL, dir.ptr);
else if (error == GIT_ENOTFOUND) { else if (error == GIT_ENOTFOUND) {
...@@ -623,13 +623,13 @@ static int attr_cache__lookup_path( ...@@ -623,13 +623,13 @@ static int attr_cache__lookup_path(
/* expand leading ~/ as needed */ /* expand leading ~/ as needed */
if (cfgval && cfgval[0] == '~' && cfgval[1] == '/' && 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); *out = git_buf_detach(&buf);
else if (cfgval) else if (cfgval)
*out = git__strdup(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); *out = git_buf_detach(&buf);
git_buf_free(&buf); git_buf_free(&buf);
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
*/ */
#include "common.h" #include "common.h"
#include "fileops.h" #include "sysdir.h"
#include "config.h" #include "config.h"
#include "git2/config.h" #include "git2/config.h"
#include "git2/sys/config.h" #include "git2/sys/config.h"
...@@ -937,17 +937,17 @@ void git_config_iterator_free(git_config_iterator *iter) ...@@ -937,17 +937,17 @@ void git_config_iterator_free(git_config_iterator *iter)
int git_config_find_global(git_buf *path) 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) 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) 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) int git_config__global_location(git_buf *buf)
...@@ -956,7 +956,7 @@ int git_config__global_location(git_buf *buf) ...@@ -956,7 +956,7 @@ int git_config__global_location(git_buf *buf)
const char *sep, *start; const char *sep, *start;
size_t len; 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; return -1;
/* no paths, so give up */ /* no paths, so give up */
......
...@@ -7,8 +7,8 @@ ...@@ -7,8 +7,8 @@
#include "common.h" #include "common.h"
#include "config.h" #include "config.h"
#include "fileops.h"
#include "filebuf.h" #include "filebuf.h"
#include "sysdir.h"
#include "buffer.h" #include "buffer.h"
#include "buf_text.h" #include "buf_text.h"
#include "git2/config.h" #include "git2/config.h"
...@@ -1003,7 +1003,7 @@ static int included_path(git_buf *out, const char *dir, const char *path) ...@@ -1003,7 +1003,7 @@ static int included_path(git_buf *out, const char *dir, const char *path)
{ {
/* From the user's home */ /* From the user's home */
if (path[0] == '~' && path[1] == '/') 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); return git_path_join_unrooted(out, path, dir, NULL);
} }
......
...@@ -558,226 +558,6 @@ int git_futils_rmdir_r( ...@@ -558,226 +558,6 @@ int git_futils_rmdir_r(
return error; 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 git_futils_fake_symlink(const char *old, const char *new)
{ {
int retcode = GIT_ERROR; int retcode = GIT_ERROR;
......
...@@ -268,89 +268,6 @@ extern int git_futils_mmap_ro_file( ...@@ -268,89 +268,6 @@ extern int git_futils_mmap_ro_file(
extern void git_futils_mmap_free(git_map *map); 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). * Create a "fake" symlink (text file containing the target path).
* *
* @param new symlink file to be created * @param new symlink file to be created
...@@ -399,9 +316,4 @@ extern int git_futils_filestamp_check( ...@@ -399,9 +316,4 @@ extern int git_futils_filestamp_check(
extern void git_futils_filestamp_set( extern void git_futils_filestamp_set(
git_futils_filestamp *tgt, const git_futils_filestamp *src); 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__ */ #endif /* INCLUDE_fileops_h__ */
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#include "common.h" #include "common.h"
#include "global.h" #include "global.h"
#include "hash.h" #include "hash.h"
#include "fileops.h" #include "sysdir.h"
#include "git2/threads.h" #include "git2/threads.h"
#include "thread-utils.h" #include "thread-utils.h"
...@@ -86,7 +86,7 @@ static int synchronized_threads_init() ...@@ -86,7 +86,7 @@ static int synchronized_threads_init()
/* Initialize any other subsystems that have global state */ /* Initialize any other subsystems that have global state */
if ((error = git_hash_global_init()) >= 0) if ((error = git_hash_global_init()) >= 0)
error = git_futils_dirs_global_init(); error = git_sysdir_global_init();
win32_pthread_initialize(); win32_pthread_initialize();
...@@ -169,7 +169,7 @@ static void init_once(void) ...@@ -169,7 +169,7 @@ static void init_once(void)
/* Initialize any other subsystems that have global state */ /* Initialize any other subsystems that have global state */
if ((init_error = git_hash_global_init()) >= 0) if ((init_error = git_hash_global_init()) >= 0)
init_error = git_futils_dirs_global_init(); init_error = git_sysdir_global_init();
GIT_MEMORY_BARRIER; GIT_MEMORY_BARRIER;
} }
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "tag.h" #include "tag.h"
#include "blob.h" #include "blob.h"
#include "fileops.h" #include "fileops.h"
#include "sysdir.h"
#include "filebuf.h" #include "filebuf.h"
#include "index.h" #include "index.h"
#include "config.h" #include "config.h"
...@@ -1265,7 +1266,7 @@ static int repo_init_structure( ...@@ -1265,7 +1266,7 @@ static int repo_init_structure(
} }
if (!tdir) { if (!tdir) {
if (!(error = git_futils_find_template_dir(&template_buf))) if (!(error = git_sysdir_find_template_dir(&template_buf)))
tdir = template_buf.ptr; tdir = template_buf.ptr;
default_template = true; default_template = true;
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include <git2.h> #include <git2.h>
#include "common.h" #include "common.h"
#include "fileops.h" #include "sysdir.h"
#include "cache.h" #include "cache.h"
void git_libgit2_version(int *major, int *minor, int *rev) void git_libgit2_version(int *major, int *minor, int *rev)
...@@ -38,14 +38,14 @@ int git_libgit2_capabilities() ...@@ -38,14 +38,14 @@ int git_libgit2_capabilities()
extern size_t git_mwindow__window_size; extern size_t git_mwindow__window_size;
extern size_t git_mwindow__mapped_limit; 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; int val = -1;
switch (config_level) { switch (config_level) {
case GIT_CONFIG_LEVEL_SYSTEM: val = GIT_FUTILS_DIR_SYSTEM; break; case GIT_CONFIG_LEVEL_SYSTEM: val = GIT_SYSDIR_SYSTEM; break;
case GIT_CONFIG_LEVEL_XDG: val = GIT_FUTILS_DIR_XDG; break; case GIT_CONFIG_LEVEL_XDG: val = GIT_SYSDIR_XDG; break;
case GIT_CONFIG_LEVEL_GLOBAL: val = GIT_FUTILS_DIR_GLOBAL; break; case GIT_CONFIG_LEVEL_GLOBAL: val = GIT_SYSDIR_GLOBAL; break;
default: default:
giterr_set( giterr_set(
GITERR_INVALID, "Invalid config path selector %d", config_level); GITERR_INVALID, "Invalid config path selector %d", config_level);
...@@ -79,17 +79,17 @@ int git_libgit2_opts(int key, ...) ...@@ -79,17 +79,17 @@ int git_libgit2_opts(int key, ...)
break; break;
case GIT_OPT_GET_SEARCH_PATH: 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 *); char *out = va_arg(ap, char *);
size_t outlen = va_arg(ap, size_t); 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; break;
case GIT_OPT_SET_SEARCH_PATH: case GIT_OPT_SET_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)
error = git_futils_dirs_set(error, va_arg(ap, const char *)); error = git_sysdir_set(error, va_arg(ap, const char *));
break; break;
case GIT_OPT_SET_CACHE_OBJECT_LIMIT: case GIT_OPT_SET_CACHE_OBJECT_LIMIT:
...@@ -118,12 +118,12 @@ int git_libgit2_opts(int key, ...) ...@@ -118,12 +118,12 @@ int git_libgit2_opts(int key, ...)
char *out = va_arg(ap, char *); char *out = va_arg(ap, char *);
size_t outlen = va_arg(ap, size_t); 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; break;
case GIT_OPT_SET_TEMPLATE_PATH: 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; break;
} }
......
/*
* 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");
}
/*
* 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__ */
#include "clar_libgit2.h" #include "clar_libgit2.h"
#include "fileops.h" #include "fileops.h"
#include "sysdir.h"
#include "path.h" #include "path.h"
#ifdef GIT_WIN32 #ifdef GIT_WIN32
...@@ -41,12 +42,12 @@ void test_core_env__initialize(void) ...@@ -41,12 +42,12 @@ void test_core_env__initialize(void)
static void reset_global_search_path(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) 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) void test_core_env__cleanup(void)
...@@ -120,18 +121,18 @@ void test_core_env__0(void) ...@@ -120,18 +121,18 @@ void test_core_env__0(void)
git_buf_rtruncate_at_char(&path, '/'); git_buf_rtruncate_at_char(&path, '/');
cl_assert_equal_i( 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); setenv_and_check("HOME", path.ptr);
reset_global_search_path(); 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]); cl_setenv("HOME", env_save[0]);
reset_global_search_path(); reset_global_search_path();
cl_assert_equal_i( 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 #ifdef GIT_WIN32
setenv_and_check("HOMEDRIVE", NULL); setenv_and_check("HOMEDRIVE", NULL);
...@@ -139,7 +140,7 @@ void test_core_env__0(void) ...@@ -139,7 +140,7 @@ void test_core_env__0(void)
setenv_and_check("USERPROFILE", path.ptr); setenv_and_check("USERPROFILE", path.ptr);
reset_global_search_path(); 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); int root = git_path_root(path.ptr);
...@@ -150,7 +151,7 @@ void test_core_env__0(void) ...@@ -150,7 +151,7 @@ void test_core_env__0(void)
reset_global_search_path(); reset_global_search_path();
cl_assert_equal_i( 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]; old = path.ptr[root];
path.ptr[root] = '\0'; path.ptr[root] = '\0';
...@@ -159,7 +160,7 @@ void test_core_env__0(void) ...@@ -159,7 +160,7 @@ void test_core_env__0(void)
setenv_and_check("HOMEPATH", &path.ptr[root]); setenv_and_check("HOMEPATH", &path.ptr[root]);
reset_global_search_path(); 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 #endif
...@@ -177,7 +178,7 @@ void test_core_env__1(void) ...@@ -177,7 +178,7 @@ void test_core_env__1(void)
git_buf path = GIT_BUF_INIT; git_buf path = GIT_BUF_INIT;
cl_assert_equal_i( 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")); cl_git_pass(cl_setenv("HOME", "doesnotexist"));
#ifdef GIT_WIN32 #ifdef GIT_WIN32
...@@ -187,7 +188,7 @@ void test_core_env__1(void) ...@@ -187,7 +188,7 @@ void test_core_env__1(void)
reset_global_search_path(); reset_global_search_path();
cl_assert_equal_i( 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)); cl_git_pass(cl_setenv("HOME", NULL));
#ifdef GIT_WIN32 #ifdef GIT_WIN32
...@@ -198,17 +199,17 @@ void test_core_env__1(void) ...@@ -198,17 +199,17 @@ void test_core_env__1(void)
reset_system_search_path(); reset_system_search_path();
cl_assert_equal_i( 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( 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 #ifdef GIT_WIN32
cl_git_pass(cl_setenv("PROGRAMFILES", NULL)); cl_git_pass(cl_setenv("PROGRAMFILES", NULL));
reset_system_search_path(); reset_system_search_path();
cl_assert_equal_i( cl_assert_equal_i(
GIT_ENOTFOUND, git_futils_find_system_file(&path, "nonexistentfile")); GIT_ENOTFOUND, git_sysdir_find_system_file(&path, "nonexistentfile"));
#endif #endif
git_buf_free(&path); git_buf_free(&path);
...@@ -242,13 +243,13 @@ static void check_global_searchpath( ...@@ -242,13 +243,13 @@ static void check_global_searchpath(
cl_assert_equal_s(out, path); cl_assert_equal_s(out, path);
/* find file using new 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 */ /* reset path and confirm file not found */
cl_git_pass(git_libgit2_opts( cl_git_pass(git_libgit2_opts(
GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, NULL)); GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, NULL));
cl_assert_equal_i( 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) void test_core_env__2(void)
...@@ -285,7 +286,7 @@ void test_core_env__2(void) ...@@ -285,7 +286,7 @@ void test_core_env__2(void)
/* default should be NOTFOUND */ /* default should be NOTFOUND */
cl_assert_equal_i( 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 */ /* try plain, append $PATH, and prepend $PATH */
check_global_searchpath(path.ptr, 0, testfile, &found); check_global_searchpath(path.ptr, 0, testfile, &found);
......
#include "clar_libgit2.h" #include "clar_libgit2.h"
#include "sysdir.h"
#include "fileops.h" #include "fileops.h"
#include <ctype.h> #include <ctype.h>
...@@ -47,7 +48,7 @@ void test_repo_config__open_missing_global(void) ...@@ -47,7 +48,7 @@ void test_repo_config__open_missing_global(void)
git_config_free(config); git_config_free(config);
git_repository_free(repo); git_repository_free(repo);
git_futils_dirs_global_shutdown(); git_sysdir_global_shutdown();
} }
void test_repo_config__open_missing_global_with_separators(void) void test_repo_config__open_missing_global_with_separators(void)
...@@ -76,7 +77,7 @@ 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_config_free(config);
git_repository_free(repo); git_repository_free(repo);
git_futils_dirs_global_shutdown(); git_sysdir_global_shutdown();
} }
#include "repository.h" #include "repository.h"
...@@ -105,7 +106,7 @@ void test_repo_config__read_no_configs(void) ...@@ -105,7 +106,7 @@ void test_repo_config__read_no_configs(void)
cl_assert_equal_i(GIT_ABBREV_DEFAULT, val); cl_assert_equal_i(GIT_ABBREV_DEFAULT, val);
git_repository_free(repo); git_repository_free(repo);
git_futils_dirs_global_shutdown(); git_sysdir_global_shutdown();
/* with just system */ /* with just system */
...@@ -204,5 +205,5 @@ void test_repo_config__read_no_configs(void) ...@@ -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("empty_standard_repo/.git/config"));
cl_assert(!git_path_exists("alternate/3/.gitconfig")); cl_assert(!git_path_exists("alternate/3/.gitconfig"));
git_futils_dirs_global_shutdown(); git_sysdir_global_shutdown();
} }
#include "clar_libgit2.h" #include "clar_libgit2.h"
#include "fileops.h" #include "fileops.h"
#include "sysdir.h"
#include <ctype.h> #include <ctype.h>
void test_repo_open__cleanup(void) void test_repo_open__cleanup(void)
...@@ -323,7 +324,7 @@ void test_repo_open__no_config(void) ...@@ -323,7 +324,7 @@ void test_repo_open__no_config(void)
git_repository_free(repo); git_repository_free(repo);
cl_fixture_cleanup("empty_standard_repo"); cl_fixture_cleanup("empty_standard_repo");
git_futils_dirs_global_shutdown(); git_sysdir_global_shutdown();
} }
void test_repo_open__force_bare(void) void test_repo_open__force_bare(void)
......
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