功能补齐、查看git提交历史

This commit is contained in:
2026-06-12 09:21:37 +08:00
parent fba3a14367
commit 2a9661a6ef
12 changed files with 329 additions and 9 deletions
+61
View File
@@ -0,0 +1,61 @@
package git
import (
"context"
"strconv"
"strings"
"time"
)
// Commit 表示一条 git log 记录。
type Commit struct {
Hash string
Author string
Email string
Date time.Time
Subject string
}
// Log 返回 dir 的最近 n 条提交历史。n <= 0 时默认 50 条。
func (r *DefaultRunner) Log(ctx context.Context, dir string, n int) ([]Commit, error) {
ctx, cancel := withCtx(ctx, r.cfg.OpsTimeout)
defer cancel()
if n <= 0 {
n = 50
}
out, _, err := r.exec(ctx, dir, nil, "log", "--format=%H%x00%an%x00%ae%x00%aI%x00%s%x00", "-n", strconv.Itoa(n))
if err != nil {
return nil, err
}
return parseLog(out), nil
}
func parseLog(buf []byte) []Commit {
if len(buf) == 0 {
return nil
}
parts := strings.Split(string(buf), "\x00")
var commits []Commit
// parts 以空字符串结尾(因为 format 最后有 %x00),所以每 5 个字段为一组。
for i := 0; i+4 < len(parts); i += 5 {
hash := parts[i]
if hash == "" {
continue
}
author := parts[i+1]
email := parts[i+2]
dateStr := parts[i+3]
subject := parts[i+4]
date, _ := time.Parse(time.RFC3339, dateStr)
commits = append(commits, Commit{
Hash: hash,
Author: author,
Email: email,
Date: date,
Subject: subject,
})
}
return commits
}
+1
View File
@@ -33,6 +33,7 @@ type Runner interface {
WorktreeList(ctx context.Context, dir string) ([]Worktree, error)
ListRemoteBranches(ctx context.Context, dir string, cred *Credential) ([]string, error)
Checkout(ctx context.Context, dir, branch string) error
Log(ctx context.Context, dir string, n int) ([]Commit, error)
}
// FileStatus 表示 `git status --porcelain=v1` 的一行。