253160a161d38cfb36ef1bd25e318d35f33176f2
   1#!/bin/sh
   2
   3test_description='test untracked cache'
   4
   5. ./test-lib.sh
   6
   7avoid_racy() {
   8        sleep 1
   9}
  10
  11test_lazy_prereq UNTRACKED_CACHE '
  12        { git update-index --test-untracked-cache; ret=$?; } &&
  13        test $ret -ne 1
  14'
  15
  16if ! test_have_prereq UNTRACKED_CACHE; then
  17        skip_all='This system does not support untracked cache'
  18        test_done
  19fi
  20
  21test_expect_success 'setup' '
  22        git init worktree &&
  23        cd worktree &&
  24        mkdir done dtwo dthree &&
  25        touch one two three done/one dtwo/two dthree/three &&
  26        git add one two done/one &&
  27        : >.git/info/exclude &&
  28        git update-index --untracked-cache
  29'
  30
  31test_expect_success 'untracked cache is empty' '
  32        test-dump-untracked-cache >../actual &&
  33        cat >../expect <<EOF &&
  34info/exclude 0000000000000000000000000000000000000000
  35core.excludesfile 0000000000000000000000000000000000000000
  36exclude_per_dir .gitignore
  37flags 00000006
  38EOF
  39        test_cmp ../expect ../actual
  40'
  41
  42cat >../status.expect <<EOF &&
  43A  done/one
  44A  one
  45A  two
  46?? dthree/
  47?? dtwo/
  48?? three
  49EOF
  50
  51cat >../dump.expect <<EOF &&
  52info/exclude e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
  53core.excludesfile 0000000000000000000000000000000000000000
  54exclude_per_dir .gitignore
  55flags 00000006
  56/ 0000000000000000000000000000000000000000 recurse valid
  57dthree/
  58dtwo/
  59three
  60/done/ 0000000000000000000000000000000000000000 recurse valid
  61/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
  62three
  63/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
  64two
  65EOF
  66
  67test_expect_success 'status first time (empty cache)' '
  68        avoid_racy &&
  69        : >../trace &&
  70        GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
  71        git status --porcelain >../actual &&
  72        test_cmp ../status.expect ../actual &&
  73        cat >../trace.expect <<EOF &&
  74node creation: 3
  75gitignore invalidation: 1
  76directory invalidation: 0
  77opendir: 4
  78EOF
  79        test_cmp ../trace.expect ../trace
  80'
  81
  82test_expect_success 'untracked cache after first status' '
  83        test-dump-untracked-cache >../actual &&
  84        test_cmp ../dump.expect ../actual
  85'
  86
  87test_expect_success 'status second time (fully populated cache)' '
  88        avoid_racy &&
  89        : >../trace &&
  90        GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
  91        git status --porcelain >../actual &&
  92        test_cmp ../status.expect ../actual &&
  93        cat >../trace.expect <<EOF &&
  94node creation: 0
  95gitignore invalidation: 0
  96directory invalidation: 0
  97opendir: 0
  98EOF
  99        test_cmp ../trace.expect ../trace
 100'
 101
 102test_expect_success 'untracked cache after second status' '
 103        test-dump-untracked-cache >../actual &&
 104        test_cmp ../dump.expect ../actual
 105'
 106
 107test_expect_success 'modify in root directory, one dir invalidation' '
 108        avoid_racy &&
 109        : >four &&
 110        : >../trace &&
 111        GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
 112        git status --porcelain >../actual &&
 113        cat >../status.expect <<EOF &&
 114A  done/one
 115A  one
 116A  two
 117?? dthree/
 118?? dtwo/
 119?? four
 120?? three
 121EOF
 122        test_cmp ../status.expect ../actual &&
 123        cat >../trace.expect <<EOF &&
 124node creation: 0
 125gitignore invalidation: 0
 126directory invalidation: 1
 127opendir: 1
 128EOF
 129        test_cmp ../trace.expect ../trace
 130
 131'
 132
 133test_expect_success 'verify untracked cache dump' '
 134        test-dump-untracked-cache >../actual &&
 135        cat >../expect <<EOF &&
 136info/exclude e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
 137core.excludesfile 0000000000000000000000000000000000000000
 138exclude_per_dir .gitignore
 139flags 00000006
 140/ 0000000000000000000000000000000000000000 recurse valid
 141dthree/
 142dtwo/
 143four
 144three
 145/done/ 0000000000000000000000000000000000000000 recurse valid
 146/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
 147three
 148/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
 149two
 150EOF
 151        test_cmp ../expect ../actual
 152'
 153
 154test_expect_success 'new .gitignore invalidates recursively' '
 155        avoid_racy &&
 156        echo four >.gitignore &&
 157        : >../trace &&
 158        GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
 159        git status --porcelain >../actual &&
 160        cat >../status.expect <<EOF &&
 161A  done/one
 162A  one
 163A  two
 164?? .gitignore
 165?? dthree/
 166?? dtwo/
 167?? three
 168EOF
 169        test_cmp ../status.expect ../actual &&
 170        cat >../trace.expect <<EOF &&
 171node creation: 0
 172gitignore invalidation: 1
 173directory invalidation: 1
 174opendir: 4
 175EOF
 176        test_cmp ../trace.expect ../trace
 177
 178'
 179
 180test_expect_success 'verify untracked cache dump' '
 181        test-dump-untracked-cache >../actual &&
 182        cat >../expect <<EOF &&
 183info/exclude e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
 184core.excludesfile 0000000000000000000000000000000000000000
 185exclude_per_dir .gitignore
 186flags 00000006
 187/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
 188.gitignore
 189dthree/
 190dtwo/
 191three
 192/done/ 0000000000000000000000000000000000000000 recurse valid
 193/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
 194three
 195/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
 196two
 197EOF
 198        test_cmp ../expect ../actual
 199'
 200
 201test_expect_success 'new info/exclude invalidates everything' '
 202        avoid_racy &&
 203        echo three >>.git/info/exclude &&
 204        : >../trace &&
 205        GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
 206        git status --porcelain >../actual &&
 207        cat >../status.expect <<EOF &&
 208A  done/one
 209A  one
 210A  two
 211?? .gitignore
 212?? dtwo/
 213EOF
 214        test_cmp ../status.expect ../actual &&
 215        cat >../trace.expect <<EOF &&
 216node creation: 0
 217gitignore invalidation: 1
 218directory invalidation: 0
 219opendir: 4
 220EOF
 221        test_cmp ../trace.expect ../trace
 222'
 223
 224test_expect_success 'verify untracked cache dump' '
 225        test-dump-untracked-cache >../actual &&
 226        cat >../expect <<EOF &&
 227info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
 228core.excludesfile 0000000000000000000000000000000000000000
 229exclude_per_dir .gitignore
 230flags 00000006
 231/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
 232.gitignore
 233dtwo/
 234/done/ 0000000000000000000000000000000000000000 recurse valid
 235/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
 236/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
 237two
 238EOF
 239        test_cmp ../expect ../actual
 240'
 241
 242test_expect_success 'move two from tracked to untracked' '
 243        git rm --cached two &&
 244        test-dump-untracked-cache >../actual &&
 245        cat >../expect <<EOF &&
 246info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
 247core.excludesfile 0000000000000000000000000000000000000000
 248exclude_per_dir .gitignore
 249flags 00000006
 250/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse
 251/done/ 0000000000000000000000000000000000000000 recurse valid
 252/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
 253/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
 254two
 255EOF
 256        test_cmp ../expect ../actual
 257'
 258
 259test_expect_success 'status after the move' '
 260        : >../trace &&
 261        GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
 262        git status --porcelain >../actual &&
 263        cat >../status.expect <<EOF &&
 264A  done/one
 265A  one
 266?? .gitignore
 267?? dtwo/
 268?? two
 269EOF
 270        test_cmp ../status.expect ../actual &&
 271        cat >../trace.expect <<EOF &&
 272node creation: 0
 273gitignore invalidation: 0
 274directory invalidation: 0
 275opendir: 1
 276EOF
 277        test_cmp ../trace.expect ../trace
 278'
 279
 280test_expect_success 'verify untracked cache dump' '
 281        test-dump-untracked-cache >../actual &&
 282        cat >../expect <<EOF &&
 283info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
 284core.excludesfile 0000000000000000000000000000000000000000
 285exclude_per_dir .gitignore
 286flags 00000006
 287/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
 288.gitignore
 289dtwo/
 290two
 291/done/ 0000000000000000000000000000000000000000 recurse valid
 292/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
 293/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
 294two
 295EOF
 296        test_cmp ../expect ../actual
 297'
 298
 299test_expect_success 'move two from untracked to tracked' '
 300        git add two &&
 301        test-dump-untracked-cache >../actual &&
 302        cat >../expect <<EOF &&
 303info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
 304core.excludesfile 0000000000000000000000000000000000000000
 305exclude_per_dir .gitignore
 306flags 00000006
 307/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse
 308/done/ 0000000000000000000000000000000000000000 recurse valid
 309/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
 310/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
 311two
 312EOF
 313        test_cmp ../expect ../actual
 314'
 315
 316test_expect_success 'status after the move' '
 317        : >../trace &&
 318        GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
 319        git status --porcelain >../actual &&
 320        cat >../status.expect <<EOF &&
 321A  done/one
 322A  one
 323A  two
 324?? .gitignore
 325?? dtwo/
 326EOF
 327        test_cmp ../status.expect ../actual &&
 328        cat >../trace.expect <<EOF &&
 329node creation: 0
 330gitignore invalidation: 0
 331directory invalidation: 0
 332opendir: 1
 333EOF
 334        test_cmp ../trace.expect ../trace
 335'
 336
 337test_expect_success 'verify untracked cache dump' '
 338        test-dump-untracked-cache >../actual &&
 339        cat >../expect <<EOF &&
 340info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
 341core.excludesfile 0000000000000000000000000000000000000000
 342exclude_per_dir .gitignore
 343flags 00000006
 344/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
 345.gitignore
 346dtwo/
 347/done/ 0000000000000000000000000000000000000000 recurse valid
 348/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
 349/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
 350two
 351EOF
 352        test_cmp ../expect ../actual
 353'
 354
 355test_expect_success 'set up for sparse checkout testing' '
 356        echo two >done/.gitignore &&
 357        echo three >>done/.gitignore &&
 358        echo two >done/two &&
 359        git add -f done/two done/.gitignore &&
 360        git commit -m "first commit"
 361'
 362
 363test_expect_success 'status after commit' '
 364        : >../trace &&
 365        GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
 366        git status --porcelain >../actual &&
 367        cat >../status.expect <<EOF &&
 368?? .gitignore
 369?? dtwo/
 370EOF
 371        test_cmp ../status.expect ../actual &&
 372        cat >../trace.expect <<EOF &&
 373node creation: 0
 374gitignore invalidation: 0
 375directory invalidation: 0
 376opendir: 2
 377EOF
 378        test_cmp ../trace.expect ../trace
 379'
 380
 381test_expect_success 'untracked cache correct after commit' '
 382        test-dump-untracked-cache >../actual &&
 383        cat >../expect <<EOF &&
 384info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
 385core.excludesfile 0000000000000000000000000000000000000000
 386exclude_per_dir .gitignore
 387flags 00000006
 388/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
 389.gitignore
 390dtwo/
 391/done/ 0000000000000000000000000000000000000000 recurse valid
 392/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
 393/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
 394two
 395EOF
 396        test_cmp ../expect ../actual
 397'
 398
 399test_expect_success 'set up sparse checkout' '
 400        echo "done/[a-z]*" >.git/info/sparse-checkout &&
 401        test_config core.sparsecheckout true &&
 402        git checkout master &&
 403        git update-index --force-untracked-cache &&
 404        git status --porcelain >/dev/null && # prime the cache
 405        test_path_is_missing done/.gitignore &&
 406        test_path_is_file done/one
 407'
 408
 409test_expect_success 'create/modify files, some of which are gitignored' '
 410        echo two bis >done/two &&
 411        echo three >done/three && # three is gitignored
 412        echo four >done/four && # four is gitignored at a higher level
 413        echo five >done/five && # five is not gitignored
 414        echo test >base && #we need to ensure that the root dir is touched
 415        rm base
 416'
 417
 418test_expect_success 'test sparse status with untracked cache' '
 419        : >../trace &&
 420        avoid_racy &&
 421        GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
 422        git status --porcelain >../status.actual &&
 423        cat >../status.expect <<EOF &&
 424 M done/two
 425?? .gitignore
 426?? done/five
 427?? dtwo/
 428EOF
 429        test_cmp ../status.expect ../status.actual &&
 430        cat >../trace.expect <<EOF &&
 431node creation: 0
 432gitignore invalidation: 1
 433directory invalidation: 2
 434opendir: 2
 435EOF
 436        test_cmp ../trace.expect ../trace
 437'
 438
 439test_expect_success 'untracked cache correct after status' '
 440        test-dump-untracked-cache >../actual &&
 441        cat >../expect <<EOF &&
 442info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
 443core.excludesfile 0000000000000000000000000000000000000000
 444exclude_per_dir .gitignore
 445flags 00000006
 446/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
 447.gitignore
 448dtwo/
 449/done/ 1946f0437f90c5005533cbe1736a6451ca301714 recurse valid
 450five
 451/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
 452/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
 453two
 454EOF
 455        test_cmp ../expect ../actual
 456'
 457
 458test_expect_success 'test sparse status again with untracked cache' '
 459        avoid_racy &&
 460        : >../trace &&
 461        GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
 462        git status --porcelain >../status.actual &&
 463        cat >../status.expect <<EOF &&
 464 M done/two
 465?? .gitignore
 466?? done/five
 467?? dtwo/
 468EOF
 469        test_cmp ../status.expect ../status.actual &&
 470        cat >../trace.expect <<EOF &&
 471node creation: 0
 472gitignore invalidation: 0
 473directory invalidation: 0
 474opendir: 0
 475EOF
 476        test_cmp ../trace.expect ../trace
 477'
 478
 479test_expect_success 'set up for test of subdir and sparse checkouts' '
 480        mkdir done/sub &&
 481        mkdir done/sub/sub &&
 482        echo "sub" > done/sub/sub/file
 483'
 484
 485test_expect_success 'test sparse status with untracked cache and subdir' '
 486        avoid_racy &&
 487        : >../trace &&
 488        GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
 489        git status --porcelain >../status.actual &&
 490        cat >../status.expect <<EOF &&
 491 M done/two
 492?? .gitignore
 493?? done/five
 494?? done/sub/
 495?? dtwo/
 496EOF
 497        test_cmp ../status.expect ../status.actual &&
 498        cat >../trace.expect <<EOF &&
 499node creation: 2
 500gitignore invalidation: 0
 501directory invalidation: 1
 502opendir: 3
 503EOF
 504        test_cmp ../trace.expect ../trace
 505'
 506
 507test_expect_success 'verify untracked cache dump (sparse/subdirs)' '
 508        test-dump-untracked-cache >../actual &&
 509        cat >../expect <<EOF &&
 510info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
 511core.excludesfile 0000000000000000000000000000000000000000
 512exclude_per_dir .gitignore
 513flags 00000006
 514/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
 515.gitignore
 516dtwo/
 517/done/ 1946f0437f90c5005533cbe1736a6451ca301714 recurse valid
 518five
 519sub/
 520/done/sub/ 0000000000000000000000000000000000000000 recurse check_only valid
 521sub/
 522/done/sub/sub/ 0000000000000000000000000000000000000000 recurse check_only valid
 523file
 524/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
 525/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
 526two
 527EOF
 528        test_cmp ../expect ../actual
 529'
 530
 531test_expect_success 'test sparse status again with untracked cache and subdir' '
 532        avoid_racy &&
 533        : >../trace &&
 534        GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
 535        git status --porcelain >../status.actual &&
 536        test_cmp ../status.expect ../status.actual &&
 537        cat >../trace.expect <<EOF &&
 538node creation: 0
 539gitignore invalidation: 0
 540directory invalidation: 0
 541opendir: 0
 542EOF
 543        test_cmp ../trace.expect ../trace
 544'
 545
 546test_expect_success 'move entry in subdir from untracked to cached' '
 547        git add dtwo/two &&
 548        git status --porcelain >../status.actual &&
 549        cat >../status.expect <<EOF &&
 550 M done/two
 551A  dtwo/two
 552?? .gitignore
 553?? done/five
 554?? done/sub/
 555EOF
 556        test_cmp ../status.expect ../status.actual
 557'
 558
 559test_expect_success 'move entry in subdir from cached to untracked' '
 560        git rm --cached dtwo/two &&
 561        git status --porcelain >../status.actual &&
 562        cat >../status.expect <<EOF &&
 563 M done/two
 564?? .gitignore
 565?? done/five
 566?? done/sub/
 567?? dtwo/
 568EOF
 569        test_cmp ../status.expect ../status.actual
 570'
 571
 572test_done