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 /forged/internal/ipc/git2c/tree.go | |
parent | Remove forge-specific functions from misc (diff) | |
download | forge-eb82fdb2dc0903e6125014abd64aceab42c8eb35.tar.gz forge-eb82fdb2dc0903e6125014abd64aceab42c8eb35.tar.zst forge-eb82fdb2dc0903e6125014abd64aceab42c8eb35.zip |
Diffstat (limited to 'forged/internal/ipc/git2c/tree.go')
-rw-r--r-- | forged/internal/ipc/git2c/tree.go | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/forged/internal/ipc/git2c/tree.go b/forged/internal/ipc/git2c/tree.go new file mode 100644 index 0000000..f598e14 --- /dev/null +++ b/forged/internal/ipc/git2c/tree.go @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org> + +package git2c + +import ( + "encoding/hex" + "fmt" +) + +type TreeEntryRaw struct { + Mode uint64 + Name string + OID string // hex +} + +func (c *Client) TreeListByOID(repoPath, treeHex string) ([]TreeEntryRaw, error) { + if err := c.writer.WriteData([]byte(repoPath)); err != nil { + return nil, fmt.Errorf("sending repo path failed: %w", err) + } + if err := c.writer.WriteUint(9); err != nil { + return nil, fmt.Errorf("sending command failed: %w", err) + } + if err := c.writer.WriteData([]byte(treeHex)); err != nil { + return nil, fmt.Errorf("sending tree oid failed: %w", err) + } + status, err := c.reader.ReadUint() + if err != nil { + return nil, fmt.Errorf("reading status failed: %w", err) + } + if status != 0 { + return nil, Perror(status) + } + count, err := c.reader.ReadUint() + if err != nil { + return nil, fmt.Errorf("reading count failed: %w", err) + } + entries := make([]TreeEntryRaw, 0, count) + for range count { + mode, err := c.reader.ReadUint() + if err != nil { + return nil, fmt.Errorf("reading mode failed: %w", err) + } + name, err := c.reader.ReadData() + if err != nil { + return nil, fmt.Errorf("reading name failed: %w", err) + } + id, err := c.reader.ReadData() + if err != nil { + return nil, fmt.Errorf("reading oid failed: %w", err) + } + entries = append(entries, TreeEntryRaw{Mode: mode, Name: string(name), OID: hex.EncodeToString(id)}) + } + return entries, nil +} + +func (c *Client) WriteTree(repoPath string, entries []TreeEntryRaw) (string, error) { + if err := c.writer.WriteData([]byte(repoPath)); err != nil { + return "", fmt.Errorf("sending repo path failed: %w", err) + } + if err := c.writer.WriteUint(10); err != nil { + return "", fmt.Errorf("sending command failed: %w", err) + } + if err := c.writer.WriteUint(uint64(len(entries))); err != nil { + return "", fmt.Errorf("sending count failed: %w", err) + } + for _, e := range entries { + if err := c.writer.WriteUint(e.Mode); err != nil { + return "", fmt.Errorf("sending mode failed: %w", err) + } + if err := c.writer.WriteData([]byte(e.Name)); err != nil { + return "", fmt.Errorf("sending name failed: %w", err) + } + raw, err := hex.DecodeString(e.OID) + if err != nil { + return "", fmt.Errorf("decode oid hex: %w", err) + } + if err := c.writer.WriteDataFixed(raw); err != nil { + return "", fmt.Errorf("sending oid failed: %w", err) + } + } + status, err := c.reader.ReadUint() + if err != nil { + return "", fmt.Errorf("reading status failed: %w", err) + } + if status != 0 { + return "", Perror(status) + } + id, err := c.reader.ReadData() + if err != nil { + return "", fmt.Errorf("reading oid failed: %w", err) + } + return hex.EncodeToString(id), nil +} + +func (c *Client) WriteBlob(repoPath string, content []byte) (string, error) { + if err := c.writer.WriteData([]byte(repoPath)); err != nil { + return "", fmt.Errorf("sending repo path failed: %w", err) + } + if err := c.writer.WriteUint(11); err != nil { + return "", fmt.Errorf("sending command failed: %w", err) + } + if err := c.writer.WriteData(content); err != nil { + return "", fmt.Errorf("sending blob content failed: %w", err) + } + status, err := c.reader.ReadUint() + if err != nil { + return "", fmt.Errorf("reading status failed: %w", err) + } + if status != 0 { + return "", Perror(status) + } + id, err := c.reader.ReadData() + if err != nil { + return "", fmt.Errorf("reading oid failed: %w", err) + } + return hex.EncodeToString(id), nil +} |