@@ -1153,9 +1153,8 @@ static int parse_branchname_arg(int argc, const char **argv,
{
const char **new_branch = &opts->new_branch;
const char *arg;
- int dash_dash_pos;
- int has_dash_dash = 0, expect_commit_only = 0;
- int i;
+ int dash_dash_pos, i;
+ int recover_with_dwim, expect_commit_only;
/*
* Resolve ambiguity where argv[0] may be <pathspec> or <commit>.
@@ -1174,15 +1173,7 @@ static int parse_branchname_arg(int argc, const char **argv,
* do that and proceed with (2)(3).
* 5) Otherwise, let caller proceed with <pathspec> interpretation.
*/
- if (!argc)
- return 0;
-
- if (!opts->accept_pathspec) {
- if (argc > 1)
- die(_("only one reference expected"));
- has_dash_dash = 1; /* helps disambiguate */
- }
-
+
arg = argv[0];
dash_dash_pos = -1;
for (i = 0; i < argc; i++) {
@@ -1192,17 +1183,49 @@ static int parse_branchname_arg(int argc, const char **argv,
}
}
- if (opts->accept_pathspec) {
- if (dash_dash_pos == 0)
- return 1;
- else if (dash_dash_pos == 1)
- has_dash_dash = 1;
- else if (dash_dash_pos >= 2)
- die(_("only one reference expected, %d given."), dash_dash_pos);
- }
+ if (dash_dash_pos == -1) {
+ if (argc == 0) {
+ /* 'git checkout/switch/restore' */
+ return 0;
+ } else if (argc == 1) {
+ /* 'git checkout/switch/restore <something>' */
+ recover_with_dwim = dwim_new_local_branch_ok;
+ } else if (!opts->accept_pathspec) {
+ /* 'git switch <commit> <unexpected> [...]' */
+ die(_("only one reference expected, %d given."), argc);
+ } else {
+ /* 'git checkout/restore <something> <pathspec> [...]' */
+ recover_with_dwim = 0;
+ }
+
+ /*
+ * Absence of '--' leaves <pathspec>/<commit> ambiguity.
+ * Try to resolve it with additional knowledge about pathspec args.
+ */
+ expect_commit_only = !opts->accept_pathspec;
+ } else if (dash_dash_pos == 0) {
+ /* 'git checkout/switch/restore -- [...]' */
+ return 1; /* Eat '--' */
+ } else if (dash_dash_pos == 1) {
+ if (!opts->accept_pathspec) {
+ /* 'git switch <commit> -- [...]' */
+ die(_("incompatible with pathspec arguments"));
+ }
+
+ if (argc == 2) {
+ /* 'git checkout/restore <commit> --' */
+ recover_with_dwim = dwim_new_local_branch_ok;
+ } else {
+ /* 'git checkout/restore <commit> -- <pathspec> [...]' */
+ recover_with_dwim = 0;
+ }
- if (has_dash_dash)
- expect_commit_only = 1;
+ /* Presence of '--' makes it certain that arg is <commit> */
+ expect_commit_only = 1;
+ } else {
+ /* 'git checkout/switch/restore <commit> <unxpected> [...] -- [...]' */
+ die(_("only one reference expected, %d given."), dash_dash_pos);
+ }
opts->count_checkout_paths = !opts->quiet && !expect_commit_only;
@@ -1210,19 +1233,12 @@ static int parse_branchname_arg(int argc, const char **argv,
arg = "@{-1}";
if (get_oid_mb(arg, rev)) {
- int recover_with_dwim = dwim_new_local_branch_ok;
-
int could_be_checkout_paths = !expect_commit_only &&
check_filename(opts->prefix, arg);
if (!expect_commit_only && !no_wildcard(arg))
recover_with_dwim = 0;
- if (!(argc == 1 && !has_dash_dash) &&
- !(argc == 2 && has_dash_dash) &&
- opts->accept_pathspec)
- recover_with_dwim = 0;
-
if (recover_with_dwim) {
const char *remote = parse_remote_branch(arg, rev,
could_be_checkout_paths);