Merge branch 'mm/verify-filename-fix' into maint
authorJunio C Hamano <gitster@pobox.com>
Wed, 11 Jul 2012 19:45:49 +0000 (12:45 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 11 Jul 2012 19:45:49 +0000 (12:45 -0700)
"git diff COPYING HEAD:COPYING" gave a nonsense error message that
claimed that the treeish HEAD did not have COPYING in it.

* mm/verify-filename-fix:
verify_filename(): ask the caller to chose the kind of diagnosis
sha1_name: do not trigger detailed diagnosis for file arguments

builtin/grep.c
builtin/reset.c
builtin/rev-parse.c
cache.h
revision.c
setup.c
sha1_name.c
t/t1506-rev-parse-diagnosis.sh
index fe1726f5ef60d054938eaa849f2ae6020a95f805..29adb0ac9399002b07942711863fa3b353926468 100644 (file)
@@ -928,7 +928,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
        if (!seen_dashdash) {
                int j;
                for (j = i; j < argc; j++)
-                       verify_filename(prefix, argv[j]);
+                       verify_filename(prefix, argv[j], j == i);
        }
 
        paths = get_pathspec(prefix, argv + i);
index 8c2c1d52a227334a3d6456bf0989cd561628ffa0..4cc34c908446fe2d3db5acf315e47f2768ba07bd 100644 (file)
@@ -285,7 +285,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
                        rev = argv[i++];
                } else {
                        /* Otherwise we treat this as a filename */
-                       verify_filename(prefix, argv[i]);
+                       verify_filename(prefix, argv[i], 1);
                }
        }
 
index 733f626f6c3e4ef54d54df923230f7ae4fbb2d7d..13495b88f5da1efc2094c0e69abfe93605ee8c03 100644 (file)
@@ -486,7 +486,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 
                if (as_is) {
                        if (show_file(arg) && as_is < 2)
-                               verify_filename(prefix, arg);
+                               verify_filename(prefix, arg, 0);
                        continue;
                }
                if (!strcmp(arg,"-n")) {
@@ -734,7 +734,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
                as_is = 1;
                if (!show_file(arg))
                        continue;
-               verify_filename(prefix, arg);
+               verify_filename(prefix, arg, 1);
        }
        if (verify) {
                if (revs_count == 1) {
diff --git a/cache.h b/cache.h
index 06413e1584dc762063feaa3728209a4d2864ebc7..506d1574f2ddba4b19146d5275e620f5f6733402 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -409,7 +409,9 @@ extern const char *setup_git_directory(void);
 extern 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 int check_filename(const char *prefix, const char *name);
-extern void verify_filename(const char *prefix, const char *name);
+extern void verify_filename(const char *prefix,
+                           const char *name,
+                           int diagnose_misspelt_rev);
 extern void verify_non_filename(const char *prefix, const char *name);
 
 #define INIT_DB_QUIET 0x0001
index 935e7a7ba413668c95a6c3e846b9058be07f0425..39cc6b0eab413d59c8f8c35a8d994df8d2025741 100644 (file)
@@ -1781,7 +1781,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
                         * but the latter we have checked in the main loop.
                         */
                        for (j = i; j < argc; j++)
-                               verify_filename(revs->prefix, argv[j]);
+                               verify_filename(revs->prefix, argv[j], j == i);
 
                        append_prune_data(&prune_data, argv + i);
                        break;
diff --git a/setup.c b/setup.c
index 731851a4a85161af49a38c481672615a6ac0bbc9..994976946b4b451ee41508a2649987c9b4e9bdbc 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -53,11 +53,17 @@ int check_filename(const char *prefix, const char *arg)
        die_errno("failed to stat '%s'", arg);
 }
 
-static void NORETURN die_verify_filename(const char *prefix, const char *arg)
+static void NORETURN die_verify_filename(const char *prefix,
+                                        const char *arg,
+                                        int diagnose_misspelt_rev)
 {
        unsigned char sha1[20];
        unsigned mode;
 
+       if (!diagnose_misspelt_rev)
+               die("%s: no such path in the working tree.\n"
+                   "Use '-- <path>...' to specify paths that do not exist locally.",
+                   arg);
        /*
         * Saying "'(icase)foo' does not exist in the index" when the
         * user gave us ":(icase)foo" is just stupid.  A magic pathspec
@@ -80,14 +86,29 @@ static void NORETURN die_verify_filename(const char *prefix, const char *arg)
  * 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")
+ *
+ * The "diagnose_misspelt_rev" is used to provide a user-friendly
+ * diagnosis when dying upon finding that "name" is not a pathname.
+ * If set to 1, the diagnosis will try to diagnose "name" as an
+ * invalid object name (e.g. HEAD:foo). If set to 0, the diagnosis
+ * will only complain about an inexisting file.
+ *
+ * This function is typically called to check that a "file or rev"
+ * argument is unambiguous. In this case, the caller will want
+ * diagnose_misspelt_rev == 1 when verifying the first non-rev
+ * argument (which could have been a revision), and
+ * diagnose_misspelt_rev == 0 for the next ones (because we already
+ * saw a filename, there's not ambiguity anymore).
  */
-void verify_filename(const char *prefix, const char *arg)
+void verify_filename(const char *prefix,
+                    const char *arg,
+                    int diagnose_misspelt_rev)
 {
        if (*arg == '-')
                die("bad flag '%s' used after filename", arg);
        if (check_filename(prefix, arg))
                return;
-       die_verify_filename(prefix, arg);
+       die_verify_filename(prefix, arg, diagnose_misspelt_rev);
 }
 
 /*
index c6331136d19c5224078fa78b6e5e794fcc587fe2..5d81ea0564c8d90b417eb8ec5ed8c32baa2c3ea3 100644 (file)
@@ -1127,7 +1127,7 @@ int get_sha1_with_context_1(const char *name, unsigned char *sha1,
                        if (new_filename)
                                filename = new_filename;
                        ret = get_tree_entry(tree_sha1, filename, sha1, &oc->mode);
-                       if (only_to_die) {
+                       if (ret && only_to_die) {
                                diagnose_invalid_sha1_path(prefix, filename,
                                                           tree_sha1, object_name);
                                free(object_name);
index 0843a1c13b3e1458418ee59c548e5441f113bbe7..c5cb77a0e1f34ac46dd8727341948389624e8f38 100755 (executable)
@@ -171,4 +171,15 @@ test_expect_success 'relative path when startup_info is NULL' '
        grep "BUG: startup_info struct is not initialized." error
 '
 
+test_expect_success '<commit>:file correctly diagnosed after a pathname' '
+       test_must_fail git rev-parse file.txt HEAD:file.txt 1>actual 2>error &&
+       test_i18ngrep ! "exists on disk" error &&
+       test_i18ngrep "no such path in the working tree" error &&
+       cat >expect <<-\EOF &&
+       file.txt
+       HEAD:file.txt
+       EOF
+       test_cmp expect actual
+'
+
 test_done