mirror of
https://github.com/gogs/gogs.git
synced 2025-05-28 18:22:45 +00:00
Move 'Commits' and 'Releases' tabs down to body. This patch also reduces page load time for pages that do not need to use commits count anywhere. Get commits count can hurt performance badly for huge repositories that has tens of thousands commits like Linux Kernel.
298 lines
8.0 KiB
Go
298 lines
8.0 KiB
Go
// Copyright 2014 The Gogs 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 repo
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
log "gopkg.in/clog.v1"
|
|
|
|
"github.com/gogits/gogs/models"
|
|
"github.com/gogits/gogs/modules/base"
|
|
"github.com/gogits/gogs/modules/context"
|
|
"github.com/gogits/gogs/modules/form"
|
|
"github.com/gogits/gogs/modules/markdown"
|
|
)
|
|
|
|
const (
|
|
RELEASES base.TplName = "repo/release/list"
|
|
RELEASE_NEW base.TplName = "repo/release/new"
|
|
)
|
|
|
|
// calReleaseNumCommitsBehind calculates given release has how many commits behind release target.
|
|
func calReleaseNumCommitsBehind(repoCtx *context.Repository, release *models.Release, countCache map[string]int64) error {
|
|
// Get count if not exists
|
|
if _, ok := countCache[release.Target]; !ok {
|
|
if repoCtx.GitRepo.IsBranchExist(release.Target) {
|
|
commit, err := repoCtx.GitRepo.GetBranchCommit(release.Target)
|
|
if err != nil {
|
|
return fmt.Errorf("GetBranchCommit: %v", err)
|
|
}
|
|
countCache[release.Target], err = commit.CommitsCount()
|
|
if err != nil {
|
|
return fmt.Errorf("CommitsCount: %v", err)
|
|
}
|
|
} else {
|
|
// Use NumCommits of the newest release on that target
|
|
countCache[release.Target] = release.NumCommits
|
|
}
|
|
}
|
|
release.NumCommitsBehind = countCache[release.Target] - release.NumCommits
|
|
return nil
|
|
}
|
|
|
|
func Releases(ctx *context.Context) {
|
|
ctx.Data["Title"] = ctx.Tr("repo.release.releases")
|
|
ctx.Data["PageIsReleaseList"] = true
|
|
|
|
tagsResult, err := ctx.Repo.GitRepo.GetTagsAfter(ctx.Query("after"), 10)
|
|
if err != nil {
|
|
ctx.Handle(500, fmt.Sprintf("GetTags '%s'", ctx.Repo.Repository.RepoPath()), err)
|
|
return
|
|
}
|
|
|
|
releases, err := models.GetPublishedReleasesByRepoID(ctx.Repo.Repository.ID, tagsResult.Tags...)
|
|
if err != nil {
|
|
ctx.Handle(500, "GetPublishedReleasesByRepoID", err)
|
|
return
|
|
}
|
|
|
|
// Temproray cache commits count of used branches to speed up.
|
|
countCache := make(map[string]int64)
|
|
|
|
results := make([]*models.Release, len(tagsResult.Tags))
|
|
for i, rawTag := range tagsResult.Tags {
|
|
for j, r := range releases {
|
|
if r == nil || r.TagName != rawTag {
|
|
continue
|
|
}
|
|
releases[j] = nil // Mark as used.
|
|
|
|
if err = r.LoadAttributes(); err != nil {
|
|
ctx.Handle(500, "LoadAttributes", err)
|
|
return
|
|
}
|
|
|
|
if err := calReleaseNumCommitsBehind(ctx.Repo, r, countCache); err != nil {
|
|
ctx.Handle(500, "calReleaseNumCommitsBehind", err)
|
|
return
|
|
}
|
|
|
|
r.Note = markdown.RenderString(r.Note, ctx.Repo.RepoLink, ctx.Repo.Repository.ComposeMetas())
|
|
results[i] = r
|
|
break
|
|
}
|
|
|
|
// No published release matches this tag
|
|
if results[i] == nil {
|
|
commit, err := ctx.Repo.GitRepo.GetTagCommit(rawTag)
|
|
if err != nil {
|
|
ctx.Handle(500, "GetTagCommit", err)
|
|
return
|
|
}
|
|
|
|
results[i] = &models.Release{
|
|
Title: rawTag,
|
|
TagName: rawTag,
|
|
Sha1: commit.ID.String(),
|
|
}
|
|
|
|
results[i].NumCommits, err = commit.CommitsCount()
|
|
if err != nil {
|
|
ctx.Handle(500, "CommitsCount", err)
|
|
return
|
|
}
|
|
results[i].NumCommitsBehind = ctx.Repo.CommitsCount - results[i].NumCommits
|
|
}
|
|
}
|
|
models.SortReleases(results)
|
|
|
|
// Only show drafts if user is viewing the latest page
|
|
var drafts []*models.Release
|
|
if tagsResult.HasLatest {
|
|
drafts, err = models.GetDraftReleasesByRepoID(ctx.Repo.Repository.ID)
|
|
if err != nil {
|
|
ctx.Handle(500, "GetDraftReleasesByRepoID", err)
|
|
return
|
|
}
|
|
|
|
for _, r := range drafts {
|
|
if err = r.LoadAttributes(); err != nil {
|
|
ctx.Handle(500, "LoadAttributes", err)
|
|
return
|
|
}
|
|
|
|
if err := calReleaseNumCommitsBehind(ctx.Repo, r, countCache); err != nil {
|
|
ctx.Handle(500, "calReleaseNumCommitsBehind", err)
|
|
return
|
|
}
|
|
|
|
r.Note = markdown.RenderString(r.Note, ctx.Repo.RepoLink, ctx.Repo.Repository.ComposeMetas())
|
|
}
|
|
|
|
if len(drafts) > 0 {
|
|
results = append(drafts, results...)
|
|
}
|
|
}
|
|
|
|
ctx.Data["Releases"] = results
|
|
ctx.Data["HasPrevious"] = !tagsResult.HasLatest
|
|
ctx.Data["ReachEnd"] = tagsResult.ReachEnd
|
|
ctx.Data["PreviousAfter"] = tagsResult.PreviousAfter
|
|
if len(results) > 0 {
|
|
ctx.Data["NextAfter"] = results[len(results)-1].TagName
|
|
}
|
|
ctx.HTML(200, RELEASES)
|
|
}
|
|
|
|
func NewRelease(ctx *context.Context) {
|
|
ctx.Data["Title"] = ctx.Tr("repo.release.new_release")
|
|
ctx.Data["PageIsReleaseList"] = true
|
|
ctx.Data["tag_target"] = ctx.Repo.Repository.DefaultBranch
|
|
ctx.HTML(200, RELEASE_NEW)
|
|
}
|
|
|
|
func NewReleasePost(ctx *context.Context, f form.NewRelease) {
|
|
ctx.Data["Title"] = ctx.Tr("repo.release.new_release")
|
|
ctx.Data["PageIsReleaseList"] = true
|
|
|
|
if ctx.HasError() {
|
|
ctx.HTML(200, RELEASE_NEW)
|
|
return
|
|
}
|
|
|
|
if !ctx.Repo.GitRepo.IsBranchExist(f.Target) {
|
|
ctx.RenderWithErr(ctx.Tr("form.target_branch_not_exist"), RELEASE_NEW, &f)
|
|
return
|
|
}
|
|
|
|
var tagCreatedUnix int64
|
|
tag, err := ctx.Repo.GitRepo.GetTag(f.TagName)
|
|
if err == nil {
|
|
commit, err := tag.Commit()
|
|
if err == nil {
|
|
tagCreatedUnix = commit.Author.When.Unix()
|
|
}
|
|
}
|
|
|
|
commit, err := ctx.Repo.GitRepo.GetBranchCommit(f.Target)
|
|
if err != nil {
|
|
ctx.Handle(500, "GetBranchCommit", err)
|
|
return
|
|
}
|
|
|
|
commitsCount, err := commit.CommitsCount()
|
|
if err != nil {
|
|
ctx.Handle(500, "CommitsCount", err)
|
|
return
|
|
}
|
|
|
|
rel := &models.Release{
|
|
RepoID: ctx.Repo.Repository.ID,
|
|
PublisherID: ctx.User.ID,
|
|
Title: f.Title,
|
|
TagName: f.TagName,
|
|
Target: f.Target,
|
|
Sha1: commit.ID.String(),
|
|
NumCommits: commitsCount,
|
|
Note: f.Content,
|
|
IsDraft: len(f.Draft) > 0,
|
|
IsPrerelease: f.Prerelease,
|
|
CreatedUnix: tagCreatedUnix,
|
|
}
|
|
|
|
if err = models.CreateRelease(ctx.Repo.GitRepo, rel); err != nil {
|
|
ctx.Data["Err_TagName"] = true
|
|
switch {
|
|
case models.IsErrReleaseAlreadyExist(err):
|
|
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_already_exist"), RELEASE_NEW, &f)
|
|
case models.IsErrInvalidTagName(err):
|
|
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_invalid"), RELEASE_NEW, &f)
|
|
default:
|
|
ctx.Handle(500, "CreateRelease", err)
|
|
}
|
|
return
|
|
}
|
|
log.Trace("Release created: %s/%s:%s", ctx.User.LowerName, ctx.Repo.Repository.Name, f.TagName)
|
|
|
|
ctx.Redirect(ctx.Repo.RepoLink + "/releases")
|
|
}
|
|
|
|
func EditRelease(ctx *context.Context) {
|
|
ctx.Data["Title"] = ctx.Tr("repo.release.edit_release")
|
|
ctx.Data["PageIsReleaseList"] = true
|
|
ctx.Data["PageIsEditRelease"] = true
|
|
|
|
tagName := ctx.Params("*")
|
|
rel, err := models.GetRelease(ctx.Repo.Repository.ID, tagName)
|
|
if err != nil {
|
|
if models.IsErrReleaseNotExist(err) {
|
|
ctx.Handle(404, "GetRelease", err)
|
|
} else {
|
|
ctx.Handle(500, "GetRelease", err)
|
|
}
|
|
return
|
|
}
|
|
ctx.Data["ID"] = rel.ID
|
|
ctx.Data["tag_name"] = rel.TagName
|
|
ctx.Data["tag_target"] = rel.Target
|
|
ctx.Data["title"] = rel.Title
|
|
ctx.Data["content"] = rel.Note
|
|
ctx.Data["prerelease"] = rel.IsPrerelease
|
|
ctx.Data["IsDraft"] = rel.IsDraft
|
|
|
|
ctx.HTML(200, RELEASE_NEW)
|
|
}
|
|
|
|
func EditReleasePost(ctx *context.Context, f form.EditRelease) {
|
|
ctx.Data["Title"] = ctx.Tr("repo.release.edit_release")
|
|
ctx.Data["PageIsReleaseList"] = true
|
|
ctx.Data["PageIsEditRelease"] = true
|
|
|
|
tagName := ctx.Params("*")
|
|
rel, err := models.GetRelease(ctx.Repo.Repository.ID, tagName)
|
|
if err != nil {
|
|
if models.IsErrReleaseNotExist(err) {
|
|
ctx.Handle(404, "GetRelease", err)
|
|
} else {
|
|
ctx.Handle(500, "GetRelease", err)
|
|
}
|
|
return
|
|
}
|
|
ctx.Data["tag_name"] = rel.TagName
|
|
ctx.Data["tag_target"] = rel.Target
|
|
ctx.Data["title"] = rel.Title
|
|
ctx.Data["content"] = rel.Note
|
|
ctx.Data["prerelease"] = rel.IsPrerelease
|
|
ctx.Data["IsDraft"] = rel.IsDraft
|
|
|
|
if ctx.HasError() {
|
|
ctx.HTML(200, RELEASE_NEW)
|
|
return
|
|
}
|
|
|
|
rel.Title = f.Title
|
|
rel.Note = f.Content
|
|
rel.IsDraft = len(f.Draft) > 0
|
|
rel.IsPrerelease = f.Prerelease
|
|
if err = models.UpdateRelease(ctx.Repo.GitRepo, rel); err != nil {
|
|
ctx.Handle(500, "UpdateRelease", err)
|
|
return
|
|
}
|
|
ctx.Redirect(ctx.Repo.RepoLink + "/releases")
|
|
}
|
|
|
|
func DeleteRelease(ctx *context.Context) {
|
|
if err := models.DeleteReleaseOfRepoByID(ctx.Repo.Repository.ID, ctx.QueryInt64("id")); err != nil {
|
|
ctx.Flash.Error("DeleteReleaseByID: " + err.Error())
|
|
} else {
|
|
ctx.Flash.Success(ctx.Tr("repo.release.deletion_success"))
|
|
}
|
|
|
|
ctx.JSON(200, map[string]interface{}{
|
|
"redirect": ctx.Repo.RepoLink + "/releases",
|
|
})
|
|
}
|