forked from tangled.org/core
Something went wrong. Try again.
2.9 kB · 135 lines
Go
at spindle
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136package git
import ( "bufio" "fmt" "io" "strings"
"tangled.sh/tangled.sh/core/api/tangled"
"github.com/go-git/go-git/v5/plumbing")
type PostReceiveLine struct { OldSha plumbing.Hash // old sha of reference being updated NewSha plumbing.Hash // new sha of reference being updated Ref string // the reference being updated}
func ParsePostReceive(buf io.Reader) ([]PostReceiveLine, error) { scanner := bufio.NewScanner(buf) var lines []PostReceiveLine for scanner.Scan() { line := scanner.Text() parts := strings.SplitN(line, " ", 3) if len(parts) != 3 { continue }
oldSha := parts[0] newSha := parts[1] ref := parts[2]
lines = append(lines, PostReceiveLine{ OldSha: plumbing.NewHash(oldSha), NewSha: plumbing.NewHash(newSha), Ref: ref, }) }
if err := scanner.Err(); err != nil { return nil, err }
return lines, nil}
type RefUpdateMeta struct { CommitCount CommitCount IsDefaultRef bool}
type CommitCount struct { ByEmail map[string]int}
func (g *GitRepo) RefUpdateMeta(line PostReceiveLine) RefUpdateMeta { commitCount, err := g.newCommitCount(line) if err != nil { // TODO: non-fatal, log this }
isDefaultRef, err := g.isDefaultBranch(line) if err != nil { // TODO: non-fatal, log this }
return RefUpdateMeta{ CommitCount: commitCount, IsDefaultRef: isDefaultRef, }}
func (g *GitRepo) newCommitCount(line PostReceiveLine) (CommitCount, error) { byEmail := make(map[string]int) commitCount := CommitCount{ ByEmail: byEmail, }
if !line.NewSha.IsZero() { output, err := g.revList( fmt.Sprintf("--max-count=%d", 100), fmt.Sprintf("%s..%s", line.OldSha.String(), line.NewSha.String()), ) if err != nil { return commitCount, fmt.Errorf("failed to run rev-list: %w", err) }
lines := strings.Split(strings.TrimSpace(string(output)), "\n") if len(lines) == 1 && lines[0] == "" { return commitCount, nil }
for _, item := range lines { obj, err := g.r.CommitObject(plumbing.NewHash(item)) if err != nil { continue } commitCount.ByEmail[obj.Author.Email] += 1 } }
return commitCount, nil}
func (g *GitRepo) isDefaultBranch(line PostReceiveLine) (bool, error) { defaultBranch, err := g.FindMainBranch() if err != nil { return false, err }
refName := plumbing.ReferenceName(line.Ref) if refName.IsBranch() { return defaultBranch == refName.Short(), nil }
return false, err}
func (m RefUpdateMeta) AsRecord() tangled.GitRefUpdate_Meta { var byEmail []*tangled.GitRefUpdate_Meta_CommitCount_ByEmail_Elem for e, v := range m.CommitCount.ByEmail { byEmail = append(byEmail, &tangled.GitRefUpdate_Meta_CommitCount_ByEmail_Elem{ Email: e, Count: int64(v), }) }
return tangled.GitRefUpdate_Meta{ CommitCount: &tangled.GitRefUpdate_Meta_CommitCount{ ByEmail: byEmail, }, IsDefaultRef: m.IsDefaultRef, }}