diff options
Diffstat (limited to 'setup.c')
-rw-r--r-- | setup.c | 173 |
1 files changed, 20 insertions, 153 deletions
@@ -5,7 +5,19 @@ static int inside_git_dir = -1; static int inside_work_tree = -1; -static char *prefix_path_gently(const char *prefix, int len, const char *path) +/* + * Normalize "path", prepending the "prefix" for relative paths. If + * remaining_prefix is not NULL, return the actual prefix still + * remains in the path. For example, prefix = sub1/sub2/ and path is + * + * foo -> sub1/sub2/foo (full prefix) + * ../foo -> sub1/foo (remaining prefix is sub1/) + * ../../bar -> bar (no remaining prefix) + * ../../sub1/sub2/foo -> sub1/sub2/foo (but no remaining prefix) + * `pwd`/../bar -> sub1/bar (no remaining prefix) + */ +char *prefix_path_gently(const char *prefix, int len, + int *remaining_prefix, const char *path) { const char *orig = path; char *sanitized; @@ -13,13 +25,17 @@ static char *prefix_path_gently(const char *prefix, int len, const char *path) const char *temp = real_path(path); sanitized = xmalloc(len + strlen(temp) + 1); strcpy(sanitized, temp); + if (remaining_prefix) + *remaining_prefix = 0; } else { sanitized = xmalloc(len + strlen(path) + 1); if (len) memcpy(sanitized, prefix, len); strcpy(sanitized + len, path); + if (remaining_prefix) + *remaining_prefix = len; } - if (normalize_path_copy(sanitized, sanitized)) + if (normalize_path_copy_len(sanitized, sanitized, remaining_prefix)) goto error_out; if (is_absolute_path(orig)) { size_t root_len, len, total; @@ -44,7 +60,7 @@ static char *prefix_path_gently(const char *prefix, int len, const char *path) char *prefix_path(const char *prefix, int len, const char *path) { - char *r = prefix_path_gently(prefix, len, path); + char *r = prefix_path_gently(prefix, len, NULL, path); if (!r) die("'%s' is outside repository", path); return r; @@ -53,7 +69,7 @@ char *prefix_path(const char *prefix, int len, const char *path) int path_inside_repo(const char *prefix, const char *path) { int len = prefix ? strlen(prefix) : 0; - char *r = prefix_path_gently(prefix, len, path); + char *r = prefix_path_gently(prefix, len, NULL, path); if (r) { free(r); return 1; @@ -154,155 +170,6 @@ void verify_non_filename(const char *prefix, const char *arg) "'git <command> [<revision>...] -- [<file>...]'", arg); } -/* - * Magic pathspec - * - * NEEDSWORK: These need to be moved to dir.h or even to a new - * pathspec.h when we restructure get_pathspec() users to use the - * "struct pathspec" interface. - * - * Possible future magic semantics include stuff like: - * - * { PATHSPEC_NOGLOB, '!', "noglob" }, - * { PATHSPEC_ICASE, '\0', "icase" }, - * { PATHSPEC_RECURSIVE, '*', "recursive" }, - * { PATHSPEC_REGEXP, '\0', "regexp" }, - * - */ -#define PATHSPEC_FROMTOP (1<<0) - -static struct pathspec_magic { - unsigned bit; - char mnemonic; /* this cannot be ':'! */ - const char *name; -} pathspec_magic[] = { - { PATHSPEC_FROMTOP, '/', "top" }, -}; - -/* - * Take an element of a pathspec and check for magic signatures. - * Append the result to the prefix. - * - * For now, we only parse the syntax and throw out anything other than - * "top" magic. - * - * NEEDSWORK: This needs to be rewritten when we start migrating - * get_pathspec() users to use the "struct pathspec" interface. For - * example, a pathspec element may be marked as case-insensitive, but - * the prefix part must always match literally, and a single stupid - * string cannot express such a case. - */ -static const char *prefix_pathspec(const char *prefix, int prefixlen, const char *elt) -{ - unsigned magic = 0; - const char *copyfrom = elt; - int i; - - if (elt[0] != ':') { - ; /* nothing to do */ - } else if (elt[1] == '(') { - /* longhand */ - const char *nextat; - for (copyfrom = elt + 2; - *copyfrom && *copyfrom != ')'; - copyfrom = nextat) { - size_t len = strcspn(copyfrom, ",)"); - if (copyfrom[len] == ',') - nextat = copyfrom + len + 1; - else - /* handle ')' and '\0' */ - nextat = copyfrom + len; - if (!len) - continue; - for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++) - if (strlen(pathspec_magic[i].name) == len && - !strncmp(pathspec_magic[i].name, copyfrom, len)) { - magic |= pathspec_magic[i].bit; - break; - } - if (ARRAY_SIZE(pathspec_magic) <= i) - die("Invalid pathspec magic '%.*s' in '%s'", - (int) len, copyfrom, elt); - } - if (*copyfrom != ')') - die("Missing ')' at the end of pathspec magic in '%s'", elt); - copyfrom++; - } else { - /* shorthand */ - for (copyfrom = elt + 1; - *copyfrom && *copyfrom != ':'; - copyfrom++) { - char ch = *copyfrom; - - if (!is_pathspec_magic(ch)) - break; - for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++) - if (pathspec_magic[i].mnemonic == ch) { - magic |= pathspec_magic[i].bit; - break; - } - if (ARRAY_SIZE(pathspec_magic) <= i) - die("Unimplemented pathspec magic '%c' in '%s'", - ch, elt); - } - if (*copyfrom == ':') - copyfrom++; - } - - if (magic & PATHSPEC_FROMTOP) - return xstrdup(copyfrom); - else - return prefix_path(prefix, prefixlen, copyfrom); -} - -/* - * N.B. get_pathspec() is deprecated in favor of the "struct pathspec" - * based interface - see pathspec_magic above. - * - * Arguments: - * - prefix - a path relative to the root of the working tree - * - pathspec - a list of paths underneath the prefix path - * - * Iterates over pathspec, prepending each path with prefix, - * and return the resulting list. - * - * If pathspec is empty, return a singleton list containing prefix. - * - * If pathspec and prefix are both empty, return an empty list. - * - * This is typically used by built-in commands such as add.c, in order - * to normalize argv arguments provided to the built-in into a list of - * paths to process, all relative to the root of the working tree. - */ -const char **get_pathspec(const char *prefix, const char **pathspec) -{ - const char *entry = *pathspec; - const char **src, **dst; - int prefixlen; - - if (!prefix && !entry) - return NULL; - - if (!entry) { - static const char *spec[2]; - spec[0] = prefix; - spec[1] = NULL; - return spec; - } - - /* Otherwise we have to re-write the entries.. */ - src = pathspec; - dst = pathspec; - prefixlen = prefix ? strlen(prefix) : 0; - while (*src) { - *(dst++) = prefix_pathspec(prefix, prefixlen, *src); - src++; - } - *dst = NULL; - if (!*pathspec) - return NULL; - return pathspec; -} /* * Test if it looks like we're at a git directory. |