1#!/bin/sh
2
3test_description='read-tree -m -u checks working tree files'
4
5GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
6export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
7
8. ./test-lib.sh
9. "$TEST_DIRECTORY"/lib-read-tree.sh
10
11# two-tree test
12
13test_expect_success 'two-way setup' '
14
15	mkdir subdir &&
16	echo >file1 file one &&
17	echo >file2 file two &&
18	echo >subdir/file1 file one in subdirectory &&
19	echo >subdir/file2 file two in subdirectory &&
20	git update-index --add file1 file2 subdir/file1 subdir/file2 &&
21	git commit -m initial &&
22
23	git branch side &&
24	git tag -f branch-point &&
25
26	echo file2 is not tracked on the main branch anymore &&
27	rm -f file2 subdir/file2 &&
28	git update-index --remove file2 subdir/file2 &&
29	git commit -a -m "main removes file2 and subdir/file2"
30'
31
32test_expect_success 'two-way not clobbering' '
33
34	echo >file2 main creates untracked file2 &&
35	echo >subdir/file2 main creates untracked subdir/file2 &&
36	if err=$(read_tree_u_must_succeed -m -u main side 2>&1)
37	then
38		echo should have complained
39		false
40	else
41		echo "happy to see $err"
42	fi
43'
44
45echo file2 >.gitignore
46
47test_expect_success 'two-way with incorrect --exclude-per-directory (1)' '
48
49	if err=$(read_tree_u_must_succeed -m --exclude-per-directory=.gitignore main side 2>&1)
50	then
51		echo should have complained
52		false
53	else
54		echo "happy to see $err"
55	fi
56'
57
58test_expect_success 'two-way with incorrect --exclude-per-directory (2)' '
59
60	if err=$(read_tree_u_must_succeed -m -u --exclude-per-directory=foo --exclude-per-directory=.gitignore main side 2>&1)
61	then
62		echo should have complained
63		false
64	else
65		echo "happy to see $err"
66	fi
67'
68
69test_expect_success 'two-way clobbering a ignored file' '
70
71	read_tree_u_must_succeed -m -u --exclude-per-directory=.gitignore main side
72'
73
74rm -f .gitignore
75
76# three-tree test
77
78test_expect_success 'three-way not complaining on an untracked path in both' '
79
80	rm -f file2 subdir/file2 &&
81	git checkout side &&
82	echo >file3 file three &&
83	echo >subdir/file3 file three &&
84	git update-index --add file3 subdir/file3 &&
85	git commit -a -m "side adds file3 and removes file2" &&
86
87	git checkout main &&
88	echo >file2 file two is untracked on the main side &&
89	echo >subdir/file2 file two is untracked on the main side &&
90
91	read_tree_u_must_succeed -m -u branch-point main side
92'
93
94test_expect_success 'three-way not clobbering a working tree file' '
95
96	git reset --hard &&
97	rm -f file2 subdir/file2 file3 subdir/file3 &&
98	git checkout main &&
99	echo >file3 file three created in main, untracked &&
100	echo >subdir/file3 file three created in main, untracked &&
101	if err=$(read_tree_u_must_succeed -m -u branch-point main side 2>&1)
102	then
103		echo should have complained
104		false
105	else
106		echo "happy to see $err"
107	fi
108'
109
110echo >.gitignore file3
111
112test_expect_success 'three-way not complaining on an untracked file' '
113
114	git reset --hard &&
115	rm -f file2 subdir/file2 file3 subdir/file3 &&
116	git checkout main &&
117	echo >file3 file three created in main, untracked &&
118	echo >subdir/file3 file three created in main, untracked &&
119
120	read_tree_u_must_succeed -m -u --exclude-per-directory=.gitignore branch-point main side
121'
122
123test_expect_success '3-way not overwriting local changes (setup)' '
124
125	git reset --hard &&
126	git checkout -b side-a branch-point &&
127	echo >>file1 "new line to be kept in the merge result" &&
128	git commit -a -m "side-a changes file1" &&
129	git checkout -b side-b branch-point &&
130	echo >>file2 "new line to be kept in the merge result" &&
131	git commit -a -m "side-b changes file2" &&
132	git checkout side-a
133
134'
135
136test_expect_success '3-way not overwriting local changes (our side)' '
137
138	# At this point, file1 from side-a should be kept as side-b
139	# did not touch it.
140
141	git reset --hard &&
142
143	echo >>file1 "local changes" &&
144	read_tree_u_must_succeed -m -u branch-point side-a side-b &&
145	grep "new line to be kept" file1 &&
146	grep "local changes" file1
147
148'
149
150test_expect_success '3-way not overwriting local changes (their side)' '
151
152	# At this point, file2 from side-b should be taken as side-a
153	# did not touch it.
154
155	git reset --hard &&
156
157	echo >>file2 "local changes" &&
158	read_tree_u_must_fail -m -u branch-point side-a side-b &&
159	! grep "new line to be kept" file2 &&
160	grep "local changes" file2
161
162'
163
164test_expect_success 'funny symlink in work tree' '
165
166	git reset --hard &&
167	git checkout -b sym-b side-b &&
168	mkdir -p a &&
169	>a/b &&
170	git add a/b &&
171	git commit -m "side adds a/b" &&
172
173	rm -fr a &&
174	git checkout -b sym-a side-a &&
175	mkdir -p a &&
176	test_ln_s_add ../b a/b &&
177	git commit -m "we add a/b" &&
178
179	read_tree_u_must_succeed -m -u sym-a sym-a sym-b
180
181'
182
183test_expect_success SANITY 'funny symlink in work tree, un-unlink-able' '
184
185	test_when_finished "chmod u+w a 2>/dev/null; rm -fr a b" &&
186
187	rm -fr a b &&
188	git reset --hard &&
189
190	git checkout sym-a &&
191	chmod a-w a &&
192	test_must_fail git read-tree -m -u sym-a sym-a sym-b
193
194'
195
196test_expect_success 'D/F setup' '
197
198	git reset --hard &&
199
200	git checkout side-a &&
201	rm -f subdir/file2 &&
202	mkdir subdir/file2 &&
203	echo qfwfq >subdir/file2/another &&
204	git add subdir/file2/another &&
205	test_tick &&
206	git commit -m "side-a changes file2 to directory"
207
208'
209
210test_expect_success 'D/F' '
211
212	git checkout side-b &&
213	read_tree_u_must_succeed -m -u branch-point side-b side-a &&
214	git ls-files -u >actual &&
215	(
216		a=$(git rev-parse branch-point:subdir/file2) &&
217		b=$(git rev-parse side-a:subdir/file2/another) &&
218		echo "100644 $a 1	subdir/file2" &&
219		echo "100644 $a 2	subdir/file2" &&
220		echo "100644 $b 3	subdir/file2/another"
221	) >expect &&
222	test_cmp expect actual
223
224'
225
226test_expect_success 'D/F resolve' '
227
228	git reset --hard &&
229	git checkout side-b &&
230	git merge-resolve branch-point -- side-b side-a
231
232'
233
234test_expect_success 'D/F recursive' '
235
236	git reset --hard &&
237	git checkout side-b &&
238	git merge-recursive branch-point -- side-b side-a
239
240'
241
242test_done
243