diff options
author | Runxi Yu <me@runxiyu.org> | 2025-04-02 03:06:54 +0800 |
---|---|---|
committer | Runxi Yu <me@runxiyu.org> | 2025-04-02 03:06:54 +0800 |
commit | 35efa2a9c96f6f6660e8f1ed5b964141ced9995b (patch) | |
tree | 6bdf06bc91ea378d75c0eecb32eec704ee6ccc46 /lmtp_handle_patch.go | |
parent | Git: Return fsPath from OpenRepo (diff) | |
download | forge-35efa2a9c96f6f6660e8f1ed5b964141ced9995b.tar.gz forge-35efa2a9c96f6f6660e8f1ed5b964141ced9995b.tar.zst forge-35efa2a9c96f6f6660e8f1ed5b964141ced9995b.zip |
LMTP: Stub patch application
Diffstat (limited to 'lmtp_handle_patch.go')
-rw-r--r-- | lmtp_handle_patch.go | 79 |
1 files changed, 76 insertions, 3 deletions
diff --git a/lmtp_handle_patch.go b/lmtp_handle_patch.go index a3064d1..4e49d55 100644 --- a/lmtp_handle_patch.go +++ b/lmtp_handle_patch.go @@ -4,12 +4,85 @@ package main import ( - "log/slog" + "bytes" + // "crypto/rand" + // "fmt" + "os" + "os/exec" + "github.com/bluekeyes/go-gitdiff/gitdiff" "github.com/emersion/go-message" + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing" + "github.com/go-git/go-git/v5/plumbing/object" ) -func lmtpHandlePatch(groupPath []string, repoName string, email *message.Entity) (err error) { - slog.Info("Pretend like I'm handling a patch!") +func lmtpHandlePatch(session *lmtpSession, groupPath []string, repoName string, email *message.Entity) (err error) { + var diffFiles []*gitdiff.File + var preamble string + if diffFiles, preamble, err = gitdiff.Parse(email.Body); err != nil { + return + } + + var repo *git.Repository + var fsPath string + repo, _, _, fsPath, err = openRepo(session.ctx, groupPath, repoName) + if err != nil { + return + } + + var headRef *plumbing.Reference + if headRef, err = repo.Head(); err != nil { + return + } + + var headCommit *object.Commit + if headCommit, err = repo.CommitObject(headRef.Hash()); err != nil { + return + } + + var headTree *object.Tree + if headTree, err = headCommit.Tree(); err != nil { + return + } + + // TODO: Try to not shell out + + for _, diffFile := range diffFiles { + var sourceFile *object.File + if sourceFile, err = headTree.File(diffFile.OldName); err != nil { + return err + } + var sourceString string + if sourceString, err = sourceFile.Contents(); err != nil { + return err + } + hashBuf := bytes.Buffer{} + patchedBuf := bytes.Buffer{} + sourceBuf := bytes.NewReader(stringToBytes(sourceString)) + if err = gitdiff.Apply(&patchedBuf, sourceBuf, diffFile); err != nil { + return err + } + proc := exec.CommandContext(session.ctx, "git", "hash-object", "w", "-t", "blob", "--stdin") + proc.Env = append(os.Environ(), "GIT_DIR="+fsPath) + proc.Stdout = &hashBuf + proc.Stdin = &patchedBuf + if err = proc.Start(); err != nil { + return err + } + newHash := hashBuf.Bytes() + if len(newHash) != 20*2+1 { // TODO: Hardcoded from the size of plumbing.Hash + panic("unexpected hash size") + } + // TODO: Add to tree + } + + // contribBranchName := rand.Text() + + // TODO: Store the branch + + // fmt.Println(repo, diffFiles, preamble) + _ = preamble + return nil } |