164 lines
4.2 KiB
Go
164 lines
4.2 KiB
Go
package git
|
|
|
|
import (
|
|
"bufio"
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
|
|
gitea_git "code.gitea.io/gitea/modules/git"
|
|
)
|
|
|
|
type RepoContributor struct {
|
|
Name string `json:"name"`
|
|
Email string `json:"email"`
|
|
Commits int `json:"commits"`
|
|
ContributionPerc string `json:"contribution_perc"`
|
|
}
|
|
|
|
func GetRepoContributors(repo *gitea_git.Repository, page, pageSize int) (int, []*RepoContributor, error) {
|
|
var total, totalContributions, skip int
|
|
var contributors []*RepoContributor
|
|
|
|
skip = (page - 1) * pageSize
|
|
|
|
stdoutReader, stdoutWriter, err := os.Pipe()
|
|
if err != nil {
|
|
return total, nil, err
|
|
}
|
|
defer func() {
|
|
_ = stdoutReader.Close()
|
|
_ = stdoutWriter.Close()
|
|
}()
|
|
cmd := gitea_git.NewCommand(repo.Ctx, "shortlog", "-sne", "--all")
|
|
|
|
stderr := new(strings.Builder)
|
|
err = cmd.Run(&gitea_git.RunOpts{
|
|
Env: []string{},
|
|
Dir: repo.Path,
|
|
Stdout: stdoutWriter,
|
|
Stderr: stderr,
|
|
PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error {
|
|
_ = stdoutWriter.Close()
|
|
scanner := bufio.NewScanner(stdoutReader)
|
|
scanner.Split(bufio.ScanLines)
|
|
var ca int
|
|
for scanner.Scan() {
|
|
l := strings.TrimSpace(scanner.Text())
|
|
commits := l[0:strings.Index(l, "\t")]
|
|
commitsInt, err := strconv.Atoi(commits)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
name := l[strings.Index(l, "\t")+1 : strings.Index(l, " <")]
|
|
email := l[strings.Index(l, "<")+1 : strings.Index(l, ">")]
|
|
totalContributions += commitsInt
|
|
total++
|
|
if skip > 0 {
|
|
skip--
|
|
} else {
|
|
if ca < pageSize {
|
|
contributors = append(contributors, &RepoContributor{
|
|
Commits: commitsInt,
|
|
Name: name,
|
|
Email: email,
|
|
})
|
|
ca++
|
|
}
|
|
}
|
|
}
|
|
|
|
_ = stdoutReader.Close()
|
|
return nil
|
|
},
|
|
})
|
|
|
|
for _, cont := range contributors {
|
|
fperc := fmt.Sprintf("%.2f", float64(cont.Commits)*100/float64(totalContributions))
|
|
cont.ContributionPerc = fperc + "%"
|
|
}
|
|
|
|
return total, contributors, nil
|
|
}
|
|
|
|
func GetRepoContributorsNew(repo *gitea_git.Repository, page, pageSize int) (int, []*RepoContributor, error) {
|
|
var total, totalContributions, skip int
|
|
var contributors []*RepoContributor
|
|
var contributorInfos []*RepoContributor
|
|
contributorInfoHash := make(map[string]*RepoContributor)
|
|
|
|
skip = (page - 1) * pageSize
|
|
|
|
stdoutReader, stdoutWriter, err := os.Pipe()
|
|
if err != nil {
|
|
return total, nil, err
|
|
}
|
|
defer func() {
|
|
_ = stdoutReader.Close()
|
|
_ = stdoutWriter.Close()
|
|
}()
|
|
cmd := gitea_git.NewCommand(repo.Ctx, "shortlog", "-sne", "--all")
|
|
|
|
stderr := new(strings.Builder)
|
|
err = cmd.Run(&gitea_git.RunOpts{
|
|
Env: []string{},
|
|
Dir: repo.Path,
|
|
Stdout: stdoutWriter,
|
|
Stderr: stderr,
|
|
PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error {
|
|
_ = stdoutWriter.Close()
|
|
scanner := bufio.NewScanner(stdoutReader)
|
|
scanner.Split(bufio.ScanLines)
|
|
for scanner.Scan() {
|
|
l := strings.TrimSpace(scanner.Text())
|
|
commits := l[0:strings.Index(l, "\t")]
|
|
commitsInt, err := strconv.Atoi(commits)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
name := l[strings.Index(l, "\t")+1 : strings.Index(l, " <")]
|
|
email := strings.ToLower(l[strings.Index(l, "<")+1 : strings.Index(l, ">")])
|
|
totalContributions += commitsInt
|
|
// committer is not system user
|
|
if existedContributorInfo, ok := contributorInfoHash[email]; ok {
|
|
// existed: same primary email, different committer name
|
|
existedContributorInfo.Commits += commitsInt
|
|
} else {
|
|
var newContributor = &RepoContributor{
|
|
Commits: commitsInt,
|
|
Name: name,
|
|
Email: email,
|
|
}
|
|
total++
|
|
contributorInfos = append(contributorInfos, newContributor)
|
|
contributorInfoHash[email] = newContributor
|
|
}
|
|
}
|
|
|
|
_ = stdoutReader.Close()
|
|
return nil
|
|
},
|
|
})
|
|
|
|
var ca int
|
|
for _, cont := range contributorInfos {
|
|
if skip > 0 {
|
|
skip--
|
|
} else {
|
|
if ca < pageSize {
|
|
fperc := fmt.Sprintf("%.2f", float64(cont.Commits)*100/float64(totalContributions))
|
|
contributors = append(contributors, &RepoContributor{
|
|
Commits: cont.Commits,
|
|
Name: cont.Name,
|
|
Email: cont.Email,
|
|
ContributionPerc: fperc + "%",
|
|
})
|
|
ca++
|
|
}
|
|
}
|
|
}
|
|
return total, contributors, nil
|
|
}
|