Commit 2b92fad7804791e1a20f46acf637ff4c40470e50

Stefan Sperling 2019-06-02T17:52:19

test and fix expected file status after 'got cherrypick'

diff --git a/got/got.1 b/got/got.1
index b8cd1a3..c120894 100644
--- a/got/got.1
+++ b/got/got.1
@@ -389,7 +389,9 @@ Show the status of each affected file, using the following status codes:
 .It C Ta file was merged and conflicts occurred during merge
 .It ! Ta changes destined for a missing file were not merged
 .It D Ta file was deleted
+.It d Ta file's deletion was obstructed by local modifications
 .It A Ta new file was added
+.It ~ Ta changes destined for a non-regular file were not merged
 .El
 .Pp
 The merged changes will appear as local changes in the work tree, which
diff --git a/include/got_worktree.h b/include/got_worktree.h
index 1174e67..5dbd069 100644
--- a/include/got_worktree.h
+++ b/include/got_worktree.h
@@ -30,6 +30,7 @@ struct got_commitable;
 #define GOT_STATUS_UNVERSIONED	'?'
 #define GOT_STATUS_OBSTRUCTED	'~'
 #define GOT_STATUS_REVERT	'R'
+#define GOT_STATUS_CANNOT_DELETE 'd'
 
 /*
  * Attempt to initialize a new work tree on disk.
diff --git a/lib/worktree.c b/lib/worktree.c
index bf46d7c..fdfbe63 100644
--- a/lib/worktree.c
+++ b/lib/worktree.c
@@ -1730,8 +1730,44 @@ merge_file_cb(void *arg, struct got_blob_object *blob1,
 			    path2);
 			return NULL;
 		}
-		err = delete_blob(a->worktree, a->fileindex, ie, repo,
-		    a->progress_cb, a->progress_arg);
+
+		if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
+		    path1) == -1)
+			return got_error_from_errno("asprintf");
+
+		err = get_file_status(&status, &sb, ie, ondisk_path, repo);
+		if (err)
+			goto done;
+
+		switch (status) {
+		case GOT_STATUS_NO_CHANGE:
+			(*a->progress_cb)(a->progress_arg, GOT_STATUS_DELETE,
+			    path1);
+			err = remove_ondisk_file(a->worktree->root_path, path1);
+			if (err)
+				goto done;
+			if (ie)
+				got_fileindex_entry_mark_deleted_from_disk(ie);
+			break;
+		case GOT_STATUS_DELETE:
+		case GOT_STATUS_MISSING:
+			(*a->progress_cb)(a->progress_arg, GOT_STATUS_DELETE,
+			    path1);
+			if (ie)
+				got_fileindex_entry_mark_deleted_from_disk(ie);
+			break;
+		case GOT_STATUS_ADD:
+		case GOT_STATUS_MODIFY:
+		case GOT_STATUS_CONFLICT:
+			(*a->progress_cb)(a->progress_arg,
+			    GOT_STATUS_CANNOT_DELETE, path1);
+			break;
+		case GOT_STATUS_OBSTRUCTED:
+			(*a->progress_cb)(a->progress_arg, status, path1);
+			break;
+		default:
+			break;
+		}
 	} else if (blob2) {
 		if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
 		    path2) == -1)
@@ -1769,11 +1805,15 @@ merge_file_cb(void *arg, struct got_blob_object *blob1,
 			    a->progress_cb, a->progress_arg);
 			if (err)
 				goto done;
-
-			err = update_blob_fileindex_entry(a->worktree,
-			    a->fileindex, NULL, ondisk_path, path2, blob2, 0);
+			err = got_fileindex_entry_alloc(&ie,
+			    ondisk_path, path2, NULL, NULL);
 			if (err)
 				goto done;
+			err = got_fileindex_entry_add(a->fileindex, ie);
+			if (err) {
+				got_fileindex_entry_free(ie);
+				goto done;
+			}
 		}
 	}
 done:
diff --git a/regress/cmdline/cherrypick.sh b/regress/cmdline/cherrypick.sh
index 8dca338..4aa318f 100755
--- a/regress/cmdline/cherrypick.sh
+++ b/regress/cmdline/cherrypick.sh
@@ -79,6 +79,17 @@ function test_cherrypick_basic {
 		return 1
 	fi
 
+	echo 'M  alpha' > $testroot/stdout.expected
+	echo 'D  beta' >> $testroot/stdout.expected
+	echo 'A  epsilon/new' >> $testroot/stdout.expected
+
+	(cd $testroot/wt && got status > $testroot/stdout)
+
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+	fi
 	test_done "$testroot" "$ret"
 }