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 }