1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
|
#!/bin/sh
test_description='undoing resolution'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
check_resolve_undo () {
msg=$1
shift
while case $# in
0) break ;;
1|2|3) die "Bug in check-resolve-undo test" ;;
esac
do
path=$1
shift
for stage in 1 2 3
do
sha1=$1
shift
case "$sha1" in
'') continue ;;
esac
sha1=$(git rev-parse --verify "$sha1")
printf "100644 %s %s\t%s\n" $sha1 $stage $path
done
done >"$msg.expect" &&
git ls-files --resolve-undo >"$msg.actual" &&
test_cmp "$msg.expect" "$msg.actual"
}
prime_resolve_undo () {
git reset --hard &&
git checkout second^0 &&
test_tick &&
test_must_fail git merge third^0 &&
check_resolve_undo empty &&
# how should the conflict be resolved?
case "$1" in
remove)
rm -f file/le && git rm fi/le
;;
*) # modify
echo different >fi/le && git add fi/le
;;
esac
check_resolve_undo recorded fi/le initial:fi/le second:fi/le third:fi/le
}
test_expect_success setup '
mkdir fi &&
printf "a\0a" >binary &&
git add binary &&
test_commit initial fi/le first &&
git branch side &&
git branch another &&
printf "a\0b" >binary &&
git add binary &&
test_commit second fi/le second &&
git checkout side &&
test_commit third fi/le third &&
git branch add-add &&
git checkout another &&
test_commit fourth fi/le fourth &&
git checkout add-add &&
test_commit fifth add-differently &&
git checkout main
'
test_expect_success 'add records switch clears' '
prime_resolve_undo &&
test_tick &&
git commit -m merged &&
echo committing keeps &&
check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
git checkout second^0 &&
echo switching clears &&
check_resolve_undo cleared
'
test_expect_success 'rm records reset clears' '
prime_resolve_undo &&
test_tick &&
git commit -m merged &&
echo committing keeps &&
check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
echo merge clears upfront &&
test_must_fail git merge fourth^0 &&
check_resolve_undo nuked &&
git rm -f fi/le &&
echo resolving records &&
check_resolve_undo recorded fi/le initial:fi/le HEAD:fi/le fourth:fi/le &&
git reset --hard &&
echo resetting discards &&
check_resolve_undo discarded
'
test_expect_success 'plumbing clears' '
prime_resolve_undo &&
test_tick &&
git commit -m merged &&
echo committing keeps &&
check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
echo plumbing clear &&
git update-index --clear-resolve-undo &&
check_resolve_undo cleared
'
test_expect_success 'add records checkout -m undoes' '
prime_resolve_undo &&
git diff HEAD &&
git checkout --conflict=merge fi/le &&
echo checkout used the record and removed it &&
check_resolve_undo removed &&
echo the index and the work tree is unmerged again &&
git diff >actual &&
grep "^++<<<<<<<" actual
'
test_expect_success 'unmerge with plumbing' '
prime_resolve_undo &&
git update-index --unresolve fi/le &&
git ls-files --resolve-undo fi/le >actual &&
test_must_be_empty actual &&
git ls-files -u >actual &&
test_line_count = 3 actual
'
test_expect_success 'unmerge can be done even after committing' '
prime_resolve_undo &&
git commit -m "record to nuke MERGE_HEAD" &&
git update-index --unresolve fi/le &&
git ls-files --resolve-undo fi/le >actual &&
test_must_be_empty actual &&
git ls-files -u >actual &&
test_line_count = 3 actual
'
test_expect_success 'unmerge removal' '
prime_resolve_undo remove &&
git update-index --unresolve fi/le &&
git ls-files --resolve-undo fi/le >actual &&
test_must_be_empty actual &&
git ls-files -u >actual &&
test_line_count = 3 actual
'
test_expect_success 'unmerge removal after committing' '
prime_resolve_undo remove &&
git commit -m "record to nuke MERGE_HEAD" &&
git update-index --unresolve fi/le &&
git ls-files --resolve-undo fi/le >actual &&
test_must_be_empty actual &&
git ls-files -u >actual &&
test_line_count = 3 actual
'
test_expect_success 'rerere and rerere forget' '
mkdir .git/rr-cache &&
prime_resolve_undo &&
echo record the resolution &&
git rerere &&
rerere_id=$(cd .git/rr-cache && echo */postimage) &&
rerere_id=${rerere_id%/postimage} &&
test -f .git/rr-cache/$rerere_id/postimage &&
git checkout -m fi/le &&
echo resurrect the conflict &&
grep "^=======" fi/le &&
echo reresolve the conflict &&
git rerere &&
test "z$(cat fi/le)" = zdifferent &&
echo register the resolution again &&
git add fi/le &&
check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
test -z "$(git ls-files -u)" &&
git rerere forget fi/le &&
! test -f .git/rr-cache/$rerere_id/postimage &&
tr "\0" "\n" <.git/MERGE_RR >actual &&
echo "$rerere_id fi/le" >expect &&
test_cmp expect actual
'
test_expect_success 'rerere and rerere forget (subdirectory)' '
rm -fr .git/rr-cache &&
mkdir .git/rr-cache &&
prime_resolve_undo &&
echo record the resolution &&
(cd fi && git rerere) &&
rerere_id=$(cd .git/rr-cache && echo */postimage) &&
rerere_id=${rerere_id%/postimage} &&
test -f .git/rr-cache/$rerere_id/postimage &&
(cd fi && git checkout -m le) &&
echo resurrect the conflict &&
grep "^=======" fi/le &&
echo reresolve the conflict &&
(cd fi && git rerere) &&
test "z$(cat fi/le)" = zdifferent &&
echo register the resolution again &&
(cd fi && git add le) &&
check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
test -z "$(git ls-files -u)" &&
(cd fi && git rerere forget le) &&
! test -f .git/rr-cache/$rerere_id/postimage &&
tr "\0" "\n" <.git/MERGE_RR >actual &&
echo "$rerere_id fi/le" >expect &&
test_cmp expect actual
'
test_expect_success 'rerere forget (binary)' '
git checkout -f side &&
test_commit --printf binary binary "a\0c" &&
test_must_fail git merge second &&
git rerere forget binary
'
test_expect_success 'rerere forget (add-add conflict)' '
git checkout -f main &&
echo main >add-differently &&
git add add-differently &&
git commit -m "add differently" &&
test_must_fail git merge fifth &&
git rerere forget add-differently 2>actual &&
test_grep "no remembered" actual
'
test_expect_success 'resolve-undo keeps blobs from gc' '
git checkout -f main &&
# First make sure we do not have any cruft left in the object store
git repack -a -d &&
git prune --expire=now &&
git prune-packed &&
git gc --prune=now &&
git fsck --unreachable >cruft &&
test_must_be_empty cruft &&
# Now add three otherwise unreferenced blob objects to the index
git reset --hard &&
B1=$(echo "resolve undo test data 1" | git hash-object -w --stdin) &&
B2=$(echo "resolve undo test data 2" | git hash-object -w --stdin) &&
B3=$(echo "resolve undo test data 3" | git hash-object -w --stdin) &&
git update-index --add --index-info <<-EOF &&
100644 $B1 1 frotz
100644 $B2 2 frotz
100644 $B3 3 frotz
EOF
# These three blob objects are reachable (only) from the index
git fsck --unreachable >cruft &&
test_must_be_empty cruft &&
# and they should be protected from GC
git gc --prune=now &&
git cat-file -e $B1 &&
git cat-file -e $B2 &&
git cat-file -e $B3 &&
# Now resolve the conflicted path
B0=$(echo "resolve undo test data 0" | git hash-object -w --stdin) &&
git update-index --add --cacheinfo 100644,$B0,frotz &&
# These three blob objects are now reachable only from the resolve-undo
git fsck --unreachable >cruft &&
test_must_be_empty cruft &&
# and they should survive GC
git gc --prune=now &&
git cat-file -e $B0 &&
git cat-file -e $B1 &&
git cat-file -e $B2 &&
git cat-file -e $B3 &&
# Now we switch away, which nukes resolve-undo, and
# blobs B0..B3 would become dangling. fsck should
# notice that they are now unreachable.
git checkout -f side &&
git fsck --unreachable >cruft &&
sort cruft >actual &&
sort <<-EOF >expect &&
unreachable blob $B0
unreachable blob $B1
unreachable blob $B2
unreachable blob $B3
EOF
test_cmp expect actual &&
# And they should go away when gc runs.
git gc --prune=now &&
git fsck --unreachable >cruft &&
test_must_be_empty cruft &&
test_must_fail git cat-file -e $B0 &&
test_must_fail git cat-file -e $B1 &&
test_must_fail git cat-file -e $B2 &&
test_must_fail git cat-file -e $B3
'
test_done
|