t / t6043-merge-rename-directories.shon commit directory rename detection: basic testcases (eabbebf)
   1#!/bin/sh
   2
   3test_description="recursive merge with directory renames"
   4# includes checking of many corner cases, with a similar methodology to:
   5#   t6042: corner cases with renames but not criss-cross merges
   6#   t6036: corner cases with both renames and criss-cross merges
   7#
   8# The setup for all of them, pictorially, is:
   9#
  10#      A
  11#      o
  12#     / \
  13#  O o   ?
  14#     \ /
  15#      o
  16#      B
  17#
  18# To help make it easier to follow the flow of tests, they have been
  19# divided into sections and each test will start with a quick explanation
  20# of what commits O, A, and B contain.
  21#
  22# Notation:
  23#    z/{b,c}   means  files z/b and z/c both exist
  24#    x/d_1     means  file x/d exists with content d1.  (Purpose of the
  25#                     underscore notation is to differentiate different
  26#                     files that might be renamed into each other's paths.)
  27
  28. ./test-lib.sh
  29
  30
  31###########################################################################
  32# SECTION 1: Basic cases we should be able to handle
  33###########################################################################
  34
  35# Testcase 1a, Basic directory rename.
  36#   Commit O: z/{b,c}
  37#   Commit A: y/{b,c}
  38#   Commit B: z/{b,c,d,e/f}
  39#   Expected: y/{b,c,d,e/f}
  40
  41test_expect_success '1a-setup: Simple directory rename detection' '
  42        test_create_repo 1a &&
  43        (
  44                cd 1a &&
  45
  46                mkdir z &&
  47                echo b >z/b &&
  48                echo c >z/c &&
  49                git add z &&
  50                test_tick &&
  51                git commit -m "O" &&
  52
  53                git branch O &&
  54                git branch A &&
  55                git branch B &&
  56
  57                git checkout A &&
  58                git mv z y &&
  59                test_tick &&
  60                git commit -m "A" &&
  61
  62                git checkout B &&
  63                echo d >z/d &&
  64                mkdir z/e &&
  65                echo f >z/e/f &&
  66                git add z/d z/e/f &&
  67                test_tick &&
  68                git commit -m "B"
  69        )
  70'
  71
  72test_expect_failure '1a-check: Simple directory rename detection' '
  73        (
  74                cd 1a &&
  75
  76                git checkout A^0 &&
  77
  78                git merge -s recursive B^0 &&
  79
  80                git ls-files -s >out &&
  81                test_line_count = 4 out &&
  82
  83                git rev-parse >actual \
  84                        HEAD:y/b HEAD:y/c HEAD:y/d HEAD:y/e/f &&
  85                git rev-parse >expect \
  86                        O:z/b    O:z/c    B:z/d    B:z/e/f &&
  87                test_cmp expect actual &&
  88
  89                git hash-object y/d >actual &&
  90                git rev-parse B:z/d >expect &&
  91                test_cmp expect actual &&
  92
  93                test_must_fail git rev-parse HEAD:z/d &&
  94                test_must_fail git rev-parse HEAD:z/e/f &&
  95                test_path_is_missing z/d &&
  96                test_path_is_missing z/e/f
  97        )
  98'
  99
 100# Testcase 1b, Merge a directory with another
 101#   Commit O: z/{b,c},   y/d
 102#   Commit A: z/{b,c,e}, y/d
 103#   Commit B: y/{b,c,d}
 104#   Expected: y/{b,c,d,e}
 105
 106test_expect_success '1b-setup: Merge a directory with another' '
 107        test_create_repo 1b &&
 108        (
 109                cd 1b &&
 110
 111                mkdir z &&
 112                echo b >z/b &&
 113                echo c >z/c &&
 114                mkdir y &&
 115                echo d >y/d &&
 116                git add z y &&
 117                test_tick &&
 118                git commit -m "O" &&
 119
 120                git branch O &&
 121                git branch A &&
 122                git branch B &&
 123
 124                git checkout A &&
 125                echo e >z/e &&
 126                git add z/e &&
 127                test_tick &&
 128                git commit -m "A" &&
 129
 130                git checkout B &&
 131                git mv z/b y &&
 132                git mv z/c y &&
 133                rmdir z &&
 134                test_tick &&
 135                git commit -m "B"
 136        )
 137'
 138
 139test_expect_failure '1b-check: Merge a directory with another' '
 140        (
 141                cd 1b &&
 142
 143                git checkout A^0 &&
 144
 145                git merge -s recursive B^0 &&
 146
 147                git ls-files -s >out &&
 148                test_line_count = 4 out &&
 149
 150                git rev-parse >actual \
 151                        HEAD:y/b HEAD:y/c HEAD:y/d HEAD:y/e &&
 152                git rev-parse >expect \
 153                        O:z/b    O:z/c    O:y/d    A:z/e &&
 154                test_cmp expect actual &&
 155                test_must_fail git rev-parse HEAD:z/e
 156        )
 157'
 158
 159# Testcase 1c, Transitive renaming
 160#   (Related to testcases 3a and 6d -- when should a transitive rename apply?)
 161#   (Related to testcases 9c and 9d -- can transitivity repeat?)
 162#   Commit O: z/{b,c},   x/d
 163#   Commit A: y/{b,c},   x/d
 164#   Commit B: z/{b,c,d}
 165#   Expected: y/{b,c,d}  (because x/d -> z/d -> y/d)
 166
 167test_expect_success '1c-setup: Transitive renaming' '
 168        test_create_repo 1c &&
 169        (
 170                cd 1c &&
 171
 172                mkdir z &&
 173                echo b >z/b &&
 174                echo c >z/c &&
 175                mkdir x &&
 176                echo d >x/d &&
 177                git add z x &&
 178                test_tick &&
 179                git commit -m "O" &&
 180
 181                git branch O &&
 182                git branch A &&
 183                git branch B &&
 184
 185                git checkout A &&
 186                git mv z y &&
 187                test_tick &&
 188                git commit -m "A" &&
 189
 190                git checkout B &&
 191                git mv x/d z/d &&
 192                test_tick &&
 193                git commit -m "B"
 194        )
 195'
 196
 197test_expect_failure '1c-check: Transitive renaming' '
 198        (
 199                cd 1c &&
 200
 201                git checkout A^0 &&
 202
 203                git merge -s recursive B^0 &&
 204
 205                git ls-files -s >out &&
 206                test_line_count = 3 out &&
 207
 208                git rev-parse >actual \
 209                        HEAD:y/b HEAD:y/c HEAD:y/d &&
 210                git rev-parse >expect \
 211                        O:z/b    O:z/c    O:x/d &&
 212                test_cmp expect actual &&
 213                test_must_fail git rev-parse HEAD:x/d &&
 214                test_must_fail git rev-parse HEAD:z/d &&
 215                test_path_is_missing z/d
 216        )
 217'
 218
 219# Testcase 1d, Directory renames (merging two directories into one new one)
 220#              cause a rename/rename(2to1) conflict
 221#   (Related to testcases 1c and 7b)
 222#   Commit O. z/{b,c},        y/{d,e}
 223#   Commit A. x/{b,c},        y/{d,e,m,wham_1}
 224#   Commit B. z/{b,c,n,wham_2}, x/{d,e}
 225#   Expected: x/{b,c,d,e,m,n}, CONFLICT:(y/wham_1 & z/wham_2 -> x/wham)
 226#   Note: y/m & z/n should definitely move into x.  By the same token, both
 227#         y/wham_1 & z/wham_2 should too...giving us a conflict.
 228
 229test_expect_success '1d-setup: Directory renames cause a rename/rename(2to1) conflict' '
 230        test_create_repo 1d &&
 231        (
 232                cd 1d &&
 233
 234                mkdir z &&
 235                echo b >z/b &&
 236                echo c >z/c &&
 237                mkdir y &&
 238                echo d >y/d &&
 239                echo e >y/e &&
 240                git add z y &&
 241                test_tick &&
 242                git commit -m "O" &&
 243
 244                git branch O &&
 245                git branch A &&
 246                git branch B &&
 247
 248                git checkout A &&
 249                git mv z x &&
 250                echo m >y/m &&
 251                echo wham1 >y/wham &&
 252                git add y &&
 253                test_tick &&
 254                git commit -m "A" &&
 255
 256                git checkout B &&
 257                git mv y x &&
 258                echo n >z/n &&
 259                echo wham2 >z/wham &&
 260                git add z &&
 261                test_tick &&
 262                git commit -m "B"
 263        )
 264'
 265
 266test_expect_failure '1d-check: Directory renames cause a rename/rename(2to1) conflict' '
 267        (
 268                cd 1d &&
 269
 270                git checkout A^0 &&
 271
 272                test_must_fail git merge -s recursive B^0 >out &&
 273                test_i18ngrep "CONFLICT (rename/rename)" out &&
 274
 275                git ls-files -s >out &&
 276                test_line_count = 8 out &&
 277                git ls-files -u >out &&
 278                test_line_count = 2 out &&
 279                git ls-files -o >out &&
 280                test_line_count = 3 out &&
 281
 282                git rev-parse >actual \
 283                        :0:x/b :0:x/c :0:x/d :0:x/e :0:x/m :0:x/n &&
 284                git rev-parse >expect \
 285                         O:z/b  O:z/c  O:y/d  O:y/e  A:y/m  B:z/n &&
 286                test_cmp expect actual &&
 287
 288                test_must_fail git rev-parse :0:x/wham &&
 289                git rev-parse >actual \
 290                        :2:x/wham :3:x/wham &&
 291                git rev-parse >expect \
 292                         A:y/wham  B:z/wham &&
 293                test_cmp expect actual &&
 294
 295                test_path_is_missing x/wham &&
 296                test_path_is_file x/wham~HEAD &&
 297                test_path_is_file x/wham~B^0 &&
 298
 299                git hash-object >actual \
 300                        x/wham~HEAD x/wham~B^0 &&
 301                git rev-parse >expect \
 302                        A:y/wham    B:z/wham &&
 303                test_cmp expect actual
 304        )
 305'
 306
 307# Testcase 1e, Renamed directory, with all filenames being renamed too
 308#   Commit O: z/{oldb,oldc}
 309#   Commit A: y/{newb,newc}
 310#   Commit B: z/{oldb,oldc,d}
 311#   Expected: y/{newb,newc,d}
 312
 313test_expect_success '1e-setup: Renamed directory, with all files being renamed too' '
 314        test_create_repo 1e &&
 315        (
 316                cd 1e &&
 317
 318                mkdir z &&
 319                echo b >z/oldb &&
 320                echo c >z/oldc &&
 321                git add z &&
 322                test_tick &&
 323                git commit -m "O" &&
 324
 325                git branch O &&
 326                git branch A &&
 327                git branch B &&
 328
 329                git checkout A &&
 330                mkdir y &&
 331                git mv z/oldb y/newb &&
 332                git mv z/oldc y/newc &&
 333                test_tick &&
 334                git commit -m "A" &&
 335
 336                git checkout B &&
 337                echo d >z/d &&
 338                git add z/d &&
 339                test_tick &&
 340                git commit -m "B"
 341        )
 342'
 343
 344test_expect_failure '1e-check: Renamed directory, with all files being renamed too' '
 345        (
 346                cd 1e &&
 347
 348                git checkout A^0 &&
 349
 350                git merge -s recursive B^0 &&
 351
 352                git ls-files -s >out &&
 353                test_line_count = 3 out &&
 354
 355                git rev-parse >actual \
 356                        HEAD:y/newb HEAD:y/newc HEAD:y/d &&
 357                git rev-parse >expect \
 358                        O:z/oldb    O:z/oldc    B:z/d &&
 359                test_cmp expect actual &&
 360                test_must_fail git rev-parse HEAD:z/d
 361        )
 362'
 363
 364# Testcase 1f, Split a directory into two other directories
 365#   (Related to testcases 3a, all of section 2, and all of section 4)
 366#   Commit O: z/{b,c,d,e,f}
 367#   Commit A: z/{b,c,d,e,f,g}
 368#   Commit B: y/{b,c}, x/{d,e,f}
 369#   Expected: y/{b,c}, x/{d,e,f,g}
 370
 371test_expect_success '1f-setup: Split a directory into two other directories' '
 372        test_create_repo 1f &&
 373        (
 374                cd 1f &&
 375
 376                mkdir z &&
 377                echo b >z/b &&
 378                echo c >z/c &&
 379                echo d >z/d &&
 380                echo e >z/e &&
 381                echo f >z/f &&
 382                git add z &&
 383                test_tick &&
 384                git commit -m "O" &&
 385
 386                git branch O &&
 387                git branch A &&
 388                git branch B &&
 389
 390                git checkout A &&
 391                echo g >z/g &&
 392                git add z/g &&
 393                test_tick &&
 394                git commit -m "A" &&
 395
 396                git checkout B &&
 397                mkdir y &&
 398                mkdir x &&
 399                git mv z/b y/ &&
 400                git mv z/c y/ &&
 401                git mv z/d x/ &&
 402                git mv z/e x/ &&
 403                git mv z/f x/ &&
 404                rmdir z &&
 405                test_tick &&
 406                git commit -m "B"
 407        )
 408'
 409
 410test_expect_failure '1f-check: Split a directory into two other directories' '
 411        (
 412                cd 1f &&
 413
 414                git checkout A^0 &&
 415
 416                git merge -s recursive B^0 &&
 417
 418                git ls-files -s >out &&
 419                test_line_count = 6 out &&
 420
 421                git rev-parse >actual \
 422                        HEAD:y/b HEAD:y/c HEAD:x/d HEAD:x/e HEAD:x/f HEAD:x/g &&
 423                git rev-parse >expect \
 424                        O:z/b    O:z/c    O:z/d    O:z/e    O:z/f    A:z/g &&
 425                test_cmp expect actual &&
 426                test_path_is_missing z/g &&
 427                test_must_fail git rev-parse HEAD:z/g
 428        )
 429'
 430
 431###########################################################################
 432# Rules suggested by testcases in section 1:
 433#
 434#   We should still detect the directory rename even if it wasn't just
 435#   the directory renamed, but the files within it. (see 1b)
 436#
 437#   If renames split a directory into two or more others, the directory
 438#   with the most renames, "wins" (see 1c).  However, see the testcases
 439#   in section 2, plus testcases 3a and 4a.
 440###########################################################################
 441
 442test_done