1816ed2e059d14a4cde86f94951bbe5b40c904df
   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        (
 151                __gitdir "otherrepo" >"$actual"
 152        ) &&
 153        test_cmp expected "$actual"
 154'
 155
 156test_expect_success '__gitdir - remote as argument' '
 157        echo "remote" >expected &&
 158        (
 159                __gitdir "remote" >"$actual"
 160        ) &&
 161        test_cmp expected "$actual"
 162'
 163
 164test_expect_success '__gitdir - .git directory in cwd' '
 165        echo ".git" >expected &&
 166        (
 167                __gitdir >"$actual"
 168        ) &&
 169        test_cmp expected "$actual"
 170'
 171
 172test_expect_success '__gitdir - .git directory in parent' '
 173        echo "$ROOT/.git" >expected &&
 174        (
 175                cd subdir/subsubdir &&
 176                __gitdir >"$actual"
 177        ) &&
 178        test_cmp expected "$actual"
 179'
 180
 181test_expect_success '__gitdir - cwd is a .git directory' '
 182        echo "." >expected &&
 183        (
 184                cd .git &&
 185                __gitdir >"$actual"
 186        ) &&
 187        test_cmp expected "$actual"
 188'
 189
 190test_expect_success '__gitdir - parent is a .git directory' '
 191        echo "$ROOT/.git" >expected &&
 192        (
 193                cd .git/refs/heads &&
 194                __gitdir >"$actual"
 195        ) &&
 196        test_cmp expected "$actual"
 197'
 198
 199test_expect_success '__gitdir - $GIT_DIR set while .git directory in cwd' '
 200        echo "$ROOT/otherrepo/.git" >expected &&
 201        (
 202                GIT_DIR="$ROOT/otherrepo/.git" &&
 203                export GIT_DIR &&
 204                __gitdir >"$actual"
 205        ) &&
 206        test_cmp expected "$actual"
 207'
 208
 209test_expect_success '__gitdir - $GIT_DIR set while .git directory in parent' '
 210        echo "$ROOT/otherrepo/.git" >expected &&
 211        (
 212                GIT_DIR="$ROOT/otherrepo/.git" &&
 213                export GIT_DIR &&
 214                cd subdir &&
 215                __gitdir >"$actual"
 216        ) &&
 217        test_cmp expected "$actual"
 218'
 219
 220test_expect_success '__gitdir - from command line while "git -C"' '
 221        echo "$ROOT/.git" >expected &&
 222        (
 223                __git_dir="$ROOT/.git" &&
 224                __git_C_args=(-C otherrepo) &&
 225                __gitdir >"$actual"
 226        ) &&
 227        test_cmp expected "$actual"
 228'
 229
 230test_expect_success '__gitdir - relative dir from command line and "git -C"' '
 231        echo "$ROOT/otherrepo/.git" >expected &&
 232        (
 233                cd subdir &&
 234                __git_dir="otherrepo/.git" &&
 235                __git_C_args=(-C ..) &&
 236                __gitdir >"$actual"
 237        ) &&
 238        test_cmp expected "$actual"
 239'
 240
 241test_expect_success '__gitdir - $GIT_DIR set while "git -C"' '
 242        echo "$ROOT/.git" >expected &&
 243        (
 244                GIT_DIR="$ROOT/.git" &&
 245                export GIT_DIR &&
 246                __git_C_args=(-C otherrepo) &&
 247                __gitdir >"$actual"
 248        ) &&
 249        test_cmp expected "$actual"
 250'
 251
 252test_expect_success '__gitdir - relative dir in $GIT_DIR and "git -C"' '
 253        echo "$ROOT/otherrepo/.git" >expected &&
 254        (
 255                cd subdir &&
 256                GIT_DIR="otherrepo/.git" &&
 257                export GIT_DIR &&
 258                __git_C_args=(-C ..) &&
 259                __gitdir >"$actual"
 260        ) &&
 261        test_cmp expected "$actual"
 262'
 263
 264test_expect_success '__gitdir - "git -C" while .git directory in cwd' '
 265        echo "$ROOT/otherrepo/.git" >expected &&
 266        (
 267                __git_C_args=(-C otherrepo) &&
 268                __gitdir >"$actual"
 269        ) &&
 270        test_cmp expected "$actual"
 271'
 272
 273test_expect_success '__gitdir - "git -C" while cwd is a .git directory' '
 274        echo "$ROOT/otherrepo/.git" >expected &&
 275        (
 276                cd .git &&
 277                __git_C_args=(-C .. -C otherrepo) &&
 278                __gitdir >"$actual"
 279        ) &&
 280        test_cmp expected "$actual"
 281'
 282
 283test_expect_success '__gitdir - "git -C" while .git directory in parent' '
 284        echo "$ROOT/otherrepo/.git" >expected &&
 285        (
 286                cd subdir &&
 287                __git_C_args=(-C .. -C otherrepo) &&
 288                __gitdir >"$actual"
 289        ) &&
 290        test_cmp expected "$actual"
 291'
 292
 293test_expect_success '__gitdir - non-existing path in "git -C"' '
 294        (
 295                __git_C_args=(-C non-existing) &&
 296                test_must_fail __gitdir >"$actual"
 297        ) &&
 298        test_must_be_empty "$actual"
 299'
 300
 301test_expect_success '__gitdir - non-existing path in $__git_dir' '
 302        (
 303                __git_dir="non-existing" &&
 304                test_must_fail __gitdir >"$actual"
 305        ) &&
 306        test_must_be_empty "$actual"
 307'
 308
 309test_expect_success '__gitdir - non-existing $GIT_DIR' '
 310        (
 311                GIT_DIR="$ROOT/non-existing" &&
 312                export GIT_DIR &&
 313                test_must_fail __gitdir >"$actual"
 314        ) &&
 315        test_must_be_empty "$actual"
 316'
 317
 318test_expect_success '__gitdir - gitfile in cwd' '
 319        echo "$ROOT/otherrepo/.git" >expected &&
 320        echo "gitdir: $ROOT/otherrepo/.git" >subdir/.git &&
 321        test_when_finished "rm -f subdir/.git" &&
 322        (
 323                cd subdir &&
 324                __gitdir >"$actual"
 325        ) &&
 326        test_cmp expected "$actual"
 327'
 328
 329test_expect_success '__gitdir - gitfile in parent' '
 330        echo "$ROOT/otherrepo/.git" >expected &&
 331        echo "gitdir: $ROOT/otherrepo/.git" >subdir/.git &&
 332        test_when_finished "rm -f subdir/.git" &&
 333        (
 334                cd subdir/subsubdir &&
 335                __gitdir >"$actual"
 336        ) &&
 337        test_cmp expected "$actual"
 338'
 339
 340test_expect_success SYMLINKS '__gitdir - resulting path avoids symlinks' '
 341        echo "$ROOT/otherrepo/.git" >expected &&
 342        mkdir otherrepo/dir &&
 343        test_when_finished "rm -rf otherrepo/dir" &&
 344        ln -s otherrepo/dir link &&
 345        test_when_finished "rm -f link" &&
 346        (
 347                cd link &&
 348                __gitdir >"$actual"
 349        ) &&
 350        test_cmp expected "$actual"
 351'
 352
 353test_expect_success '__gitdir - not a git repository' '
 354        nongit test_must_fail __gitdir >"$actual" &&
 355        test_must_be_empty "$actual"
 356'
 357
 358test_expect_success '__gitcomp - trailing space - options' '
 359        test_gitcomp "--re" "--dry-run --reuse-message= --reedit-message=
 360                --reset-author" <<-EOF
 361        --reuse-message=Z
 362        --reedit-message=Z
 363        --reset-author Z
 364        EOF
 365'
 366
 367test_expect_success '__gitcomp - trailing space - config keys' '
 368        test_gitcomp "br" "branch. branch.autosetupmerge
 369                branch.autosetuprebase browser." <<-\EOF
 370        branch.Z
 371        branch.autosetupmerge Z
 372        branch.autosetuprebase Z
 373        browser.Z
 374        EOF
 375'
 376
 377test_expect_success '__gitcomp - option parameter' '
 378        test_gitcomp "--strategy=re" "octopus ours recursive resolve subtree" \
 379                "" "re" <<-\EOF
 380        recursive Z
 381        resolve Z
 382        EOF
 383'
 384
 385test_expect_success '__gitcomp - prefix' '
 386        test_gitcomp "branch.me" "remote merge mergeoptions rebase" \
 387                "branch.maint." "me" <<-\EOF
 388        branch.maint.merge Z
 389        branch.maint.mergeoptions Z
 390        EOF
 391'
 392
 393test_expect_success '__gitcomp - suffix' '
 394        test_gitcomp "branch.me" "master maint next pu" "branch." \
 395                "ma" "." <<-\EOF
 396        branch.master.Z
 397        branch.maint.Z
 398        EOF
 399'
 400
 401test_expect_success '__gitcomp - doesnt fail because of invalid variable name' '
 402        __gitcomp "$invalid_variable_name"
 403'
 404
 405read -r -d "" refs <<-\EOF
 406maint
 407master
 408next
 409pu
 410EOF
 411
 412test_expect_success '__gitcomp_nl - trailing space' '
 413        test_gitcomp_nl "m" "$refs" <<-EOF
 414        maint Z
 415        master Z
 416        EOF
 417'
 418
 419test_expect_success '__gitcomp_nl - prefix' '
 420        test_gitcomp_nl "--fixup=m" "$refs" "--fixup=" "m" <<-EOF
 421        --fixup=maint Z
 422        --fixup=master Z
 423        EOF
 424'
 425
 426test_expect_success '__gitcomp_nl - suffix' '
 427        test_gitcomp_nl "branch.ma" "$refs" "branch." "ma" "." <<-\EOF
 428        branch.maint.Z
 429        branch.master.Z
 430        EOF
 431'
 432
 433test_expect_success '__gitcomp_nl - no suffix' '
 434        test_gitcomp_nl "ma" "$refs" "" "ma" "" <<-\EOF
 435        maintZ
 436        masterZ
 437        EOF
 438'
 439
 440test_expect_success '__gitcomp_nl - doesnt fail because of invalid variable name' '
 441        __gitcomp_nl "$invalid_variable_name"
 442'
 443
 444test_expect_success '__git_remotes - list remotes from $GIT_DIR/remotes and from config file' '
 445        cat >expect <<-EOF &&
 446        remote_from_file_1
 447        remote_from_file_2
 448        remote_in_config_1
 449        remote_in_config_2
 450        EOF
 451        test_when_finished "rm -rf .git/remotes" &&
 452        mkdir -p .git/remotes &&
 453        >.git/remotes/remote_from_file_1 &&
 454        >.git/remotes/remote_from_file_2 &&
 455        test_when_finished "git remote remove remote_in_config_1" &&
 456        git remote add remote_in_config_1 git://remote_1 &&
 457        test_when_finished "git remote remove remote_in_config_2" &&
 458        git remote add remote_in_config_2 git://remote_2 &&
 459        (
 460                __git_remotes >actual
 461        ) &&
 462        test_cmp expect actual
 463'
 464
 465test_expect_success '__git_is_configured_remote' '
 466        test_when_finished "git remote remove remote_1" &&
 467        git remote add remote_1 git://remote_1 &&
 468        test_when_finished "git remote remove remote_2" &&
 469        git remote add remote_2 git://remote_2 &&
 470        (
 471                verbose __git_is_configured_remote remote_2 &&
 472                test_must_fail __git_is_configured_remote non-existent
 473        )
 474'
 475
 476test_expect_success 'setup for ref completion' '
 477        git commit --allow-empty -m initial &&
 478        git branch matching-branch &&
 479        git tag matching-tag &&
 480        (
 481                cd otherrepo &&
 482                git commit --allow-empty -m initial &&
 483                git branch -m master master-in-other &&
 484                git branch branch-in-other &&
 485                git tag tag-in-other
 486        ) &&
 487        git remote add other "$ROOT/otherrepo/.git" &&
 488        git fetch --no-tags other &&
 489        rm -f .git/FETCH_HEAD &&
 490        git init thirdrepo
 491'
 492
 493test_expect_success '__git_refs - simple' '
 494        cat >expected <<-EOF &&
 495        HEAD
 496        master
 497        matching-branch
 498        other/branch-in-other
 499        other/master-in-other
 500        matching-tag
 501        EOF
 502        (
 503                cur= &&
 504                __git_refs >"$actual"
 505        ) &&
 506        test_cmp expected "$actual"
 507'
 508
 509test_expect_success '__git_refs - full refs' '
 510        cat >expected <<-EOF &&
 511        refs/heads/master
 512        refs/heads/matching-branch
 513        EOF
 514        (
 515                cur=refs/heads/ &&
 516                __git_refs >"$actual"
 517        ) &&
 518        test_cmp expected "$actual"
 519'
 520
 521test_expect_success '__git_refs - repo given on the command line' '
 522        cat >expected <<-EOF &&
 523        HEAD
 524        branch-in-other
 525        master-in-other
 526        tag-in-other
 527        EOF
 528        (
 529                __git_dir="$ROOT/otherrepo/.git" &&
 530                cur= &&
 531                __git_refs >"$actual"
 532        ) &&
 533        test_cmp expected "$actual"
 534'
 535
 536test_expect_success '__git_refs - remote on local file system' '
 537        cat >expected <<-EOF &&
 538        HEAD
 539        branch-in-other
 540        master-in-other
 541        tag-in-other
 542        EOF
 543        (
 544                cur= &&
 545                __git_refs otherrepo >"$actual"
 546        ) &&
 547        test_cmp expected "$actual"
 548'
 549
 550test_expect_success '__git_refs - remote on local file system - full refs' '
 551        cat >expected <<-EOF &&
 552        refs/heads/branch-in-other
 553        refs/heads/master-in-other
 554        refs/tags/tag-in-other
 555        EOF
 556        (
 557                cur=refs/ &&
 558                __git_refs otherrepo >"$actual"
 559        ) &&
 560        test_cmp expected "$actual"
 561'
 562
 563test_expect_success '__git_refs - configured remote' '
 564        cat >expected <<-EOF &&
 565        HEAD
 566        branch-in-other
 567        master-in-other
 568        EOF
 569        (
 570                cur= &&
 571                __git_refs other >"$actual"
 572        ) &&
 573        test_cmp expected "$actual"
 574'
 575
 576test_expect_success '__git_refs - configured remote - full refs' '
 577        cat >expected <<-EOF &&
 578        refs/heads/branch-in-other
 579        refs/heads/master-in-other
 580        refs/tags/tag-in-other
 581        EOF
 582        (
 583                cur=refs/ &&
 584                __git_refs other >"$actual"
 585        ) &&
 586        test_cmp expected "$actual"
 587'
 588
 589test_expect_success '__git_refs - configured remote - repo given on the command line' '
 590        cat >expected <<-EOF &&
 591        HEAD
 592        branch-in-other
 593        master-in-other
 594        EOF
 595        (
 596                cd thirdrepo &&
 597                __git_dir="$ROOT/.git" &&
 598                cur= &&
 599                __git_refs other >"$actual"
 600        ) &&
 601        test_cmp expected "$actual"
 602'
 603
 604test_expect_success '__git_refs - configured remote - full refs - repo given on the command line' '
 605        cat >expected <<-EOF &&
 606        refs/heads/branch-in-other
 607        refs/heads/master-in-other
 608        refs/tags/tag-in-other
 609        EOF
 610        (
 611                cd thirdrepo &&
 612                __git_dir="$ROOT/.git" &&
 613                cur=refs/ &&
 614                __git_refs other >"$actual"
 615        ) &&
 616        test_cmp expected "$actual"
 617'
 618
 619test_expect_success '__git_refs - configured remote - remote name matches a directory' '
 620        cat >expected <<-EOF &&
 621        HEAD
 622        branch-in-other
 623        master-in-other
 624        EOF
 625        mkdir other &&
 626        test_when_finished "rm -rf other" &&
 627        (
 628                cur= &&
 629                __git_refs other >"$actual"
 630        ) &&
 631        test_cmp expected "$actual"
 632'
 633
 634test_expect_success '__git_refs - URL remote' '
 635        cat >expected <<-EOF &&
 636        HEAD
 637        branch-in-other
 638        master-in-other
 639        tag-in-other
 640        EOF
 641        (
 642                cur= &&
 643                __git_refs "file://$ROOT/otherrepo/.git" >"$actual"
 644        ) &&
 645        test_cmp expected "$actual"
 646'
 647
 648test_expect_success '__git_refs - URL remote - full refs' '
 649        cat >expected <<-EOF &&
 650        refs/heads/branch-in-other
 651        refs/heads/master-in-other
 652        refs/tags/tag-in-other
 653        EOF
 654        (
 655                cur=refs/ &&
 656                __git_refs "file://$ROOT/otherrepo/.git" >"$actual"
 657        ) &&
 658        test_cmp expected "$actual"
 659'
 660
 661test_expect_success '__git_refs - non-existing remote' '
 662        (
 663                cur= &&
 664                __git_refs non-existing >"$actual"
 665        ) &&
 666        test_must_be_empty "$actual"
 667'
 668
 669test_expect_success '__git_refs - non-existing remote - full refs' '
 670        (
 671                cur=refs/ &&
 672                __git_refs non-existing >"$actual"
 673        ) &&
 674        test_must_be_empty "$actual"
 675'
 676
 677test_expect_success '__git_refs - non-existing URL remote' '
 678        (
 679                cur= &&
 680                __git_refs "file://$ROOT/non-existing" >"$actual"
 681        ) &&
 682        test_must_be_empty "$actual"
 683'
 684
 685test_expect_success '__git_refs - non-existing URL remote - full refs' '
 686        (
 687                cur=refs/ &&
 688                __git_refs "file://$ROOT/non-existing" >"$actual"
 689        ) &&
 690        test_must_be_empty "$actual"
 691'
 692
 693test_expect_success '__git_refs - not in a git repository' '
 694        (
 695                GIT_CEILING_DIRECTORIES="$ROOT" &&
 696                export GIT_CEILING_DIRECTORIES &&
 697                cd subdir &&
 698                cur= &&
 699                __git_refs >"$actual"
 700        ) &&
 701        test_must_be_empty "$actual"
 702'
 703
 704test_expect_success '__git_refs - unique remote branches for git checkout DWIMery' '
 705        cat >expected <<-EOF &&
 706        HEAD
 707        master
 708        matching-branch
 709        other/ambiguous
 710        other/branch-in-other
 711        other/master-in-other
 712        remote/ambiguous
 713        remote/branch-in-remote
 714        matching-tag
 715        branch-in-other
 716        branch-in-remote
 717        master-in-other
 718        EOF
 719        for remote_ref in refs/remotes/other/ambiguous \
 720                refs/remotes/remote/ambiguous \
 721                refs/remotes/remote/branch-in-remote
 722        do
 723                git update-ref $remote_ref master &&
 724                test_when_finished "git update-ref -d $remote_ref"
 725        done &&
 726        (
 727                cur= &&
 728                __git_refs "" 1 >"$actual"
 729        ) &&
 730        test_cmp expected "$actual"
 731'
 732
 733test_expect_success 'teardown after ref completion' '
 734        git branch -d matching-branch &&
 735        git tag -d matching-tag &&
 736        git remote remove other
 737'
 738
 739test_expect_success '__git_get_config_variables' '
 740        cat >expect <<-EOF &&
 741        name-1
 742        name-2
 743        EOF
 744        test_config interesting.name-1 good &&
 745        test_config interesting.name-2 good &&
 746        test_config subsection.interesting.name-3 bad &&
 747        __git_get_config_variables interesting >actual &&
 748        test_cmp expect actual
 749'
 750
 751test_expect_success '__git_pretty_aliases' '
 752        cat >expect <<-EOF &&
 753        author
 754        hash
 755        EOF
 756        test_config pretty.author "%an %ae" &&
 757        test_config pretty.hash %H &&
 758        __git_pretty_aliases >actual &&
 759        test_cmp expect actual
 760'
 761
 762test_expect_success '__git_aliases' '
 763        cat >expect <<-EOF &&
 764        ci
 765        co
 766        EOF
 767        test_config alias.ci commit &&
 768        test_config alias.co checkout &&
 769        __git_aliases >actual &&
 770        test_cmp expect actual
 771'
 772
 773test_expect_success 'basic' '
 774        run_completion "git " &&
 775        # built-in
 776        grep -q "^add \$" out &&
 777        # script
 778        grep -q "^filter-branch \$" out &&
 779        # plumbing
 780        ! grep -q "^ls-files \$" out &&
 781
 782        run_completion "git f" &&
 783        ! grep -q -v "^f" out
 784'
 785
 786test_expect_success 'double dash "git" itself' '
 787        test_completion "git --" <<-\EOF
 788        --paginate Z
 789        --no-pager Z
 790        --git-dir=
 791        --bare Z
 792        --version Z
 793        --exec-path Z
 794        --exec-path=
 795        --html-path Z
 796        --man-path Z
 797        --info-path Z
 798        --work-tree=
 799        --namespace=
 800        --no-replace-objects Z
 801        --help Z
 802        EOF
 803'
 804
 805test_expect_success 'double dash "git checkout"' '
 806        test_completion "git checkout --" <<-\EOF
 807        --quiet Z
 808        --ours Z
 809        --theirs Z
 810        --track Z
 811        --no-track Z
 812        --merge Z
 813        --conflict=
 814        --orphan Z
 815        --patch Z
 816        EOF
 817'
 818
 819test_expect_success 'general options' '
 820        test_completion "git --ver" "--version " &&
 821        test_completion "git --hel" "--help " &&
 822        test_completion "git --exe" <<-\EOF &&
 823        --exec-path Z
 824        --exec-path=
 825        EOF
 826        test_completion "git --htm" "--html-path " &&
 827        test_completion "git --pag" "--paginate " &&
 828        test_completion "git --no-p" "--no-pager " &&
 829        test_completion "git --git" "--git-dir=" &&
 830        test_completion "git --wor" "--work-tree=" &&
 831        test_completion "git --nam" "--namespace=" &&
 832        test_completion "git --bar" "--bare " &&
 833        test_completion "git --inf" "--info-path " &&
 834        test_completion "git --no-r" "--no-replace-objects "
 835'
 836
 837test_expect_success 'general options plus command' '
 838        test_completion "git --version check" "checkout " &&
 839        test_completion "git --paginate check" "checkout " &&
 840        test_completion "git --git-dir=foo check" "checkout " &&
 841        test_completion "git --bare check" "checkout " &&
 842        test_completion "git --exec-path=foo check" "checkout " &&
 843        test_completion "git --html-path check" "checkout " &&
 844        test_completion "git --no-pager check" "checkout " &&
 845        test_completion "git --work-tree=foo check" "checkout " &&
 846        test_completion "git --namespace=foo check" "checkout " &&
 847        test_completion "git --paginate check" "checkout " &&
 848        test_completion "git --info-path check" "checkout " &&
 849        test_completion "git --no-replace-objects check" "checkout " &&
 850        test_completion "git --git-dir some/path check" "checkout " &&
 851        test_completion "git -c conf.var=value check" "checkout " &&
 852        test_completion "git -C some/path check" "checkout " &&
 853        test_completion "git --work-tree some/path check" "checkout " &&
 854        test_completion "git --namespace name/space check" "checkout "
 855'
 856
 857test_expect_success 'git --help completion' '
 858        test_completion "git --help ad" "add " &&
 859        test_completion "git --help core" "core-tutorial "
 860'
 861
 862test_expect_success 'setup for integration tests' '
 863        echo content >file1 &&
 864        echo more >file2 &&
 865        git add file1 file2 &&
 866        git commit -m one &&
 867        git branch mybranch &&
 868        git tag mytag
 869'
 870
 871test_expect_success 'checkout completes ref names' '
 872        test_completion "git checkout m" <<-\EOF
 873        master Z
 874        mybranch Z
 875        mytag Z
 876        EOF
 877'
 878
 879test_expect_success 'git -C <path> checkout uses the right repo' '
 880        test_completion "git -C subdir -C subsubdir -C .. -C ../otherrepo checkout b" <<-\EOF
 881        branch-in-other Z
 882        EOF
 883'
 884
 885test_expect_success 'show completes all refs' '
 886        test_completion "git show m" <<-\EOF
 887        master Z
 888        mybranch Z
 889        mytag Z
 890        EOF
 891'
 892
 893test_expect_success '<ref>: completes paths' '
 894        test_completion "git show mytag:f" <<-\EOF
 895        file1 Z
 896        file2 Z
 897        EOF
 898'
 899
 900test_expect_success 'complete tree filename with spaces' '
 901        echo content >"name with spaces" &&
 902        git add "name with spaces" &&
 903        git commit -m spaces &&
 904        test_completion "git show HEAD:nam" <<-\EOF
 905        name with spaces Z
 906        EOF
 907'
 908
 909test_expect_success 'complete tree filename with metacharacters' '
 910        echo content >"name with \${meta}" &&
 911        git add "name with \${meta}" &&
 912        git commit -m meta &&
 913        test_completion "git show HEAD:nam" <<-\EOF
 914        name with ${meta} Z
 915        name with spaces Z
 916        EOF
 917'
 918
 919test_expect_success 'send-email' '
 920        test_completion "git send-email --cov" "--cover-letter " &&
 921        test_completion "git send-email ma" "master "
 922'
 923
 924test_expect_success 'complete files' '
 925        git init tmp && cd tmp &&
 926        test_when_finished "cd .. && rm -rf tmp" &&
 927
 928        echo "expected" > .gitignore &&
 929        echo "out" >> .gitignore &&
 930
 931        git add .gitignore &&
 932        test_completion "git commit " ".gitignore" &&
 933
 934        git commit -m ignore &&
 935
 936        touch new &&
 937        test_completion "git add " "new" &&
 938
 939        git add new &&
 940        git commit -a -m new &&
 941        test_completion "git add " "" &&
 942
 943        git mv new modified &&
 944        echo modify > modified &&
 945        test_completion "git add " "modified" &&
 946
 947        touch untracked &&
 948
 949        : TODO .gitignore should not be here &&
 950        test_completion "git rm " <<-\EOF &&
 951        .gitignore
 952        modified
 953        EOF
 954
 955        test_completion "git clean " "untracked" &&
 956
 957        : TODO .gitignore should not be here &&
 958        test_completion "git mv " <<-\EOF &&
 959        .gitignore
 960        modified
 961        EOF
 962
 963        mkdir dir &&
 964        touch dir/file-in-dir &&
 965        git add dir/file-in-dir &&
 966        git commit -m dir &&
 967
 968        mkdir untracked-dir &&
 969
 970        : TODO .gitignore should not be here &&
 971        test_completion "git mv modified " <<-\EOF &&
 972        .gitignore
 973        dir
 974        modified
 975        untracked
 976        untracked-dir
 977        EOF
 978
 979        test_completion "git commit " "modified" &&
 980
 981        : TODO .gitignore should not be here &&
 982        test_completion "git ls-files " <<-\EOF &&
 983        .gitignore
 984        dir
 985        modified
 986        EOF
 987
 988        touch momified &&
 989        test_completion "git add mom" "momified"
 990'
 991
 992test_expect_success "completion uses <cmd> completion for alias: !sh -c 'git <cmd> ...'" '
 993        test_config alias.co "!sh -c '"'"'git checkout ...'"'"'" &&
 994        test_completion "git co m" <<-\EOF
 995        master Z
 996        mybranch Z
 997        mytag Z
 998        EOF
 999'
1000
1001test_expect_success 'completion uses <cmd> completion for alias: !f () { VAR=val git <cmd> ... }' '
1002        test_config alias.co "!f () { VAR=val git checkout ... ; } f" &&
1003        test_completion "git co m" <<-\EOF
1004        master Z
1005        mybranch Z
1006        mytag Z
1007        EOF
1008'
1009
1010test_expect_success 'completion used <cmd> completion for alias: !f() { : git <cmd> ; ... }' '
1011        test_config alias.co "!f() { : git checkout ; if ... } f" &&
1012        test_completion "git co m" <<-\EOF
1013        master Z
1014        mybranch Z
1015        mytag Z
1016        EOF
1017'
1018
1019test_expect_failure 'complete with tilde expansion' '
1020        git init tmp && cd tmp &&
1021        test_when_finished "cd .. && rm -rf tmp" &&
1022
1023        touch ~/tmp/file &&
1024
1025        test_completion "git add ~/tmp/" "~/tmp/file"
1026'
1027
1028test_done