commit - cf34e6e70511929983a7a035e946966e8a833b8f
commit + c631b1152565e4c18cb2123e1d3d7c08d513c02f
blob - 315fadb7928641092f567960ffa58125ab66b04a
blob + bde4162e571552b42ca8aea844c0fb7d81ee59e3
--- lib/worktree.c
+++ lib/worktree.c
goto done;
if (S_ISLNK(sb->st_mode)) {
- /* Staging changes to symlinks is not yet(?) supported. */
- if (staged_status != GOT_STATUS_NO_CHANGE) {
- err = got_error_path(abspath, GOT_ERR_FILE_STATUS);
- goto done;
- }
err = get_symlink_status(status, sb, ie, abspath, dirfd,
de_name, blob);
goto done;
struct got_tree_entry *te;
char *entry_name;
- err = got_object_open_as_blob(&blob, repo, ct->blob_id, PATH_MAX);
- if (err)
- return err;
+ if (ct->staged_status == GOT_STATUS_ADD ||
+ ct->staged_status == GOT_STATUS_MODIFY) {
+ err = got_object_open_as_blob(&blob, repo, ct->staged_blob_id,
+ PATH_MAX);
+ if (err)
+ return err;
+ } else {
+ err = got_object_open_as_blob(&blob, repo, ct->blob_id,
+ PATH_MAX);
+ if (err)
+ return err;
+ }
err = got_path_dirname(&tree_path, ct->in_repo_path);
if (err) {
struct got_fileindex_entry *ie;
int is_bad_symlink = 0;
- if (!S_ISLNK(get_ct_file_mode(ct)))
+ if (!S_ISLNK(get_ct_file_mode(ct)) ||
+ ct->staged_status == GOT_STATUS_DELETE ||
+ ct->status == GOT_STATUS_DELETE)
continue;
err = reinstall_symlink_after_commit(&is_bad_symlink,
blob - a537bcbfccf7f2f23f1ffd8cf0407deef0991edd
blob + 199eaf6bbf1859c535e340a5c5f30777378ba090
--- regress/cmdline/stage.sh
+++ regress/cmdline/stage.sh
diff -u $testroot/stdout.expected $testroot/stdout
fi
test_done "$testroot" "$ret"
+
+}
+
+function test_stage_symlink {
+ local testroot=`test_init stage_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 && git add .)
+ git_commit $testroot/repo -m "add symlinks"
+ local head_commit=`git_show_head $testroot/repo`
+
+ got checkout $testroot/repo $testroot/wt > /dev/null
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ (cd $testroot/wt && ln -sf beta alpha.link)
+ (cd $testroot/wt && ln -sfh gamma epsilon.link)
+ (cd $testroot/wt && ln -sf ../gamma/delta epsilon/beta.link)
+ echo 'this is regular file foo' > $testroot/wt/dotgotfoo.link
+ (cd $testroot/wt && got add dotgotfoo.link > /dev/null)
+ (cd $testroot/wt && ln -sf .got/bar dotgotbar.link)
+ (cd $testroot/wt && got add dotgotbar.link > /dev/null)
+ (cd $testroot/wt && got rm nonexistent.link > /dev/null)
+ (cd $testroot/wt && ln -sf gamma/delta zeta.link)
+ (cd $testroot/wt && got add zeta.link > /dev/null)
+
+ (cd $testroot/wt && got stage > $testroot/stdout)
+
+ cat > $testroot/stdout.expected <<EOF
+ M alpha.link
+ A dotgotbar.link
+ A dotgotfoo.link
+ M epsilon/beta.link
+ M epsilon.link
+ D nonexistent.link
+ A zeta.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
+
+ (cd $testroot/wt && got diff -s > $testroot/stdout)
+
+ echo "diff $head_commit $testroot/wt (staged changes)" \
+ > $testroot/stdout.expected
+ echo -n 'blob - ' >> $testroot/stdout.expected
+ got tree -r $testroot/repo -i | grep 'alpha.link@ -> alpha$' | \
+ cut -d' ' -f 1 >> $testroot/stdout.expected
+ echo -n 'blob + ' >> $testroot/stdout.expected
+ (cd $testroot/wt && got stage -l alpha.link) | cut -d' ' -f 1 \
+ >> $testroot/stdout.expected
+ echo '--- alpha.link' >> $testroot/stdout.expected
+ echo '+++ alpha.link' >> $testroot/stdout.expected
+ echo '@@ -1 +1 @@' >> $testroot/stdout.expected
+ echo '-alpha' >> $testroot/stdout.expected
+ echo '\ No newline at end of file' >> $testroot/stdout.expected
+ echo '+beta' >> $testroot/stdout.expected
+ echo '\ No newline at end of file' >> $testroot/stdout.expected
+ echo 'blob - /dev/null' >> $testroot/stdout.expected
+ echo -n 'blob + ' >> $testroot/stdout.expected
+ (cd $testroot/wt && got stage -l dotgotbar.link) | cut -d' ' -f 1 \
+ >> $testroot/stdout.expected
+ echo '--- /dev/null' >> $testroot/stdout.expected
+ echo '+++ dotgotbar.link' >> $testroot/stdout.expected
+ echo '@@ -0,0 +1 @@' >> $testroot/stdout.expected
+ echo '+.got/bar' >> $testroot/stdout.expected
+ echo '\ No newline at end of file' >> $testroot/stdout.expected
+ echo 'blob - /dev/null' >> $testroot/stdout.expected
+ echo -n 'blob + ' >> $testroot/stdout.expected
+ (cd $testroot/wt && got stage -l dotgotfoo.link) | cut -d' ' -f 1 \
+ >> $testroot/stdout.expected
+ echo '--- /dev/null' >> $testroot/stdout.expected
+ echo '+++ dotgotfoo.link' >> $testroot/stdout.expected
+ echo '@@ -0,0 +1 @@' >> $testroot/stdout.expected
+ echo '+this is regular file foo' >> $testroot/stdout.expected
+ echo -n 'blob - ' >> $testroot/stdout.expected
+ got tree -r $testroot/repo -i epsilon | grep 'beta.link@ -> ../beta$' | \
+ cut -d' ' -f 1 >> $testroot/stdout.expected
+ echo -n 'blob + ' >> $testroot/stdout.expected
+ (cd $testroot/wt && got stage -l epsilon/beta.link) | cut -d' ' -f 1 \
+ >> $testroot/stdout.expected
+ echo '--- epsilon/beta.link' >> $testroot/stdout.expected
+ echo '+++ epsilon/beta.link' >> $testroot/stdout.expected
+ echo '@@ -1 +1 @@' >> $testroot/stdout.expected
+ echo '-../beta' >> $testroot/stdout.expected
+ echo '\ No newline at end of file' >> $testroot/stdout.expected
+ echo '+../gamma/delta' >> $testroot/stdout.expected
+ echo '\ No newline at end of file' >> $testroot/stdout.expected
+ echo -n 'blob - ' >> $testroot/stdout.expected
+ got tree -r $testroot/repo -i | grep 'epsilon.link@ -> epsilon$' | \
+ cut -d' ' -f 1 >> $testroot/stdout.expected
+ echo -n 'blob + ' >> $testroot/stdout.expected
+ (cd $testroot/wt && got stage -l epsilon.link) | cut -d' ' -f 1 \
+ >> $testroot/stdout.expected
+ echo '--- epsilon.link' >> $testroot/stdout.expected
+ echo '+++ epsilon.link' >> $testroot/stdout.expected
+ echo '@@ -1 +1 @@' >> $testroot/stdout.expected
+ echo '-epsilon' >> $testroot/stdout.expected
+ echo '\ No newline at end of file' >> $testroot/stdout.expected
+ echo '+gamma' >> $testroot/stdout.expected
+ echo '\ No newline at end of file' >> $testroot/stdout.expected
+ echo -n 'blob - ' >> $testroot/stdout.expected
+ got tree -r $testroot/repo -i | grep 'nonexistent.link@ -> nonexistent$' | \
+ cut -d' ' -f 1 >> $testroot/stdout.expected
+ echo 'blob + /dev/null' >> $testroot/stdout.expected
+ echo '--- nonexistent.link' >> $testroot/stdout.expected
+ echo '+++ /dev/null' >> $testroot/stdout.expected
+ echo '@@ -1 +0,0 @@' >> $testroot/stdout.expected
+ echo '-nonexistent' >> $testroot/stdout.expected
+ echo '\ No newline at end of file' >> $testroot/stdout.expected
+ echo 'blob - /dev/null' >> $testroot/stdout.expected
+ echo -n 'blob + ' >> $testroot/stdout.expected
+ (cd $testroot/wt && got stage -l zeta.link) | cut -d' ' -f 1 \
+ >> $testroot/stdout.expected
+ echo '--- /dev/null' >> $testroot/stdout.expected
+ echo '+++ zeta.link' >> $testroot/stdout.expected
+ echo '@@ -0,0 +1 @@' >> $testroot/stdout.expected
+ echo '+gamma/delta' >> $testroot/stdout.expected
+ echo '\ No newline at end of file' >> $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
+
+ (cd $testroot/wt && got commit -m "staged symlink" \
+ > $testroot/stdout)
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ echo "got commit command failed unexpectedly" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+ local commit_id=`git_show_head $testroot/repo`
+ echo "A dotgotbar.link" > $testroot/stdout.expected
+ echo "A dotgotfoo.link" >> $testroot/stdout.expected
+ echo "A zeta.link" >> $testroot/stdout.expected
+ echo "M alpha.link" >> $testroot/stdout.expected
+ echo "M epsilon/beta.link" >> $testroot/stdout.expected
+ echo "M epsilon.link" >> $testroot/stdout.expected
+ echo "D nonexistent.link" >> $testroot/stdout.expected
+ echo "Created commit $commit_id" >> $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
+
+ got tree -r $testroot/repo -c $commit_id > $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ echo "got tree command failed unexpectedly" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ cat > $testroot/stdout.expected <<EOF
+alpha
+alpha.link@ -> beta
+beta
+dotgotbar.link@ -> .got/bar
+dotgotfoo.link
+epsilon/
+epsilon.link@ -> gamma
+gamma/
+passwd.link@ -> /etc/passwd
+zeta.link@ -> gamma/delta
+EOF
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ 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 "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
+
+ if [ -h $testroot/wt/dotgotbar.link ]; then
+ echo "dotgotbar.link is a symlink"
+ test_done "$testroot" "1"
+ return 1
+ fi
+ echo -n ".got/bar" >> $testroot/content.expected
+ cp $testroot/wt/dotgotbar.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
+
+ if [ -h $testroot/wt/dotgotfoo.link ]; then
+ echo "dotgotfoo.link is a symlink"
+ test_done "$testroot" "1"
+ return 1
+ fi
+ echo "this is regular file 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
+ 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 "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
+
+ if [ -h $testroot/wt/passwd.link ]; then
+ echo "passwd.link is a symlink"
+ 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
+
+ if ! [ -h $testroot/wt/zeta.link ]; then
+ echo "zeta.link is not a symlink"
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ readlink $testroot/wt/zeta.link > $testroot/stdout
+ echo "gamma/delta" > $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
+
+ test_done "$testroot" "0"
}
run_test test_stage_basic
run_test test_stage_patch_removed_twice
run_test test_stage_patch_quit
run_test test_stage_patch_incomplete_script
+run_test test_stage_symlink