summaryrefslogtreecommitdiff
path: root/sha1_name.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@osdl.org>2005-10-28 12:41:49 -0700
committerJunio C Hamano <junkio@cox.net>2005-10-28 14:25:05 -0700
commitaf13cdf298b927d171a58ec30c885d2a9c9bf727 (patch)
treec297ec95c45be168d4cdb93fe417d8b8d62aded9 /sha1_name.c
parent41f222e87a9062833712367d66114cae90b3769a (diff)
downloadgit-af13cdf298b927d171a58ec30c885d2a9c9bf727.tar.gz
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.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/sha1_name.c b/sha1_name.c
index cc320d3d7f..fe409fbce4 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))