commit - fa3cef63799016195e8a917f39c82815522692aa
commit + 369fd7e5fa99b95f7d7aa812b5260584b86a3778
blob - df57239f50ac1caa3457f59d6df054cab52a05bc
blob + 2a2d317c015385526ce0f22c09ed3240dafad6a5
--- lib/worktree.c
+++ lib/worktree.c
if (a->patch_cb && (status == GOT_STATUS_MODIFY ||
status == GOT_STATUS_CONFLICT)) {
+ int is_bad_symlink = 0;
err = create_patched_content(&path_content, 1, &id,
ondisk_path, dirfd, de_name, ie->path, a->repo,
a->patch_cb, a->patch_arg);
if (err || path_content == NULL)
break;
- if (rename(path_content, ondisk_path) == -1) {
- err = got_error_from_errno3("rename",
- path_content, ondisk_path);
- goto done;
+ if (te && S_ISLNK(te->mode)) {
+ if (unlink(path_content) == -1) {
+ err = got_error_from_errno2("unlink",
+ path_content);
+ break;
+ }
+ err = install_symlink(&is_bad_symlink,
+ a->worktree, ondisk_path, ie->path,
+ blob, 0, 1, 0, a->repo,
+ a->progress_cb, a->progress_arg);
+ } else {
+ if (rename(path_content, ondisk_path) == -1) {
+ err = got_error_from_errno3("rename",
+ path_content, ondisk_path);
+ goto done;
+ }
}
} else {
int is_bad_symlink = 0;
blob - 72a6ec979f66c13f3dd2fe3b41d969024ebf7283
blob + 84419db8223bceeb8d7e6ec0d1d43f75ebff9b5a
--- regress/cmdline/revert.sh
+++ regress/cmdline/revert.sh
test_done "$testroot" "$ret"
}
+function test_revert_patch_symlink {
+ local testroot=`test_init revert_patch_symlink`
+
+ (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 -sf epsilon/zeta zeta.link)
+ (cd $testroot/repo && ln -sf epsilon/zeta zeta2.link)
+ (cd $testroot/repo && git add .)
+ git_commit $testroot/repo -m "add symlinks"
+ local commit_id1=`git_show_head $testroot/repo`
+
+ got checkout $testroot/repo $testroot/wt > /dev/null
+
+ # symlink to file A now points to file B
+ (cd $testroot/wt && ln -sf gamma/delta alpha.link)
+ # symlink to a directory A now points to file B
+ (cd $testroot/wt && ln -sfh beta epsilon.link)
+ # "bad" symlink now contains a different target path
+ echo "foo" > $testroot/wt/passwd.link
+ # relative symlink to directory A now points to relative directory B
+ (cd $testroot/wt && ln -sfh ../gamma epsilon/beta.link)
+ # an unversioned symlink
+ (cd $testroot/wt && ln -sf .got/foo dotgotfoo.link)
+ # symlink to file A now points to non-existent file B
+ (cd $testroot/wt && ln -sf nonexistent2 nonexistent.link)
+ # removed symlink
+ (cd $testroot/wt && got rm zeta.link > /dev/null)
+ (cd $testroot/wt && got rm zeta2.link > /dev/null)
+ # added symlink
+ (cd $testroot/wt && ln -sf beta new.link)
+ (cd $testroot/wt && got add new.link > /dev/null)
+ (cd $testroot/wt && ln -sf beta zeta3.link)
+ (cd $testroot/wt && got add zeta3.link > /dev/null)
+
+ printf "y\nn\ny\nn\ny\ny\nn\ny\ny\n" > $testroot/patchscript
+ (cd $testroot/wt && got revert -F $testroot/patchscript -p -R . \
+ > $testroot/stdout)
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ echo "got revert command failed unexpectedly" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+ cat > $testroot/stdout.expected <<EOF
+-----------------------------------------------
+@@ -1 +1 @@
+-alpha
+\ No newline at end of file
++gamma/delta
+\ No newline at end of file
+-----------------------------------------------
+M alpha.link (change 1 of 1)
+revert this change? [y/n/q] y
+R alpha.link
+-----------------------------------------------
+@@ -1 +1 @@
+-../beta
+\ No newline at end of file
++../gamma
+\ No newline at end of file
+-----------------------------------------------
+M epsilon/beta.link (change 1 of 1)
+revert this change? [y/n/q] n
+-----------------------------------------------
+@@ -1 +1 @@
+-epsilon
+\ No newline at end of file
++beta
+\ No newline at end of file
+-----------------------------------------------
+M epsilon.link (change 1 of 1)
+revert this change? [y/n/q] y
+R epsilon.link
+A new.link
+revert this addition? [y/n] n
+-----------------------------------------------
+@@ -1 +1 @@
+-nonexistent
+\ No newline at end of file
++nonexistent2
+\ No newline at end of file
+-----------------------------------------------
+M nonexistent.link (change 1 of 1)
+revert this change? [y/n/q] y
+R nonexistent.link
+-----------------------------------------------
+@@ -1 +1 @@
+-/etc/passwd
+\ No newline at end of file
++foo
+-----------------------------------------------
+M passwd.link (change 1 of 1)
+revert this change? [y/n/q] y
+R passwd.link
+D zeta.link
+revert this deletion? [y/n] n
+D zeta2.link
+revert this deletion? [y/n] y
+R zeta2.link
+A zeta3.link
+revert this addition? [y/n] y
+R zeta3.link
+EOF
+ 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/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 "passwd.link should not be a symlink" >&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 "../gamma" > $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 "dotgotfoo.link is not a symlink " >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+ readlink $testroot/wt/dotgotfoo.link > $testroot/stdout
+ echo ".got/foo" > $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 [ -e $testroot/wt/zeta.link ]; then
+ echo -n "zeta.link should not exist on disk" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ if [ ! -h $testroot/wt/zeta2.link ]; then
+ echo -n "zeta2.link is not a symlink" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ readlink $testroot/wt/zeta2.link > $testroot/stdout
+ echo "epsilon/zeta" > $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/zeta3.link ]; then
+ echo -n "zeta3.link is not a symlink" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ readlink $testroot/wt/zeta2.link > $testroot/stdout
+ echo "epsilon/zeta" > $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/new.link ]; then
+ echo -n "new.link is not a symlink" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ (cd $testroot/wt && got status > $testroot/stdout)
+ echo "? dotgotfoo.link" > $testroot/stdout.expected
+ echo "M epsilon/beta.link" >> $testroot/stdout.expected
+ echo "A new.link" >> $testroot/stdout.expected
+ echo "D zeta.link" >> $testroot/stdout.expected
+ echo "? zeta3.link" >> $testroot/stdout.expected
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ return 1
+ fi
+ test_done "$testroot" "$ret"
+}
+
run_test test_revert_basic
run_test test_revert_rm
run_test test_revert_add
run_test test_revert_added_subtree
run_test test_revert_deleted_subtree
run_test test_revert_symlink
+run_test test_revert_patch_symlink