Commit Diff


commit - f5a17245fd8503e5cd7c2d1dd464c8a435e83463
commit + 14c901f1f8f27565b91c2e8a74939c74250d8521
blob - 56705cf058d3318856aad68700fbc380ab11e23d
blob + 04dedb5234881a9d6726e1e8da27d6eb707ceaaa
--- lib/worktree.c
+++ lib/worktree.c
@@ -719,24 +719,21 @@ done:
 
 /*
  * Perform a 3-way merge where blob_orig acts as the common ancestor,
- * blob_deriv acts as the first derived version, and the file on disk
- * acts as the second derived version.
+ * the file at deriv_path acts as the first derived version, and the
+ * file on disk acts as the second derived version.
  */
 static const struct got_error *
-merge_blob(int *local_changes_subsumed, struct got_worktree *worktree,
+merge_file(int *local_changes_subsumed, struct got_worktree *worktree,
     struct got_blob_object *blob_orig, const char *ondisk_path,
-    const char *path, uint16_t st_mode, struct got_blob_object *blob_deriv,
-    struct got_object_id *deriv_base_commit_id,
-    struct got_repository *repo, got_worktree_checkout_cb progress_cb,
-    void *progress_arg)
+    const char *path, uint16_t st_mode, const char *deriv_path,
+    const char *label_deriv, struct got_repository *repo,
+    got_worktree_checkout_cb progress_cb, void *progress_arg)
 {
 	const struct got_error *err = NULL;
 	int merged_fd = -1;
-	FILE *f_deriv = NULL, *f_orig = NULL;
-	char *blob_deriv_path = NULL, *blob_orig_path = NULL;
+	FILE *f_orig = NULL;
+	char *blob_orig_path = NULL;
 	char *merged_path = NULL, *base_path = NULL;
-	char *id_str = NULL;
-	char *label_deriv = NULL;
 	int overlapcnt = 0;
 	char *parent;
 
@@ -750,23 +747,8 @@ merge_blob(int *local_changes_subsumed, struct got_wor
 		return got_error_from_errno("asprintf");
 
 	err = got_opentemp_named_fd(&merged_path, &merged_fd, base_path);
-	if (err)
-		goto done;
-
-	free(base_path);
-	if (asprintf(&base_path, "%s/got-merge-blob-deriv", parent) == -1) {
-		err = got_error_from_errno("asprintf");
-		base_path = NULL;
-		goto done;
-	}
-
-	err = got_opentemp_named(&blob_deriv_path, &f_deriv, base_path);
 	if (err)
 		goto done;
-	err = got_object_blob_dump_to_file(NULL, NULL, NULL, f_deriv,
-	    blob_deriv);
-	if (err)
-		goto done;
 
 	free(base_path);
 	if (asprintf(&base_path, "%s/got-merge-blob-orig", parent) == -1) {
@@ -791,15 +773,7 @@ merge_blob(int *local_changes_subsumed, struct got_wor
 		 */
 	}
 
-	err = got_object_id_str(&id_str, deriv_base_commit_id);
-	if (err)
-		goto done;
-	if (asprintf(&label_deriv, "commit %s", id_str) == -1) {
-		err = got_error_from_errno("asprintf");
-		goto done;
-	}
-
-	err = got_merge_diff3(&overlapcnt, merged_fd, blob_deriv_path,
+	err = got_merge_diff3(&overlapcnt, merged_fd, deriv_path,
 	    blob_orig_path, ondisk_path, label_deriv, path);
 	if (err)
 		goto done;
@@ -816,7 +790,7 @@ merge_blob(int *local_changes_subsumed, struct got_wor
 
 	/* Check if a clean merge has subsumed all local changes. */
 	if (overlapcnt == 0) {
-		err = check_files_equal(local_changes_subsumed, blob_deriv_path,
+		err = check_files_equal(local_changes_subsumed, deriv_path,
 		    merged_path);
 		if (err)
 			goto done;
@@ -837,20 +811,75 @@ merge_blob(int *local_changes_subsumed, struct got_wor
 done:
 	if (merged_fd != -1 && close(merged_fd) != 0 && err == NULL)
 		err = got_error_from_errno("close");
-	if (f_deriv && fclose(f_deriv) != 0 && err == NULL)
-		err = got_error_from_errno("fclose");
 	if (f_orig && fclose(f_orig) != 0 && err == NULL)
 		err = got_error_from_errno("fclose");
 	free(merged_path);
 	free(base_path);
-	if (blob_deriv_path) {
-		unlink(blob_deriv_path);
-		free(blob_deriv_path);
-	}
 	if (blob_orig_path) {
 		unlink(blob_orig_path);
 		free(blob_orig_path);
 	}
+	return err;
+}
+
+/*
+ * Perform a 3-way merge where blob_orig acts as the common ancestor,
+ * blob_deriv acts as the first derived version, and the file on disk
+ * acts as the second derived version.
+ */
+static const struct got_error *
+merge_blob(int *local_changes_subsumed, struct got_worktree *worktree,
+    struct got_blob_object *blob_orig, const char *ondisk_path,
+    const char *path, uint16_t st_mode, struct got_blob_object *blob_deriv,
+    struct got_object_id *deriv_base_commit_id,
+    struct got_repository *repo, got_worktree_checkout_cb progress_cb,
+    void *progress_arg)
+{
+	const struct got_error *err = NULL;
+	FILE *f_deriv = NULL;
+	char *blob_deriv_path = NULL, *base_path = NULL, *id_str = NULL;
+	char *label_deriv = NULL, *parent;
+
+	*local_changes_subsumed = 0;
+
+	parent = dirname(ondisk_path);
+	if (parent == NULL)
+		return got_error_from_errno2("dirname", ondisk_path);
+
+	free(base_path);
+	if (asprintf(&base_path, "%s/got-merge-blob-deriv", parent) == -1) {
+		err = got_error_from_errno("asprintf");
+		base_path = NULL;
+		goto done;
+	}
+
+	err = got_opentemp_named(&blob_deriv_path, &f_deriv, base_path);
+	if (err)
+		goto done;
+	err = got_object_blob_dump_to_file(NULL, NULL, NULL, f_deriv,
+	    blob_deriv);
+	if (err)
+		goto done;
+
+	err = got_object_id_str(&id_str, deriv_base_commit_id);
+	if (err)
+		goto done;
+	if (asprintf(&label_deriv, "commit %s", id_str) == -1) {
+		err = got_error_from_errno("asprintf");
+		goto done;
+	}
+
+	err = merge_file(local_changes_subsumed, worktree, blob_orig,
+	    ondisk_path, path, st_mode, blob_deriv_path, label_deriv,
+	    repo, progress_cb, progress_arg);
+done:
+	if (f_deriv && fclose(f_deriv) != 0 && err == NULL)
+		err = got_error_from_errno("fclose");
+	free(base_path);
+	if (blob_deriv_path) {
+		unlink(blob_deriv_path);
+		free(blob_deriv_path);
+	}
 	free(id_str);
 	free(label_deriv);
 	return err;