1#!/bin/sh 2 3test_description='merge-recursive rename options 4 5Test rename detection by examining rename/delete conflicts. 6 7* (HEAD -> rename) rename 8| * (main) delete 9|/ 10* base 11 12git diff --name-status base main 13D 0-old 14D 1-old 15D 2-old 16D 3-old 17 18git diff --name-status -M01 base rename 19R025 0-old 0-new 20R050 1-old 1-new 21R075 2-old 2-new 22R100 3-old 3-new 23 24Actual similarity indices are parsed from diff output. We rely on the fact that 25they are rounded down (see, e.g., Documentation/diff-generate-patch.txt, which 26mentions this in a different context). 27' 28 29GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 30export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 31 32. ./test-lib.sh 33 34get_expected_stages () { 35 git checkout rename -- $1-new && 36 git ls-files --stage $1-new >expected-stages-undetected-$1 && 37 sed "s/ 0 / 2 /" <expected-stages-undetected-$1 \ 38 >expected-stages-detected-$1 && 39 git read-tree -u --reset HEAD 40} 41 42rename_detected () { 43 git ls-files --stage $1-old $1-new >stages-actual-$1 && 44 test_cmp expected-stages-detected-$1 stages-actual-$1 45} 46 47rename_undetected () { 48 git ls-files --stage $1-old $1-new >stages-actual-$1 && 49 test_cmp expected-stages-undetected-$1 stages-actual-$1 50} 51 52check_common () { 53 git ls-files --stage >stages-actual && 54 test_line_count = 4 stages-actual 55} 56 57check_threshold_0 () { 58 check_common && 59 rename_detected 0 && 60 rename_detected 1 && 61 rename_detected 2 && 62 rename_detected 3 63} 64 65check_threshold_1 () { 66 check_common && 67 rename_undetected 0 && 68 rename_detected 1 && 69 rename_detected 2 && 70 rename_detected 3 71} 72 73check_threshold_2 () { 74 check_common && 75 rename_undetected 0 && 76 rename_undetected 1 && 77 rename_detected 2 && 78 rename_detected 3 79} 80 81check_exact_renames () { 82 check_common && 83 rename_undetected 0 && 84 rename_undetected 1 && 85 rename_undetected 2 && 86 rename_detected 3 87} 88 89check_no_renames () { 90 check_common && 91 rename_undetected 0 && 92 rename_undetected 1 && 93 rename_undetected 2 && 94 rename_undetected 3 95} 96 97test_expect_success 'setup repo' ' 98 cat <<-\EOF >3-old && 99 33a 100 33b 101 33c 102 33d 103 EOF 104 sed s/33/22/ <3-old >2-old && 105 sed s/33/11/ <3-old >1-old && 106 sed s/33/00/ <3-old >0-old && 107 git add [0-3]-old && 108 git commit -m base && 109 git rm [0-3]-old && 110 git commit -m delete && 111 git checkout -b rename HEAD^ && 112 cp 3-old 3-new && 113 sed 1,1s/./x/ <2-old >2-new && 114 sed 1,2s/./x/ <1-old >1-new && 115 sed 1,3s/./x/ <0-old >0-new && 116 git add [0-3]-new && 117 git rm [0-3]-old && 118 git commit -m rename && 119 get_expected_stages 0 && 120 get_expected_stages 1 && 121 get_expected_stages 2 && 122 get_expected_stages 3 && 123 check_50="false" && 124 tail="HEAD^ -- HEAD main" 125' 126 127test_expect_success 'setup thresholds' ' 128 git diff --name-status -M01 HEAD^ HEAD >diff-output && 129 test_debug "cat diff-output" && 130 test_line_count = 4 diff-output && 131 grep "R[0-9][0-9][0-9] \([0-3]\)-old \1-new" diff-output \ 132 >grep-output && 133 test_cmp diff-output grep-output && 134 th0=$(sed -n "s/R\(...\) 0-old 0-new/\1/p" <diff-output) && 135 th1=$(sed -n "s/R\(...\) 1-old 1-new/\1/p" <diff-output) && 136 th2=$(sed -n "s/R\(...\) 2-old 2-new/\1/p" <diff-output) && 137 th3=$(sed -n "s/R\(...\) 3-old 3-new/\1/p" <diff-output) && 138 test "$th0" -lt "$th1" && 139 test "$th1" -lt "$th2" && 140 test "$th2" -lt "$th3" && 141 test "$th3" = 100 && 142 if test 50 -le "$th0" 143 then 144 check_50=check_threshold_0 145 elif test 50 -le "$th1" 146 then 147 check_50=check_threshold_1 148 elif test 50 -le "$th2" 149 then 150 check_50=check_threshold_2 151 fi && 152 th0="$th0%" && 153 th1="$th1%" && 154 th2="$th2%" && 155 th3="$th3%" 156' 157 158test_expect_success 'assumption for tests: rename detection with diff' ' 159 git diff --name-status -M$th0 --diff-filter=R HEAD^ HEAD \ 160 >diff-output-0 && 161 git diff --name-status -M$th1 --diff-filter=R HEAD^ HEAD \ 162 >diff-output-1 && 163 git diff --name-status -M$th2 --diff-filter=R HEAD^ HEAD \ 164 >diff-output-2 && 165 git diff --name-status -M100% --diff-filter=R HEAD^ HEAD \ 166 >diff-output-3 && 167 test_line_count = 4 diff-output-0 && 168 test_line_count = 3 diff-output-1 && 169 test_line_count = 2 diff-output-2 && 170 test_line_count = 1 diff-output-3 171' 172 173test_expect_success 'default similarity threshold is 50%' ' 174 git read-tree --reset -u HEAD && 175 test_must_fail git merge-recursive $tail && 176 $check_50 177' 178 179test_expect_success 'low rename threshold' ' 180 git read-tree --reset -u HEAD && 181 test_must_fail git merge-recursive --find-renames=$th0 $tail && 182 check_threshold_0 183' 184 185test_expect_success 'medium rename threshold' ' 186 git read-tree --reset -u HEAD && 187 test_must_fail git merge-recursive --find-renames=$th1 $tail && 188 check_threshold_1 189' 190 191test_expect_success 'high rename threshold' ' 192 git read-tree --reset -u HEAD && 193 test_must_fail git merge-recursive --find-renames=$th2 $tail && 194 check_threshold_2 195' 196 197test_expect_success 'exact renames only' ' 198 git read-tree --reset -u HEAD && 199 test_must_fail git merge-recursive --find-renames=100% $tail && 200 check_exact_renames 201' 202 203test_expect_success 'rename threshold is truncated' ' 204 git read-tree --reset -u HEAD && 205 test_must_fail git merge-recursive --find-renames=200% $tail && 206 check_exact_renames 207' 208 209test_expect_success 'disabled rename detection' ' 210 git read-tree --reset -u HEAD && 211 git merge-recursive --no-renames $tail && 212 check_no_renames 213' 214 215test_expect_success 'last wins in --find-renames=<m> --find-renames=<n>' ' 216 git read-tree --reset -u HEAD && 217 test_must_fail git merge-recursive \ 218 --find-renames=$th0 --find-renames=$th2 $tail && 219 check_threshold_2 220' 221 222test_expect_success '--find-renames resets threshold' ' 223 git read-tree --reset -u HEAD && 224 test_must_fail git merge-recursive \ 225 --find-renames=$th0 --find-renames $tail && 226 $check_50 227' 228 229test_expect_success 'last wins in --no-renames --find-renames' ' 230 git read-tree --reset -u HEAD && 231 test_must_fail git merge-recursive --no-renames --find-renames $tail && 232 $check_50 233' 234 235test_expect_success 'last wins in --find-renames --no-renames' ' 236 git read-tree --reset -u HEAD && 237 git merge-recursive --find-renames --no-renames $tail && 238 check_no_renames 239' 240 241test_expect_success 'assumption for further tests: trivial merge succeeds' ' 242 git read-tree --reset -u HEAD && 243 git merge-recursive HEAD -- HEAD HEAD && 244 git diff --quiet --cached && 245 git merge-recursive --find-renames=$th0 HEAD -- HEAD HEAD && 246 git diff --quiet --cached && 247 git merge-recursive --find-renames=$th2 HEAD -- HEAD HEAD && 248 git diff --quiet --cached && 249 git merge-recursive --find-renames=100% HEAD -- HEAD HEAD && 250 git diff --quiet --cached && 251 git merge-recursive --no-renames HEAD -- HEAD HEAD && 252 git diff --quiet --cached 253' 254 255test_expect_success '--find-renames rejects negative argument' ' 256 git read-tree --reset -u HEAD && 257 test_must_fail git merge-recursive --find-renames=-25 \ 258 HEAD -- HEAD HEAD && 259 git diff --quiet --cached 260' 261 262test_expect_success '--find-renames rejects non-numbers' ' 263 git read-tree --reset -u HEAD && 264 test_must_fail git merge-recursive --find-renames=0xf \ 265 HEAD -- HEAD HEAD && 266 git diff --quiet --cached 267' 268 269test_expect_success 'rename-threshold=<n> is a synonym for find-renames=<n>' ' 270 git read-tree --reset -u HEAD && 271 test_must_fail git merge-recursive --rename-threshold=$th0 $tail && 272 check_threshold_0 273' 274 275test_expect_success 'last wins in --no-renames --rename-threshold=<n>' ' 276 git read-tree --reset -u HEAD && 277 test_must_fail git merge-recursive --no-renames --rename-threshold=$th0 $tail && 278 check_threshold_0 279' 280 281test_expect_success 'last wins in --rename-threshold=<n> --no-renames' ' 282 git read-tree --reset -u HEAD && 283 git merge-recursive --rename-threshold=$th0 --no-renames $tail && 284 check_no_renames 285' 286 287test_expect_success '--rename-threshold=<n> rejects negative argument' ' 288 git read-tree --reset -u HEAD && 289 test_must_fail git merge-recursive --rename-threshold=-25 \ 290 HEAD -- HEAD HEAD && 291 git diff --quiet --cached 292' 293 294test_expect_success '--rename-threshold=<n> rejects non-numbers' ' 295 git read-tree --reset -u HEAD && 296 test_must_fail git merge-recursive --rename-threshold=0xf \ 297 HEAD -- HEAD HEAD && 298 git diff --quiet --cached 299' 300 301test_expect_success 'last wins in --rename-threshold=<m> --find-renames=<n>' ' 302 git read-tree --reset -u HEAD && 303 test_must_fail git merge-recursive \ 304 --rename-threshold=$th0 --find-renames=$th2 $tail && 305 check_threshold_2 306' 307 308test_expect_success 'last wins in --find-renames=<m> --rename-threshold=<n>' ' 309 git read-tree --reset -u HEAD && 310 test_must_fail git merge-recursive \ 311 --find-renames=$th2 --rename-threshold=$th0 $tail && 312 check_threshold_0 313' 314 315test_expect_success 'merge.renames disables rename detection' ' 316 git read-tree --reset -u HEAD && 317 git -c merge.renames=false merge-recursive $tail && 318 check_no_renames 319' 320 321test_expect_success 'merge.renames defaults to diff.renames' ' 322 git read-tree --reset -u HEAD && 323 git -c diff.renames=false merge-recursive $tail && 324 check_no_renames 325' 326 327test_expect_success 'merge.renames overrides diff.renames' ' 328 git read-tree --reset -u HEAD && 329 test_must_fail git -c diff.renames=false -c merge.renames=true merge-recursive $tail && 330 $check_50 331' 332 333test_done 334