Merge branch 'jk/pathspec-magic-disambiguation'
The convention for a command line is to follow "git cmdname --options" with revisions followed by an optional "--" disambiguator and then finally pathspecs. When "--" is not there, we make sure early ones are all interpretable as revs (and do not look like paths) and later ones are the other way around. A pathspec with "magic" (e.g. ":/p/a/t/h" that matches p/a/t/h from the top-level of the working tree, no matter what subdirectory you are working from) are conservatively judged as "not a path", which required disambiguation more often. The command line parser learned to say "it's a pathspec" a bit more often when the syntax looks like so. * jk/pathspec-magic-disambiguation: verify_filename(): flip order of checks verify_filename(): treat ":(magic)" as a pathspec check_filename(): handle ":^" path magic check_filename(): use skip_prefix check_filename(): refactor ":/" handling t4208: add check for ":/" without matching file
This commit is contained in:
42
setup.c
42
setup.c
@ -134,19 +134,23 @@ int path_inside_repo(const char *prefix, const char *path)
|
||||
|
||||
int check_filename(const char *prefix, const char *arg)
|
||||
{
|
||||
const char *name;
|
||||
char *to_free = NULL;
|
||||
struct stat st;
|
||||
|
||||
if (starts_with(arg, ":/")) {
|
||||
if (arg[2] == '\0') /* ":/" is root dir, always exists */
|
||||
if (skip_prefix(arg, ":/", &arg)) {
|
||||
if (!*arg) /* ":/" is root dir, always exists */
|
||||
return 1;
|
||||
name = arg + 2;
|
||||
} else if (prefix)
|
||||
name = to_free = prefix_filename(prefix, arg);
|
||||
else
|
||||
name = arg;
|
||||
if (!lstat(name, &st)) {
|
||||
prefix = NULL;
|
||||
} else if (skip_prefix(arg, ":!", &arg) ||
|
||||
skip_prefix(arg, ":^", &arg)) {
|
||||
if (!*arg) /* excluding everything is silly, but allowed */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (prefix)
|
||||
arg = to_free = prefix_filename(prefix, arg);
|
||||
|
||||
if (!lstat(arg, &st)) {
|
||||
free(to_free);
|
||||
return 1; /* file exists */
|
||||
}
|
||||
@ -181,6 +185,24 @@ static void NORETURN die_verify_filename(const char *prefix,
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for arguments that don't resolve as actual files,
|
||||
* but which look sufficiently like pathspecs that we'll consider
|
||||
* them such for the purposes of rev/pathspec DWIM parsing.
|
||||
*/
|
||||
static int looks_like_pathspec(const char *arg)
|
||||
{
|
||||
/* anything with a wildcard character */
|
||||
if (!no_wildcard(arg))
|
||||
return 1;
|
||||
|
||||
/* long-form pathspec magic */
|
||||
if (starts_with(arg, ":("))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify a filename that we got as an argument for a pathspec
|
||||
* entry. Note that a filename that begins with "-" never verifies
|
||||
@ -207,7 +229,7 @@ void verify_filename(const char *prefix,
|
||||
{
|
||||
if (*arg == '-')
|
||||
die("bad flag '%s' used after filename", arg);
|
||||
if (check_filename(prefix, arg) || !no_wildcard(arg))
|
||||
if (looks_like_pathspec(arg) || check_filename(prefix, arg))
|
||||
return;
|
||||
die_verify_filename(prefix, arg, diagnose_misspelt_rev);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user