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 return commitCount, nil 82 } 83 84 args := []string{fmt.Sprintf("--max-count=%d", 100)} 85 86 if line.OldSha.IsZero() { 87 // just git rev-list <newsha> 88 args = append(args, line.NewSha.String()) 89 } else { 90 // git rev-list <oldsha>..<newsha> 91 args = append(args, fmt.Sprintf("%s..%s", line.OldSha.String(), line.NewSha.String())) 92 } 93 94 output, err := g.revList(args...) 95 if err != nil { 96 return commitCount, fmt.Errorf("failed to run rev-list: %w", err) 97 } 98 99 lines := strings.Split(strings.TrimSpace(string(output)), "\n") 100 if len(lines) == 1 && lines[0] == "" { 101 return commitCount, nil 102 } 103 104 for _, item := range lines { 105 obj, err := g.r.CommitObject(plumbing.NewHash(item)) 106 if err != nil { 107 continue 108 } 109 commitCount.ByEmail[obj.Author.Email] += 1 110 } 111 112 return commitCount, nil 113} 114 115func (g *GitRepo) isDefaultBranch(line PostReceiveLine) (bool, error) { 116 defaultBranch, err := g.FindMainBranch() 117 if err != nil { 118 return false, err 119 } 120 121 refName := plumbing.ReferenceName(line.Ref) 122 if refName.IsBranch() { 123 return defaultBranch == refName.Short(), nil 124 } 125 126 return false, err 127} 128 129func (m RefUpdateMeta) AsRecord() tangled.GitRefUpdate_Meta { 130 var byEmail []*tangled.GitRefUpdate_Meta_CommitCount_ByEmail_Elem 131 for e, v := range m.CommitCount.ByEmail { 132 byEmail = append(byEmail, &tangled.GitRefUpdate_Meta_CommitCount_ByEmail_Elem{ 133 Email: e, 134 Count: int64(v), 135 }) 136 } 137 138 return tangled.GitRefUpdate_Meta{ 139 CommitCount: &tangled.GitRefUpdate_Meta_CommitCount{ 140 ByEmail: byEmail, 141 }, 142 IsDefaultRef: m.IsDefaultRef, 143 } 144}