/*- * SPDX-License-Identifier: AGPL-3.0-only * SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu */ #include "x.h" int cmd_commit_tree_oid(git_repository *repo, struct bare_reader *reader, struct bare_writer *writer) { char hex[64] = { 0 }; if (bare_get_data(reader, (uint8_t *) hex, sizeof(hex) - 1) != BARE_ERROR_NONE) { bare_put_uint(writer, 11); return -1; } git_oid oid; if (git_oid_fromstr(&oid, hex) != 0) { bare_put_uint(writer, 14); return -1; } git_commit *commit = NULL; if (git_commit_lookup(&commit, repo, &oid) != 0) { bare_put_uint(writer, 14); return -1; } git_tree *tree = NULL; if (git_commit_tree(&tree, commit) != 0) { git_commit_free(commit); bare_put_uint(writer, 14); return -1; } const git_oid *toid = git_tree_id(tree); bare_put_uint(writer, 0); bare_put_data(writer, toid->id, GIT_OID_RAWSZ); git_tree_free(tree); git_commit_free(commit); return 0; } int cmd_commit_create(git_repository *repo, struct bare_reader *reader, struct bare_writer *writer) { char treehex[64] = { 0 }; if (bare_get_data(reader, (uint8_t *) treehex, sizeof(treehex) - 1) != BARE_ERROR_NONE) { bare_put_uint(writer, 11); return -1; } git_oid tree_oid; if (git_oid_fromstr(&tree_oid, treehex) != 0) { bare_put_uint(writer, 15); return -1; } uint64_t pcnt = 0; if (bare_get_uint(reader, &pcnt) != BARE_ERROR_NONE) { bare_put_uint(writer, 11); return -1; } git_commit **parents = NULL; if (pcnt > 0) { parents = (git_commit **) calloc(pcnt, sizeof(git_commit *)); if (!parents) { bare_put_uint(writer, 15); return -1; } for (uint64_t i = 0; i < pcnt; i++) { char phex[64] = { 0 }; if (bare_get_data(reader, (uint8_t *) phex, sizeof(phex) - 1) != BARE_ERROR_NONE) { bare_put_uint(writer, 11); goto fail; } git_oid poid; if (git_oid_fromstr(&poid, phex) != 0) { bare_put_uint(writer, 15); goto fail; } if (git_commit_lookup(&parents[i], repo, &poid) != 0) { bare_put_uint(writer, 15); goto fail; } } } char aname[512] = { 0 }; char aemail[512] = { 0 }; if (bare_get_data(reader, (uint8_t *) aname, sizeof(aname) - 1) != BARE_ERROR_NONE) { bare_put_uint(writer, 11); goto fail; } if (bare_get_data(reader, (uint8_t *) aemail, sizeof(aemail) - 1) != BARE_ERROR_NONE) { bare_put_uint(writer, 11); goto fail; } int64_t when = 0; int64_t tzoff = 0; if (bare_get_i64(reader, &when) != BARE_ERROR_NONE) { bare_put_uint(writer, 11); goto fail; } if (bare_get_i64(reader, &tzoff) != BARE_ERROR_NONE) { bare_put_uint(writer, 11); goto fail; } char *message = NULL; { uint64_t msz = 0; if (bare_get_uint(reader, &msz) != BARE_ERROR_NONE) { bare_put_uint(writer, 11); goto fail; } message = (char *)malloc(msz + 1); if (!message) { bare_put_uint(writer, 15); goto fail; } if (bare_get_fixed_data(reader, (uint8_t *) message, msz) != BARE_ERROR_NONE) { free(message); bare_put_uint(writer, 11); goto fail; } message[msz] = '\0'; } git_signature *sig = NULL; if (git_signature_new(&sig, aname, aemail, (git_time_t) when, (int)tzoff) != 0) { free(message); bare_put_uint(writer, 19); goto fail; } git_tree *tree = NULL; if (git_tree_lookup(&tree, repo, &tree_oid) != 0) { git_signature_free(sig); free(message); bare_put_uint(writer, 19); goto fail; } git_oid out; int rc = git_commit_create(&out, repo, NULL, sig, sig, NULL, message, tree, (int)pcnt, (const git_commit **)parents); git_tree_free(tree); git_signature_free(sig); free(message); if (rc != 0) { bare_put_uint(writer, 19); goto fail; } bare_put_uint(writer, 0); bare_put_data(writer, out.id, GIT_OID_RAWSZ); if (parents) { for (uint64_t i = 0; i < pcnt; i++) if (parents[i]) git_commit_free(parents[i]); free(parents); } return 0; fail: if (parents) { for (uint64_t i = 0; i < pcnt; i++) if (parents[i]) git_commit_free(parents[i]); free(parents); } return -1; } int cmd_update_ref(git_repository *repo, struct bare_reader *reader, struct bare_writer *writer) { char refname[4096] = { 0 }; char commithex[64] = { 0 }; if (bare_get_data(reader, (uint8_t *) refname, sizeof(refname) - 1) != BARE_ERROR_NONE) { bare_put_uint(writer, 11); return -1; } if (bare_get_data(reader, (uint8_t *) commithex, sizeof(commithex) - 1) != BARE_ERROR_NONE) { bare_put_uint(writer, 11); return -1; } git_oid oid; if (git_oid_fromstr(&oid, commithex) != 0) { bare_put_uint(writer, 18); return -1; } git_reference *out = NULL; int rc = git_reference_create(&out, repo, refname, &oid, 1, NULL); if (rc != 0) { bare_put_uint(writer, 18); return -1; } git_reference_free(out); bare_put_uint(writer, 0); return 0; }