0
点赞
收藏
分享

微信扫一扫

gilab 代码统计

这是一份通过gitlab events api 进行用户代码量统计的go语言实现的代码

代码实现

main函数

func main() {
	client, err := gitlab_cli.NewGitLabClient("https://xxxx/api/v4", "xxxx", "")
	if err != nil {
		fmt.Println(err.Error())
	}
	collect := gitlab_cli.NewCollectCodeCounts(client)
	collect.RunWithMaster()
	collect.PrintData()
}

gitlab cli

package gitlab_cli

import (
	"github.com/xanzy/go-gitlab"
)

type Client struct {
	gitlab *gitlab.Client
	token  string
	url    string
	user   string
}

func NewGitLabClient(url string, token string, user string) (*Client, error) {
	gitlabCli := Client{url: url, token: token, user: user}
	err := gitlabCli.init()
	return &gitlabCli, err
}

func (g *Client) init() error {
	git, err := gitlab.NewClient(g.token, gitlab.WithBaseURL(g.url))
	g.gitlab = git
	return err
}

func (g *Client) GetUsers(page int, perPage int) ([]*gitlab.User, error) {
	users, _, err := g.gitlab.Users.ListUsers(&gitlab.ListUsersOptions{
		ListOptions: gitlab.ListOptions{
			Page:    page,
			PerPage: perPage,
		},
	})
	return users, err
}

主要逻辑

package gitlab_cli

import (
	"encoding/csv"
	"encoding/json"
	"fmt"
	"github.com/xanzy/go-gitlab"
	"os"
	"strings"
	"sync"
)

type UserData struct {
	CommitId     map[string]struct{}
	ProjectCount map[int]*ProjectCount
	UserName     string
	Additions    int
	Deletions    int
	Total        int
}

type CollectCodeCounts struct {
	gitlab *Client
	data   []UserData
	sync.Mutex
}

func (c *CollectCodeCounts) PrintData() {
	data, err := json.Marshal(&c.data)
	if err != nil {
		fmt.Println(err)
	}
	err = os.WriteFile("codeCount.json", data, os.ModePerm)
	if err != nil {
		fmt.Println(err)
	}

	f, err := os.Create("codeCount.csv")
	if err != nil {
		panic(err)
	}
	_, _ = f.WriteString("\xEF\xBB\xBF")

	writer := csv.NewWriter(f)
	header := []string{"用户名", "项目名称", "新增总行数", "删除总行数", "代码总行数", "总提交次数", "备注"}
	if err := writer.Write(header); err != nil {
		fmt.Println(err.Error())
	}

	for _, d := range c.data {
		var csvRow []string
		projectStr := ""
		for _, p := range d.ProjectCount {
			projectStr += fmt.Sprintf("%v   %v    %v    %v    %v\n", p.Name, p.Additions, p.Deletions, p.Total, len(p.CommitId))
		}
		csvRow = append(csvRow, d.UserName, projectStr, fmt.Sprintf("%v", d.Additions), fmt.Sprintf("%v", d.Deletions), fmt.Sprintf("%v", d.Total), fmt.Sprintf("%v", len(d.CommitId)))
		if err := writer.Write(csvRow); err != nil {
			fmt.Println(err.Error())
		}
	}

	writer.Flush()
}

func NewCollectCodeCounts(gitlab *Client) *CollectCodeCounts {
	return &CollectCodeCounts{
		gitlab: gitlab,
		data:   make([]UserData, 0),
		Mutex:  sync.Mutex{},
	}
}

func (c *CollectCodeCounts) RunWithMaster() {
	page := 1
	perPage := 100
	wg := sync.WaitGroup{}
	runChan := make(chan struct{}, 200)
	endFlag := false
	for {
		user, err := c.gitlab.GetUsers(page, perPage)
		if err != nil {
			fmt.Println(err.Error())
		}
		if len(user) <= 0 {
			endFlag = true
			break
		}
		page += 1
		for i := range user {
			runChan <- struct{}{}
			wg.Add(1)
			go c.runWithMaster(user[i], &wg, runChan)
		}
	}
	for {
		if endFlag == true {
			break
		}
	}
	wg.Wait()
}

type ProjectCount struct {
	Additions int
	Deletions int
	Total     int
	Name      string
	Id        int
	CommitId  []CommitData
}

func (c *CollectCodeCounts) runWithMaster(user *gitlab.User, wg *sync.WaitGroup, runChan chan struct{}) {
	defer func() {
		<-runChan
		wg.Done()
	}()

	timeAfter, err := gitlab.ParseISOTime("2023-06-03")
	if err != nil {
		fmt.Println(err)
	}
	beforeAfter, err := gitlab.ParseISOTime("2023-06-10")
	if err != nil {
		fmt.Println(err)
	}
	userData := UserData{
		CommitId:     map[string]struct{}{},
		ProjectCount: map[int]*ProjectCount{},
		UserName:     user.Name,
		Additions:    0,
		Deletions:    0,
		Total:        0,
	}

	page := 0
	action := gitlab.EventTypeValue("pushed")
	for {
		events, response, err := c.gitlab.gitlab.Users.ListUserContributionEvents(user.ID, &gitlab.ListContributionEventsOptions{
			ListOptions: gitlab.ListOptions{
				Page:    page,
				PerPage: 100,
			},
			After:  &timeAfter,
			Before: &beforeAfter,
			Action: &action,
		})
		if err != nil {
			fmt.Println(err.Error())
			break
		}
		for i := range events {
			//if !strings.Contains(events[i].PushData.Ref, "master") {
			//	continue
			//}
			if events[i].PushData.Action == "created" {
				continue
			}
			if strings.HasPrefix(events[i].PushData.CommitTitle, "Merge ") {
				continue
			}
			if events[i].PushData.CommitTo == "" {
				continue
			}
			result, err := c.handleEvent(events[i])
			if err != nil {
				continue
			}
			// 总计总行数
			if _, ok := userData.CommitId[result.Id]; !ok {
				userData.CommitId[result.Id] = struct{}{}
				userData.Additions += result.Additions
				userData.Deletions += result.Deletions
				userData.Total += result.Total

				fmt.Println(result)

				// 按照项目统计
				if _, okk := userData.ProjectCount[result.ProjectId]; !okk {
					data := ProjectCount{
						Additions: result.Additions,
						Deletions: result.Deletions,
						Total:     result.Total,
						Name:      result.ProjectName,
						Id:        result.ProjectId,
						CommitId:  []CommitData{result},
					}
					project, _, err := c.gitlab.gitlab.Projects.GetProject(result.ProjectId, &gitlab.GetProjectOptions{})
					if err == nil {
						data.Name = project.Name
					}
					userData.ProjectCount[result.ProjectId] = &data
				} else {
					data := userData.ProjectCount[result.ProjectId]
					data.Additions += result.Additions
					data.Deletions += result.Deletions
					data.Total += result.Total
					data.CommitId = append(data.CommitId, result)
				}
			}
		}
		if response.TotalPages <= page {
			break
		}
		page += 1
	}
	if userData.Total == 0 {
		return
	}
	c.Lock()
	c.data = append(c.data, userData)
	c.Unlock()
}

type CommitData struct {
	Id          string
	Additions   int
	Ref         string
	Deletions   int
	Total       int
	ProjectId   int
	ProjectName string
}

func (c *CollectCodeCounts) handleEvent(event *gitlab.ContributionEvent) (CommitData, error) {
	commit, _, err := c.gitlab.gitlab.Commits.GetCommit(event.ProjectID, event.PushData.CommitTo)
	if err != nil {
		fmt.Println(err)
		return CommitData{}, err
	}

	return CommitData{
		Id:        commit.ID,
		Additions: commit.Stats.Additions,
		Deletions: commit.Stats.Deletions,
		Total:     commit.Stats.Total,
		ProjectId: commit.ProjectID,
		Ref:       event.PushData.Ref,
	}, nil
}
举报

相关推荐

0 条评论