summaryrefslogtreecommitdiff
path: root/src/util.c
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2013-03-15 16:39:00 -0700
committerRussell Belfer <rb@github.com>2013-03-15 16:39:00 -0700
commit5540d9477ed143707435324e785336d254b12e47 (patch)
tree4ffaba1990a82cc51ee5169d7d2913ecceef4df2 /src/util.c
parenta5f6138407efb6d8866fe8de5aac13454aefcd82 (diff)
downloadlibgit2-5540d9477ed143707435324e785336d254b12e47.tar.gz
Implement global/system file search paths
The goal of this work is to expose the search logic for "global", "system", and "xdg" files through the git_libgit2_opts() interface. Behind the scenes, I changed the logic for finding files to have a notion of a git_strarray that represents a search path and to store a separate search path for each of the three tiers of config file. For each tier, I implemented a function to initialize it to default values (generally based on environment variables), and then general interfaces to get it, set it, reset it, and prepend new directories to it. Next, I exposed these interfaces through the git_libgit2_opts interface, reusing the GIT_CONFIG_LEVEL_SYSTEM, etc., constants for the user to control which search path they were modifying. There are alternative designs for the opts interface / argument ordering, so I'm putting this phase out for discussion. Additionally, I ended up doing a little bit of clean up regarding attr.h and attr_file.h, adding a new attrcache.h so the other two files wouldn't have to be included in so many places.
Diffstat (limited to 'src/util.c')
-rw-r--r--src/util.c106
1 files changed, 98 insertions, 8 deletions
diff --git a/src/util.c b/src/util.c
index 885978046..f481646f7 100644
--- a/src/util.c
+++ b/src/util.c
@@ -10,6 +10,7 @@
#include <stdio.h>
#include <ctype.h>
#include "posix.h"
+#include "fileops.h"
#ifdef _MSC_VER
# include <Shlwapi.h>
@@ -38,13 +39,30 @@ int git_libgit2_capabilities()
extern size_t git_mwindow__window_size;
extern size_t git_mwindow__mapped_limit;
-void git_libgit2_opts(int key, ...)
+static int convert_config_level_to_futils_dir(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;
+ default:
+ giterr_set(
+ GITERR_INVALID, "Invalid config path selector %d", config_level);
+ }
+
+ return val;
+}
+
+int git_libgit2_opts(int key, ...)
+{
+ int error = 0;
va_list ap;
va_start(ap, key);
- switch(key) {
+ switch (key) {
case GIT_OPT_SET_MWINDOW_SIZE:
git_mwindow__window_size = va_arg(ap, size_t);
break;
@@ -60,9 +78,31 @@ void git_libgit2_opts(int key, ...)
case GIT_OPT_GET_MWINDOW_MAPPED_LIMIT:
*(va_arg(ap, size_t *)) = git_mwindow__mapped_limit;
break;
+
+ case GIT_OPT_GET_SEARCH_PATH:
+ {
+ const git_strarray **out = va_arg(ap, const git_strarray **);
+ int which = convert_config_level_to_futils_dir(va_arg(ap, int));
+
+ error = (which < 0) ? which : git_futils_dirs_get(out, which);
+ break;
+ }
+
+ case GIT_OPT_SET_SEARCH_PATH:
+ case GIT_OPT_PREPEND_SEARCH_PATH:
+ {
+ int which = convert_config_level_to_futils_dir(va_arg(ap, int));
+ const git_strarray *dirs = va_arg(ap, git_strarray *);
+
+ error = (which < 0) ? which : git_futils_dirs_set(
+ which, dirs, key == GIT_OPT_SET_SEARCH_PATH);
+ break;
+ }
}
va_end(ap);
+
+ return error;
}
void git_strarray_free(git_strarray *array)
@@ -72,34 +112,84 @@ void git_strarray_free(git_strarray *array)
git__free(array->strings[i]);
git__free(array->strings);
+
+ memset(array, 0, sizeof(*array));
}
int git_strarray_copy(git_strarray *tgt, const git_strarray *src)
{
+ assert(tgt && src);
+
+ memset(tgt, 0, sizeof(*tgt));
+ return git_strarray_prepend(tgt, src);
+}
+
+int git_strarray_set(git_strarray *tgt, size_t count, ...)
+{
size_t i;
+ va_list ap;
- assert(tgt && src);
+ assert(tgt);
memset(tgt, 0, sizeof(*tgt));
- if (!src->count)
+ if (!count)
return 0;
- tgt->strings = git__calloc(src->count, sizeof(char *));
+ tgt->strings = git__calloc(count, sizeof(char *));
GITERR_CHECK_ALLOC(tgt->strings);
- for (i = 0; i < src->count; ++i) {
- tgt->strings[tgt->count] = git__strdup(src->strings[i]);
+ va_start(ap, count);
+ for (i = 0; i < count; ++i) {
+ const char *str = va_arg(ap, const char *);
+ if (!str)
+ continue;
+ tgt->strings[tgt->count] = git__strdup(str);
if (!tgt->strings[tgt->count]) {
git_strarray_free(tgt);
- memset(tgt, 0, sizeof(*tgt));
+ va_end(ap);
return -1;
}
tgt->count++;
}
+ va_end(ap);
+
+ return 0;
+}
+
+int git_strarray_prepend(git_strarray *tgt, const git_strarray *src)
+{
+ size_t i;
+ git_strarray merge;
+
+ if (!src || !src->count)
+ return 0;
+
+ merge.count = 0;
+ merge.strings = git__calloc(tgt->count + src->count, sizeof(char *));
+ GITERR_CHECK_ALLOC(merge.strings);
+
+ for (i = 0; i < src->count; ++i) {
+ if (!src->strings[i])
+ continue;
+
+ merge.strings[merge.count] = git__strdup(src->strings[i]);
+ if (!merge.strings[merge.count]) {
+ git_strarray_free(&merge);
+ return -1;
+ }
+
+ merge.count++;
+ }
+
+ for (i = 0; i < tgt->count; ++i)
+ if (tgt->strings[i])
+ merge.strings[merge.count++] = tgt->strings[i];
+ git__free(tgt->strings);
+ memcpy(tgt, &merge, sizeof(merge));
return 0;
}