| 783 | } |
| 784 | |
| 785 | static int split_commit(struct repository *repo, |
| 786 | struct commit *original, |
| 787 | struct pathspec *pathspec, |
| 788 | struct commit **out) |
| 789 | { |
| 790 | struct interactive_options interactive_opts = INTERACTIVE_OPTIONS_INIT; |
| 791 | struct strbuf index_file = STRBUF_INIT; |
| 792 | struct index_state index = INDEX_STATE_INIT(repo); |
| 793 | const struct object_id *original_commit_tree_oid; |
| 794 | const struct object_id *old_tree_oid, *new_tree_oid; |
| 795 | struct object_id parent_tree_oid; |
| 796 | char original_commit_oid[GIT_MAX_HEXSZ + 1]; |
| 797 | struct commit *first_commit, *second_commit; |
| 798 | struct commit_list *parents = NULL; |
| 799 | struct tree *split_tree; |
| 800 | int ret; |
| 801 | |
| 802 | if (original->parents) { |
| 803 | if (repo_parse_commit(repo, original->parents->item)) { |
| 804 | ret = error(_("unable to parse parent commit %s"), |
| 805 | oid_to_hex(&original->parents->item->object.oid)); |
| 806 | goto out; |
| 807 | } |
| 808 | |
| 809 | parent_tree_oid = *get_commit_tree_oid(original->parents->item); |
| 810 | } else { |
| 811 | oidcpy(&parent_tree_oid, repo->hash_algo->empty_tree); |
| 812 | } |
| 813 | original_commit_tree_oid = get_commit_tree_oid(original); |
| 814 | |
| 815 | /* |
| 816 | * Construct the first commit. This is done by taking the original |
| 817 | * commit parent's tree and selectively patching changes from the diff |
| 818 | * between that parent and its child. |
| 819 | */ |
| 820 | repo_git_path_replace(repo, &index_file, "%s", "history-split.index"); |
| 821 | |
| 822 | ret = write_ondisk_index(repo, &parent_tree_oid, index_file.buf); |
| 823 | if (ret < 0) |
| 824 | goto out; |
| 825 | |
| 826 | ret = read_index_from(&index, index_file.buf, repo->gitdir); |
| 827 | if (ret < 0) { |
| 828 | ret = error(_("failed reading temporary index")); |
| 829 | goto out; |
| 830 | } |
| 831 | |
| 832 | oid_to_hex_r(original_commit_oid, &original->object.oid); |
| 833 | ret = run_add_p_index(repo, &index, index_file.buf, &interactive_opts, |
| 834 | original_commit_oid, pathspec, ADD_P_DISALLOW_EDIT); |
| 835 | if (ret < 0) |
| 836 | goto out; |
| 837 | |
| 838 | split_tree = write_in_core_index_as_tree(repo, &index); |
| 839 | if (!split_tree) { |
| 840 | ret = error(_("failed split tree")); |
| 841 | goto out; |
| 842 | } |
no test coverage detected