aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--git_plumbing.go6
-rw-r--r--lmtp_handle_patch.go35
-rw-r--r--lmtp_server.go19
3 files changed, 34 insertions, 26 deletions
diff --git a/git_plumbing.go b/git_plumbing.go
index c210027..e787c59 100644
--- a/git_plumbing.go
+++ b/git_plumbing.go
@@ -53,9 +53,6 @@ func writeTree(ctx context.Context, repoPath string, entries []treeEntry) (strin
if err := cmd.Run(); err != nil {
return "", err
}
- if err := cmd.Wait(); err != nil {
- return "", err
- }
return strings.TrimSpace(out.String()), nil
}
@@ -71,9 +68,6 @@ func buildTreeRecursive(ctx context.Context, repoPath, baseTree string, updates
if err := cmd.Run(); err != nil {
return err
}
- if err := cmd.Wait(); err != nil {
- return err
- }
data := out.Bytes()
i := 0
var entries []treeEntry
diff --git a/lmtp_handle_patch.go b/lmtp_handle_patch.go
index d69424b..6bcb272 100644
--- a/lmtp_handle_patch.go
+++ b/lmtp_handle_patch.go
@@ -7,46 +7,47 @@ import (
"bytes"
"crypto/rand"
"encoding/hex"
+ "fmt"
+ "io"
"os"
"os/exec"
"strings"
"time"
"github.com/bluekeyes/go-gitdiff/gitdiff"
- "github.com/emersion/go-message"
"github.com/go-git/go-git/v5"
)
-func lmtpHandlePatch(session *lmtpSession, groupPath []string, repoName string, email *message.Entity) (err error) {
+func lmtpHandlePatch(session *lmtpSession, groupPath []string, repoName string, mbox io.Reader) (err error) {
var diffFiles []*gitdiff.File
var preamble string
- if diffFiles, preamble, err = gitdiff.Parse(email.Body); err != nil {
- return
+ if diffFiles, preamble, err = gitdiff.Parse(mbox); err != nil {
+ return fmt.Errorf("failed to parse patch: %w", err)
}
var header *gitdiff.PatchHeader
if header, err = gitdiff.ParsePatchHeader(preamble); err != nil {
- return
+ return fmt.Errorf("failed to parse patch headers: %w", err)
}
var repo *git.Repository
var fsPath string
repo, _, _, fsPath, err = openRepo(session.ctx, groupPath, repoName)
if err != nil {
- return
+ return fmt.Errorf("failed to open repo: %w", err)
}
headRef, err := repo.Head()
if err != nil {
- return
+ return fmt.Errorf("failed to get repo head hash: %w", err)
}
headCommit, err := repo.CommitObject(headRef.Hash())
if err != nil {
- return
+ return fmt.Errorf("failed to get repo head commit: %w", err)
}
headTree, err := headCommit.Tree()
if err != nil {
- return
+ return fmt.Errorf("failed to get repo head tree: %w", err)
}
headTreeHash := headTree.Hash.String()
@@ -55,17 +56,17 @@ func lmtpHandlePatch(session *lmtpSession, groupPath []string, repoName string,
for _, diffFile := range diffFiles {
sourceFile, err := headTree.File(diffFile.OldName)
if err != nil {
- return err
+ return fmt.Errorf("failed to get file at old name %#v: %w", diffFile.OldName, err)
}
sourceString, err := sourceFile.Contents()
if err != nil {
- return err
+ return fmt.Errorf("failed to get contents: %w", err)
}
sourceBuf := bytes.NewReader(stringToBytes(sourceString))
var patchedBuf bytes.Buffer
if err := gitdiff.Apply(&patchedBuf, sourceBuf, diffFile); err != nil {
- return err
+ return fmt.Errorf("failed to apply patch: %w", err)
}
var hashBuf bytes.Buffer
@@ -78,13 +79,13 @@ func lmtpHandlePatch(session *lmtpSession, groupPath []string, repoName string,
cmd.Stdout = &hashBuf
cmd.Stdin = &patchedBuf
if err := cmd.Run(); err != nil {
- return err
+ return fmt.Errorf("failed to run git hash-object: %w", err)
}
newHashStr := strings.TrimSpace(hashBuf.String())
newHash, err := hex.DecodeString(newHashStr)
if err != nil {
- return err
+ return fmt.Errorf("failed to decode hex string from git: %w", err)
}
blobUpdates[diffFile.NewName] = newHash
@@ -95,7 +96,7 @@ func lmtpHandlePatch(session *lmtpSession, groupPath []string, repoName string,
newTreeSha, err := buildTreeRecursive(session.ctx, fsPath, headTreeHash, blobUpdates)
if err != nil {
- return err
+ return fmt.Errorf("failed to recursively build a tree: %w", err)
}
commitMsg := header.Title
@@ -115,7 +116,7 @@ func lmtpHandlePatch(session *lmtpSession, groupPath []string, repoName string,
var commitOut bytes.Buffer
commitCmd.Stdout = &commitOut
if err := commitCmd.Run(); err != nil {
- return err
+ return fmt.Errorf("failed to commit tree: %w", err)
}
newCommitSha := strings.TrimSpace(commitOut.String())
@@ -124,7 +125,7 @@ func lmtpHandlePatch(session *lmtpSession, groupPath []string, repoName string,
refCmd := exec.CommandContext(session.ctx, "git", "update-ref", "refs/heads/contrib/"+newBranchName, newCommitSha) //#nosec G204
refCmd.Env = append(os.Environ(), "GIT_DIR="+fsPath)
if err := refCmd.Run(); err != nil {
- return err
+ return fmt.Errorf("failed to update ref: %w", err)
}
return nil
diff --git a/lmtp_server.go b/lmtp_server.go
index 44dc8d4..cdfcffb 100644
--- a/lmtp_server.go
+++ b/lmtp_server.go
@@ -158,12 +158,24 @@ func (session *lmtpSession) Data(r io.Reader) error {
goto end
}
+ mbox := bytes.Buffer{}
+ if _, err = fmt.Fprint(&mbox, "From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001\r\n"); err != nil {
+ slog.Error("error handling patch... malloc???", "error", err)
+ goto end
+ }
+ data = bytes.ReplaceAll(data, []byte("\r\n"), []byte("\n"))
+ if _, err = mbox.Write(data); err != nil {
+ slog.Error("error handling patch... malloc???", "error", err)
+ goto end
+ }
+ // TODO: Is mbox's From escaping necessary here?
+
groupPath := segments[:sepIndex]
moduleType := segments[sepIndex+1]
moduleName := segments[sepIndex+2]
switch moduleType {
case "repos":
- err = lmtpHandlePatch(session, groupPath, moduleName, email)
+ err = lmtpHandlePatch(session, groupPath, moduleName, &mbox)
if err != nil {
slog.Error("error handling patch", "error", err)
goto end
@@ -182,8 +194,9 @@ end:
return nil
default:
return &smtp.SMTPError{
- Code: 550,
- Message: err.Error(),
+ Code: 550,
+ Message: "Permanent failure: " + err.Error(),
+ EnhancedCode: [3]int{5, 7, 1},
}
}
}