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