Code

Fix filename verification when in a subdirectory
authorLinus Torvalds <torvalds@osdl.org>
Wed, 26 Apr 2006 17:15:54 +0000 (10:15 -0700)
committerJunio C Hamano <junkio@cox.net>
Wed, 26 Apr 2006 19:16:21 +0000 (12:16 -0700)
When we are in a subdirectory of a git archive, we need to take the prefix
of that subdirectory into accoung when we verify filename arguments.

Noted by Matthias Lederhofer

This also uses the improved error reporting for all the other git commands
that use the revision parsing interfaces, not just git-rev-parse. Also, it
makes the error reporting for mixed filenames and argument flags clearer
(you cannot put flags after the start of the pathname list).

[jc: with fix to a trivial typo noticed by Timo Hirvonen]

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
cache.h
rev-parse.c
revision.c
setup.c

diff --git a/cache.h b/cache.h
index 69801b02d535dbbe49535c876979cd093c6db2e1..4d8fabc6d8f3059d12640b66e6cf124c77022d07 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -134,6 +134,7 @@ extern const char *setup_git_directory_gently(int *);
 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);
 
 #define alloc_nr(x) (((x)+16)*3/2)
 
index 7f66ae2db827c6ce0ee245ac416d2e80a937061f..62e16af33c29ddd6a9c8b2d9755dc11804d86bc4 100644 (file)
@@ -160,14 +160,6 @@ static int show_file(const char *arg)
        return 0;
 }
 
-static void die_badfile(const char *arg)
-{
-       if (errno != ENOENT)
-               die("'%s': %s", arg, strerror(errno));
-       die("'%s' is ambiguous - revision name or file/directory name?\n"
-           "Please put '--' before the list of filenames.", arg);
-}
-
 int main(int argc, char **argv)
 {
        int i, as_is = 0, verify = 0;
@@ -177,14 +169,12 @@ int main(int argc, char **argv)
        git_config(git_default_config);
 
        for (i = 1; i < argc; i++) {
-               struct stat st;
                char *arg = argv[i];
                char *dotdot;
 
                if (as_is) {
                        if (show_file(arg) && as_is < 2)
-                               if (lstat(arg, &st) < 0)
-                                       die_badfile(arg);
+                               verify_filename(prefix, arg);
                        continue;
                }
                if (!strcmp(arg,"-n")) {
@@ -350,8 +340,7 @@ int main(int argc, char **argv)
                        continue;
                if (verify)
                        die("Needed a single revision");
-               if (lstat(arg, &st) < 0)
-                       die_badfile(arg);
+               verify_filename(prefix, arg);
        }
        show_default();
        if (verify && revs_count != 1)
index e1f9816bd7e2f91b3c23dedd50f0a03d33c33dfc..03dd23893947231ef8040ad3c38021ae64f27ae5 100644 (file)
@@ -675,17 +675,15 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                        arg++;
                }
                if (get_sha1(arg, sha1) < 0) {
-                       struct stat st;
                        int j;
 
                        if (seen_dashdash || local_flags)
                                die("bad revision '%s'", arg);
 
                        /* If we didn't have a "--", all filenames must exist */
-                       for (j = i; j < argc; j++) {
-                               if (lstat(argv[j], &st) < 0)
-                                       die("'%s': %s", argv[j], strerror(errno));
-                       }
+                       for (j = i; j < argc; j++)
+                               verify_filename(revs->prefix, argv[j]);
+
                        revs->prune_data = get_pathspec(revs->prefix, argv + i);
                        break;
                }
diff --git a/setup.c b/setup.c
index 36ede3d87483548bb1ce6c19361d7f6584386147..cce9bb80692f99ea1661fb8ab925955b5db0336c 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -62,6 +62,29 @@ const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
        return path;
 }
 
+/*
+ * Verify a filename that we got as an argument for a pathspec
+ * entry. Note that a filename that begins with "-" never verifies
+ * as true, because even if such a filename were to exist, we want
+ * it to be preceded by the "--" marker (or we want the user to
+ * use a format like "./-filename")
+ */
+void verify_filename(const char *prefix, const char *arg)
+{
+       const char *name;
+       struct stat st;
+
+       if (*arg == '-')
+               die("bad flag '%s' used after filename", arg);
+       name = prefix ? prefix_filename(prefix, strlen(prefix), arg) : 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("'%s': %s", arg, strerror(errno));
+}
+
 const char **get_pathspec(const char *prefix, const char **pathspec)
 {
        const char *entry = *pathspec;