From 29601ccaf75ffa6a0cdc2e6bcaedaa5a573f59a2 Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Sat, 05 Apr 2025 11:58:21 +0800 Subject: [PATCH] git2d: Add a basic command for tree --- git2d/cmd2.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++++ git2d/session.c | 5 +++++ git2d/x.h | 1 + diff --git a/git2d/cmd2.c b/git2d/cmd2.c new file mode 100644 index 0000000000000000000000000000000000000000..6edacf29632659a65571fc6b86c3a42ffef0d483 --- /dev/null +++ b/git2d/cmd2.c @@ -0,0 +1,122 @@ +/*- + * SPDX-License-Identifier: AGPL-3.0-only + * SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu + */ + +#include "x.h" + +int +cmd2(git_repository *repo, struct bare_reader *reader, struct bare_writer *writer) +{ + /* Path */ + char path[4096] = {0}; + int err = bare_get_data(reader, (uint8_t *)path, sizeof(path) - 1); + if (err != BARE_ERROR_NONE) { + bare_put_uint(writer, 10); + return -1; + } + path[sizeof(path) - 1] = '\0'; + + /* HEAD^{tree} */ + git_object *head_obj = NULL; + err = git_revparse_single(&head_obj, repo, "HEAD^{tree}"); + if (err != 0) { + bare_put_uint(writer, 11); + return -1; + } + git_tree *tree = (git_tree *)head_obj; + + /* Path in tree */ + git_tree_entry *entry = NULL; + git_otype objtype; + if (strlen(path) == 0) { + entry = NULL; + objtype = GIT_OBJECT_TREE; + } else { + err = git_tree_entry_bypath(&entry, tree, path); + if (err != 0) { + bare_put_uint(writer, 3); + git_tree_free(tree); + return 0; + } + objtype = git_tree_entry_type(entry); + } + + if (objtype == GIT_OBJECT_TREE) { + /* Tree */ + git_object *tree_obj = NULL; + if (entry == NULL) { + tree_obj = (git_object *)tree; + } else { + err = git_tree_entry_to_object(&tree_obj, repo, entry); + if (err != 0) { + bare_put_uint(writer, 3); + goto cleanup; + } + } + git_tree *subtree = (git_tree *)tree_obj; + + size_t count = git_tree_entrycount(subtree); + bare_put_uint(writer, 0); + bare_put_uint(writer, 1); + bare_put_uint(writer, count); + for (size_t i = 0; i < count; i++) { + const git_tree_entry *subentry = git_tree_entry_byindex(subtree, i); + const char *name = git_tree_entry_name(subentry); + git_otype type = git_tree_entry_type(subentry); + uint32_t mode = git_tree_entry_filemode(subentry); + + uint8_t entry_type = 0; + uint64_t size = 0; + + if (type == GIT_OBJECT_TREE) { + entry_type = 1; + } else if (type == GIT_OBJECT_BLOB) { + entry_type = 2; + + git_object *subobj = NULL; + if (git_tree_entry_to_object(&subobj, repo, subentry) == 0) { + git_blob *b = (git_blob *)subobj; + size = git_blob_rawsize(b); + git_blob_free(b); + } + } + + bare_put_uint(writer, entry_type); + bare_put_uint(writer, mode); + bare_put_uint(writer, size); + bare_put_data(writer, (const uint8_t *)name, strlen(name)); + } + if (entry != NULL) { + git_tree_free(subtree); + } + } else if (objtype == GIT_OBJECT_BLOB) { + /* Blob */ + git_object *blob_obj = NULL; + err = git_tree_entry_to_object(&blob_obj, repo, entry); + if (err != 0) { + bare_put_uint(writer, 3); + goto cleanup; + } + git_blob *blob = (git_blob *)blob_obj; + const void *content = git_blob_rawcontent(blob); + if (content == NULL) { + bare_put_uint(writer, 3); + git_blob_free(blob); + goto cleanup; + } + bare_put_uint(writer, 0); + bare_put_uint(writer, 2); + bare_put_data(writer, content, git_blob_rawsize(blob)); + git_blob_free(blob); + } else { + /* Unknown */ + bare_put_uint(writer, 3); + } + +cleanup: + if (entry != NULL) + git_tree_entry_free(entry); + git_tree_free(tree); + return 0; +} diff --git a/git2d/session.c b/git2d/session.c index f7ad8439a962a2f95c76b273001952fd11981570..5efd218a4fd99eb4650542d51808fc29944023cf 100644 --- a/git2d/session.c +++ b/git2d/session.c @@ -52,6 +52,11 @@ err = cmd1(repo, &writer); if (err != 0) goto free_repo; break; + case 2: + err = cmd2(repo, &reader, &writer); + if (err != 0) + goto free_repo; + break; case 0: bare_put_uint(&writer, 3); goto free_repo; diff --git a/git2d/x.h b/git2d/x.h index f852b2369be0313ae94700cc8059262b76318391..5a9b32ac33883152fb982777704568338df666c7 100644 --- a/git2d/x.h +++ b/git2d/x.h @@ -33,5 +33,6 @@ void * session(void *_conn); int cmd1(git_repository *repo, struct bare_writer *writer); +int cmd2(git_repository *repo, struct bare_reader *reader, struct bare_writer *writer); #endif // X_H -- 2.48.1