move struct pathspec and related functions to pathspec.[ch]

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Nguyễn Thái Ngọc Duy
2013-07-14 15:35:25 +07:00
committed by Junio C Hamano
parent 5fee4df7f4
commit 64acde94ef
13 changed files with 182 additions and 169 deletions

149
setup.c
View File

@ -154,155 +154,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.