mirror of
https://github.com/taigrr/gico.git
synced 2026-04-02 03:09:07 -07:00
mid-merge
This commit is contained in:
@@ -2,29 +2,22 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/taigrr/gico/commits"
|
"github.com/taigrr/gico/commits"
|
||||||
"github.com/taigrr/gico/graph/term"
|
"github.com/taigrr/gico/graph/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
rand.Seed(time.Now().UnixMilli())
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
wfreq := []int{}
|
wfreq := []int{}
|
||||||
yd := time.Now().YearDay()
|
yd := time.Now().YearDay()
|
||||||
freq, _ := commits.GlobalFrequency(time.Now().Year(), []string{""})
|
repoPaths, err := commits.GetMRRepos()
|
||||||
if yd < 7 {
|
if err != nil {
|
||||||
// xfreq, _ := commits.GlobalFrequency(time.Now().Year()-1, []string{""})
|
panic(err)
|
||||||
} else {
|
}
|
||||||
// TODO fix bug for negative in first week of Jan
|
freq, err := repoPaths.GlobalFrequency(time.Now().Year(), []string{""})
|
||||||
for i := 0; i < 7; i++ {
|
if err != nil {
|
||||||
d := time.Now().YearDay() - 1 - 6 + i
|
panic(err)
|
||||||
wfreq = append(wfreq, freq[d])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fmt.Println("week:")
|
fmt.Println("week:")
|
||||||
fmt.Println(term.GetWeekUnicode(wfreq))
|
fmt.Println(term.GetWeekUnicode(wfreq))
|
||||||
|
|||||||
@@ -21,7 +21,11 @@ func main() {
|
|||||||
w.Header().Add("Content-Type", "text/html")
|
w.Header().Add("Content-Type", "text/html")
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
year := now.Year()
|
year := now.Year()
|
||||||
freq, err := commits.GlobalFrequencyChan(year, []string{author})
|
repoPaths, err := commits.GetMRRepos()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
freq, err := repoPaths.FrequencyChan(year, []string{author})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -29,7 +33,7 @@ func main() {
|
|||||||
fmt.Println(today)
|
fmt.Println(today)
|
||||||
if today < 6 {
|
if today < 6 {
|
||||||
curYear := year - 1
|
curYear := year - 1
|
||||||
curFreq, err := commits.GlobalFrequencyChan(curYear, []string{author})
|
curFreq, err := repoPaths.FrequencyChan(curYear, []string{author})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -53,7 +57,11 @@ func main() {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
year = y
|
year = y
|
||||||
}
|
}
|
||||||
freq, err := commits.GlobalFrequencyChan(year, []string{author})
|
repoPaths, err := commits.GetMRRepos()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
freq, err := repoPaths.FrequencyChan(year, []string{author})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
package commits
|
package commits
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
git "github.com/go-git/go-git/v5"
|
git "github.com/go-git/go-git/v5"
|
||||||
@@ -11,30 +16,185 @@ import (
|
|||||||
"github.com/taigrr/mg/parse"
|
"github.com/taigrr/mg/parse"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GlobalFrequency(year int, authors []string) (types.YearFreq, error) {
|
type Repo git.Repository
|
||||||
|
|
||||||
|
type RepoSet []string
|
||||||
|
|
||||||
|
var (
|
||||||
|
mapTex sync.RWMutex
|
||||||
|
hashCache map[int]map[string]map[string]types.ExpFreq
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
hashCache = make(map[int]map[string]map[string]types.ExpFreq)
|
||||||
|
}
|
||||||
|
|
||||||
|
func hashSlice(in []string) string {
|
||||||
|
sort.Strings(in)
|
||||||
|
sb := strings.Builder{}
|
||||||
|
for _, s := range in {
|
||||||
|
sb.WriteString(s)
|
||||||
|
}
|
||||||
|
h := md5.New()
|
||||||
|
h.Write([]byte(sb.String()))
|
||||||
|
b := h.Sum(nil)
|
||||||
|
return fmt.Sprintf("%x\n", b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCachedGraph(year int, authors []string, repoPaths []string) (types.Freq, bool) {
|
||||||
|
a := hashSlice(authors)
|
||||||
|
r := hashSlice(repoPaths)
|
||||||
|
mapTex.RLock()
|
||||||
|
defer mapTex.RUnlock()
|
||||||
|
if m1, ok := hashCache[year]; !ok {
|
||||||
|
return types.Freq{}, false
|
||||||
|
} else {
|
||||||
|
if m2, ok := m1[a]; !ok {
|
||||||
|
return types.Freq{}, false
|
||||||
|
} else {
|
||||||
|
if freq, ok := m2[r]; !ok {
|
||||||
|
return types.Freq{}, false
|
||||||
|
} else {
|
||||||
|
if freq.Created.Before(time.Now().Add(-15 * time.Minute)) {
|
||||||
|
return types.Freq{}, false
|
||||||
|
} else {
|
||||||
|
return freq.YearFreq, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CacheGraph(year int, authors, repoPaths []string, freq types.Freq) {
|
||||||
|
a := hashSlice(authors)
|
||||||
|
r := hashSlice(repoPaths)
|
||||||
|
mapTex.Lock()
|
||||||
|
defer mapTex.Unlock()
|
||||||
|
if _, ok := hashCache[year]; !ok {
|
||||||
|
hashCache[year] = make(map[string]map[string]types.ExpFreq)
|
||||||
|
}
|
||||||
|
if _, ok := hashCache[year][a]; !ok {
|
||||||
|
hashCache[year][a] = make(map[string]types.ExpFreq)
|
||||||
|
}
|
||||||
|
hashCache[year][a][r] = types.ExpFreq{YearFreq: freq, Created: time.Now()}
|
||||||
|
go func() {
|
||||||
|
time.Sleep(time.Minute * 15)
|
||||||
|
mapTex.Lock()
|
||||||
|
defer mapTex.Unlock()
|
||||||
|
delete(hashCache[year][a], r)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMRRepos() (RepoSet, error) {
|
||||||
|
mrconf, err := parse.LoadMRConfig()
|
||||||
|
if err != nil {
|
||||||
|
return RepoSet{}, err
|
||||||
|
}
|
||||||
|
paths := mrconf.GetRepoPaths()
|
||||||
|
return RepoSet(paths), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (paths RepoSet) GetWeekFreq(authors []string) (types.Freq, error) {
|
||||||
|
now := time.Now()
|
||||||
|
year := now.Year()
|
||||||
|
freq, err := paths.FrequencyChan(year, authors)
|
||||||
|
if err != nil {
|
||||||
|
return types.Freq{}, err
|
||||||
|
}
|
||||||
|
today := now.YearDay() - 1
|
||||||
|
if today < 6 {
|
||||||
|
curYear := year - 1
|
||||||
|
curFreq, err := paths.FrequencyChan(curYear, authors)
|
||||||
|
if err != nil {
|
||||||
|
return types.Freq{}, err
|
||||||
|
}
|
||||||
|
freq = append(curFreq, freq...)
|
||||||
|
today += 365
|
||||||
|
if curYear%4 == 0 {
|
||||||
|
today++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
week := freq[today-6 : today+1]
|
||||||
|
return week, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (paths RepoSet) FrequencyChan(year int, authors []string) (types.Freq, error) {
|
||||||
yearLength := 365
|
yearLength := 365
|
||||||
if year%4 == 0 {
|
if year%4 == 0 {
|
||||||
yearLength++
|
yearLength++
|
||||||
}
|
}
|
||||||
gfreq := make(types.YearFreq, yearLength)
|
cache, ok := GetCachedGraph(year, authors, paths)
|
||||||
mrconf, err := parse.LoadMRConfig()
|
if ok {
|
||||||
if err != nil {
|
return cache, 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)
|
||||||
|
}()
|
||||||
|
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 {
|
||||||
|
if commit.TimeStamp.Year() != year {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
freq[commit.TimeStamp.YearDay()-1]++
|
||||||
|
}
|
||||||
|
return freq
|
||||||
|
}
|
||||||
|
|
||||||
|
func (paths RepoSet) GlobalFrequency(year int, authors []string) (types.Freq, error) {
|
||||||
|
yearLength := 365
|
||||||
|
if year%4 == 0 {
|
||||||
|
yearLength++
|
||||||
|
}
|
||||||
|
gfreq := make(types.Freq, yearLength)
|
||||||
for _, p := range paths {
|
for _, p := range paths {
|
||||||
repo, err := OpenRepo(p)
|
repo, err := OpenRepo(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.YearFreq{}, err
|
return types.Freq{}, err
|
||||||
}
|
}
|
||||||
commits, err := repo.GetCommitSet()
|
commits, err := repo.GetCommitSet()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.YearFreq{}, err
|
return types.Freq{}, err
|
||||||
}
|
}
|
||||||
commits = commits.FilterByYear(year)
|
commits = commits.FilterByYear(year)
|
||||||
commits, err = commits.FilterByAuthorRegex(authors)
|
commits, err = commits.FilterByAuthorRegex(authors)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.YearFreq{}, err
|
return types.Freq{}, err
|
||||||
}
|
}
|
||||||
freq := commits.ToYearFreq()
|
freq := commits.ToYearFreq()
|
||||||
gfreq = gfreq.Merge(freq)
|
gfreq = gfreq.Merge(freq)
|
||||||
@@ -64,7 +224,7 @@ func (repo Repo) GetCommitSet() (CommitSet, error) {
|
|||||||
return cs, nil
|
return cs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs CommitSet) ToYearFreq() types.YearFreq {
|
func (cs CommitSet) ToYearFreq() types.Freq {
|
||||||
year := cs.Year
|
year := cs.Year
|
||||||
yearLength := 365
|
yearLength := 365
|
||||||
if year%4 == 0 {
|
if year%4 == 0 {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
git "github.com/go-git/go-git/v5"
|
git "github.com/go-git/go-git/v5"
|
||||||
|
|
||||||
"github.com/taigrr/gico/types"
|
"github.com/taigrr/gico/types"
|
||||||
|
"github.com/taigrr/mg/parse"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -28,3 +29,12 @@ func OpenRepo(directory string) (Repo, error) {
|
|||||||
r, err := git.PlainOpenWithOptions(directory, &(git.PlainOpenOptions{DetectDotGit: true}))
|
r, err := git.PlainOpenWithOptions(directory, &(git.PlainOpenOptions{DetectDotGit: true}))
|
||||||
return Repo(*r), err
|
return Repo(*r), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetMRRepos() (RepoSet, error) {
|
||||||
|
mrconf, err := parse.LoadMRConfig()
|
||||||
|
if err != nil {
|
||||||
|
return RepoSet{}, err
|
||||||
|
}
|
||||||
|
paths := mrconf.GetRepoPaths()
|
||||||
|
return RepoSet(paths), nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ type (
|
|||||||
Repo string `json:"repo,omitempty"`
|
Repo string `json:"repo,omitempty"`
|
||||||
Path string `json:"path,omitempty"`
|
Path string `json:"path,omitempty"`
|
||||||
}
|
}
|
||||||
DataSet map[time.Time]WorkDay
|
DataSet map[time.Time]WorkDay
|
||||||
YearFreq []int
|
Freq []int
|
||||||
ExpYearFreq struct {
|
ExpFreq struct {
|
||||||
YearFreq YearFreq
|
YearFreq Freq
|
||||||
Created time.Time
|
Created time.Time
|
||||||
}
|
}
|
||||||
WorkDay struct {
|
WorkDay struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user