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/extra.go | |
parent | Remove forge-specific functions from misc (diff) | |
download | forge-master.tar.gz forge-master.tar.zst forge-master.zip |
Diffstat (limited to 'forged/internal/ipc/git2c/extra.go')
-rw-r--r-- | forged/internal/ipc/git2c/extra.go | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/forged/internal/ipc/git2c/extra.go b/forged/internal/ipc/git2c/extra.go new file mode 100644 index 0000000..4d3a07e --- /dev/null +++ b/forged/internal/ipc/git2c/extra.go @@ -0,0 +1,286 @@ +// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org> + +package git2c + +import ( + "encoding/hex" + "fmt" + "time" +) + +func (c *Client) ResolveRef(repoPath, refType, refName string) (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(3); err != nil { + return "", fmt.Errorf("sending command failed: %w", err) + } + if err := c.writer.WriteData([]byte(refType)); err != nil { + return "", fmt.Errorf("sending ref type failed: %w", err) + } + if err := c.writer.WriteData([]byte(refName)); err != nil { + return "", fmt.Errorf("sending ref name 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) ListBranches(repoPath string) ([]string, 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(4); err != nil { + return nil, fmt.Errorf("sending command 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) + } + branches := make([]string, 0, count) + for range count { + name, err := c.reader.ReadData() + if err != nil { + return nil, fmt.Errorf("reading branch name failed: %w", err) + } + branches = append(branches, string(name)) + } + return branches, nil +} + +func (c *Client) FormatPatch(repoPath, commitHex string) (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(5); err != nil { + return "", fmt.Errorf("sending command failed: %w", err) + } + if err := c.writer.WriteData([]byte(commitHex)); err != nil { + return "", fmt.Errorf("sending commit 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) + } + buf, err := c.reader.ReadData() + if err != nil { + return "", fmt.Errorf("reading patch failed: %w", err) + } + return string(buf), nil +} + +func (c *Client) CommitPatch(repoPath, commitHex string) (parentHex string, stats string, patch string, err error) { + if err = c.writer.WriteData([]byte(repoPath)); err != nil { + return "", "", "", fmt.Errorf("sending repo path failed: %w", err) + } + if err = c.writer.WriteUint(6); err != nil { + return "", "", "", fmt.Errorf("sending command failed: %w", err) + } + if err = c.writer.WriteData([]byte(commitHex)); err != nil { + return "", "", "", fmt.Errorf("sending commit failed: %w", err) + } + status, err2 := c.reader.ReadUint() + if err2 != nil { + return "", "", "", fmt.Errorf("reading status failed: %w", err2) + } + if status != 0 { + return "", "", "", Perror(status) + } + id, err2 := c.reader.ReadData() + if err2 != nil { + return "", "", "", fmt.Errorf("reading parent oid failed: %w", err2) + } + statsBytes, err2 := c.reader.ReadData() + if err2 != nil { + return "", "", "", fmt.Errorf("reading stats failed: %w", err2) + } + patchBytes, err2 := c.reader.ReadData() + if err2 != nil { + return "", "", "", fmt.Errorf("reading patch failed: %w", err2) + } + return hex.EncodeToString(id), string(statsBytes), string(patchBytes), nil +} + +func (c *Client) MergeBase(repoPath, hexA, hexB string) (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(7); err != nil { + return "", fmt.Errorf("sending command failed: %w", err) + } + if err := c.writer.WriteData([]byte(hexA)); err != nil { + return "", fmt.Errorf("sending oid A failed: %w", err) + } + if err := c.writer.WriteData([]byte(hexB)); err != nil { + return "", fmt.Errorf("sending oid B 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) + } + base, err := c.reader.ReadData() + if err != nil { + return "", fmt.Errorf("reading base oid failed: %w", err) + } + return hex.EncodeToString(base), nil +} + +func (c *Client) Log(repoPath, refSpec string, n uint) ([]Commit, 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(8); err != nil { + return nil, fmt.Errorf("sending command failed: %w", err) + } + if err := c.writer.WriteData([]byte(refSpec)); err != nil { + return nil, fmt.Errorf("sending refspec failed: %w", err) + } + if err := c.writer.WriteUint(uint64(n)); err != nil { + return nil, fmt.Errorf("sending limit 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) + } + var out []Commit + for { + id, err := c.reader.ReadData() + if err != nil { + break + } + title, _ := c.reader.ReadData() + authorName, _ := c.reader.ReadData() + authorEmail, _ := c.reader.ReadData() + date, _ := c.reader.ReadData() + out = append(out, Commit{ + Hash: hex.EncodeToString(id), + Author: string(authorName), + Email: string(authorEmail), + Date: string(date), + Message: string(title), + }) + } + return out, nil +} + +func (c *Client) CommitTreeOID(repoPath, commitHex string) (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(12); err != nil { + return "", fmt.Errorf("sending command failed: %w", err) + } + if err := c.writer.WriteData([]byte(commitHex)); 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 tree oid failed: %w", err) + } + return hex.EncodeToString(id), nil +} + +func (c *Client) CommitCreate(repoPath, treeHex string, parents []string, authorName, authorEmail string, when time.Time, message string) (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(13); err != nil { + return "", fmt.Errorf("sending command failed: %w", err) + } + if err := c.writer.WriteData([]byte(treeHex)); err != nil { + return "", fmt.Errorf("sending tree oid failed: %w", err) + } + if err := c.writer.WriteUint(uint64(len(parents))); err != nil { + return "", fmt.Errorf("sending parents count failed: %w", err) + } + for _, p := range parents { + if err := c.writer.WriteData([]byte(p)); err != nil { + return "", fmt.Errorf("sending parent oid failed: %w", err) + } + } + if err := c.writer.WriteData([]byte(authorName)); err != nil { + return "", fmt.Errorf("sending author name failed: %w", err) + } + if err := c.writer.WriteData([]byte(authorEmail)); err != nil { + return "", fmt.Errorf("sending author email failed: %w", err) + } + if err := c.writer.WriteInt(when.Unix()); err != nil { + return "", fmt.Errorf("sending when failed: %w", err) + } + _, offset := when.Zone() + if err := c.writer.WriteInt(int64(offset / 60)); err != nil { + return "", fmt.Errorf("sending tz offset failed: %w", err) + } + if err := c.writer.WriteData([]byte(message)); err != nil { + return "", fmt.Errorf("sending message 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 commit oid failed: %w", err) + } + return hex.EncodeToString(id), nil +} + +func (c *Client) UpdateRef(repoPath, refName, commitHex 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(14); err != nil { + return fmt.Errorf("sending command failed: %w", err) + } + if err := c.writer.WriteData([]byte(refName)); err != nil { + return fmt.Errorf("sending ref name failed: %w", err) + } + if err := c.writer.WriteData([]byte(commitHex)); err != nil { + return fmt.Errorf("sending commit 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) + } + return nil +} |