t7002: add tests for moving from in-cone to out-of-cone

Add corresponding tests to test that user can move an in-cone <source> to out-of-cone <destination> when --sparse is supplied. Such <source> can be either clean or dirty, and moving it results in different behaviors: A clean move should move <source> to <destination> in the index (do *not* create <destination> in the worktree), then delete <source> from the worktree. A dirty move should move the <source> to the <destination>, both in the working tree and the index, but should *not* remove the resulted path from the working tree and should *not* turn on its CE_SKIP_WORKTREE bit. Also make sure that if <destination> exists in the index (existing check for if <destination> is in the worktree is not enough in in-to-out moves), warn user against the overwrite. And Git should force the overwrite when supplied with -f or --force. Helped-by: Derrick Stolee <derrickstolee@github.com> Helped-by: Victoria Dye <vdye@github.com> Signed-off-by: Shaoxuan Yuan <shaoxuan.yuan02@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Shaoxuan Yuan committed Aug 9, 2022 at 20:09 UTC 5506683deaab4c1475800e9b4cd2c06b8de4de97
1 file changed +198
t/t7002-mv-sparse-checkout.sh
+198
@@ -290,4 +290,202 @@ test_expect_success 'move sparse file to existing destination with --force and -
290 test_cmp expect sub/file1
291 '
292
293 +test_expect_failure 'move clean path from in-cone to out-of-cone' '
294 + test_when_finished "cleanup_sparse_checkout" &&
295 + setup_sparse_checkout &&
296 +
297 + test_must_fail git mv sub/d folder1 2>stderr &&
298 + cat sparse_error_header >expect &&
299 + echo "folder1/d" >>expect &&
300 + cat sparse_hint >>expect &&
301 + test_cmp expect stderr &&
302 +
303 + git mv --sparse sub/d folder1 2>stderr &&
304 + test_must_be_empty stderr &&
305 +
306 + test_path_is_missing sub/d &&
307 + test_path_is_missing folder1/d &&
308 + git ls-files -t >actual &&
309 + ! grep "^H sub/d\$" actual &&
310 + grep "S folder1/d" actual
311 +'
312 +
313 +test_expect_failure 'move clean path from in-cone to out-of-cone overwrite' '
314 + test_when_finished "cleanup_sparse_checkout" &&
315 + setup_sparse_checkout &&
316 + echo "sub/file1 overwrite" >sub/file1 &&
317 + git add sub/file1 &&
318 +
319 + test_must_fail git mv sub/file1 folder1 2>stderr &&
320 + cat sparse_error_header >expect &&
321 + echo "folder1/file1" >>expect &&
322 + cat sparse_hint >>expect &&
323 + test_cmp expect stderr &&
324 +
325 + test_must_fail git mv --sparse sub/file1 folder1 2>stderr &&
326 + echo "fatal: destination exists in the index, source=sub/file1, destination=folder1/file1" \
327 + >expect &&
328 + test_cmp expect stderr &&
329 +
330 + git mv --sparse -f sub/file1 folder1 2>stderr &&
331 + test_must_be_empty stderr &&
332 +
333 + test_path_is_missing sub/file1 &&
334 + test_path_is_missing folder1/file1 &&
335 + git ls-files -t >actual &&
336 + ! grep "H sub/file1" actual &&
337 + grep "S folder1/file1" actual &&
338 +
339 + # compare file content before move and after move
340 + echo "sub/file1 overwrite" >expect &&
341 + git ls-files -s -- folder1/file1 | awk "{print \$2}" >oid &&
342 + git cat-file blob $(cat oid) >actual &&
343 + test_cmp expect actual
344 +'
345 +
346 +# This test is testing the same behavior as the
347 +# "move clean path from in-cone to out-of-cone overwrite" above.
348 +# The only difference is the <destination> changes from "folder1" to "folder1/file1"
349 +test_expect_failure 'move clean path from in-cone to out-of-cone file overwrite' '
350 + test_when_finished "cleanup_sparse_checkout" &&
351 + setup_sparse_checkout &&
352 + echo "sub/file1 overwrite" >sub/file1 &&
353 + git add sub/file1 &&
354 +
355 + test_must_fail git mv sub/file1 folder1/file1 2>stderr &&
356 + cat sparse_error_header >expect &&
357 + echo "folder1/file1" >>expect &&
358 + cat sparse_hint >>expect &&
359 + test_cmp expect stderr &&
360 +
361 + test_must_fail git mv --sparse sub/file1 folder1/file1 2>stderr &&
362 + echo "fatal: destination exists in the index, source=sub/file1, destination=folder1/file1" \
363 + >expect &&
364 + test_cmp expect stderr &&
365 +
366 + git mv --sparse -f sub/file1 folder1/file1 2>stderr &&
367 + test_must_be_empty stderr &&
368 +
369 + test_path_is_missing sub/file1 &&
370 + test_path_is_missing folder1/file1 &&
371 + git ls-files -t >actual &&
372 + ! grep "H sub/file1" actual &&
373 + grep "S folder1/file1" actual &&
374 +
375 + # compare file content before move and after move
376 + echo "sub/file1 overwrite" >expect &&
377 + git ls-files -s -- folder1/file1 | awk "{print \$2}" >oid &&
378 + git cat-file blob $(cat oid) >actual &&
379 + test_cmp expect actual
380 +'
381 +
382 +test_expect_failure 'move directory with one of the files overwrite' '
383 + test_when_finished "cleanup_sparse_checkout" &&
384 + mkdir -p folder1/dir &&
385 + touch folder1/dir/file1 &&
386 + git add folder1 &&
387 + git sparse-checkout set --cone sub &&
388 +
389 + echo test >sub/dir/file1 &&
390 + git add sub/dir/file1 &&
391 +
392 + test_must_fail git mv sub/dir folder1 2>stderr &&
393 + cat sparse_error_header >expect &&
394 + echo "folder1/dir/e" >>expect &&
395 + echo "folder1/dir/file1" >>expect &&
396 + cat sparse_hint >>expect &&
397 + test_cmp expect stderr &&
398 +
399 + test_must_fail git mv --sparse sub/dir folder1 2>stderr &&
400 + echo "fatal: destination exists in the index, source=sub/dir/file1, destination=folder1/dir/file1" \
401 + >expect &&
402 + test_cmp expect stderr &&
403 +
404 + git mv --sparse -f sub/dir folder1 2>stderr &&
405 + test_must_be_empty stderr &&
406 +
407 + test_path_is_missing sub/dir/file1 &&
408 + test_path_is_missing sub/dir/e &&
409 + test_path_is_missing folder1/file1 &&
410 + git ls-files -t >actual &&
411 + ! grep "H sub/dir/file1" actual &&
412 + ! grep "H sub/dir/e" actual &&
413 + grep "S folder1/dir/file1" actual &&
414 +
415 + # compare file content before move and after move
416 + echo test >expect &&
417 + git ls-files -s -- folder1/dir/file1 | awk "{print \$2}" >oid &&
418 + git cat-file blob $(cat oid) >actual &&
419 + test_cmp expect actual
420 +'
421 +
422 +test_expect_failure 'move dirty path from in-cone to out-of-cone' '
423 + test_when_finished "cleanup_sparse_checkout" &&
424 + setup_sparse_checkout &&
425 + echo "modified" >>sub/d &&
426 +
427 + test_must_fail git mv sub/d folder1 2>stderr &&
428 + cat sparse_error_header >expect &&
429 + echo "folder1/d" >>expect &&
430 + cat sparse_hint >>expect &&
431 + test_cmp expect stderr &&
432 +
433 + git mv --sparse sub/d folder1 2>stderr &&
434 +
435 + test_path_is_missing sub/d &&
436 + test_path_is_file folder1/d &&
437 + git ls-files -t >actual &&
438 + ! grep "^H sub/d\$" actual &&
439 + grep "H folder1/d" actual
440 +'
441 +
442 +test_expect_failure 'move dir from in-cone to out-of-cone' '
443 + test_when_finished "cleanup_sparse_checkout" &&
444 + setup_sparse_checkout &&
445 +
446 + test_must_fail git mv sub/dir folder1 2>stderr &&
447 + cat sparse_error_header >expect &&
448 + echo "folder1/dir/e" >>expect &&
449 + cat sparse_hint >>expect &&
450 + test_cmp expect stderr &&
451 +
452 + git mv --sparse sub/dir folder1 2>stderr &&
453 + test_must_be_empty stderr &&
454 +
455 + test_path_is_missing folder1 &&
456 + git ls-files -t >actual &&
457 + ! grep "H sub/dir/e" actual &&
458 + grep "S folder1/dir/e" actual
459 +'
460 +
461 +test_expect_failure 'move partially-dirty dir from in-cone to out-of-cone' '
462 + test_when_finished "cleanup_sparse_checkout" &&
463 + setup_sparse_checkout &&
464 + touch sub/dir/e2 sub/dir/e3 &&
465 + git add sub/dir/e2 sub/dir/e3 &&
466 + echo "modified" >>sub/dir/e2 &&
467 + echo "modified" >>sub/dir/e3 &&
468 +
469 + test_must_fail git mv sub/dir folder1 2>stderr &&
470 + cat sparse_error_header >expect &&
471 + echo "folder1/dir/e" >>expect &&
472 + echo "folder1/dir/e2" >>expect &&
473 + echo "folder1/dir/e3" >>expect &&
474 + cat sparse_hint >>expect &&
475 + test_cmp expect stderr &&
476 +
477 + git mv --sparse sub/dir folder1 2>stderr &&
478 +
479 + test_path_is_missing folder1/dir/e &&
480 + test_path_is_file folder1/dir/e2 &&
481 + test_path_is_file folder1/dir/e3 &&
482 + git ls-files -t >actual &&
483 + ! grep "H sub/dir/e" actual &&
484 + ! grep "H sub/dir/e2" actual &&
485 + ! grep "H sub/dir/e3" actual &&
486 + grep "S folder1/dir/e" actual &&
487 + grep "H folder1/dir/e2" actual &&
488 + grep "H folder1/dir/e3" actual
489 +'
490 +
491 test_done