diff --git a/integrations/editor_test.go b/integrations/editor_test.go index cc94edfd3..453b38491 100644 --- a/integrations/editor_test.go +++ b/integrations/editor_test.go @@ -89,10 +89,7 @@ func TestCreateFileOnProtectedBranch(t *testing.T) { } -func testEditFile(t *testing.T, session *TestSession, user, repo, branch, filePath string) *TestResponse { - - newContent := "Hello, World (Edited)\n" - +func testEditFile(t *testing.T, session *TestSession, user, repo, branch, filePath, newContent string) *TestResponse { // Get to the 'edit this file' page req := NewRequest(t, "GET", path.Join(user, repo, "_edit", branch, filePath)) resp := session.MakeRequest(t, req, http.StatusOK) @@ -121,9 +118,7 @@ func testEditFile(t *testing.T, session *TestSession, user, repo, branch, filePa return resp } -func testEditFileToNewBranch(t *testing.T, session *TestSession, user, repo, branch, targetBranch, filePath string) *TestResponse { - - newContent := "Hello, World (Edited)\n" +func testEditFileToNewBranch(t *testing.T, session *TestSession, user, repo, branch, targetBranch, filePath, newContent string) *TestResponse { // Get to the 'edit this file' page req := NewRequest(t, "GET", path.Join(user, repo, "_edit", branch, filePath)) @@ -157,11 +152,11 @@ func testEditFileToNewBranch(t *testing.T, session *TestSession, user, repo, bra func TestEditFile(t *testing.T) { prepareTestEnv(t) session := loginUser(t, "user2") - testEditFile(t, session, "user2", "repo1", "master", "README.md") + testEditFile(t, session, "user2", "repo1", "master", "README.md", "Hello, World (Edited)\n") } func TestEditFileToNewBranch(t *testing.T) { prepareTestEnv(t) session := loginUser(t, "user2") - testEditFileToNewBranch(t, session, "user2", "repo1", "master", "feature/test", "README.md") + testEditFileToNewBranch(t, session, "user2", "repo1", "master", "feature/test", "README.md", "Hello, World (Edited)\n") } diff --git a/integrations/pull_create_test.go b/integrations/pull_create_test.go index a62144c61..8f1658b11 100644 --- a/integrations/pull_create_test.go +++ b/integrations/pull_create_test.go @@ -47,6 +47,6 @@ func TestPullCreate(t *testing.T) { prepareTestEnv(t) session := loginUser(t, "user1") testRepoFork(t, session, "user2", "repo1", "user1", "repo1") - testEditFile(t, session, "user1", "repo1", "master", "README.md") + testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n") testPullCreate(t, session, "user1", "repo1", "master") } diff --git a/integrations/pull_merge_test.go b/integrations/pull_merge_test.go index 100298b08..f3be6f288 100644 --- a/integrations/pull_merge_test.go +++ b/integrations/pull_merge_test.go @@ -49,7 +49,7 @@ func TestPullMerge(t *testing.T) { prepareTestEnv(t) session := loginUser(t, "user1") testRepoFork(t, session, "user2", "repo1", "user1", "repo1") - testEditFile(t, session, "user1", "repo1", "master", "README.md") + testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n") resp := testPullCreate(t, session, "user1", "repo1", "master") @@ -62,7 +62,7 @@ func TestPullCleanUpAfterMerge(t *testing.T) { prepareTestEnv(t) session := loginUser(t, "user1") testRepoFork(t, session, "user2", "repo1", "user1", "repo1") - testEditFileToNewBranch(t, session, "user1", "repo1", "master", "feature/test", "README.md") + testEditFileToNewBranch(t, session, "user1", "repo1", "master", "feature/test", "README.md", "Hello, World (Edited)\n") resp := testPullCreate(t, session, "user1", "repo1", "feature/test") diff --git a/integrations/repo_activity_test.go b/integrations/repo_activity_test.go new file mode 100644 index 000000000..5a374ff6a --- /dev/null +++ b/integrations/repo_activity_test.go @@ -0,0 +1,61 @@ +// Copyright 2017 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package integrations + +import ( + "net/http" + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRepoActivity(t *testing.T) { + prepareTestEnv(t) + session := loginUser(t, "user1") + + // Create PRs (1 merged & 2 proposed) + testRepoFork(t, session, "user2", "repo1", "user1", "repo1") + testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n") + resp := testPullCreate(t, session, "user1", "repo1", "master") + elem := strings.Split(RedirectURL(t, resp), "/") + assert.EqualValues(t, "pulls", elem[3]) + testPullMerge(t, session, elem[1], elem[2], elem[4]) + + testEditFileToNewBranch(t, session, "user1", "repo1", "master", "feat/better_readme", "README.md", "Hello, World (Edited Again)\n") + testPullCreate(t, session, "user1", "repo1", "feat/better_readme") + + testEditFileToNewBranch(t, session, "user1", "repo1", "master", "feat/much_better_readme", "README.md", "Hello, World (Edited More)\n") + testPullCreate(t, session, "user1", "repo1", "feat/much_better_readme") + + // Create issues (3 new issues) + testNewIssue(t, session, "user2", "repo1", "Issue 1") + testNewIssue(t, session, "user2", "repo1", "Issue 2") + testNewIssue(t, session, "user2", "repo1", "Issue 3") + + // Create releases (1 new release) + createNewRelease(t, session, "/user2/repo1", "v1.0.0", "v1.0.0", false, false) + + // Open Activity page and check stats + req := NewRequest(t, "GET", "/user2/repo1/activity") + resp = session.MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + + // Should be 1 published release + list := htmlDoc.doc.Find("#published-releases").Next().Find("p.desc") + assert.Len(t, list.Nodes, 1) + + // Should be 1 merged pull request + list = htmlDoc.doc.Find("#merged-pull-requests").Next().Find("p.desc") + assert.Len(t, list.Nodes, 1) + + // Should be 2 merged proposed pull requests + list = htmlDoc.doc.Find("#proposed-pull-requests").Next().Find("p.desc") + assert.Len(t, list.Nodes, 2) + + // Should be 3 new issues + list = htmlDoc.doc.Find("#new-issues").Next().Find("p.desc") + assert.Len(t, list.Nodes, 3) +} diff --git a/models/repo_activity.go b/models/repo_activity.go index 6f01bf20e..839a74a7e 100644 --- a/models/repo_activity.go +++ b/models/repo_activity.go @@ -5,6 +5,7 @@ package models import ( + "fmt" "time" "github.com/go-xorm/xorm" @@ -25,6 +26,30 @@ type ActivityStats struct { PublishedReleaseAuthorCount int64 } +// GetActivityStats return stats for repository at given time range +func GetActivityStats(repoID int64, timeFrom time.Time, releases, issues, prs bool) (*ActivityStats, error) { + stats := &ActivityStats{} + if releases { + if err := stats.FillReleases(repoID, timeFrom); err != nil { + return nil, fmt.Errorf("FillReleases: %v", err) + } + } + if prs { + if err := stats.FillPullRequests(repoID, timeFrom); err != nil { + return nil, fmt.Errorf("FillPullRequests: %v", err) + } + } + if issues { + if err := stats.FillIssues(repoID, timeFrom); err != nil { + return nil, fmt.Errorf("FillIssues: %v", err) + } + } + if err := stats.FillUnresolvedIssues(repoID, timeFrom, issues, prs); err != nil { + return nil, fmt.Errorf("FillUnresolvedIssues: %v", err) + } + return stats, nil +} + // ActivePRCount returns total active pull request count func (stats *ActivityStats) ActivePRCount() int { return stats.OpenedPRCount() + stats.MergedPRCount() @@ -85,13 +110,13 @@ func (stats *ActivityStats) PublishedReleaseCount() int { return len(stats.PublishedReleases) } -// FillPullRequestsForActivity returns pull request information for activity page -func FillPullRequestsForActivity(stats *ActivityStats, baseRepoID int64, fromTime time.Time) error { +// FillPullRequests returns pull request information for activity page +func (stats *ActivityStats) FillPullRequests(repoID int64, fromTime time.Time) error { var err error var count int64 // Merged pull requests - sess := pullRequestsForActivityStatement(baseRepoID, fromTime, true) + sess := pullRequestsForActivityStatement(repoID, fromTime, true) sess.OrderBy("pull_request.merged_unix DESC") stats.MergedPRs = make(PullRequestList, 0) if err = sess.Find(&stats.MergedPRs); err != nil { @@ -102,14 +127,14 @@ func FillPullRequestsForActivity(stats *ActivityStats, baseRepoID int64, fromTim } // Merged pull request authors - sess = pullRequestsForActivityStatement(baseRepoID, fromTime, true) + sess = pullRequestsForActivityStatement(repoID, fromTime, true) if _, err = sess.Select("count(distinct issue.poster_id) as `count`").Table("pull_request").Get(&count); err != nil { return err } stats.MergedPRAuthorCount = count // Opened pull requests - sess = pullRequestsForActivityStatement(baseRepoID, fromTime, false) + sess = pullRequestsForActivityStatement(repoID, fromTime, false) sess.OrderBy("issue.created_unix ASC") stats.OpenedPRs = make(PullRequestList, 0) if err = sess.Find(&stats.OpenedPRs); err != nil { @@ -120,7 +145,7 @@ func FillPullRequestsForActivity(stats *ActivityStats, baseRepoID int64, fromTim } // Opened pull request authors - sess = pullRequestsForActivityStatement(baseRepoID, fromTime, false) + sess = pullRequestsForActivityStatement(repoID, fromTime, false) if _, err = sess.Select("count(distinct issue.poster_id) as `count`").Table("pull_request").Get(&count); err != nil { return err } @@ -129,8 +154,8 @@ func FillPullRequestsForActivity(stats *ActivityStats, baseRepoID int64, fromTim return nil } -func pullRequestsForActivityStatement(baseRepoID int64, fromTime time.Time, merged bool) *xorm.Session { - sess := x.Where("pull_request.base_repo_id=?", baseRepoID). +func pullRequestsForActivityStatement(repoID int64, fromTime time.Time, merged bool) *xorm.Session { + sess := x.Where("pull_request.base_repo_id=?", repoID). Join("INNER", "issue", "pull_request.issue_id = issue.id") if merged { @@ -144,13 +169,13 @@ func pullRequestsForActivityStatement(baseRepoID int64, fromTime time.Time, merg return sess } -// FillIssuesForActivity returns issue information for activity page -func FillIssuesForActivity(stats *ActivityStats, baseRepoID int64, fromTime time.Time) error { +// FillIssues returns issue information for activity page +func (stats *ActivityStats) FillIssues(repoID int64, fromTime time.Time) error { var err error var count int64 // Closed issues - sess := issuesForActivityStatement(baseRepoID, fromTime, true, false) + sess := issuesForActivityStatement(repoID, fromTime, true, false) sess.OrderBy("issue.updated_unix DESC") stats.ClosedIssues = make(IssueList, 0) if err = sess.Find(&stats.ClosedIssues); err != nil { @@ -158,14 +183,14 @@ func FillIssuesForActivity(stats *ActivityStats, baseRepoID int64, fromTime time } // Closed issue authors - sess = issuesForActivityStatement(baseRepoID, fromTime, true, false) + sess = issuesForActivityStatement(repoID, fromTime, true, false) if _, err = sess.Select("count(distinct issue.poster_id) as `count`").Table("issue").Get(&count); err != nil { return err } stats.ClosedIssueAuthorCount = count // New issues - sess = issuesForActivityStatement(baseRepoID, fromTime, false, false) + sess = issuesForActivityStatement(repoID, fromTime, false, false) sess.OrderBy("issue.created_unix ASC") stats.OpenedIssues = make(IssueList, 0) if err = sess.Find(&stats.OpenedIssues); err != nil { @@ -173,7 +198,7 @@ func FillIssuesForActivity(stats *ActivityStats, baseRepoID int64, fromTime time } // Opened issue authors - sess = issuesForActivityStatement(baseRepoID, fromTime, false, false) + sess = issuesForActivityStatement(repoID, fromTime, false, false) if _, err = sess.Select("count(distinct issue.poster_id) as `count`").Table("issue").Get(&count); err != nil { return err } @@ -182,13 +207,13 @@ func FillIssuesForActivity(stats *ActivityStats, baseRepoID int64, fromTime time return nil } -// FillUnresolvedIssuesForActivity returns unresolved issue and pull request information for activity page -func FillUnresolvedIssuesForActivity(stats *ActivityStats, baseRepoID int64, fromTime time.Time, issues, prs bool) error { +// FillUnresolvedIssues returns unresolved issue and pull request information for activity page +func (stats *ActivityStats) FillUnresolvedIssues(repoID int64, fromTime time.Time, issues, prs bool) error { // Check if we need to select anything if !issues && !prs { return nil } - sess := issuesForActivityStatement(baseRepoID, fromTime, false, true) + sess := issuesForActivityStatement(repoID, fromTime, false, true) if !issues || !prs { sess.And("issue.is_pull = ?", prs) } @@ -197,8 +222,8 @@ func FillUnresolvedIssuesForActivity(stats *ActivityStats, baseRepoID int64, fro return sess.Find(&stats.UnresolvedIssues) } -func issuesForActivityStatement(baseRepoID int64, fromTime time.Time, closed, unresolved bool) *xorm.Session { - sess := x.Where("issue.repo_id = ?", baseRepoID). +func issuesForActivityStatement(repoID int64, fromTime time.Time, closed, unresolved bool) *xorm.Session { + sess := x.Where("issue.repo_id = ?", repoID). And("issue.is_closed = ?", closed) if !unresolved { @@ -212,13 +237,13 @@ func issuesForActivityStatement(baseRepoID int64, fromTime time.Time, closed, un return sess } -// FillReleasesForActivity returns release information for activity page -func FillReleasesForActivity(stats *ActivityStats, baseRepoID int64, fromTime time.Time) error { +// FillReleases returns release information for activity page +func (stats *ActivityStats) FillReleases(repoID int64, fromTime time.Time) error { var err error var count int64 // Published releases list - sess := releasesForActivityStatement(baseRepoID, fromTime) + sess := releasesForActivityStatement(repoID, fromTime) sess.OrderBy("release.created_unix DESC") stats.PublishedReleases = make([]*Release, 0) if err = sess.Find(&stats.PublishedReleases); err != nil { @@ -226,7 +251,7 @@ func FillReleasesForActivity(stats *ActivityStats, baseRepoID int64, fromTime ti } // Published releases authors - sess = releasesForActivityStatement(baseRepoID, fromTime) + sess = releasesForActivityStatement(repoID, fromTime) if _, err = sess.Select("count(distinct release.publisher_id) as `count`").Table("release").Get(&count); err != nil { return err } @@ -235,8 +260,8 @@ func FillReleasesForActivity(stats *ActivityStats, baseRepoID int64, fromTime ti return nil } -func releasesForActivityStatement(baseRepoID int64, fromTime time.Time) *xorm.Session { - return x.Where("release.repo_id = ?", baseRepoID). +func releasesForActivityStatement(repoID int64, fromTime time.Time) *xorm.Session { + return x.Where("release.repo_id = ?", repoID). And("release.is_draft = ?", false). And("release.created_unix >= ?", fromTime.Unix()) } diff --git a/routers/repo/activity.go b/routers/repo/activity.go index 564537c1f..fbe51e152 100644 --- a/routers/repo/activity.go +++ b/routers/repo/activity.go @@ -43,34 +43,14 @@ func Activity(ctx *context.Context) { ctx.Data["DateUntil"] = timeUntil.Format("January 2, 2006") ctx.Data["PeriodText"] = ctx.Tr("repo.activity.period." + ctx.Data["Period"].(string)) - stats := &models.ActivityStats{} - - if ctx.Repo.Repository.UnitEnabled(models.UnitTypeReleases) { - if err := models.FillReleasesForActivity(stats, ctx.Repo.Repository.ID, timeFrom); err != nil { - ctx.Handle(500, "FillReleasesForActivity", err) - return - } - } - if ctx.Repo.Repository.UnitEnabled(models.UnitTypePullRequests) { - if err := models.FillPullRequestsForActivity(stats, ctx.Repo.Repository.ID, timeFrom); err != nil { - ctx.Handle(500, "FillPullRequestsForActivity", err) - return - } - } - if ctx.Repo.Repository.UnitEnabled(models.UnitTypeIssues) { - if err := models.FillIssuesForActivity(stats, ctx.Repo.Repository.ID, timeFrom); err != nil { - ctx.Handle(500, "FillIssuesForActivity", err) - return - } - } - if err := models.FillUnresolvedIssuesForActivity(stats, ctx.Repo.Repository.ID, timeFrom, + var err error + if ctx.Data["Activity"], err = models.GetActivityStats(ctx.Repo.Repository.ID, timeFrom, + ctx.Repo.Repository.UnitEnabled(models.UnitTypeReleases), ctx.Repo.Repository.UnitEnabled(models.UnitTypeIssues), ctx.Repo.Repository.UnitEnabled(models.UnitTypePullRequests)); err != nil { - ctx.Handle(500, "FillUnresolvedIssuesForActivity", err) + ctx.Handle(500, "GetActivityStats", err) return } - ctx.Data["Activity"] = stats - ctx.HTML(200, tplActivity) }