ref-filter: make remote_ref_atom_parser() use refname_atom_parser_internal()
[gitweb.git] / t / t2020-checkout-detach.sh
index 00421453ba26327b929fa7b5133a3072fce2bb03..fbb4ee9bb42dbcfdfcdb79511523a8fa2ac8b5d9 100755 (executable)
@@ -11,6 +11,16 @@ check_not_detached () {
        git symbolic-ref -q HEAD >/dev/null
 }
 
+PREV_HEAD_DESC='Previous HEAD position was'
+check_orphan_warning() {
+       test_i18ngrep "you are leaving $2 behind" "$1" &&
+       test_i18ngrep ! "$PREV_HEAD_DESC" "$1"
+}
+check_no_orphan_warning() {
+       test_i18ngrep ! "you are leaving .* commit.*behind" "$1" &&
+       test_i18ngrep "$PREV_HEAD_DESC" "$1"
+}
+
 reset () {
        git checkout master &&
        check_not_detached
@@ -19,6 +29,8 @@ reset () {
 test_expect_success 'setup' '
        test_commit one &&
        test_commit two &&
+       test_commit three && git tag -d three &&
+       test_commit four && git tag -d four &&
        git branch branch &&
        git tag tag
 '
@@ -92,4 +104,86 @@ test_expect_success 'checkout --detach moves HEAD' '
        git diff --exit-code two
 '
 
+test_expect_success 'checkout warns on orphan commits' '
+       reset &&
+       git checkout --detach two &&
+       echo content >orphan &&
+       git add orphan &&
+       git commit -a -m orphan1 &&
+       echo new content >orphan &&
+       git commit -a -m orphan2 &&
+       orphan2=$(git rev-parse HEAD) &&
+       git checkout master 2>stderr
+'
+
+test_expect_success 'checkout warns on orphan commits: output' '
+       check_orphan_warning stderr "2 commits"
+'
+
+test_expect_success 'checkout warns orphaning 1 of 2 commits' '
+       git checkout "$orphan2" &&
+       git checkout HEAD^ 2>stderr
+'
+
+test_expect_success 'checkout warns orphaning 1 of 2 commits: output' '
+       check_orphan_warning stderr "1 commit"
+'
+
+test_expect_success 'checkout does not warn leaving ref tip' '
+       reset &&
+       git checkout --detach two &&
+       git checkout master 2>stderr
+'
+
+test_expect_success 'checkout does not warn leaving ref tip' '
+       check_no_orphan_warning stderr
+'
+
+test_expect_success 'checkout does not warn leaving reachable commit' '
+       reset &&
+       git checkout --detach HEAD^ &&
+       git checkout master 2>stderr
+'
+
+test_expect_success 'checkout does not warn leaving reachable commit' '
+       check_no_orphan_warning stderr
+'
+
+cat >expect <<'EOF'
+Your branch is behind 'master' by 1 commit, and can be fast-forwarded.
+  (use "git pull" to update your local branch)
+EOF
+test_expect_success 'tracking count is accurate after orphan check' '
+       reset &&
+       git branch child master^ &&
+       git config branch.child.remote . &&
+       git config branch.child.merge refs/heads/master &&
+       git checkout child^ &&
+       git checkout child >stdout &&
+       test_i18ncmp expect stdout
+'
+
+test_expect_success 'no advice given for explicit detached head state' '
+       # baseline
+       test_config advice.detachedHead true &&
+       git checkout child && git checkout HEAD^0 >expect.advice 2>&1 &&
+       test_config advice.detachedHead false &&
+       git checkout child && git checkout HEAD^0 >expect.no-advice 2>&1 &&
+       test_unconfig advice.detachedHead &&
+       # without configuration, the advice.* variables default to true
+       git checkout child && git checkout HEAD^0 >actual 2>&1 &&
+       test_cmp expect.advice actual &&
+
+       # with explicit --detach
+       # no configuration
+       test_unconfig advice.detachedHead &&
+       git checkout child && git checkout --detach HEAD^0 >actual 2>&1 &&
+       test_cmp expect.no-advice actual &&
+
+       # explicitly decline advice
+       test_config advice.detachedHead false &&
+       git checkout child && git checkout --detach HEAD^0 >actual 2>&1 &&
+       test_cmp expect.no-advice actual
+'
+
 test_done