forked from tangled.org/core
this repo has no description
1package git 2 3import ( 4 "bufio" 5 "fmt" 6 "io" 7 "strings" 8 9 "tangled.sh/tangled.sh/core/api/tangled" 10 11 "github.com/go-git/go-git/v5/plumbing" 12) 13 14type PostReceiveLine struct { 15 OldSha plumbing.Hash // old sha of reference being updated 16 NewSha plumbing.Hash // new sha of reference being updated 17 Ref string // the reference being updated 18} 19 20func ParsePostReceive(buf io.Reader) ([]PostReceiveLine, error) { 21 scanner := bufio.NewScanner(buf) 22 var lines []PostReceiveLine 23 for scanner.Scan() { 24 line := scanner.Text() 25 parts := strings.SplitN(line, " ", 3) 26 if len(parts) != 3 { 27 continue 28 } 29 30 oldSha := parts[0] 31 newSha := parts[1] 32 ref := parts[2] 33 34 lines = append(lines, PostReceiveLine{ 35 OldSha: plumbing.NewHash(oldSha), 36 NewSha: plumbing.NewHash(newSha), 37 Ref: ref, 38 }) 39 } 40 41 if err := scanner.Err(); err != nil { 42 return nil, err 43 } 44 45 return lines, nil 46} 47 48type RefUpdateMeta struct { 49 CommitCount CommitCount 50 IsDefaultRef bool 51} 52 53type CommitCount struct { 54 ByEmail map[string]int 55} 56 57func (g *GitRepo) RefUpdateMeta(line PostReceiveLine) RefUpdateMeta { 58 commitCount, err := g.newCommitCount(line) 59 if err != nil { 60 // TODO: non-fatal, log this 61 } 62 63 isDefaultRef, err := g.isDefaultBranch(line) 64 if err != nil { 65 // TODO: non-fatal, log this 66 } 67 68 return RefUpdateMeta{ 69 CommitCount: commitCount, 70 IsDefaultRef: isDefaultRef, 71 } 72} 73 74func (g *GitRepo) newCommitCount(line PostReceiveLine) (CommitCount, error) { 75 byEmail := make(map[string]int) 76 commitCount := CommitCount{ 77 ByEmail: byEmail, 78 } 79 80 if !line.NewSha.IsZero() { 81 output, err := g.revList( 82 fmt.Sprintf("--max-count=%d", 100), 83 fmt.Sprintf("%s..%s", line.OldSha.String(), line.NewSha.String()), 84 ) 85 if err != nil { 86 return commitCount, fmt.Errorf("failed to run rev-list: %w", err) 87 } 88 89 lines := strings.Split(strings.TrimSpace(string(output)), "\n") 90 if len(lines) == 1 && lines[0] == "" { 91 return commitCount, nil 92 } 93 94 for _, item := range lines { 95 obj, err := g.r.CommitObject(plumbing.NewHash(item)) 96 if err != nil { 97 continue 98 } 99 commitCount.ByEmail[obj.Author.Email] += 1 100 } 101 } 102 103 return commitCount, nil 104} 105 106func (g *GitRepo) isDefaultBranch(line PostReceiveLine) (bool, error) { 107 defaultBranch, err := g.FindMainBranch() 108 if err != nil { 109 return false, err 110 } 111 112 refName := plumbing.ReferenceName(line.Ref) 113 if refName.IsBranch() { 114 return defaultBranch == refName.Short(), nil 115 } 116 117 return false, err 118} 119 120func (m RefUpdateMeta) AsRecord() tangled.GitRefUpdate_Meta { 121 var byEmail []*tangled.GitRefUpdate_Meta_CommitCount_ByEmail_Elem 122 for e, v := range m.CommitCount.ByEmail { 123 byEmail = append(byEmail, &tangled.GitRefUpdate_Meta_CommitCount_ByEmail_Elem{ 124 Email: e, 125 Count: int64(v), 126 }) 127 } 128 129 return tangled.GitRefUpdate_Meta{ 130 CommitCount: &tangled.GitRefUpdate_Meta_CommitCount{ 131 ByEmail: byEmail, 132 }, 133 IsDefaultRef: m.IsDefaultRef, 134 } 135}