1#!/bin/sh 2# 3# Copyright (c) 2006 Carl D. Worth 4# 5 6test_description='Test of git add, including the -- option.' 7 8TEST_PASSES_SANITIZE_LEAK=true 9. ./test-lib.sh 10 11# Test the file mode "$1" of the file "$2" in the index. 12test_mode_in_index () { 13 case "$(git ls-files -s "$2")" in 14 "$1 "*" $2") 15 echo pass 16 ;; 17 *) 18 echo fail 19 git ls-files -s "$2" 20 return 1 21 ;; 22 esac 23} 24 25test_expect_success \ 26 'Test of git add' \ 27 'touch foo && git add foo' 28 29test_expect_success \ 30 'Post-check that foo is in the index' \ 31 'git ls-files foo | grep foo' 32 33test_expect_success \ 34 'Test that "git add -- -q" works' \ 35 'touch -- -q && git add -- -q' 36 37test_expect_success \ 38 'git add: Test that executable bit is not used if core.filemode=0' \ 39 'git config core.filemode 0 && 40 echo foo >xfoo1 && 41 chmod 755 xfoo1 && 42 git add xfoo1 && 43 test_mode_in_index 100644 xfoo1' 44 45test_expect_success 'git add: filemode=0 should not get confused by symlink' ' 46 rm -f xfoo1 && 47 test_ln_s_add foo xfoo1 && 48 test_mode_in_index 120000 xfoo1 49' 50 51test_expect_success \ 52 'git update-index --add: Test that executable bit is not used...' \ 53 'git config core.filemode 0 && 54 echo foo >xfoo2 && 55 chmod 755 xfoo2 && 56 git update-index --add xfoo2 && 57 test_mode_in_index 100644 xfoo2' 58 59test_expect_success 'git add: filemode=0 should not get confused by symlink' ' 60 rm -f xfoo2 && 61 test_ln_s_add foo xfoo2 && 62 test_mode_in_index 120000 xfoo2 63' 64 65test_expect_success \ 66 'git update-index --add: Test that executable bit is not used...' \ 67 'git config core.filemode 0 && 68 test_ln_s_add xfoo2 xfoo3 && # runs git update-index --add 69 test_mode_in_index 120000 xfoo3' 70 71test_expect_success '.gitignore test setup' ' 72 echo "*.ig" >.gitignore && 73 mkdir c.if d.ig && 74 >a.ig && >b.if && 75 >c.if/c.if && >c.if/c.ig && 76 >d.ig/d.if && >d.ig/d.ig 77' 78 79test_expect_success '.gitignore is honored' ' 80 git add . && 81 ! (git ls-files | grep "\\.ig") 82' 83 84test_expect_success 'error out when attempting to add ignored ones without -f' ' 85 test_must_fail git add a.?? && 86 ! (git ls-files | grep "\\.ig") 87' 88 89test_expect_success 'error out when attempting to add ignored ones without -f' ' 90 test_must_fail git add d.?? && 91 ! (git ls-files | grep "\\.ig") 92' 93 94test_expect_success 'error out when attempting to add ignored ones but add others' ' 95 touch a.if && 96 test_must_fail git add a.?? && 97 ! (git ls-files | grep "\\.ig") && 98 (git ls-files | grep a.if) 99' 100 101test_expect_success 'add ignored ones with -f' ' 102 git add -f a.?? && 103 git ls-files --error-unmatch a.ig 104' 105 106test_expect_success 'add ignored ones with -f' ' 107 git add -f d.??/* && 108 git ls-files --error-unmatch d.ig/d.if d.ig/d.ig 109' 110 111test_expect_success 'add ignored ones with -f' ' 112 rm -f .git/index && 113 git add -f d.?? && 114 git ls-files --error-unmatch d.ig/d.if d.ig/d.ig 115' 116 117test_expect_success '.gitignore with subdirectory' ' 118 119 rm -f .git/index && 120 mkdir -p sub/dir && 121 echo "!dir/a.*" >sub/.gitignore && 122 >sub/a.ig && 123 >sub/dir/a.ig && 124 git add sub/dir && 125 git ls-files --error-unmatch sub/dir/a.ig && 126 rm -f .git/index && 127 ( 128 cd sub/dir && 129 git add . 130 ) && 131 git ls-files --error-unmatch sub/dir/a.ig 132' 133 134mkdir 1 1/2 1/3 135touch 1/2/a 1/3/b 1/2/c 136test_expect_success 'check correct prefix detection' ' 137 rm -f .git/index && 138 git add 1/2/a 1/3/b 1/2/c 139' 140 141test_expect_success 'git add with filemode=0, symlinks=0, and unmerged entries' ' 142 for s in 1 2 3 143 do 144 echo $s > stage$s 145 echo "100755 $(git hash-object -w stage$s) $s file" 146 echo "120000 $(printf $s | git hash-object -w -t blob --stdin) $s symlink" 147 done | git update-index --index-info && 148 git config core.filemode 0 && 149 git config core.symlinks 0 && 150 echo new > file && 151 echo new > symlink && 152 git add file symlink && 153 git ls-files --stage | grep "^100755 .* 0 file$" && 154 git ls-files --stage | grep "^120000 .* 0 symlink$" 155' 156 157test_expect_success 'git add with filemode=0, symlinks=0 prefers stage 2 over stage 1' ' 158 git rm --cached -f file symlink && 159 ( 160 echo "100644 $(git hash-object -w stage1) 1 file" && 161 echo "100755 $(git hash-object -w stage2) 2 file" && 162 echo "100644 $(printf 1 | git hash-object -w -t blob --stdin) 1 symlink" && 163 echo "120000 $(printf 2 | git hash-object -w -t blob --stdin) 2 symlink" 164 ) | git update-index --index-info && 165 git config core.filemode 0 && 166 git config core.symlinks 0 && 167 echo new > file && 168 echo new > symlink && 169 git add file symlink && 170 git ls-files --stage | grep "^100755 .* 0 file$" && 171 git ls-files --stage | grep "^120000 .* 0 symlink$" 172' 173 174test_expect_success 'git add --refresh' ' 175 >foo && git add foo && git commit -a -m "commit all" && 176 test -z "$(git diff-index HEAD -- foo)" && 177 git read-tree HEAD && 178 case "$(git diff-index HEAD -- foo)" in 179 :100644" "*"M foo") echo pass;; 180 *) echo fail; (exit 1);; 181 esac && 182 git add --refresh -- foo && 183 test -z "$(git diff-index HEAD -- foo)" 184' 185 186test_expect_success 'git add --refresh with pathspec' ' 187 git reset --hard && 188 echo >foo && echo >bar && echo >baz && 189 git add foo bar baz && H=$(git rev-parse :foo) && git rm -f foo && 190 echo "100644 $H 3 foo" | git update-index --index-info && 191 test-tool chmtime -60 bar baz && 192 git add --refresh bar >actual && 193 test_must_be_empty actual && 194 195 git diff-files --name-only >actual && 196 ! grep bar actual && 197 grep baz actual 198' 199 200test_expect_success 'git add --refresh correctly reports no match error' " 201 echo \"fatal: pathspec ':(icase)nonexistent' did not match any files\" >expect && 202 test_must_fail git add --refresh ':(icase)nonexistent' 2>actual && 203 test_cmp expect actual 204" 205 206test_expect_success POSIXPERM,SANITY 'git add should fail atomically upon an unreadable file' ' 207 git reset --hard && 208 date >foo1 && 209 date >foo2 && 210 chmod 0 foo2 && 211 test_must_fail git add --verbose . && 212 ! ( git ls-files foo1 | grep foo1 ) 213' 214 215rm -f foo2 216 217test_expect_success POSIXPERM,SANITY 'git add --ignore-errors' ' 218 git reset --hard && 219 date >foo1 && 220 date >foo2 && 221 chmod 0 foo2 && 222 test_must_fail git add --verbose --ignore-errors . && 223 git ls-files foo1 | grep foo1 224' 225 226rm -f foo2 227 228test_expect_success POSIXPERM,SANITY 'git add (add.ignore-errors)' ' 229 git config add.ignore-errors 1 && 230 git reset --hard && 231 date >foo1 && 232 date >foo2 && 233 chmod 0 foo2 && 234 test_must_fail git add --verbose . && 235 git ls-files foo1 | grep foo1 236' 237rm -f foo2 238 239test_expect_success POSIXPERM,SANITY 'git add (add.ignore-errors = false)' ' 240 git config add.ignore-errors 0 && 241 git reset --hard && 242 date >foo1 && 243 date >foo2 && 244 chmod 0 foo2 && 245 test_must_fail git add --verbose . && 246 ! ( git ls-files foo1 | grep foo1 ) 247' 248rm -f foo2 249 250test_expect_success POSIXPERM,SANITY '--no-ignore-errors overrides config' ' 251 git config add.ignore-errors 1 && 252 git reset --hard && 253 date >foo1 && 254 date >foo2 && 255 chmod 0 foo2 && 256 test_must_fail git add --verbose --no-ignore-errors . && 257 ! ( git ls-files foo1 | grep foo1 ) && 258 git config add.ignore-errors 0 259' 260rm -f foo2 261 262test_expect_success BSLASHPSPEC "git add 'fo\\[ou\\]bar' ignores foobar" ' 263 git reset --hard && 264 touch fo\[ou\]bar foobar && 265 git add '\''fo\[ou\]bar'\'' && 266 git ls-files fo\[ou\]bar | fgrep fo\[ou\]bar && 267 ! ( git ls-files foobar | grep foobar ) 268' 269 270test_expect_success 'git add to resolve conflicts on otherwise ignored path' ' 271 git reset --hard && 272 H=$(git rev-parse :1/2/a) && 273 ( 274 echo "100644 $H 1 track-this" && 275 echo "100644 $H 3 track-this" 276 ) | git update-index --index-info && 277 echo track-this >>.gitignore && 278 echo resolved >track-this && 279 git add track-this 280' 281 282test_expect_success '"add non-existent" should fail' ' 283 test_must_fail git add non-existent && 284 ! (git ls-files | grep "non-existent") 285' 286 287test_expect_success 'git add -A on empty repo does not error out' ' 288 rm -fr empty && 289 git init empty && 290 ( 291 cd empty && 292 git add -A . && 293 git add -A 294 ) 295' 296 297test_expect_success '"git add ." in empty repo' ' 298 rm -fr empty && 299 git init empty && 300 ( 301 cd empty && 302 git add . 303 ) 304' 305 306test_expect_success 'error on a repository with no commits' ' 307 rm -fr empty && 308 git init empty && 309 test_must_fail git add empty >actual 2>&1 && 310 cat >expect <<-EOF && 311 error: '"'empty/'"' does not have a commit checked out 312 fatal: adding files failed 313 EOF 314 test_cmp expect actual 315' 316 317test_expect_success 'git add --dry-run of existing changed file' " 318 echo new >>track-this && 319 git add --dry-run track-this >actual 2>&1 && 320 echo \"add 'track-this'\" | test_cmp - actual 321" 322 323test_expect_success 'git add --dry-run of non-existing file' " 324 echo ignored-file >>.gitignore && 325 test_must_fail git add --dry-run track-this ignored-file >actual 2>&1 326" 327 328test_expect_success 'git add --dry-run of an existing file output' " 329 echo \"fatal: pathspec 'ignored-file' did not match any files\" >expect && 330 test_cmp expect actual 331" 332 333cat >expect.err <<\EOF 334The following paths are ignored by one of your .gitignore files: 335ignored-file 336hint: Use -f if you really want to add them. 337hint: Turn this message off by running 338hint: "git config advice.addIgnoredFile false" 339EOF 340cat >expect.out <<\EOF 341add 'track-this' 342EOF 343 344test_expect_success 'git add --dry-run --ignore-missing of non-existing file' ' 345 test_must_fail git add --dry-run --ignore-missing track-this ignored-file >actual.out 2>actual.err 346' 347 348test_expect_success 'git add --dry-run --ignore-missing of non-existing file output' ' 349 test_cmp expect.out actual.out && 350 test_cmp expect.err actual.err 351' 352 353test_expect_success 'git add --dry-run --interactive should fail' ' 354 test_must_fail git add --dry-run --interactive 355' 356 357test_expect_success 'git add empty string should fail' ' 358 test_must_fail git add "" 359' 360 361test_expect_success 'git add --chmod=[+-]x stages correctly' ' 362 rm -f foo1 && 363 echo foo >foo1 && 364 git add --chmod=+x foo1 && 365 test_mode_in_index 100755 foo1 && 366 git add --chmod=-x foo1 && 367 test_mode_in_index 100644 foo1 368' 369 370test_expect_success POSIXPERM,SYMLINKS 'git add --chmod=+x with symlinks' ' 371 git config core.filemode 1 && 372 git config core.symlinks 1 && 373 rm -f foo2 && 374 echo foo >foo2 && 375 git add --chmod=+x foo2 && 376 test_mode_in_index 100755 foo2 377' 378 379test_expect_success 'git add --chmod=[+-]x changes index with already added file' ' 380 rm -f foo3 xfoo3 && 381 git reset --hard && 382 echo foo >foo3 && 383 git add foo3 && 384 git add --chmod=+x foo3 && 385 test_mode_in_index 100755 foo3 && 386 echo foo >xfoo3 && 387 chmod 755 xfoo3 && 388 git add xfoo3 && 389 git add --chmod=-x xfoo3 && 390 test_mode_in_index 100644 xfoo3 391' 392 393test_expect_success POSIXPERM 'git add --chmod=[+-]x does not change the working tree' ' 394 echo foo >foo4 && 395 git add foo4 && 396 git add --chmod=+x foo4 && 397 ! test -x foo4 398' 399 400test_expect_success 'git add --chmod fails with non regular files (but updates the other paths)' ' 401 git reset --hard && 402 test_ln_s_add foo foo3 && 403 touch foo4 && 404 test_must_fail git add --chmod=+x foo3 foo4 2>stderr && 405 test_i18ngrep "cannot chmod +x .foo3." stderr && 406 test_mode_in_index 120000 foo3 && 407 test_mode_in_index 100755 foo4 408' 409 410test_expect_success 'git add --chmod honors --dry-run' ' 411 git reset --hard && 412 echo foo >foo4 && 413 git add foo4 && 414 git add --chmod=+x --dry-run foo4 && 415 test_mode_in_index 100644 foo4 416' 417 418test_expect_success 'git add --chmod --dry-run reports error for non regular files' ' 419 git reset --hard && 420 test_ln_s_add foo foo4 && 421 test_must_fail git add --chmod=+x --dry-run foo4 2>stderr && 422 test_i18ngrep "cannot chmod +x .foo4." stderr 423' 424 425test_expect_success 'git add --chmod --dry-run reports error for unmatched pathspec' ' 426 test_must_fail git add --chmod=+x --dry-run nonexistent 2>stderr && 427 test_i18ngrep "pathspec .nonexistent. did not match any files" stderr 428' 429 430test_expect_success 'no file status change if no pathspec is given' ' 431 >foo5 && 432 >foo6 && 433 git add foo5 foo6 && 434 git add --chmod=+x && 435 test_mode_in_index 100644 foo5 && 436 test_mode_in_index 100644 foo6 437' 438 439test_expect_success 'no file status change if no pathspec is given in subdir' ' 440 mkdir -p sub && 441 ( 442 cd sub && 443 >sub-foo1 && 444 >sub-foo2 && 445 git add . && 446 git add --chmod=+x && 447 test_mode_in_index 100644 sub-foo1 && 448 test_mode_in_index 100644 sub-foo2 449 ) 450' 451 452test_expect_success 'all statuses changed in folder if . is given' ' 453 git init repo && 454 ( 455 cd repo && 456 mkdir -p sub/dir && 457 touch x y z sub/a sub/dir/b && 458 git add -A && 459 git add --chmod=+x . && 460 test $(git ls-files --stage | grep ^100644 | wc -l) -eq 0 && 461 git add --chmod=-x . && 462 test $(git ls-files --stage | grep ^100755 | wc -l) -eq 0 463 ) 464' 465 466test_expect_success CASE_INSENSITIVE_FS 'path is case-insensitive' ' 467 path="$(pwd)/BLUB" && 468 touch "$path" && 469 downcased="$(echo "$path" | tr A-Z a-z)" && 470 git add "$downcased" 471' 472 473test_done 474