@@ -102,14 +102,23 @@ test_expect_success POSIXPERM 'do not use core.sharedRepository for working tree
102102 )
103103'
104104
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+
105114test_file_mode_staged () {
106115 git ls-files --stage -- " $2 " > ls-files-output &&
107- test_grep " ^ $1 " ls-files-output
116+ test_file_mode_common " $1 " ls-files-output
108117}
109118
110119test_file_mode_HEAD () {
111120 git ls-tree HEAD -- " $2 " > ls-tree-output &&
112- test_grep " ^ $1 " ls-tree-output
121+ test_file_mode_common " $1 " ls-tree-output
113122}
114123
115124test_expect_success ' git apply respects core.fileMode' '
@@ -189,6 +198,158 @@ test_expect_success 'git apply --reverse warns about incorrect file modes' '
189198 test_file_mode_HEAD 100755 mode_test
190199'
191200
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+
192353test_expect_success POSIXPERM ' patch mode for new file is canonicalized' '
193354 cat >patch <<-\EOF &&
194355 diff --git a/non-canon b/non-canon
0 commit comments