Commit Diff


commit - b2c50a0a51e3a8e22fb1e9867cbf6bc7356acbd3
commit + 3e3a69f1a29c6322b5464dca5023d8766661d7bf
blob - d826f0a1b82911906aa324cfb67c46858b054fdc
blob + f267e721b6b581f74d68a80a860a0b837ada803a
--- got/got.c
+++ got/got.c
@@ -3598,18 +3598,19 @@ rebase_progress(void *arg, unsigned char status, const
 }
 
 static const struct got_error *
-rebase_complete(struct got_worktree *worktree, struct got_reference *branch,
-    struct got_reference *new_base_branch, struct got_reference *tmp_branch,
-    struct got_repository *repo)
+rebase_complete(struct got_worktree *worktree, struct got_fileindex *fileindex,
+    struct got_reference *branch, struct got_reference *new_base_branch,
+    struct got_reference *tmp_branch, struct got_repository *repo)
 {
 	printf("Switching work tree to %s\n", got_ref_get_name(branch));
-	return got_worktree_rebase_complete(worktree,
+	return got_worktree_rebase_complete(worktree, fileindex,
 	    new_base_branch, tmp_branch, branch, repo);
 }
 
 static const struct got_error *
 rebase_commit(struct got_pathlist_head *merged_paths,
-    struct got_worktree *worktree, struct got_reference *tmp_branch,
+    struct got_worktree *worktree, struct got_fileindex *fileindex,
+    struct got_reference *tmp_branch,
     struct got_object_id *commit_id, struct got_repository *repo)
 {
 	const struct got_error *error;
@@ -3621,7 +3622,7 @@ rebase_commit(struct got_pathlist_head *merged_paths,
 		return error;
 
 	error = got_worktree_rebase_commit(&new_commit_id, merged_paths,
-	    worktree, tmp_branch, commit, commit_id, repo);
+	    worktree, fileindex, tmp_branch, commit, commit_id, repo);
 	if (error) {
 		if (error->code != GOT_ERR_COMMIT_NO_CHANGES)
 			goto done;
@@ -3764,6 +3765,7 @@ cmd_rebase(int argc, char *argv[])
 	const struct got_error *error = NULL;
 	struct got_worktree *worktree = NULL;
 	struct got_repository *repo = NULL;
+	struct got_fileindex *fileindex = NULL;
 	char *cwd = NULL;
 	struct got_reference *branch = NULL;
 	struct got_reference *new_base_branch = NULL, *tmp_branch = NULL;
@@ -3840,12 +3842,13 @@ cmd_rebase(int argc, char *argv[])
 			goto done;
 		}
 		error = got_worktree_rebase_continue(&resume_commit_id,
-		    &new_base_branch, &tmp_branch, &branch, worktree, repo);
+		    &new_base_branch, &tmp_branch, &branch, &fileindex,
+		    worktree, repo);
 		if (error)
 			goto done;
 		printf("Switching work tree to %s\n",
 		    got_ref_get_symref_target(new_base_branch));
-		error = got_worktree_rebase_abort(worktree, repo,
+		error = got_worktree_rebase_abort(worktree, fileindex, repo,
 		    new_base_branch, update_progress, &did_something);
 		if (error)
 			goto done;
@@ -3859,11 +3862,12 @@ cmd_rebase(int argc, char *argv[])
 			goto done;
 		}
 		error = got_worktree_rebase_continue(&resume_commit_id,
-		    &new_base_branch, &tmp_branch, &branch, worktree, repo);
+		    &new_base_branch, &tmp_branch, &branch, &fileindex,
+		    worktree, repo);
 		if (error)
 			goto done;
 
-		error = rebase_commit(NULL, worktree, tmp_branch,
+		error = rebase_commit(NULL, worktree, fileindex, tmp_branch,
 		    resume_commit_id, repo);
 		if (error)
 			goto done;
@@ -3910,7 +3914,7 @@ cmd_rebase(int argc, char *argv[])
 		}
 
 		error = got_worktree_rebase_prepare(&new_base_branch,
-		    &tmp_branch, worktree, branch, repo);
+		    &tmp_branch, &fileindex, worktree, branch, repo);
 		if (error)
 			goto done;
 	}
@@ -3932,8 +3936,8 @@ cmd_rebase(int argc, char *argv[])
 
 	if (SIMPLEQ_EMPTY(&commits)) {
 		if (continue_rebase)
-			error = rebase_complete(worktree, branch,
-			    new_base_branch, tmp_branch, repo);
+			error = rebase_complete(worktree, fileindex,
+			    branch, new_base_branch, tmp_branch, repo);
 		else
 			error = got_error(GOT_ERR_EMPTY_REBASE);
 		goto done;
@@ -3946,8 +3950,8 @@ cmd_rebase(int argc, char *argv[])
 		pid = qid;
 
 		error = got_worktree_rebase_merge_files(&merged_paths,
-		    worktree, parent_id, commit_id, repo, rebase_progress,
-		    &rebase_status, check_cancelled, NULL);
+		    worktree, fileindex, parent_id, commit_id, repo,
+		    rebase_progress, &rebase_status, check_cancelled, NULL);
 		if (error)
 			goto done;
 
@@ -3956,22 +3960,22 @@ cmd_rebase(int argc, char *argv[])
 			break;
 		}
 
-		error = rebase_commit(&merged_paths, worktree, tmp_branch,
-		    commit_id, repo);
+		error = rebase_commit(&merged_paths, worktree, fileindex,
+		    tmp_branch, commit_id, repo);
 		got_worktree_rebase_pathlist_free(&merged_paths);
 		if (error)
 			goto done;
 	}
 
 	if (rebase_status == GOT_STATUS_CONFLICT) {
-		error = got_worktree_rebase_postpone(worktree);
+		error = got_worktree_rebase_postpone(worktree, fileindex);
 		if (error)
 			goto done;
 		error = got_error_msg(GOT_ERR_CONFLICTS,
 		    "conflicts must be resolved before rebasing can continue");
 	} else
-		error = rebase_complete(worktree, branch, new_base_branch,
-		    tmp_branch, repo);
+		error = rebase_complete(worktree, fileindex, branch,
+		    new_base_branch, tmp_branch, repo);
 done:
 	got_object_id_queue_free(&commits);
 	free(branch_head_commit_id);
@@ -4520,13 +4524,13 @@ histedit_edit_list_retry(struct got_histedit_list *his
 
 static const struct got_error *
 histedit_complete(struct got_worktree *worktree,
-    struct got_reference *tmp_branch, struct got_reference *branch,
-    struct got_repository *repo)
+    struct got_fileindex *fileindex, struct got_reference *tmp_branch,
+    struct got_reference *branch, struct got_repository *repo)
 {
 	printf("Switching work tree to %s\n",
 	    got_ref_get_symref_target(branch));
-	return got_worktree_histedit_complete(worktree, tmp_branch, branch,
-	    repo);
+	return got_worktree_histedit_complete(worktree, fileindex, tmp_branch,
+	    branch, repo);
 }
 
 static const struct got_error *
@@ -4586,8 +4590,9 @@ done:
 
 static const struct got_error *
 histedit_commit(struct got_pathlist_head *merged_paths,
-    struct got_worktree *worktree, struct got_reference *tmp_branch,
-    struct got_histedit_list_entry *hle, struct got_repository *repo)
+    struct got_worktree *worktree, struct got_fileindex *fileindex,
+    struct got_reference *tmp_branch, struct got_histedit_list_entry *hle,
+    struct got_repository *repo)
 {
 	const struct got_error *err;
 	struct got_commit_object *commit;
@@ -4605,7 +4610,8 @@ histedit_commit(struct got_pathlist_head *merged_paths
 		return err;
 
 	err = got_worktree_histedit_commit(&new_commit_id, merged_paths,
-	    worktree, tmp_branch, commit, hle->commit_id, hle->logmsg, repo);
+	    worktree, fileindex, tmp_branch, commit, hle->commit_id,
+	    hle->logmsg, repo);
 	if (err) {
 		if (err->code != GOT_ERR_COMMIT_NO_CHANGES)
 			goto done;
@@ -4681,6 +4687,7 @@ cmd_histedit(int argc, char *argv[])
 {
 	const struct got_error *error = NULL;
 	struct got_worktree *worktree = NULL;
+	struct got_fileindex *fileindex = NULL;
 	struct got_repository *repo = NULL;
 	char *cwd = NULL;
 	struct got_reference *branch = NULL;
@@ -4771,12 +4778,13 @@ cmd_histedit(int argc, char *argv[])
 	if (edit_in_progress && abort_edit) {
 		int did_something;
 		error = got_worktree_histedit_continue(&resume_commit_id,
-		    &tmp_branch, &branch, &base_commit_id, worktree, repo);
+		    &tmp_branch, &branch, &base_commit_id, &fileindex,
+		    worktree, repo);
 		if (error)
 			goto done;
 		printf("Switching work tree to %s\n",
 		    got_ref_get_symref_target(branch));
-		error = got_worktree_histedit_abort(worktree, repo,
+		error = got_worktree_histedit_abort(worktree, fileindex, repo,
 		    branch, base_commit_id, update_progress, &did_something);
 		if (error)
 			goto done;
@@ -4806,7 +4814,8 @@ cmd_histedit(int argc, char *argv[])
 			goto done;
 
 		error = got_worktree_histedit_continue(&resume_commit_id,
-		    &tmp_branch, &branch, &base_commit_id, worktree, repo);
+		    &tmp_branch, &branch, &base_commit_id, &fileindex,
+		    worktree, repo);
 		if (error)
 			goto done;
 
@@ -4884,7 +4893,7 @@ cmd_histedit(int argc, char *argv[])
 			goto done;
 
 		error = got_worktree_histedit_prepare(&tmp_branch, &branch,
-		    &base_commit_id, worktree, repo);
+		    &base_commit_id, &fileindex, worktree, repo);
 		if (error)
 			goto done;
 
@@ -4907,7 +4916,7 @@ cmd_histedit(int argc, char *argv[])
 				   repo);
 			} else {
 				error = histedit_commit(NULL, worktree,
-				    tmp_branch, hle, repo);
+				    fileindex, tmp_branch, hle, repo);
 			}
 			if (error)
 				goto done;
@@ -4929,8 +4938,8 @@ cmd_histedit(int argc, char *argv[])
 		pid = SIMPLEQ_FIRST(parent_ids);
 
 		error = got_worktree_histedit_merge_files(&merged_paths,
-		    worktree, pid->id, hle->commit_id, repo, rebase_progress,
-		    &rebase_status, check_cancelled, NULL);
+		    worktree, fileindex, pid->id, hle->commit_id, repo,
+		    rebase_progress, &rebase_status, check_cancelled, NULL);
 		if (error)
 			goto done;
 		got_object_commit_close(commit);
@@ -4950,7 +4959,8 @@ cmd_histedit(int argc, char *argv[])
 			    id_str);
 			free(id_str);
 			got_worktree_rebase_pathlist_free(&merged_paths);
-			error = got_worktree_histedit_postpone(worktree);
+			error = got_worktree_histedit_postpone(worktree,
+			    fileindex);
 			goto done;
 		}
 
@@ -4961,21 +4971,22 @@ cmd_histedit(int argc, char *argv[])
 			continue;
 		}
 
-		error = histedit_commit(&merged_paths, worktree, tmp_branch,
-		    hle, repo);
+		error = histedit_commit(&merged_paths, worktree, fileindex,
+		    tmp_branch, hle, repo);
 		got_worktree_rebase_pathlist_free(&merged_paths);
 		if (error)
 			goto done;
 	}
 
 	if (rebase_status == GOT_STATUS_CONFLICT) {
-		error = got_worktree_histedit_postpone(worktree);
+		error = got_worktree_histedit_postpone(worktree, fileindex);
 		if (error)
 			goto done;
 		error = got_error_msg(GOT_ERR_CONFLICTS,
 		    "conflicts must be resolved before rebasing can continue");
 	} else
-		error = histedit_complete(worktree, tmp_branch, branch, repo);
+		error = histedit_complete(worktree, fileindex, tmp_branch,
+		    branch, repo);
 done:
 	got_object_id_queue_free(&commits);
 	free(head_commit_id);
blob - 6e6d2f53d8d2d5dd4b9b32075806433ee2a4cb49
blob + e9f5a6c90d4b5185ce58d45c93a4c57a850306a3
--- include/got_worktree.h
+++ include/got_worktree.h
@@ -17,6 +17,7 @@
 struct got_worktree;
 struct got_commitable;
 struct got_commit_object;
+struct got_fileindex;
 
 /* status codes */
 #define GOT_STATUS_NO_CHANGE	' '
@@ -218,20 +219,24 @@ unsigned int got_commitable_get_status(struct got_comm
  * "got/worktree/rebase/" namespace. These references are used to
  * keep track of rebase operation state and are used as input and/or
  * output arguments with other rebase-related functions.
+ * The function also returns a pointer to a fileindex which must be
+ * passed back to other rebase-related functions.
  */
 const struct got_error *got_worktree_rebase_prepare(struct got_reference **,
-    struct got_reference **, struct got_worktree *, struct got_reference *,
-    struct got_repository *);
+    struct got_reference **, struct got_fileindex **, struct got_worktree *,
+    struct got_reference *, struct got_repository *);
 
 /*
  * Continue an interrupted rebase operation.
  * This function returns existing references created when rebase was prepared,
  * and the ID of the commit currently being rebased. This should be called
  * before either resuming or aborting a rebase operation.
+ * The function also returns a pointer to a fileindex which must be
+ * passed back to other rebase-related functions.
  */
 const struct got_error *got_worktree_rebase_continue(struct got_object_id **,
     struct got_reference **, struct got_reference **, struct got_reference **,
-    struct got_worktree *, struct got_repository *);
+    struct got_fileindex **, struct got_worktree *, struct got_repository *);
 
 /* Check whether a, potentially interrupted, rebase operation is in progress. */
 const struct got_error *got_worktree_rebase_in_progress(int *,
@@ -246,7 +251,7 @@ const struct got_error *got_worktree_rebase_in_progres
  * got_worktree_rebase_pathlist_free().
  */
 const struct got_error *got_worktree_rebase_merge_files(
-    struct got_pathlist_head *, struct got_worktree *,
+    struct got_pathlist_head *, struct got_worktree *, struct got_fileindex *,
     struct got_object_id *, struct got_object_id *, struct got_repository *,
     got_worktree_checkout_cb, void *, got_worktree_cancel_cb, void *);
 
@@ -257,7 +262,7 @@ const struct got_error *got_worktree_rebase_merge_file
  * crawl across the entire work tree to find paths to commit.
  */
 const struct got_error *got_worktree_rebase_commit(struct got_object_id **,
-    struct got_pathlist_head *, struct got_worktree *,
+    struct got_pathlist_head *, struct got_worktree *, struct got_fileindex *,
     struct got_reference *, struct got_commit_object *,
     struct got_object_id *, struct got_repository *);
 
@@ -265,22 +270,23 @@ const struct got_error *got_worktree_rebase_commit(str
 void got_worktree_rebase_pathlist_free(struct got_pathlist_head *);
 
 /* Postpone the rebase operation. Should be called after a merge conflict. */
-const struct got_error *got_worktree_rebase_postpone(struct got_worktree *);
+const struct got_error *got_worktree_rebase_postpone(struct got_worktree *,
+    struct got_fileindex *);
 
 /*
  * Complete the current rebase operation. This should be called once all
  * commits have been rebased successfully.
  */
 const struct got_error *got_worktree_rebase_complete(struct got_worktree *,
-    struct got_reference *, struct got_reference *, struct got_reference *,
-    struct got_repository *);
+    struct got_fileindex *, struct got_reference *, struct got_reference *,
+    struct got_reference *, struct got_repository *);
 
 /*
  * Abort the current rebase operation.
  * Report reverted files via the specified progress callback.
  */
 const struct got_error *got_worktree_rebase_abort(struct got_worktree *,
-    struct got_repository *, struct got_reference *,
+    struct got_fileindex *, struct got_repository *, struct got_reference *,
     got_worktree_checkout_cb, void *);
 
 /*
@@ -292,8 +298,8 @@ const struct got_error *got_worktree_rebase_abort(stru
  * functions.
  */
 const struct got_error *got_worktree_histedit_prepare(struct got_reference **,
-    struct got_reference **, struct got_object_id **, struct got_worktree *,
-    struct got_repository *);
+    struct got_reference **, struct got_object_id **, struct got_fileindex **,
+    struct got_worktree *, struct got_repository *);
 
 /*
  * Continue an interrupted histedit operation.
@@ -303,7 +309,7 @@ const struct got_error *got_worktree_histedit_prepare(
  */
 const struct got_error *got_worktree_histedit_continue(struct got_object_id **,
     struct got_reference **, struct got_reference **, struct got_object_id **,
-    struct got_worktree *, struct got_repository *);
+    struct got_fileindex **, struct got_worktree *, struct got_repository *);
 
 /* Check whether a histedit operation is in progress. */
 const struct got_error *got_worktree_histedit_in_progress(int *,
@@ -318,7 +324,7 @@ const struct got_error *got_worktree_histedit_in_progr
  * got_worktree_rebase_pathlist_free().
  */
 const struct got_error *got_worktree_histedit_merge_files(
-    struct got_pathlist_head *, struct got_worktree *,
+    struct got_pathlist_head *, struct got_worktree *, struct got_fileindex *,
     struct got_object_id *, struct got_object_id *, struct got_repository *,
     got_worktree_checkout_cb, void *, got_worktree_cancel_cb, void *);
 
@@ -331,7 +337,7 @@ const struct got_error *got_worktree_histedit_merge_fi
  * commit's original message.
  */
 const struct got_error *got_worktree_histedit_commit(struct got_object_id **,
-    struct got_pathlist_head *, struct got_worktree *,
+    struct got_pathlist_head *, struct got_worktree *, struct got_fileindex *,
     struct got_reference *, struct got_commit_object *,
     struct got_object_id *, const char *, struct got_repository *);
 
@@ -344,22 +350,24 @@ const struct got_error *got_worktree_histedit_skip_com
     struct got_object_id *, struct got_repository *);
 
 /* Postpone the histedit operation. */
-const struct got_error *got_worktree_histedit_postpone(struct got_worktree *);
+const struct got_error *got_worktree_histedit_postpone(struct got_worktree *,
+    struct got_fileindex *);
 
 /*
  * Complete the current histedit operation. This should be called once all
  * commits have been edited successfully.
  */
 const struct got_error *got_worktree_histedit_complete(struct got_worktree *,
-    struct got_reference *, struct got_reference *, struct got_repository *);
+    struct got_fileindex *, struct got_reference *, struct got_reference *,
+    struct got_repository *);
 
 /*
  * Abort the current histedit operation.
  * Report reverted files via the specified progress callback.
  */
 const struct got_error *got_worktree_histedit_abort(struct got_worktree *,
-    struct got_repository *, struct got_reference *, struct got_object_id *,
-    got_worktree_checkout_cb, void *);
+    struct got_fileindex *, struct got_repository *, struct got_reference *,
+    struct got_object_id *, got_worktree_checkout_cb, void *);
 
 /* Get the path to this work tree's histedit command list file. */
 const struct got_error *got_worktree_get_histedit_list_path(char **,
blob - e97e4a41f6e33058d7fa59cafff72d23268115a3
blob + a4aa679e50c2f3cd51a8cea50b51003ea9aecc08
--- lib/worktree.c
+++ lib/worktree.c
@@ -1503,9 +1503,23 @@ done:
 	free(refname);
 	if (ref)
 		got_ref_close(ref);
+	return err;
+}
+
+static const struct got_error *
+get_fileindex_path(char **fileindex_path, struct got_worktree *worktree)
+{
+	const struct got_error *err = NULL;
+
+	if (asprintf(fileindex_path, "%s/%s/%s", worktree->root_path,
+	    GOT_WORKTREE_GOT_DIR, GOT_WORKTREE_FILE_INDEX) == -1) {
+		err = got_error_from_errno("asprintf");
+		*fileindex_path = NULL;
+	}
 	return err;
 }
 
+
 static const struct got_error *
 open_fileindex(struct got_fileindex **fileindex, char **fileindex_path,
    struct got_worktree *worktree)
@@ -1518,12 +1532,9 @@ open_fileindex(struct got_fileindex **fileindex, char 
 	if (*fileindex == NULL)
 		return got_error_from_errno("got_fileindex_alloc");
 
-	if (asprintf(fileindex_path, "%s/%s/%s", worktree->root_path,
-	    GOT_WORKTREE_GOT_DIR, GOT_WORKTREE_FILE_INDEX) == -1) {
-		err = got_error_from_errno("asprintf");
-		*fileindex_path = NULL;
+	err = get_fileindex_path(fileindex_path, worktree);
+	if (err)
 		goto done;
-	}
 
 	index = fopen(*fileindex_path, "rb");
 	if (index == NULL) {
@@ -3599,32 +3610,33 @@ check_rebase_ok(void *arg, struct got_fileindex_entry 
 
 const struct got_error *
 got_worktree_rebase_prepare(struct got_reference **new_base_branch_ref,
-    struct got_reference **tmp_branch, struct got_worktree *worktree,
-    struct got_reference *branch, struct got_repository *repo)
+    struct got_reference **tmp_branch, struct got_fileindex **fileindex,
+    struct got_worktree *worktree, struct got_reference *branch,
+    struct got_repository *repo)
 {
 	const struct got_error *err = NULL;
 	char *tmp_branch_name = NULL, *new_base_branch_ref_name = NULL;
 	char *branch_ref_name = NULL;
-	struct got_fileindex *fileindex = NULL;
 	char *fileindex_path = NULL;
 	struct check_rebase_ok_arg ok_arg;
 	struct got_reference *wt_branch = NULL, *branch_ref = NULL;
 
 	*new_base_branch_ref = NULL;
 	*tmp_branch = NULL;
+	*fileindex = NULL;
 
 	err = lock_worktree(worktree, LOCK_EX);
 	if (err)
 		return err;
 
-	err = open_fileindex(&fileindex, &fileindex_path, worktree);
+	err = open_fileindex(fileindex, &fileindex_path, worktree);
 	if (err)
 		goto done;
 
 	ok_arg.worktree = worktree;
 	ok_arg.repo = repo;
 	ok_arg.rebase_in_progress = 0;
-	err = got_fileindex_for_each_entry_safe(fileindex, check_rebase_ok,
+	err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
 	    &ok_arg);
 	if (err)
 		goto done;
@@ -3677,8 +3689,6 @@ got_worktree_rebase_prepare(struct got_reference **new
 		goto done;
 done:
 	free(fileindex_path);
-	if (fileindex)
-		got_fileindex_free(fileindex);
 	free(tmp_branch_name);
 	free(new_base_branch_ref_name);
 	free(branch_ref_name);
@@ -3695,6 +3705,10 @@ done:
 			got_ref_close(*tmp_branch);
 			*tmp_branch = NULL;
 		}
+		if (*fileindex) {
+			got_fileindex_free(*fileindex);
+			*fileindex = NULL;
+		}
 		lock_worktree(worktree, LOCK_SH);
 	}
 	return err;
@@ -3703,16 +3717,29 @@ done:
 const struct got_error *
 got_worktree_rebase_continue(struct got_object_id **commit_id,
     struct got_reference **new_base_branch, struct got_reference **tmp_branch,
-    struct got_reference **branch, struct got_worktree *worktree,
-    struct got_repository *repo)
+    struct got_reference **branch, struct got_fileindex **fileindex,
+    struct got_worktree *worktree, struct got_repository *repo)
 {
 	const struct got_error *err;
 	char *commit_ref_name = NULL, *new_base_branch_ref_name = NULL;
 	char *tmp_branch_name = NULL, *branch_ref_name = NULL;
 	struct got_reference *commit_ref = NULL, *branch_ref = NULL;
+	char *fileindex_path = NULL;
 
 	*commit_id = NULL;
+	*new_base_branch = NULL;
+	*tmp_branch = NULL;
+	*branch = NULL;
+	*fileindex = NULL;
+
+	err = lock_worktree(worktree, LOCK_EX);
+	if (err)
+		return err;
 
+	err = open_fileindex(fileindex, &fileindex_path, worktree);
+	if (err)
+		goto done;
+
 	err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
 	if (err)
 		return err;
@@ -3757,6 +3784,7 @@ got_worktree_rebase_continue(struct got_object_id **co
 done:
 	free(commit_ref_name);
 	free(branch_ref_name);
+	free(fileindex_path);
 	if (commit_ref)
 		got_ref_close(commit_ref);
 	if (branch_ref)
@@ -3776,6 +3804,11 @@ done:
 			got_ref_close(*branch);
 			*branch = NULL;
 		}
+		if (*fileindex) {
+			got_fileindex_free(*fileindex);
+			*fileindex = NULL;
+		}
+		lock_worktree(worktree, LOCK_SH);
 	}
 	return err;
 }
@@ -3895,19 +3928,19 @@ done:
 static const struct got_error *
 rebase_merge_files(struct got_pathlist_head *merged_paths,
     const char *commit_ref_name, struct got_worktree *worktree,
-    struct got_object_id *parent_commit_id, struct got_object_id *commit_id,
-    struct got_repository *repo, got_worktree_checkout_cb progress_cb,
-    void *progress_arg, got_worktree_cancel_cb cancel_cb, void *cancel_arg)
+    struct got_fileindex *fileindex, struct got_object_id *parent_commit_id,
+    struct got_object_id *commit_id, 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;
-	struct got_fileindex *fileindex;
-	char *fileindex_path;
 	struct got_reference *commit_ref = NULL;
 	struct collect_merged_paths_arg cmp_arg;
+	char *fileindex_path;
 
 	/* Work tree is locked/unlocked during rebase preparation/teardown. */
 
-	err = open_fileindex(&fileindex, &fileindex_path, worktree);
+	err = get_fileindex_path(&fileindex_path, worktree);
 	if (err)
 		return err;
 
@@ -3917,8 +3950,6 @@ rebase_merge_files(struct got_pathlist_head *merged_pa
 	err = merge_files(worktree, fileindex, fileindex_path,
 	    parent_commit_id, commit_id, repo, collect_merged_paths,
 	    &cmp_arg, cancel_cb, cancel_arg);
-	got_fileindex_free(fileindex);
-	free(fileindex_path);
 	if (commit_ref)
 		got_ref_close(commit_ref);
 	return err;
@@ -3926,8 +3957,9 @@ rebase_merge_files(struct got_pathlist_head *merged_pa
 
 const struct got_error *
 got_worktree_rebase_merge_files(struct got_pathlist_head *merged_paths,
-    struct got_worktree *worktree, struct got_object_id *parent_commit_id,
-    struct got_object_id *commit_id, struct got_repository *repo,
+    struct got_worktree *worktree, struct got_fileindex *fileindex,
+    struct got_object_id *parent_commit_id, struct got_object_id *commit_id,
+    struct got_repository *repo,
     got_worktree_checkout_cb progress_cb, void *progress_arg,
     got_worktree_cancel_cb cancel_cb, void *cancel_arg)
 {
@@ -3943,8 +3975,8 @@ got_worktree_rebase_merge_files(struct got_pathlist_he
 		goto done;
 
 	err = rebase_merge_files(merged_paths, commit_ref_name, worktree,
-	    parent_commit_id, commit_id, repo, progress_cb, progress_arg,
-	    cancel_cb, cancel_arg);
+	    fileindex, parent_commit_id, commit_id, repo, progress_cb,
+	    progress_arg, cancel_cb, cancel_arg);
 done:
 	free(commit_ref_name);
 	return err;
@@ -3952,8 +3984,9 @@ done:
 
 const struct got_error *
 got_worktree_histedit_merge_files(struct got_pathlist_head *merged_paths,
-    struct got_worktree *worktree, struct got_object_id *parent_commit_id,
-    struct got_object_id *commit_id, struct got_repository *repo,
+    struct got_worktree *worktree, struct got_fileindex *fileindex,
+    struct got_object_id *parent_commit_id, struct got_object_id *commit_id,
+    struct got_repository *repo,
     got_worktree_checkout_cb progress_cb, void *progress_arg,
     got_worktree_cancel_cb cancel_cb, void *cancel_arg)
 {
@@ -3969,8 +4002,8 @@ got_worktree_histedit_merge_files(struct got_pathlist_
 		goto done;
 
 	err = rebase_merge_files(merged_paths, commit_ref_name, worktree,
-	    parent_commit_id, commit_id, repo, progress_cb, progress_arg,
-	    cancel_cb, cancel_arg);
+	    fileindex, parent_commit_id, commit_id, repo, progress_cb,
+	    progress_arg, cancel_cb, cancel_arg);
 done:
 	free(commit_ref_name);
 	return err;
@@ -3979,14 +4012,13 @@ done:
 static const struct got_error *
 rebase_commit(struct got_object_id **new_commit_id,
     struct got_pathlist_head *merged_paths, struct got_reference *commit_ref,
-    struct got_worktree *worktree, struct got_reference *tmp_branch,
-    struct got_commit_object *orig_commit, const char *new_logmsg,
-    struct got_repository *repo)
+    struct got_worktree *worktree, struct got_fileindex *fileindex,
+    struct got_reference *tmp_branch, struct got_commit_object *orig_commit,
+    const char *new_logmsg, struct got_repository *repo)
 {
 	const struct got_error *err, *sync_err;
 	struct got_pathlist_head commitable_paths;
 	struct collect_commitables_arg cc_arg;
-	struct got_fileindex *fileindex = NULL;
 	char *fileindex_path = NULL;
 	struct got_reference *head_ref = NULL;
 	struct got_object_id *head_commit_id = NULL;
@@ -3997,9 +4029,9 @@ rebase_commit(struct got_object_id **new_commit_id,
 
 	/* Work tree is locked/unlocked during rebase preparation/teardown. */
 
-	err = open_fileindex(&fileindex, &fileindex_path, worktree);
+	err = get_fileindex_path(&fileindex_path, worktree);
 	if (err)
-		goto done;
+		return err;
 
 	cc_arg.commitable_paths = &commitable_paths;
 	cc_arg.worktree = worktree;
@@ -4074,8 +4106,6 @@ rebase_commit(struct got_object_id **new_commit_id,
 	if (sync_err && err == NULL)
 		err = sync_err;
 done:
-	if (fileindex)
-		got_fileindex_free(fileindex);
 	free(fileindex_path);
 	free(head_commit_id);
 	if (head_ref)
@@ -4090,7 +4120,8 @@ done:
 const struct got_error *
 got_worktree_rebase_commit(struct got_object_id **new_commit_id,
     struct got_pathlist_head *merged_paths, struct got_worktree *worktree,
-    struct got_reference *tmp_branch, struct got_commit_object *orig_commit,
+    struct got_fileindex *fileindex, struct got_reference *tmp_branch,
+    struct got_commit_object *orig_commit,
     struct got_object_id *orig_commit_id, struct got_repository *repo)
 {
 	const struct got_error *err;
@@ -4114,7 +4145,7 @@ got_worktree_rebase_commit(struct got_object_id **new_
 	}
 
 	err = rebase_commit(new_commit_id, merged_paths, commit_ref,
-	    worktree, tmp_branch, orig_commit, NULL, repo);
+	    worktree, fileindex, tmp_branch, orig_commit, NULL, repo);
 done:
 	if (commit_ref)
 		got_ref_close(commit_ref);
@@ -4126,7 +4157,8 @@ done:
 const struct got_error *
 got_worktree_histedit_commit(struct got_object_id **new_commit_id,
     struct got_pathlist_head *merged_paths, struct got_worktree *worktree,
-    struct got_reference *tmp_branch, struct got_commit_object *orig_commit,
+    struct got_fileindex *fileindex, struct got_reference *tmp_branch,
+    struct got_commit_object *orig_commit,
     struct got_object_id *orig_commit_id, const char *new_logmsg,
     struct got_repository *repo)
 {
@@ -4151,7 +4183,7 @@ got_worktree_histedit_commit(struct got_object_id **ne
 	}
 
 	err = rebase_commit(new_commit_id, merged_paths, commit_ref,
-	    worktree, tmp_branch, orig_commit, new_logmsg, repo);
+	    worktree, fileindex, tmp_branch, orig_commit, new_logmsg, repo);
 done:
 	if (commit_ref)
 		got_ref_close(commit_ref);
@@ -4161,8 +4193,11 @@ done:
 }
 
 const struct got_error *
-got_worktree_rebase_postpone(struct got_worktree *worktree)
+got_worktree_rebase_postpone(struct got_worktree *worktree,
+    struct got_fileindex *fileindex)
 {
+	if (fileindex)
+		got_fileindex_free(fileindex);
 	return lock_worktree(worktree, LOCK_SH);
 }
 
@@ -4229,8 +4264,8 @@ done:
 
 const struct got_error *
 got_worktree_rebase_complete(struct got_worktree *worktree,
-    struct got_reference *new_base_branch, struct got_reference *tmp_branch,
-    struct got_reference *rebased_branch,
+    struct got_fileindex *fileindex, struct got_reference *new_base_branch,
+    struct got_reference *tmp_branch, struct got_reference *rebased_branch,
     struct got_repository *repo)
 {
 	const struct got_error *err, *unlockerr;
@@ -4254,6 +4289,8 @@ got_worktree_rebase_complete(struct got_worktree *work
 
 	err = delete_rebase_refs(worktree, repo);
 done:
+	if (fileindex)
+		got_fileindex_free(fileindex);
 	free(new_head_commit_id);
 	unlockerr = lock_worktree(worktree, LOCK_SH);
 	if (unlockerr && err == NULL)
@@ -4293,13 +4330,13 @@ collect_revertible_paths(void *arg, unsigned char stat
 
 const struct got_error *
 got_worktree_rebase_abort(struct got_worktree *worktree,
-    struct got_repository *repo, struct got_reference *new_base_branch,
+    struct got_fileindex *fileindex, struct got_repository *repo,
+    struct got_reference *new_base_branch,
      got_worktree_checkout_cb progress_cb, void *progress_arg)
 {
 	const struct got_error *err, *unlockerr, *sync_err;
 	struct got_reference *resolved = NULL;
 	struct got_object_id *commit_id = NULL;
-	struct got_fileindex *fileindex = NULL;
 	char *fileindex_path = NULL;
 	struct got_pathlist_head revertible_paths;
 	struct got_pathlist_entry *pe;
@@ -4343,7 +4380,7 @@ got_worktree_rebase_abort(struct got_worktree *worktre
 	if (err)
 		goto done;
 
-	err = open_fileindex(&fileindex, &fileindex_path, worktree);
+	err = get_fileindex_path(&fileindex_path, worktree);
 	if (err)
 		goto done;
 
@@ -4387,13 +4424,13 @@ done:
 const struct got_error *
 got_worktree_histedit_prepare(struct got_reference **tmp_branch,
     struct got_reference **branch_ref, struct got_object_id **base_commit_id,
-    struct got_worktree *worktree, struct got_repository *repo)
+    struct got_fileindex **fileindex, struct got_worktree *worktree,
+    struct got_repository *repo)
 {
 	const struct got_error *err = NULL;
 	char *tmp_branch_name = NULL;
 	char *branch_ref_name = NULL;
 	char *base_commit_ref_name = NULL;
-	struct got_fileindex *fileindex = NULL;
 	char *fileindex_path = NULL;
 	struct check_rebase_ok_arg ok_arg;
 	struct got_reference *wt_branch = NULL;
@@ -4402,19 +4439,20 @@ got_worktree_histedit_prepare(struct got_reference **t
 	*tmp_branch = NULL;
 	*branch_ref = NULL;
 	*base_commit_id = NULL;
+	*fileindex = NULL;
 
 	err = lock_worktree(worktree, LOCK_EX);
 	if (err)
 		return err;
 
-	err = open_fileindex(&fileindex, &fileindex_path, worktree);
+	err = open_fileindex(fileindex, &fileindex_path, worktree);
 	if (err)
 		goto done;
 
 	ok_arg.worktree = worktree;
 	ok_arg.repo = repo;
 	ok_arg.rebase_in_progress = 0;
-	err = got_fileindex_for_each_entry_safe(fileindex, check_rebase_ok,
+	err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
 	    &ok_arg);
 	if (err)
 		goto done;
@@ -4471,8 +4509,6 @@ got_worktree_histedit_prepare(struct got_reference **t
 		goto done;
 done:
 	free(fileindex_path);
-	if (fileindex)
-		got_fileindex_free(fileindex);
 	free(tmp_branch_name);
 	free(branch_ref_name);
 	free(base_commit_ref_name);
@@ -4488,14 +4524,21 @@ done:
 			*tmp_branch = NULL;
 		}
 		free(*base_commit_id);
+		if (*fileindex) {
+			got_fileindex_free(*fileindex);
+			*fileindex = NULL;
+		}
 		lock_worktree(worktree, LOCK_SH);
 	}
 	return err;
 }
 
 const struct got_error *
-got_worktree_histedit_postpone(struct got_worktree *worktree)
+got_worktree_histedit_postpone(struct got_worktree *worktree,
+    struct got_fileindex *fileindex)
 {
+	if (fileindex)
+		got_fileindex_free(fileindex);
 	return lock_worktree(worktree, LOCK_SH);
 }
 
@@ -4518,7 +4561,7 @@ got_worktree_histedit_in_progress(int *in_progress,
 const struct got_error *
 got_worktree_histedit_continue(struct got_object_id **commit_id,
     struct got_reference **tmp_branch, struct got_reference **branch_ref,
-    struct got_object_id **base_commit_id,
+    struct got_object_id **base_commit_id, struct got_fileindex **fileindex,
     struct got_worktree *worktree, struct got_repository *repo)
 {
 	const struct got_error *err;
@@ -4526,11 +4569,21 @@ got_worktree_histedit_continue(struct got_object_id **
 	char *tmp_branch_name = NULL, *branch_ref_name = NULL;
 	struct got_reference *commit_ref = NULL;
 	struct got_reference *base_commit_ref = NULL;
+	char *fileindex_path = NULL;
 
 	*commit_id = NULL;
 	*tmp_branch = NULL;
 	*base_commit_id = NULL;
+	*fileindex = NULL;
 
+	err = lock_worktree(worktree, LOCK_EX);
+	if (err)
+		return err;
+
+	err = open_fileindex(fileindex, &fileindex_path, worktree);
+	if (err)
+		goto done;
+
 	err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
 	if (err)
 		return err;
@@ -4572,6 +4625,7 @@ got_worktree_histedit_continue(struct got_object_id **
 done:
 	free(commit_ref_name);
 	free(branch_ref_name);
+	free(fileindex_path);
 	if (commit_ref)
 		got_ref_close(commit_ref);
 	if (base_commit_ref)
@@ -4585,6 +4639,11 @@ done:
 			got_ref_close(*tmp_branch);
 			*tmp_branch = NULL;
 		}
+		if (*fileindex) {
+			got_fileindex_free(*fileindex);
+			*fileindex = NULL;
+		}
+		lock_worktree(worktree, LOCK_EX);
 	}
 	return err;
 }
@@ -4634,13 +4693,12 @@ done:
 
 const struct got_error *
 got_worktree_histedit_abort(struct got_worktree *worktree,
-    struct got_repository *repo, struct got_reference *branch,
-    struct got_object_id *base_commit_id,
+    struct got_fileindex *fileindex, struct got_repository *repo,
+    struct got_reference *branch, struct got_object_id *base_commit_id,
     got_worktree_checkout_cb progress_cb, void *progress_arg)
 {
 	const struct got_error *err, *unlockerr, *sync_err;
 	struct got_reference *resolved = NULL;
-	struct got_fileindex *fileindex = NULL;
 	char *fileindex_path = NULL;
 	struct got_pathlist_head revertible_paths;
 	struct got_pathlist_entry *pe;
@@ -4675,7 +4733,7 @@ got_worktree_histedit_abort(struct got_worktree *workt
 	if (err)
 		goto done;
 
-	err = open_fileindex(&fileindex, &fileindex_path, worktree);
+	err = get_fileindex_path(&fileindex_path, worktree);
 	if (err)
 		goto done;
 
@@ -4702,8 +4760,6 @@ sync:
 done:
 	got_ref_close(resolved);
 	free(tree_id);
-	if (fileindex)
-		got_fileindex_free(fileindex);
 	free(fileindex_path);
 	TAILQ_FOREACH(pe, &revertible_paths, entry)
 		free((char *)pe->path);
@@ -4717,8 +4773,8 @@ done:
 
 const struct got_error *
 got_worktree_histedit_complete(struct got_worktree *worktree,
-    struct got_reference *tmp_branch, struct got_reference *edited_branch,
-    struct got_repository *repo)
+    struct got_fileindex *fileindex, struct got_reference *tmp_branch,
+    struct got_reference *edited_branch, struct got_repository *repo)
 {
 	const struct got_error *err, *unlockerr;
 	struct got_object_id *new_head_commit_id = NULL;
@@ -4747,6 +4803,8 @@ got_worktree_histedit_complete(struct got_worktree *wo
 
 	err = delete_histedit_refs(worktree, repo);
 done:
+	if (fileindex)
+		got_fileindex_free(fileindex);
 	free(new_head_commit_id);
 	unlockerr = lock_worktree(worktree, LOCK_SH);
 	if (unlockerr && err == NULL)