Commit Diff


commit - e9b3576faf75d4564e5ed585837da4482e6a9c26
commit + 708d8e672e598275721ee0e9707e5bea2b0435b4
blob - 5d07d5a5961de07dae868ca1e72e47e990d7620d
blob + 442288387b7a34120e7bba5f27c9f45dbfc31768
--- lib/worktree.c
+++ lib/worktree.c
@@ -1188,6 +1188,38 @@ remove_ondisk_file(const char *root_path, const char *
 	return err;
 }
 
+static const struct got_error *
+delete_blob(struct got_worktree *worktree, struct got_fileindex *fileindex,
+    struct got_fileindex_entry *ie, const char *parent_path,
+    struct got_repository *repo,
+    got_worktree_checkout_cb progress_cb, void *progress_arg,
+    got_worktree_cancel_cb cancel_cb, void *cancel_arg)
+{
+	const struct got_error *err;
+	unsigned char status;
+	struct stat sb;
+	char *ondisk_path;
+
+	if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, ie->path)
+	    == -1)
+		return got_error_from_errno();
+
+	err = get_file_status(&status, &sb, ie, ondisk_path, repo);
+	if (err)
+		return err;
+
+	(*progress_cb)(progress_arg, GOT_STATUS_DELETE, ie->path);
+
+	if (status == GOT_STATUS_NO_CHANGE) {
+		err = remove_ondisk_file(worktree->root_path, ie->path);
+		if (err)
+			return err;
+	}
+
+	got_fileindex_entry_remove(fileindex, ie);
+	return NULL;
+}
+
 struct diff_cb_arg {
     struct got_fileindex *fileindex;
     struct got_worktree *worktree;
@@ -1212,16 +1244,11 @@ diff_old_new(void *arg, struct got_fileindex_entry *ie
 static const struct got_error *
 diff_old(void *arg, struct got_fileindex_entry *ie, const char *parent_path)
 {
-	const struct got_error *err;
 	struct diff_cb_arg *a = arg;
 
-	(*a->progress_cb)(a->progress_arg, GOT_STATUS_DELETE, ie->path);
-
-	err = remove_ondisk_file(a->worktree->root_path, ie->path);
-	if (err)
-		return err;
-	got_fileindex_entry_remove(a->fileindex, ie);
-	return NULL;
+	return delete_blob(a->worktree, a->fileindex, ie, parent_path,
+	    a->repo, a->progress_cb, a->progress_arg,
+	    a->cancel_cb, a->cancel_arg);
 }
 
 static const struct got_error *
blob - bd9f958e79f52fe03a9add930fabbdca8726c8cd
blob + a05ab91111b4dc3478db7c579fed501b845d275f
--- regress/cmdline/update.sh
+++ regress/cmdline/update.sh
@@ -908,7 +908,59 @@ function test_update_conflict_add_vs_add {
 	fi
 	test_done "$testroot" "$ret"
 }
+
+function test_update_conflict_local_edit_vs_rm {
+	local testroot=`test_init update_conflict_local_edit_vs_rm`
+
+	got checkout $testroot/repo $testroot/wt > /dev/null
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	(cd $testroot/repo && git rm -q beta)
+	git_commit $testroot/repo -m "removing a file"
+
+	echo "modified beta" > $testroot/wt/beta
 
+	(cd $testroot/wt && got update > $testroot/stdout)
+
+	echo "D  beta" > $testroot/stdout.expected
+	echo -n "Updated to commit " >> $testroot/stdout.expected
+	git_show_head $testroot/repo >> $testroot/stdout.expected
+	echo >> $testroot/stdout.expected
+	cmp $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	echo "modified beta" > $testroot/content.expected
+
+	cat $testroot/wt/beta > $testroot/content
+
+	cmp $testroot/content.expected $testroot/content
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/content.expected $testroot/content
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	# beta is now an unversioned file... we don't flag tree conflicts yet
+	echo '?  beta' > $testroot/stdout.expected
+	(cd $testroot/wt && got status > $testroot/stdout)
+	cmp $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+	fi
+	test_done "$testroot" "$ret"
+}
+
 run_test test_update_basic
 run_test test_update_adds_file
 run_test test_update_deletes_file
@@ -927,3 +979,4 @@ run_test test_update_keeps_xbit
 run_test test_update_clears_xbit
 run_test test_update_restores_missing_file
 run_test test_update_conflict_add_vs_add
+run_test test_update_conflict_local_edit_vs_rm