Commit 75f0a0fb346fb0ad381536024728164cd32d2a7e

Stefan Sperling 2020-07-23T14:22:39

stop reinstalling symlinks after commit; 'got update' can handle that

diff --git a/lib/worktree.c b/lib/worktree.c
index bf1f2be..4975303 100644
--- a/lib/worktree.c
+++ b/lib/worktree.c
@@ -5139,128 +5139,6 @@ done:
 }
 
 static const struct got_error *
-reinstall_symlink_after_commit(int *is_bad_symlink, struct got_commitable *ct,
-    struct got_object_id *new_base_commit_id, struct got_worktree *worktree,
-    struct got_fileindex_entry *ie, struct got_repository *repo)
-{
-	const struct got_error *err = NULL;
-	struct got_blob_object *blob = NULL;
-	struct got_object_id *tree_id = NULL;
-	char *tree_path = NULL;
-	struct got_tree_object *tree = NULL;
-	struct got_tree_entry *te;
-	char *entry_name;
-	unsigned char status;
-	struct stat sb;
-
-	err = get_file_status(&status, &sb, ie, ct->ondisk_path,
-	    -1, NULL, repo);
-	if (err)
-		return err;
-	if (status != GOT_STATUS_NO_CHANGE)
-		return NULL;
-
-	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) {
-		if (err->code != GOT_ERR_BAD_PATH)
-			goto done;
-		err = got_object_id_by_path(&tree_id, repo,
-		    new_base_commit_id, "");
-		if (err)
-			goto done;
-	} else {
-		err = got_object_id_by_path(&tree_id, repo,
-		    new_base_commit_id, tree_path);
-		if (err)
-			goto done;
-	}
-
-	err = got_object_open_as_tree(&tree, repo, tree_id);
-	if (err)
-		goto done;
-
-	entry_name = basename(ct->path);
-	if (entry_name == NULL) {
-		err = got_error_from_errno2("basename", ct->path);
-		goto done;
-	}
-
-	te = got_object_tree_find_entry(tree, entry_name);
-	if (te == NULL) {
-		err = got_error_path(ct->path, GOT_ERR_NO_TREE_ENTRY);
-		goto done;
-	}
-
-	err = install_symlink(is_bad_symlink, worktree, ct->ondisk_path,
-	    ct->path, blob, 0, 0, 0, repo, NULL, NULL);
-done:
-	if (blob)
-		got_object_blob_close(blob);
-	if (tree)
-		got_object_tree_close(tree);
-	free(tree_id);
-	free(tree_path);
-	return err;
-}
-
-/*
- * After comitting a symlink we have a chance to convert "bad" symlinks
- * (those which point outside the work tree or into .got) to regular files.
- * This way, the post-commit work tree state matches a fresh checkout of
- * the tree which was just committed. We also mark such newly committed
- * symlinks as "bad" in the work tree's fileindex.
- */
-static const struct got_error *
-reinstall_symlinks_after_commit(struct got_pathlist_head *commitable_paths,
-    struct got_object_id *new_base_commit_id, struct got_fileindex *fileindex,
-    struct got_worktree *worktree, struct got_repository *repo)
-{
-	const struct got_error *err = NULL;
-	struct got_pathlist_entry *pe;
-
-	TAILQ_FOREACH(pe, commitable_paths, entry) {
-		struct got_commitable *ct = pe->data;
-		struct got_fileindex_entry *ie;
-		int is_bad_symlink = 0;
-	
-		if (!S_ISLNK(get_ct_file_mode(ct)) ||
-		    ct->staged_status == GOT_STATUS_DELETE ||
-		    ct->status == GOT_STATUS_DELETE)
-			continue;
-
-		ie = got_fileindex_entry_get(fileindex, ct->path,
-		    strlen(ct->path));
-		if (ie == NULL) {
-			err = got_error_path(ct->path, GOT_ERR_BAD_PATH);
-			break;
-		}
-		err = reinstall_symlink_after_commit(&is_bad_symlink,
-		    ct, new_base_commit_id, worktree, ie, repo);
-		if (err)
-			break;
-		if (ie && is_bad_symlink) {
-			got_fileindex_entry_filetype_set(ie,
-			    GOT_FILEIDX_MODE_BAD_SYMLINK);
-		}
-	}
-
-	return err;
-}
-
-static const struct got_error *
 update_fileindex_after_commit(struct got_pathlist_head *commitable_paths,
     struct got_object_id *new_base_commit_id, struct got_fileindex *fileindex,
     int have_staged_files)
@@ -5639,10 +5517,6 @@ got_worktree_commit(struct got_object_id **new_commit_id,
 
 	err = update_fileindex_after_commit(&commitable_paths, *new_commit_id,
 	    fileindex, have_staged_files);
-	if (err == NULL) {
-		err = reinstall_symlinks_after_commit(&commitable_paths,
-		    *new_commit_id, fileindex, worktree, repo);
-	}
 	sync_err = sync_fileindex(fileindex, fileindex_path);
 	if (sync_err && err == NULL)
 		err = sync_err;
diff --git a/regress/cmdline/commit.sh b/regress/cmdline/commit.sh
index 1f478a3..b877e38 100755
--- a/regress/cmdline/commit.sh
+++ b/regress/cmdline/commit.sh
@@ -1044,7 +1044,14 @@ function test_commit_symlink {
 		return 1
 	fi
 
-	# verify post-commit work tree state matches a fresh checkout
+	if ! [ -h $testroot/wt/passwd.link ]; then
+		echo 'passwd.link is not a symlink' >&2
+		test_done "$testroot" 1
+		return 1
+	fi
+
+	# 'got update' should reinstall passwd.link as a regular file
+	(cd $testroot/wt && got update > /dev/null)
 	check_symlinks $testroot/wt
 	ret="$?"
 	if [ "$ret" != "0" ]; then
@@ -1142,6 +1149,12 @@ function test_commit_fix_bad_symlink {
 	(cd $testroot/wt && got commit -S -m 'commit bad symlink' \
 		> $testroot/stdout)
 
+	if ! [ -h $testroot/wt/passwd.link ]; then
+		echo 'passwd.link is not a symlink' >&2
+		test_done "$testroot" 1
+		return 1
+	fi
+	(cd $testroot/wt && got update >/dev/null)
 	if [ -h $testroot/wt/passwd.link ]; then
 		echo "passwd.link is a symlink but should be a regular file" >&2
 		test_done "$testroot" "1"
diff --git a/regress/cmdline/stage.sh b/regress/cmdline/stage.sh
index 90792ac..21af589 100755
--- a/regress/cmdline/stage.sh
+++ b/regress/cmdline/stage.sh
@@ -2579,6 +2579,12 @@ EOF
 		return 1
 	fi
 
+	if [ ! -h $testroot/wt/dotgotbar.link ]; then
+		echo "dotgotbar.link is not a symlink"
+		test_done "$testroot" "1"
+		return 1
+	fi
+	(cd $testroot/wt && got update > /dev/null)
 	if [ -h $testroot/wt/dotgotbar.link ]; then
 		echo "dotgotbar.link is a symlink"
 		test_done "$testroot" "1"