revision parsing: make "rev -- paths" checks stronger.
If you don't have a "--" marker, then: - all of the arguments we are going to assume are pathspecs must exist in the working tree. - none of the arguments we parsed as revisions could be interpreted as a filename. so that there really isn't any possibility of confusion in case somebody does have a revision that looks like a pathname too. The former rule has been in effect; this implements the latter. Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
69bcc43eca
commit
ea92f41ff9
1
cache.h
1
cache.h
@ -135,6 +135,7 @@ extern const char *setup_git_directory(void);
|
|||||||
extern const char *prefix_path(const char *prefix, int len, const char *path);
|
extern const char *prefix_path(const char *prefix, int len, const char *path);
|
||||||
extern const char *prefix_filename(const char *prefix, int len, const char *path);
|
extern const char *prefix_filename(const char *prefix, int len, const char *path);
|
||||||
extern void verify_filename(const char *prefix, const char *name);
|
extern void verify_filename(const char *prefix, const char *name);
|
||||||
|
extern void verify_non_filename(const char *prefix, const char *name);
|
||||||
|
|
||||||
#define alloc_nr(x) (((x)+16)*3/2)
|
#define alloc_nr(x) (((x)+16)*3/2)
|
||||||
|
|
||||||
|
14
revision.c
14
revision.c
@ -740,6 +740,11 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
|
|||||||
include = get_reference(revs, next, sha1, flags);
|
include = get_reference(revs, next, sha1, flags);
|
||||||
if (!exclude || !include)
|
if (!exclude || !include)
|
||||||
die("Invalid revision range %s..%s", arg, next);
|
die("Invalid revision range %s..%s", arg, next);
|
||||||
|
|
||||||
|
if (!seen_dashdash) {
|
||||||
|
*dotdot = '.';
|
||||||
|
verify_non_filename(revs->prefix, arg);
|
||||||
|
}
|
||||||
add_pending_object(revs, exclude, this);
|
add_pending_object(revs, exclude, this);
|
||||||
add_pending_object(revs, include, next);
|
add_pending_object(revs, include, next);
|
||||||
continue;
|
continue;
|
||||||
@ -757,13 +762,20 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
|
|||||||
if (seen_dashdash || local_flags)
|
if (seen_dashdash || local_flags)
|
||||||
die("bad revision '%s'", arg);
|
die("bad revision '%s'", arg);
|
||||||
|
|
||||||
/* If we didn't have a "--", all filenames must exist */
|
/* If we didn't have a "--":
|
||||||
|
* (1) all filenames must exist;
|
||||||
|
* (2) all rev-args must not be interpretable
|
||||||
|
* as a valid filename.
|
||||||
|
* but the latter we have checked in the main loop.
|
||||||
|
*/
|
||||||
for (j = i; j < argc; j++)
|
for (j = i; j < argc; j++)
|
||||||
verify_filename(revs->prefix, argv[j]);
|
verify_filename(revs->prefix, argv[j]);
|
||||||
|
|
||||||
revs->prune_data = get_pathspec(revs->prefix, argv + i);
|
revs->prune_data = get_pathspec(revs->prefix, argv + i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!seen_dashdash)
|
||||||
|
verify_non_filename(revs->prefix, arg);
|
||||||
object = get_reference(revs, arg, sha1, flags ^ local_flags);
|
object = get_reference(revs, arg, sha1, flags ^ local_flags);
|
||||||
add_pending_object(revs, object, arg);
|
add_pending_object(revs, object, arg);
|
||||||
}
|
}
|
||||||
|
24
setup.c
24
setup.c
@ -80,11 +80,31 @@ void verify_filename(const char *prefix, const char *arg)
|
|||||||
if (!lstat(name, &st))
|
if (!lstat(name, &st))
|
||||||
return;
|
return;
|
||||||
if (errno == ENOENT)
|
if (errno == ENOENT)
|
||||||
die("ambiguous argument '%s': unknown revision or filename\n"
|
die("ambiguous argument '%s': unknown revision or path not in the working tree.\n"
|
||||||
"Use '--' to separate filenames from revisions", arg);
|
"Use '--' to separate paths from revisions", arg);
|
||||||
die("'%s': %s", arg, strerror(errno));
|
die("'%s': %s", arg, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Opposite of the above: the command line did not have -- marker
|
||||||
|
* and we parsed the arg as a refname. It should not be interpretable
|
||||||
|
* as a filename.
|
||||||
|
*/
|
||||||
|
void verify_non_filename(const char *prefix, const char *arg)
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (*arg == '-')
|
||||||
|
return; /* flag */
|
||||||
|
name = prefix ? prefix_filename(prefix, strlen(prefix), arg) : arg;
|
||||||
|
if (!lstat(name, &st))
|
||||||
|
die("ambiguous argument '%s': both revision and filename\n"
|
||||||
|
"Use '--' to separate filenames from revisions", arg);
|
||||||
|
if (errno != ENOENT)
|
||||||
|
die("'%s': %s", arg, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
const char **get_pathspec(const char *prefix, const char **pathspec)
|
const char **get_pathspec(const char *prefix, const char **pathspec)
|
||||||
{
|
{
|
||||||
const char *entry = *pathspec;
|
const char *entry = *pathspec;
|
||||||
|
Loading…
Reference in New Issue
Block a user