static int git_commit__create_internal( git_oid *id, git_repository *repo, const char *update_ref, const git_signature *author, const git_signature *committer, const char *message_encoding, const char *message, const git_oid *tree, git_commit_parent_callback parent_cb, void *parent_payload, bool validate) { int error; git_odb *odb; git_reference *ref = NULL; git_buf buf = GIT_BUF_INIT; const git_oid *current_id = NULL; git_array_oid_t parents = GIT_ARRAY_INIT; if (update_ref) { error = git_reference_lookup_resolved(&ref, repo, update_ref, 10); if (error < 0 && error != GIT_ENOTFOUND) return error; } giterr_clear(); if (ref) current_id = git_reference_target(ref); if ((error = validate_tree_and_parents(&parents, repo, tree, parent_cb, parent_payload, current_id, validate)) < 0) goto cleanup; error = git_commit__create_buffer_internal(&buf, author, committer, message_encoding, message, tree, &parents); if (error < 0) goto cleanup; if (git_repository_odb__weakptr(&odb, repo) < 0) goto cleanup; if (git_odb_write(id, odb, buf.ptr, buf.size, GIT_OBJ_COMMIT) < 0) goto cleanup; if (update_ref != NULL) { error = git_reference__update_for_commit( repo, ref, update_ref, id, "commit"); goto cleanup; } cleanup: git_array_clear(parents); git_reference_free(ref); git_buf_free(&buf); return error; }
static int rebase_commit_merge( git_oid *commit_id, git_rebase *rebase, const git_signature *author, const git_signature *committer, const char *message_encoding, const char *message) { git_rebase_operation *operation; git_reference *head = NULL; git_commit *head_commit = NULL, *commit = NULL; git_index *index = NULL; char old_idstr[GIT_OID_HEXSZ], new_idstr[GIT_OID_HEXSZ]; int error; operation = git_array_get(rebase->operations, rebase->current); assert(operation); if ((error = rebase_ensure_not_dirty(rebase->repo, false, true, GIT_EUNMERGED)) < 0 || (error = git_repository_head(&head, rebase->repo)) < 0 || (error = git_reference_peel((git_object **)&head_commit, head, GIT_OBJ_COMMIT)) < 0 || (error = git_repository_index(&index, rebase->repo)) < 0 || (error = rebase_commit__create(&commit, rebase, index, head_commit, author, committer, message_encoding, message)) < 0 || (error = git_reference__update_for_commit( rebase->repo, NULL, "HEAD", git_commit_id(commit), "rebase")) < 0) goto done; git_oid_fmt(old_idstr, &operation->id); git_oid_fmt(new_idstr, git_commit_id(commit)); if ((error = rebase_setupfile(rebase, REWRITTEN_FILE, O_CREAT|O_WRONLY|O_APPEND, "%.*s %.*s\n", GIT_OID_HEXSZ, old_idstr, GIT_OID_HEXSZ, new_idstr)) < 0) goto done; git_oid_cpy(commit_id, git_commit_id(commit)); done: git_index_free(index); git_reference_free(head); git_commit_free(head_commit); git_commit_free(commit); return error; }
int git_commit_amend( git_oid *id, const git_commit *commit_to_amend, const char *update_ref, const git_signature *author, const git_signature *committer, const char *message_encoding, const char *message, const git_tree *tree) { git_repository *repo; git_oid tree_id; git_reference *ref; int error; assert(id && commit_to_amend); repo = git_commit_owner(commit_to_amend); if (!author) author = git_commit_author(commit_to_amend); if (!committer) committer = git_commit_committer(commit_to_amend); if (!message_encoding) message_encoding = git_commit_message_encoding(commit_to_amend); if (!message) message = git_commit_message(commit_to_amend); if (!tree) { git_tree *old_tree; GITERR_CHECK_ERROR( git_commit_tree(&old_tree, commit_to_amend) ); git_oid_cpy(&tree_id, git_tree_id(old_tree)); git_tree_free(old_tree); } else { assert(git_tree_owner(tree) == repo); git_oid_cpy(&tree_id, git_tree_id(tree)); } if (update_ref) { if ((error = git_reference_lookup_resolved(&ref, repo, update_ref, 5)) < 0) return error; if (git_oid_cmp(git_commit_id(commit_to_amend), git_reference_target(ref))) { git_reference_free(ref); giterr_set(GITERR_REFERENCE, "commit to amend is not the tip of the given branch"); return -1; } } error = git_commit__create_internal( id, repo, NULL, author, committer, message_encoding, message, &tree_id, commit_parent_for_amend, (void *)commit_to_amend, false); if (!error && update_ref) { error = git_reference__update_for_commit( repo, ref, NULL, id, "commit"); git_reference_free(ref); } return error; }
static int git_commit__create_internal( git_oid *id, git_repository *repo, const char *update_ref, const git_signature *author, const git_signature *committer, const char *message_encoding, const char *message, const git_oid *tree, git_commit_parent_callback parent_cb, void *parent_payload, bool validate) { git_reference *ref = NULL; int error = 0, matched_parent = 0; const git_oid *current_id = NULL; git_buf commit = GIT_BUF_INIT; size_t i = 0; git_odb *odb; const git_oid *parent; assert(id && repo && tree && parent_cb); if (validate && !git_object__is_valid(repo, tree, GIT_OBJ_TREE)) return -1; if (update_ref) { error = git_reference_lookup_resolved(&ref, repo, update_ref, 10); if (error < 0 && error != GIT_ENOTFOUND) return error; } giterr_clear(); if (ref) current_id = git_reference_target(ref); git_oid__writebuf(&commit, "tree ", tree); while ((parent = parent_cb(i, parent_payload)) != NULL) { if (validate && !git_object__is_valid(repo, parent, GIT_OBJ_COMMIT)) { error = -1; goto on_error; } git_oid__writebuf(&commit, "parent ", parent); if (i == 0 && current_id && git_oid_equal(current_id, parent)) matched_parent = 1; i++; } if (ref && !matched_parent) { git_reference_free(ref); git_buf_free(&commit); giterr_set(GITERR_OBJECT, "failed to create commit: current tip is not the first parent"); return GIT_EMODIFIED; } git_signature__writebuf(&commit, "author ", author); git_signature__writebuf(&commit, "committer ", committer); if (message_encoding != NULL) git_buf_printf(&commit, "encoding %s\n", message_encoding); git_buf_putc(&commit, '\n'); if (git_buf_puts(&commit, message) < 0) goto on_error; if (git_repository_odb__weakptr(&odb, repo) < 0) goto on_error; if (git_odb_write(id, odb, commit.ptr, commit.size, GIT_OBJ_COMMIT) < 0) goto on_error; git_buf_free(&commit); if (update_ref != NULL) { error = git_reference__update_for_commit( repo, ref, update_ref, id, "commit"); git_reference_free(ref); return error; } return 0; on_error: git_buf_free(&commit); return -1; }
static int rebase_commit_merge( git_oid *commit_id, git_rebase *rebase, const git_signature *author, const git_signature *committer, const char *message_encoding, const char *message) { git_index *index = NULL; git_reference *head = NULL; git_commit *current_commit = NULL, *head_commit = NULL, *commit = NULL; git_rebase_operation *operation; git_tree *head_tree = NULL, *tree = NULL; git_diff *diff = NULL; git_oid tree_id; git_buf reflog_msg = GIT_BUF_INIT; char old_idstr[GIT_OID_HEXSZ], new_idstr[GIT_OID_HEXSZ]; int error; operation = git_array_get(rebase->operations, rebase->current); assert(operation); if ((error = git_repository_index(&index, rebase->repo)) < 0) goto done; if (git_index_has_conflicts(index)) { giterr_set(GITERR_REBASE, "Conflicts have not been resolved"); error = GIT_EMERGECONFLICT; goto done; } if ((error = git_commit_lookup(¤t_commit, rebase->repo, &operation->id)) < 0 || (error = git_repository_head(&head, rebase->repo)) < 0 || (error = git_reference_peel((git_object **)&head_commit, head, GIT_OBJ_COMMIT)) < 0 || (error = git_commit_tree(&head_tree, head_commit)) < 0 || (error = git_diff_tree_to_index(&diff, rebase->repo, head_tree, index, NULL)) < 0) goto done; if (git_diff_num_deltas(diff) == 0) { giterr_set(GITERR_REBASE, "This patch has already been applied"); error = GIT_EAPPLIED; goto done; } if ((error = git_index_write_tree(&tree_id, index)) < 0 || (error = git_tree_lookup(&tree, rebase->repo, &tree_id)) < 0) goto done; if (!author) author = git_commit_author(current_commit); if (!message) { message_encoding = git_commit_message_encoding(current_commit); message = git_commit_message(current_commit); } if ((error = git_commit_create(commit_id, rebase->repo, NULL, author, committer, message_encoding, message, tree, 1, (const git_commit **)&head_commit)) < 0 || (error = git_commit_lookup(&commit, rebase->repo, commit_id)) < 0 || (error = git_reference__update_for_commit( rebase->repo, NULL, "HEAD", commit_id, "rebase")) < 0) goto done; git_oid_fmt(old_idstr, git_commit_id(current_commit)); git_oid_fmt(new_idstr, commit_id); error = rebase_setupfile(rebase, REWRITTEN_FILE, O_CREAT|O_WRONLY|O_APPEND, "%.*s %.*s\n", GIT_OID_HEXSZ, old_idstr, GIT_OID_HEXSZ, new_idstr); done: git_buf_free(&reflog_msg); git_commit_free(commit); git_diff_free(diff); git_tree_free(tree); git_tree_free(head_tree); git_commit_free(head_commit); git_commit_free(current_commit); git_reference_free(head); git_index_free(index); return error; }