Raw
1 #!/bin/sh
2
3 test_description='applying patch with mode bits'
4
5
6 . ./test-lib.sh
7
8 test_expect_success setup '
9 echo original >file &&
10 git add file &&
11 test_tick &&
12 git commit -m initial &&
13 git tag initial &&
14 echo modified >file &&
15 git diff --stat -p >patch-0.txt &&
16 chmod +x file &&
17 git diff --stat -p >patch-1.txt &&
18 sed "s/^\(new mode \).*/\1/" <patch-1.txt >patch-empty-mode.txt &&
19 sed "s/^\(new mode \).*/\1garbage/" <patch-1.txt >patch-bogus-mode.txt
20 '
21
22 test_expect_success FILEMODE 'same mode (no index)' '
23 git reset --hard &&
24 chmod +x file &&
25 git apply patch-0.txt &&
26 test -x file
27 '
28
29 test_expect_success FILEMODE 'same mode (with index)' '
30 git reset --hard &&
31 chmod +x file &&
32 git add file &&
33 git apply --index patch-0.txt &&
34 test -x file &&
35 git diff --exit-code
36 '
37
38 test_expect_success FILEMODE 'same mode (index only)' '
39 git reset --hard &&
40 chmod +x file &&
41 git add file &&
42 git apply --cached patch-0.txt &&
43 git ls-files -s file >ls-files-output &&
44 test_grep "^100755" ls-files-output
45 '
46
47 test_expect_success FILEMODE 'mode update (no index)' '
48 git reset --hard &&
49 git apply patch-1.txt &&
50 test -x file
51 '
52
53 test_expect_success FILEMODE 'mode update (with index)' '
54 git reset --hard &&
55 git apply --index patch-1.txt &&
56 test -x file &&
57 git diff --exit-code
58 '
59
60 test_expect_success FILEMODE 'mode update (index only)' '
61 git reset --hard &&
62 git apply --cached patch-1.txt &&
63 git ls-files -s file >ls-files-output &&
64 test_grep "^100755" ls-files-output
65 '
66
67 test_expect_success FILEMODE 'empty mode is rejected' '
68 git reset --hard &&
69 test_must_fail git apply patch-empty-mode.txt 2>err &&
70 test_grep "invalid mode" err
71 '
72
73 test_expect_success FILEMODE 'bogus mode is rejected' '
74 git reset --hard &&
75 test_must_fail git apply patch-bogus-mode.txt 2>err &&
76 test_grep "invalid mode" err
77 '
78
79 test_expect_success POSIXPERM 'do not use core.sharedRepository for working tree files' '
80 git reset --hard &&
81 test_config core.sharedRepository 0666 &&
82 (
83 # Remove a default ACL if possible.
84 (setfacl -k . 2>/dev/null || true) &&
85 umask 0077 &&
86
87 # Test both files (f1) and leading dirs (d)
88 mkdir d &&
89 touch f1 d/f2 &&
90 git add f1 d/f2 &&
91 git diff --staged >patch-f1-and-f2.txt &&
92
93 rm -rf d f1 &&
94 git apply patch-f1-and-f2.txt &&
95
96 echo "-rw-------" >f1_mode.expected &&
97 echo "drwx------" >d_mode.expected &&
98 test_modebits f1 >f1_mode.actual &&
99 test_modebits d >d_mode.actual &&
100 test_cmp f1_mode.expected f1_mode.actual &&
101 test_cmp d_mode.expected d_mode.actual
102 )
103 '
104
105 test_file_mode_common () {
106 if test "$1" = "000000"
107 then
108 test_must_be_empty "$2"
109 else
110 test_grep "^$1 " "$2"
111 fi
112 }
113
114 test_file_mode_staged () {
115 git ls-files --stage -- "$2" >ls-files-output &&
116 test_file_mode_common "$1" ls-files-output
117 }
118
119 test_file_mode_HEAD () {
120 git ls-tree HEAD -- "$2" >ls-tree-output &&
121 test_file_mode_common "$1" ls-tree-output
122 }
123
124 test_expect_success 'git apply respects core.fileMode' '
125 test_config core.fileMode false &&
126 echo true >script.sh &&
127 git add --chmod=+x script.sh &&
128 test_file_mode_staged 100755 script.sh &&
129 test_tick && git commit -m "Add script" &&
130 test_file_mode_HEAD 100755 script.sh &&
131
132 echo true >>script.sh &&
133 test_tick && git commit -m "Modify script" script.sh &&
134 git format-patch -1 --stdout >patch &&
135 test_grep "^index.*100755$" patch &&
136
137 git switch -c branch HEAD^ &&
138 git apply --index patch 2>err &&
139 test_grep ! "has type 100644, expected 100755" err &&
140 git reset --hard &&
141
142 git apply patch 2>err &&
143 test_grep ! "has type 100644, expected 100755" err &&
144
145 git apply --cached patch 2>err &&
146 test_grep ! "has type 100644, expected 100755" err &&
147 git reset --hard
148 '
149
150 test_expect_success 'setup: git apply [--reverse] warns about incorrect file modes' '
151 test_config core.fileMode false &&
152
153 >mode_test &&
154 git add --chmod=-x mode_test &&
155 test_file_mode_staged 100644 mode_test &&
156 test_tick && git commit -m "add mode_test" &&
157 test_file_mode_HEAD 100644 mode_test &&
158 git tag mode_test_forward_initial &&
159
160 echo content >>mode_test &&
161 test_tick && git commit -m "append to mode_test" mode_test &&
162 test_file_mode_HEAD 100644 mode_test &&
163 git tag mode_test_reverse_initial &&
164
165 git format-patch -1 --stdout >patch &&
166 test_grep "^index .* 100644$" patch
167 '
168
169 test_expect_success 'git apply warns about incorrect file modes' '
170 test_config core.fileMode false &&
171 git reset --hard mode_test_forward_initial &&
172
173 git add --chmod=+x mode_test &&
174 test_file_mode_staged 100755 mode_test &&
175 test_tick && git commit -m "make mode_test executable" &&
176 test_file_mode_HEAD 100755 mode_test &&
177
178 git apply --index patch 2>err &&
179 test_grep "has type 100755, expected 100644" err &&
180 test_file_mode_staged 100755 mode_test &&
181 test_tick && git commit -m "redo: append to mode_test" &&
182 test_file_mode_HEAD 100755 mode_test
183 '
184
185 test_expect_success 'git apply --reverse warns about incorrect file modes' '
186 test_config core.fileMode false &&
187 git reset --hard mode_test_reverse_initial &&
188
189 git add --chmod=+x mode_test &&
190 test_file_mode_staged 100755 mode_test &&
191 test_tick && git commit -m "make mode_test executable" &&
192 test_file_mode_HEAD 100755 mode_test &&
193
194 git apply --index --reverse patch 2>err &&
195 test_grep "has type 100755, expected 100644" err &&
196 test_file_mode_staged 100755 mode_test &&
197 test_tick && git commit -m "undo: append to mode_test" &&
198 test_file_mode_HEAD 100755 mode_test
199 '
200
201 test_expect_success 'setup: git apply [--reverse] restores file modes (change_x_to_notx)' '
202 test_config core.fileMode false &&
203
204 touch change_x_to_notx &&
205 git add --chmod=+x change_x_to_notx &&
206 test_file_mode_staged 100755 change_x_to_notx &&
207 test_tick && git commit -m "add change_x_to_notx as executable" &&
208 test_file_mode_HEAD 100755 change_x_to_notx &&
209
210 git add --chmod=-x change_x_to_notx &&
211 test_file_mode_staged 100644 change_x_to_notx &&
212 test_tick && git commit -m "make change_x_to_notx not executable" &&
213 test_file_mode_HEAD 100644 change_x_to_notx &&
214
215 git rm change_x_to_notx &&
216 test_file_mode_staged 000000 change_x_to_notx &&
217 test_tick && git commit -m "remove change_x_to_notx" &&
218 test_file_mode_HEAD 000000 change_x_to_notx &&
219
220 git format-patch -o patches -3 &&
221 mv patches/0001-* change_x_to_notx-0001-create-0755.patch &&
222 mv patches/0002-* change_x_to_notx-0002-chmod-0644.patch &&
223 mv patches/0003-* change_x_to_notx-0003-delete.patch &&
224
225 test_grep "^new file mode 100755$" change_x_to_notx-0001-create-0755.patch &&
226 test_grep "^old mode 100755$" change_x_to_notx-0002-chmod-0644.patch &&
227 test_grep "^new mode 100644$" change_x_to_notx-0002-chmod-0644.patch &&
228 test_grep "^deleted file mode 100644$" change_x_to_notx-0003-delete.patch &&
229
230 git tag change_x_to_notx_initial
231 '
232
233 test_expect_success 'git apply restores file modes (change_x_to_notx)' '
234 test_config core.fileMode false &&
235 git reset --hard change_x_to_notx_initial &&
236
237 git apply --index change_x_to_notx-0001-create-0755.patch &&
238 test_file_mode_staged 100755 change_x_to_notx &&
239 test_tick && git commit -m "redo: add change_x_to_notx as executable" &&
240 test_file_mode_HEAD 100755 change_x_to_notx &&
241
242 git apply --index change_x_to_notx-0002-chmod-0644.patch 2>err &&
243 test_grep ! "has type 100.*, expected 100.*" err &&
244 test_file_mode_staged 100644 change_x_to_notx &&
245 test_tick && git commit -m "redo: make change_x_to_notx not executable" &&
246 test_file_mode_HEAD 100644 change_x_to_notx &&
247
248 git apply --index change_x_to_notx-0003-delete.patch 2>err &&
249 test_grep ! "has type 100.*, expected 100.*" err &&
250 test_file_mode_staged 000000 change_x_to_notx &&
251 test_tick && git commit -m "redo: remove change_notx_to_x" &&
252 test_file_mode_HEAD 000000 change_x_to_notx
253 '
254
255 test_expect_success 'git apply --reverse restores file modes (change_x_to_notx)' '
256 test_config core.fileMode false &&
257 git reset --hard change_x_to_notx_initial &&
258
259 git apply --index --reverse change_x_to_notx-0003-delete.patch &&
260 test_file_mode_staged 100644 change_x_to_notx &&
261 test_tick && git commit -m "undo: remove change_x_to_notx" &&
262 test_file_mode_HEAD 100644 change_x_to_notx &&
263
264 git apply --index --reverse change_x_to_notx-0002-chmod-0644.patch 2>err &&
265 test_grep ! "has type 100.*, expected 100.*" err &&
266 test_file_mode_staged 100755 change_x_to_notx &&
267 test_tick && git commit -m "undo: make change_x_to_notx not executable" &&
268 test_file_mode_HEAD 100755 change_x_to_notx &&
269
270 git apply --index --reverse change_x_to_notx-0001-create-0755.patch 2>err &&
271 test_grep ! "has type 100.*, expected 100.*" err &&
272 test_file_mode_staged 000000 change_x_to_notx &&
273 test_tick && git commit -m "undo: add change_x_to_notx as executable" &&
274 test_file_mode_HEAD 000000 change_x_to_notx
275 '
276
277 test_expect_success 'setup: git apply [--reverse] restores file modes (change_notx_to_x)' '
278 test_config core.fileMode false &&
279
280 touch change_notx_to_x &&
281 git add --chmod=-x change_notx_to_x &&
282 test_file_mode_staged 100644 change_notx_to_x &&
283 test_tick && git commit -m "add change_notx_to_x as not executable" &&
284 test_file_mode_HEAD 100644 change_notx_to_x &&
285
286 git add --chmod=+x change_notx_to_x &&
287 test_file_mode_staged 100755 change_notx_to_x &&
288 test_tick && git commit -m "make change_notx_to_x executable" &&
289 test_file_mode_HEAD 100755 change_notx_to_x &&
290
291 git rm change_notx_to_x &&
292 test_file_mode_staged 000000 change_notx_to_x &&
293 test_tick && git commit -m "remove change_notx_to_x" &&
294 test_file_mode_HEAD 000000 change_notx_to_x &&
295
296 git format-patch -o patches -3 &&
297 mv patches/0001-* change_notx_to_x-0001-create-0644.patch &&
298 mv patches/0002-* change_notx_to_x-0002-chmod-0755.patch &&
299 mv patches/0003-* change_notx_to_x-0003-delete.patch &&
300
301 test_grep "^new file mode 100644$" change_notx_to_x-0001-create-0644.patch &&
302 test_grep "^old mode 100644$" change_notx_to_x-0002-chmod-0755.patch &&
303 test_grep "^new mode 100755$" change_notx_to_x-0002-chmod-0755.patch &&
304 test_grep "^deleted file mode 100755$" change_notx_to_x-0003-delete.patch &&
305
306 git tag change_notx_to_x_initial
307 '
308
309 test_expect_success 'git apply restores file modes (change_notx_to_x)' '
310 test_config core.fileMode false &&
311 git reset --hard change_notx_to_x_initial &&
312
313 git apply --index change_notx_to_x-0001-create-0644.patch &&
314 test_file_mode_staged 100644 change_notx_to_x &&
315 test_tick && git commit -m "redo: add change_notx_to_x as not executable" &&
316 test_file_mode_HEAD 100644 change_notx_to_x &&
317
318 git apply --index change_notx_to_x-0002-chmod-0755.patch 2>err &&
319 test_grep ! "has type 100.*, expected 100.*" err &&
320 test_file_mode_staged 100755 change_notx_to_x &&
321 test_tick && git commit -m "redo: make change_notx_to_x executable" &&
322 test_file_mode_HEAD 100755 change_notx_to_x &&
323
324 git apply --index change_notx_to_x-0003-delete.patch &&
325 test_grep ! "has type 100.*, expected 100.*" err &&
326 test_file_mode_staged 000000 change_notx_to_x &&
327 test_tick && git commit -m "undo: remove change_notx_to_x" &&
328 test_file_mode_HEAD 000000 change_notx_to_x
329 '
330
331 test_expect_success 'git apply --reverse restores file modes (change_notx_to_x)' '
332 test_config core.fileMode false &&
333 git reset --hard change_notx_to_x_initial &&
334
335 git apply --index --reverse change_notx_to_x-0003-delete.patch &&
336 test_file_mode_staged 100755 change_notx_to_x &&
337 test_tick && git commit -m "undo: remove change_notx_to_x" &&
338 test_file_mode_HEAD 100755 change_notx_to_x &&
339
340 git apply --index --reverse change_notx_to_x-0002-chmod-0755.patch 2>err &&
341 test_grep ! "has type 100.*, expected 100.*" err &&
342 test_file_mode_staged 100644 change_notx_to_x &&
343 test_tick && git commit -m "undo: make change_notx_to_x executable" &&
344 test_file_mode_HEAD 100644 change_notx_to_x &&
345
346 git apply --index --reverse change_notx_to_x-0001-create-0644.patch 2>err &&
347 test_grep ! "has type 100.*, expected 100.*" err &&
348 test_file_mode_staged 000000 change_notx_to_x &&
349 test_tick && git commit -m "undo: add change_notx_to_x as not executable" &&
350 test_file_mode_HEAD 000000 change_notx_to_x
351 '
352
353 test_expect_success POSIXPERM 'patch mode for new file is canonicalized' '
354 cat >patch <<-\EOF &&
355 diff --git a/non-canon b/non-canon
356 new file mode 100660
357 --- /dev/null
358 +++ b/non-canon
359 +content
360 EOF
361 test_when_finished "git reset --hard" &&
362 (
363 umask 0 &&
364 git apply --index patch 2>err
365 ) &&
366 test_must_be_empty err &&
367 git ls-files -s -- non-canon >staged &&
368 test_grep "^100644" staged &&
369 ls -l non-canon >worktree &&
370 test_grep "^-rw-rw-rw" worktree
371 '
372
373 test_expect_success POSIXPERM 'patch mode for deleted file is canonicalized' '
374 test_when_finished "git reset --hard" &&
375 echo content >non-canon &&
376 chmod 666 non-canon &&
377 git add non-canon &&
378
379 cat >patch <<-\EOF &&
380 diff --git a/non-canon b/non-canon
381 deleted file mode 100660
382 --- a/non-canon
383 +++ /dev/null
384 @@ -1 +0,0 @@
385 -content
386 EOF
387 git apply --index patch 2>err &&
388 test_must_be_empty err &&
389 git ls-files -- non-canon >staged &&
390 test_must_be_empty staged &&
391 test_path_is_missing non-canon
392 '
393
394 test_expect_success POSIXPERM 'patch mode for mode change is canonicalized' '
395 test_when_finished "git reset --hard" &&
396 echo content >non-canon &&
397 git add non-canon &&
398
399 cat >patch <<-\EOF &&
400 diff --git a/non-canon b/non-canon
401 old mode 100660
402 new mode 100770
403 EOF
404 (
405 umask 0 &&
406 git apply --index patch 2>err
407 ) &&
408 test_must_be_empty err &&
409 git ls-files -s -- non-canon >staged &&
410 test_grep "^100755" staged &&
411 ls -l non-canon >worktree &&
412 test_grep "^-rwxrwxrwx" worktree
413 '
414
415 test_done