directory rename detection: tests for handling overwriting untracked files

Reviewed-by: Stefan Beller <sbeller@google.com> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Elijah Newren committed Apr 19, 2018 at 10:57 UTC a0b0a15103eda69a528f43c88facb011b91564aa
1 file changed +367
t/t6043-merge-rename-directories.sh
+367
@@ -2879,4 +2879,371 @@ test_expect_failure '9g-check: Renamed directory that only contained immediate s
2879 # side of history for any implicit directory renames.
2880 ###########################################################################
2881
2882 +###########################################################################
2883 +# SECTION 10: Handling untracked files
2884 +#
2885 +# unpack_trees(), upon which the recursive merge algorithm is based, aborts
2886 +# the operation if untracked or dirty files would be deleted or overwritten
2887 +# by the merge. Unfortunately, unpack_trees() does not understand renames,
2888 +# and if it doesn't abort, then it muddies up the working directory before
2889 +# we even get to the point of detecting renames, so we need some special
2890 +# handling, at least in the case of directory renames.
2891 +###########################################################################
2892 +
2893 +# Testcase 10a, Overwrite untracked: normal rename/delete
2894 +# Commit O: z/{b,c_1}
2895 +# Commit A: z/b + untracked z/c + untracked z/d
2896 +# Commit B: z/{b,d_1}
2897 +# Expected: Aborted Merge +
2898 +# ERROR_MSG(untracked working tree files would be overwritten by merge)
2899 +
2900 +test_expect_success '10a-setup: Overwrite untracked with normal rename/delete' '
2901 + test_create_repo 10a &&
2902 + (
2903 + cd 10a &&
2904 +
2905 + mkdir z &&
2906 + echo b >z/b &&
2907 + echo c >z/c &&
2908 + git add z &&
2909 + test_tick &&
2910 + git commit -m "O" &&
2911 +
2912 + git branch O &&
2913 + git branch A &&
2914 + git branch B &&
2915 +
2916 + git checkout A &&
2917 + git rm z/c &&
2918 + test_tick &&
2919 + git commit -m "A" &&
2920 +
2921 + git checkout B &&
2922 + git mv z/c z/d &&
2923 + test_tick &&
2924 + git commit -m "B"
2925 + )
2926 +'
2927 +
2928 +test_expect_success '10a-check: Overwrite untracked with normal rename/delete' '
2929 + (
2930 + cd 10a &&
2931 +
2932 + git checkout A^0 &&
2933 + echo very >z/c &&
2934 + echo important >z/d &&
2935 +
2936 + test_must_fail git merge -s recursive B^0 >out 2>err &&
2937 + test_i18ngrep "The following untracked working tree files would be overwritten by merge" err &&
2938 +
2939 + git ls-files -s >out &&
2940 + test_line_count = 1 out &&
2941 + git ls-files -o >out &&
2942 + test_line_count = 4 out &&
2943 +
2944 + echo very >expect &&
2945 + test_cmp expect z/c &&
2946 +
2947 + echo important >expect &&
2948 + test_cmp expect z/d &&
2949 +
2950 + git rev-parse HEAD:z/b >actual &&
2951 + git rev-parse O:z/b >expect &&
2952 + test_cmp expect actual
2953 + )
2954 +'
2955 +
2956 +# Testcase 10b, Overwrite untracked: dir rename + delete
2957 +# Commit O: z/{b,c_1}
2958 +# Commit A: y/b + untracked y/{c,d,e}
2959 +# Commit B: z/{b,d_1,e}
2960 +# Expected: Failed Merge; y/b + untracked y/c + untracked y/d on disk +
2961 +# z/c_1 -> z/d_1 rename recorded at stage 3 for y/d +
2962 +# ERROR_MSG(refusing to lose untracked file at 'y/d')
2963 +
2964 +test_expect_success '10b-setup: Overwrite untracked with dir rename + delete' '
2965 + test_create_repo 10b &&
2966 + (
2967 + cd 10b &&
2968 +
2969 + mkdir z &&
2970 + echo b >z/b &&
2971 + echo c >z/c &&
2972 + git add z &&
2973 + test_tick &&
2974 + git commit -m "O" &&
2975 +
2976 + git branch O &&
2977 + git branch A &&
2978 + git branch B &&
2979 +
2980 + git checkout A &&
2981 + git rm z/c &&
2982 + git mv z/ y/ &&
2983 + test_tick &&
2984 + git commit -m "A" &&
2985 +
2986 + git checkout B &&
2987 + git mv z/c z/d &&
2988 + echo e >z/e &&
2989 + git add z/e &&
2990 + test_tick &&
2991 + git commit -m "B"
2992 + )
2993 +'
2994 +
2995 +test_expect_failure '10b-check: Overwrite untracked with dir rename + delete' '
2996 + (
2997 + cd 10b &&
2998 +
2999 + git checkout A^0 &&
3000 + echo very >y/c &&
3001 + echo important >y/d &&
3002 + echo contents >y/e &&
3003 +
3004 + test_must_fail git merge -s recursive B^0 >out 2>err &&
3005 + test_i18ngrep "CONFLICT (rename/delete).*Version B\^0 of y/d left in tree at y/d~B\^0" out &&
3006 + test_i18ngrep "Error: Refusing to lose untracked file at y/e; writing to y/e~B\^0 instead" out &&
3007 +
3008 + git ls-files -s >out &&
3009 + test_line_count = 3 out &&
3010 + git ls-files -u >out &&
3011 + test_line_count = 2 out &&
3012 + git ls-files -o >out &&
3013 + test_line_count = 5 out &&
3014 +
3015 + git rev-parse >actual \
3016 + :0:y/b :3:y/d :3:y/e &&
3017 + git rev-parse >expect \
3018 + O:z/b O:z/c B:z/e &&
3019 + test_cmp expect actual &&
3020 +
3021 + echo very >expect &&
3022 + test_cmp expect y/c &&
3023 +
3024 + echo important >expect &&
3025 + test_cmp expect y/d &&
3026 +
3027 + echo contents >expect &&
3028 + test_cmp expect y/e
3029 + )
3030 +'
3031 +
3032 +# Testcase 10c, Overwrite untracked: dir rename/rename(1to2)
3033 +# Commit O: z/{a,b}, x/{c,d}
3034 +# Commit A: y/{a,b}, w/c, x/d + different untracked y/c
3035 +# Commit B: z/{a,b,c}, x/d
3036 +# Expected: Failed Merge; y/{a,b} + x/d + untracked y/c +
3037 +# CONFLICT(rename/rename) x/c -> w/c vs y/c +
3038 +# y/c~B^0 +
3039 +# ERROR_MSG(Refusing to lose untracked file at y/c)
3040 +
3041 +test_expect_success '10c-setup: Overwrite untracked with dir rename/rename(1to2)' '
3042 + test_create_repo 10c &&
3043 + (
3044 + cd 10c &&
3045 +
3046 + mkdir z x &&
3047 + echo a >z/a &&
3048 + echo b >z/b &&
3049 + echo c >x/c &&
3050 + echo d >x/d &&
3051 + git add z x &&
3052 + test_tick &&
3053 + git commit -m "O" &&
3054 +
3055 + git branch O &&
3056 + git branch A &&
3057 + git branch B &&
3058 +
3059 + git checkout A &&
3060 + mkdir w &&
3061 + git mv x/c w/c &&
3062 + git mv z/ y/ &&
3063 + test_tick &&
3064 + git commit -m "A" &&
3065 +
3066 + git checkout B &&
3067 + git mv x/c z/ &&
3068 + test_tick &&
3069 + git commit -m "B"
3070 + )
3071 +'
3072 +
3073 +test_expect_failure '10c-check: Overwrite untracked with dir rename/rename(1to2)' '
3074 + (
3075 + cd 10c &&
3076 +
3077 + git checkout A^0 &&
3078 + echo important >y/c &&
3079 +
3080 + test_must_fail git merge -s recursive B^0 >out 2>err &&
3081 + test_i18ngrep "CONFLICT (rename/rename)" out &&
3082 + test_i18ngrep "Refusing to lose untracked file at y/c; adding as y/c~B\^0 instead" out &&
3083 +
3084 + git ls-files -s >out &&
3085 + test_line_count = 6 out &&
3086 + git ls-files -u >out &&
3087 + test_line_count = 3 out &&
3088 + git ls-files -o >out &&
3089 + test_line_count = 3 out &&
3090 +
3091 + git rev-parse >actual \
3092 + :0:y/a :0:y/b :0:x/d :1:x/c :2:w/c :3:y/c &&
3093 + git rev-parse >expect \
3094 + O:z/a O:z/b O:x/d O:x/c O:x/c O:x/c &&
3095 + test_cmp expect actual &&
3096 +
3097 + git hash-object y/c~B^0 >actual &&
3098 + git rev-parse O:x/c >expect &&
3099 + test_cmp expect actual &&
3100 +
3101 + echo important >expect &&
3102 + test_cmp expect y/c
3103 + )
3104 +'
3105 +
3106 +# Testcase 10d, Delete untracked w/ dir rename/rename(2to1)
3107 +# Commit O: z/{a,b,c_1}, x/{d,e,f_2}
3108 +# Commit A: y/{a,b}, x/{d,e,f_2,wham_1} + untracked y/wham
3109 +# Commit B: z/{a,b,c_1,wham_2}, y/{d,e}
3110 +# Expected: Failed Merge; y/{a,b,d,e} + untracked y/{wham,wham~B^0,wham~HEAD}+
3111 +# CONFLICT(rename/rename) z/c_1 vs x/f_2 -> y/wham
3112 +# ERROR_MSG(Refusing to lose untracked file at y/wham)
3113 +
3114 +test_expect_success '10d-setup: Delete untracked with dir rename/rename(2to1)' '
3115 + test_create_repo 10d &&
3116 + (
3117 + cd 10d &&
3118 +
3119 + mkdir z x &&
3120 + echo a >z/a &&
3121 + echo b >z/b &&
3122 + echo c >z/c &&
3123 + echo d >x/d &&
3124 + echo e >x/e &&
3125 + echo f >x/f &&
3126 + git add z x &&
3127 + test_tick &&
3128 + git commit -m "O" &&
3129 +
3130 + git branch O &&
3131 + git branch A &&
3132 + git branch B &&
3133 +
3134 + git checkout A &&
3135 + git mv z/c x/wham &&
3136 + git mv z/ y/ &&
3137 + test_tick &&
3138 + git commit -m "A" &&
3139 +
3140 + git checkout B &&
3141 + git mv x/f z/wham &&
3142 + git mv x/ y/ &&
3143 + test_tick &&
3144 + git commit -m "B"
3145 + )
3146 +'
3147 +
3148 +test_expect_failure '10d-check: Delete untracked with dir rename/rename(2to1)' '
3149 + (
3150 + cd 10d &&
3151 +
3152 + git checkout A^0 &&
3153 + echo important >y/wham &&
3154 +
3155 + test_must_fail git merge -s recursive B^0 >out 2>err &&
3156 + test_i18ngrep "CONFLICT (rename/rename)" out &&
3157 + test_i18ngrep "Refusing to lose untracked file at y/wham" out &&
3158 +
3159 + git ls-files -s >out &&
3160 + test_line_count = 6 out &&
3161 + git ls-files -u >out &&
3162 + test_line_count = 2 out &&
3163 + git ls-files -o >out &&
3164 + test_line_count = 4 out &&
3165 +
3166 + git rev-parse >actual \
3167 + :0:y/a :0:y/b :0:y/d :0:y/e :2:y/wham :3:y/wham &&
3168 + git rev-parse >expect \
3169 + O:z/a O:z/b O:x/d O:x/e O:z/c O:x/f &&
3170 + test_cmp expect actual &&
3171 +
3172 + test_must_fail git rev-parse :1:y/wham &&
3173 +
3174 + echo important >expect &&
3175 + test_cmp expect y/wham &&
3176 +
3177 + git hash-object >actual \
3178 + y/wham~B^0 y/wham~HEAD &&
3179 + git rev-parse >expect \
3180 + O:x/f O:z/c &&
3181 + test_cmp expect actual
3182 + )
3183 +'
3184 +
3185 +# Testcase 10e, Does git complain about untracked file that's not in the way?
3186 +# Commit O: z/{a,b}
3187 +# Commit A: y/{a,b} + untracked z/c
3188 +# Commit B: z/{a,b,c}
3189 +# Expected: y/{a,b,c} + untracked z/c
3190 +
3191 +test_expect_success '10e-setup: Does git complain about untracked file that is not really in the way?' '
3192 + test_create_repo 10e &&
3193 + (
3194 + cd 10e &&
3195 +
3196 + mkdir z &&
3197 + echo a >z/a &&
3198 + echo b >z/b &&
3199 + git add z &&
3200 + test_tick &&
3201 + git commit -m "O" &&
3202 +
3203 + git branch O &&
3204 + git branch A &&
3205 + git branch B &&
3206 +
3207 + git checkout A &&
3208 + git mv z/ y/ &&
3209 + test_tick &&
3210 + git commit -m "A" &&
3211 +
3212 + git checkout B &&
3213 + echo c >z/c &&
3214 + git add z/c &&
3215 + test_tick &&
3216 + git commit -m "B"
3217 + )
3218 +'
3219 +
3220 +test_expect_failure '10e-check: Does git complain about untracked file that is not really in the way?' '
3221 + (
3222 + cd 10e &&
3223 +
3224 + git checkout A^0 &&
3225 + mkdir z &&
3226 + echo random >z/c &&
3227 +
3228 + git merge -s recursive B^0 >out 2>err &&
3229 + test_i18ngrep ! "following untracked working tree files would be overwritten by merge" err &&
3230 +
3231 + git ls-files -s >out &&
3232 + test_line_count = 3 out &&
3233 + git ls-files -u >out &&
3234 + test_line_count = 0 out &&
3235 + git ls-files -o >out &&
3236 + test_line_count = 3 out &&
3237 +
3238 + git rev-parse >actual \
3239 + :0:y/a :0:y/b :0:y/c &&
3240 + git rev-parse >expect \
3241 + O:z/a O:z/b B:z/c &&
3242 + test_cmp expect actual &&
3243 +
3244 + echo random >expect &&
3245 + test_cmp expect z/c
3246 + )
3247 +'
3248 +
3249 test_done