1#!/bin/sh
2#
3# Copyright (c) 2009 Jens Lehmann, based on t7401 by Ping Yin
4# Copyright (c) 2011 Alexey Shumkin (+ non-UTF-8 commit encoding tests)
5#
6
7test_description='Support for verbose submodule differences in git diff
8
9This test tries to verify the sanity of the --submodule option of git diff.
10'
11
12. ./test-lib.sh
13
14# Tested non-UTF-8 encoding
15test_encoding="ISO8859-1"
16
17# String "added" in German (translated with Google Translate), encoded in UTF-8,
18# used in sample commit log messages in add_file() function below.
19added=$(printf "hinzugef\303\274gt")
20add_file () {
21	(
22		cd "$1" &&
23		shift &&
24		for name
25		do
26			echo "$name" >"$name" &&
27			git add "$name" &&
28			test_tick &&
29			# "git commit -m" would break MinGW, as Windows refuse to pass
30			# $test_encoding encoded parameter to git.
31			echo "Add $name ($added $name)" | iconv -f utf-8 -t $test_encoding |
32			git -c "i18n.commitEncoding=$test_encoding" commit -F -
33		done >/dev/null &&
34		git rev-parse --short --verify HEAD
35	)
36}
37commit_file () {
38	test_tick &&
39	git commit "$@" -m "Commit $*" >/dev/null
40}
41
42test_create_repo sm1 &&
43add_file . foo >/dev/null
44
45head1=$(add_file sm1 foo1 foo2)
46fullhead1=$(cd sm1; git rev-parse --verify HEAD)
47
48test_expect_success 'added submodule' '
49	git add sm1 &&
50	git diff-index -p --submodule=log HEAD >actual &&
51	cat >expected <<-EOF &&
52	Submodule sm1 0000000...$head1 (new submodule)
53	EOF
54	test_cmp expected actual
55'
56
57test_expect_success 'added submodule, set diff.submodule' '
58	git config diff.submodule log &&
59	git add sm1 &&
60	git diff --cached >actual &&
61	cat >expected <<-EOF &&
62	Submodule sm1 0000000...$head1 (new submodule)
63	EOF
64	git config --unset diff.submodule &&
65	test_cmp expected actual
66'
67
68test_expect_success '--submodule=short overrides diff.submodule' '
69	test_config diff.submodule log &&
70	git add sm1 &&
71	git diff --submodule=short --cached >actual &&
72	cat >expected <<-EOF &&
73	diff --git a/sm1 b/sm1
74	new file mode 160000
75	index 0000000..$head1
76	--- /dev/null
77	+++ b/sm1
78	@@ -0,0 +1 @@
79	+Subproject commit $fullhead1
80	EOF
81	test_cmp expected actual
82'
83
84test_expect_success 'diff.submodule does not affect plumbing' '
85	test_config diff.submodule log &&
86	git diff-index -p HEAD >actual &&
87	cat >expected <<-EOF &&
88	diff --git a/sm1 b/sm1
89	new file mode 160000
90	index 0000000..$head1
91	--- /dev/null
92	+++ b/sm1
93	@@ -0,0 +1 @@
94	+Subproject commit $fullhead1
95	EOF
96	test_cmp expected actual
97'
98
99commit_file sm1 &&
100head2=$(add_file sm1 foo3)
101
102test_expect_success 'modified submodule(forward)' '
103	git diff-index -p --submodule=log HEAD >actual &&
104	cat >expected <<-EOF &&
105	Submodule sm1 $head1..$head2:
106	  > Add foo3 ($added foo3)
107	EOF
108	test_cmp expected actual
109'
110
111test_expect_success 'modified submodule(forward)' '
112	git diff --submodule=log >actual &&
113	cat >expected <<-EOF &&
114	Submodule sm1 $head1..$head2:
115	  > Add foo3 ($added foo3)
116	EOF
117	test_cmp expected actual
118'
119
120test_expect_success 'modified submodule(forward) --submodule' '
121	git diff --submodule >actual &&
122	cat >expected <<-EOF &&
123	Submodule sm1 $head1..$head2:
124	  > Add foo3 ($added foo3)
125	EOF
126	test_cmp expected actual
127'
128
129fullhead2=$(cd sm1; git rev-parse --verify HEAD)
130test_expect_success 'modified submodule(forward) --submodule=short' '
131	git diff --submodule=short >actual &&
132	cat >expected <<-EOF &&
133	diff --git a/sm1 b/sm1
134	index $head1..$head2 160000
135	--- a/sm1
136	+++ b/sm1
137	@@ -1 +1 @@
138	-Subproject commit $fullhead1
139	+Subproject commit $fullhead2
140	EOF
141	test_cmp expected actual
142'
143
144commit_file sm1 &&
145head3=$(
146	cd sm1 &&
147	git reset --hard HEAD~2 >/dev/null &&
148	git rev-parse --short --verify HEAD
149)
150
151test_expect_success 'modified submodule(backward)' '
152	git diff-index -p --submodule=log HEAD >actual &&
153	cat >expected <<-EOF &&
154	Submodule sm1 $head2..$head3 (rewind):
155	  < Add foo3 ($added foo3)
156	  < Add foo2 ($added foo2)
157	EOF
158	test_cmp expected actual
159'
160
161head4=$(add_file sm1 foo4 foo5)
162test_expect_success 'modified submodule(backward and forward)' '
163	git diff-index -p --submodule=log HEAD >actual &&
164	cat >expected <<-EOF &&
165	Submodule sm1 $head2...$head4:
166	  > Add foo5 ($added foo5)
167	  > Add foo4 ($added foo4)
168	  < Add foo3 ($added foo3)
169	  < Add foo2 ($added foo2)
170	EOF
171	test_cmp expected actual
172'
173
174commit_file sm1 &&
175mv sm1 sm1-bak &&
176echo sm1 >sm1 &&
177head5=$(git hash-object sm1 | cut -c1-7) &&
178git add sm1 &&
179rm -f sm1 &&
180mv sm1-bak sm1
181
182test_expect_success 'typechanged submodule(submodule->blob), --cached' '
183	git diff --submodule=log --cached >actual &&
184	cat >expected <<-EOF &&
185	Submodule sm1 $head4...0000000 (submodule deleted)
186	diff --git a/sm1 b/sm1
187	new file mode 100644
188	index 0000000..$head5
189	--- /dev/null
190	+++ b/sm1
191	@@ -0,0 +1 @@
192	+sm1
193	EOF
194	test_cmp expected actual
195'
196
197test_expect_success 'typechanged submodule(submodule->blob)' '
198	git diff --submodule=log >actual &&
199	cat >expected <<-EOF &&
200	diff --git a/sm1 b/sm1
201	deleted file mode 100644
202	index $head5..0000000
203	--- a/sm1
204	+++ /dev/null
205	@@ -1 +0,0 @@
206	-sm1
207	Submodule sm1 0000000...$head4 (new submodule)
208	EOF
209	test_cmp expected actual
210'
211
212rm -rf sm1 &&
213git checkout-index sm1
214test_expect_success 'typechanged submodule(submodule->blob)' '
215	git diff-index -p --submodule=log HEAD >actual &&
216	cat >expected <<-EOF &&
217	Submodule sm1 $head4...0000000 (submodule deleted)
218	diff --git a/sm1 b/sm1
219	new file mode 100644
220	index 0000000..$head5
221	--- /dev/null
222	+++ b/sm1
223	@@ -0,0 +1 @@
224	+sm1
225	EOF
226	test_cmp expected actual
227'
228
229rm -f sm1 &&
230test_create_repo sm1 &&
231head6=$(add_file sm1 foo6 foo7)
232fullhead6=$(cd sm1; git rev-parse --verify HEAD)
233test_expect_success 'nonexistent commit' '
234	git diff-index -p --submodule=log HEAD >actual &&
235	cat >expected <<-EOF &&
236	Submodule sm1 $head4...$head6 (commits not present)
237	EOF
238	test_cmp expected actual
239'
240
241commit_file
242test_expect_success 'typechanged submodule(blob->submodule)' '
243	git diff-index -p --submodule=log HEAD >actual &&
244	cat >expected <<-EOF &&
245	diff --git a/sm1 b/sm1
246	deleted file mode 100644
247	index $head5..0000000
248	--- a/sm1
249	+++ /dev/null
250	@@ -1 +0,0 @@
251	-sm1
252	Submodule sm1 0000000...$head6 (new submodule)
253	EOF
254	test_cmp expected actual
255'
256
257commit_file sm1 &&
258test_expect_success 'submodule is up to date' '
259	git diff-index -p --submodule=log HEAD >actual &&
260	test_must_be_empty actual
261'
262
263test_expect_success 'submodule contains untracked content' '
264	echo new > sm1/new-file &&
265	git diff-index -p --submodule=log HEAD >actual &&
266	cat >expected <<-EOF &&
267	Submodule sm1 contains untracked content
268	EOF
269	test_cmp expected actual
270'
271
272test_expect_success 'submodule contains untracked content (untracked ignored)' '
273	git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual &&
274	test_must_be_empty actual
275'
276
277test_expect_success 'submodule contains untracked content (dirty ignored)' '
278	git diff-index -p --ignore-submodules=dirty --submodule=log HEAD >actual &&
279	test_must_be_empty actual
280'
281
282test_expect_success 'submodule contains untracked content (all ignored)' '
283	git diff-index -p --ignore-submodules=all --submodule=log HEAD >actual &&
284	test_must_be_empty actual
285'
286
287test_expect_success 'submodule contains untracked and modified content' '
288	echo new > sm1/foo6 &&
289	git diff-index -p --submodule=log HEAD >actual &&
290	cat >expected <<-EOF &&
291	Submodule sm1 contains untracked content
292	Submodule sm1 contains modified content
293	EOF
294	test_cmp expected actual
295'
296
297test_expect_success 'submodule contains untracked and modified content (untracked ignored)' '
298	echo new > sm1/foo6 &&
299	git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual &&
300	cat >expected <<-EOF &&
301	Submodule sm1 contains modified content
302	EOF
303	test_cmp expected actual
304'
305
306test_expect_success 'submodule contains untracked and modified content (dirty ignored)' '
307	echo new > sm1/foo6 &&
308	git diff-index -p --ignore-submodules=dirty --submodule=log HEAD >actual &&
309	test_must_be_empty actual
310'
311
312test_expect_success 'submodule contains untracked and modified content (all ignored)' '
313	echo new > sm1/foo6 &&
314	git diff-index -p --ignore-submodules --submodule=log HEAD >actual &&
315	test_must_be_empty actual
316'
317
318test_expect_success 'submodule contains modified content' '
319	rm -f sm1/new-file &&
320	git diff-index -p --submodule=log HEAD >actual &&
321	cat >expected <<-EOF &&
322	Submodule sm1 contains modified content
323	EOF
324	test_cmp expected actual
325'
326
327(cd sm1; git commit -mchange foo6 >/dev/null) &&
328head8=$(cd sm1; git rev-parse --short --verify HEAD) &&
329test_expect_success 'submodule is modified' '
330	git diff-index -p --submodule=log HEAD >actual &&
331	cat >expected <<-EOF &&
332	Submodule sm1 $head6..$head8:
333	  > change
334	EOF
335	test_cmp expected actual
336'
337
338test_expect_success 'modified submodule contains untracked content' '
339	echo new > sm1/new-file &&
340	git diff-index -p --submodule=log HEAD >actual &&
341	cat >expected <<-EOF &&
342	Submodule sm1 contains untracked content
343	Submodule sm1 $head6..$head8:
344	  > change
345	EOF
346	test_cmp expected actual
347'
348
349test_expect_success 'modified submodule contains untracked content (untracked ignored)' '
350	git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual &&
351	cat >expected <<-EOF &&
352	Submodule sm1 $head6..$head8:
353	  > change
354	EOF
355	test_cmp expected actual
356'
357
358test_expect_success 'modified submodule contains untracked content (dirty ignored)' '
359	git diff-index -p --ignore-submodules=dirty --submodule=log HEAD >actual &&
360	cat >expected <<-EOF &&
361	Submodule sm1 $head6..$head8:
362	  > change
363	EOF
364	test_cmp expected actual
365'
366
367test_expect_success 'modified submodule contains untracked content (all ignored)' '
368	git diff-index -p --ignore-submodules=all --submodule=log HEAD >actual &&
369	test_must_be_empty actual
370'
371
372test_expect_success 'modified submodule contains untracked and modified content' '
373	echo modification >> sm1/foo6 &&
374	git diff-index -p --submodule=log HEAD >actual &&
375	cat >expected <<-EOF &&
376	Submodule sm1 contains untracked content
377	Submodule sm1 contains modified content
378	Submodule sm1 $head6..$head8:
379	  > change
380	EOF
381	test_cmp expected actual
382'
383
384test_expect_success 'modified submodule contains untracked and modified content (untracked ignored)' '
385	echo modification >> sm1/foo6 &&
386	git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual &&
387	cat >expected <<-EOF &&
388	Submodule sm1 contains modified content
389	Submodule sm1 $head6..$head8:
390	  > change
391	EOF
392	test_cmp expected actual
393'
394
395test_expect_success 'modified submodule contains untracked and modified content (dirty ignored)' '
396	echo modification >> sm1/foo6 &&
397	git diff-index -p --ignore-submodules=dirty --submodule=log HEAD >actual &&
398	cat >expected <<-EOF &&
399	Submodule sm1 $head6..$head8:
400	  > change
401	EOF
402	test_cmp expected actual
403'
404
405test_expect_success 'modified submodule contains untracked and modified content (all ignored)' '
406	echo modification >> sm1/foo6 &&
407	git diff-index -p --ignore-submodules --submodule=log HEAD >actual &&
408	test_must_be_empty actual
409'
410
411test_expect_success 'modified submodule contains modified content' '
412	rm -f sm1/new-file &&
413	git diff-index -p --submodule=log HEAD >actual &&
414	cat >expected <<-EOF &&
415	Submodule sm1 contains modified content
416	Submodule sm1 $head6..$head8:
417	  > change
418	EOF
419	test_cmp expected actual
420'
421
422rm -rf sm1
423test_expect_success 'deleted submodule' '
424	git diff-index -p --submodule=log HEAD >actual &&
425	cat >expected <<-EOF &&
426	Submodule sm1 $head6...0000000 (submodule deleted)
427	EOF
428	test_cmp expected actual
429'
430
431test_expect_success 'create second submodule' '
432	test_create_repo sm2 &&
433	head7=$(add_file sm2 foo8 foo9) &&
434	git add sm2
435'
436
437test_expect_success 'multiple submodules' '
438	git diff-index -p --submodule=log HEAD >actual &&
439	cat >expected <<-EOF &&
440	Submodule sm1 $head6...0000000 (submodule deleted)
441	Submodule sm2 0000000...$head7 (new submodule)
442	EOF
443	test_cmp expected actual
444'
445
446test_expect_success 'path filter' '
447	git diff-index -p --submodule=log HEAD sm2 >actual &&
448	cat >expected <<-EOF &&
449	Submodule sm2 0000000...$head7 (new submodule)
450	EOF
451	test_cmp expected actual
452'
453
454commit_file sm2
455test_expect_success 'given commit' '
456	git diff-index -p --submodule=log HEAD^ >actual &&
457	cat >expected <<-EOF &&
458	Submodule sm1 $head6...0000000 (submodule deleted)
459	Submodule sm2 0000000...$head7 (new submodule)
460	EOF
461	test_cmp expected actual
462'
463
464test_expect_success 'given commit --submodule' '
465	git diff-index -p --submodule HEAD^ >actual &&
466	cat >expected <<-EOF &&
467	Submodule sm1 $head6...0000000 (submodule deleted)
468	Submodule sm2 0000000...$head7 (new submodule)
469	EOF
470	test_cmp expected actual
471'
472
473fullhead7=$(cd sm2; git rev-parse --verify HEAD)
474
475test_expect_success 'given commit --submodule=short' '
476	git diff-index -p --submodule=short HEAD^ >actual &&
477	cat >expected <<-EOF &&
478	diff --git a/sm1 b/sm1
479	deleted file mode 160000
480	index $head6..0000000
481	--- a/sm1
482	+++ /dev/null
483	@@ -1 +0,0 @@
484	-Subproject commit $fullhead6
485	diff --git a/sm2 b/sm2
486	new file mode 160000
487	index 0000000..$head7
488	--- /dev/null
489	+++ b/sm2
490	@@ -0,0 +1 @@
491	+Subproject commit $fullhead7
492	EOF
493	test_cmp expected actual
494'
495
496test_expect_success 'setup .git file for sm2' '
497	(cd sm2 &&
498	 REAL="$(pwd)/../.real" &&
499	 mv .git "$REAL" &&
500	 echo "gitdir: $REAL" >.git)
501'
502
503test_expect_success 'diff --submodule with .git file' '
504	git diff --submodule HEAD^ >actual &&
505	cat >expected <<-EOF &&
506	Submodule sm1 $head6...0000000 (submodule deleted)
507	Submodule sm2 0000000...$head7 (new submodule)
508	EOF
509	test_cmp expected actual
510'
511
512test_expect_success 'diff --submodule with objects referenced by alternates' '
513	mkdir sub_alt &&
514	(cd sub_alt &&
515		git init &&
516		echo a >a &&
517		git add a &&
518		git commit -m a
519	) &&
520	mkdir super &&
521	(cd super &&
522		git clone -s ../sub_alt sub &&
523		git init &&
524		git add sub &&
525		git commit -m "sub a"
526	) &&
527	(cd sub_alt &&
528		sha1_before=$(git rev-parse --short HEAD) &&
529		echo b >b &&
530		git add b &&
531		git commit -m b &&
532		sha1_after=$(git rev-parse --short HEAD) &&
533		{
534			echo "Submodule sub $sha1_before..$sha1_after:" &&
535			echo "  > b"
536		} >../expected
537	) &&
538	(cd super &&
539		(cd sub &&
540			git fetch &&
541			git checkout origin/master
542		) &&
543		git diff --submodule > ../actual
544	) &&
545	test_cmp expected actual
546'
547
548test_done
549