t / t1501-work-tree.shon commit Merge branch 'pw/add-p-single' (60f8b89)
   1#!/bin/sh
   2
   3test_description='test separate work tree'
   4. ./test-lib.sh
   5
   6test_expect_success 'setup' '
   7        EMPTY_TREE=$(git write-tree) &&
   8        EMPTY_BLOB=$(git hash-object -t blob --stdin </dev/null) &&
   9        CHANGED_BLOB=$(echo changed | git hash-object -t blob --stdin) &&
  10        EMPTY_BLOB7=$(echo $EMPTY_BLOB | sed "s/\(.......\).*/\1/") &&
  11        CHANGED_BLOB7=$(echo $CHANGED_BLOB | sed "s/\(.......\).*/\1/") &&
  12
  13        mkdir -p work/sub/dir &&
  14        mkdir -p work2 &&
  15        mv .git repo.git
  16'
  17
  18test_expect_success 'setup: helper for testing rev-parse' '
  19        test_rev_parse() {
  20                echo $1 >expected.bare &&
  21                echo $2 >expected.inside-git &&
  22                echo $3 >expected.inside-worktree &&
  23                if test $# -ge 4
  24                then
  25                        echo $4 >expected.prefix
  26                fi &&
  27
  28                git rev-parse --is-bare-repository >actual.bare &&
  29                git rev-parse --is-inside-git-dir >actual.inside-git &&
  30                git rev-parse --is-inside-work-tree >actual.inside-worktree &&
  31                if test $# -ge 4
  32                then
  33                        git rev-parse --show-prefix >actual.prefix
  34                fi &&
  35
  36                test_cmp expected.bare actual.bare &&
  37                test_cmp expected.inside-git actual.inside-git &&
  38                test_cmp expected.inside-worktree actual.inside-worktree &&
  39                if test $# -ge 4
  40                then
  41                        # rev-parse --show-prefix should output
  42                        # a single newline when at the top of the work tree,
  43                        # but we test for that separately.
  44                        test -z "$4" && ! test -s actual.prefix ||
  45                        test_cmp expected.prefix actual.prefix
  46                fi
  47        }
  48'
  49
  50test_expect_success 'setup: core.worktree = relative path' '
  51        sane_unset GIT_WORK_TREE &&
  52        GIT_DIR=repo.git &&
  53        GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
  54        export GIT_DIR GIT_CONFIG &&
  55        git config core.worktree ../work
  56'
  57
  58test_expect_success 'outside' '
  59        test_rev_parse false false false
  60'
  61
  62test_expect_success 'inside work tree' '
  63        (
  64                cd work &&
  65                GIT_DIR=../repo.git &&
  66                GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
  67                test_rev_parse false false true ""
  68        )
  69'
  70
  71test_expect_success 'empty prefix is actually written out' '
  72        echo >expected &&
  73        (
  74                cd work &&
  75                GIT_DIR=../repo.git &&
  76                GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
  77                git rev-parse --show-prefix >../actual
  78        ) &&
  79        test_cmp expected actual
  80'
  81
  82test_expect_success 'subdir of work tree' '
  83        (
  84                cd work/sub/dir &&
  85                GIT_DIR=../../../repo.git &&
  86                GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
  87                test_rev_parse false false true sub/dir/
  88        )
  89'
  90
  91test_expect_success 'setup: core.worktree = absolute path' '
  92        sane_unset GIT_WORK_TREE &&
  93        GIT_DIR=$(pwd)/repo.git &&
  94        GIT_CONFIG=$GIT_DIR/config &&
  95        export GIT_DIR GIT_CONFIG &&
  96        git config core.worktree "$(pwd)/work"
  97'
  98
  99test_expect_success 'outside' '
 100        test_rev_parse false false false &&
 101        (
 102                cd work2 &&
 103                test_rev_parse false false false
 104        )
 105'
 106
 107test_expect_success 'inside work tree' '
 108        (
 109                cd work &&
 110                test_rev_parse false false true ""
 111        )
 112'
 113
 114test_expect_success 'subdir of work tree' '
 115        (
 116                cd work/sub/dir &&
 117                test_rev_parse false false true sub/dir/
 118        )
 119'
 120
 121test_expect_success 'setup: GIT_WORK_TREE=relative (override core.worktree)' '
 122        GIT_DIR=$(pwd)/repo.git &&
 123        GIT_CONFIG=$GIT_DIR/config &&
 124        git config core.worktree non-existent &&
 125        GIT_WORK_TREE=work &&
 126        export GIT_DIR GIT_CONFIG GIT_WORK_TREE
 127'
 128
 129test_expect_success 'outside' '
 130        test_rev_parse false false false &&
 131        (
 132                cd work2 &&
 133                test_rev_parse false false false
 134        )
 135'
 136
 137test_expect_success 'inside work tree' '
 138        (
 139                cd work &&
 140                GIT_WORK_TREE=. &&
 141                test_rev_parse false false true ""
 142        )
 143'
 144
 145test_expect_success 'subdir of work tree' '
 146        (
 147                cd work/sub/dir &&
 148                GIT_WORK_TREE=../.. &&
 149                test_rev_parse false false true sub/dir/
 150        )
 151'
 152
 153test_expect_success 'setup: GIT_WORK_TREE=absolute, below git dir' '
 154        mv work repo.git/work &&
 155        mv work2 repo.git/work2 &&
 156        GIT_DIR=$(pwd)/repo.git &&
 157        GIT_CONFIG=$GIT_DIR/config &&
 158        GIT_WORK_TREE=$(pwd)/repo.git/work &&
 159        export GIT_DIR GIT_CONFIG GIT_WORK_TREE
 160'
 161
 162test_expect_success 'outside' '
 163        echo outside &&
 164        test_rev_parse false false false
 165'
 166
 167test_expect_success 'in repo.git' '
 168        (
 169                cd repo.git &&
 170                test_rev_parse false true false
 171        ) &&
 172        (
 173                cd repo.git/objects &&
 174                test_rev_parse false true false
 175        ) &&
 176        (
 177                cd repo.git/work2 &&
 178                test_rev_parse false true false
 179        )
 180'
 181
 182test_expect_success 'inside work tree' '
 183        (
 184                cd repo.git/work &&
 185                test_rev_parse false true true ""
 186        )
 187'
 188
 189test_expect_success 'subdir of work tree' '
 190        (
 191                cd repo.git/work/sub/dir &&
 192                test_rev_parse false true true sub/dir/
 193        )
 194'
 195
 196test_expect_success 'find work tree from repo' '
 197        echo sub/dir/untracked >expected &&
 198        cat <<-\EOF >repo.git/work/.gitignore &&
 199        expected.*
 200        actual.*
 201        .gitignore
 202        EOF
 203        >repo.git/work/sub/dir/untracked &&
 204        (
 205                cd repo.git &&
 206                git ls-files --others --exclude-standard >../actual
 207        ) &&
 208        test_cmp expected actual
 209'
 210
 211test_expect_success 'find work tree from work tree' '
 212        echo sub/dir/tracked >expected &&
 213        >repo.git/work/sub/dir/tracked &&
 214        (
 215                cd repo.git/work/sub/dir &&
 216                git --git-dir=../../.. add tracked
 217        ) &&
 218        (
 219                cd repo.git &&
 220                git ls-files >../actual
 221        ) &&
 222        test_cmp expected actual
 223'
 224
 225test_expect_success '_gently() groks relative GIT_DIR & GIT_WORK_TREE' '
 226        (
 227                cd repo.git/work/sub/dir &&
 228                GIT_DIR=../../.. &&
 229                GIT_WORK_TREE=../.. &&
 230                GIT_PAGER= &&
 231                export GIT_DIR GIT_WORK_TREE GIT_PAGER &&
 232
 233                git diff --exit-code tracked &&
 234                echo changed >tracked &&
 235                test_must_fail git diff --exit-code tracked
 236        )
 237'
 238
 239test_expect_success 'diff-index respects work tree under .git dir' '
 240        cat >diff-index-cached.expected <<-EOF &&
 241        :000000 100644 $_z40 $EMPTY_BLOB A      sub/dir/tracked
 242        EOF
 243        cat >diff-index.expected <<-EOF &&
 244        :000000 100644 $_z40 $_z40 A    sub/dir/tracked
 245        EOF
 246
 247        (
 248                GIT_DIR=repo.git &&
 249                GIT_WORK_TREE=repo.git/work &&
 250                export GIT_DIR GIT_WORK_TREE &&
 251                git diff-index $EMPTY_TREE >diff-index.actual &&
 252                git diff-index --cached $EMPTY_TREE >diff-index-cached.actual
 253        ) &&
 254        test_cmp diff-index.expected diff-index.actual &&
 255        test_cmp diff-index-cached.expected diff-index-cached.actual
 256'
 257
 258test_expect_success 'diff-files respects work tree under .git dir' '
 259        cat >diff-files.expected <<-EOF &&
 260        :100644 100644 $EMPTY_BLOB $_z40 M      sub/dir/tracked
 261        EOF
 262
 263        (
 264                GIT_DIR=repo.git &&
 265                GIT_WORK_TREE=repo.git/work &&
 266                export GIT_DIR GIT_WORK_TREE &&
 267                git diff-files >diff-files.actual
 268        ) &&
 269        test_cmp diff-files.expected diff-files.actual
 270'
 271
 272test_expect_success 'git diff respects work tree under .git dir' '
 273        cat >diff-TREE.expected <<-EOF &&
 274        diff --git a/sub/dir/tracked b/sub/dir/tracked
 275        new file mode 100644
 276        index 0000000..$CHANGED_BLOB7
 277        --- /dev/null
 278        +++ b/sub/dir/tracked
 279        @@ -0,0 +1 @@
 280        +changed
 281        EOF
 282        cat >diff-TREE-cached.expected <<-EOF &&
 283        diff --git a/sub/dir/tracked b/sub/dir/tracked
 284        new file mode 100644
 285        index 0000000..$EMPTY_BLOB7
 286        EOF
 287        cat >diff-FILES.expected <<-EOF &&
 288        diff --git a/sub/dir/tracked b/sub/dir/tracked
 289        index $EMPTY_BLOB7..$CHANGED_BLOB7 100644
 290        --- a/sub/dir/tracked
 291        +++ b/sub/dir/tracked
 292        @@ -0,0 +1 @@
 293        +changed
 294        EOF
 295
 296        (
 297                GIT_DIR=repo.git &&
 298                GIT_WORK_TREE=repo.git/work &&
 299                export GIT_DIR GIT_WORK_TREE &&
 300                git diff $EMPTY_TREE >diff-TREE.actual &&
 301                git diff --cached $EMPTY_TREE >diff-TREE-cached.actual &&
 302                git diff >diff-FILES.actual
 303        ) &&
 304        test_cmp diff-TREE.expected diff-TREE.actual &&
 305        test_cmp diff-TREE-cached.expected diff-TREE-cached.actual &&
 306        test_cmp diff-FILES.expected diff-FILES.actual
 307'
 308
 309test_expect_success 'git grep' '
 310        echo dir/tracked >expected.grep &&
 311        (
 312                cd repo.git/work/sub &&
 313                GIT_DIR=../.. &&
 314                GIT_WORK_TREE=.. &&
 315                export GIT_DIR GIT_WORK_TREE &&
 316                git grep -l changed >../../../actual.grep
 317        ) &&
 318        test_cmp expected.grep actual.grep
 319'
 320
 321test_expect_success 'git commit' '
 322        (
 323                cd repo.git &&
 324                GIT_DIR=. GIT_WORK_TREE=work git commit -a -m done
 325        )
 326'
 327
 328test_expect_success 'absolute pathspec should fail gracefully' '
 329        (
 330                cd repo.git &&
 331                test_might_fail git config --unset core.worktree &&
 332                test_must_fail git log HEAD -- /home
 333        )
 334'
 335
 336test_expect_success 'make_relative_path handles double slashes in GIT_DIR' '
 337        >dummy_file &&
 338        echo git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file &&
 339        git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file
 340'
 341
 342test_expect_success 'relative $GIT_WORK_TREE and git subprocesses' '
 343        GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work \
 344        test-subprocess --setup-work-tree rev-parse --show-toplevel >actual &&
 345        echo "$(pwd)/repo.git/work" >expected &&
 346        test_cmp expected actual
 347'
 348
 349test_expect_success 'Multi-worktree setup' '
 350        mkdir work &&
 351        mkdir -p repo.git/repos/foo &&
 352        cp repo.git/HEAD repo.git/index repo.git/repos/foo &&
 353        test_might_fail cp repo.git/sharedindex.* repo.git/repos/foo &&
 354        sane_unset GIT_DIR GIT_CONFIG GIT_WORK_TREE
 355'
 356
 357test_expect_success 'GIT_DIR set (1)' '
 358        echo "gitdir: repo.git/repos/foo" >gitfile &&
 359        echo ../.. >repo.git/repos/foo/commondir &&
 360        (
 361                cd work &&
 362                GIT_DIR=../gitfile git rev-parse --git-common-dir >actual &&
 363                test-path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
 364                test_cmp expect actual
 365        )
 366'
 367
 368test_expect_success 'GIT_DIR set (2)' '
 369        echo "gitdir: repo.git/repos/foo" >gitfile &&
 370        echo "$(pwd)/repo.git" >repo.git/repos/foo/commondir &&
 371        (
 372                cd work &&
 373                GIT_DIR=../gitfile git rev-parse --git-common-dir >actual &&
 374                test-path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
 375                test_cmp expect actual
 376        )
 377'
 378
 379test_expect_success 'Auto discovery' '
 380        echo "gitdir: repo.git/repos/foo" >.git &&
 381        echo ../.. >repo.git/repos/foo/commondir &&
 382        (
 383                cd work &&
 384                git rev-parse --git-common-dir >actual &&
 385                test-path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
 386                test_cmp expect actual &&
 387                echo haha >data1 &&
 388                git add data1 &&
 389                git ls-files --full-name :/ | grep data1 >actual &&
 390                echo work/data1 >expect &&
 391                test_cmp expect actual
 392        )
 393'
 394
 395test_expect_success '$GIT_DIR/common overrides core.worktree' '
 396        mkdir elsewhere &&
 397        git --git-dir=repo.git config core.worktree "$TRASH_DIRECTORY/elsewhere" &&
 398        echo "gitdir: repo.git/repos/foo" >.git &&
 399        echo ../.. >repo.git/repos/foo/commondir &&
 400        (
 401                cd work &&
 402                git rev-parse --git-common-dir >actual &&
 403                test-path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
 404                test_cmp expect actual &&
 405                echo haha >data2 &&
 406                git add data2 &&
 407                git ls-files --full-name :/ | grep data2 >actual &&
 408                echo work/data2 >expect &&
 409                test_cmp expect actual
 410        )
 411'
 412
 413test_expect_success '$GIT_WORK_TREE overrides $GIT_DIR/common' '
 414        echo "gitdir: repo.git/repos/foo" >.git &&
 415        echo ../.. >repo.git/repos/foo/commondir &&
 416        (
 417                cd work &&
 418                echo haha >data3 &&
 419                git --git-dir=../.git --work-tree=. add data3 &&
 420                git ls-files --full-name -- :/ | grep data3 >actual &&
 421                echo data3 >expect &&
 422                test_cmp expect actual
 423        )
 424'
 425
 426test_expect_success 'error out gracefully on invalid $GIT_WORK_TREE' '
 427        (
 428                GIT_WORK_TREE=/.invalid/work/tree &&
 429                export GIT_WORK_TREE &&
 430                test_expect_code 128 git rev-parse
 431        )
 432'
 433
 434test_done