705
)
706
'
707
708
+test_dwim_orphan () {
709
+ local info_text="No possible source branch, inferring '--orphan'" &&
710
+ local fetch_error_text="fatal: No local or remote refs exist despite at least one remote" &&
711
+ local orphan_hint="hint: If you meant to create a worktree containing a new orphan branch" &&
712
+ local invalid_ref_regex="^fatal: invalid reference:\s\+.*" &&
713
+ local bad_combo_regex="^fatal: '[a-z-]\+' and '[a-z-]\+' cannot be used together" &&
714
+
715
+ local git_ns="repo" &&
716
+ local dashc_args="-C $git_ns" &&
717
+ local use_cd=0 &&
718
+
719
+ local bad_head=0 &&
720
+ local empty_repo=1 &&
721
+ local local_ref=0 &&
722
+ local use_quiet=0 &&
723
+ local remote=0 &&
724
+ local remote_ref=0 &&
725
+ local use_new_branch=0 &&
726
+
727
+ local outcome="$1" &&
728
+ local outcome_text &&
729
+ local success &&
730
+ shift &&
731
+ local args="" &&
732
+ local context="" &&
733
+ case "$outcome" in
734
+ "infer")
735
+ success=1 &&
736
+ outcome_text='"add" DWIM infer --orphan'
737
+ ;;
738
+ "no_infer")
739
+ success=1 &&
740
+ outcome_text='"add" DWIM doesnt infer --orphan'
741
+ ;;
742
+ "fetch_error")
743
+ success=0 &&
744
+ outcome_text='"add" error need fetch'
745
+ ;;
746
+ "fatal_orphan_bad_combo")
747
+ success=0 &&
748
+ outcome_text='"add" error inferred "--orphan" gives illegal opts combo'
749
+ ;;
750
+ *)
751
+ echo "test_dwim_orphan(): invalid outcome: '$outcome'" >&2 &&
752
+ return 1
753
+ ;;
754
+ esac &&
755
+ while [ $# -gt 0 ]
756
+ do
757
+ case "$1" in
758
+ # How and from where to create the worktree
759
+ "-C_repo")
760
+ use_cd=0 &&
761
+ git_ns="repo" &&
762
+ dashc_args="-C $git_ns" &&
763
+ context="$context, 'git -C repo'"
764
+ ;;
765
+ "-C_wt")
766
+ use_cd=0 &&
767
+ git_ns="wt" &&
768
+ dashc_args="-C $git_ns" &&
769
+ context="$context, 'git -C wt'"
770
+ ;;
771
+ "cd_repo")
772
+ use_cd=1 &&
773
+ git_ns="repo" &&
774
+ dashc_args="" &&
775
+ context="$context, 'cd repo && git'"
776
+ ;;
777
+ "cd_wt")
778
+ use_cd=1 &&
779
+ git_ns="wt" &&
780
+ dashc_args="" &&
781
+ context="$context, 'cd wt && git'"
782
+ ;;
783
+
784
+ # Bypass the "pull first" warning
785
+ "force")
786
+ args="$args --force" &&
787
+ context="$context, --force"
788
+ ;;
789
+
790
+ # Try to use remote refs when DWIM
791
+ "guess_remote")
792
+ args="$args --guess-remote" &&
793
+ context="$context, --guess-remote"
794
+ ;;
795
+ "no_guess_remote")
796
+ args="$args --no-guess-remote" &&
797
+ context="$context, --no-guess-remote"
798
+ ;;
799
+
800
+ # Whether there is at least one local branch present
801
+ "local_ref")
802
+ empty_repo=0 &&
803
+ local_ref=1 &&
804
+ context="$context, >=1 local branches"
805
+ ;;
806
+ "no_local_ref")
807
+ empty_repo=0 &&
808
+ context="$context, 0 local branches"
809
+ ;;
810
+
811
+ # Whether the HEAD points at a valid ref (skip this opt when no refs)
812
+ "good_head")
813
+ # requires: local_ref
814
+ context="$context, valid HEAD"
815
+ ;;
816
+ "bad_head")
817
+ bad_head=1 &&
818
+ context="$context, invalid (or orphan) HEAD"
819
+ ;;
820
+
821
+ # Whether the code path is tested with the base add command or -b
822
+ "no_-b")
823
+ use_new_branch=0 &&
824
+ context="$context, no --branch"
825
+ ;;
826
+ "-b")
827
+ use_new_branch=1 &&
828
+ context="$context, --branch"
829
+ ;;
830
+
831
+ # Whether to check that all output is suppressed (except errors)
832
+ # or that the output is as expected
833
+ "quiet")
834
+ use_quiet=1 &&
835
+ args="$args --quiet" &&
836
+ context="$context, --quiet"
837
+ ;;
838
+ "no_quiet")
839
+ use_quiet=0 &&
840
+ context="$context, no --quiet (expect output)"
841
+ ;;
842
+
843
+ # Whether there is at least one remote attached to the repo
844
+ "remote")
845
+ empty_repo=0 &&
846
+ remote=1 &&
847
+ context="$context, >=1 remotes"
848
+ ;;
849
+ "no_remote")
850
+ empty_repo=0 &&
851
+ remote=0 &&
852
+ context="$context, 0 remotes"
853
+ ;;
854
+
855
+ # Whether there is at least one valid remote ref
856
+ "remote_ref")
857
+ # requires: remote
858
+ empty_repo=0 &&
859
+ remote_ref=1 &&
860
+ context="$context, >=1 fetched remote branches"
861
+ ;;
862
+ "no_remote_ref")
863
+ empty_repo=0 &&
864
+ remote_ref=0 &&
865
+ context="$context, 0 fetched remote branches"
866
+ ;;
867
+
868
+ # Options or flags that become illegal when --orphan is inferred
869
+ "no_checkout")
870
+ args="$args --no-checkout" &&
871
+ context="$context, --no-checkout"
872
+ ;;
873
+ "track")
874
+ args="$args --track" &&
875
+ context="$context, --track"
876
+ ;;
877
+
878
+ # All other options are illegal
879
+ *)
880
+ echo "test_dwim_orphan(): invalid arg: '$1'" >&2 &&
881
+ return 1
882
+ ;;
883
+ esac &&
884
+ shift
885
+ done &&
886
+ context="${context#', '}" &&
887
+ if [ $use_new_branch -eq 1 ]
888
+ then
889
+ args="$args -b foo"
890
+ else
891
+ context="DWIM (no --branch), $context"
892
+ fi &&
893
+ if [ $empty_repo -eq 1 ]
894
+ then
895
+ context="empty repo, $context"
896
+ fi &&
897
+ args="$args ../foo" &&
898
+ context="${context%', '}" &&
899
+ test_expect_success "$outcome_text w/ $context" '
900
+ test_when_finished "rm -rf repo" &&
901
+ git init repo &&
902
+ if [ $local_ref -eq 1 ] && [ "$git_ns" = "repo" ]
903
+ then
904
+ (cd repo && test_commit commit) &&
905
+ if [ $bad_head -eq 1 ]
906
+ then
907
+ git -C repo symbolic-ref HEAD refs/heads/badbranch
908
+ fi
909
+ elif [ $local_ref -eq 1 ] && [ "$git_ns" = "wt" ]
910
+ then
911
+ test_when_finished "git -C repo worktree remove -f ../wt" &&
912
+ git -C repo worktree add --orphan -b main ../wt &&
913
+ (cd wt && test_commit commit) &&
914
+ if [ $bad_head -eq 1 ]
915
+ then
916
+ git -C wt symbolic-ref HEAD refs/heads/badbranch
917
+ fi
918
+ elif [ $local_ref -eq 0 ] && [ "$git_ns" = "wt" ]
919
+ then
920
+ test_when_finished "git -C repo worktree remove -f ../wt" &&
921
+ git -C repo worktree add --orphan -b orphanbranch ../wt
922
+ fi &&
923
+
924
+ if [ $remote -eq 1 ]
925
+ then
926
+ test_when_finished "rm -rf upstream" &&
927
+ git init upstream &&
928
+ (cd upstream && test_commit commit) &&
929
+ git -C upstream switch -c foo &&
930
+ git -C repo remote add upstream ../upstream
931
+ fi &&
932
+
933
+ if [ $remote_ref -eq 1 ]
934
+ then
935
+ git -C repo fetch
936
+ fi &&
937
+ if [ $success -eq 1 ]
938
+ then
939
+ test_when_finished git -C repo worktree remove ../foo
940
+ fi &&
941
+ (
942
+ if [ $use_cd -eq 1 ]
943
+ then
944
+ cd $git_ns
945
+ fi &&
946
+ if [ "$outcome" = "infer" ]
947
+ then
948
+ git $dashc_args worktree add $args 2>actual &&
949
+ if [ $use_quiet -eq 1 ]
950
+ then
951
+ test_must_be_empty actual
952
+ else
953
+ grep "$info_text" actual
954
+ fi
955
+ elif [ "$outcome" = "no_infer" ]
956
+ then
957
+ git $dashc_args worktree add $args 2>actual &&
958
+ if [ $use_quiet -eq 1 ]
959
+ then
960
+ test_must_be_empty actual
961
+ else
962
+ ! grep "$info_text" actual
963
+ fi
964
+ elif [ "$outcome" = "fetch_error" ]
965
+ then
966
+ test_must_fail git $dashc_args worktree add $args 2>actual &&
967
+ grep "$fetch_error_text" actual
968
+ elif [ "$outcome" = "fatal_orphan_bad_combo" ]
969
+ then
970
+ test_must_fail git $dashc_args worktree add $args 2>actual &&
971
+ if [ $use_quiet -eq 1 ]
972
+ then
973
+ ! grep "$info_text" actual
974
+ else
975
+ grep "$info_text" actual
976
+ fi &&
977
+ grep "$bad_combo_regex" actual
978
+ elif [ "$outcome" = "warn_bad_head" ]
979
+ then
980
+ test_must_fail git $dashc_args worktree add $args 2>actual &&
981
+ if [ $use_quiet -eq 1 ]
982
+ then
983
+ grep "$invalid_ref_regex" actual &&
984
+ ! grep "$orphan_hint" actual
985
+ else
986
+ headpath=$(git $dashc_args rev-parse --sq --path-format=absolute --git-path HEAD) &&
987
+ headcontents=$(cat "$headpath") &&
988
+ grep "HEAD points to an invalid (or orphaned) reference" actual &&
989
+ grep "HEAD path:\s*.$headpath." actual &&
990
+ grep "HEAD contents:\s*.$headcontents." actual &&
991
+ grep "$orphan_hint" actual &&
992
+ ! grep "$info_text" actual
993
+ fi &&
994
+ grep "$invalid_ref_regex" actual
995
+ else
996
+ # Unreachable
997
+ false
998
+ fi
999
+ ) &&
1000
+ if [ $success -ne 1 ]
1001
+ then
1002
+ test_path_is_missing foo
1003
+ fi
1004
+ '
1005
+}
1006
+
1007
+for quiet_mode in "no_quiet" "quiet"
1008
+do
1009
+ for changedir_type in "cd_repo" "cd_wt" "-C_repo" "-C_wt"
1010
+ do
1011
+ dwim_test_args="$quiet_mode $changedir_type"
1012
+ test_dwim_orphan 'infer' $dwim_test_args no_-b
1013
+ test_dwim_orphan 'no_infer' $dwim_test_args no_-b local_ref good_head
1014
+ test_dwim_orphan 'infer' $dwim_test_args no_-b no_local_ref no_remote no_remote_ref no_guess_remote
1015
+ test_dwim_orphan 'infer' $dwim_test_args no_-b no_local_ref remote no_remote_ref no_guess_remote
1016
+ test_dwim_orphan 'fetch_error' $dwim_test_args no_-b no_local_ref remote no_remote_ref guess_remote
1017
+ test_dwim_orphan 'infer' $dwim_test_args no_-b no_local_ref remote no_remote_ref guess_remote force
1018
+ test_dwim_orphan 'no_infer' $dwim_test_args no_-b no_local_ref remote remote_ref guess_remote
1019
+
1020
+ test_dwim_orphan 'infer' $dwim_test_args -b
1021
+ test_dwim_orphan 'no_infer' $dwim_test_args -b local_ref good_head
1022
+ test_dwim_orphan 'infer' $dwim_test_args -b no_local_ref no_remote no_remote_ref no_guess_remote
1023
+ test_dwim_orphan 'infer' $dwim_test_args -b no_local_ref remote no_remote_ref no_guess_remote
1024
+ test_dwim_orphan 'infer' $dwim_test_args -b no_local_ref remote no_remote_ref guess_remote
1025
+ test_dwim_orphan 'infer' $dwim_test_args -b no_local_ref remote remote_ref guess_remote
1026
+ done
1027
+
1028
+ test_dwim_orphan 'fatal_orphan_bad_combo' $quiet_mode no_-b no_checkout
1029
+ test_dwim_orphan 'fatal_orphan_bad_combo' $quiet_mode no_-b track
1030
+ test_dwim_orphan 'fatal_orphan_bad_combo' $quiet_mode -b no_checkout
1031
+ test_dwim_orphan 'fatal_orphan_bad_combo' $quiet_mode -b track
1032
+done
1033
+
1034
post_checkout_hook () {
1035
test_when_finished "rm -rf .git/hooks" &&
1036
mkdir .git/hooks &&