diff --git a/cmd/mgfetch/mgfetch.go b/cmd/mgfetch/mgfetch.go index 37db193..ccd8ade 100644 --- a/cmd/mgfetch/mgfetch.go +++ b/cmd/mgfetch/mgfetch.go @@ -14,7 +14,7 @@ type Repo git.Repository func main() { year := time.Now().Year() - 1 authors := []string{"Groot"} - gfreq, err := commits.GlobalFrequency(year, authors) + gfreq, err := commits.GlobalFrequencyChan(year, authors) if err != nil { panic(err) } diff --git a/commits/commits.go b/commits/commits.go index 8738012..77b28a9 100644 --- a/commits/commits.go +++ b/commits/commits.go @@ -4,6 +4,7 @@ import ( "errors" "os" "regexp" + "sync" "time" git "github.com/go-git/go-git/v5" @@ -15,6 +16,53 @@ import ( type Repo git.Repository +func GlobalFrequencyChan(year int, authors []string) (types.YearFreq, error) { + yearLength := 365 + if year%4 == 0 { + yearLength++ + } + mrconf, err := parse.LoadMRConfig() + if err != nil { + return types.YearFreq{}, err + } + paths := mrconf.GetRepoPaths() + outChan := make(chan types.Commit, 10) + var wg sync.WaitGroup + for _, p := range paths { + wg.Add(1) + go func(path string) { + 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 + } + wg.Done() + }(p) + } + go func() { + wg.Wait() + close(outChan) + }() + commitSet := CommitSet{Year: year, Commits: []types.Commit{}} + for c := range outChan { + commitSet.Commits = append(commitSet.Commits, c) + } + freq := commitSet.ToYearFreq() + + return freq, nil +} + func GlobalFrequency(year int, authors []string) (types.YearFreq, error) { yearLength := 365 if year%4 == 0 { @@ -128,6 +176,67 @@ func (cs CommitSet) FilterByYear(year int) CommitSet { return newCS } +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 { + for _, r := range regSet { + if r.MatchString(commit.Author) { + out <- commit + break + } + } + } + close(out) + }() + return out, nil +} + +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 (repo Repo) GetCommitSet() (CommitSet, error) { cs := CommitSet{} commits := []types.Commit{}