Skip to content

Commit 1a6342a

Browse files
committed
Initial implementation for git statistics in Activity tab
1 parent 0514376 commit 1a6342a

File tree

3 files changed

+117
-7
lines changed

3 files changed

+117
-7
lines changed

models/repo_activity.go

Lines changed: 106 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,26 @@
55
package models
66

77
import (
8+
"bufio"
89
"fmt"
10+
"strconv"
11+
"strings"
912
"time"
1013

14+
"code.gitea.io/gitea/modules/process"
15+
1116
"github.com/go-xorm/xorm"
1217
)
1318

19+
type CodeActivityStats struct {
20+
AuthorCount int64
21+
CommitCount int64
22+
ChangedFiles int64
23+
Additions int64
24+
Deletions int64
25+
CommitCountInAllBranches int64
26+
}
27+
1428
// ActivityStats represets issue and pull request information.
1529
type ActivityStats struct {
1630
OpenedPRs PullRequestList
@@ -24,29 +38,35 @@ type ActivityStats struct {
2438
UnresolvedIssues IssueList
2539
PublishedReleases []*Release
2640
PublishedReleaseAuthorCount int64
41+
Code *CodeActivityStats
2742
}
2843

2944
// GetActivityStats return stats for repository at given time range
30-
func GetActivityStats(repoID int64, timeFrom time.Time, releases, issues, prs bool) (*ActivityStats, error) {
31-
stats := &ActivityStats{}
45+
func GetActivityStats(repo *Repository, timeFrom time.Time, releases, issues, prs, code bool) (*ActivityStats, error) {
46+
stats := &ActivityStats{Code: &CodeActivityStats{}}
3247
if releases {
33-
if err := stats.FillReleases(repoID, timeFrom); err != nil {
48+
if err := stats.FillReleases(repo.ID, timeFrom); err != nil {
3449
return nil, fmt.Errorf("FillReleases: %v", err)
3550
}
3651
}
3752
if prs {
38-
if err := stats.FillPullRequests(repoID, timeFrom); err != nil {
53+
if err := stats.FillPullRequests(repo.ID, timeFrom); err != nil {
3954
return nil, fmt.Errorf("FillPullRequests: %v", err)
4055
}
4156
}
4257
if issues {
43-
if err := stats.FillIssues(repoID, timeFrom); err != nil {
58+
if err := stats.FillIssues(repo.ID, timeFrom); err != nil {
4459
return nil, fmt.Errorf("FillIssues: %v", err)
4560
}
4661
}
47-
if err := stats.FillUnresolvedIssues(repoID, timeFrom, issues, prs); err != nil {
62+
if err := stats.FillUnresolvedIssues(repo.ID, timeFrom, issues, prs); err != nil {
4863
return nil, fmt.Errorf("FillUnresolvedIssues: %v", err)
4964
}
65+
if code {
66+
if err := stats.Code.FillFromGit(repo, timeFrom); err != nil {
67+
return nil, fmt.Errorf("FillFromGit: %v", err)
68+
}
69+
}
5070
return stats, nil
5171
}
5272

@@ -269,3 +289,83 @@ func releasesForActivityStatement(repoID int64, fromTime time.Time) *xorm.Sessio
269289
And("release.is_draft = ?", false).
270290
And("release.created_unix >= ?", fromTime.Unix())
271291
}
292+
293+
// FillFromGit returns code statistics for acitivity page
294+
func (stats *CodeActivityStats) FillFromGit(repo *Repository, fromTime time.Time) error {
295+
gitPath := repo.RepoPath()
296+
since := fromTime.Format(time.RFC3339)
297+
298+
if stdout, stderr, err := process.GetManager().ExecDir(-1, gitPath,
299+
fmt.Sprintf("FillFromGit.RevList (git rev-list): %s", gitPath),
300+
"git", "rev-list", "--count", "--no-merges", "--branches=*", "--date=iso", fmt.Sprintf("--since='%s'", since)); err != nil {
301+
return fmt.Errorf("git rev-list --count --branch [%s]: %s", gitPath, stderr)
302+
} else {
303+
if c, err := strconv.ParseInt(strings.TrimSpace(stdout), 10, 64); err != nil {
304+
return err
305+
} else {
306+
stats.CommitCountInAllBranches = c
307+
}
308+
}
309+
310+
if stdout, stderr, err := process.GetManager().ExecDir(-1, gitPath,
311+
fmt.Sprintf("FillFromGit.RevList (git rev-list): %s", gitPath),
312+
"git", "log", "--numstat", "--no-merges", "--pretty=format:---%n%h%n%an%n%ae%n", "--first-parent", "--date=iso", fmt.Sprintf("--since='%s'", since), repo.DefaultBranch); err != nil {
313+
return fmt.Errorf("git log --numstat --first-parent [%s -> %s]: %s", repo.DefaultBranch, gitPath, stderr)
314+
} else {
315+
scanner := bufio.NewScanner(strings.NewReader(stdout))
316+
scanner.Split(bufio.ScanLines)
317+
stats.CommitCount = 0
318+
stats.Additions = 0
319+
stats.Deletions = 0
320+
authors := make(map[string]int64)
321+
files := make(map[string]bool)
322+
p := 0
323+
for scanner.Scan() {
324+
l := strings.TrimSpace(scanner.Text())
325+
if l == "---" {
326+
p = 1
327+
} else if p == 0 {
328+
continue
329+
} else {
330+
p++
331+
}
332+
if p > 4 && len(l) == 0 {
333+
continue
334+
}
335+
switch p {
336+
case 1: // Seperator
337+
case 2: // Commit sha-1
338+
stats.CommitCount++
339+
case 3: // Author
340+
//fmt.Println("Author: " + l)
341+
case 4: // E-mail
342+
email := strings.ToLower(l)
343+
i := authors[email]
344+
authors[email] = i + 1
345+
default: // Changed fileB
346+
fmt.Println("L:" + l)
347+
if parts := strings.Fields(l); len(parts) >= 3 {
348+
if parts[0] != "-" {
349+
if c, err := strconv.ParseInt(strings.TrimSpace(parts[0]), 10, 64); err == nil {
350+
stats.Additions += c
351+
}
352+
}
353+
if parts[1] != "-" {
354+
if c, err := strconv.ParseInt(strings.TrimSpace(parts[1]), 10, 64); err == nil {
355+
stats.Deletions += c
356+
}
357+
}
358+
if _, ok := files[parts[2]]; !ok {
359+
files[parts[2]] = true
360+
}
361+
} else {
362+
fmt.Println("err fields")
363+
}
364+
}
365+
}
366+
stats.AuthorCount = int64(len(authors))
367+
stats.ChangedFiles = int64(len(files))
368+
}
369+
370+
return nil
371+
}

routers/repo/activity.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ func Activity(ctx *context.Context) {
4747
if ctx.Data["Activity"], err = models.GetActivityStats(ctx.Repo.Repository.ID, timeFrom,
4848
ctx.Repo.CanRead(models.UnitTypeReleases),
4949
ctx.Repo.CanRead(models.UnitTypeIssues),
50-
ctx.Repo.CanRead(models.UnitTypePullRequests)); err != nil {
50+
ctx.Repo.CanRead(models.UnitTypePullRequests),
51+
ctx.Repo.CanRead(models.UnitTypeCode)); err != nil {
5152
ctx.ServerError("GetActivityStats", err)
5253
return
5354
}

templates/repo/activity.tmpl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,15 @@
8181
</div>
8282
{{end}}
8383

84+
<span>
85+
Excluding merges, <strong>{{.Activity.Code.AuthorCount}} authors</strong>
86+
has pushed <strong>{{.Activity.Code.CommitCount}} commits</strong> to {{.Repository.DefaultBranch}}
87+
and <strong>{{.Activity.Code.CommitCountInAllBranches}} commits</strong> to all branches.
88+
On {{.Repository.DefaultBranch}}, <strong>{{.Activity.Code.ChangedFiles}} files</strong> have changed
89+
and there have been <strong>{{.Activity.Code.Additions}} additions</strong>
90+
and <strong>{{.Activity.Code.Deletions}} deletions</strong>.
91+
</span>
92+
8493
{{if gt .Activity.PublishedReleaseCount 0}}
8594
<h4 class="ui horizontal divider header" id="published-releases">
8695
<i class="text octicon octicon-tag"></i>

0 commit comments

Comments
 (0)