submodules: add the lib-submodule-update.sh test library

Add this test library to simplify covering all combinations of submodule update scenarios without having to add those to a test of each work tree manipulating command over and over again. The functions test_submodule_switch() and test_submodule_forced_switch() are intended to be called from a test script with a single argument. This argument is either a work tree manipulating command (including any command line options) or a function (when more than a single git command is needed to switch work trees from the current HEAD to another commit). This command (or function) is passed a target branch as argument. The two new functions check that each submodule transition is handled as expected, which currently means that submodule work trees are not affected until "git submodule update" is called. The "forced" variant is for commands using their '-f' or '--hard' option and expects them to overwrite local modifications as a result. Each of these two functions contains 14 tests_expect_* calls. Calling one of these test functions the first time creates a repository named "submodule_update_repo". At first it contains two files, then a single submodule is added in another commit followed by commits covering all relevant submodule modifications. This repository is newly cloned into the "submodule_update" for each test_expect_* to avoid interference between different parts of the test functions (some to-be-tested commands also manipulate refs along with the work tree, e.g. "git reset"). Follow-up commits will then call these two test functions for all work tree manipulating commands (with a combination of all their options relevant to what they do with the work tree) making sure they work as expected. Later this test library will be extended to cover merges resulting in conflicts too. Also it is intended to be easily extendable for the recursive update functionality, where even more combinations of submodule modifications have to be tested for. This version documents two bugs in current Git with expected failures: *) When a submodule is replaced with a tracked file of the same name the submodule work tree including any local modifications (and even the whole history if it uses a .git directory instead of a gitfile!) is silently removed. *) Forced work tree updates happily manipulate files in the directory of a submodule that has just been removed in the superproject (but is of course still present in the work tree due to the way submodules are currently handled). This becomes dangerous when files in the submodule directory are overwritten by files from the new superproject commit, as any modifications to the submodule files will be lost) and is expected to also destroy history in the - admittedly unlikely case - the new commit adds a file named ".git" to the submodule directory. Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jens Lehmann committed Jul 1, 2014 at 23:24 UTC 42639d2317ac8b15aae3e28468b7c86e0eb89800
1 file changed +640
t/lib-submodule-update.sh new
+640
@@ -0,0 +1,640 @@
1 +# Create a submodule layout used for all tests below.
2 +#
3 +# The following use cases are covered:
4 +# - New submodule (no_submodule => add_sub1)
5 +# - Removed submodule (add_sub1 => remove_sub1)
6 +# - Updated submodule (add_sub1 => modify_sub1)
7 +# - Submodule updated to invalid commit (add_sub1 => invalid_sub1)
8 +# - Submodule updated from invalid commit (invalid_sub1 => valid_sub1)
9 +# - Submodule replaced by tracked files in directory (add_sub1 =>
10 +# replace_sub1_with_directory)
11 +# - Directory containing tracked files replaced by submodule
12 +# (replace_sub1_with_directory => replace_directory_with_sub1)
13 +# - Submodule replaced by tracked file with the same name (add_sub1 =>
14 +# replace_sub1_with_file)
15 +# - Tracked file replaced by submodule (replace_sub1_with_file =>
16 +# replace_file_with_sub1)
17 +#
18 +# --O-----O
19 +# / ^ replace_directory_with_sub1
20 +# / replace_sub1_with_directory
21 +# /----O
22 +# / ^
23 +# / modify_sub1
24 +# O------O-------O
25 +# ^ ^\ ^
26 +# | | \ remove_sub1
27 +# | | -----O-----O
28 +# | | \ ^ replace_file_with_sub1
29 +# | | \ replace_sub1_with_file
30 +# | add_sub1 --O-----O
31 +# no_submodule ^ valid_sub1
32 +# invalid_sub1
33 +#
34 +create_lib_submodule_repo () {
35 + git init submodule_update_repo &&
36 + (
37 + cd submodule_update_repo &&
38 + echo "expect" >>.gitignore &&
39 + echo "actual" >>.gitignore &&
40 + echo "x" >file1 &&
41 + echo "y" >file2 &&
42 + git add .gitignore file1 file2 &&
43 + git commit -m "Base" &&
44 + git branch "no_submodule" &&
45 +
46 + git checkout -b "add_sub1" &&
47 + git submodule add ./. sub1 &&
48 + git config -f .gitmodules submodule.sub1.ignore all &&
49 + git config submodule.sub1.ignore all &&
50 + git add .gitmodules &&
51 + git commit -m "Add sub1" &&
52 + git checkout -b remove_sub1 &&
53 + git revert HEAD &&
54 +
55 + git checkout -b "modify_sub1" "add_sub1" &&
56 + git submodule update &&
57 + (
58 + cd sub1 &&
59 + git fetch &&
60 + git checkout -b "modifications" &&
61 + echo "z" >file2 &&
62 + echo "x" >file3 &&
63 + git add file2 file3 &&
64 + git commit -m "modified file2 and added file3" &&
65 + git push origin modifications
66 + ) &&
67 + git add sub1 &&
68 + git commit -m "Modify sub1" &&
69 +
70 + git checkout -b "replace_sub1_with_directory" "add_sub1" &&
71 + git submodule update &&
72 + (
73 + cd sub1 &&
74 + git checkout modifications
75 + ) &&
76 + git rm --cached sub1 &&
77 + rm sub1/.git* &&
78 + git config -f .gitmodules --remove-section "submodule.sub1" &&
79 + git add .gitmodules sub1/* &&
80 + git commit -m "Replace sub1 with directory" &&
81 + git checkout -b replace_directory_with_sub1 &&
82 + git revert HEAD &&
83 +
84 + git checkout -b "replace_sub1_with_file" "add_sub1" &&
85 + git rm sub1 &&
86 + echo "content" >sub1 &&
87 + git add sub1 &&
88 + git commit -m "Replace sub1 with file" &&
89 + git checkout -b replace_file_with_sub1 &&
90 + git revert HEAD &&
91 +
92 + git checkout -b "invalid_sub1" "add_sub1" &&
93 + git update-index --cacheinfo 160000 0123456789012345678901234567890123456789 sub1 &&
94 + git commit -m "Invalid sub1 commit" &&
95 + git checkout -b valid_sub1 &&
96 + git revert HEAD &&
97 + git checkout master
98 + )
99 +}
100 +
101 +# Helper function to replace gitfile with .git directory
102 +replace_gitfile_with_git_dir () {
103 + (
104 + cd "$1" &&
105 + git_dir="$(git rev-parse --git-dir)" &&
106 + rm -f .git &&
107 + cp -R "$git_dir" .git &&
108 + GIT_WORK_TREE=. git config --unset core.worktree
109 + )
110 +}
111 +
112 +# Test that the .git directory in the submodule is unchanged (except for the
113 +# core.worktree setting, which appears only in $GIT_DIR/modules/$1/config).
114 +# Call this function before test_submodule_content as the latter might
115 +# write the index file leading to false positive index differences.
116 +#
117 +# Note that this only supports submodules at the root level of the
118 +# superproject, with the default name, i.e. same as its path.
119 +test_git_directory_is_unchanged () {
120 + (
121 + cd ".git/modules/$1" &&
122 + # does core.worktree point at the right place?
123 + test "$(git config core.worktree)" = "../../../$1" &&
124 + # remove it temporarily before comparing, as
125 + # "$1/.git/config" lacks it...
126 + git config --unset core.worktree
127 + ) &&
128 + diff -r ".git/modules/$1" "$1/.git" &&
129 + (
130 + # ... and then restore.
131 + cd ".git/modules/$1" &&
132 + git config core.worktree "../../../$1"
133 + )
134 +}
135 +
136 +# Helper function to be executed at the start of every test below, it sets up
137 +# the submodule repo if it doesn't exist and configures the most problematic
138 +# settings for diff.ignoreSubmodules.
139 +prolog () {
140 + (test -d submodule_update_repo || create_lib_submodule_repo) &&
141 + test_config_global diff.ignoreSubmodules all &&
142 + test_config diff.ignoreSubmodules all
143 +}
144 +
145 +# Helper function to bring work tree back into the state given by the
146 +# commit. This includes trying to populate sub1 accordingly if it exists and
147 +# should be updated to an existing commit.
148 +reset_work_tree_to () {
149 + rm -rf submodule_update &&
150 + git clone submodule_update_repo submodule_update &&
151 + (
152 + cd submodule_update &&
153 + rm -rf sub1 &&
154 + git checkout -f "$1" &&
155 + git status -u -s >actual &&
156 + test_must_be_empty actual &&
157 + sha1=$(git rev-parse --revs-only HEAD:sub1) &&
158 + if test -n "$sha1" &&
159 + test $(cd "sub1" && git rev-parse --verify "$sha1^{commit}")
160 + then
161 + git submodule update --init --recursive "sub1"
162 + fi
163 + )
164 +}
165 +
166 +# Test that the superproject contains the content according to commit "$1"
167 +# (the work tree must match the index for everything but submodules but the
168 +# index must exactly match the given commit including any submodule SHA-1s).
169 +test_superproject_content () {
170 + git diff-index --cached "$1" >actual &&
171 + test_must_be_empty actual &&
172 + git diff-files --ignore-submodules >actual &&
173 + test_must_be_empty actual
174 +}
175 +
176 +# Test that the given submodule at path "$1" contains the content according
177 +# to the submodule commit recorded in the superproject's commit "$2"
178 +test_submodule_content () {
179 + if test $# != 2
180 + then
181 + echo "test_submodule_content needs two arguments"
182 + return 1
183 + fi &&
184 + submodule="$1" &&
185 + commit="$2" &&
186 + test -d "$submodule"/ &&
187 + if ! test -f "$submodule"/.git && ! test -d "$submodule"/.git
188 + then
189 + echo "Submodule $submodule is not populated"
190 + return 1
191 + fi &&
192 + sha1=$(git rev-parse --verify "$commit:$submodule") &&
193 + if test -z "$sha1"
194 + then
195 + echo "Couldn't retrieve SHA-1 of $submodule for $commit"
196 + return 1
197 + fi &&
198 + (
199 + cd "$submodule" &&
200 + git status -u -s >actual &&
201 + test_must_be_empty actual &&
202 + git diff "$sha1" >actual &&
203 + test_must_be_empty actual
204 + )
205 +}
206 +
207 +# Test that the following transitions are correctly handled:
208 +# - Updated submodule
209 +# - New submodule
210 +# - Removed submodule
211 +# - Directory containing tracked files replaced by submodule
212 +# - Submodule replaced by tracked files in directory
213 +# - Submodule replaced by tracked file with the same name
214 +# - tracked file replaced by submodule
215 +#
216 +# The default is that submodule contents aren't changed until "git submodule
217 +# update" is run. And even then that command doesn't delete the work tree of
218 +# a removed submodule.
219 +#
220 +# Removing a submodule containing a .git directory must fail even when forced
221 +# to protect the history!
222 +#
223 +
224 +# Test that submodule contents are currently not updated when switching
225 +# between commits that change a submodule.
226 +test_submodule_switch () {
227 + command="$1"
228 + ######################### Appearing submodule #########################
229 + # Switching to a commit letting a submodule appear creates empty dir ...
230 + test_expect_success "$command: added submodule creates empty directory" '
231 + prolog &&
232 + reset_work_tree_to no_submodule &&
233 + (
234 + cd submodule_update &&
235 + git branch -t add_sub1 origin/add_sub1 &&
236 + $command add_sub1 &&
237 + test_superproject_content origin/add_sub1 &&
238 + test_dir_is_empty sub1 &&
239 + git submodule update --init --recursive &&
240 + test_submodule_content sub1 origin/add_sub1
241 + )
242 + '
243 + # ... and doesn't care if it already exists ...
244 + test_expect_success "$command: added submodule leaves existing empty directory alone" '
245 + prolog &&
246 + reset_work_tree_to no_submodule &&
247 + (
248 + cd submodule_update &&
249 + mkdir sub1 &&
250 + git branch -t add_sub1 origin/add_sub1 &&
251 + $command add_sub1 &&
252 + test_superproject_content origin/add_sub1 &&
253 + test_dir_is_empty sub1 &&
254 + git submodule update --init --recursive &&
255 + test_submodule_content sub1 origin/add_sub1
256 + )
257 + '
258 + # ... unless there is an untracked file in its place.
259 + test_expect_success "$command: added submodule doesn't remove untracked unignored file with same name" '
260 + prolog &&
261 + reset_work_tree_to no_submodule &&
262 + (
263 + cd submodule_update &&
264 + git branch -t add_sub1 origin/add_sub1 &&
265 + >sub1 &&
266 + test_must_fail $command add_sub1 &&
267 + test_superproject_content origin/no_submodule &&
268 + test_must_be_empty sub1
269 + )
270 + '
271 + # Replacing a tracked file with a submodule produces an empty
272 + # directory ...
273 + test_expect_success "$command: replace tracked file with submodule creates empty directory" '
274 + prolog &&
275 + reset_work_tree_to replace_sub1_with_file &&
276 + (
277 + cd submodule_update &&
278 + git branch -t replace_file_with_sub1 origin/replace_file_with_sub1 &&
279 + $command replace_file_with_sub1 &&
280 + test_superproject_content origin/replace_file_with_sub1 &&
281 + test_dir_is_empty sub1 &&
282 + git submodule update --init --recursive &&
283 + test_submodule_content sub1 origin/replace_file_with_sub1
284 + )
285 + '
286 + # ... as does removing a directory with tracked files with a
287 + # submodule.
288 + test_expect_success "$command: replace directory with submodule" '
289 + prolog &&
290 + reset_work_tree_to replace_sub1_with_directory &&
291 + (
292 + cd submodule_update &&
293 + git branch -t replace_directory_with_sub1 origin/replace_directory_with_sub1 &&
294 + $command replace_directory_with_sub1 &&
295 + test_superproject_content origin/replace_directory_with_sub1 &&
296 + test_dir_is_empty sub1 &&
297 + git submodule update --init --recursive &&
298 + test_submodule_content sub1 origin/replace_directory_with_sub1
299 + )
300 + '
301 +
302 + ######################## Disappearing submodule #######################
303 + # Removing a submodule doesn't remove its work tree ...
304 + test_expect_success "$command: removed submodule leaves submodule directory and its contents in place" '
305 + prolog &&
306 + reset_work_tree_to add_sub1 &&
307 + (
308 + cd submodule_update &&
309 + git branch -t remove_sub1 origin/remove_sub1 &&
310 + $command remove_sub1 &&
311 + test_superproject_content origin/remove_sub1 &&
312 + test_submodule_content sub1 origin/add_sub1
313 + )
314 + '
315 + # ... especially when it contains a .git directory.
316 + test_expect_success "$command: removed submodule leaves submodule containing a .git directory alone" '
317 + prolog &&
318 + reset_work_tree_to add_sub1 &&
319 + (
320 + cd submodule_update &&
321 + git branch -t remove_sub1 origin/remove_sub1 &&
322 + replace_gitfile_with_git_dir sub1 &&
323 + $command remove_sub1 &&
324 + test_superproject_content origin/remove_sub1 &&
325 + test_git_directory_is_unchanged sub1 &&
326 + test_submodule_content sub1 origin/add_sub1
327 + )
328 + '
329 + # Replacing a submodule with files in a directory must fail as the
330 + # submodule work tree isn't removed ...
331 + test_expect_success "$command: replace submodule with a directory must fail" '
332 + prolog &&
333 + reset_work_tree_to add_sub1 &&
334 + (
335 + cd submodule_update &&
336 + git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&
337 + test_must_fail $command replace_sub1_with_directory &&
338 + test_superproject_content origin/add_sub1 &&
339 + test_submodule_content sub1 origin/add_sub1
340 + )
341 + '
342 + # ... especially when it contains a .git directory.
343 + test_expect_success "$command: replace submodule containing a .git directory with a directory must fail" '
344 + prolog &&
345 + reset_work_tree_to add_sub1 &&
346 + (
347 + cd submodule_update &&
348 + git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&
349 + replace_gitfile_with_git_dir sub1 &&
350 + test_must_fail $command replace_sub1_with_directory &&
351 + test_superproject_content origin/add_sub1 &&
352 + test_git_directory_is_unchanged sub1 &&
353 + test_submodule_content sub1 origin/add_sub1
354 + )
355 + '
356 + # Replacing it with a file must fail as it could throw away any local
357 + # work tree changes ...
358 + test_expect_failure "$command: replace submodule with a file must fail" '
359 + prolog &&
360 + reset_work_tree_to add_sub1 &&
361 + (
362 + cd submodule_update &&
363 + git branch -t replace_sub1_with_file origin/replace_sub1_with_file &&
364 + test_must_fail $command replace_sub1_with_file &&
365 + test_superproject_content origin/add_sub1 &&
366 + test_submodule_content sub1 origin/add_sub1
367 + )
368 + '
369 + # ... or even destroy unpushed parts of submodule history if that
370 + # still uses a .git directory.
371 + test_expect_failure "$command: replace submodule containing a .git directory with a file must fail" '
372 + prolog &&
373 + reset_work_tree_to add_sub1 &&
374 + (
375 + cd submodule_update &&
376 + git branch -t replace_sub1_with_file origin/replace_sub1_with_file &&
377 + replace_gitfile_with_git_dir sub1 &&
378 + test_must_fail $command replace_sub1_with_file &&
379 + test_superproject_content origin/add_sub1 &&
380 + test_git_directory_is_unchanged sub1 &&
381 + test_submodule_content sub1 origin/add_sub1
382 + )
383 + '
384 +
385 + ########################## Modified submodule #########################
386 + # Updating a submodule sha1 doesn't update the submodule's work tree
387 + test_expect_success "$command: modified submodule does not update submodule work tree" '
388 + prolog &&
389 + reset_work_tree_to add_sub1 &&
390 + (
391 + cd submodule_update &&
392 + git branch -t modify_sub1 origin/modify_sub1 &&
393 + $command modify_sub1 &&
394 + test_superproject_content origin/modify_sub1 &&
395 + test_submodule_content sub1 origin/add_sub1 &&
396 + git submodule update &&
397 + test_submodule_content sub1 origin/modify_sub1
398 + )
399 + '
400 +
401 + # Updating a submodule to an invalid sha1 doesn't update the
402 + # submodule's work tree, subsequent update will fail
403 + test_expect_success "$command: modified submodule does not update submodule work tree to invalid commit" '
404 + prolog &&
405 + reset_work_tree_to add_sub1 &&
406 + (
407 + cd submodule_update &&
408 + git branch -t invalid_sub1 origin/invalid_sub1 &&
409 + $command invalid_sub1 &&
410 + test_superproject_content origin/invalid_sub1 &&
411 + test_submodule_content sub1 origin/add_sub1 &&
412 + test_must_fail git submodule update &&
413 + test_submodule_content sub1 origin/add_sub1
414 + )
415 + '
416 + # Updating a submodule from an invalid sha1 doesn't update the
417 + # submodule's work tree, subsequent update will succeed
418 + test_expect_success "$command: modified submodule does not update submodule work tree from invalid commit" '
419 + prolog &&
420 + reset_work_tree_to invalid_sub1 &&
421 + (
422 + cd submodule_update &&
423 + git branch -t valid_sub1 origin/valid_sub1 &&
424 + $command valid_sub1 &&
425 + test_superproject_content origin/valid_sub1 &&
426 + test_dir_is_empty sub1 &&
427 + git submodule update --init --recursive &&
428 + test_submodule_content sub1 origin/valid_sub1
429 + )
430 + '
431 +}
432 +
433 +# Test that submodule contents are currently not updated when switching
434 +# between commits that change a submodule, but throwing away local changes in
435 +# the superproject is allowed.
436 +test_submodule_forced_switch () {
437 + command="$1"
438 + ######################### Appearing submodule #########################
439 + # Switching to a commit letting a submodule appear creates empty dir ...
440 + test_expect_success "$command: added submodule creates empty directory" '
441 + prolog &&
442 + reset_work_tree_to no_submodule &&
443 + (
444 + cd submodule_update &&
445 + git branch -t add_sub1 origin/add_sub1 &&
446 + $command add_sub1 &&
447 + test_superproject_content origin/add_sub1 &&
448 + test_dir_is_empty sub1 &&
449 + git submodule update --init --recursive &&
450 + test_submodule_content sub1 origin/add_sub1
451 + )
452 + '
453 + # ... and doesn't care if it already exists ...
454 + test_expect_success "$command: added submodule leaves existing empty directory alone" '
455 + prolog &&
456 + reset_work_tree_to no_submodule &&
457 + (
458 + cd submodule_update &&
459 + git branch -t add_sub1 origin/add_sub1 &&
460 + mkdir sub1 &&
461 + $command add_sub1 &&
462 + test_superproject_content origin/add_sub1 &&
463 + test_dir_is_empty sub1 &&
464 + git submodule update --init --recursive &&
465 + test_submodule_content sub1 origin/add_sub1
466 + )
467 + '
468 + # ... unless there is an untracked file in its place.
469 + test_expect_success "$command: added submodule does remove untracked unignored file with same name when forced" '
470 + prolog &&
471 + reset_work_tree_to no_submodule &&
472 + (
473 + cd submodule_update &&
474 + git branch -t add_sub1 origin/add_sub1 &&
475 + >sub1 &&
476 + $command add_sub1 &&
477 + test_superproject_content origin/add_sub1 &&
478 + test_dir_is_empty sub1
479 + )
480 + '
481 + # Replacing a tracked file with a submodule produces an empty
482 + # directory ...
483 + test_expect_success "$command: replace tracked file with submodule creates empty directory" '
484 + prolog &&
485 + reset_work_tree_to replace_sub1_with_file &&
486 + (
487 + cd submodule_update &&
488 + git branch -t replace_file_with_sub1 origin/replace_file_with_sub1 &&
489 + $command replace_file_with_sub1 &&
490 + test_superproject_content origin/replace_file_with_sub1 &&
491 + test_dir_is_empty sub1 &&
492 + git submodule update --init --recursive &&
493 + test_submodule_content sub1 origin/replace_file_with_sub1
494 + )
495 + '
496 + # ... as does removing a directory with tracked files with a
497 + # submodule.
498 + test_expect_success "$command: replace directory with submodule" '
499 + prolog &&
500 + reset_work_tree_to replace_sub1_with_directory &&
501 + (
502 + cd submodule_update &&
503 + git branch -t replace_directory_with_sub1 origin/replace_directory_with_sub1 &&
504 + $command replace_directory_with_sub1 &&
505 + test_superproject_content origin/replace_directory_with_sub1 &&
506 + test_dir_is_empty sub1 &&
507 + git submodule update --init --recursive &&
508 + test_submodule_content sub1 origin/replace_directory_with_sub1
509 + )
510 + '
511 +
512 + ######################## Disappearing submodule #######################
513 + # Removing a submodule doesn't remove its work tree ...
514 + test_expect_success "$command: removed submodule leaves submodule directory and its contents in place" '
515 + prolog &&
516 + reset_work_tree_to add_sub1 &&
517 + (
518 + cd submodule_update &&
519 + git branch -t remove_sub1 origin/remove_sub1 &&
520 + $command remove_sub1 &&
521 + test_superproject_content origin/remove_sub1 &&
522 + test_submodule_content sub1 origin/add_sub1
523 + )
524 + '
525 + # ... especially when it contains a .git directory.
526 + test_expect_success "$command: removed submodule leaves submodule containing a .git directory alone" '
527 + prolog &&
528 + reset_work_tree_to add_sub1 &&
529 + (
530 + cd submodule_update &&
531 + git branch -t remove_sub1 origin/remove_sub1 &&
532 + replace_gitfile_with_git_dir sub1 &&
533 + $command remove_sub1 &&
534 + test_superproject_content origin/remove_sub1 &&
535 + test_git_directory_is_unchanged sub1 &&
536 + test_submodule_content sub1 origin/add_sub1
537 + )
538 + '
539 + # Replacing a submodule with files in a directory must fail as the
540 + # submodule work tree isn't removed ...
541 + test_expect_failure "$command: replace submodule with a directory must fail" '
542 + prolog &&
543 + reset_work_tree_to add_sub1 &&
544 + (
545 + cd submodule_update &&
546 + git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&
547 + test_must_fail $command replace_sub1_with_directory &&
548 + test_superproject_content origin/add_sub1 &&
549 + test_submodule_content sub1 origin/add_sub1
550 + )
551 + '
552 + # ... especially when it contains a .git directory.
553 + test_expect_failure "$command: replace submodule containing a .git directory with a directory must fail" '
554 + prolog &&
555 + reset_work_tree_to add_sub1 &&
556 + (
557 + cd submodule_update &&
558 + git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&
559 + replace_gitfile_with_git_dir sub1 &&
560 + test_must_fail $command replace_sub1_with_directory &&
561 + test_superproject_content origin/add_sub1 &&
562 + test_git_directory_is_unchanged sub1 &&
563 + test_submodule_content sub1 origin/add_sub1
564 + )
565 + '
566 + # Replacing it with a file must fail as it could throw away any local
567 + # work tree changes ...
568 + test_expect_failure "$command: replace submodule with a file must fail" '
569 + prolog &&
570 + reset_work_tree_to add_sub1 &&
571 + (
572 + cd submodule_update &&
573 + git branch -t replace_sub1_with_file origin/replace_sub1_with_file &&
574 + test_must_fail $command replace_sub1_with_file &&
575 + test_superproject_content origin/add_sub1 &&
576 + test_submodule_content sub1 origin/add_sub1
577 + )
578 + '
579 + # ... or even destroy unpushed parts of submodule history if that
580 + # still uses a .git directory.
581 + test_expect_failure "$command: replace submodule containing a .git directory with a file must fail" '
582 + prolog &&
583 + reset_work_tree_to add_sub1 &&
584 + (
585 + cd submodule_update &&
586 + git branch -t replace_sub1_with_file origin/replace_sub1_with_file &&
587 + replace_gitfile_with_git_dir sub1 &&
588 + test_must_fail $command replace_sub1_with_file &&
589 + test_superproject_content origin/add_sub1 &&
590 + test_git_directory_is_unchanged sub1 &&
591 + test_submodule_content sub1 origin/add_sub1
592 + )
593 + '
594 +
595 + ########################## Modified submodule #########################
596 + # Updating a submodule sha1 doesn't update the submodule's work tree
597 + test_expect_success "$command: modified submodule does not update submodule work tree" '
598 + prolog &&
599 + reset_work_tree_to add_sub1 &&
600 + (
601 + cd submodule_update &&
602 + git branch -t modify_sub1 origin/modify_sub1 &&
603 + $command modify_sub1 &&
604 + test_superproject_content origin/modify_sub1 &&
605 + test_submodule_content sub1 origin/add_sub1 &&
606 + git submodule update &&
607 + test_submodule_content sub1 origin/modify_sub1
608 + )
609 + '
610 + # Updating a submodule to an invalid sha1 doesn't update the
611 + # submodule's work tree, subsequent update will fail
612 + test_expect_success "$command: modified submodule does not update submodule work tree to invalid commit" '
613 + prolog &&
614 + reset_work_tree_to add_sub1 &&
615 + (
616 + cd submodule_update &&
617 + git branch -t invalid_sub1 origin/invalid_sub1 &&
618 + $command invalid_sub1 &&
619 + test_superproject_content origin/invalid_sub1 &&
620 + test_submodule_content sub1 origin/add_sub1 &&
621 + test_must_fail git submodule update &&
622 + test_submodule_content sub1 origin/add_sub1
623 + )
624 + '
625 + # Updating a submodule from an invalid sha1 doesn't update the
626 + # submodule's work tree, subsequent update will succeed
627 + test_expect_success "$command: modified submodule does not update submodule work tree from invalid commit" '
628 + prolog &&
629 + reset_work_tree_to invalid_sub1 &&
630 + (
631 + cd submodule_update &&
632 + git branch -t valid_sub1 origin/valid_sub1 &&
633 + $command valid_sub1 &&
634 + test_superproject_content origin/valid_sub1 &&
635 + test_dir_is_empty sub1 &&
636 + git submodule update --init --recursive &&
637 + test_submodule_content sub1 origin/valid_sub1
638 + )
639 + '
640 +}