diff options
author | Runxi Yu <me@runxiyu.org> | 2025-08-12 11:01:07 +0800 |
---|---|---|
committer | Runxi Yu <me@runxiyu.org> | 2025-09-15 15:19:12 +0800 |
commit | eb82fdb2dc0903e6125014abd64aceab42c8eb35 (patch) | |
tree | c07276ba1595c415ebc28943163d88f3e3180254 /git2d/cmd_commit.c | |
parent | Remove forge-specific functions from misc (diff) | |
download | forge-master.tar.gz forge-master.tar.zst forge-master.zip |
Diffstat (limited to '')
-rw-r--r-- | git2d/cmd_commit.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/git2d/cmd_commit.c b/git2d/cmd_commit.c new file mode 100644 index 0000000..3031088 --- /dev/null +++ b/git2d/cmd_commit.c @@ -0,0 +1,188 @@ +/*- + * SPDX-License-Identifier: AGPL-3.0-only + * SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org> + */ + +#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; +} |