commit 3e3a69f1a29c6322b5464dca5023d8766661d7bf from: Stefan Sperling date: Thu Jul 25 12:25:02 2019 UTC open fileindex just once to make rebase and histedit faster 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)