Raw
1 #!/bin/sh
2 #
3 # Copyright (c) 2006 Carl D. Worth
4 #
5
6 test_description='Test of git add, including the -- option.'
7
8 . ./test-lib.sh
9
10 . "$TEST_DIRECTORY"/lib-unique-files.sh
11
12 # Test the file mode "$1" of the file "$2" in the index.
13 test_mode_in_index () {
14 case "$(git ls-files -s "$2")" in
15 "$1 "*" $2")
16 echo pass
17 ;;
18 *)
19 echo fail
20 git ls-files -s "$2"
21 return 1
22 ;;
23 esac
24 }
25
26 test_expect_success 'Test of git add' '
27 touch foo && git add foo
28 '
29
30 test_expect_success 'Test with no pathspecs' '
31 cat >expect <<-EOF &&
32 Nothing specified, nothing added.
33 hint: Maybe you wanted to say ${SQ}git add .${SQ}?
34 hint: Disable this message with "git config set advice.addEmptyPathspec false"
35 EOF
36 git add 2>actual &&
37 test_cmp expect actual
38 '
39
40 test_expect_success 'Post-check that foo is in the index' '
41 git ls-files foo >actual &&
42 test_grep foo actual
43 '
44
45 test_expect_success 'Test that "git add -- -q" works' '
46 touch -- -q && git add -- -q
47 '
48
49 BATCH_CONFIGURATION='-c core.fsync=loose-object -c core.fsyncmethod=batch'
50
51 test_expect_success 'git add: core.fsyncmethod=batch' "
52 test_create_unique_files 2 4 files_base_dir1 &&
53 GIT_TEST_FSYNC=1 git $BATCH_CONFIGURATION add -- ./files_base_dir1/ &&
54 git ls-files --stage files_base_dir1/ |
55 test_parse_ls_files_stage_oids >added_files_oids &&
56
57 # We created 2 subdirs with 4 files each (8 files total) above
58 test_line_count = 8 added_files_oids &&
59 git cat-file --batch-check='%(objectname)' <added_files_oids >added_files_actual &&
60 test_cmp added_files_oids added_files_actual
61 "
62
63 test_expect_success 'git update-index: core.fsyncmethod=batch' "
64 test_create_unique_files 2 4 files_base_dir2 &&
65 find files_base_dir2 ! -type d -print | xargs git $BATCH_CONFIGURATION update-index --add -- &&
66 git ls-files --stage files_base_dir2 |
67 test_parse_ls_files_stage_oids >added_files2_oids &&
68
69 # We created 2 subdirs with 4 files each (8 files total) above
70 test_line_count = 8 added_files2_oids &&
71 git cat-file --batch-check='%(objectname)' <added_files2_oids >added_files2_actual &&
72 test_cmp added_files2_oids added_files2_actual
73 "
74
75 test_expect_success \
76 'git add: Test that executable bit is not used if core.filemode=0' \
77 'git config core.filemode 0 &&
78 echo foo >xfoo1 &&
79 chmod 755 xfoo1 &&
80 git add xfoo1 &&
81 test_mode_in_index 100644 xfoo1'
82
83 test_expect_success 'git add: filemode=0 should not get confused by symlink' '
84 rm -f xfoo1 &&
85 test_ln_s_add foo xfoo1 &&
86 test_mode_in_index 120000 xfoo1
87 '
88
89 test_expect_success \
90 'git update-index --add: Test that executable bit is not used...' \
91 'git config core.filemode 0 &&
92 echo foo >xfoo2 &&
93 chmod 755 xfoo2 &&
94 git update-index --add xfoo2 &&
95 test_mode_in_index 100644 xfoo2'
96
97 test_expect_success 'git add: filemode=0 should not get confused by symlink' '
98 rm -f xfoo2 &&
99 test_ln_s_add foo xfoo2 &&
100 test_mode_in_index 120000 xfoo2
101 '
102
103 test_expect_success \
104 'git update-index --add: Test that executable bit is not used...' \
105 'git config core.filemode 0 &&
106 test_ln_s_add xfoo2 xfoo3 && # runs git update-index --add
107 test_mode_in_index 120000 xfoo3'
108
109 test_expect_success '.gitignore test setup' '
110 echo "*.ig" >.gitignore &&
111 mkdir c.if d.ig &&
112 >a.ig && >b.if &&
113 >c.if/c.if && >c.if/c.ig &&
114 >d.ig/d.if && >d.ig/d.ig
115 '
116
117 test_expect_success '.gitignore is honored' '
118 git add . &&
119 git ls-files >files &&
120 sed -n "/\\.ig/p" <files >actual &&
121 test_must_be_empty actual
122 '
123
124 test_expect_success 'error out when attempting to add ignored ones without -f' '
125 test_must_fail git add a.?? &&
126 git ls-files >files &&
127 sed -n "/\\.ig/p" <files >actual &&
128 test_must_be_empty actual
129 '
130
131 test_expect_success 'error out when attempting to add ignored ones without -f' '
132 test_must_fail git add d.?? &&
133 git ls-files >files &&
134 sed -n "/\\.ig/p" <files >actual &&
135 test_must_be_empty actual
136 '
137
138 test_expect_success 'error out when attempting to add ignored ones but add others' '
139 touch a.if &&
140 test_must_fail git add a.?? &&
141 git ls-files >files &&
142 sed -n "/\\.ig/p" <files >actual &&
143 test_must_be_empty actual &&
144 test_grep a.if files
145 '
146
147 test_expect_success 'add ignored ones with -f' '
148 git add -f a.?? &&
149 git ls-files --error-unmatch a.ig
150 '
151
152 test_expect_success 'add ignored ones with -f' '
153 git add -f d.??/* &&
154 git ls-files --error-unmatch d.ig/d.if d.ig/d.ig
155 '
156
157 test_expect_success 'add ignored ones with -f' '
158 rm -f .git/index &&
159 git add -f d.?? &&
160 git ls-files --error-unmatch d.ig/d.if d.ig/d.ig
161 '
162
163 test_expect_success '.gitignore with subdirectory' '
164
165 rm -f .git/index &&
166 mkdir -p sub/dir &&
167 echo "!dir/a.*" >sub/.gitignore &&
168 >sub/a.ig &&
169 >sub/dir/a.ig &&
170 git add sub/dir &&
171 git ls-files --error-unmatch sub/dir/a.ig &&
172 rm -f .git/index &&
173 (
174 cd sub/dir &&
175 git add .
176 ) &&
177 git ls-files --error-unmatch sub/dir/a.ig
178 '
179
180 mkdir 1 1/2 1/3
181 touch 1/2/a 1/3/b 1/2/c
182 test_expect_success 'check correct prefix detection' '
183 rm -f .git/index &&
184 git add 1/2/a 1/3/b 1/2/c
185 '
186
187 test_expect_success 'git add with filemode=0, symlinks=0, and unmerged entries' '
188 for s in 1 2 3
189 do
190 echo $s > stage$s &&
191 echo "100755 $(git hash-object -w stage$s) $s file" &&
192 echo "120000 $(printf $s | git hash-object -w -t blob --stdin) $s symlink" || return 1
193 done | git update-index --index-info &&
194 git config core.filemode 0 &&
195 git config core.symlinks 0 &&
196 echo new > file &&
197 echo new > symlink &&
198 git add file symlink &&
199 git ls-files --stage >actual &&
200 test_grep "^100755 .* 0 file$" actual &&
201 test_grep "^120000 .* 0 symlink$" actual
202 '
203
204 test_expect_success 'git add with filemode=0, symlinks=0 prefers stage 2 over stage 1' '
205 git rm --cached -f file symlink &&
206 (
207 echo "100644 $(git hash-object -w stage1) 1 file" &&
208 echo "100755 $(git hash-object -w stage2) 2 file" &&
209 echo "100644 $(printf 1 | git hash-object -w -t blob --stdin) 1 symlink" &&
210 echo "120000 $(printf 2 | git hash-object -w -t blob --stdin) 2 symlink"
211 ) | git update-index --index-info &&
212 git config core.filemode 0 &&
213 git config core.symlinks 0 &&
214 echo new > file &&
215 echo new > symlink &&
216 git add file symlink &&
217 git ls-files --stage >actual &&
218 test_grep "^100755 .* 0 file$" actual &&
219 test_grep "^120000 .* 0 symlink$" actual
220 '
221
222 test_expect_success 'git add --refresh' '
223 >foo && git add foo && git commit -a -m "commit all" &&
224 test -z "$(git diff-index HEAD -- foo)" &&
225 git read-tree HEAD &&
226 case "$(git diff-index HEAD -- foo)" in
227 :100644" "*"M foo") echo pass;;
228 *) echo fail; false;;
229 esac &&
230 git add --refresh -- foo &&
231 test -z "$(git diff-index HEAD -- foo)"
232 '
233
234 test_expect_success 'git add --refresh with pathspec' '
235 git reset --hard &&
236 echo >foo && echo >bar && echo >baz &&
237 git add foo bar baz && H=$(git rev-parse :foo) && git rm -f foo &&
238 echo "100644 $H 3 foo" | git update-index --index-info &&
239 test-tool chmtime -60 bar baz &&
240 git add --refresh bar >actual &&
241 test_must_be_empty actual &&
242
243 git diff-files --name-only >actual &&
244 test_grep ! bar actual &&
245 test_grep baz actual
246 '
247
248 test_expect_success 'git add --refresh correctly reports no match error' "
249 echo \"fatal: pathspec ':(icase)nonexistent' did not match any files\" >expect &&
250 test_must_fail git add --refresh ':(icase)nonexistent' 2>actual &&
251 test_cmp expect actual
252 "
253
254 test_expect_success POSIXPERM,SANITY 'git add should fail atomically upon an unreadable file' '
255 git reset --hard &&
256 date >foo1 &&
257 date >foo2 &&
258 chmod 0 foo2 &&
259 test_must_fail git add --verbose . &&
260 git ls-files foo1 >actual &&
261 test_grep ! foo1 actual
262 '
263
264 rm -f foo2
265
266 test_expect_success POSIXPERM,SANITY 'git add --ignore-errors' '
267 git reset --hard &&
268 date >foo1 &&
269 date >foo2 &&
270 chmod 0 foo2 &&
271 test_must_fail git add --verbose --ignore-errors . &&
272 git ls-files foo1 >actual &&
273 test_grep foo1 actual
274 '
275
276 rm -f foo2
277
278 test_expect_success POSIXPERM,SANITY 'git add (add.ignore-errors)' '
279 git config add.ignore-errors 1 &&
280 git reset --hard &&
281 date >foo1 &&
282 date >foo2 &&
283 chmod 0 foo2 &&
284 test_must_fail git add --verbose . &&
285 git ls-files foo1 >actual &&
286 test_grep foo1 actual
287 '
288 rm -f foo2
289
290 test_expect_success POSIXPERM,SANITY 'git add (add.ignore-errors = false)' '
291 git config add.ignore-errors 0 &&
292 git reset --hard &&
293 date >foo1 &&
294 date >foo2 &&
295 chmod 0 foo2 &&
296 test_must_fail git add --verbose . &&
297 git ls-files foo1 >actual &&
298 test_grep ! foo1 actual
299 '
300 rm -f foo2
301
302 test_expect_success POSIXPERM,SANITY '--no-ignore-errors overrides config' '
303 git config add.ignore-errors 1 &&
304 git reset --hard &&
305 date >foo1 &&
306 date >foo2 &&
307 chmod 0 foo2 &&
308 test_must_fail git add --verbose --no-ignore-errors . &&
309 git ls-files foo1 >actual &&
310 test_grep ! foo1 actual &&
311 git config add.ignore-errors 0
312 '
313 rm -f foo2
314
315 test_expect_success BSLASHPSPEC "git add 'fo\\[ou\\]bar' ignores foobar" '
316 git reset --hard &&
317 touch fo\[ou\]bar foobar &&
318 git add '\''fo\[ou\]bar'\'' &&
319 git ls-files fo\[ou\]bar >actual &&
320 test_grep -F fo\[ou\]bar actual &&
321 git ls-files foobar >actual &&
322 test_grep ! foobar actual
323 '
324
325 test_expect_success 'git add to resolve conflicts on otherwise ignored path' '
326 git reset --hard &&
327 H=$(git rev-parse :1/2/a) &&
328 (
329 echo "100644 $H 1 track-this" &&
330 echo "100644 $H 3 track-this"
331 ) | git update-index --index-info &&
332 echo track-this >>.gitignore &&
333 echo resolved >track-this &&
334 git add track-this
335 '
336
337 test_expect_success '"add non-existent" should fail' '
338 test_must_fail git add non-existent &&
339 git ls-files >actual &&
340 test_grep ! "non-existent" actual
341 '
342
343 test_expect_success 'git add -A on empty repo does not error out' '
344 rm -fr empty &&
345 git init empty &&
346 (
347 cd empty &&
348 git add -A . &&
349 git add -A
350 )
351 '
352
353 test_expect_success '"git add ." in empty repo' '
354 rm -fr empty &&
355 git init empty &&
356 (
357 cd empty &&
358 git add .
359 )
360 '
361
362 test_expect_success '"git add" a embedded repository' '
363 rm -fr outer && git init outer &&
364 (
365 cd outer &&
366 for i in 1 2
367 do
368 name=inner$i &&
369 git init $name &&
370 git -C $name commit --allow-empty -m $name ||
371 return 1
372 done &&
373 git add . 2>actual &&
374 cat >expect <<-EOF &&
375 warning: adding embedded git repository: inner1
376 hint: You${SQ}ve added another git repository inside your current repository.
377 hint: Clones of the outer repository will not contain the contents of
378 hint: the embedded repository and will not know how to obtain it.
379 hint: If you meant to add a submodule, use:
380 hint:
381 hint: git submodule add <url> inner1
382 hint:
383 hint: If you added this path by mistake, you can remove it from the
384 hint: index with:
385 hint:
386 hint: git rm --cached inner1
387 hint:
388 hint: See "git help submodule" for more information.
389 hint: Disable this message with "git config set advice.addEmbeddedRepo false"
390 warning: adding embedded git repository: inner2
391 EOF
392 test_cmp expect actual
393 )
394 '
395
396 test_expect_success 'error on a repository with no commits' '
397 rm -fr empty &&
398 git init empty &&
399 test_must_fail git add empty >actual 2>&1 &&
400 cat >expect <<-EOF &&
401 error: '"'empty/'"' does not have a commit checked out
402 error: unable to index file '"'empty/'"'
403 fatal: adding files failed
404 EOF
405 test_cmp expect actual
406 '
407
408 test_expect_success 'git add --dry-run of existing changed file' "
409 echo new >>track-this &&
410 git add --dry-run track-this >actual 2>&1 &&
411 echo \"add 'track-this'\" | test_cmp - actual
412 "
413
414 test_expect_success 'git add --dry-run of non-existing file' "
415 echo ignored-file >>.gitignore &&
416 test_must_fail git add --dry-run track-this ignored-file >actual 2>&1
417 "
418
419 test_expect_success 'git add --dry-run of an existing file output' "
420 echo \"fatal: pathspec 'ignored-file' did not match any files\" >expect &&
421 test_cmp expect actual
422 "
423
424 cat >expect.err <<\EOF
425 The following paths are ignored by one of your .gitignore files:
426 ignored-file
427 hint: Use -f if you really want to add them.
428 hint: Disable this message with "git config set advice.addIgnoredFile false"
429 EOF
430 cat >expect.out <<\EOF
431 add 'track-this'
432 EOF
433
434 test_expect_success 'git add --dry-run --ignore-missing of non-existing file' '
435 test_must_fail git add --dry-run --ignore-missing track-this ignored-file >actual.out 2>actual.err
436 '
437
438 test_expect_success 'git add --dry-run --ignore-missing of non-existing file output' '
439 test_cmp expect.out actual.out &&
440 test_cmp expect.err actual.err
441 '
442
443 test_expect_success 'git add --dry-run --interactive should fail' '
444 test_must_fail git add --dry-run --interactive
445 '
446
447 test_expect_success 'git add empty string should fail' '
448 test_must_fail git add ""
449 '
450
451 test_expect_success 'git add --chmod=[+-]x stages correctly' '
452 rm -f foo1 &&
453 echo foo >foo1 &&
454 git add --chmod=+x foo1 &&
455 test_mode_in_index 100755 foo1 &&
456 git add --chmod=-x foo1 &&
457 test_mode_in_index 100644 foo1
458 '
459
460 test_expect_success POSIXPERM,SYMLINKS 'git add --chmod=+x with symlinks' '
461 git config core.filemode 1 &&
462 git config core.symlinks 1 &&
463 rm -f foo2 &&
464 echo foo >foo2 &&
465 git add --chmod=+x foo2 &&
466 test_mode_in_index 100755 foo2
467 '
468
469 test_expect_success 'git add --chmod=[+-]x changes index with already added file' '
470 rm -f foo3 xfoo3 &&
471 git reset --hard &&
472 echo foo >foo3 &&
473 git add foo3 &&
474 git add --chmod=+x foo3 &&
475 test_mode_in_index 100755 foo3 &&
476 echo foo >xfoo3 &&
477 chmod 755 xfoo3 &&
478 git add xfoo3 &&
479 git add --chmod=-x xfoo3 &&
480 test_mode_in_index 100644 xfoo3
481 '
482
483 test_expect_success POSIXPERM 'git add --chmod=[+-]x does not change the working tree' '
484 echo foo >foo4 &&
485 git add foo4 &&
486 git add --chmod=+x foo4 &&
487 ! test -x foo4
488 '
489
490 test_expect_success 'git add --chmod fails with non regular files (but updates the other paths)' '
491 git reset --hard &&
492 test_ln_s_add foo foo3 &&
493 touch foo4 &&
494 test_must_fail git add --chmod=+x foo3 foo4 2>stderr &&
495 test_grep "cannot chmod +x .foo3." stderr &&
496 test_mode_in_index 120000 foo3 &&
497 test_mode_in_index 100755 foo4
498 '
499
500 test_expect_success 'git add --chmod honors --dry-run' '
501 git reset --hard &&
502 echo foo >foo4 &&
503 git add foo4 &&
504 git add --chmod=+x --dry-run foo4 &&
505 test_mode_in_index 100644 foo4
506 '
507
508 test_expect_success 'git add --chmod --dry-run reports error for non regular files' '
509 git reset --hard &&
510 test_ln_s_add foo foo4 &&
511 test_must_fail git add --chmod=+x --dry-run foo4 2>stderr &&
512 test_grep "cannot chmod +x .foo4." stderr
513 '
514
515 test_expect_success 'git add --chmod --dry-run reports error for unmatched pathspec' '
516 test_must_fail git add --chmod=+x --dry-run nonexistent 2>stderr &&
517 test_grep "pathspec .nonexistent. did not match any files" stderr
518 '
519
520 test_expect_success 'no file status change if no pathspec is given' '
521 >foo5 &&
522 >foo6 &&
523 git add foo5 foo6 &&
524 git add --chmod=+x &&
525 test_mode_in_index 100644 foo5 &&
526 test_mode_in_index 100644 foo6
527 '
528
529 test_expect_success 'no file status change if no pathspec is given in subdir' '
530 mkdir -p sub &&
531 (
532 cd sub &&
533 >sub-foo1 &&
534 >sub-foo2 &&
535 git add . &&
536 git add --chmod=+x &&
537 test_mode_in_index 100644 sub-foo1 &&
538 test_mode_in_index 100644 sub-foo2
539 )
540 '
541
542 test_expect_success 'all statuses changed in folder if . is given' '
543 git init repo &&
544 (
545 cd repo &&
546 mkdir -p sub/dir &&
547 touch x y z sub/a sub/dir/b &&
548 git add -A &&
549 git add --chmod=+x . &&
550 git ls-files --stage >actual &&
551 test_grep ! ^100644 actual &&
552 git add --chmod=-x . &&
553 git ls-files --stage >actual &&
554 test_grep ! ^100755 actual
555 )
556 '
557
558 test_expect_success 'cannot add a submodule of a different algorithm' '
559 git init --object-format=sha256 sha256 &&
560 (
561 cd sha256 &&
562 test_commit abc &&
563 git init --object-format=sha1 submodule &&
564 test_commit -C submodule def &&
565 test_must_fail git add submodule 2>err &&
566 test_grep "cannot add a submodule of a different hash algorithm" err &&
567 git ls-files --stage >entries &&
568 test_grep ! ^160000 entries
569 ) &&
570 git init --object-format=sha1 sha1 &&
571 (
572 cd sha1 &&
573 test_commit abc &&
574 git init --object-format=sha256 submodule &&
575 test_commit -C submodule def &&
576 test_must_fail git add submodule 2>err &&
577 test_grep "cannot add a submodule of a different hash algorithm" err &&
578 git ls-files --stage >entries &&
579 test_grep ! ^160000 entries
580 )
581 '
582
583 test_expect_success CASE_INSENSITIVE_FS 'path is case-insensitive' '
584 path="$(pwd)/BLUB" &&
585 touch "$path" &&
586 downcased="$(echo "$path" | tr A-Z a-z)" &&
587 git add "$downcased"
588 '
589
590 test_done