2014-04-02 20:43:31 +04:00
// 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 (
2017-01-06 04:51:15 +03:00
"errors"
2016-03-06 22:44:22 +03:00
"fmt"
2017-01-06 04:51:15 +03:00
"code.gitea.io/git"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markdown"
2017-01-15 17:57:00 +03:00
"code.gitea.io/gitea/modules/setting"
2016-11-11 15:11:45 +03:00
"github.com/Unknwon/paginater"
2014-04-02 20:43:31 +04:00
)
2014-06-23 07:11:12 +04:00
const (
2016-11-24 10:04:31 +03:00
tplReleases base . TplName = "repo/release/list"
tplReleaseNew base . TplName = "repo/release/new"
2014-06-23 07:11:12 +04:00
)
2016-07-27 11:57:32 +03:00
// calReleaseNumCommitsBehind calculates given release has how many commits behind release target.
2016-03-11 19:56:52 +03:00
func calReleaseNumCommitsBehind ( repoCtx * context . Repository , release * models . Release , countCache map [ string ] int64 ) error {
2016-03-06 22:44:22 +03:00
// Fast return if release target is same as default branch.
if repoCtx . BranchName == release . Target {
release . NumCommitsBehind = repoCtx . CommitsCount - release . NumCommits
return nil
}
// Get count if not exists
if _ , ok := countCache [ release . Target ] ; ! ok {
2016-07-27 11:57:32 +03:00
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
2016-03-06 22:44:22 +03:00
}
}
2016-07-27 11:57:32 +03:00
release . NumCommitsBehind = countCache [ release . Target ] - release . NumCommits
2016-03-06 22:44:22 +03:00
return nil
}
2016-11-24 10:04:31 +03:00
// Releases render releases list page
2016-03-11 19:56:52 +03:00
func Releases ( ctx * context . Context ) {
2014-12-11 00:37:54 +03:00
ctx . Data [ "Title" ] = ctx . Tr ( "repo.release.releases" )
2015-11-16 19:16:52 +03:00
ctx . Data [ "PageIsReleaseList" ] = true
2014-11-07 06:06:41 +03:00
2017-01-06 04:51:15 +03:00
page := ctx . QueryInt ( "page" )
if page <= 1 {
page = 1
}
limit := ctx . QueryInt ( "limit" )
if limit <= 0 {
limit = 10
}
rawTags , err := ctx . Repo . GitRepo . GetTagInfos ( git . TagOption { } )
2014-07-26 10:28:04 +04:00
if err != nil {
2014-11-07 06:06:41 +03:00
ctx . Handle ( 500 , "GetTags" , err )
2014-07-26 10:28:04 +04:00
return
}
2017-01-09 18:51:21 +03:00
if len ( rawTags ) == 0 {
ctx . HTML ( 200 , tplReleases )
return
}
2017-01-06 04:51:15 +03:00
if len ( rawTags ) <= ( page - 1 ) * limit {
ctx . Handle ( 500 , "Releases" , errors . New ( "no more pages" ) )
return
}
var tags [ ] * git . Tag
if page * limit > len ( rawTags ) {
tags = rawTags [ ( page - 1 ) * limit : ]
} else {
tags = rawTags [ ( page - 1 ) * limit : page * limit ]
2016-11-04 22:28:07 +03:00
}
2017-01-06 04:51:15 +03:00
var tagNames [ ] string
for _ , t := range tags {
tagNames = append ( tagNames , t . Name )
}
releases , err := models . GetReleasesByRepoIDAndNames ( ctx . Repo . Repository . ID , tagNames )
2014-07-26 10:28:04 +04:00
if err != nil {
2017-01-06 04:51:15 +03:00
ctx . Handle ( 500 , "GetReleasesByRepoIDAndNames" , err )
2014-11-07 06:06:41 +03:00
return
}
2017-01-15 17:57:00 +03:00
err = models . GetReleaseAttachments ( releases ... )
if err != nil {
ctx . Handle ( 500 , "GetReleaseAttachments" , err )
return
}
2014-07-26 10:28:04 +04:00
// Temproray cache commits count of used branches to speed up.
2015-12-10 04:46:05 +03:00
countCache := make ( map [ string ] int64 )
2016-12-29 16:21:19 +03:00
var cacheUsers = make ( map [ int64 ] * models . User )
var ok bool
2017-01-06 04:51:15 +03:00
releaseTags := make ( [ ] * models . Release , len ( tags ) )
for i , rawTag := range tags {
for _ , r := range releases {
if r . IsDraft && ! ctx . Repo . IsOwner ( ) {
2014-07-26 10:28:04 +04:00
continue
}
2017-01-06 04:51:15 +03:00
if r . TagName == rawTag . Name {
2016-12-29 16:21:19 +03:00
if r . Publisher , ok = cacheUsers [ r . PublisherID ] ; ! ok {
r . Publisher , err = models . GetUserByID ( r . PublisherID )
if err != nil {
if models . IsErrUserNotExist ( err ) {
r . Publisher = models . NewGhostUser ( )
} else {
ctx . Handle ( 500 , "GetUserByID" , err )
return
}
2016-02-10 23:35:58 +03:00
}
2016-12-29 16:21:19 +03:00
cacheUsers [ r . PublisherID ] = r . Publisher
2014-07-26 10:28:04 +04:00
}
2016-03-06 22:44:22 +03:00
if err := calReleaseNumCommitsBehind ( ctx . Repo , r , countCache ) ; err != nil {
ctx . Handle ( 500 , "calReleaseNumCommitsBehind" , err )
return
2014-07-26 10:28:04 +04:00
}
2016-03-06 22:44:22 +03:00
r . Note = markdown . RenderString ( r . Note , ctx . Repo . RepoLink , ctx . Repo . Repository . ComposeMetas ( ) )
2017-01-06 04:51:15 +03:00
releaseTags [ i ] = r
2014-07-26 10:28:04 +04:00
break
}
}
2017-01-06 04:51:15 +03:00
if releaseTags [ i ] == nil {
releaseTags [ i ] = & models . Release {
Title : rawTag . Name ,
TagName : rawTag . Name ,
Sha1 : rawTag . Object . String ( ) ,
Note : rawTag . Message ,
2014-07-26 10:28:04 +04:00
}
2017-01-06 04:51:15 +03:00
releaseTags [ i ] . NumCommits , err = git . CommitsCount ( ctx . Repo . GitRepo . Path , rawTag . Object . String ( ) )
2014-07-26 10:28:04 +04:00
if err != nil {
ctx . Handle ( 500 , "CommitsCount" , err )
return
}
2017-01-06 04:51:15 +03:00
releaseTags [ i ] . NumCommitsBehind = ctx . Repo . CommitsCount - releaseTags [ i ] . NumCommits
2014-12-11 00:37:54 +03:00
}
}
2017-02-07 18:38:24 +03:00
pager := paginater . New ( len ( rawTags ) , limit , page , 5 )
2016-11-04 22:28:07 +03:00
ctx . Data [ "Page" ] = pager
2017-01-06 04:51:15 +03:00
ctx . Data [ "Releases" ] = releaseTags
2016-11-24 10:04:31 +03:00
ctx . HTML ( 200 , tplReleases )
2014-07-26 10:28:04 +04:00
}
2016-11-24 10:04:31 +03:00
// NewRelease render creating release page
2016-03-11 19:56:52 +03:00
func NewRelease ( ctx * context . Context ) {
2014-12-11 00:37:54 +03:00
ctx . Data [ "Title" ] = ctx . Tr ( "repo.release.new_release" )
2015-11-16 19:16:52 +03:00
ctx . Data [ "PageIsReleaseList" ] = true
2014-12-11 00:37:54 +03:00
ctx . Data [ "tag_target" ] = ctx . Repo . Repository . DefaultBranch
2017-01-29 01:14:56 +03:00
renderAttachmentSettings ( ctx )
2016-11-24 10:04:31 +03:00
ctx . HTML ( 200 , tplReleaseNew )
2014-07-26 10:28:04 +04:00
}
2016-11-24 10:04:31 +03:00
// NewReleasePost response for creating a release
2016-03-11 19:56:52 +03:00
func NewReleasePost ( ctx * context . Context , form auth . NewReleaseForm ) {
2014-12-11 00:37:54 +03:00
ctx . Data [ "Title" ] = ctx . Tr ( "repo.release.new_release" )
2015-11-16 19:16:52 +03:00
ctx . Data [ "PageIsReleaseList" ] = true
2014-07-26 10:28:04 +04:00
if ctx . HasError ( ) {
2016-11-24 10:04:31 +03:00
ctx . HTML ( 200 , tplReleaseNew )
2014-07-26 10:28:04 +04:00
return
}
2014-11-07 06:06:41 +03:00
if ! ctx . Repo . GitRepo . IsBranchExist ( form . Target ) {
2016-11-24 10:04:31 +03:00
ctx . RenderWithErr ( ctx . Tr ( "form.target_branch_not_exist" ) , tplReleaseNew , & form )
2014-11-07 06:06:41 +03:00
return
}
2016-08-06 20:02:15 +03:00
var tagCreatedUnix int64
tag , err := ctx . Repo . GitRepo . GetTag ( form . TagName )
if err == nil {
commit , err := tag . Commit ( )
if err == nil {
tagCreatedUnix = commit . Author . When . Unix ( )
}
}
2015-12-10 04:46:05 +03:00
commit , err := ctx . Repo . GitRepo . GetBranchCommit ( form . Target )
2014-07-26 10:28:04 +04:00
if err != nil {
2015-12-10 04:46:05 +03:00
ctx . Handle ( 500 , "GetBranchCommit" , err )
2014-07-26 10:28:04 +04:00
return
}
2014-11-07 06:06:41 +03:00
commitsCount , err := commit . CommitsCount ( )
if err != nil {
ctx . Handle ( 500 , "CommitsCount" , err )
2014-07-26 10:28:04 +04:00
return
}
rel := & models . Release {
2015-11-16 07:52:46 +03:00
RepoID : ctx . Repo . Repository . ID ,
2016-07-23 20:08:22 +03:00
PublisherID : ctx . User . ID ,
2014-07-26 10:28:04 +04:00
Title : form . Title ,
TagName : form . TagName ,
Target : form . Target ,
2015-11-04 06:49:06 +03:00
Sha1 : commit . ID . String ( ) ,
2014-07-26 10:28:04 +04:00
NumCommits : commitsCount ,
Note : form . Content ,
IsDraft : len ( form . Draft ) > 0 ,
IsPrerelease : form . Prerelease ,
2016-08-06 20:02:15 +03:00
CreatedUnix : tagCreatedUnix ,
2014-07-26 10:28:04 +04:00
}
2017-01-15 17:57:00 +03:00
var attachmentUUIDs [ ] string
if setting . AttachmentEnabled {
attachmentUUIDs = form . Files
}
if err = models . CreateRelease ( ctx . Repo . GitRepo , rel , attachmentUUIDs ) ; err != nil {
2016-07-23 10:59:19 +03:00
ctx . Data [ "Err_TagName" ] = true
switch {
case models . IsErrReleaseAlreadyExist ( err ) :
2016-11-24 10:04:31 +03:00
ctx . RenderWithErr ( ctx . Tr ( "repo.release.tag_name_already_exist" ) , tplReleaseNew , & form )
2016-07-23 10:59:19 +03:00
case models . IsErrInvalidTagName ( err ) :
2016-11-24 10:04:31 +03:00
ctx . RenderWithErr ( ctx . Tr ( "repo.release.tag_name_invalid" ) , tplReleaseNew , & form )
2016-07-23 10:59:19 +03:00
default :
2014-12-11 00:37:54 +03:00
ctx . Handle ( 500 , "CreateRelease" , err )
2014-07-26 10:28:04 +04:00
}
return
}
2015-11-16 07:52:46 +03:00
log . Trace ( "Release created: %s/%s:%s" , ctx . User . LowerName , ctx . Repo . Repository . Name , form . TagName )
2014-07-26 10:28:04 +04:00
ctx . Redirect ( ctx . Repo . RepoLink + "/releases" )
}
2016-11-24 10:04:31 +03:00
// EditRelease render release edit page
2016-03-11 19:56:52 +03:00
func EditRelease ( ctx * context . Context ) {
2015-11-16 07:52:46 +03:00
ctx . Data [ "Title" ] = ctx . Tr ( "repo.release.edit_release" )
2015-11-16 19:16:52 +03:00
ctx . Data [ "PageIsReleaseList" ] = true
2015-11-16 07:52:46 +03:00
ctx . Data [ "PageIsEditRelease" ] = true
2017-01-29 01:14:56 +03:00
renderAttachmentSettings ( ctx )
2014-07-26 10:28:04 +04:00
2016-08-11 23:45:42 +03:00
tagName := ctx . Params ( "*" )
2015-08-08 17:43:14 +03:00
rel , err := models . GetRelease ( ctx . Repo . Repository . ID , tagName )
2014-07-26 10:28:04 +04:00
if err != nil {
2015-11-16 07:52:46 +03:00
if models . IsErrReleaseNotExist ( err ) {
2014-12-11 00:37:54 +03:00
ctx . Handle ( 404 , "GetRelease" , err )
2014-07-26 10:28:04 +04:00
} else {
2014-12-11 00:37:54 +03:00
ctx . Handle ( 500 , "GetRelease" , err )
2014-07-26 10:28:04 +04:00
}
return
}
2015-11-20 10:38:41 +03:00
ctx . Data [ "ID" ] = rel . ID
2015-11-16 07:52:46 +03:00
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
2016-11-14 19:30:22 +03:00
ctx . Data [ "IsDraft" ] = rel . IsDraft
2014-07-26 10:28:04 +04:00
2016-11-24 10:04:31 +03:00
ctx . HTML ( 200 , tplReleaseNew )
2014-07-26 10:28:04 +04:00
}
2016-11-24 10:04:31 +03:00
// EditReleasePost response for edit release
2016-03-11 19:56:52 +03:00
func EditReleasePost ( ctx * context . Context , form auth . EditReleaseForm ) {
2015-11-16 07:52:46 +03:00
ctx . Data [ "Title" ] = ctx . Tr ( "repo.release.edit_release" )
2015-11-16 19:16:52 +03:00
ctx . Data [ "PageIsReleaseList" ] = true
2015-11-16 07:52:46 +03:00
ctx . Data [ "PageIsEditRelease" ] = true
2014-07-26 10:28:04 +04:00
2016-08-11 23:45:42 +03:00
tagName := ctx . Params ( "*" )
2015-08-08 17:43:14 +03:00
rel , err := models . GetRelease ( ctx . Repo . Repository . ID , tagName )
2014-07-26 10:28:04 +04:00
if err != nil {
2015-11-16 07:52:46 +03:00
if models . IsErrReleaseNotExist ( err ) {
2014-12-11 00:37:54 +03:00
ctx . Handle ( 404 , "GetRelease" , err )
2014-07-26 10:28:04 +04:00
} else {
2014-12-11 00:37:54 +03:00
ctx . Handle ( 500 , "GetRelease" , err )
2014-07-26 10:28:04 +04:00
}
return
}
2015-11-16 07:52:46 +03:00
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
2014-07-26 10:28:04 +04:00
if ctx . HasError ( ) {
2016-11-24 10:04:31 +03:00
ctx . HTML ( 200 , tplReleaseNew )
2014-07-26 10:28:04 +04:00
return
}
2017-01-15 17:57:00 +03:00
var attachmentUUIDs [ ] string
if setting . AttachmentEnabled {
attachmentUUIDs = form . Files
}
2014-07-26 10:28:04 +04:00
rel . Title = form . Title
rel . Note = form . Content
rel . IsDraft = len ( form . Draft ) > 0
rel . IsPrerelease = form . Prerelease
2017-01-15 17:57:00 +03:00
if err = models . UpdateRelease ( ctx . Repo . GitRepo , rel , attachmentUUIDs ) ; err != nil {
2014-12-11 00:37:54 +03:00
ctx . Handle ( 500 , "UpdateRelease" , err )
2014-07-26 10:28:04 +04:00
return
}
ctx . Redirect ( ctx . Repo . RepoLink + "/releases" )
}
2015-11-20 10:38:41 +03:00
2016-11-24 10:04:31 +03:00
// DeleteRelease delete a release
2016-03-11 19:56:52 +03:00
func DeleteRelease ( ctx * context . Context ) {
2016-12-31 14:51:12 +03:00
delTag := ctx . QueryBool ( "delTag" )
if err := models . DeleteReleaseByID ( ctx . QueryInt64 ( "id" ) , ctx . User , delTag ) ; err != nil {
2015-11-20 10:38:41 +03:00
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" ,
} )
}