| #!/bin/sh | 
 |  | 
 | test_description="remember regular & dir renames in sequence of merges" | 
 |  | 
 | . ./test-lib.sh | 
 |  | 
 | # | 
 | # NOTE 1: this testfile tends to not only rename files, but modify on both | 
 | #         sides; without modifying on both sides, optimizations can kick in | 
 | #         which make rename detection irrelevant or trivial.  We want to make | 
 | #         sure that we are triggering rename caching rather than rename | 
 | #         bypassing. | 
 | # | 
 | # NOTE 2: this testfile uses 'test-tool fast-rebase' instead of either | 
 | #         cherry-pick or rebase.  sequencer.c is only superficially | 
 | #         integrated with merge-ort; it calls merge_switch_to_result() | 
 | #         after EACH merge, which updates the index and working copy AND | 
 | #         throws away the cached results (because merge_switch_to_result() | 
 | #         is only supposed to be called at the end of the sequence). | 
 | #         Integrating them more deeply is a big task, so for now the tests | 
 | #         use 'test-tool fast-rebase'. | 
 | # | 
 |  | 
 |  | 
 | # | 
 | # In the following simple testcase: | 
 | #   Base:     numbers_1, values_1 | 
 | #   Upstream: numbers_2, values_2 | 
 | #   Topic_1:  sequence_3 | 
 | #   Topic_2:  scruples_3 | 
 | # or, in english, rename numbers -> sequence in the first commit, and rename | 
 | # values -> scruples in the second commit. | 
 | # | 
 | # This shouldn't be a challenge, it's just verifying that cached renames isn't | 
 | # preventing us from finding new renames. | 
 | # | 
 | test_expect_success 'caching renames does not preclude finding new ones' ' | 
 | 	git init caching-renames-and-new-renames && | 
 | 	( | 
 | 		cd caching-renames-and-new-renames && | 
 |  | 
 | 		test_seq 2 10 >numbers && | 
 | 		test_seq 2 10 >values && | 
 | 		git add numbers values && | 
 | 		git commit -m orig && | 
 |  | 
 | 		git branch upstream && | 
 | 		git branch topic && | 
 |  | 
 | 		git switch upstream && | 
 | 		test_seq 1 10 >numbers && | 
 | 		test_seq 1 10 >values && | 
 | 		git add numbers values && | 
 | 		git commit -m "Tweaked both files" && | 
 |  | 
 | 		git switch topic && | 
 |  | 
 | 		test_seq 2 12 >numbers && | 
 | 		git add numbers && | 
 | 		git mv numbers sequence && | 
 | 		git commit -m A && | 
 |  | 
 | 		test_seq 2 12 >values && | 
 | 		git add values && | 
 | 		git mv values scruples && | 
 | 		git commit -m B && | 
 |  | 
 | 		# | 
 | 		# Actual testing | 
 | 		# | 
 |  | 
 | 		git switch upstream && | 
 |  | 
 | 		git replay --onto HEAD upstream~1..topic >out && | 
 | 		git update-ref --stdin <out && | 
 | 		git checkout topic && | 
 |  | 
 | 		git ls-files >tracked-files && | 
 | 		test_line_count = 2 tracked-files && | 
 | 		test_seq 1 12 >expect && | 
 | 		test_cmp expect sequence && | 
 | 		test_cmp expect scruples | 
 | 	) | 
 | ' | 
 |  | 
 | # | 
 | # In the following testcase: | 
 | #   Base:     numbers_1 | 
 | #   Upstream: rename numbers_1 -> sequence_2 | 
 | #   Topic_1:  numbers_3 | 
 | #   Topic_2:  numbers_1 | 
 | # or, in english, the first commit on the topic branch modifies numbers by | 
 | # shrinking it (dramatically) and the second commit on topic reverts its | 
 | # parent. | 
 | # | 
 | # Can git apply both patches? | 
 | # | 
 | # Traditional cherry-pick/rebase will fail to apply the second commit, the | 
 | # one that reverted its parent, because despite detecting the rename from | 
 | # 'numbers' to 'sequence' for the first commit, it fails to detect that | 
 | # rename when picking the second commit.  That's "reasonable" given the | 
 | # dramatic change in size of the file, but remembering the rename and | 
 | # reusing it is reasonable too. | 
 | # | 
 | # We do test here that we expect rename detection to only be run once total | 
 | # (the topic side of history doesn't need renames, and with caching we | 
 | # should be able to only run rename detection on the upstream side one | 
 | # time.) | 
 | test_expect_success 'cherry-pick both a commit and its immediate revert' ' | 
 | 	git init pick-commit-and-its-immediate-revert && | 
 | 	( | 
 | 		cd pick-commit-and-its-immediate-revert && | 
 |  | 
 | 		test_seq 11 30 >numbers && | 
 | 		git add numbers && | 
 | 		git commit -m orig && | 
 |  | 
 | 		git branch upstream && | 
 | 		git branch topic && | 
 |  | 
 | 		git switch upstream && | 
 | 		test_seq 1 30 >numbers && | 
 | 		git add numbers && | 
 | 		git mv numbers sequence && | 
 | 		git commit -m "Renamed (and modified) numbers -> sequence" && | 
 |  | 
 | 		git switch topic && | 
 |  | 
 | 		test_seq 11 13 >numbers && | 
 | 		git add numbers && | 
 | 		git commit -m A && | 
 |  | 
 | 		git revert HEAD && | 
 |  | 
 | 		# | 
 | 		# Actual testing | 
 | 		# | 
 |  | 
 | 		git switch upstream && | 
 |  | 
 | 		GIT_TRACE2_PERF="$(pwd)/trace.output" && | 
 | 		export GIT_TRACE2_PERF && | 
 |  | 
 | 		git replay --onto HEAD upstream~1..topic >out && | 
 | 		git update-ref --stdin <out && | 
 | 		git checkout topic && | 
 |  | 
 | 		grep region_enter.*diffcore_rename trace.output >calls && | 
 | 		test_line_count = 1 calls | 
 | 	) | 
 | ' | 
 |  | 
 | # | 
 | # In the following testcase: | 
 | #   Base:     sequence_1 | 
 | #   Upstream: rename sequence_1 -> values_2 | 
 | #   Topic_1:  rename sequence_1 -> values_3 | 
 | #   Topic_2:  add unrelated sequence_4 | 
 | # or, in english, both sides rename sequence -> values, and then the second | 
 | # commit on the topic branch adds an unrelated file called sequence. | 
 | # | 
 | # This testcase presents no problems for git traditionally, but having both | 
 | # sides do the same rename in effect "uses it up" and if it remains cached, | 
 | # could cause a spurious rename/add conflict. | 
 | # | 
 | test_expect_success 'rename same file identically, then reintroduce it' ' | 
 | 	git init rename-rename-1to1-then-add-old-filename && | 
 | 	( | 
 | 		cd rename-rename-1to1-then-add-old-filename && | 
 |  | 
 | 		test_seq 3 8 >sequence && | 
 | 		git add sequence && | 
 | 		git commit -m orig && | 
 |  | 
 | 		git branch upstream && | 
 | 		git branch topic && | 
 |  | 
 | 		git switch upstream && | 
 | 		test_seq 1 8 >sequence && | 
 | 		git add sequence && | 
 | 		git mv sequence values && | 
 | 		git commit -m "Renamed (and modified) sequence -> values" && | 
 |  | 
 | 		git switch topic && | 
 |  | 
 | 		test_seq 3 10 >sequence && | 
 | 		git add sequence && | 
 | 		git mv sequence values && | 
 | 		git commit -m A && | 
 |  | 
 | 		test_write_lines A B C D E F G H I J >sequence && | 
 | 		git add sequence && | 
 | 		git commit -m B && | 
 |  | 
 | 		# | 
 | 		# Actual testing | 
 | 		# | 
 |  | 
 | 		git switch upstream && | 
 |  | 
 | 		GIT_TRACE2_PERF="$(pwd)/trace.output" && | 
 | 		export GIT_TRACE2_PERF && | 
 |  | 
 | 		git replay --onto HEAD upstream~1..topic >out && | 
 | 		git update-ref --stdin <out && | 
 | 		git checkout topic && | 
 |  | 
 | 		git ls-files >tracked && | 
 | 		test_line_count = 2 tracked && | 
 | 		test_path_is_file values && | 
 | 		test_path_is_file sequence && | 
 |  | 
 | 		grep region_enter.*diffcore_rename trace.output >calls && | 
 | 		test_line_count = 2 calls | 
 | 	) | 
 | ' | 
 |  | 
 | # | 
 | # In the following testcase: | 
 | #   Base:     olddir/{valuesZ_1, valuesY_1, valuesX_1} | 
 | #   Upstream: rename olddir/valuesZ_1 -> dirA/valuesZ_2 | 
 | #             rename olddir/valuesY_1 -> dirA/valuesY_2 | 
 | #             rename olddir/valuesX_1 -> dirB/valuesX_2 | 
 | #   Topic_1:  rename olddir/valuesZ_1 -> dirA/valuesZ_3 | 
 | #             rename olddir/valuesY_1 -> dirA/valuesY_3 | 
 | #   Topic_2:  add olddir/newfile | 
 | #   Expected Pick1: dirA/{valuesZ, valuesY}, dirB/valuesX | 
 | #   Expected Pick2: dirA/{valuesZ, valuesY}, dirB/{valuesX, newfile} | 
 | # | 
 | # This testcase presents no problems for git traditionally, but having both | 
 | # sides do the same renames in effect "use it up" but if the renames remain | 
 | # cached, the directory rename could put newfile in the wrong directory. | 
 | # | 
 | test_expect_success 'rename same file identically, then add file to old dir' ' | 
 | 	git init rename-rename-1to1-then-add-file-to-old-dir && | 
 | 	( | 
 | 		cd rename-rename-1to1-then-add-file-to-old-dir && | 
 |  | 
 | 		mkdir olddir/ && | 
 | 		test_seq 3 8 >olddir/valuesZ && | 
 | 		test_seq 3 8 >olddir/valuesY && | 
 | 		test_seq 3 8 >olddir/valuesX && | 
 | 		git add olddir && | 
 | 		git commit -m orig && | 
 |  | 
 | 		git branch upstream && | 
 | 		git branch topic && | 
 |  | 
 | 		git switch upstream && | 
 | 		test_seq 1 8 >olddir/valuesZ && | 
 | 		test_seq 1 8 >olddir/valuesY && | 
 | 		test_seq 1 8 >olddir/valuesX && | 
 | 		git add olddir && | 
 | 		mkdir dirA && | 
 | 		git mv olddir/valuesZ olddir/valuesY dirA && | 
 | 		git mv olddir/ dirB/ && | 
 | 		git commit -m "Renamed (and modified) values*" && | 
 |  | 
 | 		git switch topic && | 
 |  | 
 | 		test_seq 3 10 >olddir/valuesZ && | 
 | 		test_seq 3 10 >olddir/valuesY && | 
 | 		git add olddir && | 
 | 		mkdir dirA && | 
 | 		git mv olddir/valuesZ olddir/valuesY dirA && | 
 | 		git commit -m A && | 
 |  | 
 | 		>olddir/newfile && | 
 | 		git add olddir/newfile && | 
 | 		git commit -m B && | 
 |  | 
 | 		# | 
 | 		# Actual testing | 
 | 		# | 
 |  | 
 | 		git switch upstream && | 
 | 		git config merge.directoryRenames true && | 
 |  | 
 | 		GIT_TRACE2_PERF="$(pwd)/trace.output" && | 
 | 		export GIT_TRACE2_PERF && | 
 |  | 
 | 		git replay --onto HEAD upstream~1..topic >out && | 
 | 		git update-ref --stdin <out && | 
 | 		git checkout topic && | 
 |  | 
 | 		git ls-files >tracked && | 
 | 		test_line_count = 4 tracked && | 
 | 		test_path_is_file dirA/valuesZ && | 
 | 		test_path_is_file dirA/valuesY && | 
 | 		test_path_is_file dirB/valuesX && | 
 | 		test_path_is_file dirB/newfile && | 
 |  | 
 | 		grep region_enter.*diffcore_rename trace.output >calls && | 
 | 		test_line_count = 3 calls | 
 | 	) | 
 | ' | 
 |  | 
 | # | 
 | # In the following testcase, upstream renames a directory, and the topic branch | 
 | # first adds a file to the directory, then later renames the directory | 
 | # differently: | 
 | #   Base:     olddir/a | 
 | #             olddir/b | 
 | #   Upstream: rename olddir/ -> newdir/ | 
 | #   Topic_1:  add olddir/newfile | 
 | #   Topic_2:  rename olddir/ -> otherdir/ | 
 | # | 
 | # Here we are just concerned that cached renames might prevent us from seeing | 
 | # the rename conflict, and we want to ensure that we do get a conflict. | 
 | # | 
 | # While at it, though, we do test that we only try to detect renames 2 | 
 | # times and not three.  (The first merge needs to detect renames on the | 
 | # upstream side.  Traditionally, the second merge would need to detect | 
 | # renames on both sides of history, but our caching of upstream renames | 
 | # should avoid the need to re-detect upstream renames.) | 
 | # | 
 | test_expect_success 'cached dir rename does not prevent noticing later conflict' ' | 
 | 	git init dir-rename-cache-not-occluding-later-conflict && | 
 | 	( | 
 | 		cd dir-rename-cache-not-occluding-later-conflict && | 
 |  | 
 | 		mkdir olddir && | 
 | 		test_seq 3 10 >olddir/a && | 
 | 		test_seq 3 10 >olddir/b && | 
 | 		git add olddir && | 
 | 		git commit -m orig && | 
 |  | 
 | 		git branch upstream && | 
 | 		git branch topic && | 
 |  | 
 | 		git switch upstream && | 
 | 		test_seq 3 10 >olddir/a && | 
 | 		test_seq 3 10 >olddir/b && | 
 | 		git add olddir && | 
 | 		git mv olddir newdir && | 
 | 		git commit -m "Dir renamed" && | 
 |  | 
 | 		git switch topic && | 
 |  | 
 | 		>olddir/newfile && | 
 | 		git add olddir/newfile && | 
 | 		git commit -m A && | 
 |  | 
 | 		test_seq 1 8 >olddir/a && | 
 | 		test_seq 1 8 >olddir/b && | 
 | 		git add olddir && | 
 | 		git mv olddir otherdir && | 
 | 		git commit -m B && | 
 |  | 
 | 		# | 
 | 		# Actual testing | 
 | 		# | 
 |  | 
 | 		git switch upstream && | 
 | 		git config merge.directoryRenames true && | 
 |  | 
 | 		GIT_TRACE2_PERF="$(pwd)/trace.output" && | 
 | 		export GIT_TRACE2_PERF && | 
 |  | 
 | 		test_must_fail git replay --onto HEAD upstream~1..topic >output && | 
 |  | 
 | 		grep region_enter.*diffcore_rename trace.output >calls && | 
 | 		test_line_count = 2 calls | 
 | 	) | 
 | ' | 
 |  | 
 | # Helper for the next two tests | 
 | test_setup_upstream_rename () { | 
 | 	git init $1 && | 
 | 	( | 
 | 		cd $1 && | 
 |  | 
 | 		test_seq 3 8 >somefile && | 
 | 		test_seq 3 8 >relevant-rename && | 
 | 		git add somefile relevant-rename && | 
 | 		mkdir olddir && | 
 | 		test_write_lines a b c d e f g >olddir/a && | 
 | 		test_write_lines z y x w v u t >olddir/b && | 
 | 		git add olddir && | 
 | 		git commit -m orig && | 
 |  | 
 | 		git branch upstream && | 
 | 		git branch topic && | 
 |  | 
 | 		git switch upstream && | 
 | 		test_seq 1 8 >somefile && | 
 | 		test_seq 1 8 >relevant-rename && | 
 | 		git add somefile relevant-rename && | 
 | 		git mv relevant-rename renamed && | 
 | 		echo h >>olddir/a && | 
 | 		echo s >>olddir/b && | 
 | 		git add olddir && | 
 | 		git mv olddir newdir && | 
 | 		git commit -m "Dir renamed" | 
 | 	) | 
 | } | 
 |  | 
 | # | 
 | # In the following testcase, upstream renames a file in the toplevel directory | 
 | # as well as its only directory: | 
 | #   Base:     relevant-rename_1 | 
 | #             somefile | 
 | #             olddir/a | 
 | #             olddir/b | 
 | #   Upstream: rename relevant-rename_1 -> renamed_2 | 
 | #             rename olddir/           -> newdir/ | 
 | #   Topic_1:  relevant-rename_3 | 
 | #   Topic_2:  olddir/newfile_1 | 
 | #   Topic_3:  olddir/newfile_2 | 
 | # | 
 | # In this testcase, since the first commit being picked only modifies a | 
 | # file in the toplevel directory, the directory rename is irrelevant for | 
 | # that first merge.  However, we need to notice the directory rename for | 
 | # the merge that picks the second commit, and we don't want the third | 
 | # commit to mess up its location either.  We want to make sure that | 
 | # olddir/newfile doesn't exist in the result and that newdir/newfile does. | 
 | # | 
 | # We also test that we only do rename detection twice.  We never need | 
 | # rename detection on the topic side of history, but we do need it twice on | 
 | # the upstream side of history.  For the first topic commit, we only need | 
 | # the | 
 | #   relevant-rename -> renamed | 
 | # rename, because olddir is unmodified by Topic_1.  For Topic_2, however, | 
 | # the new file being added to olddir means files that were previously | 
 | # irrelevant for rename detection are now relevant, forcing us to repeat | 
 | # rename detection for the paths we don't already have cached.  Topic_3 also | 
 | # tweaks olddir/newfile, but the renames in olddir/ will have been cached | 
 | # from the second rename detection run. | 
 | # | 
 | test_expect_success 'dir rename unneeded, then add new file to old dir' ' | 
 | 	test_setup_upstream_rename dir-rename-unneeded-until-new-file && | 
 | 	( | 
 | 		cd dir-rename-unneeded-until-new-file && | 
 |  | 
 | 		git switch topic && | 
 |  | 
 | 		test_seq 3 10 >relevant-rename && | 
 | 		git add relevant-rename && | 
 | 		git commit -m A && | 
 |  | 
 | 		echo foo >olddir/newfile && | 
 | 		git add olddir/newfile && | 
 | 		git commit -m B && | 
 |  | 
 | 		echo bar >>olddir/newfile && | 
 | 		git add olddir/newfile && | 
 | 		git commit -m C && | 
 |  | 
 | 		# | 
 | 		# Actual testing | 
 | 		# | 
 |  | 
 | 		git switch upstream && | 
 | 		git config merge.directoryRenames true && | 
 |  | 
 | 		GIT_TRACE2_PERF="$(pwd)/trace.output" && | 
 | 		export GIT_TRACE2_PERF && | 
 |  | 
 | 		git replay --onto HEAD upstream~1..topic >out && | 
 | 		git update-ref --stdin <out && | 
 | 		git checkout topic && | 
 |  | 
 | 		grep region_enter.*diffcore_rename trace.output >calls && | 
 | 		test_line_count = 2 calls && | 
 |  | 
 | 		git ls-files >tracked && | 
 | 		test_line_count = 5 tracked && | 
 | 		test_path_is_missing olddir/newfile && | 
 | 		test_path_is_file newdir/newfile | 
 | 	) | 
 | ' | 
 |  | 
 | # | 
 | # The following testcase is *very* similar to the last one, but instead of | 
 | # adding a new olddir/newfile, it renames somefile -> olddir/newfile: | 
 | #   Base:     relevant-rename_1 | 
 | #             somefile_1 | 
 | #             olddir/a | 
 | #             olddir/b | 
 | #   Upstream: rename relevant-rename_1 -> renamed_2 | 
 | #             rename olddir/           -> newdir/ | 
 | #   Topic_1:  relevant-rename_3 | 
 | #   Topic_2:  rename somefile -> olddir/newfile_2 | 
 | #   Topic_3:  modify olddir/newfile_3 | 
 | # | 
 | # In this testcase, since the first commit being picked only modifies a | 
 | # file in the toplevel directory, the directory rename is irrelevant for | 
 | # that first merge.  However, we need to notice the directory rename for | 
 | # the merge that picks the second commit, and we don't want the third | 
 | # commit to mess up its location either.  We want to make sure that | 
 | # neither somefile or olddir/newfile exists in the result and that | 
 | # newdir/newfile does. | 
 | # | 
 | # This testcase needs one more call to rename detection than the last | 
 | # testcase, because of the somefile -> olddir/newfile rename in Topic_2. | 
 | test_expect_success 'dir rename unneeded, then rename existing file into old dir' ' | 
 | 	test_setup_upstream_rename dir-rename-unneeded-until-file-moved-inside && | 
 | 	( | 
 | 		cd dir-rename-unneeded-until-file-moved-inside && | 
 |  | 
 | 		git switch topic && | 
 |  | 
 | 		test_seq 3 10 >relevant-rename && | 
 | 		git add relevant-rename && | 
 | 		git commit -m A && | 
 |  | 
 | 		test_seq 1 10 >somefile && | 
 | 		git add somefile && | 
 | 		git mv somefile olddir/newfile && | 
 | 		git commit -m B && | 
 |  | 
 | 		test_seq 1 12 >olddir/newfile && | 
 | 		git add olddir/newfile && | 
 | 		git commit -m C && | 
 |  | 
 | 		# | 
 | 		# Actual testing | 
 | 		# | 
 |  | 
 | 		git switch upstream && | 
 | 		git config merge.directoryRenames true && | 
 |  | 
 | 		GIT_TRACE2_PERF="$(pwd)/trace.output" && | 
 | 		export GIT_TRACE2_PERF && | 
 |  | 
 | 		git replay --onto HEAD upstream~1..topic >out && | 
 | 		git update-ref --stdin <out && | 
 | 		git checkout topic && | 
 |  | 
 | 		grep region_enter.*diffcore_rename trace.output >calls && | 
 | 		test_line_count = 3 calls && | 
 |  | 
 | 		test_path_is_missing somefile && | 
 | 		test_path_is_missing olddir/newfile && | 
 | 		test_path_is_file newdir/newfile && | 
 | 		git ls-files >tracked && | 
 | 		test_line_count = 4 tracked | 
 | 	) | 
 | ' | 
 |  | 
 | # Helper for the next two tests | 
 | test_setup_topic_rename () { | 
 | 	git init $1 && | 
 | 	( | 
 | 		cd $1 && | 
 |  | 
 | 		test_seq 3 8 >somefile && | 
 | 		mkdir olddir && | 
 | 		test_seq 3 8 >olddir/a && | 
 | 		echo b >olddir/b && | 
 | 		git add olddir somefile && | 
 | 		git commit -m orig && | 
 |  | 
 | 		git branch upstream && | 
 | 		git branch topic && | 
 |  | 
 | 		git switch topic && | 
 | 		test_seq 1 8 >somefile && | 
 | 		test_seq 1 8 >olddir/a && | 
 | 		git add somefile olddir/a && | 
 | 		git mv olddir newdir && | 
 | 		git commit -m "Dir renamed" && | 
 |  | 
 | 		test_seq 1 10 >somefile && | 
 | 		git add somefile && | 
 | 		mkdir olddir && | 
 | 		>olddir/unrelated-file && | 
 | 		git add olddir && | 
 | 		git commit -m "Unrelated file in recreated old dir" | 
 | 	) | 
 | } | 
 |  | 
 | # | 
 | # In the following testcase, the first commit on the topic branch renames | 
 | # a directory, while the second recreates the old directory and places a | 
 | # file into it: | 
 | #   Base:     somefile | 
 | #             olddir/a | 
 | #             olddir/b | 
 | #   Upstream: olddir/newfile | 
 | #   Topic_1:  somefile_2 | 
 | #             rename olddir/ -> newdir/ | 
 | #   Topic_2:  olddir/unrelated-file | 
 | # | 
 | # Note that the first pick should merge: | 
 | #   Base:     somefile | 
 | #             olddir/{a,b} | 
 | #   Upstream: olddir/newfile | 
 | #   Topic_1:  rename olddir/ -> newdir/ | 
 | # For which the expected result (assuming merge.directoryRenames=true) is | 
 | # clearly: | 
 | #   Result:   somefile | 
 | #             newdir/{a, b, newfile} | 
 | # | 
 | # While the second pick does the following three-way merge: | 
 | #   Base (Topic_1):           somefile | 
 | #                             newdir/{a,b} | 
 | #   Upstream (Result from 1): same files as base, but adds newdir/newfile | 
 | #   Topic_2:                  same files as base, but adds olddir/unrelated-file | 
 | # | 
 | # The second merge is pretty trivial; upstream adds newdir/newfile, and | 
 | # topic_2 adds olddir/unrelated-file.  We're just testing that we don't | 
 | # accidentally cache directory renames somehow and rename | 
 | # olddir/unrelated-file to newdir/unrelated-file. | 
 | # | 
 | # This testcase should only need one call to diffcore_rename_extended(). | 
 | test_expect_success 'caching renames only on upstream side, part 1' ' | 
 | 	test_setup_topic_rename cache-renames-only-upstream-add-file && | 
 | 	( | 
 | 		cd cache-renames-only-upstream-add-file && | 
 |  | 
 | 		git switch upstream && | 
 |  | 
 | 		>olddir/newfile && | 
 | 		git add olddir/newfile && | 
 | 		git commit -m "Add newfile" && | 
 |  | 
 | 		# | 
 | 		# Actual testing | 
 | 		# | 
 |  | 
 | 		git switch upstream && | 
 |  | 
 | 		git config merge.directoryRenames true && | 
 |  | 
 | 		GIT_TRACE2_PERF="$(pwd)/trace.output" && | 
 | 		export GIT_TRACE2_PERF && | 
 |  | 
 | 		git replay --onto HEAD upstream~1..topic >out && | 
 | 		git update-ref --stdin <out && | 
 | 		git checkout topic && | 
 |  | 
 | 		grep region_enter.*diffcore_rename trace.output >calls && | 
 | 		test_line_count = 1 calls && | 
 |  | 
 | 		git ls-files >tracked && | 
 | 		test_line_count = 5 tracked && | 
 | 		test_path_is_missing newdir/unrelated-file && | 
 | 		test_path_is_file olddir/unrelated-file && | 
 | 		test_path_is_file newdir/newfile && | 
 | 		test_path_is_file newdir/b && | 
 | 		test_path_is_file newdir/a && | 
 | 		test_path_is_file somefile | 
 | 	) | 
 | ' | 
 |  | 
 | # | 
 | # The following testcase is *very* similar to the last one, but instead of | 
 | # adding a new olddir/newfile, it renames somefile -> olddir/newfile: | 
 | #   Base:     somefile | 
 | #             olddir/a | 
 | #             olddir/b | 
 | #   Upstream: somefile_1 -> olddir/newfile | 
 | #   Topic_1:  rename olddir/ -> newdir/ | 
 | #             somefile_2 | 
 | #   Topic_2:  olddir/unrelated-file | 
 | #             somefile_3 | 
 | # | 
 | # Much like the previous test, this case is actually trivial and we are just | 
 | # making sure there isn't some spurious directory rename caching going on | 
 | # for the wrong side of history. | 
 | # | 
 | # | 
 | # This testcase should only need two calls to diffcore_rename_extended(), | 
 | # both for the first merge, one for each side of history. | 
 | # | 
 | test_expect_success 'caching renames only on upstream side, part 2' ' | 
 | 	test_setup_topic_rename cache-renames-only-upstream-rename-file && | 
 | 	( | 
 | 		cd cache-renames-only-upstream-rename-file && | 
 |  | 
 | 		git switch upstream && | 
 |  | 
 | 		git mv somefile olddir/newfile && | 
 | 		git commit -m "Add newfile" && | 
 |  | 
 | 		# | 
 | 		# Actual testing | 
 | 		# | 
 |  | 
 | 		git switch upstream && | 
 |  | 
 | 		git config merge.directoryRenames true && | 
 |  | 
 | 		GIT_TRACE2_PERF="$(pwd)/trace.output" && | 
 | 		export GIT_TRACE2_PERF && | 
 |  | 
 | 		git replay --onto HEAD upstream~1..topic >out && | 
 | 		git update-ref --stdin <out && | 
 | 		git checkout topic && | 
 |  | 
 | 		grep region_enter.*diffcore_rename trace.output >calls && | 
 | 		test_line_count = 2 calls && | 
 |  | 
 | 		git ls-files >tracked && | 
 | 		test_line_count = 4 tracked && | 
 | 		test_path_is_missing newdir/unrelated-file && | 
 | 		test_path_is_file olddir/unrelated-file && | 
 | 		test_path_is_file newdir/newfile && | 
 | 		test_path_is_file newdir/b && | 
 | 		test_path_is_file newdir/a | 
 | 	) | 
 | ' | 
 |  | 
 | # | 
 | # The following testcase just creates two simple renames (slightly modified | 
 | # on both sides but without conflicting changes), and a directory full of | 
 | # files that are otherwise uninteresting.  The setup is as follows: | 
 | # | 
 | #   base:     unrelated/<BUNCH OF FILES> | 
 | #             numbers | 
 | #             values | 
 | #   upstream: modify: numbers | 
 | #             modify: values | 
 | #   topic:    add: unrelated/foo | 
 | #             modify: numbers | 
 | #             modify: values | 
 | #             rename: numbers -> sequence | 
 | #             rename: values -> progression | 
 | # | 
 | # This is a trivial rename case, but we're curious what happens with a very | 
 | # low renameLimit interacting with the restart optimization trying to notice | 
 | # that unrelated/ looks like a trivial merge candidate. | 
 | # | 
 | test_expect_success 'avoid assuming we detected renames' ' | 
 | 	git init redo-weirdness && | 
 | 	( | 
 | 		cd redo-weirdness && | 
 |  | 
 | 		mkdir unrelated && | 
 | 		for i in $(test_seq 1 10) | 
 | 		do | 
 | 			>unrelated/$i || exit 1 | 
 | 		done && | 
 | 		test_seq  2 10 >numbers && | 
 | 		test_seq 12 20 >values && | 
 | 		git add numbers values unrelated/ && | 
 | 		git commit -m orig && | 
 |  | 
 | 		git branch upstream && | 
 | 		git branch topic && | 
 |  | 
 | 		git switch upstream && | 
 | 		test_seq  1 10 >numbers && | 
 | 		test_seq 11 20 >values && | 
 | 		git add numbers && | 
 | 		git commit -m "Some tweaks" && | 
 |  | 
 | 		git switch topic && | 
 |  | 
 | 		>unrelated/foo && | 
 | 		test_seq  2 12 >numbers && | 
 | 		test_seq 12 22 >values && | 
 | 		git add numbers values unrelated/ && | 
 | 		git mv numbers sequence && | 
 | 		git mv values progression && | 
 | 		git commit -m A && | 
 |  | 
 | 		# | 
 | 		# Actual testing | 
 | 		# | 
 |  | 
 | 		git switch --detach topic^0 && | 
 |  | 
 | 		test_must_fail git -c merge.renameLimit=1 rebase upstream && | 
 |  | 
 | 		git ls-files -u >actual && | 
 | 		test_line_count = 2 actual | 
 | 	) | 
 | ' | 
 |  | 
 | test_done |