Skip to content

Commit

Permalink
revision parsing: make "rev -- paths" checks stronger.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Junio C Hamano committed Apr 27, 2006
1 parent 69bcc43 commit ea92f41
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 3 deletions.
1 change: 1 addition & 0 deletions cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_filename(const char *prefix, int len, const char *path);
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)

Expand Down
14 changes: 13 additions & 1 deletion revision.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
if (!exclude || !include)
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, include, next);
continue;
Expand All @@ -757,13 +762,20 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
if (seen_dashdash || local_flags)
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++)
verify_filename(revs->prefix, argv[j]);

revs->prune_data = get_pathspec(revs->prefix, argv + i);
break;
}
if (!seen_dashdash)
verify_non_filename(revs->prefix, arg);
object = get_reference(revs, arg, sha1, flags ^ local_flags);
add_pending_object(revs, object, arg);
}
Expand Down
24 changes: 22 additions & 2 deletions setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,31 @@ void verify_filename(const char *prefix, const char *arg)
if (!lstat(name, &st))
return;
if (errno == ENOENT)
die("ambiguous argument '%s': unknown revision or filename\n"
"Use '--' to separate filenames from revisions", arg);
die("ambiguous argument '%s': unknown revision or path not in the working tree.\n"
"Use '--' to separate paths from revisions", arg);
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 *entry = *pathspec;
Expand Down

0 comments on commit ea92f41

Please sign in to comment.