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