use strpbrk(3) to search for characters from a given set
[git/debian.git] / t / t7519-status-fsmonitor.sh
blobcf0fda2d5aa534d3ed4f64be48a52201535d854f
1 #!/bin/sh
3 test_description='git status with file system watcher'
5 . ./test-lib.sh
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.
11 clean_repo () {
12 git reset --hard HEAD &&
13 git clean -fd
16 dirty_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
28 write_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
35 if test "$1" != 1
36 then
37 echo "Unsupported core.fsmonitor hook version." >&2
38 exit 1
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
52 test_lazy_prereq UNTRACKED_CACHE '
53 { git update-index --test-untracked-cache; ret=$?; } &&
54 test $ret -ne 1
57 test_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
78 # test that the fsmonitor extension is off by default
79 test_expect_success 'fsmonitor extension is off by default' '
80 test-tool dump-fsmonitor >actual &&
81 grep "^no fsmonitor" actual
84 # test that "update-index --fsmonitor" adds the fsmonitor extension
85 test_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
91 # test that "update-index --no-fsmonitor" removes the fsmonitor extension
92 test_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
98 cat >expect <<EOF &&
99 h dir1/modified
100 H dir1/tracked
101 h dir2/modified
102 H dir2/tracked
103 h modified
104 H tracked
107 # test that "update-index --fsmonitor-valid" sets the fsmonitor valid bit
108 test_expect_success 'update-index --fsmonitor-valid" sets the fsmonitor valid bit' '
109 write_script .git/hooks/fsmonitor-test<<-\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
119 cat >expect <<EOF &&
120 H dir1/modified
121 H dir1/tracked
122 H dir2/modified
123 H dir2/tracked
124 H modified
125 H tracked
128 # test that "update-index --no-fsmonitor-valid" clears the fsmonitor valid bit
129 test_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
137 cat >expect <<EOF &&
138 H dir1/modified
139 H dir1/tracked
140 H dir2/modified
141 H dir2/tracked
142 H modified
143 H tracked
146 # test that all files returned by the script get flagged as invalid
147 test_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
155 cat >expect <<EOF &&
156 H dir1/modified
157 h dir1/new
158 H dir1/tracked
159 H dir2/modified
160 h dir2/new
161 H dir2/tracked
162 H modified
163 h new
164 H tracked
167 # test that newly added files are marked valid
168 test_expect_success 'newly added files are marked valid' '
169 write_script .git/hooks/fsmonitor-test<<-\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
178 cat >expect <<EOF &&
179 H dir1/modified
180 h dir1/new
181 h dir1/tracked
182 H dir2/modified
183 h dir2/new
184 h dir2/tracked
185 H modified
186 h new
187 h tracked
190 # test that all unmodified files get marked valid
191 test_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
198 cat >expect <<EOF &&
199 H dir1/modified
200 h dir1/tracked
201 h dir2/modified
202 h dir2/tracked
203 h modified
204 h tracked
207 # test that *only* files returned by the integration script get flagged as invalid
208 test_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"
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
222 # Ensure commands that call refresh_index() to move the index back in time
223 # properly invalidate the fsmonitor cache
224 test_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 &&
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
238 # test fsmonitor with and without preloadIndex
239 preload_values="false true"
240 for preload_val in $preload_values
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
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
257 test_expect_success "setup untracked cache to $uc_val" '
258 git config core.untrackedcache $uc_val
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
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
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
299 done
300 done
302 # test that splitting the index doesn't interfere
303 test_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
315 test_expect_success UNTRACKED_CACHE 'ignore .git changes when invalidating UNTR' '
316 test_create_repo dot-git &&
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"
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
354 test_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
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.
366 test_expect_success 'status succeeds after staging/unstaging' '
367 test_create_repo fsmonitor-stage-unstage &&
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
381 test_done