t / t7001-mv.shon commit clone: better handle symlinked files at .git/objects/ (36596fd)
   1#!/bin/sh
   2
   3test_description='git mv in subdirs'
   4. ./test-lib.sh
   5
   6test_expect_success \
   7    'prepare reference tree' \
   8    'mkdir path0 path1 &&
   9     cp "$TEST_DIRECTORY"/../COPYING path0/COPYING &&
  10     git add path0/COPYING &&
  11     git commit -m add -a'
  12
  13test_expect_success \
  14    'moving the file out of subdirectory' \
  15    'cd path0 && git mv COPYING ../path1/COPYING'
  16
  17# in path0 currently
  18test_expect_success \
  19    'commiting the change' \
  20    'cd .. && git commit -m move-out -a'
  21
  22test_expect_success \
  23    'checking the commit' \
  24    'git diff-tree -r -M --name-status  HEAD^ HEAD >actual &&
  25    grep "^R100..*path0/COPYING..*path1/COPYING" actual'
  26
  27test_expect_success \
  28    'moving the file back into subdirectory' \
  29    'cd path0 && git mv ../path1/COPYING COPYING'
  30
  31# in path0 currently
  32test_expect_success \
  33    'commiting the change' \
  34    'cd .. && git commit -m move-in -a'
  35
  36test_expect_success \
  37    'checking the commit' \
  38    'git diff-tree -r -M --name-status  HEAD^ HEAD >actual &&
  39    grep "^R100..*path1/COPYING..*path0/COPYING" actual'
  40
  41test_expect_success \
  42    'mv --dry-run does not move file' \
  43    'git mv -n path0/COPYING MOVED &&
  44     test -f path0/COPYING &&
  45     test ! -f MOVED'
  46
  47test_expect_success \
  48    'checking -k on non-existing file' \
  49    'git mv -k idontexist path0'
  50
  51test_expect_success \
  52    'checking -k on untracked file' \
  53    'touch untracked1 &&
  54     git mv -k untracked1 path0 &&
  55     test -f untracked1 &&
  56     test ! -f path0/untracked1'
  57
  58test_expect_success \
  59    'checking -k on multiple untracked files' \
  60    'touch untracked2 &&
  61     git mv -k untracked1 untracked2 path0 &&
  62     test -f untracked1 &&
  63     test -f untracked2 &&
  64     test ! -f path0/untracked1 &&
  65     test ! -f path0/untracked2'
  66
  67test_expect_success \
  68    'checking -f on untracked file with existing target' \
  69    'touch path0/untracked1 &&
  70     test_must_fail git mv -f untracked1 path0 &&
  71     test ! -f .git/index.lock &&
  72     test -f untracked1 &&
  73     test -f path0/untracked1'
  74
  75# clean up the mess in case bad things happen
  76rm -f idontexist untracked1 untracked2 \
  77     path0/idontexist path0/untracked1 path0/untracked2 \
  78     .git/index.lock
  79rmdir path1
  80
  81test_expect_success \
  82    'moving to absent target with trailing slash' \
  83    'test_must_fail git mv path0/COPYING no-such-dir/ &&
  84     test_must_fail git mv path0/COPYING no-such-dir// &&
  85     git mv path0/ no-such-dir/ &&
  86     test_path_is_dir no-such-dir'
  87
  88test_expect_success \
  89    'clean up' \
  90    'git reset --hard'
  91
  92test_expect_success \
  93    'moving to existing untracked target with trailing slash' \
  94    'mkdir path1 &&
  95     git mv path0/ path1/ &&
  96     test_path_is_dir path1/path0/'
  97
  98test_expect_success \
  99    'moving to existing tracked target with trailing slash' \
 100    'mkdir path2 &&
 101     >path2/file && git add path2/file &&
 102     git mv path1/path0/ path2/ &&
 103     test_path_is_dir path2/path0/'
 104
 105test_expect_success \
 106    'clean up' \
 107    'git reset --hard'
 108
 109test_expect_success \
 110    'adding another file' \
 111    'cp "$TEST_DIRECTORY"/../README.md path0/README &&
 112     git add path0/README &&
 113     git commit -m add2 -a'
 114
 115test_expect_success \
 116    'moving whole subdirectory' \
 117    'git mv path0 path2'
 118
 119test_expect_success \
 120    'commiting the change' \
 121    'git commit -m dir-move -a'
 122
 123test_expect_success \
 124    'checking the commit' \
 125    'git diff-tree -r -M --name-status  HEAD^ HEAD >actual &&
 126     grep "^R100..*path0/COPYING..*path2/COPYING" actual &&
 127     grep "^R100..*path0/README..*path2/README" actual'
 128
 129test_expect_success \
 130    'succeed when source is a prefix of destination' \
 131    'git mv path2/COPYING path2/COPYING-renamed'
 132
 133test_expect_success \
 134    'moving whole subdirectory into subdirectory' \
 135    'git mv path2 path1'
 136
 137test_expect_success \
 138    'commiting the change' \
 139    'git commit -m dir-move -a'
 140
 141test_expect_success \
 142    'checking the commit' \
 143    'git diff-tree -r -M --name-status  HEAD^ HEAD >actual &&
 144     grep "^R100..*path2/COPYING..*path1/path2/COPYING" actual &&
 145     grep "^R100..*path2/README..*path1/path2/README" actual'
 146
 147test_expect_success \
 148    'do not move directory over existing directory' \
 149    'mkdir path0 && mkdir path0/path2 && test_must_fail git mv path2 path0'
 150
 151test_expect_success \
 152    'move into "."' \
 153    'git mv path1/path2/ .'
 154
 155test_expect_success "Michael Cassar's test case" '
 156        rm -fr .git papers partA &&
 157        git init &&
 158        mkdir -p papers/unsorted papers/all-papers partA &&
 159        echo a > papers/unsorted/Thesis.pdf &&
 160        echo b > partA/outline.txt &&
 161        echo c > papers/unsorted/_another &&
 162        git add papers partA &&
 163        T1=$(git write-tree) &&
 164
 165        git mv papers/unsorted/Thesis.pdf papers/all-papers/moo-blah.pdf &&
 166
 167        T=$(git write-tree) &&
 168        git ls-tree -r $T | verbose grep partA/outline.txt
 169'
 170
 171rm -fr papers partA path?
 172
 173test_expect_success "Sergey Vlasov's test case" '
 174        rm -fr .git &&
 175        git init &&
 176        mkdir ab &&
 177        date >ab.c &&
 178        date >ab/d &&
 179        git add ab.c ab &&
 180        git commit -m 'initial' &&
 181        git mv ab a
 182'
 183
 184test_expect_success 'absolute pathname' '(
 185
 186        rm -fr mine &&
 187        mkdir mine &&
 188        cd mine &&
 189        test_create_repo one &&
 190        cd one &&
 191        mkdir sub &&
 192        >sub/file &&
 193        git add sub/file &&
 194
 195        git mv sub "$(pwd)/in" &&
 196        ! test -d sub &&
 197        test -d in &&
 198        git ls-files --error-unmatch in/file
 199
 200
 201)'
 202
 203test_expect_success 'absolute pathname outside should fail' '(
 204
 205        rm -fr mine &&
 206        mkdir mine &&
 207        cd mine &&
 208        out=$(pwd) &&
 209        test_create_repo one &&
 210        cd one &&
 211        mkdir sub &&
 212        >sub/file &&
 213        git add sub/file &&
 214
 215        test_must_fail git mv sub "$out/out" &&
 216        test -d sub &&
 217        ! test -d ../in &&
 218        git ls-files --error-unmatch sub/file
 219
 220)'
 221
 222test_expect_success 'git mv to move multiple sources into a directory' '
 223        rm -fr .git && git init &&
 224        mkdir dir other &&
 225        >dir/a.txt &&
 226        >dir/b.txt &&
 227        git add dir/?.txt &&
 228        git mv dir/a.txt dir/b.txt other &&
 229        git ls-files >actual &&
 230        { echo other/a.txt; echo other/b.txt; } >expect &&
 231        test_cmp expect actual
 232'
 233
 234test_expect_success 'git mv should not change sha1 of moved cache entry' '
 235
 236        rm -fr .git &&
 237        git init &&
 238        echo 1 >dirty &&
 239        git add dirty &&
 240        entry="$(git ls-files --stage dirty | cut -f 1)" &&
 241        git mv dirty dirty2 &&
 242        [ "$entry" = "$(git ls-files --stage dirty2 | cut -f 1)" ] &&
 243        echo 2 >dirty2 &&
 244        git mv dirty2 dirty &&
 245        [ "$entry" = "$(git ls-files --stage dirty | cut -f 1)" ]
 246
 247'
 248
 249rm -f dirty dirty2
 250
 251test_expect_success 'git mv should overwrite symlink to a file' '
 252
 253        rm -fr .git &&
 254        git init &&
 255        echo 1 >moved &&
 256        test_ln_s_add moved symlink &&
 257        git add moved &&
 258        test_must_fail git mv moved symlink &&
 259        git mv -f moved symlink &&
 260        ! test -e moved &&
 261        test -f symlink &&
 262        test "$(cat symlink)" = 1 &&
 263        git update-index --refresh &&
 264        git diff-files --quiet
 265
 266'
 267
 268rm -f moved symlink
 269
 270test_expect_success 'git mv should overwrite file with a symlink' '
 271
 272        rm -fr .git &&
 273        git init &&
 274        echo 1 >moved &&
 275        test_ln_s_add moved symlink &&
 276        git add moved &&
 277        test_must_fail git mv symlink moved &&
 278        git mv -f symlink moved &&
 279        ! test -e symlink &&
 280        git update-index --refresh &&
 281        git diff-files --quiet
 282
 283'
 284
 285test_expect_success SYMLINKS 'check moved symlink' '
 286
 287        test -h moved
 288'
 289
 290rm -f moved symlink
 291
 292test_expect_success 'setup submodule' '
 293        git commit -m initial &&
 294        git reset --hard &&
 295        git submodule add ./. sub &&
 296        echo content >file &&
 297        git add file &&
 298        git commit -m "added sub and file" &&
 299        mkdir -p deep/directory/hierarchy &&
 300        git submodule add ./. deep/directory/hierarchy/sub &&
 301        git commit -m "added another submodule" &&
 302        git branch submodule
 303'
 304
 305test_expect_success 'git mv cannot move a submodule in a file' '
 306        test_must_fail git mv sub file
 307'
 308
 309test_expect_success 'git mv moves a submodule with a .git directory and no .gitmodules' '
 310        entry="$(git ls-files --stage sub | cut -f 1)" &&
 311        git rm .gitmodules &&
 312        (
 313                cd sub &&
 314                rm -f .git &&
 315                cp -R -P -p ../.git/modules/sub .git &&
 316                GIT_WORK_TREE=. git config --unset core.worktree
 317        ) &&
 318        mkdir mod &&
 319        git mv sub mod/sub &&
 320        ! test -e sub &&
 321        [ "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" ] &&
 322        (
 323                cd mod/sub &&
 324                git status
 325        ) &&
 326        git update-index --refresh &&
 327        git diff-files --quiet
 328'
 329
 330test_expect_success 'git mv moves a submodule with a .git directory and .gitmodules' '
 331        rm -rf mod &&
 332        git reset --hard &&
 333        git submodule update &&
 334        entry="$(git ls-files --stage sub | cut -f 1)" &&
 335        (
 336                cd sub &&
 337                rm -f .git &&
 338                cp -R -P -p ../.git/modules/sub .git &&
 339                GIT_WORK_TREE=. git config --unset core.worktree
 340        ) &&
 341        mkdir mod &&
 342        git mv sub mod/sub &&
 343        ! test -e sub &&
 344        [ "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" ] &&
 345        (
 346                cd mod/sub &&
 347                git status
 348        ) &&
 349        echo mod/sub >expected &&
 350        git config -f .gitmodules submodule.sub.path >actual &&
 351        test_cmp expected actual &&
 352        git update-index --refresh &&
 353        git diff-files --quiet
 354'
 355
 356test_expect_success 'git mv moves a submodule with gitfile' '
 357        rm -rf mod &&
 358        git reset --hard &&
 359        git submodule update &&
 360        entry="$(git ls-files --stage sub | cut -f 1)" &&
 361        mkdir mod &&
 362        (
 363                cd mod &&
 364                git mv ../sub/ .
 365        ) &&
 366        ! test -e sub &&
 367        [ "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" ] &&
 368        (
 369                cd mod/sub &&
 370                git status
 371        ) &&
 372        echo mod/sub >expected &&
 373        git config -f .gitmodules submodule.sub.path >actual &&
 374        test_cmp expected actual &&
 375        git update-index --refresh &&
 376        git diff-files --quiet
 377'
 378
 379test_expect_success 'mv does not complain when no .gitmodules file is found' '
 380        rm -rf mod &&
 381        git reset --hard &&
 382        git submodule update &&
 383        git rm .gitmodules &&
 384        entry="$(git ls-files --stage sub | cut -f 1)" &&
 385        mkdir mod &&
 386        git mv sub mod/sub 2>actual.err &&
 387        test_must_be_empty actual.err &&
 388        ! test -e sub &&
 389        [ "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" ] &&
 390        (
 391                cd mod/sub &&
 392                git status
 393        ) &&
 394        git update-index --refresh &&
 395        git diff-files --quiet
 396'
 397
 398test_expect_success 'mv will error out on a modified .gitmodules file unless staged' '
 399        rm -rf mod &&
 400        git reset --hard &&
 401        git submodule update &&
 402        git config -f .gitmodules foo.bar true &&
 403        entry="$(git ls-files --stage sub | cut -f 1)" &&
 404        mkdir mod &&
 405        test_must_fail git mv sub mod/sub 2>actual.err &&
 406        test -s actual.err &&
 407        test -e sub &&
 408        git diff-files --quiet -- sub &&
 409        git add .gitmodules &&
 410        git mv sub mod/sub 2>actual.err &&
 411        test_must_be_empty actual.err &&
 412        ! test -e sub &&
 413        [ "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" ] &&
 414        (
 415                cd mod/sub &&
 416                git status
 417        ) &&
 418        git update-index --refresh &&
 419        git diff-files --quiet
 420'
 421
 422test_expect_success 'mv issues a warning when section is not found in .gitmodules' '
 423        rm -rf mod &&
 424        git reset --hard &&
 425        git submodule update &&
 426        git config -f .gitmodules --remove-section submodule.sub &&
 427        git add .gitmodules &&
 428        entry="$(git ls-files --stage sub | cut -f 1)" &&
 429        echo "warning: Could not find section in .gitmodules where path=sub" >expect.err &&
 430        mkdir mod &&
 431        git mv sub mod/sub 2>actual.err &&
 432        test_i18ncmp expect.err actual.err &&
 433        ! test -e sub &&
 434        [ "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" ] &&
 435        (
 436                cd mod/sub &&
 437                git status
 438        ) &&
 439        git update-index --refresh &&
 440        git diff-files --quiet
 441'
 442
 443test_expect_success 'mv --dry-run does not touch the submodule or .gitmodules' '
 444        rm -rf mod &&
 445        git reset --hard &&
 446        git submodule update &&
 447        mkdir mod &&
 448        git mv -n sub mod/sub 2>actual.err &&
 449        test -f sub/.git &&
 450        git diff-index --exit-code HEAD &&
 451        git update-index --refresh &&
 452        git diff-files --quiet -- sub .gitmodules
 453'
 454
 455test_expect_success 'checking out a commit before submodule moved needs manual updates' '
 456        git mv sub sub2 &&
 457        git commit -m "moved sub to sub2" &&
 458        git checkout -q HEAD^ 2>actual &&
 459        test_i18ngrep "^warning: unable to rmdir '\''sub2'\'':" actual &&
 460        git status -s sub2 >actual &&
 461        echo "?? sub2/" >expected &&
 462        test_cmp expected actual &&
 463        ! test -f sub/.git &&
 464        test -f sub2/.git &&
 465        git submodule update &&
 466        test -f sub/.git &&
 467        rm -rf sub2 &&
 468        git diff-index --exit-code HEAD &&
 469        git update-index --refresh &&
 470        git diff-files --quiet -- sub .gitmodules &&
 471        git status -s sub2 >actual &&
 472        test_must_be_empty actual
 473'
 474
 475test_expect_success 'mv -k does not accidentally destroy submodules' '
 476        git checkout submodule &&
 477        mkdir dummy dest &&
 478        git mv -k dummy sub dest &&
 479        git status --porcelain >actual &&
 480        grep "^R  sub -> dest/sub" actual &&
 481        git reset --hard &&
 482        git checkout .
 483'
 484
 485test_expect_success 'moving a submodule in nested directories' '
 486        (
 487                cd deep &&
 488                git mv directory ../ &&
 489                # git status would fail if the update of linking git dir to
 490                # work dir of the submodule failed.
 491                git status &&
 492                git config -f ../.gitmodules submodule.deep/directory/hierarchy/sub.path >../actual &&
 493                echo "directory/hierarchy/sub" >../expect
 494        ) &&
 495        test_cmp expect actual
 496'
 497
 498test_expect_success 'moving nested submodules' '
 499        git commit -am "cleanup commit" &&
 500        mkdir sub_nested_nested &&
 501        (cd sub_nested_nested &&
 502                touch nested_level2 &&
 503                git init &&
 504                git add . &&
 505                git commit -m "nested level 2"
 506        ) &&
 507        mkdir sub_nested &&
 508        (cd sub_nested &&
 509                touch nested_level1 &&
 510                git init &&
 511                git add . &&
 512                git commit -m "nested level 1" &&
 513                git submodule add ../sub_nested_nested &&
 514                git commit -m "add nested level 2"
 515        ) &&
 516        git submodule add ./sub_nested nested_move &&
 517        git commit -m "add nested_move" &&
 518        git submodule update --init --recursive &&
 519        git mv nested_move sub_nested_moved &&
 520        git status
 521'
 522
 523test_done