t / t7519-status-fsmonitor.shon commit Merge branch 'ds/reachable' (0f7ac90)
   1#!/bin/sh
   2
   3test_description='git status with file system watcher'
   4
   5. ./test-lib.sh
   6
   7#
   8# To run the entire git test suite using fsmonitor:
   9#
  10# copy t/t7519/fsmonitor-all to a location in your path and then set
  11# GIT_FSMONITOR_TEST=fsmonitor-all and run your tests.
  12#
  13
  14# Note, after "git reset --hard HEAD" no extensions exist other than 'TREE'
  15# "git update-index --fsmonitor" can be used to get the extension written
  16# before testing the results.
  17
  18clean_repo () {
  19        git reset --hard HEAD &&
  20        git clean -fd
  21}
  22
  23dirty_repo () {
  24        : >untracked &&
  25        : >dir1/untracked &&
  26        : >dir2/untracked &&
  27        echo 1 >modified &&
  28        echo 2 >dir1/modified &&
  29        echo 3 >dir2/modified &&
  30        echo 4 >new &&
  31        echo 5 >dir1/new &&
  32        echo 6 >dir2/new
  33}
  34
  35write_integration_script () {
  36        write_script .git/hooks/fsmonitor-test<<-\EOF
  37        if test "$#" -ne 2
  38        then
  39                echo "$0: exactly 2 arguments expected"
  40                exit 2
  41        fi
  42        if test "$1" != 1
  43        then
  44                echo "Unsupported core.fsmonitor hook version." >&2
  45                exit 1
  46        fi
  47        printf "untracked\0"
  48        printf "dir1/untracked\0"
  49        printf "dir2/untracked\0"
  50        printf "modified\0"
  51        printf "dir1/modified\0"
  52        printf "dir2/modified\0"
  53        printf "new\0"
  54        printf "dir1/new\0"
  55        printf "dir2/new\0"
  56        EOF
  57}
  58
  59test_lazy_prereq UNTRACKED_CACHE '
  60        { git update-index --test-untracked-cache; ret=$?; } &&
  61        test $ret -ne 1
  62'
  63
  64test_expect_success 'setup' '
  65        mkdir -p .git/hooks &&
  66        : >tracked &&
  67        : >modified &&
  68        mkdir dir1 &&
  69        : >dir1/tracked &&
  70        : >dir1/modified &&
  71        mkdir dir2 &&
  72        : >dir2/tracked &&
  73        : >dir2/modified &&
  74        git -c core.fsmonitor= add . &&
  75        git -c core.fsmonitor= commit -m initial &&
  76        git config core.fsmonitor .git/hooks/fsmonitor-test &&
  77        cat >.gitignore <<-\EOF
  78        .gitignore
  79        expect*
  80        actual*
  81        marker*
  82        EOF
  83'
  84
  85# test that the fsmonitor extension is off by default
  86test_expect_success 'fsmonitor extension is off by default' '
  87        test-dump-fsmonitor >actual &&
  88        grep "^no fsmonitor" actual
  89'
  90
  91# test that "update-index --fsmonitor" adds the fsmonitor extension
  92test_expect_success 'update-index --fsmonitor" adds the fsmonitor extension' '
  93        git update-index --fsmonitor &&
  94        test-dump-fsmonitor >actual &&
  95        grep "^fsmonitor last update" actual
  96'
  97
  98# test that "update-index --no-fsmonitor" removes the fsmonitor extension
  99test_expect_success 'update-index --no-fsmonitor" removes the fsmonitor extension' '
 100        git update-index --no-fsmonitor &&
 101        test-dump-fsmonitor >actual &&
 102        grep "^no fsmonitor" actual
 103'
 104
 105cat >expect <<EOF &&
 106h dir1/modified
 107H dir1/tracked
 108h dir2/modified
 109H dir2/tracked
 110h modified
 111H tracked
 112EOF
 113
 114# test that "update-index --fsmonitor-valid" sets the fsmonitor valid bit
 115test_expect_success 'update-index --fsmonitor-valid" sets the fsmonitor valid bit' '
 116        git update-index --fsmonitor &&
 117        git update-index --fsmonitor-valid dir1/modified &&
 118        git update-index --fsmonitor-valid dir2/modified &&
 119        git update-index --fsmonitor-valid modified &&
 120        git ls-files -f >actual &&
 121        test_cmp expect actual
 122'
 123
 124cat >expect <<EOF &&
 125H dir1/modified
 126H dir1/tracked
 127H dir2/modified
 128H dir2/tracked
 129H modified
 130H tracked
 131EOF
 132
 133# test that "update-index --no-fsmonitor-valid" clears the fsmonitor valid bit
 134test_expect_success 'update-index --no-fsmonitor-valid" clears the fsmonitor valid bit' '
 135        git update-index --no-fsmonitor-valid dir1/modified &&
 136        git update-index --no-fsmonitor-valid dir2/modified &&
 137        git update-index --no-fsmonitor-valid modified &&
 138        git ls-files -f >actual &&
 139        test_cmp expect actual
 140'
 141
 142cat >expect <<EOF &&
 143H dir1/modified
 144H dir1/tracked
 145H dir2/modified
 146H dir2/tracked
 147H modified
 148H tracked
 149EOF
 150
 151# test that all files returned by the script get flagged as invalid
 152test_expect_success 'all files returned by integration script get flagged as invalid' '
 153        write_integration_script &&
 154        dirty_repo &&
 155        git update-index --fsmonitor &&
 156        git ls-files -f >actual &&
 157        test_cmp expect actual
 158'
 159
 160cat >expect <<EOF &&
 161H dir1/modified
 162h dir1/new
 163H dir1/tracked
 164H dir2/modified
 165h dir2/new
 166H dir2/tracked
 167H modified
 168h new
 169H tracked
 170EOF
 171
 172# test that newly added files are marked valid
 173test_expect_success 'newly added files are marked valid' '
 174        git add new &&
 175        git add dir1/new &&
 176        git add dir2/new &&
 177        git ls-files -f >actual &&
 178        test_cmp expect actual
 179'
 180
 181cat >expect <<EOF &&
 182H dir1/modified
 183h dir1/new
 184h dir1/tracked
 185H dir2/modified
 186h dir2/new
 187h dir2/tracked
 188H modified
 189h new
 190h tracked
 191EOF
 192
 193# test that all unmodified files get marked valid
 194test_expect_success 'all unmodified files get marked valid' '
 195        # modified files result in update-index returning 1
 196        test_must_fail git update-index --refresh --force-write-index &&
 197        git ls-files -f >actual &&
 198        test_cmp expect actual
 199'
 200
 201cat >expect <<EOF &&
 202H dir1/modified
 203h dir1/tracked
 204h dir2/modified
 205h dir2/tracked
 206h modified
 207h tracked
 208EOF
 209
 210# test that *only* files returned by the integration script get flagged as invalid
 211test_expect_success '*only* files returned by the integration script get flagged as invalid' '
 212        write_script .git/hooks/fsmonitor-test<<-\EOF &&
 213        printf "dir1/modified\0"
 214        EOF
 215        clean_repo &&
 216        git update-index --refresh --force-write-index &&
 217        echo 1 >modified &&
 218        echo 2 >dir1/modified &&
 219        echo 3 >dir2/modified &&
 220        test_must_fail git update-index --refresh --force-write-index &&
 221        git ls-files -f >actual &&
 222        test_cmp expect actual
 223'
 224
 225# Ensure commands that call refresh_index() to move the index back in time
 226# properly invalidate the fsmonitor cache
 227test_expect_success 'refresh_index() invalidates fsmonitor cache' '
 228        write_script .git/hooks/fsmonitor-test<<-\EOF &&
 229        EOF
 230        clean_repo &&
 231        dirty_repo &&
 232        git add . &&
 233        git commit -m "to reset" &&
 234        git reset HEAD~1 &&
 235        git status >actual &&
 236        git -c core.fsmonitor= status >expect &&
 237        test_i18ncmp expect actual
 238'
 239
 240# test fsmonitor with and without preloadIndex
 241preload_values="false true"
 242for preload_val in $preload_values
 243do
 244        test_expect_success "setup preloadIndex to $preload_val" '
 245                git config core.preloadIndex $preload_val &&
 246                if test $preload_val = true
 247                then
 248                        GIT_FORCE_PRELOAD_TEST=$preload_val; export GIT_FORCE_PRELOAD_TEST
 249                else
 250                        unset GIT_FORCE_PRELOAD_TEST
 251                fi
 252        '
 253
 254        # test fsmonitor with and without the untracked cache (if available)
 255        uc_values="false"
 256        test_have_prereq UNTRACKED_CACHE && uc_values="false true"
 257        for uc_val in $uc_values
 258        do
 259                test_expect_success "setup untracked cache to $uc_val" '
 260                        git config core.untrackedcache $uc_val
 261                '
 262
 263                # Status is well tested elsewhere so we'll just ensure that the results are
 264                # the same when using core.fsmonitor.
 265                test_expect_success 'compare status with and without fsmonitor' '
 266                        write_integration_script &&
 267                        clean_repo &&
 268                        dirty_repo &&
 269                        git add new &&
 270                        git add dir1/new &&
 271                        git add dir2/new &&
 272                        git status >actual &&
 273                        git -c core.fsmonitor= status >expect &&
 274                        test_i18ncmp expect actual
 275                '
 276
 277                # Make sure it's actually skipping the check for modified and untracked
 278                # (if enabled) files unless it is told about them.
 279                test_expect_success "status doesn't detect unreported modifications" '
 280                        write_script .git/hooks/fsmonitor-test<<-\EOF &&
 281                        :>marker
 282                        EOF
 283                        clean_repo &&
 284                        git status &&
 285                        test_path_is_file marker &&
 286                        dirty_repo &&
 287                        rm -f marker &&
 288                        git status >actual &&
 289                        test_path_is_file marker &&
 290                        test_i18ngrep ! "Changes not staged for commit:" actual &&
 291                        if test $uc_val = true
 292                        then
 293                                test_i18ngrep ! "Untracked files:" actual
 294                        fi &&
 295                        if test $uc_val = false
 296                        then
 297                                test_i18ngrep "Untracked files:" actual
 298                        fi &&
 299                        rm -f marker
 300                '
 301        done
 302done
 303
 304# test that splitting the index dosn't interfere
 305test_expect_success 'splitting the index results in the same state' '
 306        write_integration_script &&
 307        dirty_repo &&
 308        git update-index --fsmonitor  &&
 309        git ls-files -f >expect &&
 310        test-dump-fsmonitor >&2 && echo &&
 311        git update-index --fsmonitor --split-index &&
 312        test-dump-fsmonitor >&2 && echo &&
 313        git ls-files -f >actual &&
 314        test_cmp expect actual
 315'
 316
 317test_expect_success UNTRACKED_CACHE 'ignore .git changes when invalidating UNTR' '
 318        test_create_repo dot-git &&
 319        (
 320                cd dot-git &&
 321                mkdir -p .git/hooks &&
 322                : >tracked &&
 323                : >modified &&
 324                mkdir dir1 &&
 325                : >dir1/tracked &&
 326                : >dir1/modified &&
 327                mkdir dir2 &&
 328                : >dir2/tracked &&
 329                : >dir2/modified &&
 330                write_integration_script &&
 331                git config core.fsmonitor .git/hooks/fsmonitor-test &&
 332                git update-index --untracked-cache &&
 333                git update-index --fsmonitor &&
 334                GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace-before" \
 335                git status &&
 336                test-dump-untracked-cache >../before
 337        ) &&
 338        cat >>dot-git/.git/hooks/fsmonitor-test <<-\EOF &&
 339        printf ".git\0"
 340        printf ".git/index\0"
 341        printf "dir1/.git\0"
 342        printf "dir1/.git/index\0"
 343        EOF
 344        (
 345                cd dot-git &&
 346                GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace-after" \
 347                git status &&
 348                test-dump-untracked-cache >../after
 349        ) &&
 350        grep "directory invalidation" trace-before >>before &&
 351        grep "directory invalidation" trace-after >>after &&
 352        # UNTR extension unchanged, dir invalidation count unchanged
 353        test_cmp before after
 354'
 355
 356test_done