t / t9902-completion.shon commit completion: let 'for-each-ref' strip the remote name from remote branches (e8cb023)
   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 __git_find_repo_path/__gitdir tests' '
 135        mkdir -p subdir/subsubdir &&
 136        mkdir -p non-repo &&
 137        git init otherrepo
 138'
 139
 140test_expect_success '__git_find_repo_path - from command line (through $__git_dir)' '
 141        echo "$ROOT/otherrepo/.git" >expected &&
 142        (
 143                __git_dir="$ROOT/otherrepo/.git" &&
 144                __git_find_repo_path &&
 145                echo "$__git_repo_path" >"$actual"
 146        ) &&
 147        test_cmp expected "$actual"
 148'
 149
 150test_expect_success '__git_find_repo_path - .git directory in cwd' '
 151        echo ".git" >expected &&
 152        (
 153                __git_find_repo_path &&
 154                echo "$__git_repo_path" >"$actual"
 155        ) &&
 156        test_cmp expected "$actual"
 157'
 158
 159test_expect_success '__git_find_repo_path - .git directory in parent' '
 160        echo "$ROOT/.git" >expected &&
 161        (
 162                cd subdir/subsubdir &&
 163                __git_find_repo_path &&
 164                echo "$__git_repo_path" >"$actual"
 165        ) &&
 166        test_cmp expected "$actual"
 167'
 168
 169test_expect_success '__git_find_repo_path - cwd is a .git directory' '
 170        echo "." >expected &&
 171        (
 172                cd .git &&
 173                __git_find_repo_path &&
 174                echo "$__git_repo_path" >"$actual"
 175        ) &&
 176        test_cmp expected "$actual"
 177'
 178
 179test_expect_success '__git_find_repo_path - parent is a .git directory' '
 180        echo "$ROOT/.git" >expected &&
 181        (
 182                cd .git/refs/heads &&
 183                __git_find_repo_path &&
 184                echo "$__git_repo_path" >"$actual"
 185        ) &&
 186        test_cmp expected "$actual"
 187'
 188
 189test_expect_success '__git_find_repo_path - $GIT_DIR set while .git directory in cwd' '
 190        echo "$ROOT/otherrepo/.git" >expected &&
 191        (
 192                GIT_DIR="$ROOT/otherrepo/.git" &&
 193                export GIT_DIR &&
 194                __git_find_repo_path &&
 195                echo "$__git_repo_path" >"$actual"
 196        ) &&
 197        test_cmp expected "$actual"
 198'
 199
 200test_expect_success '__git_find_repo_path - $GIT_DIR set while .git directory in parent' '
 201        echo "$ROOT/otherrepo/.git" >expected &&
 202        (
 203                GIT_DIR="$ROOT/otherrepo/.git" &&
 204                export GIT_DIR &&
 205                cd subdir &&
 206                __git_find_repo_path &&
 207                echo "$__git_repo_path" >"$actual"
 208        ) &&
 209        test_cmp expected "$actual"
 210'
 211
 212test_expect_success '__git_find_repo_path - from command line while "git -C"' '
 213        echo "$ROOT/.git" >expected &&
 214        (
 215                __git_dir="$ROOT/.git" &&
 216                __git_C_args=(-C otherrepo) &&
 217                __git_find_repo_path &&
 218                echo "$__git_repo_path" >"$actual"
 219        ) &&
 220        test_cmp expected "$actual"
 221'
 222
 223test_expect_success '__git_find_repo_path - relative dir from command line and "git -C"' '
 224        echo "$ROOT/otherrepo/.git" >expected &&
 225        (
 226                cd subdir &&
 227                __git_dir="otherrepo/.git" &&
 228                __git_C_args=(-C ..) &&
 229                __git_find_repo_path &&
 230                echo "$__git_repo_path" >"$actual"
 231        ) &&
 232        test_cmp expected "$actual"
 233'
 234
 235test_expect_success '__git_find_repo_path - $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                __git_find_repo_path &&
 242                echo "$__git_repo_path" >"$actual"
 243        ) &&
 244        test_cmp expected "$actual"
 245'
 246
 247test_expect_success '__git_find_repo_path - relative dir in $GIT_DIR and "git -C"' '
 248        echo "$ROOT/otherrepo/.git" >expected &&
 249        (
 250                cd subdir &&
 251                GIT_DIR="otherrepo/.git" &&
 252                export GIT_DIR &&
 253                __git_C_args=(-C ..) &&
 254                __git_find_repo_path &&
 255                echo "$__git_repo_path" >"$actual"
 256        ) &&
 257        test_cmp expected "$actual"
 258'
 259
 260test_expect_success '__git_find_repo_path - "git -C" while .git directory in cwd' '
 261        echo "$ROOT/otherrepo/.git" >expected &&
 262        (
 263                __git_C_args=(-C otherrepo) &&
 264                __git_find_repo_path &&
 265                echo "$__git_repo_path" >"$actual"
 266        ) &&
 267        test_cmp expected "$actual"
 268'
 269
 270test_expect_success '__git_find_repo_path - "git -C" while cwd is a .git directory' '
 271        echo "$ROOT/otherrepo/.git" >expected &&
 272        (
 273                cd .git &&
 274                __git_C_args=(-C .. -C otherrepo) &&
 275                __git_find_repo_path &&
 276                echo "$__git_repo_path" >"$actual"
 277        ) &&
 278        test_cmp expected "$actual"
 279'
 280
 281test_expect_success '__git_find_repo_path - "git -C" while .git directory in parent' '
 282        echo "$ROOT/otherrepo/.git" >expected &&
 283        (
 284                cd subdir &&
 285                __git_C_args=(-C .. -C otherrepo) &&
 286                __git_find_repo_path &&
 287                echo "$__git_repo_path" >"$actual"
 288        ) &&
 289        test_cmp expected "$actual"
 290'
 291
 292test_expect_success '__git_find_repo_path - non-existing path in "git -C"' '
 293        (
 294                __git_C_args=(-C non-existing) &&
 295                test_must_fail __git_find_repo_path &&
 296                printf "$__git_repo_path" >"$actual"
 297        ) &&
 298        test_must_be_empty "$actual"
 299'
 300
 301test_expect_success '__git_find_repo_path - non-existing path in $__git_dir' '
 302        (
 303                __git_dir="non-existing" &&
 304                test_must_fail __git_find_repo_path &&
 305                printf "$__git_repo_path" >"$actual"
 306        ) &&
 307        test_must_be_empty "$actual"
 308'
 309
 310test_expect_success '__git_find_repo_path - non-existing $GIT_DIR' '
 311        (
 312                GIT_DIR="$ROOT/non-existing" &&
 313                export GIT_DIR &&
 314                test_must_fail __git_find_repo_path &&
 315                printf "$__git_repo_path" >"$actual"
 316        ) &&
 317        test_must_be_empty "$actual"
 318'
 319
 320test_expect_success '__git_find_repo_path - gitfile in cwd' '
 321        echo "$ROOT/otherrepo/.git" >expected &&
 322        echo "gitdir: $ROOT/otherrepo/.git" >subdir/.git &&
 323        test_when_finished "rm -f subdir/.git" &&
 324        (
 325                cd subdir &&
 326                __git_find_repo_path &&
 327                echo "$__git_repo_path" >"$actual"
 328        ) &&
 329        test_cmp expected "$actual"
 330'
 331
 332test_expect_success '__git_find_repo_path - gitfile in parent' '
 333        echo "$ROOT/otherrepo/.git" >expected &&
 334        echo "gitdir: $ROOT/otherrepo/.git" >subdir/.git &&
 335        test_when_finished "rm -f subdir/.git" &&
 336        (
 337                cd subdir/subsubdir &&
 338                __git_find_repo_path &&
 339                echo "$__git_repo_path" >"$actual"
 340        ) &&
 341        test_cmp expected "$actual"
 342'
 343
 344test_expect_success SYMLINKS '__git_find_repo_path - resulting path avoids symlinks' '
 345        echo "$ROOT/otherrepo/.git" >expected &&
 346        mkdir otherrepo/dir &&
 347        test_when_finished "rm -rf otherrepo/dir" &&
 348        ln -s otherrepo/dir link &&
 349        test_when_finished "rm -f link" &&
 350        (
 351                cd link &&
 352                __git_find_repo_path &&
 353                echo "$__git_repo_path" >"$actual"
 354        ) &&
 355        test_cmp expected "$actual"
 356'
 357
 358test_expect_success '__git_find_repo_path - not a git repository' '
 359        (
 360                cd non-repo &&
 361                GIT_CEILING_DIRECTORIES="$ROOT" &&
 362                export GIT_CEILING_DIRECTORIES &&
 363                test_must_fail __git_find_repo_path &&
 364                printf "$__git_repo_path" >"$actual"
 365        ) &&
 366        test_must_be_empty "$actual"
 367'
 368
 369test_expect_success '__gitdir - finds repo' '
 370        echo "$ROOT/.git" >expected &&
 371        (
 372                cd subdir/subsubdir &&
 373                __gitdir >"$actual"
 374        ) &&
 375        test_cmp expected "$actual"
 376'
 377
 378
 379test_expect_success '__gitdir - returns error when cant find repo' '
 380        (
 381                __git_dir="non-existing" &&
 382                test_must_fail __gitdir >"$actual"
 383        ) &&
 384        test_must_be_empty "$actual"
 385'
 386
 387test_expect_success '__gitdir - repo as argument' '
 388        echo "otherrepo/.git" >expected &&
 389        (
 390                __gitdir "otherrepo" >"$actual"
 391        ) &&
 392        test_cmp expected "$actual"
 393'
 394
 395test_expect_success '__gitdir - remote as argument' '
 396        echo "remote" >expected &&
 397        (
 398                __gitdir "remote" >"$actual"
 399        ) &&
 400        test_cmp expected "$actual"
 401'
 402
 403test_expect_success '__gitcomp - trailing space - options' '
 404        test_gitcomp "--re" "--dry-run --reuse-message= --reedit-message=
 405                --reset-author" <<-EOF
 406        --reuse-message=Z
 407        --reedit-message=Z
 408        --reset-author Z
 409        EOF
 410'
 411
 412test_expect_success '__gitcomp - trailing space - config keys' '
 413        test_gitcomp "br" "branch. branch.autosetupmerge
 414                branch.autosetuprebase browser." <<-\EOF
 415        branch.Z
 416        branch.autosetupmerge Z
 417        branch.autosetuprebase Z
 418        browser.Z
 419        EOF
 420'
 421
 422test_expect_success '__gitcomp - option parameter' '
 423        test_gitcomp "--strategy=re" "octopus ours recursive resolve subtree" \
 424                "" "re" <<-\EOF
 425        recursive Z
 426        resolve Z
 427        EOF
 428'
 429
 430test_expect_success '__gitcomp - prefix' '
 431        test_gitcomp "branch.me" "remote merge mergeoptions rebase" \
 432                "branch.maint." "me" <<-\EOF
 433        branch.maint.merge Z
 434        branch.maint.mergeoptions Z
 435        EOF
 436'
 437
 438test_expect_success '__gitcomp - suffix' '
 439        test_gitcomp "branch.me" "master maint next pu" "branch." \
 440                "ma" "." <<-\EOF
 441        branch.master.Z
 442        branch.maint.Z
 443        EOF
 444'
 445
 446test_expect_success '__gitcomp - doesnt fail because of invalid variable name' '
 447        __gitcomp "$invalid_variable_name"
 448'
 449
 450read -r -d "" refs <<-\EOF
 451maint
 452master
 453next
 454pu
 455EOF
 456
 457test_expect_success '__gitcomp_nl - trailing space' '
 458        test_gitcomp_nl "m" "$refs" <<-EOF
 459        maint Z
 460        master Z
 461        EOF
 462'
 463
 464test_expect_success '__gitcomp_nl - prefix' '
 465        test_gitcomp_nl "--fixup=m" "$refs" "--fixup=" "m" <<-EOF
 466        --fixup=maint Z
 467        --fixup=master Z
 468        EOF
 469'
 470
 471test_expect_success '__gitcomp_nl - suffix' '
 472        test_gitcomp_nl "branch.ma" "$refs" "branch." "ma" "." <<-\EOF
 473        branch.maint.Z
 474        branch.master.Z
 475        EOF
 476'
 477
 478test_expect_success '__gitcomp_nl - no suffix' '
 479        test_gitcomp_nl "ma" "$refs" "" "ma" "" <<-\EOF
 480        maintZ
 481        masterZ
 482        EOF
 483'
 484
 485test_expect_success '__gitcomp_nl - doesnt fail because of invalid variable name' '
 486        __gitcomp_nl "$invalid_variable_name"
 487'
 488
 489test_expect_success '__git_remotes - list remotes from $GIT_DIR/remotes and from config file' '
 490        cat >expect <<-EOF &&
 491        remote_from_file_1
 492        remote_from_file_2
 493        remote_in_config_1
 494        remote_in_config_2
 495        EOF
 496        test_when_finished "rm -rf .git/remotes" &&
 497        mkdir -p .git/remotes &&
 498        >.git/remotes/remote_from_file_1 &&
 499        >.git/remotes/remote_from_file_2 &&
 500        test_when_finished "git remote remove remote_in_config_1" &&
 501        git remote add remote_in_config_1 git://remote_1 &&
 502        test_when_finished "git remote remove remote_in_config_2" &&
 503        git remote add remote_in_config_2 git://remote_2 &&
 504        (
 505                __git_remotes >actual
 506        ) &&
 507        test_cmp expect actual
 508'
 509
 510test_expect_success '__git_is_configured_remote' '
 511        test_when_finished "git remote remove remote_1" &&
 512        git remote add remote_1 git://remote_1 &&
 513        test_when_finished "git remote remove remote_2" &&
 514        git remote add remote_2 git://remote_2 &&
 515        (
 516                verbose __git_is_configured_remote remote_2 &&
 517                test_must_fail __git_is_configured_remote non-existent
 518        )
 519'
 520
 521test_expect_success 'setup for ref completion' '
 522        git commit --allow-empty -m initial &&
 523        git branch matching-branch &&
 524        git tag matching-tag &&
 525        (
 526                cd otherrepo &&
 527                git commit --allow-empty -m initial &&
 528                git branch -m master master-in-other &&
 529                git branch branch-in-other &&
 530                git tag tag-in-other
 531        ) &&
 532        git remote add other "$ROOT/otherrepo/.git" &&
 533        git fetch --no-tags other &&
 534        rm -f .git/FETCH_HEAD &&
 535        git init thirdrepo
 536'
 537
 538test_expect_success '__git_refs - simple' '
 539        cat >expected <<-EOF &&
 540        HEAD
 541        master
 542        matching-branch
 543        other/branch-in-other
 544        other/master-in-other
 545        matching-tag
 546        EOF
 547        (
 548                cur= &&
 549                __git_refs >"$actual"
 550        ) &&
 551        test_cmp expected "$actual"
 552'
 553
 554test_expect_success '__git_refs - full refs' '
 555        cat >expected <<-EOF &&
 556        refs/heads/master
 557        refs/heads/matching-branch
 558        refs/remotes/other/branch-in-other
 559        refs/remotes/other/master-in-other
 560        refs/tags/matching-tag
 561        EOF
 562        (
 563                cur=refs/heads/ &&
 564                __git_refs >"$actual"
 565        ) &&
 566        test_cmp expected "$actual"
 567'
 568
 569test_expect_success '__git_refs - repo given on the command line' '
 570        cat >expected <<-EOF &&
 571        HEAD
 572        branch-in-other
 573        master-in-other
 574        tag-in-other
 575        EOF
 576        (
 577                __git_dir="$ROOT/otherrepo/.git" &&
 578                cur= &&
 579                __git_refs >"$actual"
 580        ) &&
 581        test_cmp expected "$actual"
 582'
 583
 584test_expect_success '__git_refs - remote on local file system' '
 585        cat >expected <<-EOF &&
 586        HEAD
 587        branch-in-other
 588        master-in-other
 589        tag-in-other
 590        EOF
 591        (
 592                cur= &&
 593                __git_refs otherrepo >"$actual"
 594        ) &&
 595        test_cmp expected "$actual"
 596'
 597
 598test_expect_success '__git_refs - remote on local file system - full refs' '
 599        cat >expected <<-EOF &&
 600        refs/heads/branch-in-other
 601        refs/heads/master-in-other
 602        refs/tags/tag-in-other
 603        EOF
 604        (
 605                cur=refs/ &&
 606                __git_refs otherrepo >"$actual"
 607        ) &&
 608        test_cmp expected "$actual"
 609'
 610
 611test_expect_success '__git_refs - configured remote' '
 612        cat >expected <<-EOF &&
 613        HEAD
 614        branch-in-other
 615        master-in-other
 616        EOF
 617        (
 618                cur= &&
 619                __git_refs other >"$actual"
 620        ) &&
 621        test_cmp expected "$actual"
 622'
 623
 624test_expect_success '__git_refs - configured remote - full refs' '
 625        cat >expected <<-EOF &&
 626        HEAD
 627        refs/heads/branch-in-other
 628        refs/heads/master-in-other
 629        refs/tags/tag-in-other
 630        EOF
 631        (
 632                cur=refs/ &&
 633                __git_refs other >"$actual"
 634        ) &&
 635        test_cmp expected "$actual"
 636'
 637
 638test_expect_success '__git_refs - configured remote - repo given on the command line' '
 639        cat >expected <<-EOF &&
 640        HEAD
 641        branch-in-other
 642        master-in-other
 643        EOF
 644        (
 645                cd thirdrepo &&
 646                __git_dir="$ROOT/.git" &&
 647                cur= &&
 648                __git_refs other >"$actual"
 649        ) &&
 650        test_cmp expected "$actual"
 651'
 652
 653test_expect_success '__git_refs - configured remote - full refs - repo given on the command line' '
 654        cat >expected <<-EOF &&
 655        HEAD
 656        refs/heads/branch-in-other
 657        refs/heads/master-in-other
 658        refs/tags/tag-in-other
 659        EOF
 660        (
 661                cd thirdrepo &&
 662                __git_dir="$ROOT/.git" &&
 663                cur=refs/ &&
 664                __git_refs other >"$actual"
 665        ) &&
 666        test_cmp expected "$actual"
 667'
 668
 669test_expect_success '__git_refs - configured remote - remote name matches a directory' '
 670        cat >expected <<-EOF &&
 671        HEAD
 672        branch-in-other
 673        master-in-other
 674        EOF
 675        mkdir other &&
 676        test_when_finished "rm -rf other" &&
 677        (
 678                cur= &&
 679                __git_refs other >"$actual"
 680        ) &&
 681        test_cmp expected "$actual"
 682'
 683
 684test_expect_success '__git_refs - URL remote' '
 685        cat >expected <<-EOF &&
 686        HEAD
 687        branch-in-other
 688        master-in-other
 689        tag-in-other
 690        EOF
 691        (
 692                cur= &&
 693                __git_refs "file://$ROOT/otherrepo/.git" >"$actual"
 694        ) &&
 695        test_cmp expected "$actual"
 696'
 697
 698test_expect_success '__git_refs - URL remote - full refs' '
 699        cat >expected <<-EOF &&
 700        HEAD
 701        refs/heads/branch-in-other
 702        refs/heads/master-in-other
 703        refs/tags/tag-in-other
 704        EOF
 705        (
 706                cur=refs/ &&
 707                __git_refs "file://$ROOT/otherrepo/.git" >"$actual"
 708        ) &&
 709        test_cmp expected "$actual"
 710'
 711
 712test_expect_success '__git_refs - non-existing remote' '
 713        (
 714                cur= &&
 715                __git_refs non-existing >"$actual"
 716        ) &&
 717        test_must_be_empty "$actual"
 718'
 719
 720test_expect_success '__git_refs - non-existing remote - full refs' '
 721        (
 722                cur=refs/ &&
 723                __git_refs non-existing >"$actual"
 724        ) &&
 725        test_must_be_empty "$actual"
 726'
 727
 728test_expect_success '__git_refs - non-existing URL remote' '
 729        (
 730                cur= &&
 731                __git_refs "file://$ROOT/non-existing" >"$actual"
 732        ) &&
 733        test_must_be_empty "$actual"
 734'
 735
 736test_expect_success '__git_refs - non-existing URL remote - full refs' '
 737        (
 738                cur=refs/ &&
 739                __git_refs "file://$ROOT/non-existing" >"$actual"
 740        ) &&
 741        test_must_be_empty "$actual"
 742'
 743
 744test_expect_success '__git_refs - not in a git repository' '
 745        (
 746                GIT_CEILING_DIRECTORIES="$ROOT" &&
 747                export GIT_CEILING_DIRECTORIES &&
 748                cd subdir &&
 749                cur= &&
 750                __git_refs >"$actual"
 751        ) &&
 752        test_must_be_empty "$actual"
 753'
 754
 755test_expect_success '__git_refs - unique remote branches for git checkout DWIMery' '
 756        cat >expected <<-EOF &&
 757        HEAD
 758        master
 759        matching-branch
 760        other/ambiguous
 761        other/branch-in-other
 762        other/master-in-other
 763        remote/ambiguous
 764        remote/branch-in-remote
 765        matching-tag
 766        branch-in-other
 767        branch-in-remote
 768        master-in-other
 769        EOF
 770        for remote_ref in refs/remotes/other/ambiguous \
 771                refs/remotes/remote/ambiguous \
 772                refs/remotes/remote/branch-in-remote
 773        do
 774                git update-ref $remote_ref master &&
 775                test_when_finished "git update-ref -d $remote_ref"
 776        done &&
 777        (
 778                cur= &&
 779                __git_refs "" 1 >"$actual"
 780        ) &&
 781        test_cmp expected "$actual"
 782'
 783
 784test_expect_success '__git_refs - after --opt=' '
 785        cat >expected <<-EOF &&
 786        HEAD
 787        master
 788        matching-branch
 789        other/branch-in-other
 790        other/master-in-other
 791        matching-tag
 792        EOF
 793        (
 794                cur="--opt=" &&
 795                __git_refs "" "" "" "" >"$actual"
 796        ) &&
 797        test_cmp expected "$actual"
 798'
 799
 800test_expect_success '__git_refs - after --opt= - full refs' '
 801        cat >expected <<-EOF &&
 802        refs/heads/master
 803        refs/heads/matching-branch
 804        refs/remotes/other/branch-in-other
 805        refs/remotes/other/master-in-other
 806        refs/tags/matching-tag
 807        EOF
 808        (
 809                cur="--opt=refs/" &&
 810                __git_refs "" "" "" refs/ >"$actual"
 811        ) &&
 812        test_cmp expected "$actual"
 813'
 814
 815test_expect_success '__git refs - exluding refs' '
 816        cat >expected <<-EOF &&
 817        ^HEAD
 818        ^master
 819        ^matching-branch
 820        ^other/branch-in-other
 821        ^other/master-in-other
 822        ^matching-tag
 823        EOF
 824        (
 825                cur=^ &&
 826                __git_refs >"$actual"
 827        ) &&
 828        test_cmp expected "$actual"
 829'
 830
 831test_expect_success '__git refs - exluding full refs' '
 832        cat >expected <<-EOF &&
 833        ^refs/heads/master
 834        ^refs/heads/matching-branch
 835        ^refs/remotes/other/branch-in-other
 836        ^refs/remotes/other/master-in-other
 837        ^refs/tags/matching-tag
 838        EOF
 839        (
 840                cur=^refs/ &&
 841                __git_refs >"$actual"
 842        ) &&
 843        test_cmp expected "$actual"
 844'
 845
 846test_expect_success 'setup for filtering matching refs' '
 847        git branch matching/branch &&
 848        git tag matching/tag &&
 849        git -C otherrepo branch matching/branch-in-other &&
 850        git fetch --no-tags other &&
 851        rm -f .git/FETCH_HEAD
 852'
 853
 854test_expect_success '__git_refs - dont filter refs unless told so' '
 855        cat >expected <<-EOF &&
 856        HEAD
 857        master
 858        matching-branch
 859        matching/branch
 860        other/branch-in-other
 861        other/master-in-other
 862        other/matching/branch-in-other
 863        matching-tag
 864        matching/tag
 865        EOF
 866        (
 867                cur=master &&
 868                __git_refs >"$actual"
 869        ) &&
 870        test_cmp expected "$actual"
 871'
 872
 873test_expect_success '__git_refs - only matching refs' '
 874        cat >expected <<-EOF &&
 875        matching-branch
 876        matching/branch
 877        matching-tag
 878        matching/tag
 879        EOF
 880        (
 881                cur=mat &&
 882                __git_refs "" "" "" "$cur" >"$actual"
 883        ) &&
 884        test_cmp expected "$actual"
 885'
 886
 887test_expect_success '__git_refs - only matching refs - full refs' '
 888        cat >expected <<-EOF &&
 889        refs/heads/matching-branch
 890        refs/heads/matching/branch
 891        EOF
 892        (
 893                cur=refs/heads/mat &&
 894                __git_refs "" "" "" "$cur" >"$actual"
 895        ) &&
 896        test_cmp expected "$actual"
 897'
 898
 899test_expect_success '__git_refs - only matching refs - remote on local file system' '
 900        cat >expected <<-EOF &&
 901        master-in-other
 902        matching/branch-in-other
 903        EOF
 904        (
 905                cur=ma &&
 906                __git_refs otherrepo "" "" "$cur" >"$actual"
 907        ) &&
 908        test_cmp expected "$actual"
 909'
 910
 911test_expect_success '__git_refs - only matching refs - configured remote' '
 912        cat >expected <<-EOF &&
 913        master-in-other
 914        matching/branch-in-other
 915        EOF
 916        (
 917                cur=ma &&
 918                __git_refs other "" "" "$cur" >"$actual"
 919        ) &&
 920        test_cmp expected "$actual"
 921'
 922
 923test_expect_success '__git_refs - only matching refs - remote - full refs' '
 924        cat >expected <<-EOF &&
 925        refs/heads/master-in-other
 926        refs/heads/matching/branch-in-other
 927        EOF
 928        (
 929                cur=refs/heads/ma &&
 930                __git_refs other "" "" "$cur" >"$actual"
 931        ) &&
 932        test_cmp expected "$actual"
 933'
 934
 935test_expect_success '__git_refs - only matching refs - checkout DWIMery' '
 936        cat >expected <<-EOF &&
 937        matching-branch
 938        matching/branch
 939        matching-tag
 940        matching/tag
 941        matching/branch-in-other
 942        EOF
 943        for remote_ref in refs/remotes/other/ambiguous \
 944                refs/remotes/remote/ambiguous \
 945                refs/remotes/remote/branch-in-remote
 946        do
 947                git update-ref $remote_ref master &&
 948                test_when_finished "git update-ref -d $remote_ref"
 949        done &&
 950        (
 951                cur=mat &&
 952                __git_refs "" 1 "" "$cur" >"$actual"
 953        ) &&
 954        test_cmp expected "$actual"
 955'
 956
 957test_expect_success 'teardown after filtering matching refs' '
 958        git branch -d matching/branch &&
 959        git tag -d matching/tag &&
 960        git update-ref -d refs/remotes/other/matching/branch-in-other &&
 961        git -C otherrepo branch -D matching/branch-in-other
 962'
 963
 964test_expect_success '__git_complete_refs - simple' '
 965        sed -e "s/Z$//" >expected <<-EOF &&
 966        HEAD Z
 967        master Z
 968        matching-branch Z
 969        other/branch-in-other Z
 970        other/master-in-other Z
 971        matching-tag Z
 972        EOF
 973        (
 974                cur= &&
 975                __git_complete_refs &&
 976                print_comp
 977        ) &&
 978        test_cmp expected out
 979'
 980
 981test_expect_success '__git_complete_refs - matching' '
 982        sed -e "s/Z$//" >expected <<-EOF &&
 983        matching-branch Z
 984        matching-tag Z
 985        EOF
 986        (
 987                cur=mat &&
 988                __git_complete_refs &&
 989                print_comp
 990        ) &&
 991        test_cmp expected out
 992'
 993
 994test_expect_success '__git_complete_refs - remote' '
 995        sed -e "s/Z$//" >expected <<-EOF &&
 996        HEAD Z
 997        branch-in-other Z
 998        master-in-other Z
 999        EOF
1000        (
1001                cur=
1002                __git_complete_refs --remote=other &&
1003                print_comp
1004        ) &&
1005        test_cmp expected out
1006'
1007
1008test_expect_success '__git_complete_refs - track' '
1009        sed -e "s/Z$//" >expected <<-EOF &&
1010        HEAD Z
1011        master Z
1012        matching-branch Z
1013        other/branch-in-other Z
1014        other/master-in-other Z
1015        matching-tag Z
1016        branch-in-other Z
1017        master-in-other Z
1018        EOF
1019        (
1020                cur=
1021                __git_complete_refs --track &&
1022                print_comp
1023        ) &&
1024        test_cmp expected out
1025'
1026
1027test_expect_success '__git_complete_refs - current word' '
1028        sed -e "s/Z$//" >expected <<-EOF &&
1029        matching-branch Z
1030        matching-tag Z
1031        EOF
1032        (
1033                cur="--option=mat" &&
1034                __git_complete_refs --cur="${cur#*=}" &&
1035                print_comp
1036        ) &&
1037        test_cmp expected out
1038'
1039
1040test_expect_success '__git_complete_refs - prefix' '
1041        sed -e "s/Z$//" >expected <<-EOF &&
1042        v1.0..matching-branch Z
1043        v1.0..matching-tag Z
1044        EOF
1045        (
1046                cur=v1.0..mat &&
1047                __git_complete_refs --pfx=v1.0.. --cur=mat &&
1048                print_comp
1049        ) &&
1050        test_cmp expected out
1051'
1052
1053test_expect_success '__git_complete_refs - suffix' '
1054        cat >expected <<-EOF &&
1055        HEAD.
1056        master.
1057        matching-branch.
1058        other/branch-in-other.
1059        other/master-in-other.
1060        matching-tag.
1061        EOF
1062        (
1063                cur= &&
1064                __git_complete_refs --sfx=. &&
1065                print_comp
1066        ) &&
1067        test_cmp expected out
1068'
1069
1070test_expect_success '__git_complete_fetch_refspecs - simple' '
1071        sed -e "s/Z$//" >expected <<-EOF &&
1072        HEAD:HEAD Z
1073        branch-in-other:branch-in-other Z
1074        master-in-other:master-in-other Z
1075        EOF
1076        (
1077                cur= &&
1078                __git_complete_fetch_refspecs other &&
1079                print_comp
1080        ) &&
1081        test_cmp expected out
1082'
1083
1084test_expect_success '__git_complete_fetch_refspecs - matching' '
1085        sed -e "s/Z$//" >expected <<-EOF &&
1086        branch-in-other:branch-in-other Z
1087        EOF
1088        (
1089                cur=br &&
1090                __git_complete_fetch_refspecs other "" br &&
1091                print_comp
1092        ) &&
1093        test_cmp expected out
1094'
1095
1096test_expect_success '__git_complete_fetch_refspecs - prefix' '
1097        sed -e "s/Z$//" >expected <<-EOF &&
1098        +HEAD:HEAD Z
1099        +branch-in-other:branch-in-other Z
1100        +master-in-other:master-in-other Z
1101        EOF
1102        (
1103                cur="+" &&
1104                __git_complete_fetch_refspecs other "+" ""  &&
1105                print_comp
1106        ) &&
1107        test_cmp expected out
1108'
1109
1110test_expect_success '__git_complete_fetch_refspecs - fully qualified' '
1111        sed -e "s/Z$//" >expected <<-EOF &&
1112        refs/heads/branch-in-other:refs/heads/branch-in-other Z
1113        refs/heads/master-in-other:refs/heads/master-in-other Z
1114        refs/tags/tag-in-other:refs/tags/tag-in-other Z
1115        EOF
1116        (
1117                cur=refs/ &&
1118                __git_complete_fetch_refspecs other "" refs/ &&
1119                print_comp
1120        ) &&
1121        test_cmp expected out
1122'
1123
1124test_expect_success '__git_complete_fetch_refspecs - fully qualified & prefix' '
1125        sed -e "s/Z$//" >expected <<-EOF &&
1126        +refs/heads/branch-in-other:refs/heads/branch-in-other Z
1127        +refs/heads/master-in-other:refs/heads/master-in-other Z
1128        +refs/tags/tag-in-other:refs/tags/tag-in-other Z
1129        EOF
1130        (
1131                cur=+refs/ &&
1132                __git_complete_fetch_refspecs other + refs/ &&
1133                print_comp
1134        ) &&
1135        test_cmp expected out
1136'
1137
1138test_expect_success 'teardown after ref completion' '
1139        git branch -d matching-branch &&
1140        git tag -d matching-tag &&
1141        git remote remove other
1142'
1143
1144test_expect_success '__git_get_config_variables' '
1145        cat >expect <<-EOF &&
1146        name-1
1147        name-2
1148        EOF
1149        test_config interesting.name-1 good &&
1150        test_config interesting.name-2 good &&
1151        test_config subsection.interesting.name-3 bad &&
1152        __git_get_config_variables interesting >actual &&
1153        test_cmp expect actual
1154'
1155
1156test_expect_success '__git_pretty_aliases' '
1157        cat >expect <<-EOF &&
1158        author
1159        hash
1160        EOF
1161        test_config pretty.author "%an %ae" &&
1162        test_config pretty.hash %H &&
1163        __git_pretty_aliases >actual &&
1164        test_cmp expect actual
1165'
1166
1167test_expect_success '__git_aliases' '
1168        cat >expect <<-EOF &&
1169        ci
1170        co
1171        EOF
1172        test_config alias.ci commit &&
1173        test_config alias.co checkout &&
1174        __git_aliases >actual &&
1175        test_cmp expect actual
1176'
1177
1178test_expect_success 'basic' '
1179        run_completion "git " &&
1180        # built-in
1181        grep -q "^add \$" out &&
1182        # script
1183        grep -q "^filter-branch \$" out &&
1184        # plumbing
1185        ! grep -q "^ls-files \$" out &&
1186
1187        run_completion "git f" &&
1188        ! grep -q -v "^f" out
1189'
1190
1191test_expect_success 'double dash "git" itself' '
1192        test_completion "git --" <<-\EOF
1193        --paginate Z
1194        --no-pager Z
1195        --git-dir=
1196        --bare Z
1197        --version Z
1198        --exec-path Z
1199        --exec-path=
1200        --html-path Z
1201        --man-path Z
1202        --info-path Z
1203        --work-tree=
1204        --namespace=
1205        --no-replace-objects Z
1206        --help Z
1207        EOF
1208'
1209
1210test_expect_success 'double dash "git checkout"' '
1211        test_completion "git checkout --" <<-\EOF
1212        --quiet Z
1213        --ours Z
1214        --theirs Z
1215        --track Z
1216        --no-track Z
1217        --merge Z
1218        --conflict=
1219        --orphan Z
1220        --patch Z
1221        EOF
1222'
1223
1224test_expect_success 'general options' '
1225        test_completion "git --ver" "--version " &&
1226        test_completion "git --hel" "--help " &&
1227        test_completion "git --exe" <<-\EOF &&
1228        --exec-path Z
1229        --exec-path=
1230        EOF
1231        test_completion "git --htm" "--html-path " &&
1232        test_completion "git --pag" "--paginate " &&
1233        test_completion "git --no-p" "--no-pager " &&
1234        test_completion "git --git" "--git-dir=" &&
1235        test_completion "git --wor" "--work-tree=" &&
1236        test_completion "git --nam" "--namespace=" &&
1237        test_completion "git --bar" "--bare " &&
1238        test_completion "git --inf" "--info-path " &&
1239        test_completion "git --no-r" "--no-replace-objects "
1240'
1241
1242test_expect_success 'general options plus command' '
1243        test_completion "git --version check" "checkout " &&
1244        test_completion "git --paginate check" "checkout " &&
1245        test_completion "git --git-dir=foo check" "checkout " &&
1246        test_completion "git --bare check" "checkout " &&
1247        test_completion "git --exec-path=foo check" "checkout " &&
1248        test_completion "git --html-path check" "checkout " &&
1249        test_completion "git --no-pager check" "checkout " &&
1250        test_completion "git --work-tree=foo check" "checkout " &&
1251        test_completion "git --namespace=foo check" "checkout " &&
1252        test_completion "git --paginate check" "checkout " &&
1253        test_completion "git --info-path check" "checkout " &&
1254        test_completion "git --no-replace-objects check" "checkout " &&
1255        test_completion "git --git-dir some/path check" "checkout " &&
1256        test_completion "git -c conf.var=value check" "checkout " &&
1257        test_completion "git -C some/path check" "checkout " &&
1258        test_completion "git --work-tree some/path check" "checkout " &&
1259        test_completion "git --namespace name/space check" "checkout "
1260'
1261
1262test_expect_success 'git --help completion' '
1263        test_completion "git --help ad" "add " &&
1264        test_completion "git --help core" "core-tutorial "
1265'
1266
1267test_expect_success 'setup for integration tests' '
1268        echo content >file1 &&
1269        echo more >file2 &&
1270        git add file1 file2 &&
1271        git commit -m one &&
1272        git branch mybranch &&
1273        git tag mytag
1274'
1275
1276test_expect_success 'checkout completes ref names' '
1277        test_completion "git checkout m" <<-\EOF
1278        master Z
1279        mybranch Z
1280        mytag Z
1281        EOF
1282'
1283
1284test_expect_success 'git -C <path> checkout uses the right repo' '
1285        test_completion "git -C subdir -C subsubdir -C .. -C ../otherrepo checkout b" <<-\EOF
1286        branch-in-other Z
1287        EOF
1288'
1289
1290test_expect_success 'show completes all refs' '
1291        test_completion "git show m" <<-\EOF
1292        master Z
1293        mybranch Z
1294        mytag Z
1295        EOF
1296'
1297
1298test_expect_success '<ref>: completes paths' '
1299        test_completion "git show mytag:f" <<-\EOF
1300        file1 Z
1301        file2 Z
1302        EOF
1303'
1304
1305test_expect_success 'complete tree filename with spaces' '
1306        echo content >"name with spaces" &&
1307        git add "name with spaces" &&
1308        git commit -m spaces &&
1309        test_completion "git show HEAD:nam" <<-\EOF
1310        name with spaces Z
1311        EOF
1312'
1313
1314test_expect_success 'complete tree filename with metacharacters' '
1315        echo content >"name with \${meta}" &&
1316        git add "name with \${meta}" &&
1317        git commit -m meta &&
1318        test_completion "git show HEAD:nam" <<-\EOF
1319        name with ${meta} Z
1320        name with spaces Z
1321        EOF
1322'
1323
1324test_expect_success 'send-email' '
1325        test_completion "git send-email --cov" "--cover-letter " &&
1326        test_completion "git send-email ma" "master "
1327'
1328
1329test_expect_success 'complete files' '
1330        git init tmp && cd tmp &&
1331        test_when_finished "cd .. && rm -rf tmp" &&
1332
1333        echo "expected" > .gitignore &&
1334        echo "out" >> .gitignore &&
1335
1336        git add .gitignore &&
1337        test_completion "git commit " ".gitignore" &&
1338
1339        git commit -m ignore &&
1340
1341        touch new &&
1342        test_completion "git add " "new" &&
1343
1344        git add new &&
1345        git commit -a -m new &&
1346        test_completion "git add " "" &&
1347
1348        git mv new modified &&
1349        echo modify > modified &&
1350        test_completion "git add " "modified" &&
1351
1352        touch untracked &&
1353
1354        : TODO .gitignore should not be here &&
1355        test_completion "git rm " <<-\EOF &&
1356        .gitignore
1357        modified
1358        EOF
1359
1360        test_completion "git clean " "untracked" &&
1361
1362        : TODO .gitignore should not be here &&
1363        test_completion "git mv " <<-\EOF &&
1364        .gitignore
1365        modified
1366        EOF
1367
1368        mkdir dir &&
1369        touch dir/file-in-dir &&
1370        git add dir/file-in-dir &&
1371        git commit -m dir &&
1372
1373        mkdir untracked-dir &&
1374
1375        : TODO .gitignore should not be here &&
1376        test_completion "git mv modified " <<-\EOF &&
1377        .gitignore
1378        dir
1379        modified
1380        untracked
1381        untracked-dir
1382        EOF
1383
1384        test_completion "git commit " "modified" &&
1385
1386        : TODO .gitignore should not be here &&
1387        test_completion "git ls-files " <<-\EOF &&
1388        .gitignore
1389        dir
1390        modified
1391        EOF
1392
1393        touch momified &&
1394        test_completion "git add mom" "momified"
1395'
1396
1397test_expect_success "completion uses <cmd> completion for alias: !sh -c 'git <cmd> ...'" '
1398        test_config alias.co "!sh -c '"'"'git checkout ...'"'"'" &&
1399        test_completion "git co m" <<-\EOF
1400        master Z
1401        mybranch Z
1402        mytag Z
1403        EOF
1404'
1405
1406test_expect_success 'completion uses <cmd> completion for alias: !f () { VAR=val git <cmd> ... }' '
1407        test_config alias.co "!f () { VAR=val git checkout ... ; } f" &&
1408        test_completion "git co m" <<-\EOF
1409        master Z
1410        mybranch Z
1411        mytag Z
1412        EOF
1413'
1414
1415test_expect_success 'completion used <cmd> completion for alias: !f() { : git <cmd> ; ... }' '
1416        test_config alias.co "!f() { : git checkout ; if ... } f" &&
1417        test_completion "git co m" <<-\EOF
1418        master Z
1419        mybranch Z
1420        mytag Z
1421        EOF
1422'
1423
1424test_expect_failure 'complete with tilde expansion' '
1425        git init tmp && cd tmp &&
1426        test_when_finished "cd .. && rm -rf tmp" &&
1427
1428        touch ~/tmp/file &&
1429
1430        test_completion "git add ~/tmp/" "~/tmp/file"
1431'
1432
1433test_done