commit 7d61d89137e4704e685dacfcfb71a42a87ba9f78 from: Stefan Sperling date: Thu Jul 23 14:21:29 2020 UTC fix checkout of symlinks when a relative work tree path is given commit - 906c123b76844b1bba457451f3571b64afa77006 commit + 7d61d89137e4704e685dacfcfb71a42a87ba9f78 blob - 879e8cb6f14e7b6c5f1c156dc33f16a2e9710324 blob + 365bc046c6f9d63a9505071b9fcfa2ed056c4931 --- lib/worktree.c +++ lib/worktree.c @@ -376,9 +376,9 @@ open_worktree(struct got_worktree **worktree, const ch } (*worktree)->lockfd = -1; - (*worktree)->root_path = strdup(path); + (*worktree)->root_path = realpath(path, NULL); if ((*worktree)->root_path == NULL) { - err = got_error_from_errno("strdup"); + err = got_error_from_errno2("realpath", path); goto done; } err = read_meta_file(&(*worktree)->repo_path, path_got, blob - a7cf8346fb69dcd9589570531e799d90564c3ee0 blob + 3cf2adea08569d237c3ae2792cad85f134715215 --- regress/cmdline/checkout.sh +++ regress/cmdline/checkout.sh @@ -608,7 +608,113 @@ function test_checkout_symlink { fi test_done "$testroot" "$ret" } + +function test_checkout_symlink_relative_wtpath { + local testroot=`test_init checkout_symlink_with_wtpath` + + (cd $testroot/repo && ln -s alpha alpha.link) + (cd $testroot/repo && ln -s epsilon epsilon.link) + (cd $testroot/repo && ln -s /etc/passwd passwd.link) + (cd $testroot/repo && ln -s ../beta epsilon/beta.link) + (cd $testroot/repo && ln -s nonexistent nonexistent.link) + (cd $testroot/repo && ln -s .got/foo dotgotfoo.link) + (cd $testroot/repo && git add .) + git_commit $testroot/repo -m "add symlinks" + + (cd $testroot && got checkout $testroot/repo wt > /dev/null) + ret="$?" + if [ "$ret" != "0" ]; then + test_done "$testroot" "$ret" + return 1 + fi + if ! [ -h $testroot/wt/alpha.link ]; then + echo "alpha.link is not a symlink" + test_done "$testroot" "1" + return 1 + fi + + readlink $testroot/wt/alpha.link > $testroot/stdout + echo "alpha" > $testroot/stdout.expected + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + if ! [ -h $testroot/wt/epsilon.link ]; then + echo "epsilon.link is not a symlink" + test_done "$testroot" "1" + return 1 + fi + + readlink $testroot/wt/epsilon.link > $testroot/stdout + echo "epsilon" > $testroot/stdout.expected + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + if [ -h $testroot/wt/passwd.link ]; then + echo -n "passwd.link symlink points outside of work tree: " >&2 + readlink $testroot/wt/passwd.link >&2 + test_done "$testroot" "1" + return 1 + fi + + echo -n "/etc/passwd" > $testroot/content.expected + cp $testroot/wt/passwd.link $testroot/content + + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + readlink $testroot/wt/epsilon/beta.link > $testroot/stdout + echo "../beta" > $testroot/stdout.expected + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + readlink $testroot/wt/nonexistent.link > $testroot/stdout + echo "nonexistent" > $testroot/stdout.expected + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + fi + + if [ -h $testroot/wt/dotgotfoo.link ]; then + echo -n "dotgotfoo.link symlink points into .got dir: " >&2 + readlink $testroot/wt/dotgotfoo.link >&2 + test_done "$testroot" "1" + return 1 + fi + + echo -n ".got/foo" > $testroot/content.expected + cp $testroot/wt/dotgotfoo.link $testroot/content + + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + fi + test_done "$testroot" "$ret" +} + run_test test_checkout_basic run_test test_checkout_dir_exists run_test test_checkout_dir_not_empty @@ -619,3 +725,4 @@ run_test test_checkout_ignores_submodules run_test test_checkout_read_only run_test test_checkout_into_nonempty_dir run_test test_checkout_symlink +run_test test_checkout_symlink_relative_wtpath