t / t9902-completion.shon commit completion: improve handling quoted paths in 'git ls-files's output (193757f)
   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$//' |sort >expected
  88        fi &&
  89        run_completion "$1" &&
  90        sort out >out_sorted &&
  91        test_cmp expected out_sorted
  92}
  93
  94# Test __gitcomp.
  95# The first argument is the typed text so far (cur); the rest are
  96# passed to __gitcomp.  Expected output comes is read from the
  97# standard input, like test_completion().
  98test_gitcomp ()
  99{
 100        local -a COMPREPLY &&
 101        sed -e 's/Z$//' >expected &&
 102        local cur="$1" &&
 103        shift &&
 104        __gitcomp "$@" &&
 105        print_comp &&
 106        test_cmp expected out
 107}
 108
 109# Test __gitcomp_nl
 110# Arguments are:
 111# 1: current word (cur)
 112# -: the rest are passed to __gitcomp_nl
 113test_gitcomp_nl ()
 114{
 115        local -a COMPREPLY &&
 116        sed -e 's/Z$//' >expected &&
 117        local cur="$1" &&
 118        shift &&
 119        __gitcomp_nl "$@" &&
 120        print_comp &&
 121        test_cmp expected out
 122}
 123
 124invalid_variable_name='${foo.bar}'
 125
 126actual="$TRASH_DIRECTORY/actual"
 127
 128if test_have_prereq MINGW
 129then
 130        ROOT="$(pwd -W)"
 131else
 132        ROOT="$(pwd)"
 133fi
 134
 135test_expect_success 'setup for __git_find_repo_path/__gitdir tests' '
 136        mkdir -p subdir/subsubdir &&
 137        mkdir -p non-repo &&
 138        git init otherrepo
 139'
 140
 141test_expect_success '__git_find_repo_path - from command line (through $__git_dir)' '
 142        echo "$ROOT/otherrepo/.git" >expected &&
 143        (
 144                __git_dir="$ROOT/otherrepo/.git" &&
 145                __git_find_repo_path &&
 146                echo "$__git_repo_path" >"$actual"
 147        ) &&
 148        test_cmp expected "$actual"
 149'
 150
 151test_expect_success '__git_find_repo_path - .git directory in cwd' '
 152        echo ".git" >expected &&
 153        (
 154                __git_find_repo_path &&
 155                echo "$__git_repo_path" >"$actual"
 156        ) &&
 157        test_cmp expected "$actual"
 158'
 159
 160test_expect_success '__git_find_repo_path - .git directory in parent' '
 161        echo "$ROOT/.git" >expected &&
 162        (
 163                cd subdir/subsubdir &&
 164                __git_find_repo_path &&
 165                echo "$__git_repo_path" >"$actual"
 166        ) &&
 167        test_cmp expected "$actual"
 168'
 169
 170test_expect_success '__git_find_repo_path - cwd is a .git directory' '
 171        echo "." >expected &&
 172        (
 173                cd .git &&
 174                __git_find_repo_path &&
 175                echo "$__git_repo_path" >"$actual"
 176        ) &&
 177        test_cmp expected "$actual"
 178'
 179
 180test_expect_success '__git_find_repo_path - parent is a .git directory' '
 181        echo "$ROOT/.git" >expected &&
 182        (
 183                cd .git/refs/heads &&
 184                __git_find_repo_path &&
 185                echo "$__git_repo_path" >"$actual"
 186        ) &&
 187        test_cmp expected "$actual"
 188'
 189
 190test_expect_success '__git_find_repo_path - $GIT_DIR set while .git directory in cwd' '
 191        echo "$ROOT/otherrepo/.git" >expected &&
 192        (
 193                GIT_DIR="$ROOT/otherrepo/.git" &&
 194                export GIT_DIR &&
 195                __git_find_repo_path &&
 196                echo "$__git_repo_path" >"$actual"
 197        ) &&
 198        test_cmp expected "$actual"
 199'
 200
 201test_expect_success '__git_find_repo_path - $GIT_DIR set while .git directory in parent' '
 202        echo "$ROOT/otherrepo/.git" >expected &&
 203        (
 204                GIT_DIR="$ROOT/otherrepo/.git" &&
 205                export GIT_DIR &&
 206                cd subdir &&
 207                __git_find_repo_path &&
 208                echo "$__git_repo_path" >"$actual"
 209        ) &&
 210        test_cmp expected "$actual"
 211'
 212
 213test_expect_success '__git_find_repo_path - from command line while "git -C"' '
 214        echo "$ROOT/.git" >expected &&
 215        (
 216                __git_dir="$ROOT/.git" &&
 217                __git_C_args=(-C otherrepo) &&
 218                __git_find_repo_path &&
 219                echo "$__git_repo_path" >"$actual"
 220        ) &&
 221        test_cmp expected "$actual"
 222'
 223
 224test_expect_success '__git_find_repo_path - 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                __git_find_repo_path &&
 231                echo "$__git_repo_path" >"$actual"
 232        ) &&
 233        test_cmp expected "$actual"
 234'
 235
 236test_expect_success '__git_find_repo_path - $GIT_DIR set while "git -C"' '
 237        echo "$ROOT/.git" >expected &&
 238        (
 239                GIT_DIR="$ROOT/.git" &&
 240                export GIT_DIR &&
 241                __git_C_args=(-C otherrepo) &&
 242                __git_find_repo_path &&
 243                echo "$__git_repo_path" >"$actual"
 244        ) &&
 245        test_cmp expected "$actual"
 246'
 247
 248test_expect_success '__git_find_repo_path - relative dir in $GIT_DIR and "git -C"' '
 249        echo "$ROOT/otherrepo/.git" >expected &&
 250        (
 251                cd subdir &&
 252                GIT_DIR="otherrepo/.git" &&
 253                export GIT_DIR &&
 254                __git_C_args=(-C ..) &&
 255                __git_find_repo_path &&
 256                echo "$__git_repo_path" >"$actual"
 257        ) &&
 258        test_cmp expected "$actual"
 259'
 260
 261test_expect_success '__git_find_repo_path - "git -C" while .git directory in cwd' '
 262        echo "$ROOT/otherrepo/.git" >expected &&
 263        (
 264                __git_C_args=(-C otherrepo) &&
 265                __git_find_repo_path &&
 266                echo "$__git_repo_path" >"$actual"
 267        ) &&
 268        test_cmp expected "$actual"
 269'
 270
 271test_expect_success '__git_find_repo_path - "git -C" while cwd is a .git directory' '
 272        echo "$ROOT/otherrepo/.git" >expected &&
 273        (
 274                cd .git &&
 275                __git_C_args=(-C .. -C otherrepo) &&
 276                __git_find_repo_path &&
 277                echo "$__git_repo_path" >"$actual"
 278        ) &&
 279        test_cmp expected "$actual"
 280'
 281
 282test_expect_success '__git_find_repo_path - "git -C" while .git directory in parent' '
 283        echo "$ROOT/otherrepo/.git" >expected &&
 284        (
 285                cd subdir &&
 286                __git_C_args=(-C .. -C otherrepo) &&
 287                __git_find_repo_path &&
 288                echo "$__git_repo_path" >"$actual"
 289        ) &&
 290        test_cmp expected "$actual"
 291'
 292
 293test_expect_success '__git_find_repo_path - non-existing path in "git -C"' '
 294        (
 295                __git_C_args=(-C non-existing) &&
 296                test_must_fail __git_find_repo_path &&
 297                printf "$__git_repo_path" >"$actual"
 298        ) &&
 299        test_must_be_empty "$actual"
 300'
 301
 302test_expect_success '__git_find_repo_path - non-existing path in $__git_dir' '
 303        (
 304                __git_dir="non-existing" &&
 305                test_must_fail __git_find_repo_path &&
 306                printf "$__git_repo_path" >"$actual"
 307        ) &&
 308        test_must_be_empty "$actual"
 309'
 310
 311test_expect_success '__git_find_repo_path - non-existing $GIT_DIR' '
 312        (
 313                GIT_DIR="$ROOT/non-existing" &&
 314                export GIT_DIR &&
 315                test_must_fail __git_find_repo_path &&
 316                printf "$__git_repo_path" >"$actual"
 317        ) &&
 318        test_must_be_empty "$actual"
 319'
 320
 321test_expect_success '__git_find_repo_path - gitfile in cwd' '
 322        echo "$ROOT/otherrepo/.git" >expected &&
 323        echo "gitdir: $ROOT/otherrepo/.git" >subdir/.git &&
 324        test_when_finished "rm -f subdir/.git" &&
 325        (
 326                cd subdir &&
 327                __git_find_repo_path &&
 328                echo "$__git_repo_path" >"$actual"
 329        ) &&
 330        test_cmp expected "$actual"
 331'
 332
 333test_expect_success '__git_find_repo_path - gitfile in parent' '
 334        echo "$ROOT/otherrepo/.git" >expected &&
 335        echo "gitdir: $ROOT/otherrepo/.git" >subdir/.git &&
 336        test_when_finished "rm -f subdir/.git" &&
 337        (
 338                cd subdir/subsubdir &&
 339                __git_find_repo_path &&
 340                echo "$__git_repo_path" >"$actual"
 341        ) &&
 342        test_cmp expected "$actual"
 343'
 344
 345test_expect_success SYMLINKS '__git_find_repo_path - resulting path avoids symlinks' '
 346        echo "$ROOT/otherrepo/.git" >expected &&
 347        mkdir otherrepo/dir &&
 348        test_when_finished "rm -rf otherrepo/dir" &&
 349        ln -s otherrepo/dir link &&
 350        test_when_finished "rm -f link" &&
 351        (
 352                cd link &&
 353                __git_find_repo_path &&
 354                echo "$__git_repo_path" >"$actual"
 355        ) &&
 356        test_cmp expected "$actual"
 357'
 358
 359test_expect_success '__git_find_repo_path - not a git repository' '
 360        (
 361                cd non-repo &&
 362                GIT_CEILING_DIRECTORIES="$ROOT" &&
 363                export GIT_CEILING_DIRECTORIES &&
 364                test_must_fail __git_find_repo_path &&
 365                printf "$__git_repo_path" >"$actual"
 366        ) &&
 367        test_must_be_empty "$actual"
 368'
 369
 370test_expect_success '__gitdir - finds repo' '
 371        echo "$ROOT/.git" >expected &&
 372        (
 373                cd subdir/subsubdir &&
 374                __gitdir >"$actual"
 375        ) &&
 376        test_cmp expected "$actual"
 377'
 378
 379
 380test_expect_success '__gitdir - returns error when cant find repo' '
 381        (
 382                __git_dir="non-existing" &&
 383                test_must_fail __gitdir >"$actual"
 384        ) &&
 385        test_must_be_empty "$actual"
 386'
 387
 388test_expect_success '__gitdir - repo as argument' '
 389        echo "otherrepo/.git" >expected &&
 390        (
 391                __gitdir "otherrepo" >"$actual"
 392        ) &&
 393        test_cmp expected "$actual"
 394'
 395
 396test_expect_success '__gitdir - remote as argument' '
 397        echo "remote" >expected &&
 398        (
 399                __gitdir "remote" >"$actual"
 400        ) &&
 401        test_cmp expected "$actual"
 402'
 403
 404
 405test_expect_success '__git_dequote - plain unquoted word' '
 406        __git_dequote unquoted-word &&
 407        verbose test unquoted-word = "$dequoted_word"
 408'
 409
 410# input:    b\a\c\k\'\\\"s\l\a\s\h\es
 411# expected: back'\"slashes
 412test_expect_success '__git_dequote - backslash escaped' '
 413        __git_dequote "b\a\c\k\\'\''\\\\\\\"s\l\a\s\h\es" &&
 414        verbose test "back'\''\\\"slashes" = "$dequoted_word"
 415'
 416
 417# input:    sin'gle\' '"quo'ted
 418# expected: single\ "quoted
 419test_expect_success '__git_dequote - single quoted' '
 420        __git_dequote "'"sin'gle\\\\' '\\\"quo'ted"'" &&
 421        verbose test '\''single\ "quoted'\'' = "$dequoted_word"
 422'
 423
 424# input:    dou"ble\\" "\"\quot"ed
 425# expected: double\ "\quoted
 426test_expect_success '__git_dequote - double quoted' '
 427        __git_dequote '\''dou"ble\\" "\"\quot"ed'\'' &&
 428        verbose test '\''double\ "\quoted'\'' = "$dequoted_word"
 429'
 430
 431# input: 'open single quote
 432test_expect_success '__git_dequote - open single quote' '
 433        __git_dequote "'\''open single quote" &&
 434        verbose test "open single quote" = "$dequoted_word"
 435'
 436
 437# input: "open double quote
 438test_expect_success '__git_dequote - open double quote' '
 439        __git_dequote "\"open double quote" &&
 440        verbose test "open double quote" = "$dequoted_word"
 441'
 442
 443
 444test_expect_success '__gitcomp_direct - puts everything into COMPREPLY as-is' '
 445        sed -e "s/Z$//g" >expected <<-EOF &&
 446        with-trailing-space Z
 447        without-trailing-spaceZ
 448        --option Z
 449        --option=Z
 450        $invalid_variable_name Z
 451        EOF
 452        (
 453                cur=should_be_ignored &&
 454                __gitcomp_direct "$(cat expected)" &&
 455                print_comp
 456        ) &&
 457        test_cmp expected out
 458'
 459
 460test_expect_success '__gitcomp - trailing space - options' '
 461        test_gitcomp "--re" "--dry-run --reuse-message= --reedit-message=
 462                --reset-author" <<-EOF
 463        --reuse-message=Z
 464        --reedit-message=Z
 465        --reset-author Z
 466        EOF
 467'
 468
 469test_expect_success '__gitcomp - trailing space - config keys' '
 470        test_gitcomp "br" "branch. branch.autosetupmerge
 471                branch.autosetuprebase browser." <<-\EOF
 472        branch.Z
 473        branch.autosetupmerge Z
 474        branch.autosetuprebase Z
 475        browser.Z
 476        EOF
 477'
 478
 479test_expect_success '__gitcomp - option parameter' '
 480        test_gitcomp "--strategy=re" "octopus ours recursive resolve subtree" \
 481                "" "re" <<-\EOF
 482        recursive Z
 483        resolve Z
 484        EOF
 485'
 486
 487test_expect_success '__gitcomp - prefix' '
 488        test_gitcomp "branch.me" "remote merge mergeoptions rebase" \
 489                "branch.maint." "me" <<-\EOF
 490        branch.maint.merge Z
 491        branch.maint.mergeoptions Z
 492        EOF
 493'
 494
 495test_expect_success '__gitcomp - suffix' '
 496        test_gitcomp "branch.me" "master maint next pu" "branch." \
 497                "ma" "." <<-\EOF
 498        branch.master.Z
 499        branch.maint.Z
 500        EOF
 501'
 502
 503test_expect_success '__gitcomp - doesnt fail because of invalid variable name' '
 504        __gitcomp "$invalid_variable_name"
 505'
 506
 507read -r -d "" refs <<-\EOF
 508maint
 509master
 510next
 511pu
 512EOF
 513
 514test_expect_success '__gitcomp_nl - trailing space' '
 515        test_gitcomp_nl "m" "$refs" <<-EOF
 516        maint Z
 517        master Z
 518        EOF
 519'
 520
 521test_expect_success '__gitcomp_nl - prefix' '
 522        test_gitcomp_nl "--fixup=m" "$refs" "--fixup=" "m" <<-EOF
 523        --fixup=maint Z
 524        --fixup=master Z
 525        EOF
 526'
 527
 528test_expect_success '__gitcomp_nl - suffix' '
 529        test_gitcomp_nl "branch.ma" "$refs" "branch." "ma" "." <<-\EOF
 530        branch.maint.Z
 531        branch.master.Z
 532        EOF
 533'
 534
 535test_expect_success '__gitcomp_nl - no suffix' '
 536        test_gitcomp_nl "ma" "$refs" "" "ma" "" <<-\EOF
 537        maintZ
 538        masterZ
 539        EOF
 540'
 541
 542test_expect_success '__gitcomp_nl - doesnt fail because of invalid variable name' '
 543        __gitcomp_nl "$invalid_variable_name"
 544'
 545
 546test_expect_success '__git_remotes - list remotes from $GIT_DIR/remotes and from config file' '
 547        cat >expect <<-EOF &&
 548        remote_from_file_1
 549        remote_from_file_2
 550        remote_in_config_1
 551        remote_in_config_2
 552        EOF
 553        test_when_finished "rm -rf .git/remotes" &&
 554        mkdir -p .git/remotes &&
 555        >.git/remotes/remote_from_file_1 &&
 556        >.git/remotes/remote_from_file_2 &&
 557        test_when_finished "git remote remove remote_in_config_1" &&
 558        git remote add remote_in_config_1 git://remote_1 &&
 559        test_when_finished "git remote remove remote_in_config_2" &&
 560        git remote add remote_in_config_2 git://remote_2 &&
 561        (
 562                __git_remotes >actual
 563        ) &&
 564        test_cmp expect actual
 565'
 566
 567test_expect_success '__git_is_configured_remote' '
 568        test_when_finished "git remote remove remote_1" &&
 569        git remote add remote_1 git://remote_1 &&
 570        test_when_finished "git remote remove remote_2" &&
 571        git remote add remote_2 git://remote_2 &&
 572        (
 573                verbose __git_is_configured_remote remote_2 &&
 574                test_must_fail __git_is_configured_remote non-existent
 575        )
 576'
 577
 578test_expect_success 'setup for ref completion' '
 579        git commit --allow-empty -m initial &&
 580        git branch matching-branch &&
 581        git tag matching-tag &&
 582        (
 583                cd otherrepo &&
 584                git commit --allow-empty -m initial &&
 585                git branch -m master master-in-other &&
 586                git branch branch-in-other &&
 587                git tag tag-in-other
 588        ) &&
 589        git remote add other "$ROOT/otherrepo/.git" &&
 590        git fetch --no-tags other &&
 591        rm -f .git/FETCH_HEAD &&
 592        git init thirdrepo
 593'
 594
 595test_expect_success '__git_refs - simple' '
 596        cat >expected <<-EOF &&
 597        HEAD
 598        master
 599        matching-branch
 600        other/branch-in-other
 601        other/master-in-other
 602        matching-tag
 603        EOF
 604        (
 605                cur= &&
 606                __git_refs >"$actual"
 607        ) &&
 608        test_cmp expected "$actual"
 609'
 610
 611test_expect_success '__git_refs - full refs' '
 612        cat >expected <<-EOF &&
 613        refs/heads/master
 614        refs/heads/matching-branch
 615        refs/remotes/other/branch-in-other
 616        refs/remotes/other/master-in-other
 617        refs/tags/matching-tag
 618        EOF
 619        (
 620                cur=refs/heads/ &&
 621                __git_refs >"$actual"
 622        ) &&
 623        test_cmp expected "$actual"
 624'
 625
 626test_expect_success '__git_refs - repo given on the command line' '
 627        cat >expected <<-EOF &&
 628        HEAD
 629        branch-in-other
 630        master-in-other
 631        tag-in-other
 632        EOF
 633        (
 634                __git_dir="$ROOT/otherrepo/.git" &&
 635                cur= &&
 636                __git_refs >"$actual"
 637        ) &&
 638        test_cmp expected "$actual"
 639'
 640
 641test_expect_success '__git_refs - remote on local file system' '
 642        cat >expected <<-EOF &&
 643        HEAD
 644        branch-in-other
 645        master-in-other
 646        tag-in-other
 647        EOF
 648        (
 649                cur= &&
 650                __git_refs otherrepo >"$actual"
 651        ) &&
 652        test_cmp expected "$actual"
 653'
 654
 655test_expect_success '__git_refs - remote on local file system - full refs' '
 656        cat >expected <<-EOF &&
 657        refs/heads/branch-in-other
 658        refs/heads/master-in-other
 659        refs/tags/tag-in-other
 660        EOF
 661        (
 662                cur=refs/ &&
 663                __git_refs otherrepo >"$actual"
 664        ) &&
 665        test_cmp expected "$actual"
 666'
 667
 668test_expect_success '__git_refs - configured remote' '
 669        cat >expected <<-EOF &&
 670        HEAD
 671        branch-in-other
 672        master-in-other
 673        EOF
 674        (
 675                cur= &&
 676                __git_refs other >"$actual"
 677        ) &&
 678        test_cmp expected "$actual"
 679'
 680
 681test_expect_success '__git_refs - configured remote - full refs' '
 682        cat >expected <<-EOF &&
 683        HEAD
 684        refs/heads/branch-in-other
 685        refs/heads/master-in-other
 686        refs/tags/tag-in-other
 687        EOF
 688        (
 689                cur=refs/ &&
 690                __git_refs other >"$actual"
 691        ) &&
 692        test_cmp expected "$actual"
 693'
 694
 695test_expect_success '__git_refs - configured remote - repo given on the command line' '
 696        cat >expected <<-EOF &&
 697        HEAD
 698        branch-in-other
 699        master-in-other
 700        EOF
 701        (
 702                cd thirdrepo &&
 703                __git_dir="$ROOT/.git" &&
 704                cur= &&
 705                __git_refs other >"$actual"
 706        ) &&
 707        test_cmp expected "$actual"
 708'
 709
 710test_expect_success '__git_refs - configured remote - full refs - repo given on the command line' '
 711        cat >expected <<-EOF &&
 712        HEAD
 713        refs/heads/branch-in-other
 714        refs/heads/master-in-other
 715        refs/tags/tag-in-other
 716        EOF
 717        (
 718                cd thirdrepo &&
 719                __git_dir="$ROOT/.git" &&
 720                cur=refs/ &&
 721                __git_refs other >"$actual"
 722        ) &&
 723        test_cmp expected "$actual"
 724'
 725
 726test_expect_success '__git_refs - configured remote - remote name matches a directory' '
 727        cat >expected <<-EOF &&
 728        HEAD
 729        branch-in-other
 730        master-in-other
 731        EOF
 732        mkdir other &&
 733        test_when_finished "rm -rf other" &&
 734        (
 735                cur= &&
 736                __git_refs other >"$actual"
 737        ) &&
 738        test_cmp expected "$actual"
 739'
 740
 741test_expect_success '__git_refs - URL remote' '
 742        cat >expected <<-EOF &&
 743        HEAD
 744        branch-in-other
 745        master-in-other
 746        tag-in-other
 747        EOF
 748        (
 749                cur= &&
 750                __git_refs "file://$ROOT/otherrepo/.git" >"$actual"
 751        ) &&
 752        test_cmp expected "$actual"
 753'
 754
 755test_expect_success '__git_refs - URL remote - full refs' '
 756        cat >expected <<-EOF &&
 757        HEAD
 758        refs/heads/branch-in-other
 759        refs/heads/master-in-other
 760        refs/tags/tag-in-other
 761        EOF
 762        (
 763                cur=refs/ &&
 764                __git_refs "file://$ROOT/otherrepo/.git" >"$actual"
 765        ) &&
 766        test_cmp expected "$actual"
 767'
 768
 769test_expect_success '__git_refs - non-existing remote' '
 770        (
 771                cur= &&
 772                __git_refs non-existing >"$actual"
 773        ) &&
 774        test_must_be_empty "$actual"
 775'
 776
 777test_expect_success '__git_refs - non-existing remote - full refs' '
 778        (
 779                cur=refs/ &&
 780                __git_refs non-existing >"$actual"
 781        ) &&
 782        test_must_be_empty "$actual"
 783'
 784
 785test_expect_success '__git_refs - non-existing URL remote' '
 786        (
 787                cur= &&
 788                __git_refs "file://$ROOT/non-existing" >"$actual"
 789        ) &&
 790        test_must_be_empty "$actual"
 791'
 792
 793test_expect_success '__git_refs - non-existing URL remote - full refs' '
 794        (
 795                cur=refs/ &&
 796                __git_refs "file://$ROOT/non-existing" >"$actual"
 797        ) &&
 798        test_must_be_empty "$actual"
 799'
 800
 801test_expect_success '__git_refs - not in a git repository' '
 802        (
 803                GIT_CEILING_DIRECTORIES="$ROOT" &&
 804                export GIT_CEILING_DIRECTORIES &&
 805                cd subdir &&
 806                cur= &&
 807                __git_refs >"$actual"
 808        ) &&
 809        test_must_be_empty "$actual"
 810'
 811
 812test_expect_success '__git_refs - unique remote branches for git checkout DWIMery' '
 813        cat >expected <<-EOF &&
 814        HEAD
 815        master
 816        matching-branch
 817        other/ambiguous
 818        other/branch-in-other
 819        other/master-in-other
 820        remote/ambiguous
 821        remote/branch-in-remote
 822        matching-tag
 823        branch-in-other
 824        branch-in-remote
 825        master-in-other
 826        EOF
 827        for remote_ref in refs/remotes/other/ambiguous \
 828                refs/remotes/remote/ambiguous \
 829                refs/remotes/remote/branch-in-remote
 830        do
 831                git update-ref $remote_ref master &&
 832                test_when_finished "git update-ref -d $remote_ref"
 833        done &&
 834        (
 835                cur= &&
 836                __git_refs "" 1 >"$actual"
 837        ) &&
 838        test_cmp expected "$actual"
 839'
 840
 841test_expect_success '__git_refs - after --opt=' '
 842        cat >expected <<-EOF &&
 843        HEAD
 844        master
 845        matching-branch
 846        other/branch-in-other
 847        other/master-in-other
 848        matching-tag
 849        EOF
 850        (
 851                cur="--opt=" &&
 852                __git_refs "" "" "" "" >"$actual"
 853        ) &&
 854        test_cmp expected "$actual"
 855'
 856
 857test_expect_success '__git_refs - after --opt= - full refs' '
 858        cat >expected <<-EOF &&
 859        refs/heads/master
 860        refs/heads/matching-branch
 861        refs/remotes/other/branch-in-other
 862        refs/remotes/other/master-in-other
 863        refs/tags/matching-tag
 864        EOF
 865        (
 866                cur="--opt=refs/" &&
 867                __git_refs "" "" "" refs/ >"$actual"
 868        ) &&
 869        test_cmp expected "$actual"
 870'
 871
 872test_expect_success '__git refs - exluding refs' '
 873        cat >expected <<-EOF &&
 874        ^HEAD
 875        ^master
 876        ^matching-branch
 877        ^other/branch-in-other
 878        ^other/master-in-other
 879        ^matching-tag
 880        EOF
 881        (
 882                cur=^ &&
 883                __git_refs >"$actual"
 884        ) &&
 885        test_cmp expected "$actual"
 886'
 887
 888test_expect_success '__git refs - exluding full refs' '
 889        cat >expected <<-EOF &&
 890        ^refs/heads/master
 891        ^refs/heads/matching-branch
 892        ^refs/remotes/other/branch-in-other
 893        ^refs/remotes/other/master-in-other
 894        ^refs/tags/matching-tag
 895        EOF
 896        (
 897                cur=^refs/ &&
 898                __git_refs >"$actual"
 899        ) &&
 900        test_cmp expected "$actual"
 901'
 902
 903test_expect_success 'setup for filtering matching refs' '
 904        git branch matching/branch &&
 905        git tag matching/tag &&
 906        git -C otherrepo branch matching/branch-in-other &&
 907        git fetch --no-tags other &&
 908        rm -f .git/FETCH_HEAD
 909'
 910
 911test_expect_success '__git_refs - dont filter refs unless told so' '
 912        cat >expected <<-EOF &&
 913        HEAD
 914        master
 915        matching-branch
 916        matching/branch
 917        other/branch-in-other
 918        other/master-in-other
 919        other/matching/branch-in-other
 920        matching-tag
 921        matching/tag
 922        EOF
 923        (
 924                cur=master &&
 925                __git_refs >"$actual"
 926        ) &&
 927        test_cmp expected "$actual"
 928'
 929
 930test_expect_success '__git_refs - only matching refs' '
 931        cat >expected <<-EOF &&
 932        matching-branch
 933        matching/branch
 934        matching-tag
 935        matching/tag
 936        EOF
 937        (
 938                cur=mat &&
 939                __git_refs "" "" "" "$cur" >"$actual"
 940        ) &&
 941        test_cmp expected "$actual"
 942'
 943
 944test_expect_success '__git_refs - only matching refs - full refs' '
 945        cat >expected <<-EOF &&
 946        refs/heads/matching-branch
 947        refs/heads/matching/branch
 948        EOF
 949        (
 950                cur=refs/heads/mat &&
 951                __git_refs "" "" "" "$cur" >"$actual"
 952        ) &&
 953        test_cmp expected "$actual"
 954'
 955
 956test_expect_success '__git_refs - only matching refs - remote on local file system' '
 957        cat >expected <<-EOF &&
 958        master-in-other
 959        matching/branch-in-other
 960        EOF
 961        (
 962                cur=ma &&
 963                __git_refs otherrepo "" "" "$cur" >"$actual"
 964        ) &&
 965        test_cmp expected "$actual"
 966'
 967
 968test_expect_success '__git_refs - only matching refs - configured remote' '
 969        cat >expected <<-EOF &&
 970        master-in-other
 971        matching/branch-in-other
 972        EOF
 973        (
 974                cur=ma &&
 975                __git_refs other "" "" "$cur" >"$actual"
 976        ) &&
 977        test_cmp expected "$actual"
 978'
 979
 980test_expect_success '__git_refs - only matching refs - remote - full refs' '
 981        cat >expected <<-EOF &&
 982        refs/heads/master-in-other
 983        refs/heads/matching/branch-in-other
 984        EOF
 985        (
 986                cur=refs/heads/ma &&
 987                __git_refs other "" "" "$cur" >"$actual"
 988        ) &&
 989        test_cmp expected "$actual"
 990'
 991
 992test_expect_success '__git_refs - only matching refs - checkout DWIMery' '
 993        cat >expected <<-EOF &&
 994        matching-branch
 995        matching/branch
 996        matching-tag
 997        matching/tag
 998        matching/branch-in-other
 999        EOF
1000        for remote_ref in refs/remotes/other/ambiguous \
1001                refs/remotes/remote/ambiguous \
1002                refs/remotes/remote/branch-in-remote
1003        do
1004                git update-ref $remote_ref master &&
1005                test_when_finished "git update-ref -d $remote_ref"
1006        done &&
1007        (
1008                cur=mat &&
1009                __git_refs "" 1 "" "$cur" >"$actual"
1010        ) &&
1011        test_cmp expected "$actual"
1012'
1013
1014test_expect_success 'teardown after filtering matching refs' '
1015        git branch -d matching/branch &&
1016        git tag -d matching/tag &&
1017        git update-ref -d refs/remotes/other/matching/branch-in-other &&
1018        git -C otherrepo branch -D matching/branch-in-other
1019'
1020
1021test_expect_success '__git_refs - for-each-ref format specifiers in prefix' '
1022        cat >expected <<-EOF &&
1023        evil-%%-%42-%(refname)..master
1024        EOF
1025        (
1026                cur="evil-%%-%42-%(refname)..mas" &&
1027                __git_refs "" "" "evil-%%-%42-%(refname).." mas >"$actual"
1028        ) &&
1029        test_cmp expected "$actual"
1030'
1031
1032test_expect_success '__git_complete_refs - simple' '
1033        sed -e "s/Z$//" >expected <<-EOF &&
1034        HEAD Z
1035        master Z
1036        matching-branch Z
1037        other/branch-in-other Z
1038        other/master-in-other Z
1039        matching-tag Z
1040        EOF
1041        (
1042                cur= &&
1043                __git_complete_refs &&
1044                print_comp
1045        ) &&
1046        test_cmp expected out
1047'
1048
1049test_expect_success '__git_complete_refs - matching' '
1050        sed -e "s/Z$//" >expected <<-EOF &&
1051        matching-branch Z
1052        matching-tag Z
1053        EOF
1054        (
1055                cur=mat &&
1056                __git_complete_refs &&
1057                print_comp
1058        ) &&
1059        test_cmp expected out
1060'
1061
1062test_expect_success '__git_complete_refs - remote' '
1063        sed -e "s/Z$//" >expected <<-EOF &&
1064        HEAD Z
1065        branch-in-other Z
1066        master-in-other Z
1067        EOF
1068        (
1069                cur=
1070                __git_complete_refs --remote=other &&
1071                print_comp
1072        ) &&
1073        test_cmp expected out
1074'
1075
1076test_expect_success '__git_complete_refs - track' '
1077        sed -e "s/Z$//" >expected <<-EOF &&
1078        HEAD Z
1079        master Z
1080        matching-branch Z
1081        other/branch-in-other Z
1082        other/master-in-other Z
1083        matching-tag Z
1084        branch-in-other Z
1085        master-in-other Z
1086        EOF
1087        (
1088                cur=
1089                __git_complete_refs --track &&
1090                print_comp
1091        ) &&
1092        test_cmp expected out
1093'
1094
1095test_expect_success '__git_complete_refs - current word' '
1096        sed -e "s/Z$//" >expected <<-EOF &&
1097        matching-branch Z
1098        matching-tag Z
1099        EOF
1100        (
1101                cur="--option=mat" &&
1102                __git_complete_refs --cur="${cur#*=}" &&
1103                print_comp
1104        ) &&
1105        test_cmp expected out
1106'
1107
1108test_expect_success '__git_complete_refs - prefix' '
1109        sed -e "s/Z$//" >expected <<-EOF &&
1110        v1.0..matching-branch Z
1111        v1.0..matching-tag Z
1112        EOF
1113        (
1114                cur=v1.0..mat &&
1115                __git_complete_refs --pfx=v1.0.. --cur=mat &&
1116                print_comp
1117        ) &&
1118        test_cmp expected out
1119'
1120
1121test_expect_success '__git_complete_refs - suffix' '
1122        cat >expected <<-EOF &&
1123        HEAD.
1124        master.
1125        matching-branch.
1126        other/branch-in-other.
1127        other/master-in-other.
1128        matching-tag.
1129        EOF
1130        (
1131                cur= &&
1132                __git_complete_refs --sfx=. &&
1133                print_comp
1134        ) &&
1135        test_cmp expected out
1136'
1137
1138test_expect_success '__git_complete_fetch_refspecs - simple' '
1139        sed -e "s/Z$//" >expected <<-EOF &&
1140        HEAD:HEAD Z
1141        branch-in-other:branch-in-other Z
1142        master-in-other:master-in-other Z
1143        EOF
1144        (
1145                cur= &&
1146                __git_complete_fetch_refspecs other &&
1147                print_comp
1148        ) &&
1149        test_cmp expected out
1150'
1151
1152test_expect_success '__git_complete_fetch_refspecs - matching' '
1153        sed -e "s/Z$//" >expected <<-EOF &&
1154        branch-in-other:branch-in-other Z
1155        EOF
1156        (
1157                cur=br &&
1158                __git_complete_fetch_refspecs other "" br &&
1159                print_comp
1160        ) &&
1161        test_cmp expected out
1162'
1163
1164test_expect_success '__git_complete_fetch_refspecs - prefix' '
1165        sed -e "s/Z$//" >expected <<-EOF &&
1166        +HEAD:HEAD Z
1167        +branch-in-other:branch-in-other Z
1168        +master-in-other:master-in-other Z
1169        EOF
1170        (
1171                cur="+" &&
1172                __git_complete_fetch_refspecs other "+" ""  &&
1173                print_comp
1174        ) &&
1175        test_cmp expected out
1176'
1177
1178test_expect_success '__git_complete_fetch_refspecs - fully qualified' '
1179        sed -e "s/Z$//" >expected <<-EOF &&
1180        refs/heads/branch-in-other:refs/heads/branch-in-other Z
1181        refs/heads/master-in-other:refs/heads/master-in-other Z
1182        refs/tags/tag-in-other:refs/tags/tag-in-other Z
1183        EOF
1184        (
1185                cur=refs/ &&
1186                __git_complete_fetch_refspecs other "" refs/ &&
1187                print_comp
1188        ) &&
1189        test_cmp expected out
1190'
1191
1192test_expect_success '__git_complete_fetch_refspecs - fully qualified & prefix' '
1193        sed -e "s/Z$//" >expected <<-EOF &&
1194        +refs/heads/branch-in-other:refs/heads/branch-in-other Z
1195        +refs/heads/master-in-other:refs/heads/master-in-other Z
1196        +refs/tags/tag-in-other:refs/tags/tag-in-other Z
1197        EOF
1198        (
1199                cur=+refs/ &&
1200                __git_complete_fetch_refspecs other + refs/ &&
1201                print_comp
1202        ) &&
1203        test_cmp expected out
1204'
1205
1206test_expect_success 'teardown after ref completion' '
1207        git branch -d matching-branch &&
1208        git tag -d matching-tag &&
1209        git remote remove other
1210'
1211
1212test_expect_success '__git_get_config_variables' '
1213        cat >expect <<-EOF &&
1214        name-1
1215        name-2
1216        EOF
1217        test_config interesting.name-1 good &&
1218        test_config interesting.name-2 good &&
1219        test_config subsection.interesting.name-3 bad &&
1220        __git_get_config_variables interesting >actual &&
1221        test_cmp expect actual
1222'
1223
1224test_expect_success '__git_pretty_aliases' '
1225        cat >expect <<-EOF &&
1226        author
1227        hash
1228        EOF
1229        test_config pretty.author "%an %ae" &&
1230        test_config pretty.hash %H &&
1231        __git_pretty_aliases >actual &&
1232        test_cmp expect actual
1233'
1234
1235test_expect_success '__git_aliases' '
1236        cat >expect <<-EOF &&
1237        ci
1238        co
1239        EOF
1240        test_config alias.ci commit &&
1241        test_config alias.co checkout &&
1242        __git_aliases >actual &&
1243        test_cmp expect actual
1244'
1245
1246test_expect_success 'basic' '
1247        run_completion "git " &&
1248        # built-in
1249        grep -q "^add \$" out &&
1250        # script
1251        grep -q "^filter-branch \$" out &&
1252        # plumbing
1253        ! grep -q "^ls-files \$" out &&
1254
1255        run_completion "git f" &&
1256        ! grep -q -v "^f" out
1257'
1258
1259test_expect_success 'double dash "git" itself' '
1260        test_completion "git --" <<-\EOF
1261        --paginate Z
1262        --no-pager Z
1263        --git-dir=
1264        --bare Z
1265        --version Z
1266        --exec-path Z
1267        --exec-path=
1268        --html-path Z
1269        --man-path Z
1270        --info-path Z
1271        --work-tree=
1272        --namespace=
1273        --no-replace-objects Z
1274        --help Z
1275        EOF
1276'
1277
1278test_expect_success 'double dash "git checkout"' '
1279        test_completion "git checkout --" <<-\EOF
1280        --quiet Z
1281        --detach Z
1282        --track Z
1283        --orphan=Z
1284        --ours Z
1285        --theirs Z
1286        --merge Z
1287        --conflict=Z
1288        --patch Z
1289        --ignore-skip-worktree-bits Z
1290        --ignore-other-worktrees Z
1291        --recurse-submodules Z
1292        --progress Z
1293        --no-track Z
1294        --no-recurse-submodules Z
1295        EOF
1296'
1297
1298test_expect_success 'general options' '
1299        test_completion "git --ver" "--version " &&
1300        test_completion "git --hel" "--help " &&
1301        test_completion "git --exe" <<-\EOF &&
1302        --exec-path Z
1303        --exec-path=
1304        EOF
1305        test_completion "git --htm" "--html-path " &&
1306        test_completion "git --pag" "--paginate " &&
1307        test_completion "git --no-p" "--no-pager " &&
1308        test_completion "git --git" "--git-dir=" &&
1309        test_completion "git --wor" "--work-tree=" &&
1310        test_completion "git --nam" "--namespace=" &&
1311        test_completion "git --bar" "--bare " &&
1312        test_completion "git --inf" "--info-path " &&
1313        test_completion "git --no-r" "--no-replace-objects "
1314'
1315
1316test_expect_success 'general options plus command' '
1317        test_completion "git --version check" "checkout " &&
1318        test_completion "git --paginate check" "checkout " &&
1319        test_completion "git --git-dir=foo check" "checkout " &&
1320        test_completion "git --bare check" "checkout " &&
1321        test_completion "git --exec-path=foo check" "checkout " &&
1322        test_completion "git --html-path check" "checkout " &&
1323        test_completion "git --no-pager check" "checkout " &&
1324        test_completion "git --work-tree=foo check" "checkout " &&
1325        test_completion "git --namespace=foo check" "checkout " &&
1326        test_completion "git --paginate check" "checkout " &&
1327        test_completion "git --info-path check" "checkout " &&
1328        test_completion "git --no-replace-objects check" "checkout " &&
1329        test_completion "git --git-dir some/path check" "checkout " &&
1330        test_completion "git -c conf.var=value check" "checkout " &&
1331        test_completion "git -C some/path check" "checkout " &&
1332        test_completion "git --work-tree some/path check" "checkout " &&
1333        test_completion "git --namespace name/space check" "checkout "
1334'
1335
1336test_expect_success 'git --help completion' '
1337        test_completion "git --help ad" "add " &&
1338        test_completion "git --help core" "core-tutorial "
1339'
1340
1341test_expect_success 'setup for integration tests' '
1342        echo content >file1 &&
1343        echo more >file2 &&
1344        git add file1 file2 &&
1345        git commit -m one &&
1346        git branch mybranch &&
1347        git tag mytag
1348'
1349
1350test_expect_success 'checkout completes ref names' '
1351        test_completion "git checkout m" <<-\EOF
1352        master Z
1353        mybranch Z
1354        mytag Z
1355        EOF
1356'
1357
1358test_expect_success 'git -C <path> checkout uses the right repo' '
1359        test_completion "git -C subdir -C subsubdir -C .. -C ../otherrepo checkout b" <<-\EOF
1360        branch-in-other Z
1361        EOF
1362'
1363
1364test_expect_success 'show completes all refs' '
1365        test_completion "git show m" <<-\EOF
1366        master Z
1367        mybranch Z
1368        mytag Z
1369        EOF
1370'
1371
1372test_expect_success '<ref>: completes paths' '
1373        test_completion "git show mytag:f" <<-\EOF
1374        file1 Z
1375        file2 Z
1376        EOF
1377'
1378
1379test_expect_success 'complete tree filename with spaces' '
1380        echo content >"name with spaces" &&
1381        git add "name with spaces" &&
1382        git commit -m spaces &&
1383        test_completion "git show HEAD:nam" <<-\EOF
1384        name with spaces Z
1385        EOF
1386'
1387
1388test_expect_success 'complete tree filename with metacharacters' '
1389        echo content >"name with \${meta}" &&
1390        git add "name with \${meta}" &&
1391        git commit -m meta &&
1392        test_completion "git show HEAD:nam" <<-\EOF
1393        name with ${meta} Z
1394        name with spaces Z
1395        EOF
1396'
1397
1398test_expect_success 'send-email' '
1399        test_completion "git send-email --cov" "--cover-letter " &&
1400        test_completion "git send-email ma" "master "
1401'
1402
1403test_expect_success 'complete files' '
1404        git init tmp && cd tmp &&
1405        test_when_finished "cd .. && rm -rf tmp" &&
1406
1407        echo "expected" > .gitignore &&
1408        echo "out" >> .gitignore &&
1409        echo "out_sorted" >> .gitignore &&
1410
1411        git add .gitignore &&
1412        test_completion "git commit " ".gitignore" &&
1413
1414        git commit -m ignore &&
1415
1416        touch new &&
1417        test_completion "git add " "new" &&
1418
1419        git add new &&
1420        git commit -a -m new &&
1421        test_completion "git add " "" &&
1422
1423        git mv new modified &&
1424        echo modify > modified &&
1425        test_completion "git add " "modified" &&
1426
1427        touch untracked &&
1428
1429        : TODO .gitignore should not be here &&
1430        test_completion "git rm " <<-\EOF &&
1431        .gitignore
1432        modified
1433        EOF
1434
1435        test_completion "git clean " "untracked" &&
1436
1437        : TODO .gitignore should not be here &&
1438        test_completion "git mv " <<-\EOF &&
1439        .gitignore
1440        modified
1441        EOF
1442
1443        mkdir dir &&
1444        touch dir/file-in-dir &&
1445        git add dir/file-in-dir &&
1446        git commit -m dir &&
1447
1448        mkdir untracked-dir &&
1449
1450        : TODO .gitignore should not be here &&
1451        test_completion "git mv modified " <<-\EOF &&
1452        .gitignore
1453        dir
1454        modified
1455        untracked
1456        untracked-dir
1457        EOF
1458
1459        test_completion "git commit " "modified" &&
1460
1461        : TODO .gitignore should not be here &&
1462        test_completion "git ls-files " <<-\EOF &&
1463        .gitignore
1464        dir
1465        modified
1466        EOF
1467
1468        touch momified &&
1469        test_completion "git add mom" "momified"
1470'
1471
1472# The next tests only care about how the completion script deals with
1473# unusual characters in path names.  By defining a custom completion
1474# function to list untracked files they won't be influenced by future
1475# changes of the completion functions of real git commands, and we
1476# don't have to bother with adding files to the index in these tests.
1477_git_test_path_comp ()
1478{
1479        __git_complete_index_file --others
1480}
1481
1482test_expect_success 'complete files - escaped characters on cmdline' '
1483        test_when_finished "rm -rf \"New|Dir\"" &&
1484        mkdir "New|Dir" &&
1485        >"New|Dir/New&File.c" &&
1486
1487        test_completion "git test-path-comp N" \
1488                        "New|Dir" &&    # Bash will turn this into "New\|Dir/"
1489        test_completion "git test-path-comp New\\|D" \
1490                        "New|Dir" &&
1491        test_completion "git test-path-comp New\\|Dir/N" \
1492                        "New|Dir/New&File.c" && # Bash will turn this into
1493                                                # "New\|Dir/New\&File.c "
1494        test_completion "git test-path-comp New\\|Dir/New\\&F" \
1495                        "New|Dir/New&File.c"
1496'
1497
1498test_expect_success 'complete files - quoted characters on cmdline' '
1499        test_when_finished "rm -r \"New(Dir\"" &&
1500        mkdir "New(Dir" &&
1501        >"New(Dir/New)File.c" &&
1502
1503        # Testing with an opening but without a corresponding closing
1504        # double quote is important.
1505        test_completion "git test-path-comp \"New(D" "New(Dir" &&
1506        test_completion "git test-path-comp \"New(Dir/New)F" \
1507                        "New(Dir/New)File.c"
1508'
1509
1510test_expect_success 'complete files - UTF-8 in ls-files output' '
1511        test_when_finished "rm -r árvíztűrő" &&
1512        mkdir árvíztűrő &&
1513        >"árvíztűrő/Сайн яваарай" &&
1514
1515        test_completion "git test-path-comp á" "árvíztűrő" &&
1516        test_completion "git test-path-comp árvíztűrő/С" \
1517                        "árvíztűrő/Сайн яваарай"
1518'
1519
1520# Testing with a path containing a backslash is important.
1521if test_have_prereq !MINGW &&
1522   mkdir 'New\Dir' 2>/dev/null &&
1523   touch 'New\Dir/New"File.c' 2>/dev/null
1524then
1525        test_set_prereq FUNNYNAMES_BS_DQ
1526else
1527        say "Your filesystem does not allow \\ and \" in filenames."
1528        rm -rf 'New\Dir'
1529fi
1530test_expect_success FUNNYNAMES_BS_DQ \
1531    'complete files - C-style escapes in ls-files output' '
1532        test_when_finished "rm -r \"New\\\\Dir\"" &&
1533
1534        test_completion "git test-path-comp N" "New\\Dir" &&
1535        test_completion "git test-path-comp New\\\\D" "New\\Dir" &&
1536        test_completion "git test-path-comp New\\\\Dir/N" \
1537                        "New\\Dir/New\"File.c" &&
1538        test_completion "git test-path-comp New\\\\Dir/New\\\"F" \
1539                        "New\\Dir/New\"File.c"
1540'
1541
1542if test_have_prereq !MINGW &&
1543   mkdir $'New\034Special\035Dir' 2>/dev/null &&
1544   touch $'New\034Special\035Dir/New\036Special\037File' 2>/dev/null
1545then
1546        test_set_prereq FUNNYNAMES_SEPARATORS
1547else
1548        say 'Your filesystem does not allow special separator characters (FS, GS, RS, US) in filenames.'
1549        rm -rf $'New\034Special\035Dir'
1550fi
1551test_expect_success FUNNYNAMES_SEPARATORS \
1552    'complete files - \nnn-escaped control characters in ls-files output' '
1553        test_when_finished "rm -r '$'New\034Special\035Dir''" &&
1554
1555        # Note: these will be literal separator characters on the cmdline.
1556        test_completion "git test-path-comp N" "'$'New\034Special\035Dir''" &&
1557        test_completion "git test-path-comp '$'New\034S''" \
1558                        "'$'New\034Special\035Dir''" &&
1559        test_completion "git test-path-comp '$'New\034Special\035Dir/''" \
1560                        "'$'New\034Special\035Dir/New\036Special\037File''" &&
1561        test_completion "git test-path-comp '$'New\034Special\035Dir/New\036S''" \
1562                        "'$'New\034Special\035Dir/New\036Special\037File''"
1563'
1564
1565test_expect_success FUNNYNAMES_BS_DQ \
1566    'complete files - removing repeated quoted path components' '
1567        test_when_finished rm -rf NewDir &&
1568        mkdir NewDir &&    # A dirname which in itself would not be quoted ...
1569        >NewDir/0-file &&
1570        >NewDir/1\"file && # ... but here the file makes the dirname quoted ...
1571        >NewDir/2-file &&
1572        >NewDir/3\"file && # ... and here, too.
1573
1574        # Still, we should only list it once.
1575        test_completion "git test-path-comp New" "NewDir"
1576'
1577
1578
1579test_expect_success "completion uses <cmd> completion for alias: !sh -c 'git <cmd> ...'" '
1580        test_config alias.co "!sh -c '"'"'git checkout ...'"'"'" &&
1581        test_completion "git co m" <<-\EOF
1582        master Z
1583        mybranch Z
1584        mytag Z
1585        EOF
1586'
1587
1588test_expect_success 'completion uses <cmd> completion for alias: !f () { VAR=val git <cmd> ... }' '
1589        test_config alias.co "!f () { VAR=val git checkout ... ; } f" &&
1590        test_completion "git co m" <<-\EOF
1591        master Z
1592        mybranch Z
1593        mytag Z
1594        EOF
1595'
1596
1597test_expect_success 'completion used <cmd> completion for alias: !f() { : git <cmd> ; ... }' '
1598        test_config alias.co "!f() { : git checkout ; if ... } f" &&
1599        test_completion "git co m" <<-\EOF
1600        master Z
1601        mybranch Z
1602        mytag Z
1603        EOF
1604'
1605
1606test_expect_success 'completion without explicit _git_xxx function' '
1607        test_completion "git version --" <<-\EOF
1608        --build-options Z
1609        EOF
1610'
1611
1612test_expect_failure 'complete with tilde expansion' '
1613        git init tmp && cd tmp &&
1614        test_when_finished "cd .. && rm -rf tmp" &&
1615
1616        touch ~/tmp/file &&
1617
1618        test_completion "git add ~/tmp/" "~/tmp/file"
1619'
1620
1621test_expect_success 'setup other remote for remote reference completion' '
1622        git remote add other otherrepo &&
1623        git fetch other
1624'
1625
1626for flag in -d --delete
1627do
1628        test_expect_success "__git_complete_remote_or_refspec - push $flag other" '
1629                sed -e "s/Z$//" >expected <<-EOF &&
1630                master-in-other Z
1631                EOF
1632                (
1633                        words=(git push '$flag' other ma) &&
1634                        cword=${#words[@]} cur=${words[cword-1]} &&
1635                        __git_complete_remote_or_refspec &&
1636                        print_comp
1637                ) &&
1638                test_cmp expected out
1639        '
1640
1641        test_expect_failure "__git_complete_remote_or_refspec - push other $flag" '
1642                sed -e "s/Z$//" >expected <<-EOF &&
1643                master-in-other Z
1644                EOF
1645                (
1646                        words=(git push other '$flag' ma) &&
1647                        cword=${#words[@]} cur=${words[cword-1]} &&
1648                        __git_complete_remote_or_refspec &&
1649                        print_comp
1650                ) &&
1651                test_cmp expected out
1652        '
1653done
1654
1655test_expect_success 'sourcing the completion script clears cached commands' '
1656        __git_compute_all_commands &&
1657        verbose test -n "$__git_all_commands" &&
1658        . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
1659        verbose test -z "$__git_all_commands"
1660'
1661
1662test_expect_success 'sourcing the completion script clears cached porcelain commands' '
1663        __git_compute_porcelain_commands &&
1664        verbose test -n "$__git_porcelain_commands" &&
1665        . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
1666        verbose test -z "$__git_porcelain_commands"
1667'
1668
1669test_expect_success !GETTEXT_POISON 'sourcing the completion script clears cached merge strategies' '
1670        __git_compute_merge_strategies &&
1671        verbose test -n "$__git_merge_strategies" &&
1672        . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
1673        verbose test -z "$__git_merge_strategies"
1674'
1675
1676test_expect_success 'sourcing the completion script clears cached --options' '
1677        __gitcomp_builtin checkout &&
1678        verbose test -n "$__gitcomp_builtin_checkout" &&
1679        __gitcomp_builtin notes_edit &&
1680        verbose test -n "$__gitcomp_builtin_notes_edit" &&
1681        . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
1682        verbose test -z "$__gitcomp_builtin_checkout" &&
1683        verbose test -z "$__gitcomp_builtin_notes_edit"
1684'
1685
1686test_done