Files
gico/commits/chancommits.go

143 lines
2.7 KiB
Go

package commits
import (
"regexp"
"sync"
git "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/taigrr/gico/types"
)
func (paths RepoSet) FrequencyChan(year int, authors []string) (types.Freq, error) {
yearLength := 365
if year%4 == 0 {
yearLength++
}
cache, ok := GetCachedGraph(year, authors, paths)
if ok {
return cache, nil
}
outChan := make(chan types.Commit, 10)
var wg sync.WaitGroup
for _, p := range paths {
wg.Add(1)
go func(path string) {
defer wg.Done()
repo, err := OpenRepo(path)
if err != nil {
return
}
cc, err := repo.GetCommitChan()
if err != nil {
return
}
cc = FilterCChanByYear(cc, year)
cc, err = FilterCChanByAuthor(cc, authors)
if err != nil {
return
}
for c := range cc {
outChan <- c
}
}(p)
}
go func() {
wg.Wait()
close(outChan)
}()
freq := YearFreqFromChan(outChan, year)
CacheGraph(year, authors, paths, freq)
return freq, nil
}
func YearFreqFromChan(cc chan types.Commit, year int) types.Freq {
yearLength := 365
if year%4 == 0 {
yearLength++
}
freq := make([]int, yearLength)
for commit := range cc {
freq[commit.TimeStamp.YearDay()-1]++
}
return freq
}
func (repo Repo) GetCommitChan() (chan types.Commit, error) {
cc := make(chan types.Commit, 30)
r := git.Repository(repo)
ref, err := r.Head()
if err != nil {
return cc, err
}
cIter, err := r.Log(&git.LogOptions{From: ref.Hash()})
if err != nil {
return cc, err
}
go func() {
cIter.ForEach(func(c *object.Commit) error {
ts := c.Author.When
commit := types.Commit{Author: c.Author.Name, Message: c.Message, TimeStamp: ts}
cc <- commit
return nil
})
close(cc)
}()
return cc, nil
}
func FreqFromChan(cc chan types.Commit, year int) types.Freq {
yearLength := 365
if year%4 == 0 {
yearLength++
}
freq := make([]int, yearLength)
for commit := range cc {
if commit.TimeStamp.Year() != year {
continue
}
freq[commit.TimeStamp.YearDay()-1]++
}
return freq
}
func FilterCChanByYear(in chan types.Commit, year int) chan types.Commit {
out := make(chan types.Commit, 30)
go func() {
for commit := range in {
if commit.TimeStamp.Year() == year {
out <- commit
}
}
close(out)
}()
return out
}
func FilterCChanByAuthor(in chan types.Commit, authors []string) (chan types.Commit, error) {
out := make(chan types.Commit, 30)
regSet := [](*regexp.Regexp){}
for _, a := range authors {
r, err := regexp.Compile(a)
if err != nil {
close(out)
return out, err
}
regSet = append(regSet, r)
}
go func() {
for commit := range in {
regset:
for _, r := range regSet {
if r.MatchString(commit.Author) {
out <- commit
break regset
}
}
}
close(out)
}()
return out, nil
}