commit e5cbb211a342397e8ac59234046e2bbbe017c7c1 from: Johannes Thyssen Tishman date: Thu Jul 31 16:51:36 2025 UTC preserve bad symlinks across merges ok stsp@ and op@ commit - 40e36ce5301442ff9172f57a80b91e1ca8bfd426 commit + e5cbb211a342397e8ac59234046e2bbbe017c7c1 blob - e229bb2a3ce1e8dedaa1b6d9cbb7ee90751a6673 blob + 628ec31796975901db85d57d58dc1aea8554e73d --- lib/worktree.c +++ lib/worktree.c @@ -7402,6 +7402,7 @@ rebase_commit(struct got_object_id **new_commit_id, cc_arg.repo = repo; cc_arg.have_staged_files = 0; cc_arg.commit_conflicts = allow_conflict; + cc_arg.allow_bad_symlinks = 1; /* preserve bad symlinks across merges */ /* * If possible get the status of individual files directly to * avoid crawling the entire work tree once per rebased commit. blob - a5e4a5b4eb82a85c156e715f8a32adb4fe2f3256 blob + 26b2c3e0885bfb34a45095898ff615b88dd7db10 --- regress/cmdline/histedit.sh +++ regress/cmdline/histedit.sh @@ -2901,7 +2901,99 @@ EOF test_done "$testroot" 0 } + +test_histedit_preserve_bad_link() { + local testroot=`test_init histedit_preserve_bad_link` + local orig_commit=`git_show_head $testroot/repo` + + got checkout $testroot/repo $testroot/wt > /dev/null + ret=$? + if [ $ret -ne 0 ]; then + echo "got checkout failed unexpectedly" + test_done "$testroot" "$ret" + return 1 + fi + + echo "file outside worktree" > $testroot/external_file + ln -sf $testroot/external_file $testroot/wt/bad_link + + (cd $testroot/wt && got add bad_link && \ + got commit -S -m 'add bad link') >/dev/null 2>&1 + ret=$? + if [ $ret -ne 0 ]; then + echo "got commit failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + local old_commit1=`git_show_head $testroot/repo` + (cd $testroot/wt && got update -c $orig_commit \ + >/dev/null 2>&1) + ret=$? + if [ $ret -ne 0 ]; then + echo "got update failed unexpectedly" + test_done "$testroot" "$ret" + return 1 + fi + + cat > $testroot/editor.sh < $testroot/stdout \ + 2>$testroot/stderr) + + ret=$? + if [ $ret -ne 0 ]; then + echo "histedit failed unexpectedly" >&2 + test_done "$testroot" "$ret" + return 1 + fi + + local old_commit2=`git_show_head $testroot/repo` + + local short_old_commit1=`trim_obj_id 12 $old_commit1` + local short_old_commit2=`trim_obj_id 12 $old_commit2` + + echo "A bad_link" > $testroot/stdout.expected + echo "$short_old_commit1 -> $short_old_commit2: add really bad link" \ + >> $testroot/stdout.expected + echo "Switching work tree to refs/heads/master" \ + >> $testroot/stdout.expected + + cmp -s $testroot/stdout.expected $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stderr.expected $testroot/stderr + test_done "$testroot" "$ret" + return 1 + fi + + cmp -s $testroot/external_file $testroot/wt/bad_link + ret=$? + if [ $ret -ne 0 ]; then + echo "contents of linked file and external file do not match" >&2 + test_done "$testroot" "$ret" + return 1 + fi + + bad_link_path=$(readlink $testroot/wt/bad_link) + if [ "$bad_link_path" != "$testroot/external_file" ]; then + echo "link was not preserved" >&2 + test_done "$testroot" "$ret" + return 1 + fi + + test_done "$testroot" "$ret" +} + test_parseargs "$@" run_test test_histedit_no_op run_test test_histedit_swap @@ -2931,3 +3023,4 @@ run_test test_histedit_mesg_filemode_change run_test test_histedit_drop_only run_test test_histedit_conflict_revert run_test test_histedit_no_eof_newline +run_test test_histedit_preserve_bad_link