commit 692a4bb1222d6b7c94768d7305a2178a15b05887 from: Stefan Sperling date: Mon Aug 28 17:20:33 2023 UTC prevent overlapping repo and work tree in 'got checkout' Some people are eager to try to make Got work just like Git by overlaying the repository and work tree. This causes problems with unveil conflicts at run-time. Fail as early as possible during 'got checkout' when users attempt this. cosmetic tweaks + ok op@ commit - 9c6f408e227e19f58acfc34e96b12d9de29581fd commit + 692a4bb1222d6b7c94768d7305a2178a15b05887 blob - 29feb8935ab716a9191034d2ebede3da7cea1f73 blob + 4370083c6addb07677bb5bf8779721aad3c6fdec --- got/got.c +++ got/got.c @@ -3077,6 +3077,15 @@ cmd_checkout(int argc, char *argv[]) got_path_strip_trailing_slashes(repo_path); got_path_strip_trailing_slashes(worktree_path); + if (got_path_is_child(worktree_path, repo_path, strlen(repo_path)) || + got_path_is_child(repo_path, worktree_path, + strlen(worktree_path))) { + error = got_error_fmt(GOT_ERR_BAD_PATH, + "work tree and repository paths may not overlap: %s", + worktree_path); + goto done; + } + error = got_repo_pack_fds_open(&pack_fds); if (error != NULL) goto done; blob - 993c64afcbd5f4598770774738e513c4afb9387c blob + 642aa7ff0a7ff201dae5e22b59ce99b7e725eced --- regress/cmdline/checkout.sh +++ regress/cmdline/checkout.sh @@ -141,9 +141,77 @@ test_checkout_dir_not_empty() { ret=$? if [ $ret -ne 0 ]; then diff -u $testroot/stdout.expected $testroot/stdout + fi + test_done "$testroot" "$ret" + +} + +test_checkout_into_repo() { + local testroot=`test_init checkout_into_repo` + local commit_id=`git_show_head $testroot/repo` + + got checkout $testroot/repo $testroot/repo/wt \ + > $testroot/stdout 2> $testroot/stderr + ret=$? + if [ $ret -eq 0 ]; then + echo "checkout succeeded unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + echo -n > $testroot/stdout.expected + + cmp -s $testroot/stdout.expected $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + echo -n "got: work tree and repository paths may not overlap: " \ + > $testroot/stderr.expected + echo "$testroot/repo/wt: bad path" >> $testroot/stderr.expected + cmp -s $testroot/stderr.expected $testroot/stderr + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stderr.expected $testroot/stderr fi test_done "$testroot" "$ret" +} +test_checkout_overlap_repo() { + local testroot=`test_init checkout_into_repo` + local commit_id=`git_show_head $testroot/repo` + + got checkout $testroot/repo $testroot \ + > $testroot/stdout 2> $testroot/stderr + ret=$? + if [ $ret -eq 0 ]; then + echo "checkout succeeded unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + echo -n > $testroot/stdout.expected + + cmp -s $testroot/stdout.expected $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + echo -n "got: work tree and repository paths may not overlap: " \ + > $testroot/stderr.expected + echo "$testroot: bad path" >> $testroot/stderr.expected + cmp -s $testroot/stderr.expected $testroot/stderr + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stderr.expected $testroot/stderr + fi + test_done "$testroot" "$ret" } test_checkout_sets_xbit() { @@ -1010,6 +1078,8 @@ test_parseargs "$@" run_test test_checkout_basic run_test test_checkout_dir_exists run_test test_checkout_dir_not_empty +run_test test_checkout_into_repo +run_test test_checkout_overlap_repo run_test test_checkout_sets_xbit run_test test_checkout_commit_from_wrong_branch run_test test_checkout_tag