t / t9902-completion.shon commit completion: respect 'git -C <path>' (80ac074)
   1#!/bin/sh
   2#
   3# Copyright (c) 2012 Felipe Contreras
   4#
   5
   6test_description='test bash completion'
   7
   8. ./lib-bash.sh
   9
  10complete ()
  11{
  12        # do nothing
  13        return 0
  14}
  15
  16# Be careful when updating this list:
  17#
  18# (1) The build tree may have build artifact from different branch, or
  19#     the user's $PATH may have a random executable that may begin
  20#     with "git-check" that are not part of the subcommands this build
  21#     will ship, e.g.  "check-ignore".  The tests for completion for
  22#     subcommand names tests how "check" is expanded; we limit the
  23#     possible candidates to "checkout" and "check-attr" to make sure
  24#     "check-attr", which is known by the filter function as a
  25#     subcommand to be thrown out, while excluding other random files
  26#     that happen to begin with "check" to avoid letting them get in
  27#     the way.
  28#
  29# (2) A test makes sure that common subcommands are included in the
  30#     completion for "git <TAB>", and a plumbing is excluded.  "add",
  31#     "filter-branch" and "ls-files" are listed for this.
  32
  33GIT_TESTING_COMMAND_COMPLETION='add checkout check-attr filter-branch ls-files'
  34
  35. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash"
  36
  37# We don't need this function to actually join words or do anything special.
  38# Also, it's cleaner to avoid touching bash's internal completion variables.
  39# So let's override it with a minimal version for testing purposes.
  40_get_comp_words_by_ref ()
  41{
  42        while [ $# -gt 0 ]; do
  43                case "$1" in
  44                cur)
  45                        cur=${_words[_cword]}
  46                        ;;
  47                prev)
  48                        prev=${_words[_cword-1]}
  49                        ;;
  50                words)
  51                        words=("${_words[@]}")
  52                        ;;
  53                cword)
  54                        cword=$_cword
  55                        ;;
  56                esac
  57                shift
  58        done
  59}
  60
  61print_comp ()
  62{
  63        local IFS=$'\n'
  64        echo "${COMPREPLY[*]}" > out
  65}
  66
  67run_completion ()
  68{
  69        local -a COMPREPLY _words
  70        local _cword
  71        _words=( $1 )
  72        test "${1: -1}" = ' ' && _words[${#_words[@]}+1]=''
  73        (( _cword = ${#_words[@]} - 1 ))
  74        __git_wrap__git_main && print_comp
  75}
  76
  77# Test high-level completion
  78# Arguments are:
  79# 1: typed text so far (cur)
  80# 2: expected completion
  81test_completion ()
  82{
  83        if test $# -gt 1
  84        then
  85                printf '%s\n' "$2" >expected
  86        else
  87                sed -e 's/Z$//' >expected
  88        fi &&
  89        run_completion "$1" &&
  90        test_cmp expected out
  91}
  92
  93# Test __gitcomp.
  94# The first argument is the typed text so far (cur); the rest are
  95# passed to __gitcomp.  Expected output comes is read from the
  96# standard input, like test_completion().
  97test_gitcomp ()
  98{
  99        local -a COMPREPLY &&
 100        sed -e 's/Z$//' >expected &&
 101        local cur="$1" &&
 102        shift &&
 103        __gitcomp "$@" &&
 104        print_comp &&
 105        test_cmp expected out
 106}
 107
 108# Test __gitcomp_nl
 109# Arguments are:
 110# 1: current word (cur)
 111# -: the rest are passed to __gitcomp_nl
 112test_gitcomp_nl ()
 113{
 114        local -a COMPREPLY &&
 115        sed -e 's/Z$//' >expected &&
 116        local cur="$1" &&
 117        shift &&
 118        __gitcomp_nl "$@" &&
 119        print_comp &&
 120        test_cmp expected out
 121}
 122
 123invalid_variable_name='${foo.bar}'
 124
 125actual="$TRASH_DIRECTORY/actual"
 126
 127if test_have_prereq MINGW
 128then
 129        ROOT="$(pwd -W)"
 130else
 131        ROOT="$(pwd)"
 132fi
 133
 134test_expect_success 'setup for __gitdir tests' '
 135        mkdir -p subdir/subsubdir &&
 136        git init otherrepo
 137'
 138
 139test_expect_success '__gitdir - from command line (through $__git_dir)' '
 140        echo "$ROOT/otherrepo/.git" >expected &&
 141        (
 142                __git_dir="$ROOT/otherrepo/.git" &&
 143                __gitdir >"$actual"
 144        ) &&
 145        test_cmp expected "$actual"
 146'
 147
 148test_expect_success '__gitdir - repo as argument' '
 149        echo "otherrepo/.git" >expected &&
 150        __gitdir "otherrepo" >"$actual" &&
 151        test_cmp expected "$actual"
 152'
 153
 154test_expect_success '__gitdir - remote as argument' '
 155        echo "remote" >expected &&
 156        __gitdir "remote" >"$actual" &&
 157        test_cmp expected "$actual"
 158'
 159
 160test_expect_success '__gitdir - .git directory in cwd' '
 161        echo ".git" >expected &&
 162        __gitdir >"$actual" &&
 163        test_cmp expected "$actual"
 164'
 165
 166test_expect_success '__gitdir - .git directory in parent' '
 167        echo "$ROOT/.git" >expected &&
 168        (
 169                cd subdir/subsubdir &&
 170                __gitdir >"$actual"
 171        ) &&
 172        test_cmp expected "$actual"
 173'
 174
 175test_expect_success '__gitdir - cwd is a .git directory' '
 176        echo "." >expected &&
 177        (
 178                cd .git &&
 179                __gitdir >"$actual"
 180        ) &&
 181        test_cmp expected "$actual"
 182'
 183
 184test_expect_success '__gitdir - parent is a .git directory' '
 185        echo "$ROOT/.git" >expected &&
 186        (
 187                cd .git/refs/heads &&
 188                __gitdir >"$actual"
 189        ) &&
 190        test_cmp expected "$actual"
 191'
 192
 193test_expect_success '__gitdir - $GIT_DIR set while .git directory in cwd' '
 194        echo "$ROOT/otherrepo/.git" >expected &&
 195        (
 196                GIT_DIR="$ROOT/otherrepo/.git" &&
 197                export GIT_DIR &&
 198                __gitdir >"$actual"
 199        ) &&
 200        test_cmp expected "$actual"
 201'
 202
 203test_expect_success '__gitdir - $GIT_DIR set while .git directory in parent' '
 204        echo "$ROOT/otherrepo/.git" >expected &&
 205        (
 206                GIT_DIR="$ROOT/otherrepo/.git" &&
 207                export GIT_DIR &&
 208                cd subdir &&
 209                __gitdir >"$actual"
 210        ) &&
 211        test_cmp expected "$actual"
 212'
 213
 214test_expect_success '__gitdir - from command line while "git -C"' '
 215        echo "$ROOT/.git" >expected &&
 216        (
 217                __git_dir="$ROOT/.git" &&
 218                __git_C_args=(-C otherrepo) &&
 219                __gitdir >"$actual"
 220        ) &&
 221        test_cmp expected "$actual"
 222'
 223
 224test_expect_success '__gitdir - relative dir from command line and "git -C"' '
 225        echo "$ROOT/otherrepo/.git" >expected &&
 226        (
 227                cd subdir &&
 228                __git_dir="otherrepo/.git" &&
 229                __git_C_args=(-C ..) &&
 230                __gitdir >"$actual"
 231        ) &&
 232        test_cmp expected "$actual"
 233'
 234
 235test_expect_success '__gitdir - $GIT_DIR set while "git -C"' '
 236        echo "$ROOT/.git" >expected &&
 237        (
 238                GIT_DIR="$ROOT/.git" &&
 239                export GIT_DIR &&
 240                __git_C_args=(-C otherrepo) &&
 241                __gitdir >"$actual"
 242        ) &&
 243        test_cmp expected "$actual"
 244'
 245
 246test_expect_success '__gitdir - relative dir in $GIT_DIR and "git -C"' '
 247        echo "$ROOT/otherrepo/.git" >expected &&
 248        (
 249                cd subdir &&
 250                GIT_DIR="otherrepo/.git" &&
 251                export GIT_DIR &&
 252                __git_C_args=(-C ..) &&
 253                __gitdir >"$actual"
 254        ) &&
 255        test_cmp expected "$actual"
 256'
 257
 258test_expect_success '__gitdir - "git -C" while .git directory in cwd' '
 259        echo "$ROOT/otherrepo/.git" >expected &&
 260        (
 261                __git_C_args=(-C otherrepo) &&
 262                __gitdir >"$actual"
 263        ) &&
 264        test_cmp expected "$actual"
 265'
 266
 267test_expect_success '__gitdir - "git -C" while cwd is a .git directory' '
 268        echo "$ROOT/otherrepo/.git" >expected &&
 269        (
 270                cd .git &&
 271                __git_C_args=(-C .. -C otherrepo) &&
 272                __gitdir >"$actual"
 273        ) &&
 274        test_cmp expected "$actual"
 275'
 276
 277test_expect_success '__gitdir - "git -C" while .git directory in parent' '
 278        echo "$ROOT/otherrepo/.git" >expected &&
 279        (
 280                cd subdir &&
 281                __git_C_args=(-C .. -C otherrepo) &&
 282                __gitdir >"$actual"
 283        ) &&
 284        test_cmp expected "$actual"
 285'
 286
 287test_expect_success '__gitdir - non-existing path in "git -C"' '
 288        (
 289                __git_C_args=(-C non-existing) &&
 290                test_must_fail __gitdir >"$actual"
 291        ) &&
 292        test_must_be_empty "$actual"
 293'
 294
 295test_expect_success '__gitdir - non-existing path in $__git_dir' '
 296        (
 297                __git_dir="non-existing" &&
 298                test_must_fail __gitdir >"$actual"
 299        ) &&
 300        test_must_be_empty "$actual"
 301'
 302
 303test_expect_success '__gitdir - non-existing $GIT_DIR' '
 304        (
 305                GIT_DIR="$ROOT/non-existing" &&
 306                export GIT_DIR &&
 307                test_must_fail __gitdir >"$actual"
 308        ) &&
 309        test_must_be_empty "$actual"
 310'
 311
 312test_expect_success '__gitdir - gitfile in cwd' '
 313        echo "$ROOT/otherrepo/.git" >expected &&
 314        echo "gitdir: $ROOT/otherrepo/.git" >subdir/.git &&
 315        test_when_finished "rm -f subdir/.git" &&
 316        (
 317                cd subdir &&
 318                __gitdir >"$actual"
 319        ) &&
 320        test_cmp expected "$actual"
 321'
 322
 323test_expect_success '__gitdir - gitfile in parent' '
 324        echo "$ROOT/otherrepo/.git" >expected &&
 325        echo "gitdir: $ROOT/otherrepo/.git" >subdir/.git &&
 326        test_when_finished "rm -f subdir/.git" &&
 327        (
 328                cd subdir/subsubdir &&
 329                __gitdir >"$actual"
 330        ) &&
 331        test_cmp expected "$actual"
 332'
 333
 334test_expect_success SYMLINKS '__gitdir - resulting path avoids symlinks' '
 335        echo "$ROOT/otherrepo/.git" >expected &&
 336        mkdir otherrepo/dir &&
 337        test_when_finished "rm -rf otherrepo/dir" &&
 338        ln -s otherrepo/dir link &&
 339        test_when_finished "rm -f link" &&
 340        (
 341                cd link &&
 342                __gitdir >"$actual"
 343        ) &&
 344        test_cmp expected "$actual"
 345'
 346
 347test_expect_success '__gitdir - not a git repository' '
 348        nongit test_must_fail __gitdir >"$actual" &&
 349        test_must_be_empty "$actual"
 350'
 351
 352test_expect_success '__gitcomp - trailing space - options' '
 353        test_gitcomp "--re" "--dry-run --reuse-message= --reedit-message=
 354                --reset-author" <<-EOF
 355        --reuse-message=Z
 356        --reedit-message=Z
 357        --reset-author Z
 358        EOF
 359'
 360
 361test_expect_success '__gitcomp - trailing space - config keys' '
 362        test_gitcomp "br" "branch. branch.autosetupmerge
 363                branch.autosetuprebase browser." <<-\EOF
 364        branch.Z
 365        branch.autosetupmerge Z
 366        branch.autosetuprebase Z
 367        browser.Z
 368        EOF
 369'
 370
 371test_expect_success '__gitcomp - option parameter' '
 372        test_gitcomp "--strategy=re" "octopus ours recursive resolve subtree" \
 373                "" "re" <<-\EOF
 374        recursive Z
 375        resolve Z
 376        EOF
 377'
 378
 379test_expect_success '__gitcomp - prefix' '
 380        test_gitcomp "branch.me" "remote merge mergeoptions rebase" \
 381                "branch.maint." "me" <<-\EOF
 382        branch.maint.merge Z
 383        branch.maint.mergeoptions Z
 384        EOF
 385'
 386
 387test_expect_success '__gitcomp - suffix' '
 388        test_gitcomp "branch.me" "master maint next pu" "branch." \
 389                "ma" "." <<-\EOF
 390        branch.master.Z
 391        branch.maint.Z
 392        EOF
 393'
 394
 395test_expect_success '__gitcomp - doesnt fail because of invalid variable name' '
 396        __gitcomp "$invalid_variable_name"
 397'
 398
 399read -r -d "" refs <<-\EOF
 400maint
 401master
 402next
 403pu
 404EOF
 405
 406test_expect_success '__gitcomp_nl - trailing space' '
 407        test_gitcomp_nl "m" "$refs" <<-EOF
 408        maint Z
 409        master Z
 410        EOF
 411'
 412
 413test_expect_success '__gitcomp_nl - prefix' '
 414        test_gitcomp_nl "--fixup=m" "$refs" "--fixup=" "m" <<-EOF
 415        --fixup=maint Z
 416        --fixup=master Z
 417        EOF
 418'
 419
 420test_expect_success '__gitcomp_nl - suffix' '
 421        test_gitcomp_nl "branch.ma" "$refs" "branch." "ma" "." <<-\EOF
 422        branch.maint.Z
 423        branch.master.Z
 424        EOF
 425'
 426
 427test_expect_success '__gitcomp_nl - no suffix' '
 428        test_gitcomp_nl "ma" "$refs" "" "ma" "" <<-\EOF
 429        maintZ
 430        masterZ
 431        EOF
 432'
 433
 434test_expect_success '__gitcomp_nl - doesnt fail because of invalid variable name' '
 435        __gitcomp_nl "$invalid_variable_name"
 436'
 437
 438test_expect_success '__git_remotes - list remotes from $GIT_DIR/remotes and from config file' '
 439        cat >expect <<-EOF &&
 440        remote_from_file_1
 441        remote_from_file_2
 442        remote_in_config_1
 443        remote_in_config_2
 444        EOF
 445        test_when_finished "rm -rf .git/remotes" &&
 446        mkdir -p .git/remotes &&
 447        >.git/remotes/remote_from_file_1 &&
 448        >.git/remotes/remote_from_file_2 &&
 449        test_when_finished "git remote remove remote_in_config_1" &&
 450        git remote add remote_in_config_1 git://remote_1 &&
 451        test_when_finished "git remote remove remote_in_config_2" &&
 452        git remote add remote_in_config_2 git://remote_2 &&
 453        __git_remotes >actual &&
 454        test_cmp expect actual
 455'
 456
 457test_expect_success '__git_is_configured_remote' '
 458        test_when_finished "git remote remove remote_1" &&
 459        git remote add remote_1 git://remote_1 &&
 460        test_when_finished "git remote remove remote_2" &&
 461        git remote add remote_2 git://remote_2 &&
 462        verbose __git_is_configured_remote remote_2 &&
 463        test_must_fail __git_is_configured_remote non-existent
 464'
 465
 466test_expect_success 'setup for ref completion' '
 467        git commit --allow-empty -m initial &&
 468        git branch matching-branch &&
 469        git tag matching-tag &&
 470        (
 471                cd otherrepo &&
 472                git commit --allow-empty -m initial &&
 473                git branch -m master master-in-other &&
 474                git branch branch-in-other &&
 475                git tag tag-in-other
 476        ) &&
 477        git remote add other "$ROOT/otherrepo/.git" &&
 478        git fetch --no-tags other &&
 479        rm -f .git/FETCH_HEAD &&
 480        git init thirdrepo
 481'
 482
 483test_expect_success '__git_refs - simple' '
 484        cat >expected <<-EOF &&
 485        HEAD
 486        master
 487        matching-branch
 488        other/branch-in-other
 489        other/master-in-other
 490        matching-tag
 491        EOF
 492        (
 493                cur= &&
 494                __git_refs >"$actual"
 495        ) &&
 496        test_cmp expected "$actual"
 497'
 498
 499test_expect_success '__git_refs - full refs' '
 500        cat >expected <<-EOF &&
 501        refs/heads/master
 502        refs/heads/matching-branch
 503        EOF
 504        (
 505                cur=refs/heads/ &&
 506                __git_refs >"$actual"
 507        ) &&
 508        test_cmp expected "$actual"
 509'
 510
 511test_expect_success '__git_refs - repo given on the command line' '
 512        cat >expected <<-EOF &&
 513        HEAD
 514        branch-in-other
 515        master-in-other
 516        tag-in-other
 517        EOF
 518        (
 519                __git_dir="$ROOT/otherrepo/.git" &&
 520                cur= &&
 521                __git_refs >"$actual"
 522        ) &&
 523        test_cmp expected "$actual"
 524'
 525
 526test_expect_success '__git_refs - remote on local file system' '
 527        cat >expected <<-EOF &&
 528        HEAD
 529        branch-in-other
 530        master-in-other
 531        tag-in-other
 532        EOF
 533        (
 534                cur= &&
 535                __git_refs otherrepo >"$actual"
 536        ) &&
 537        test_cmp expected "$actual"
 538'
 539
 540test_expect_success '__git_refs - remote on local file system - full refs' '
 541        cat >expected <<-EOF &&
 542        refs/heads/branch-in-other
 543        refs/heads/master-in-other
 544        refs/tags/tag-in-other
 545        EOF
 546        (
 547                cur=refs/ &&
 548                __git_refs otherrepo >"$actual"
 549        ) &&
 550        test_cmp expected "$actual"
 551'
 552
 553test_expect_success '__git_refs - configured remote' '
 554        cat >expected <<-EOF &&
 555        HEAD
 556        branch-in-other
 557        master-in-other
 558        EOF
 559        (
 560                cur= &&
 561                __git_refs other >"$actual"
 562        ) &&
 563        test_cmp expected "$actual"
 564'
 565
 566test_expect_success '__git_refs - configured remote - full refs' '
 567        cat >expected <<-EOF &&
 568        refs/heads/branch-in-other
 569        refs/heads/master-in-other
 570        refs/tags/tag-in-other
 571        EOF
 572        (
 573                cur=refs/ &&
 574                __git_refs other >"$actual"
 575        ) &&
 576        test_cmp expected "$actual"
 577'
 578
 579test_expect_success '__git_refs - configured remote - repo given on the command line' '
 580        cat >expected <<-EOF &&
 581        HEAD
 582        branch-in-other
 583        master-in-other
 584        EOF
 585        (
 586                cd thirdrepo &&
 587                __git_dir="$ROOT/.git" &&
 588                cur= &&
 589                __git_refs other >"$actual"
 590        ) &&
 591        test_cmp expected "$actual"
 592'
 593
 594test_expect_success '__git_refs - configured remote - full refs - repo given on the command line' '
 595        cat >expected <<-EOF &&
 596        refs/heads/branch-in-other
 597        refs/heads/master-in-other
 598        refs/tags/tag-in-other
 599        EOF
 600        (
 601                cd thirdrepo &&
 602                __git_dir="$ROOT/.git" &&
 603                cur=refs/ &&
 604                __git_refs other >"$actual"
 605        ) &&
 606        test_cmp expected "$actual"
 607'
 608
 609test_expect_success '__git_refs - configured remote - remote name matches a directory' '
 610        cat >expected <<-EOF &&
 611        HEAD
 612        branch-in-other
 613        master-in-other
 614        EOF
 615        mkdir other &&
 616        test_when_finished "rm -rf other" &&
 617        (
 618                cur= &&
 619                __git_refs other >"$actual"
 620        ) &&
 621        test_cmp expected "$actual"
 622'
 623
 624test_expect_success '__git_refs - URL remote' '
 625        cat >expected <<-EOF &&
 626        HEAD
 627        branch-in-other
 628        master-in-other
 629        tag-in-other
 630        EOF
 631        (
 632                cur= &&
 633                __git_refs "file://$ROOT/otherrepo/.git" >"$actual"
 634        ) &&
 635        test_cmp expected "$actual"
 636'
 637
 638test_expect_success '__git_refs - URL remote - full refs' '
 639        cat >expected <<-EOF &&
 640        refs/heads/branch-in-other
 641        refs/heads/master-in-other
 642        refs/tags/tag-in-other
 643        EOF
 644        (
 645                cur=refs/ &&
 646                __git_refs "file://$ROOT/otherrepo/.git" >"$actual"
 647        ) &&
 648        test_cmp expected "$actual"
 649'
 650
 651test_expect_success '__git_refs - non-existing remote' '
 652        (
 653                cur= &&
 654                __git_refs non-existing >"$actual"
 655        ) &&
 656        test_must_be_empty "$actual"
 657'
 658
 659test_expect_success '__git_refs - non-existing remote - full refs' '
 660        (
 661                cur=refs/ &&
 662                __git_refs non-existing >"$actual"
 663        ) &&
 664        test_must_be_empty "$actual"
 665'
 666
 667test_expect_success '__git_refs - non-existing URL remote' '
 668        (
 669                cur= &&
 670                __git_refs "file://$ROOT/non-existing" >"$actual"
 671        ) &&
 672        test_must_be_empty "$actual"
 673'
 674
 675test_expect_success '__git_refs - non-existing URL remote - full refs' '
 676        (
 677                cur=refs/ &&
 678                __git_refs "file://$ROOT/non-existing" >"$actual"
 679        ) &&
 680        test_must_be_empty "$actual"
 681'
 682
 683test_expect_success '__git_refs - not in a git repository' '
 684        (
 685                GIT_CEILING_DIRECTORIES="$ROOT" &&
 686                export GIT_CEILING_DIRECTORIES &&
 687                cd subdir &&
 688                cur= &&
 689                __git_refs >"$actual"
 690        ) &&
 691        test_must_be_empty "$actual"
 692'
 693
 694test_expect_success '__git_refs - unique remote branches for git checkout DWIMery' '
 695        cat >expected <<-EOF &&
 696        HEAD
 697        master
 698        matching-branch
 699        other/ambiguous
 700        other/branch-in-other
 701        other/master-in-other
 702        remote/ambiguous
 703        remote/branch-in-remote
 704        matching-tag
 705        branch-in-other
 706        branch-in-remote
 707        master-in-other
 708        EOF
 709        for remote_ref in refs/remotes/other/ambiguous \
 710                refs/remotes/remote/ambiguous \
 711                refs/remotes/remote/branch-in-remote
 712        do
 713                git update-ref $remote_ref master &&
 714                test_when_finished "git update-ref -d $remote_ref"
 715        done &&
 716        (
 717                cur= &&
 718                __git_refs "" 1 >"$actual"
 719        ) &&
 720        test_cmp expected "$actual"
 721'
 722
 723test_expect_success 'teardown after ref completion' '
 724        git branch -d matching-branch &&
 725        git tag -d matching-tag &&
 726        git remote remove other
 727'
 728
 729test_expect_success '__git_get_config_variables' '
 730        cat >expect <<-EOF &&
 731        name-1
 732        name-2
 733        EOF
 734        test_config interesting.name-1 good &&
 735        test_config interesting.name-2 good &&
 736        test_config subsection.interesting.name-3 bad &&
 737        __git_get_config_variables interesting >actual &&
 738        test_cmp expect actual
 739'
 740
 741test_expect_success '__git_pretty_aliases' '
 742        cat >expect <<-EOF &&
 743        author
 744        hash
 745        EOF
 746        test_config pretty.author "%an %ae" &&
 747        test_config pretty.hash %H &&
 748        __git_pretty_aliases >actual &&
 749        test_cmp expect actual
 750'
 751
 752test_expect_success '__git_aliases' '
 753        cat >expect <<-EOF &&
 754        ci
 755        co
 756        EOF
 757        test_config alias.ci commit &&
 758        test_config alias.co checkout &&
 759        __git_aliases >actual &&
 760        test_cmp expect actual
 761'
 762
 763test_expect_success 'basic' '
 764        run_completion "git " &&
 765        # built-in
 766        grep -q "^add \$" out &&
 767        # script
 768        grep -q "^filter-branch \$" out &&
 769        # plumbing
 770        ! grep -q "^ls-files \$" out &&
 771
 772        run_completion "git f" &&
 773        ! grep -q -v "^f" out
 774'
 775
 776test_expect_success 'double dash "git" itself' '
 777        test_completion "git --" <<-\EOF
 778        --paginate Z
 779        --no-pager Z
 780        --git-dir=
 781        --bare Z
 782        --version Z
 783        --exec-path Z
 784        --exec-path=
 785        --html-path Z
 786        --man-path Z
 787        --info-path Z
 788        --work-tree=
 789        --namespace=
 790        --no-replace-objects Z
 791        --help Z
 792        EOF
 793'
 794
 795test_expect_success 'double dash "git checkout"' '
 796        test_completion "git checkout --" <<-\EOF
 797        --quiet Z
 798        --ours Z
 799        --theirs Z
 800        --track Z
 801        --no-track Z
 802        --merge Z
 803        --conflict=
 804        --orphan Z
 805        --patch Z
 806        EOF
 807'
 808
 809test_expect_success 'general options' '
 810        test_completion "git --ver" "--version " &&
 811        test_completion "git --hel" "--help " &&
 812        test_completion "git --exe" <<-\EOF &&
 813        --exec-path Z
 814        --exec-path=
 815        EOF
 816        test_completion "git --htm" "--html-path " &&
 817        test_completion "git --pag" "--paginate " &&
 818        test_completion "git --no-p" "--no-pager " &&
 819        test_completion "git --git" "--git-dir=" &&
 820        test_completion "git --wor" "--work-tree=" &&
 821        test_completion "git --nam" "--namespace=" &&
 822        test_completion "git --bar" "--bare " &&
 823        test_completion "git --inf" "--info-path " &&
 824        test_completion "git --no-r" "--no-replace-objects "
 825'
 826
 827test_expect_success 'general options plus command' '
 828        test_completion "git --version check" "checkout " &&
 829        test_completion "git --paginate check" "checkout " &&
 830        test_completion "git --git-dir=foo check" "checkout " &&
 831        test_completion "git --bare check" "checkout " &&
 832        test_completion "git --exec-path=foo check" "checkout " &&
 833        test_completion "git --html-path check" "checkout " &&
 834        test_completion "git --no-pager check" "checkout " &&
 835        test_completion "git --work-tree=foo check" "checkout " &&
 836        test_completion "git --namespace=foo check" "checkout " &&
 837        test_completion "git --paginate check" "checkout " &&
 838        test_completion "git --info-path check" "checkout " &&
 839        test_completion "git --no-replace-objects check" "checkout " &&
 840        test_completion "git --git-dir some/path check" "checkout " &&
 841        test_completion "git -c conf.var=value check" "checkout " &&
 842        test_completion "git -C some/path check" "checkout " &&
 843        test_completion "git --work-tree some/path check" "checkout " &&
 844        test_completion "git --namespace name/space check" "checkout "
 845'
 846
 847test_expect_success 'git --help completion' '
 848        test_completion "git --help ad" "add " &&
 849        test_completion "git --help core" "core-tutorial "
 850'
 851
 852test_expect_success 'setup for integration tests' '
 853        echo content >file1 &&
 854        echo more >file2 &&
 855        git add file1 file2 &&
 856        git commit -m one &&
 857        git branch mybranch &&
 858        git tag mytag
 859'
 860
 861test_expect_success 'checkout completes ref names' '
 862        test_completion "git checkout m" <<-\EOF
 863        master Z
 864        mybranch Z
 865        mytag Z
 866        EOF
 867'
 868
 869test_expect_success 'git -C <path> checkout uses the right repo' '
 870        test_completion "git -C subdir -C subsubdir -C .. -C ../otherrepo checkout b" <<-\EOF
 871        branch-in-other Z
 872        EOF
 873'
 874
 875test_expect_success 'show completes all refs' '
 876        test_completion "git show m" <<-\EOF
 877        master Z
 878        mybranch Z
 879        mytag Z
 880        EOF
 881'
 882
 883test_expect_success '<ref>: completes paths' '
 884        test_completion "git show mytag:f" <<-\EOF
 885        file1 Z
 886        file2 Z
 887        EOF
 888'
 889
 890test_expect_success 'complete tree filename with spaces' '
 891        echo content >"name with spaces" &&
 892        git add "name with spaces" &&
 893        git commit -m spaces &&
 894        test_completion "git show HEAD:nam" <<-\EOF
 895        name with spaces Z
 896        EOF
 897'
 898
 899test_expect_success 'complete tree filename with metacharacters' '
 900        echo content >"name with \${meta}" &&
 901        git add "name with \${meta}" &&
 902        git commit -m meta &&
 903        test_completion "git show HEAD:nam" <<-\EOF
 904        name with ${meta} Z
 905        name with spaces Z
 906        EOF
 907'
 908
 909test_expect_success 'send-email' '
 910        test_completion "git send-email --cov" "--cover-letter " &&
 911        test_completion "git send-email ma" "master "
 912'
 913
 914test_expect_success 'complete files' '
 915        git init tmp && cd tmp &&
 916        test_when_finished "cd .. && rm -rf tmp" &&
 917
 918        echo "expected" > .gitignore &&
 919        echo "out" >> .gitignore &&
 920
 921        git add .gitignore &&
 922        test_completion "git commit " ".gitignore" &&
 923
 924        git commit -m ignore &&
 925
 926        touch new &&
 927        test_completion "git add " "new" &&
 928
 929        git add new &&
 930        git commit -a -m new &&
 931        test_completion "git add " "" &&
 932
 933        git mv new modified &&
 934        echo modify > modified &&
 935        test_completion "git add " "modified" &&
 936
 937        touch untracked &&
 938
 939        : TODO .gitignore should not be here &&
 940        test_completion "git rm " <<-\EOF &&
 941        .gitignore
 942        modified
 943        EOF
 944
 945        test_completion "git clean " "untracked" &&
 946
 947        : TODO .gitignore should not be here &&
 948        test_completion "git mv " <<-\EOF &&
 949        .gitignore
 950        modified
 951        EOF
 952
 953        mkdir dir &&
 954        touch dir/file-in-dir &&
 955        git add dir/file-in-dir &&
 956        git commit -m dir &&
 957
 958        mkdir untracked-dir &&
 959
 960        : TODO .gitignore should not be here &&
 961        test_completion "git mv modified " <<-\EOF &&
 962        .gitignore
 963        dir
 964        modified
 965        untracked
 966        untracked-dir
 967        EOF
 968
 969        test_completion "git commit " "modified" &&
 970
 971        : TODO .gitignore should not be here &&
 972        test_completion "git ls-files " <<-\EOF &&
 973        .gitignore
 974        dir
 975        modified
 976        EOF
 977
 978        touch momified &&
 979        test_completion "git add mom" "momified"
 980'
 981
 982test_expect_success "completion uses <cmd> completion for alias: !sh -c 'git <cmd> ...'" '
 983        test_config alias.co "!sh -c '"'"'git checkout ...'"'"'" &&
 984        test_completion "git co m" <<-\EOF
 985        master Z
 986        mybranch Z
 987        mytag Z
 988        EOF
 989'
 990
 991test_expect_success 'completion uses <cmd> completion for alias: !f () { VAR=val git <cmd> ... }' '
 992        test_config alias.co "!f () { VAR=val git checkout ... ; } f" &&
 993        test_completion "git co m" <<-\EOF
 994        master Z
 995        mybranch Z
 996        mytag Z
 997        EOF
 998'
 999
1000test_expect_success 'completion used <cmd> completion for alias: !f() { : git <cmd> ; ... }' '
1001        test_config alias.co "!f() { : git checkout ; if ... } f" &&
1002        test_completion "git co m" <<-\EOF
1003        master Z
1004        mybranch Z
1005        mytag Z
1006        EOF
1007'
1008
1009test_expect_failure 'complete with tilde expansion' '
1010        git init tmp && cd tmp &&
1011        test_when_finished "cd .. && rm -rf tmp" &&
1012
1013        touch ~/tmp/file &&
1014
1015        test_completion "git add ~/tmp/" "~/tmp/file"
1016'
1017
1018test_done