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-tool 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-tool 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-tool 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-tool dump-fsmonitor >&2 && echo &&
311 git update-index --fsmonitor --split-index &&
312 test-tool 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-tool 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-tool 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