Merge branch 'ps/pack-bitmap-optim'
[git] / t / t0003-attributes.sh
1 #!/bin/sh
2
3 test_description=gitattributes
4
5 . ./test-lib.sh
6
7 attr_check_basic () {
8         path="$1" expect="$2" git_opts="$3" &&
9
10         git $git_opts check-attr test -- "$path" >actual 2>err &&
11         echo "$path: test: $expect" >expect &&
12         test_cmp expect actual
13 }
14
15 attr_check () {
16         attr_check_basic "$@" &&
17         test_must_be_empty err
18 }
19
20 attr_check_quote () {
21         path="$1" quoted_path="$2" expect="$3" &&
22
23         git check-attr test -- "$path" >actual &&
24         echo "\"$quoted_path\": test: $expect" >expect &&
25         test_cmp expect actual
26
27 }
28
29 test_expect_success 'open-quoted pathname' '
30         echo "\"a test=a" >.gitattributes &&
31         attr_check a unspecified
32 '
33
34
35 test_expect_success 'setup' '
36         mkdir -p a/b/d a/c b &&
37         (
38                 echo "[attr]notest !test" &&
39                 echo "\" d \"   test=d" &&
40                 echo " e        test=e" &&
41                 echo " e\"      test=e" &&
42                 echo "f test=f" &&
43                 echo "a/i test=a/i" &&
44                 echo "onoff test -test" &&
45                 echo "offon -test test" &&
46                 echo "no notest" &&
47                 echo "A/e/F test=A/e/F"
48         ) >.gitattributes &&
49         (
50                 echo "g test=a/g" &&
51                 echo "b/g test=a/b/g"
52         ) >a/.gitattributes &&
53         (
54                 echo "h test=a/b/h" &&
55                 echo "d/* test=a/b/d/*" &&
56                 echo "d/yes notest"
57         ) >a/b/.gitattributes &&
58         (
59                 echo "global test=global"
60         ) >"$HOME"/global-gitattributes &&
61         cat <<-EOF >expect-all
62         f: test: f
63         a/f: test: f
64         a/c/f: test: f
65         a/g: test: a/g
66         a/b/g: test: a/b/g
67         b/g: test: unspecified
68         a/b/h: test: a/b/h
69         a/b/d/g: test: a/b/d/*
70         onoff: test: unset
71         offon: test: set
72         no: notest: set
73         no: test: unspecified
74         a/b/d/no: notest: set
75         a/b/d/no: test: a/b/d/*
76         a/b/d/yes: notest: set
77         a/b/d/yes: test: unspecified
78         EOF
79 '
80
81 test_expect_success 'command line checks' '
82         test_must_fail git check-attr &&
83         test_must_fail git check-attr -- &&
84         test_must_fail git check-attr test &&
85         test_must_fail git check-attr test -- &&
86         test_must_fail git check-attr -- f &&
87         echo "f" | test_must_fail git check-attr --stdin &&
88         echo "f" | test_must_fail git check-attr --stdin -- f &&
89         echo "f" | test_must_fail git check-attr --stdin test -- f &&
90         test_must_fail git check-attr "" -- f
91 '
92
93 test_expect_success 'attribute test' '
94
95         attr_check " d " d &&
96         attr_check e e &&
97         attr_check_quote e\" e\\\" e &&
98
99         attr_check f f &&
100         attr_check a/f f &&
101         attr_check a/c/f f &&
102         attr_check a/g a/g &&
103         attr_check a/b/g a/b/g &&
104         attr_check b/g unspecified &&
105         attr_check a/b/h a/b/h &&
106         attr_check a/b/d/g "a/b/d/*" &&
107         attr_check onoff unset &&
108         attr_check offon set &&
109         attr_check no unspecified &&
110         attr_check a/b/d/no "a/b/d/*" &&
111         attr_check a/b/d/yes unspecified
112 '
113
114 test_expect_success 'attribute matching is case sensitive when core.ignorecase=0' '
115
116         attr_check F unspecified "-c core.ignorecase=0" &&
117         attr_check a/F unspecified "-c core.ignorecase=0" &&
118         attr_check a/c/F unspecified "-c core.ignorecase=0" &&
119         attr_check a/G unspecified "-c core.ignorecase=0" &&
120         attr_check a/B/g a/g "-c core.ignorecase=0" &&
121         attr_check a/b/G unspecified "-c core.ignorecase=0" &&
122         attr_check a/b/H unspecified "-c core.ignorecase=0" &&
123         attr_check a/b/D/g a/g "-c core.ignorecase=0" &&
124         attr_check oNoFf unspecified "-c core.ignorecase=0" &&
125         attr_check oFfOn unspecified "-c core.ignorecase=0" &&
126         attr_check NO unspecified "-c core.ignorecase=0" &&
127         attr_check a/b/D/NO unspecified "-c core.ignorecase=0" &&
128         attr_check a/b/d/YES a/b/d/* "-c core.ignorecase=0" &&
129         attr_check a/E/f f "-c core.ignorecase=0"
130
131 '
132
133 test_expect_success 'attribute matching is case insensitive when core.ignorecase=1' '
134
135         attr_check F f "-c core.ignorecase=1" &&
136         attr_check a/F f "-c core.ignorecase=1" &&
137         attr_check a/c/F f "-c core.ignorecase=1" &&
138         attr_check a/G a/g "-c core.ignorecase=1" &&
139         attr_check a/B/g a/b/g "-c core.ignorecase=1" &&
140         attr_check a/b/G a/b/g "-c core.ignorecase=1" &&
141         attr_check a/b/H a/b/h "-c core.ignorecase=1" &&
142         attr_check a/b/D/g "a/b/d/*" "-c core.ignorecase=1" &&
143         attr_check oNoFf unset "-c core.ignorecase=1" &&
144         attr_check oFfOn set "-c core.ignorecase=1" &&
145         attr_check NO unspecified "-c core.ignorecase=1" &&
146         attr_check a/b/D/NO "a/b/d/*" "-c core.ignorecase=1" &&
147         attr_check a/b/d/YES unspecified "-c core.ignorecase=1" &&
148         attr_check a/E/f "A/e/F" "-c core.ignorecase=1"
149
150 '
151
152 test_expect_success CASE_INSENSITIVE_FS 'additional case insensitivity tests' '
153         attr_check a/B/D/g a/g "-c core.ignorecase=0" &&
154         attr_check A/B/D/NO unspecified "-c core.ignorecase=0" &&
155         attr_check A/b/h a/b/h "-c core.ignorecase=1" &&
156         attr_check a/B/D/g "a/b/d/*" "-c core.ignorecase=1" &&
157         attr_check A/B/D/NO "a/b/d/*" "-c core.ignorecase=1"
158 '
159
160 test_expect_success 'unnormalized paths' '
161         attr_check ./f f &&
162         attr_check ./a/g a/g &&
163         attr_check a/./g a/g &&
164         attr_check a/c/../b/g a/b/g
165 '
166
167 test_expect_success 'relative paths' '
168         (cd a && attr_check ../f f) &&
169         (cd a && attr_check f f) &&
170         (cd a && attr_check i a/i) &&
171         (cd a && attr_check g a/g) &&
172         (cd a && attr_check b/g a/b/g) &&
173         (cd b && attr_check ../a/f f) &&
174         (cd b && attr_check ../a/g a/g) &&
175         (cd b && attr_check ../a/b/g a/b/g)
176 '
177
178 test_expect_success 'prefixes are not confused with leading directories' '
179         attr_check a_plus/g unspecified &&
180         cat >expect <<-\EOF &&
181         a/g: test: a/g
182         a_plus/g: test: unspecified
183         EOF
184         git check-attr test a/g a_plus/g >actual &&
185         test_cmp expect actual
186 '
187
188 test_expect_success 'core.attributesfile' '
189         attr_check global unspecified &&
190         git config core.attributesfile "$HOME/global-gitattributes" &&
191         attr_check global global &&
192         git config core.attributesfile "~/global-gitattributes" &&
193         attr_check global global &&
194         echo "global test=precedence" >>.gitattributes &&
195         attr_check global precedence
196 '
197
198 test_expect_success 'attribute test: read paths from stdin' '
199         grep -v notest <expect-all >expect &&
200         sed -e "s/:.*//" <expect | git check-attr --stdin test >actual &&
201         test_cmp expect actual
202 '
203
204 test_expect_success 'attribute test: --all option' '
205         grep -v unspecified <expect-all | sort >specified-all &&
206         sed -e "s/:.*//" <expect-all | uniq >stdin-all &&
207         git check-attr --stdin --all <stdin-all | sort >actual &&
208         test_cmp specified-all actual
209 '
210
211 test_expect_success 'attribute test: --cached option' '
212         git check-attr --cached --stdin --all <stdin-all | sort >actual &&
213         test_must_be_empty actual &&
214         git add .gitattributes a/.gitattributes a/b/.gitattributes &&
215         git check-attr --cached --stdin --all <stdin-all | sort >actual &&
216         test_cmp specified-all actual
217 '
218
219 test_expect_success 'root subdir attribute test' '
220         attr_check a/i a/i &&
221         attr_check subdir/a/i unspecified
222 '
223
224 test_expect_success 'negative patterns' '
225         echo "!f test=bar" >.gitattributes &&
226         git check-attr test -- '"'"'!f'"'"' 2>errors &&
227         test_i18ngrep "Negative patterns are ignored" errors
228 '
229
230 test_expect_success 'patterns starting with exclamation' '
231         echo "\!f test=foo" >.gitattributes &&
232         attr_check "!f" foo
233 '
234
235 test_expect_success '"**" test' '
236         echo "**/f foo=bar" >.gitattributes &&
237         cat <<\EOF >expect &&
238 f: foo: bar
239 a/f: foo: bar
240 a/b/f: foo: bar
241 a/b/c/f: foo: bar
242 EOF
243         git check-attr foo -- "f" >actual 2>err &&
244         git check-attr foo -- "a/f" >>actual 2>>err &&
245         git check-attr foo -- "a/b/f" >>actual 2>>err &&
246         git check-attr foo -- "a/b/c/f" >>actual 2>>err &&
247         test_cmp expect actual &&
248         test_must_be_empty err
249 '
250
251 test_expect_success '"**" with no slashes test' '
252         echo "a**f foo=bar" >.gitattributes &&
253         git check-attr foo -- "f" >actual &&
254         cat <<\EOF >expect &&
255 f: foo: unspecified
256 af: foo: bar
257 axf: foo: bar
258 a/f: foo: unspecified
259 a/b/f: foo: unspecified
260 a/b/c/f: foo: unspecified
261 EOF
262         git check-attr foo -- "f" >actual 2>err &&
263         git check-attr foo -- "af" >>actual 2>err &&
264         git check-attr foo -- "axf" >>actual 2>err &&
265         git check-attr foo -- "a/f" >>actual 2>>err &&
266         git check-attr foo -- "a/b/f" >>actual 2>>err &&
267         git check-attr foo -- "a/b/c/f" >>actual 2>>err &&
268         test_cmp expect actual &&
269         test_must_be_empty err
270 '
271
272 test_expect_success 'using --git-dir and --work-tree' '
273         mkdir unreal real &&
274         git init real &&
275         echo "file test=in-real" >real/.gitattributes &&
276         (
277                 cd unreal &&
278                 attr_check file in-real "--git-dir ../real/.git --work-tree ../real"
279         )
280 '
281
282 test_expect_success 'setup bare' '
283         git clone --bare . bare.git
284 '
285
286 test_expect_success 'bare repository: check that .gitattribute is ignored' '
287         (
288                 cd bare.git &&
289                 (
290                         echo "f test=f" &&
291                         echo "a/i test=a/i"
292                 ) >.gitattributes &&
293                 attr_check f unspecified &&
294                 attr_check a/f unspecified &&
295                 attr_check a/c/f unspecified &&
296                 attr_check a/i unspecified &&
297                 attr_check subdir/a/i unspecified
298         )
299 '
300
301 test_expect_success 'bare repository: check that --cached honors index' '
302         (
303                 cd bare.git &&
304                 GIT_INDEX_FILE=../.git/index \
305                 git check-attr --cached --stdin --all <../stdin-all |
306                 sort >actual &&
307                 test_cmp ../specified-all actual
308         )
309 '
310
311 test_expect_success 'bare repository: test info/attributes' '
312         (
313                 cd bare.git &&
314                 (
315                         echo "f test=f" &&
316                         echo "a/i test=a/i"
317                 ) >info/attributes &&
318                 attr_check f f &&
319                 attr_check a/f f &&
320                 attr_check a/c/f f &&
321                 attr_check a/i a/i &&
322                 attr_check subdir/a/i unspecified
323         )
324 '
325
326 test_expect_success 'binary macro expanded by -a' '
327         echo "file binary" >.gitattributes &&
328         cat >expect <<-\EOF &&
329         file: binary: set
330         file: diff: unset
331         file: merge: unset
332         file: text: unset
333         EOF
334         git check-attr -a file >actual &&
335         test_cmp expect actual
336 '
337
338 test_expect_success 'query binary macro directly' '
339         echo "file binary" >.gitattributes &&
340         echo file: binary: set >expect &&
341         git check-attr binary file >actual &&
342         test_cmp expect actual
343 '
344
345 test_expect_success SYMLINKS 'set up symlink tests' '
346         echo "* test" >attr &&
347         rm -f .gitattributes
348 '
349
350 test_expect_success SYMLINKS 'symlinks respected in core.attributesFile' '
351         test_when_finished "rm symlink" &&
352         ln -s attr symlink &&
353         test_config core.attributesFile "$(pwd)/symlink" &&
354         attr_check file set
355 '
356
357 test_expect_success SYMLINKS 'symlinks respected in info/attributes' '
358         test_when_finished "rm .git/info/attributes" &&
359         ln -s ../../attr .git/info/attributes &&
360         attr_check file set
361 '
362
363 test_expect_success SYMLINKS 'symlinks not respected in-tree' '
364         test_when_finished "rm -rf .gitattributes subdir" &&
365         ln -s attr .gitattributes &&
366         mkdir subdir &&
367         ln -s ../attr subdir/.gitattributes &&
368         attr_check_basic subdir/file unspecified &&
369         test_i18ngrep "unable to access.*gitattributes" err
370 '
371
372 test_done