checkout: proper error message on 'git checkout foo bar --'

The previous code was detecting the presence of "--" by looking only at argument 1. As a result, "git checkout foo bar --" was interpreted as an ambiguous file/revision list, and errored out with: error: pathspec 'foo' did not match any file(s) known to git. error: pathspec 'bar' did not match any file(s) known to git. error: pathspec '--' did not match any file(s) known to git. This patch fixes it by walking through the argument list to find the "--", and now complains about the number of references given. Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Matthieu Moy committed Oct 18, 2013 at 11:25 UTC bca39695343ecb113b30c72a3b2e0cb7e73757d8
2 files changed +22 -5
builtin/checkout.c
+16 -5
@@ -872,7 +872,9 @@ static int parse_branchname_arg(int argc, const char **argv,
872 int argcount = 0;
873 unsigned char branch_rev[20];
874 const char *arg;
875 - int has_dash_dash;
875 + int dash_dash_pos;
876 + int has_dash_dash = 0;
877 + int i;
878
879 /*
880 * case 1: git checkout <ref> -- [<paths>]
@@ -916,11 +918,20 @@ static int parse_branchname_arg(int argc, const char **argv,
918 if (!argc)
919 return 0;
920
919 - if (!strcmp(argv[0], "--")) /* case (2) */
920 - return 1;
921 -
921 arg = argv[0];
923 - has_dash_dash = (argc > 1) && !strcmp(argv[1], "--");
922 + dash_dash_pos = -1;
923 + for (i = 0; i < argc; i++) {
924 + if (!strcmp(argv[i], "--")) {
925 + dash_dash_pos = i;
926 + break;
927 + }
928 + }
929 + if (dash_dash_pos == 0)
930 + return 1; /* case (2) */
931 + else if (dash_dash_pos == 1)
932 + has_dash_dash = 1; /* case (3) or (1) */
933 + else if (dash_dash_pos >= 2)
934 + die(_("only one reference expected, %d given."), dash_dash_pos);
935
936 if (!strcmp(arg, "-"))
937 arg = "@{-1}";
t/t2010-checkout-ambiguous.sh
+6
@@ -47,4 +47,10 @@ test_expect_success 'disambiguate checking out from a tree-ish' '
47 git diff --exit-code --quiet
48 '
49
50 +test_expect_success 'accurate error message with more than one ref' '
51 + test_must_fail git checkout HEAD master -- 2>actual &&
52 + grep 2 actual &&
53 + test_i18ngrep "one reference expected, 2 given" actual
54 +'
55 +
56 test_done