diff options
author | Linus Torvalds <torvalds@osdl.org> | 2005-10-28 12:41:49 -0700 |
---|---|---|
committer | Junio C Hamano <junkio@cox.net> | 2005-10-28 14:25:05 -0700 |
commit | af13cdf298b927d171a58ec30c885d2a9c9bf727 (patch) | |
tree | c297ec95c45be168d4cdb93fe417d8b8d62aded9 /sha1_name.c | |
parent | 41f222e87a9062833712367d66114cae90b3769a (diff) | |
download | git-af13cdf298b927d171a58ec30c885d2a9c9bf727.tar.gz git-af13cdf298b927d171a58ec30c885d2a9c9bf727.tar.xz |
Be more careful about reference parsing
This does two things:
- we don't allow "." and ".." as components of a refname. Thus get_sha1()
will not accept "./refname" as being the same as "refname" any more.
- git-rev-parse stops doing revision translation after seeing a pathname,
to match the brhaviour of all the tools (once we see a pathname,
everything else will also be parsed as a pathname).
Basically, if you did
git log *
and "gitk" was somewhere in the "*", we don't want to replace the filename
"gitk" with the SHA1 of the branch with the same name.
Of course, if there is any change of ambiguity, you should always use "--"
to make it explicit what are filenames and what are revisions, but this
makes the normal cases sane. The refname rule also means that instead of
the "--", you can do the same thing we're used to doing with filenames
that start with a slash: use "./filename" instead, and now it's a
filename, not an option (and not a revision).
So "git log ./*.c" is now actually a perfectly valid thing to do, even if
the first C-file might have the same name as a branch.
Trivial test:
git-rev-parse gitk ./gitk gitk
should output something like
9843c3074dfbf57117565f6b7c93e3e6812857ee
./gitk
gitk
where the "./gitk" isn't seen as a revision, and the second "gitk" is a
filename simply because we've seen filenames already, and thus stopped
doing revision parsing.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
Diffstat (limited to 'sha1_name.c')
-rw-r--r-- | sha1_name.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/sha1_name.c b/sha1_name.c index cc320d3d7..fe409fbce 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -203,6 +203,29 @@ const char *find_unique_abbrev(const unsigned char *sha1, int len) return NULL; } +static int ambiguous_path(const char *path) +{ + int slash = 1; + + for (;;) { + switch (*path++) { + case '\0': + break; + case '/': + if (slash) + break; + slash = 1; + continue; + case '.': + continue; + default: + slash = 0; + continue; + } + return slash; + } +} + static int get_sha1_basic(const char *str, int len, unsigned char *sha1) { static const char *prefix[] = { @@ -217,6 +240,10 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1) if (len == 40 && !get_sha1_hex(str, sha1)) return 0; + /* Accept only unambiguous ref paths. */ + if (ambiguous_path(str)) + return -1; + for (p = prefix; *p; p++) { char *pathname = git_path("%s/%.*s", *p, len, str); if (!read_ref(pathname, sha1)) |