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 write_script .git/hooks/fsmonitor-test<<-\EOF && 110 EOF 111 git update-index --fsmonitor && 112 git update-index --fsmonitor-valid dir1/modified && 113 git update-index --fsmonitor-valid dir2/modified && 114 git update-index --fsmonitor-valid modified && 115 git ls-files -f >actual && 116 test_cmp expect actual 117' 118 119cat >expect <<EOF && 120H dir1/modified 121H dir1/tracked 122H dir2/modified 123H dir2/tracked 124H modified 125H tracked 126EOF 127 128# test that "update-index --no-fsmonitor-valid" clears the fsmonitor valid bit 129test_expect_success 'update-index --no-fsmonitor-valid" clears the fsmonitor valid bit' ' 130 git update-index --no-fsmonitor-valid dir1/modified && 131 git update-index --no-fsmonitor-valid dir2/modified && 132 git update-index --no-fsmonitor-valid modified && 133 git ls-files -f >actual && 134 test_cmp expect actual 135' 136 137cat >expect <<EOF && 138H dir1/modified 139H dir1/tracked 140H dir2/modified 141H dir2/tracked 142H modified 143H tracked 144EOF 145 146# test that all files returned by the script get flagged as invalid 147test_expect_success 'all files returned by integration script get flagged as invalid' ' 148 write_integration_script && 149 dirty_repo && 150 git update-index --fsmonitor && 151 git ls-files -f >actual && 152 test_cmp expect actual 153' 154 155cat >expect <<EOF && 156H dir1/modified 157h dir1/new 158H dir1/tracked 159H dir2/modified 160h dir2/new 161H dir2/tracked 162H modified 163h new 164H tracked 165EOF 166 167# test that newly added files are marked valid 168test_expect_success 'newly added files are marked valid' ' 169 write_script .git/hooks/fsmonitor-test<<-\EOF && 170 EOF 171 git add new && 172 git add dir1/new && 173 git add dir2/new && 174 git ls-files -f >actual && 175 test_cmp expect actual 176' 177 178cat >expect <<EOF && 179H dir1/modified 180h dir1/new 181h dir1/tracked 182H dir2/modified 183h dir2/new 184h dir2/tracked 185H modified 186h new 187h tracked 188EOF 189 190# test that all unmodified files get marked valid 191test_expect_success 'all unmodified files get marked valid' ' 192 # modified files result in update-index returning 1 193 test_must_fail git update-index --refresh --force-write-index && 194 git ls-files -f >actual && 195 test_cmp expect actual 196' 197 198cat >expect <<EOF && 199H dir1/modified 200h dir1/tracked 201h dir2/modified 202h dir2/tracked 203h modified 204h tracked 205EOF 206 207# test that *only* files returned by the integration script get flagged as invalid 208test_expect_success '*only* files returned by the integration script get flagged as invalid' ' 209 write_script .git/hooks/fsmonitor-test<<-\EOF && 210 printf "dir1/modified\0" 211 EOF 212 clean_repo && 213 git update-index --refresh --force-write-index && 214 echo 1 >modified && 215 echo 2 >dir1/modified && 216 echo 3 >dir2/modified && 217 test_must_fail git update-index --refresh --force-write-index && 218 git ls-files -f >actual && 219 test_cmp expect actual 220' 221 222# Ensure commands that call refresh_index() to move the index back in time 223# properly invalidate the fsmonitor cache 224test_expect_success 'refresh_index() invalidates fsmonitor cache' ' 225 clean_repo && 226 dirty_repo && 227 write_integration_script && 228 git add . && 229 write_script .git/hooks/fsmonitor-test<<-\EOF && 230 EOF 231 git commit -m "to reset" && 232 git reset HEAD~1 && 233 git status >actual && 234 git -c core.fsmonitor= status >expect && 235 test_i18ncmp expect actual 236' 237 238# test fsmonitor with and without preloadIndex 239preload_values="false true" 240for preload_val in $preload_values 241do 242 test_expect_success "setup preloadIndex to $preload_val" ' 243 git config core.preloadIndex $preload_val && 244 if test $preload_val = true 245 then 246 GIT_TEST_PRELOAD_INDEX=$preload_val; export GIT_TEST_PRELOAD_INDEX 247 else 248 sane_unset GIT_TEST_PRELOAD_INDEX 249 fi 250 ' 251 252 # test fsmonitor with and without the untracked cache (if available) 253 uc_values="false" 254 test_have_prereq UNTRACKED_CACHE && uc_values="false true" 255 for uc_val in $uc_values 256 do 257 test_expect_success "setup untracked cache to $uc_val" ' 258 git config core.untrackedcache $uc_val 259 ' 260 261 # Status is well tested elsewhere so we'll just ensure that the results are 262 # the same when using core.fsmonitor. 263 test_expect_success 'compare status with and without fsmonitor' ' 264 write_integration_script && 265 clean_repo && 266 dirty_repo && 267 git add new && 268 git add dir1/new && 269 git add dir2/new && 270 git status >actual && 271 git -c core.fsmonitor= status >expect && 272 test_i18ncmp expect actual 273 ' 274 275 # Make sure it's actually skipping the check for modified and untracked 276 # (if enabled) files unless it is told about them. 277 test_expect_success "status doesn't detect unreported modifications" ' 278 write_script .git/hooks/fsmonitor-test<<-\EOF && 279 :>marker 280 EOF 281 clean_repo && 282 git status && 283 test_path_is_file marker && 284 dirty_repo && 285 rm -f marker && 286 git status >actual && 287 test_path_is_file marker && 288 test_i18ngrep ! "Changes not staged for commit:" actual && 289 if test $uc_val = true 290 then 291 test_i18ngrep ! "Untracked files:" actual 292 fi && 293 if test $uc_val = false 294 then 295 test_i18ngrep "Untracked files:" actual 296 fi && 297 rm -f marker 298 ' 299 done 300done 301 302# test that splitting the index doesn't interfere 303test_expect_success 'splitting the index results in the same state' ' 304 write_integration_script && 305 dirty_repo && 306 git update-index --fsmonitor && 307 git ls-files -f >expect && 308 test-tool dump-fsmonitor >&2 && echo && 309 git update-index --fsmonitor --split-index && 310 test-tool dump-fsmonitor >&2 && echo && 311 git ls-files -f >actual && 312 test_cmp expect actual 313' 314 315test_expect_success UNTRACKED_CACHE 'ignore .git changes when invalidating UNTR' ' 316 test_create_repo dot-git && 317 ( 318 cd dot-git && 319 mkdir -p .git/hooks && 320 : >tracked && 321 : >modified && 322 mkdir dir1 && 323 : >dir1/tracked && 324 : >dir1/modified && 325 mkdir dir2 && 326 : >dir2/tracked && 327 : >dir2/modified && 328 write_integration_script && 329 git config core.fsmonitor .git/hooks/fsmonitor-test && 330 git update-index --untracked-cache && 331 git update-index --fsmonitor && 332 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace-before" \ 333 git status && 334 test-tool dump-untracked-cache >../before 335 ) && 336 cat >>dot-git/.git/hooks/fsmonitor-test <<-\EOF && 337 printf ".git\0" 338 printf ".git/index\0" 339 printf "dir1/.git\0" 340 printf "dir1/.git/index\0" 341 EOF 342 ( 343 cd dot-git && 344 GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace-after" \ 345 git status && 346 test-tool dump-untracked-cache >../after 347 ) && 348 grep "directory invalidation" trace-before >>before && 349 grep "directory invalidation" trace-after >>after && 350 # UNTR extension unchanged, dir invalidation count unchanged 351 test_cmp before after 352' 353 354test_expect_success 'discard_index() also discards fsmonitor info' ' 355 test_config core.fsmonitor "$TEST_DIRECTORY/t7519/fsmonitor-all" && 356 test_might_fail git update-index --refresh && 357 test-tool read-cache --print-and-refresh=tracked 2 >actual && 358 printf "tracked is%s up to date\n" "" " not" >expect && 359 test_cmp expect actual 360' 361 362# Test unstaging entries that: 363# - Are not flagged with CE_FSMONITOR_VALID 364# - Have a position in the index >= the number of entries present in the index 365# after unstaging. 366test_expect_success 'status succeeds after staging/unstaging' ' 367 test_create_repo fsmonitor-stage-unstage && 368 ( 369 cd fsmonitor-stage-unstage && 370 test_commit initial && 371 git update-index --fsmonitor && 372 removed=$(test_seq 1 100 | sed "s/^/z/") && 373 touch $removed && 374 git add $removed && 375 git config core.fsmonitor "$TEST_DIRECTORY/t7519/fsmonitor-env" && 376 FSMONITOR_LIST="$removed" git restore -S $removed && 377 FSMONITOR_LIST="$removed" git status 378 ) 379' 380 381test_done 382