diff options
Diffstat (limited to 'path.c')
-rw-r--r-- | path.c | 115 |
1 files changed, 72 insertions, 43 deletions
@@ -12,6 +12,7 @@ */ #include "cache.h" #include "strbuf.h" +#include "string-list.h" static char bad_path[] = "/bad-path/"; @@ -48,7 +49,7 @@ char *mksnpath(char *buf, size_t n, const char *fmt, ...) return cleanup_path(buf); } -static char *git_vsnpath(char *buf, size_t n, const char *fmt, va_list args) +static char *vsnpath(char *buf, size_t n, const char *fmt, va_list args) { const char *git_dir = get_git_dir(); size_t len; @@ -70,21 +71,37 @@ bad: char *git_snpath(char *buf, size_t n, const char *fmt, ...) { + char *ret; va_list args; va_start(args, fmt); - (void)git_vsnpath(buf, n, fmt, args); + ret = vsnpath(buf, n, fmt, args); va_end(args); - return buf; + return ret; } char *git_pathdup(const char *fmt, ...) { - char path[PATH_MAX]; + char path[PATH_MAX], *ret; + va_list args; + va_start(args, fmt); + ret = vsnpath(path, sizeof(path), fmt, args); + va_end(args); + return xstrdup(ret); +} + +char *mkpathdup(const char *fmt, ...) +{ + char *path; + struct strbuf sb = STRBUF_INIT; va_list args; + va_start(args, fmt); - (void)git_vsnpath(path, sizeof(path), fmt, args); + strbuf_vaddf(&sb, fmt, args); va_end(args); - return xstrdup(path); + path = xstrdup(cleanup_path(sb.buf)); + + strbuf_release(&sb); + return path; } char *mkpath(const char *fmt, ...) @@ -103,23 +120,40 @@ char *mkpath(const char *fmt, ...) char *git_path(const char *fmt, ...) { - const char *git_dir = get_git_dir(); char *pathname = get_pathname(); va_list args; - unsigned len; + char *ret; - len = strlen(git_dir); - if (len > PATH_MAX-100) - return bad_path; - memcpy(pathname, git_dir, len); - if (len && git_dir[len-1] != '/') - pathname[len++] = '/'; va_start(args, fmt); - len += vsnprintf(pathname + len, PATH_MAX - len, fmt, args); + ret = vsnpath(pathname, PATH_MAX, fmt, args); va_end(args); - if (len >= PATH_MAX) - return bad_path; - return cleanup_path(pathname); + return ret; +} + +void home_config_paths(char **global, char **xdg, char *file) +{ + char *xdg_home = getenv("XDG_CONFIG_HOME"); + char *home = getenv("HOME"); + char *to_free = NULL; + + if (!home) { + if (global) + *global = NULL; + } else { + if (!xdg_home) { + to_free = mkpathdup("%s/.config", home); + xdg_home = to_free; + } + if (global) + *global = mkpathdup("%s/.gitconfig", home); + } + + if (!xdg_home) + *xdg = NULL; + else + *xdg = mkpathdup("%s/git/%s", xdg_home, file); + + free(to_free); } char *git_path_submodule(const char *path, const char *fmt, ...) @@ -536,43 +570,38 @@ int normalize_path_copy(char *dst, const char *src) /* * path = Canonical absolute path - * prefix_list = Colon-separated list of absolute paths + * prefixes = string_list containing normalized, absolute paths without + * trailing slashes (except for the root directory, which is denoted by "/"). * - * Determines, for each path in prefix_list, whether the "prefix" really + * Determines, for each path in prefixes, whether the "prefix" * is an ancestor directory of path. Returns the length of the longest * ancestor directory, excluding any trailing slashes, or -1 if no prefix - * is an ancestor. (Note that this means 0 is returned if prefix_list is - * "/".) "/foo" is not considered an ancestor of "/foobar". Directories + * is an ancestor. (Note that this means 0 is returned if prefixes is + * ["/"].) "/foo" is not considered an ancestor of "/foobar". Directories * are not considered to be their own ancestors. path must be in a * canonical form: empty components, or "." or ".." components are not - * allowed. prefix_list may be null, which is like "". + * allowed. */ -int longest_ancestor_length(const char *path, const char *prefix_list) +int longest_ancestor_length(const char *path, struct string_list *prefixes) { - char buf[PATH_MAX+1]; - const char *ceil, *colon; - int len, max_len = -1; + int i, max_len = -1; - if (prefix_list == NULL || !strcmp(path, "/")) + if (!strcmp(path, "/")) return -1; - for (colon = ceil = prefix_list; *colon; ceil = colon+1) { - for (colon = ceil; *colon && *colon != PATH_SEP; colon++); - len = colon - ceil; - if (len == 0 || len > PATH_MAX || !is_absolute_path(ceil)) - continue; - strlcpy(buf, ceil, len+1); - if (normalize_path_copy(buf, buf) < 0) - continue; - len = strlen(buf); - if (len > 0 && buf[len-1] == '/') - buf[--len] = '\0'; + for (i = 0; i < prefixes->nr; i++) { + const char *ceil = prefixes->items[i].string; + int len = strlen(ceil); + + if (len == 1 && ceil[0] == '/') + len = 0; /* root matches anything, with length 0 */ + else if (!strncmp(path, ceil, len) && path[len] == '/') + ; /* match of length len */ + else + continue; /* no match */ - if (!strncmp(path, buf, len) && - path[len] == '/' && - len > max_len) { + if (len > max_len) max_len = len; - } } return max_len; |