Merge branch 'ab/submodule-relative-url-tests'
[git] / t / t7519-status-fsmonitor.sh
1 #!/bin/sh
2
3 test_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
18 clean_repo () {
19         git reset --hard HEAD &&
20         git clean -fd
21 }
22
23 dirty_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
35 write_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
59 test_lazy_prereq UNTRACKED_CACHE '
60         { git update-index --test-untracked-cache; ret=$?; } &&
61         test $ret -ne 1
62 '
63
64 test_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
86 test_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
92 test_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
99 test_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
105 cat >expect <<EOF &&
106 h dir1/modified
107 H dir1/tracked
108 h dir2/modified
109 H dir2/tracked
110 h modified
111 H tracked
112 EOF
113
114 # test that "update-index --fsmonitor-valid" sets the fsmonitor valid bit
115 test_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
124 cat >expect <<EOF &&
125 H dir1/modified
126 H dir1/tracked
127 H dir2/modified
128 H dir2/tracked
129 H modified
130 H tracked
131 EOF
132
133 # test that "update-index --no-fsmonitor-valid" clears the fsmonitor valid bit
134 test_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
142 cat >expect <<EOF &&
143 H dir1/modified
144 H dir1/tracked
145 H dir2/modified
146 H dir2/tracked
147 H modified
148 H tracked
149 EOF
150
151 # test that all files returned by the script get flagged as invalid
152 test_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
160 cat >expect <<EOF &&
161 H dir1/modified
162 h dir1/new
163 H dir1/tracked
164 H dir2/modified
165 h dir2/new
166 H dir2/tracked
167 H modified
168 h new
169 H tracked
170 EOF
171
172 # test that newly added files are marked valid
173 test_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
181 cat >expect <<EOF &&
182 H dir1/modified
183 h dir1/new
184 h dir1/tracked
185 H dir2/modified
186 h dir2/new
187 h dir2/tracked
188 H modified
189 h new
190 h tracked
191 EOF
192
193 # test that all unmodified files get marked valid
194 test_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
201 cat >expect <<EOF &&
202 H dir1/modified
203 h dir1/tracked
204 h dir2/modified
205 h dir2/tracked
206 h modified
207 h tracked
208 EOF
209
210 # test that *only* files returned by the integration script get flagged as invalid
211 test_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
227 test_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
241 preload_values="false true"
242 for preload_val in $preload_values
243 do
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
302 done
303
304 # test that splitting the index dosn't interfere
305 test_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
317 test_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
356 test_done