From: Junio C Hamano Date: Mon, 22 Sep 2008 06:50:05 +0000 (-0700) Subject: Merge branch 'db/maint-checkout-b' X-Git-Tag: v1.6.1-rc1~222 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/666599d798102df2d7b32196cadb7dfb737e0b32?ds=inline;hp=-c Merge branch 'db/maint-checkout-b' * db/maint-checkout-b: Check early that a new branch is new and valid --- 666599d798102df2d7b32196cadb7dfb737e0b32 diff --combined builtin-checkout.c index 9377a1c71e,1ee23468ff..4497b7092d --- a/builtin-checkout.c +++ b/builtin-checkout.c @@@ -184,7 -184,7 +184,7 @@@ struct checkout_opts int force; int writeout_error; - char *new_branch; + const char *new_branch; int new_branch_log; enum branch_track track; }; @@@ -464,28 -464,13 +464,28 @@@ int cmd_checkout(int argc, const char * git_config(git_default_config, NULL); - opts.track = git_branch_track; + opts.track = BRANCH_TRACK_UNSPECIFIED; argc = parse_options(argc, argv, options, checkout_usage, PARSE_OPT_KEEP_DASHDASH); - if (!opts.new_branch && (opts.track != git_branch_track)) - die("git checkout: --track and --no-track require -b"); + /* --track without -b should DWIM */ + if (0 < opts.track && !opts.new_branch) { + const char *argv0 = argv[0]; + if (!argc || !strcmp(argv0, "--")) + die ("--track needs a branch name"); + if (!prefixcmp(argv0, "refs/")) + argv0 += 5; + if (!prefixcmp(argv0, "remotes/")) + argv0 += 8; + argv0 = strchr(argv0, '/'); + if (!argv0 || !argv0[1]) + die ("Missing branch name; try -b"); + opts.new_branch = argv0 + 1; + } + + if (opts.track == BRANCH_TRACK_UNSPECIFIED) + opts.track = git_branch_track; if (opts.force && opts.merge) die("git checkout: -f and -m are incompatible"); @@@ -580,6 -565,18 +580,18 @@@ no_reference return checkout_paths(source_tree, pathspec); } + if (opts.new_branch) { + struct strbuf buf; + strbuf_init(&buf, 0); + strbuf_addstr(&buf, "refs/heads/"); + strbuf_addstr(&buf, opts.new_branch); + if (!get_sha1(buf.buf, rev)) + die("git checkout: branch %s already exists", opts.new_branch); + if (check_ref_format(buf.buf)) + die("git checkout: we do not like '%s' as a branch name.", opts.new_branch); + strbuf_release(&buf); + } + if (new.name && !new.commit) { die("Cannot switch branch to a non-commit."); } diff --combined t/t7201-co.sh index 25181388f8,0679abd29d..62d73f934a --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@@ -337,38 -337,6 +337,38 @@@ test_expect_success test refs/heads/delete-me = "$(git symbolic-ref HEAD)" && test_must_fail git checkout --track -b track' +test_expect_success \ + 'checkout with --track fakes a sensible -b ' ' + git update-ref refs/remotes/origin/koala/bear renamer && + git update-ref refs/new/koala/bear renamer && + + git checkout --track origin/koala/bear && + test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && + test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" && + + git checkout master && git branch -D koala/bear && + + git checkout --track refs/remotes/origin/koala/bear && + test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && + test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" && + + git checkout master && git branch -D koala/bear && + + git checkout --track remotes/origin/koala/bear && + test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && + test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" && + + git checkout master && git branch -D koala/bear && + + git checkout --track refs/new/koala/bear && + test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && + test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" +' + +test_expect_success \ + 'checkout with --track, but without -b, fails with too short tracked name' ' + test_must_fail git checkout --track renamer' + test_expect_success 'checkout an unmerged path should fail' ' rm -f .git/index && O=$(echo original | git hash-object -w --stdin) && @@@ -391,4 -359,14 +391,14 @@@ test_cmp sample file ' + test_expect_success 'failing checkout -b should not break working tree' ' + git reset --hard master && + git symbolic-ref HEAD refs/heads/master && + test_must_fail git checkout -b renamer side^ && + test $(git symbolic-ref HEAD) = refs/heads/master && + git diff --exit-code && + git diff --cached --exit-code + + ' + test_done