630
test_all_match git ls-files -s -- folder1
631
'
632
633
+test_expect_success 'update-index modify outside sparse definition' '
634
+ init_repos &&
635
+
636
+ write_script edit-contents <<-\EOF &&
637
+ echo text >>$1
638
+ EOF
639
+
640
+ # Create & modify folder1/a
641
+ # Note that this setup is a manual way of reaching the erroneous
642
+ # condition in which a `skip-worktree` enabled, outside-of-cone file
643
+ # exists on disk. It is used here to ensure `update-index` is stable
644
+ # and behaves predictably if such a condition occurs.
645
+ run_on_sparse mkdir -p folder1 &&
646
+ run_on_sparse cp ../initial-repo/folder1/a folder1/a &&
647
+ run_on_all ../edit-contents folder1/a &&
648
+
649
+ # If file has skip-worktree enabled, update-index does not modify the
650
+ # index entry
651
+ test_sparse_match git update-index folder1/a &&
652
+ test_sparse_match git status --porcelain=v2 &&
653
+ test_must_be_empty sparse-checkout-out &&
654
+
655
+ # When skip-worktree is disabled (even on files outside sparse cone), file
656
+ # is updated in the index
657
+ test_sparse_match git update-index --no-skip-worktree folder1/a &&
658
+ test_all_match git status --porcelain=v2 &&
659
+ test_all_match git update-index folder1/a &&
660
+ test_all_match git status --porcelain=v2
661
+'
662
+
663
+test_expect_success 'update-index --add outside sparse definition' '
664
+ init_repos &&
665
+
666
+ write_script edit-contents <<-\EOF &&
667
+ echo text >>$1
668
+ EOF
669
+
670
+ # Create folder1, add new file
671
+ run_on_sparse mkdir -p folder1 &&
672
+ run_on_all ../edit-contents folder1/b &&
673
+
674
+ # The *untracked* out-of-cone file is added to the index because it does
675
+ # not have a `skip-worktree` bit to signal that it should be ignored
676
+ # (unlike in `git add`, which will fail due to the file being outside
677
+ # the sparse checkout definition).
678
+ test_all_match git update-index --add folder1/b &&
679
+ test_all_match git status --porcelain=v2
680
+'
681
+
682
+# NEEDSWORK: `--remove`, unlike the rest of `update-index`, does not ignore
683
+# `skip-worktree` entries by default and will remove them from the index.
684
+# The `--ignore-skip-worktree-entries` flag must be used in conjunction with
685
+# `--remove` to ignore the `skip-worktree` entries and prevent their removal
686
+# from the index.
687
+test_expect_success 'update-index --remove outside sparse definition' '
688
+ init_repos &&
689
+
690
+ # When --ignore-skip-worktree-entries is _not_ specified:
691
+ # out-of-cone, not-on-disk files are removed from the index
692
+ test_sparse_match git update-index --remove folder1/a &&
693
+ cat >expect <<-EOF &&
694
+ D folder1/a
695
+ EOF
696
+ test_sparse_match git diff --cached --name-status &&
697
+ test_cmp expect sparse-checkout-out &&
698
+
699
+ # Reset the state
700
+ test_all_match git reset --hard &&
701
+
702
+ # When --ignore-skip-worktree-entries is specified, out-of-cone
703
+ # (skip-worktree) files are ignored
704
+ test_sparse_match git update-index --remove --ignore-skip-worktree-entries folder1/a &&
705
+ test_sparse_match git diff --cached --name-status &&
706
+ test_must_be_empty sparse-checkout-out &&
707
+
708
+ # Reset the state
709
+ test_all_match git reset --hard &&
710
+
711
+ # --force-remove supercedes --ignore-skip-worktree-entries, removing
712
+ # a skip-worktree file from the index (and disk) when both are specified
713
+ # with --remove
714
+ test_sparse_match git update-index --force-remove --ignore-skip-worktree-entries folder1/a &&
715
+ cat >expect <<-EOF &&
716
+ D folder1/a
717
+ EOF
718
+ test_sparse_match git diff --cached --name-status &&
719
+ test_cmp expect sparse-checkout-out
720
+'
721
+
722
+test_expect_success 'update-index with directories' '
723
+ init_repos &&
724
+
725
+ # update-index will exit silently when provided with a directory name
726
+ # containing a trailing slash
727
+ test_all_match git update-index deep/ folder1/ &&
728
+ grep "Ignoring path deep/" sparse-checkout-err &&
729
+ grep "Ignoring path folder1/" sparse-checkout-err &&
730
+
731
+ # When update-index is given a directory name WITHOUT a trailing slash, it will
732
+ # behave in different ways depending on the status of the directory on disk:
733
+ # * if it exists, the command exits with an error ("add individual files instead")
734
+ # * if it does NOT exist (e.g., in a sparse-checkout), it is assumed to be a
735
+ # file and either triggers an error ("does not exist and --remove not passed")
736
+ # or is ignored completely (when using --remove)
737
+ test_all_match test_must_fail git update-index deep &&
738
+ run_on_all test_must_fail git update-index folder1 &&
739
+ test_must_fail git -C full-checkout update-index --remove folder1 &&
740
+ test_sparse_match git update-index --remove folder1 &&
741
+ test_all_match git status --porcelain=v2
742
+'
743
+
744
+test_expect_success 'update-index --again file outside sparse definition' '
745
+ init_repos &&
746
+
747
+ test_all_match git checkout -b test-reupdate &&
748
+
749
+ # Update HEAD without modifying the index to introduce a difference in
750
+ # folder1/a
751
+ test_sparse_match git reset --soft update-folder1 &&
752
+
753
+ # Because folder1/a differs in the index vs HEAD,
754
+ # `git update-index --no-skip-worktree --again` will effectively perform
755
+ # `git update-index --no-skip-worktree folder1/a` and remove the skip-worktree
756
+ # flag from folder1/a
757
+ test_sparse_match git update-index --no-skip-worktree --again &&
758
+ test_sparse_match git status --porcelain=v2 &&
759
+
760
+ cat >expect <<-EOF &&
761
+ D folder1/a
762
+ EOF
763
+ test_sparse_match git diff --name-status &&
764
+ test_cmp expect sparse-checkout-out
765
+'
766
+
767
+test_expect_success 'update-index --cacheinfo' '
768
+ init_repos &&
769
+
770
+ deep_a_oid=$(git -C full-checkout rev-parse update-deep:deep/a) &&
771
+ folder2_oid=$(git -C full-checkout rev-parse update-folder2:folder2) &&
772
+ folder1_a_oid=$(git -C full-checkout rev-parse update-folder1:folder1/a) &&
773
+
774
+ test_all_match git update-index --cacheinfo 100644 $deep_a_oid deep/a &&
775
+ test_all_match git status --porcelain=v2 &&
776
+
777
+ # Cannot add sparse directory, even in sparse index case
778
+ test_all_match test_must_fail git update-index --add --cacheinfo 040000 $folder2_oid folder2/ &&
779
+
780
+ # Sparse match only: the new outside-of-cone entry is added *without* skip-worktree,
781
+ # so `git status` reports it as "deleted" in the worktree
782
+ test_sparse_match git update-index --add --cacheinfo 100644 $folder1_a_oid folder1/a &&
783
+ test_sparse_match git status --porcelain=v2 &&
784
+ cat >expect <<-EOF &&
785
+ MD folder1/a
786
+ EOF
787
+ test_sparse_match git status --short -- folder1/a &&
788
+ test_cmp expect sparse-checkout-out &&
789
+
790
+ # To return folder1/a to "normal" for a sparse checkout (ignored &
791
+ # outside-of-cone), add the skip-worktree flag.
792
+ test_sparse_match git update-index --skip-worktree folder1/a &&
793
+ cat >expect <<-EOF &&
794
+ S folder1/a
795
+ EOF
796
+ test_sparse_match git ls-files -t -- folder1/a &&
797
+ test_cmp expect sparse-checkout-out
798
+'
799
+
800
test_expect_success 'merge, cherry-pick, and rebase' '
801
init_repos &&
802