t / t7001-mv.shon commit t/helper: 'test-chmtime (--get|-g)' to print only the mtime (decf711)
   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 | \
  25    grep "^R100..*path0/COPYING..*path1/COPYING"'
  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 | \
  39    grep "^R100..*path1/COPYING..*path0/COPYING"'
  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 | \
 126     grep "^R100..*path0/COPYING..*path2/COPYING" &&
 127     git diff-tree -r -M --name-status  HEAD^ HEAD | \
 128     grep "^R100..*path0/README..*path2/README"'
 129
 130test_expect_success \
 131    'succeed when source is a prefix of destination' \
 132    'git mv path2/COPYING path2/COPYING-renamed'
 133
 134test_expect_success \
 135    'moving whole subdirectory into subdirectory' \
 136    'git mv path2 path1'
 137
 138test_expect_success \
 139    'commiting the change' \
 140    'git commit -m dir-move -a'
 141
 142test_expect_success \
 143    'checking the commit' \
 144    'git diff-tree -r -M --name-status  HEAD^ HEAD | \
 145     grep "^R100..*path2/COPYING..*path1/path2/COPYING" &&
 146     git diff-tree -r -M --name-status  HEAD^ HEAD | \
 147     grep "^R100..*path2/README..*path1/path2/README"'
 148
 149test_expect_success \
 150    'do not move directory over existing directory' \
 151    'mkdir path0 && mkdir path0/path2 && test_must_fail git mv path2 path0'
 152
 153test_expect_success \
 154    'move into "."' \
 155    'git mv path1/path2/ .'
 156
 157test_expect_success "Michael Cassar's test case" '
 158        rm -fr .git papers partA &&
 159        git init &&
 160        mkdir -p papers/unsorted papers/all-papers partA &&
 161        echo a > papers/unsorted/Thesis.pdf &&
 162        echo b > partA/outline.txt &&
 163        echo c > papers/unsorted/_another &&
 164        git add papers partA &&
 165        T1=$(git write-tree) &&
 166
 167        git mv papers/unsorted/Thesis.pdf papers/all-papers/moo-blah.pdf &&
 168
 169        T=$(git write-tree) &&
 170        git ls-tree -r $T | verbose grep partA/outline.txt
 171'
 172
 173rm -fr papers partA path?
 174
 175test_expect_success "Sergey Vlasov's test case" '
 176        rm -fr .git &&
 177        git init &&
 178        mkdir ab &&
 179        date >ab.c &&
 180        date >ab/d &&
 181        git add ab.c ab &&
 182        git commit -m 'initial' &&
 183        git mv ab a
 184'
 185
 186test_expect_success 'absolute pathname' '(
 187
 188        rm -fr mine &&
 189        mkdir mine &&
 190        cd mine &&
 191        test_create_repo one &&
 192        cd one &&
 193        mkdir sub &&
 194        >sub/file &&
 195        git add sub/file &&
 196
 197        git mv sub "$(pwd)/in" &&
 198        ! test -d sub &&
 199        test -d in &&
 200        git ls-files --error-unmatch in/file
 201
 202
 203)'
 204
 205test_expect_success 'absolute pathname outside should fail' '(
 206
 207        rm -fr mine &&
 208        mkdir mine &&
 209        cd mine &&
 210        out=$(pwd) &&
 211        test_create_repo one &&
 212        cd one &&
 213        mkdir sub &&
 214        >sub/file &&
 215        git add sub/file &&
 216
 217        test_must_fail git mv sub "$out/out" &&
 218        test -d sub &&
 219        ! test -d ../in &&
 220        git ls-files --error-unmatch sub/file
 221
 222)'
 223
 224test_expect_success 'git mv to move multiple sources into a directory' '
 225        rm -fr .git && git init &&
 226        mkdir dir other &&
 227        >dir/a.txt &&
 228        >dir/b.txt &&
 229        git add dir/?.txt &&
 230        git mv dir/a.txt dir/b.txt other &&
 231        git ls-files >actual &&
 232        { echo other/a.txt; echo other/b.txt; } >expect &&
 233        test_cmp expect actual
 234'
 235
 236test_expect_success 'git mv should not change sha1 of moved cache entry' '
 237
 238        rm -fr .git &&
 239        git init &&
 240        echo 1 >dirty &&
 241        git add dirty &&
 242        entry="$(git ls-files --stage dirty | cut -f 1)" &&
 243        git mv dirty dirty2 &&
 244        [ "$entry" = "$(git ls-files --stage dirty2 | cut -f 1)" ] &&
 245        echo 2 >dirty2 &&
 246        git mv dirty2 dirty &&
 247        [ "$entry" = "$(git ls-files --stage dirty | cut -f 1)" ]
 248
 249'
 250
 251rm -f dirty dirty2
 252
 253test_expect_success 'git mv should overwrite symlink to a file' '
 254
 255        rm -fr .git &&
 256        git init &&
 257        echo 1 >moved &&
 258        test_ln_s_add moved symlink &&
 259        git add moved &&
 260        test_must_fail git mv moved symlink &&
 261        git mv -f moved symlink &&
 262        ! test -e moved &&
 263        test -f symlink &&
 264        test "$(cat symlink)" = 1 &&
 265        git update-index --refresh &&
 266        git diff-files --quiet
 267
 268'
 269
 270rm -f moved symlink
 271
 272test_expect_success 'git mv should overwrite file with a symlink' '
 273
 274        rm -fr .git &&
 275        git init &&
 276        echo 1 >moved &&
 277        test_ln_s_add moved symlink &&
 278        git add moved &&
 279        test_must_fail git mv symlink moved &&
 280        git mv -f symlink moved &&
 281        ! test -e symlink &&
 282        git update-index --refresh &&
 283        git diff-files --quiet
 284
 285'
 286
 287test_expect_success SYMLINKS 'check moved symlink' '
 288
 289        test -h moved
 290'
 291
 292rm -f moved symlink
 293
 294test_expect_success 'setup submodule' '
 295        git commit -m initial &&
 296        git reset --hard &&
 297        git submodule add ./. sub &&
 298        echo content >file &&
 299        git add file &&
 300        git commit -m "added sub and file" &&
 301        mkdir -p deep/directory/hierarchy &&
 302        git submodule add ./. deep/directory/hierarchy/sub &&
 303        git commit -m "added another submodule" &&
 304        git branch submodule
 305'
 306
 307test_expect_success 'git mv cannot move a submodule in a file' '
 308        test_must_fail git mv sub file
 309'
 310
 311test_expect_success 'git mv moves a submodule with a .git directory and no .gitmodules' '
 312        entry="$(git ls-files --stage sub | cut -f 1)" &&
 313        git rm .gitmodules &&
 314        (
 315                cd sub &&
 316                rm -f .git &&
 317                cp -R -P -p ../.git/modules/sub .git &&
 318                GIT_WORK_TREE=. git config --unset core.worktree
 319        ) &&
 320        mkdir mod &&
 321        git mv sub mod/sub &&
 322        ! test -e sub &&
 323        [ "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" ] &&
 324        (
 325                cd mod/sub &&
 326                git status
 327        ) &&
 328        git update-index --refresh &&
 329        git diff-files --quiet
 330'
 331
 332test_expect_success 'git mv moves a submodule with a .git directory and .gitmodules' '
 333        rm -rf mod &&
 334        git reset --hard &&
 335        git submodule update &&
 336        entry="$(git ls-files --stage sub | cut -f 1)" &&
 337        (
 338                cd sub &&
 339                rm -f .git &&
 340                cp -R -P -p ../.git/modules/sub .git &&
 341                GIT_WORK_TREE=. git config --unset core.worktree
 342        ) &&
 343        mkdir mod &&
 344        git mv sub mod/sub &&
 345        ! test -e sub &&
 346        [ "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" ] &&
 347        (
 348                cd mod/sub &&
 349                git status
 350        ) &&
 351        echo mod/sub >expected &&
 352        git config -f .gitmodules submodule.sub.path >actual &&
 353        test_cmp expected actual &&
 354        git update-index --refresh &&
 355        git diff-files --quiet
 356'
 357
 358test_expect_success 'git mv moves a submodule with gitfile' '
 359        rm -rf mod &&
 360        git reset --hard &&
 361        git submodule update &&
 362        entry="$(git ls-files --stage sub | cut -f 1)" &&
 363        mkdir mod &&
 364        (
 365                cd mod &&
 366                git mv ../sub/ .
 367        ) &&
 368        ! test -e sub &&
 369        [ "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" ] &&
 370        (
 371                cd mod/sub &&
 372                git status
 373        ) &&
 374        echo mod/sub >expected &&
 375        git config -f .gitmodules submodule.sub.path >actual &&
 376        test_cmp expected actual &&
 377        git update-index --refresh &&
 378        git diff-files --quiet
 379'
 380
 381test_expect_success 'mv does not complain when no .gitmodules file is found' '
 382        rm -rf mod &&
 383        git reset --hard &&
 384        git submodule update &&
 385        git rm .gitmodules &&
 386        entry="$(git ls-files --stage sub | cut -f 1)" &&
 387        mkdir mod &&
 388        git mv sub mod/sub 2>actual.err &&
 389        ! test -s actual.err &&
 390        ! test -e sub &&
 391        [ "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" ] &&
 392        (
 393                cd mod/sub &&
 394                git status
 395        ) &&
 396        git update-index --refresh &&
 397        git diff-files --quiet
 398'
 399
 400test_expect_success 'mv will error out on a modified .gitmodules file unless staged' '
 401        rm -rf mod &&
 402        git reset --hard &&
 403        git submodule update &&
 404        git config -f .gitmodules foo.bar true &&
 405        entry="$(git ls-files --stage sub | cut -f 1)" &&
 406        mkdir mod &&
 407        test_must_fail git mv sub mod/sub 2>actual.err &&
 408        test -s actual.err &&
 409        test -e sub &&
 410        git diff-files --quiet -- sub &&
 411        git add .gitmodules &&
 412        git mv sub mod/sub 2>actual.err &&
 413        ! test -s actual.err &&
 414        ! test -e sub &&
 415        [ "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" ] &&
 416        (
 417                cd mod/sub &&
 418                git status
 419        ) &&
 420        git update-index --refresh &&
 421        git diff-files --quiet
 422'
 423
 424test_expect_success 'mv issues a warning when section is not found in .gitmodules' '
 425        rm -rf mod &&
 426        git reset --hard &&
 427        git submodule update &&
 428        git config -f .gitmodules --remove-section submodule.sub &&
 429        git add .gitmodules &&
 430        entry="$(git ls-files --stage sub | cut -f 1)" &&
 431        echo "warning: Could not find section in .gitmodules where path=sub" >expect.err &&
 432        mkdir mod &&
 433        git mv sub mod/sub 2>actual.err &&
 434        test_i18ncmp expect.err actual.err &&
 435        ! test -e sub &&
 436        [ "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" ] &&
 437        (
 438                cd mod/sub &&
 439                git status
 440        ) &&
 441        git update-index --refresh &&
 442        git diff-files --quiet
 443'
 444
 445test_expect_success 'mv --dry-run does not touch the submodule or .gitmodules' '
 446        rm -rf mod &&
 447        git reset --hard &&
 448        git submodule update &&
 449        mkdir mod &&
 450        git mv -n sub mod/sub 2>actual.err &&
 451        test -f sub/.git &&
 452        git diff-index --exit-code HEAD &&
 453        git update-index --refresh &&
 454        git diff-files --quiet -- sub .gitmodules
 455'
 456
 457test_expect_success 'checking out a commit before submodule moved needs manual updates' '
 458        git mv sub sub2 &&
 459        git commit -m "moved sub to sub2" &&
 460        git checkout -q HEAD^ 2>actual &&
 461        test_i18ngrep "^warning: unable to rmdir '\''sub2'\'':" actual &&
 462        git status -s sub2 >actual &&
 463        echo "?? sub2/" >expected &&
 464        test_cmp expected actual &&
 465        ! test -f sub/.git &&
 466        test -f sub2/.git &&
 467        git submodule update &&
 468        test -f sub/.git &&
 469        rm -rf sub2 &&
 470        git diff-index --exit-code HEAD &&
 471        git update-index --refresh &&
 472        git diff-files --quiet -- sub .gitmodules &&
 473        git status -s sub2 >actual &&
 474        ! test -s actual
 475'
 476
 477test_expect_success 'mv -k does not accidentally destroy submodules' '
 478        git checkout submodule &&
 479        mkdir dummy dest &&
 480        git mv -k dummy sub dest &&
 481        git status --porcelain >actual &&
 482        grep "^R  sub -> dest/sub" actual &&
 483        git reset --hard &&
 484        git checkout .
 485'
 486
 487test_expect_success 'moving a submodule in nested directories' '
 488        (
 489                cd deep &&
 490                git mv directory ../ &&
 491                # git status would fail if the update of linking git dir to
 492                # work dir of the submodule failed.
 493                git status &&
 494                git config -f ../.gitmodules submodule.deep/directory/hierarchy/sub.path >../actual &&
 495                echo "directory/hierarchy/sub" >../expect
 496        ) &&
 497        test_cmp expect actual
 498'
 499
 500test_expect_failure 'moving nested submodules' '
 501        git commit -am "cleanup commit" &&
 502        mkdir sub_nested_nested &&
 503        (cd sub_nested_nested &&
 504                touch nested_level2 &&
 505                git init &&
 506                git add . &&
 507                git commit -m "nested level 2"
 508        ) &&
 509        mkdir sub_nested &&
 510        (cd sub_nested &&
 511                touch nested_level1 &&
 512                git init &&
 513                git add . &&
 514                git commit -m "nested level 1"
 515                git submodule add ../sub_nested_nested &&
 516                git commit -m "add nested level 2"
 517        ) &&
 518        git submodule add ./sub_nested nested_move &&
 519        git commit -m "add nested_move" &&
 520        git submodule update --init --recursive &&
 521        git mv nested_move sub_nested_moved &&
 522        git status
 523'
 524
 525test_done