2014-04-02 20:43:31 +04:00
// Copyright 2014 The Gogs Authors. All rights reserved.
2018-11-28 14:26:14 +03:00
// Copyright 2018 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2014-04-02 20:43:31 +04:00
package repo
import (
2023-05-10 06:43:55 +03:00
"errors"
2016-03-06 22:44:22 +03:00
"fmt"
2021-04-05 18:30:52 +03:00
"net/http"
2021-03-22 19:09:51 +03:00
"strings"
2016-03-06 22:44:22 +03:00
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/models"
2021-09-24 14:32:56 +03:00
"code.gitea.io/gitea/models/db"
2024-02-19 13:27:05 +03:00
git_model "code.gitea.io/gitea/models/git"
2022-08-25 05:31:57 +03:00
repo_model "code.gitea.io/gitea/models/repo"
2021-11-09 22:57:58 +03:00
"code.gitea.io/gitea/models/unit"
2021-11-24 12:49:20 +03:00
user_model "code.gitea.io/gitea/models/user"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/modules/base"
2023-05-10 06:43:55 +03:00
"code.gitea.io/gitea/modules/git"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/modules/log"
2021-04-20 01:25:08 +03:00
"code.gitea.io/gitea/modules/markup"
2017-09-21 08:20:14 +03:00
"code.gitea.io/gitea/modules/markup/markdown"
2024-02-28 08:39:12 +03:00
"code.gitea.io/gitea/modules/optional"
2017-01-15 17:57:00 +03:00
"code.gitea.io/gitea/modules/setting"
2021-11-16 21:18:25 +03:00
"code.gitea.io/gitea/modules/util"
2021-01-26 18:36:53 +03:00
"code.gitea.io/gitea/modules/web"
2022-12-22 00:06:26 +03:00
"code.gitea.io/gitea/routers/web/feed"
2024-02-27 10:12:22 +03:00
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/context/upload"
2021-04-06 22:44:05 +03:00
"code.gitea.io/gitea/services/forms"
2019-09-15 18:28:25 +03:00
releaseservice "code.gitea.io/gitea/services/release"
2014-04-02 20:43:31 +04:00
)
2014-06-23 07:11:12 +04:00
const (
2023-04-25 19:29:00 +03:00
tplReleasesList base . TplName = "repo/release/list"
tplReleaseNew base . TplName = "repo/release/new"
tplTagsList base . TplName = "repo/tag/list"
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.
2022-08-25 05:31:57 +03:00
func calReleaseNumCommitsBehind ( repoCtx * context . Repository , release * repo_model . Release , countCache map [ string ] int64 ) error {
2023-05-10 06:43:55 +03:00
target := release . Target
if target == "" {
target = repoCtx . Repository . DefaultBranch
}
// Get count if not cached
if _ , ok := countCache [ target ] ; ! ok {
commit , err := repoCtx . GitRepo . GetBranchCommit ( target )
if err != nil {
var errNotExist git . ErrNotExist
if target == repoCtx . Repository . DefaultBranch || ! errors . As ( err , & errNotExist ) {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "GetBranchCommit: %w" , err )
2016-07-27 11:57:32 +03:00
}
2023-05-10 06:43:55 +03:00
// fallback to default branch
target = repoCtx . Repository . DefaultBranch
commit , err = repoCtx . GitRepo . GetBranchCommit ( target )
2016-07-27 11:57:32 +03:00
if err != nil {
2023-05-10 06:43:55 +03:00
return fmt . Errorf ( "GetBranchCommit(DefaultBranch): %w" , err )
2016-07-27 11:57:32 +03:00
}
2023-05-10 06:43:55 +03:00
}
countCache [ target ] , err = commit . CommitsCount ( )
if err != nil {
return fmt . Errorf ( "CommitsCount: %w" , err )
2016-03-06 22:44:22 +03:00
}
}
2023-05-10 06:43:55 +03:00
release . NumCommitsBehind = countCache [ target ] - release . NumCommits
release . TargetBehind = target
2016-03-06 22:44:22 +03:00
return nil
}
2024-02-19 13:27:05 +03:00
type ReleaseInfo struct {
Release * repo_model . Release
CommitStatus * git_model . CommitStatus
CommitStatuses [ ] * git_model . CommitStatus
}
2017-06-29 18:11:38 +03:00
2024-02-19 13:27:05 +03:00
func getReleaseInfos ( ctx * context . Context , opts * repo_model . FindReleasesOptions ) ( [ ] * ReleaseInfo , error ) {
2024-01-15 05:19:25 +03:00
releases , err := db . Find [ repo_model . Release ] ( ctx , opts )
2014-07-26 10:28:04 +04:00
if err != nil {
2024-02-19 13:27:05 +03:00
return nil , err
2017-06-28 17:47:00 +03:00
}
2023-04-12 12:05:23 +03:00
for _ , release := range releases {
release . Repo = ctx . Repo . Repository
}
2022-08-25 05:31:57 +03:00
if err = repo_model . GetReleaseAttachments ( ctx , releases ... ) ; err != nil {
2024-02-19 13:27:05 +03:00
return nil , err
2017-01-15 17:57:00 +03:00
}
2017-06-03 06:46:56 +03:00
// Temporary cache commits count of used branches to speed up.
2015-12-10 04:46:05 +03:00
countCache := make ( map [ string ] int64 )
2021-11-24 12:49:20 +03:00
cacheUsers := make ( map [ int64 ] * user_model . User )
2022-03-22 10:03:22 +03:00
if ctx . Doer != nil {
cacheUsers [ ctx . Doer . ID ] = ctx . Doer
2017-06-18 06:38:24 +03:00
}
2016-12-29 16:21:19 +03:00
var ok bool
2016-03-06 22:44:22 +03:00
2024-02-19 13:27:05 +03:00
canReadActions := ctx . Repo . CanRead ( unit . TypeActions )
releaseInfos := make ( [ ] * ReleaseInfo , 0 , len ( releases ) )
2017-06-03 06:46:56 +03:00
for _ , r := range releases {
if r . Publisher , ok = cacheUsers [ r . PublisherID ] ; ! ok {
2022-12-03 05:48:26 +03:00
r . Publisher , err = user_model . GetUserByID ( ctx , r . PublisherID )
2017-06-03 06:46:56 +03:00
if err != nil {
2021-11-24 12:49:20 +03:00
if user_model . IsErrUserNotExist ( err ) {
r . Publisher = user_model . NewGhostUser ( )
2017-06-03 06:46:56 +03:00
} else {
2024-02-19 13:27:05 +03:00
return nil , err
2014-07-26 10:28:04 +04:00
}
}
2017-06-03 06:46:56 +03:00
cacheUsers [ r . PublisherID ] = r . Publisher
2014-07-26 10:28:04 +04:00
}
2021-05-06 06:12:50 +03:00
2024-03-01 10:11:51 +03:00
r . RenderedNote , err = markdown . RenderString ( & markup . RenderContext {
2024-01-15 11:49:24 +03:00
Links : markup . Links {
Base : ctx . Repo . RepoLink ,
} ,
Metas : ctx . Repo . Repository . ComposeMetas ( ctx ) ,
GitRepo : ctx . Repo . GitRepo ,
Ctx : ctx ,
2021-04-20 01:25:08 +03:00
} , r . Note )
if err != nil {
2024-02-19 13:27:05 +03:00
return nil , err
2021-04-20 01:25:08 +03:00
}
2021-05-06 06:12:50 +03:00
2024-02-19 13:27:05 +03:00
if ! r . IsDraft {
if err := calReleaseNumCommitsBehind ( ctx . Repo , r , countCache ) ; err != nil {
return nil , err
}
2021-05-06 06:12:50 +03:00
}
2024-02-19 13:27:05 +03:00
info := & ReleaseInfo {
Release : r ,
2021-05-06 06:12:50 +03:00
}
2024-02-19 13:27:05 +03:00
if canReadActions {
statuses , _ , err := git_model . GetLatestCommitStatus ( ctx , r . Repo . ID , r . Sha1 , db . ListOptions { ListAll : true } )
if err != nil {
return nil , err
}
info . CommitStatus = git_model . CalcCommitStatus ( statuses )
info . CommitStatuses = statuses
}
releaseInfos = append ( releaseInfos , info )
}
return releaseInfos , nil
}
// Releases render releases list page
func Releases ( ctx * context . Context ) {
ctx . Data [ "PageIsReleaseList" ] = true
ctx . Data [ "Title" ] = ctx . Tr ( "repo.release.releases" )
ctx . Data [ "IsViewBranch" ] = false
ctx . Data [ "IsViewTag" ] = true
// Disable the showCreateNewBranch form in the dropdown on this page.
ctx . Data [ "CanCreateBranch" ] = false
ctx . Data [ "HideBranchesInDropdown" ] = true
listOptions := db . ListOptions {
Page : ctx . FormInt ( "page" ) ,
PageSize : ctx . FormInt ( "limit" ) ,
}
if listOptions . PageSize == 0 {
listOptions . PageSize = setting . Repository . Release . DefaultPagingNum
}
if listOptions . PageSize > setting . API . MaxResponseItems {
listOptions . PageSize = setting . API . MaxResponseItems
}
writeAccess := ctx . Repo . CanWrite ( unit . TypeReleases )
ctx . Data [ "CanCreateRelease" ] = writeAccess && ! ctx . Repo . Repository . IsArchived
releases , err := getReleaseInfos ( ctx , & repo_model . FindReleasesOptions {
ListOptions : listOptions ,
// only show draft releases for users who can write, read-only users shouldn't see draft releases.
IncludeDrafts : writeAccess ,
RepoID : ctx . Repo . Repository . ID ,
} )
if err != nil {
ctx . ServerError ( "getReleaseInfos" , err )
return
2014-12-11 00:37:54 +03:00
}
Fix a bug returning 404 when display a single tag with no release (#29466)
Partially caused by #29149
When use
```go
releases, err := getReleaseInfos(ctx, &repo_model.FindReleasesOptions{
ListOptions: db.ListOptions{Page: 1, PageSize: 1},
RepoID: ctx.Repo.Repository.ID,
TagNames: []string{ctx.Params("*")},
// only show draft releases for users who can write, read-only users shouldn't see draft releases.
IncludeDrafts: writeAccess,
})
```
replace
```go
release, err := repo_model.GetRelease(ctx, ctx.Repo.Repository.ID, ctx.Params("*"))
```
It missed `IncludeTags: true,`. That means this bug will be occupied only when the release is a tag.
This PR will fix
- Get the right tag record when it's not a release
- Display correct tag tab but not release tag when it's a tag.
- The button will bring the tag name to the new page when it's a single tag page
- the new page will automatically hide the release target inputbox when the tag name is pre filled. This should be backport to v1.21.
2024-03-02 17:03:39 +03:00
for _ , rel := range releases {
if rel . Release . IsTag && rel . Release . Title == "" {
rel . Release . Title = rel . Release . TagName
}
}
2014-12-11 00:37:54 +03:00
2017-06-29 18:11:38 +03:00
ctx . Data [ "Releases" ] = releases
2019-04-20 07:15:19 +03:00
2023-09-28 16:21:47 +03:00
numReleases := ctx . Data [ "NumReleases" ] . ( int64 )
2024-02-19 13:27:05 +03:00
pager := context . NewPagination ( int ( numReleases ) , listOptions . PageSize , listOptions . Page , 5 )
2019-04-20 07:15:19 +03:00
pager . SetDefaultParams ( ctx )
ctx . Data [ "Page" ] = pager
2023-09-28 16:21:47 +03:00
ctx . HTML ( http . StatusOK , tplReleasesList )
}
// TagsList render tags list page
func TagsList ( ctx * context . Context ) {
ctx . Data [ "PageIsTagList" ] = true
ctx . Data [ "Title" ] = ctx . Tr ( "repo.release.tags" )
ctx . Data [ "IsViewBranch" ] = false
ctx . Data [ "IsViewTag" ] = true
// Disable the showCreateNewBranch form in the dropdown on this page.
ctx . Data [ "CanCreateBranch" ] = false
ctx . Data [ "HideBranchesInDropdown" ] = true
2023-11-30 18:26:56 +03:00
ctx . Data [ "CanCreateRelease" ] = ctx . Repo . CanWrite ( unit . TypeReleases ) && ! ctx . Repo . Repository . IsArchived
2023-09-28 16:21:47 +03:00
listOptions := db . ListOptions {
Page : ctx . FormInt ( "page" ) ,
PageSize : ctx . FormInt ( "limit" ) ,
}
if listOptions . PageSize == 0 {
listOptions . PageSize = setting . Repository . Release . DefaultPagingNum
}
if listOptions . PageSize > setting . API . MaxResponseItems {
listOptions . PageSize = setting . API . MaxResponseItems
}
opts := repo_model . FindReleasesOptions {
ListOptions : listOptions ,
// for the tags list page, show all releases with real tags (having real commit-id),
// the drafts should also be included because a real tag might be used as a draft.
IncludeDrafts : true ,
IncludeTags : true ,
2024-02-28 08:39:12 +03:00
HasSha1 : optional . Some ( true ) ,
2024-01-15 05:19:25 +03:00
RepoID : ctx . Repo . Repository . ID ,
2023-09-28 16:21:47 +03:00
}
2024-01-15 05:19:25 +03:00
releases , err := db . Find [ repo_model . Release ] ( ctx , opts )
2023-09-28 16:21:47 +03:00
if err != nil {
ctx . ServerError ( "GetReleasesByRepoID" , err )
return
2023-04-25 19:29:00 +03:00
}
2023-09-28 16:21:47 +03:00
ctx . Data [ "Releases" ] = releases
numTags := ctx . Data [ "NumTags" ] . ( int64 )
pager := context . NewPagination ( int ( numTags ) , opts . PageSize , opts . Page , 5 )
pager . SetDefaultParams ( ctx )
ctx . Data [ "Page" ] = pager
ctx . Data [ "PageIsViewCode" ] = ! ctx . Repo . Repository . UnitEnabled ( ctx , unit . TypeReleases )
ctx . HTML ( http . StatusOK , tplTagsList )
2014-07-26 10:28:04 +04:00
}
2022-12-22 00:06:26 +03:00
// ReleasesFeedRSS get feeds for releases in RSS format
func ReleasesFeedRSS ( ctx * context . Context ) {
releasesOrTagsFeed ( ctx , true , "rss" )
}
// TagsListFeedRSS get feeds for tags in RSS format
func TagsListFeedRSS ( ctx * context . Context ) {
releasesOrTagsFeed ( ctx , false , "rss" )
}
// ReleasesFeedAtom get feeds for releases in Atom format
func ReleasesFeedAtom ( ctx * context . Context ) {
releasesOrTagsFeed ( ctx , true , "atom" )
}
// TagsListFeedAtom get feeds for tags in RSS format
func TagsListFeedAtom ( ctx * context . Context ) {
releasesOrTagsFeed ( ctx , false , "atom" )
}
func releasesOrTagsFeed ( ctx * context . Context , isReleasesOnly bool , formatType string ) {
feed . ShowReleaseFeed ( ctx , ctx . Repo . Repository , isReleasesOnly , formatType )
}
2020-04-18 17:47:15 +03:00
// SingleRelease renders a single release's page
func SingleRelease ( ctx * context . Context ) {
ctx . Data [ "PageIsReleaseList" ] = true
2023-03-27 16:41:33 +03:00
ctx . Data [ "DefaultBranch" ] = ctx . Repo . Repository . DefaultBranch
2020-04-18 17:47:15 +03:00
2021-11-09 22:57:58 +03:00
writeAccess := ctx . Repo . CanWrite ( unit . TypeReleases )
2020-04-18 17:47:15 +03:00
ctx . Data [ "CanCreateRelease" ] = writeAccess && ! ctx . Repo . Repository . IsArchived
2024-02-19 13:27:05 +03:00
releases , err := getReleaseInfos ( ctx , & repo_model . FindReleasesOptions {
ListOptions : db . ListOptions { Page : 1 , PageSize : 1 } ,
RepoID : ctx . Repo . Repository . ID ,
TagNames : [ ] string { ctx . Params ( "*" ) } ,
// only show draft releases for users who can write, read-only users shouldn't see draft releases.
IncludeDrafts : writeAccess ,
Fix a bug returning 404 when display a single tag with no release (#29466)
Partially caused by #29149
When use
```go
releases, err := getReleaseInfos(ctx, &repo_model.FindReleasesOptions{
ListOptions: db.ListOptions{Page: 1, PageSize: 1},
RepoID: ctx.Repo.Repository.ID,
TagNames: []string{ctx.Params("*")},
// only show draft releases for users who can write, read-only users shouldn't see draft releases.
IncludeDrafts: writeAccess,
})
```
replace
```go
release, err := repo_model.GetRelease(ctx, ctx.Repo.Repository.ID, ctx.Params("*"))
```
It missed `IncludeTags: true,`. That means this bug will be occupied only when the release is a tag.
This PR will fix
- Get the right tag record when it's not a release
- Display correct tag tab but not release tag when it's a tag.
- The button will bring the tag name to the new page when it's a single tag page
- the new page will automatically hide the release target inputbox when the tag name is pre filled. This should be backport to v1.21.
2024-03-02 17:03:39 +03:00
IncludeTags : true ,
2024-02-19 13:27:05 +03:00
} )
2020-04-18 17:47:15 +03:00
if err != nil {
2024-02-19 13:27:05 +03:00
ctx . ServerError ( "getReleaseInfos" , err )
return
}
if len ( releases ) != 1 {
ctx . NotFound ( "SingleRelease" , err )
2020-04-18 17:47:15 +03:00
return
}
2024-02-19 13:27:05 +03:00
release := releases [ 0 ] . Release
Fix a bug returning 404 when display a single tag with no release (#29466)
Partially caused by #29149
When use
```go
releases, err := getReleaseInfos(ctx, &repo_model.FindReleasesOptions{
ListOptions: db.ListOptions{Page: 1, PageSize: 1},
RepoID: ctx.Repo.Repository.ID,
TagNames: []string{ctx.Params("*")},
// only show draft releases for users who can write, read-only users shouldn't see draft releases.
IncludeDrafts: writeAccess,
})
```
replace
```go
release, err := repo_model.GetRelease(ctx, ctx.Repo.Repository.ID, ctx.Params("*"))
```
It missed `IncludeTags: true,`. That means this bug will be occupied only when the release is a tag.
This PR will fix
- Get the right tag record when it's not a release
- Display correct tag tab but not release tag when it's a tag.
- The button will bring the tag name to the new page when it's a single tag page
- the new page will automatically hide the release target inputbox when the tag name is pre filled. This should be backport to v1.21.
2024-03-02 17:03:39 +03:00
if release . IsTag && release . Title == "" {
release . Title = release . TagName
}
2024-02-19 13:27:05 +03:00
2023-03-27 16:41:33 +03:00
ctx . Data [ "PageIsSingleTag" ] = release . IsTag
if release . IsTag {
ctx . Data [ "Title" ] = release . TagName
} else {
ctx . Data [ "Title" ] = release . Title
}
2020-04-18 17:47:15 +03:00
2024-02-19 13:27:05 +03:00
ctx . Data [ "Releases" ] = releases
2023-04-25 19:29:00 +03:00
ctx . HTML ( http . StatusOK , tplReleasesList )
2020-04-18 17:47:15 +03:00
}
// LatestRelease redirects to the latest release
func LatestRelease ( ctx * context . Context ) {
2023-09-25 16:17:37 +03:00
release , err := repo_model . GetLatestReleaseByRepoID ( ctx , ctx . Repo . Repository . ID )
2020-04-18 17:47:15 +03:00
if err != nil {
2022-08-25 05:31:57 +03:00
if repo_model . IsErrReleaseNotExist ( err ) {
2020-04-18 17:47:15 +03:00
ctx . NotFound ( "LatestRelease" , err )
return
}
ctx . ServerError ( "GetLatestReleaseByRepoID" , err )
return
}
2022-11-19 11:12:33 +03:00
if err := release . LoadAttributes ( ctx ) ; err != nil {
2020-04-18 17:47:15 +03:00
ctx . ServerError ( "LoadAttributes" , err )
return
}
2023-02-11 09:34:11 +03:00
ctx . Redirect ( release . Link ( ) )
2020-04-18 17:47:15 +03:00
}
2021-03-22 19:09:51 +03:00
// NewRelease render creating or edit 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
2021-08-11 03:31:13 +03:00
if tagName := ctx . FormString ( "tag" ) ; len ( tagName ) > 0 {
2023-09-25 16:17:37 +03:00
rel , err := repo_model . GetRelease ( ctx , ctx . Repo . Repository . ID , tagName )
2022-08-25 05:31:57 +03:00
if err != nil && ! repo_model . IsErrReleaseNotExist ( err ) {
2020-11-03 02:10:22 +03:00
ctx . ServerError ( "GetRelease" , err )
return
}
if rel != nil {
2021-03-22 19:09:51 +03:00
rel . Repo = ctx . Repo . Repository
2022-11-19 11:12:33 +03:00
if err := rel . LoadAttributes ( ctx ) ; err != nil {
2021-03-22 19:09:51 +03:00
ctx . ServerError ( "LoadAttributes" , err )
return
}
2020-11-03 02:10:22 +03:00
ctx . Data [ "tag_name" ] = rel . TagName
2022-05-10 15:41:37 +03:00
if rel . Target != "" {
ctx . Data [ "tag_target" ] = rel . Target
}
2020-11-03 02:10:22 +03:00
ctx . Data [ "title" ] = rel . Title
ctx . Data [ "content" ] = rel . Note
2021-03-22 19:09:51 +03:00
ctx . Data [ "attachments" ] = rel . Attachments
2020-11-03 02:10:22 +03:00
}
}
2020-10-05 08:49:33 +03:00
ctx . Data [ "IsAttachmentEnabled" ] = setting . Attachment . Enabled
2023-04-07 03:11:02 +03:00
assigneeUsers , err := repo_model . GetRepoAssignees ( ctx , ctx . Repo . Repository )
2023-02-01 22:14:40 +03:00
if err != nil {
2023-04-07 03:11:02 +03:00
ctx . ServerError ( "GetRepoAssignees" , err )
2023-02-01 22:14:40 +03:00
return
}
2023-08-25 14:07:42 +03:00
ctx . Data [ "Assignees" ] = MakeSelfOnTop ( ctx . Doer , assigneeUsers )
2023-02-01 22:14:40 +03:00
2020-10-05 08:49:33 +03:00
upload . AddUploadContext ( ctx , "release" )
2023-07-21 14:20:04 +03:00
// For New Release page
PrepareBranchList ( ctx )
if ctx . Written ( ) {
return
}
tags , err := repo_model . GetTagNamesByRepoID ( ctx , ctx . Repo . Repository . ID )
if err != nil {
ctx . ServerError ( "GetTagNamesByRepoID" , err )
return
}
ctx . Data [ "Tags" ] = tags
2021-04-05 18:30:52 +03:00
ctx . HTML ( http . StatusOK , tplReleaseNew )
2014-07-26 10:28:04 +04:00
}
2016-11-24 10:04:31 +03:00
// NewReleasePost response for creating a release
2021-01-26 18:36:53 +03:00
func NewReleasePost ( ctx * context . Context ) {
2021-04-06 22:44:05 +03:00
form := web . GetForm ( ctx ) . ( * forms . 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
2023-07-21 14:20:04 +03:00
tags , err := repo_model . GetTagNamesByRepoID ( ctx , ctx . Repo . Repository . ID )
if err != nil {
ctx . ServerError ( "GetTagNamesByRepoID" , err )
return
}
ctx . Data [ "Tags" ] = tags
2014-07-26 10:28:04 +04:00
if ctx . HasError ( ) {
2021-04-05 18:30:52 +03:00
ctx . HTML ( http . StatusOK , 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 )
2023-04-07 04:44:52 +03:00
return
}
// Title of release cannot be empty
if len ( form . TagOnly ) == 0 && len ( form . Title ) == 0 {
ctx . RenderWithErr ( ctx . Tr ( "repo.release.title_empty" ) , tplReleaseNew , & form )
2014-11-07 06:06:41 +03:00
return
}
2017-09-20 08:26:49 +03:00
var attachmentUUIDs [ ] string
2020-08-18 07:23:45 +03:00
if setting . Attachment . Enabled {
2017-09-20 08:26:49 +03:00
attachmentUUIDs = form . Files
2016-08-06 20:02:15 +03:00
}
2023-09-25 16:17:37 +03:00
rel , err := repo_model . GetRelease ( ctx , ctx . Repo . Repository . ID , form . TagName )
2014-07-26 10:28:04 +04:00
if err != nil {
2022-08-25 05:31:57 +03:00
if ! repo_model . IsErrReleaseNotExist ( err ) {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "GetRelease" , err )
2017-09-20 08:26:49 +03:00
return
}
2014-07-26 10:28:04 +04:00
2021-02-28 22:57:45 +03:00
msg := ""
if len ( form . Title ) > 0 && form . AddTagMsg {
msg = form . Title + "\n\n" + form . Content
}
if len ( form . TagOnly ) > 0 {
2022-03-22 10:03:22 +03:00
if err = releaseservice . CreateNewTag ( ctx , ctx . Doer , ctx . Repo . Repository , form . Target , form . TagName , msg ) ; err != nil {
2021-02-28 22:57:45 +03:00
if models . IsErrTagAlreadyExists ( err ) {
e := err . ( models . ErrTagAlreadyExists )
ctx . Flash . Error ( ctx . Tr ( "repo.branch.tag_collision" , e . TagName ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/src/" + ctx . Repo . BranchNameSubURL ( ) )
return
}
2021-06-25 17:28:55 +03:00
if models . IsErrInvalidTagName ( err ) {
ctx . Flash . Error ( ctx . Tr ( "repo.release.tag_name_invalid" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/src/" + ctx . Repo . BranchNameSubURL ( ) )
return
}
if models . IsErrProtectedTagName ( err ) {
ctx . Flash . Error ( ctx . Tr ( "repo.release.tag_name_protected" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/src/" + ctx . Repo . BranchNameSubURL ( ) )
return
}
2021-02-28 22:57:45 +03:00
ctx . ServerError ( "releaseservice.CreateNewTag" , err )
return
}
ctx . Flash . Success ( ctx . Tr ( "repo.tag.create_success" , form . TagName ) )
2021-11-16 21:18:25 +03:00
ctx . Redirect ( ctx . Repo . RepoLink + "/src/tag/" + util . PathEscapeSegments ( form . TagName ) )
2021-02-28 22:57:45 +03:00
return
}
2022-08-25 05:31:57 +03:00
rel = & repo_model . Release {
2017-09-20 08:26:49 +03:00
RepoID : ctx . Repo . Repository . ID ,
2021-06-25 17:28:55 +03:00
Repo : ctx . Repo . Repository ,
2022-03-22 10:03:22 +03:00
PublisherID : ctx . Doer . ID ,
Publisher : ctx . Doer ,
2017-09-20 08:26:49 +03:00
Title : form . Title ,
TagName : form . TagName ,
Target : form . Target ,
Note : form . Content ,
IsDraft : len ( form . Draft ) > 0 ,
IsPrerelease : form . Prerelease ,
IsTag : false ,
}
2014-07-26 10:28:04 +04:00
2021-02-28 22:57:45 +03:00
if err = releaseservice . CreateRelease ( ctx . Repo . GitRepo , rel , attachmentUUIDs , msg ) ; err != nil {
2017-09-20 08:26:49 +03:00
ctx . Data [ "Err_TagName" ] = true
switch {
2022-08-25 05:31:57 +03:00
case repo_model . IsErrReleaseAlreadyExist ( err ) :
2017-09-20 08:26:49 +03:00
ctx . RenderWithErr ( ctx . Tr ( "repo.release.tag_name_already_exist" ) , tplReleaseNew , & form )
case models . IsErrInvalidTagName ( err ) :
ctx . RenderWithErr ( ctx . Tr ( "repo.release.tag_name_invalid" ) , tplReleaseNew , & form )
2021-06-25 17:28:55 +03:00
case models . IsErrProtectedTagName ( err ) :
ctx . RenderWithErr ( ctx . Tr ( "repo.release.tag_name_protected" ) , tplReleaseNew , & form )
2017-09-20 08:26:49 +03:00
default :
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "CreateRelease" , err )
2017-09-20 08:26:49 +03:00
}
return
}
} else {
if ! rel . IsTag {
ctx . Data [ "Err_TagName" ] = true
ctx . RenderWithErr ( ctx . Tr ( "repo.release.tag_name_already_exist" ) , tplReleaseNew , & form )
return
}
2014-07-26 10:28:04 +04:00
2017-09-20 08:26:49 +03:00
rel . Title = form . Title
rel . Note = form . Content
2017-12-08 08:22:02 +03:00
rel . Target = form . Target
2017-09-20 08:26:49 +03:00
rel . IsDraft = len ( form . Draft ) > 0
rel . IsPrerelease = form . Prerelease
2022-03-22 10:03:22 +03:00
rel . PublisherID = ctx . Doer . ID
2017-09-20 08:26:49 +03:00
rel . IsTag = false
2017-01-15 17:57:00 +03:00
2023-09-25 16:17:37 +03:00
if err = releaseservice . UpdateRelease ( ctx , ctx . Doer , ctx . Repo . GitRepo , rel , attachmentUUIDs , nil , nil ) ; err != nil {
2017-09-20 08:26:49 +03:00
ctx . Data [ "Err_TagName" ] = true
2021-03-22 19:09:51 +03:00
ctx . ServerError ( "UpdateRelease" , err )
2017-09-20 08:26:49 +03:00
return
2014-07-26 10:28:04 +04:00
}
}
2022-03-22 10:03:22 +03:00
log . Trace ( "Release created: %s/%s:%s" , ctx . Doer . 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
2020-10-05 08:49:33 +03:00
ctx . Data [ "IsAttachmentEnabled" ] = setting . Attachment . Enabled
upload . AddUploadContext ( ctx , "release" )
2014-07-26 10:28:04 +04:00
2016-08-11 23:45:42 +03:00
tagName := ctx . Params ( "*" )
2023-09-25 16:17:37 +03:00
rel , err := repo_model . GetRelease ( ctx , ctx . Repo . Repository . ID , tagName )
2014-07-26 10:28:04 +04:00
if err != nil {
2022-08-25 05:31:57 +03:00
if repo_model . IsErrReleaseNotExist ( err ) {
2018-01-11 00:34:17 +03:00
ctx . NotFound ( "GetRelease" , err )
2014-07-26 10:28:04 +04:00
} else {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "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
2021-03-22 19:09:51 +03:00
rel . Repo = ctx . Repo . Repository
2022-11-19 11:12:33 +03:00
if err := rel . LoadAttributes ( ctx ) ; err != nil {
2021-03-22 19:09:51 +03:00
ctx . ServerError ( "LoadAttributes" , err )
return
}
ctx . Data [ "attachments" ] = rel . Attachments
2023-02-01 22:14:40 +03:00
// Get assignees.
2023-04-07 03:11:02 +03:00
assigneeUsers , err := repo_model . GetRepoAssignees ( ctx , rel . Repo )
2023-02-01 22:14:40 +03:00
if err != nil {
2023-04-07 03:11:02 +03:00
ctx . ServerError ( "GetRepoAssignees" , err )
2023-02-01 22:14:40 +03:00
return
}
2023-08-25 14:07:42 +03:00
ctx . Data [ "Assignees" ] = MakeSelfOnTop ( ctx . Doer , assigneeUsers )
2023-02-01 22:14:40 +03:00
2021-04-05 18:30:52 +03:00
ctx . HTML ( http . StatusOK , tplReleaseNew )
2014-07-26 10:28:04 +04:00
}
2016-11-24 10:04:31 +03:00
// EditReleasePost response for edit release
2021-01-26 18:36:53 +03:00
func EditReleasePost ( ctx * context . Context ) {
2021-04-06 22:44:05 +03:00
form := web . GetForm ( ctx ) . ( * forms . 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 ( "*" )
2023-09-25 16:17:37 +03:00
rel , err := repo_model . GetRelease ( ctx , ctx . Repo . Repository . ID , tagName )
2014-07-26 10:28:04 +04:00
if err != nil {
2022-08-25 05:31:57 +03:00
if repo_model . IsErrReleaseNotExist ( err ) {
2018-01-11 00:34:17 +03:00
ctx . NotFound ( "GetRelease" , err )
2014-07-26 10:28:04 +04:00
} else {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "GetRelease" , err )
2014-07-26 10:28:04 +04:00
}
return
}
2017-09-20 08:26:49 +03:00
if rel . IsTag {
2018-01-11 00:34:17 +03:00
ctx . NotFound ( "GetRelease" , err )
2017-09-20 08:26:49 +03: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 ( ) {
2021-04-05 18:30:52 +03:00
ctx . HTML ( http . StatusOK , tplReleaseNew )
2014-07-26 10:28:04 +04:00
return
}
2021-03-22 19:09:51 +03:00
const delPrefix = "attachment-del-"
const editPrefix = "attachment-edit-"
var addAttachmentUUIDs , delAttachmentUUIDs [ ] string
2022-01-20 20:46:10 +03:00
editAttachments := make ( map [ string ] string ) // uuid -> new name
2020-08-18 07:23:45 +03:00
if setting . Attachment . Enabled {
2021-03-22 19:09:51 +03:00
addAttachmentUUIDs = form . Files
for k , v := range ctx . Req . Form {
if strings . HasPrefix ( k , delPrefix ) && v [ 0 ] == "true" {
delAttachmentUUIDs = append ( delAttachmentUUIDs , k [ len ( delPrefix ) : ] )
} else if strings . HasPrefix ( k , editPrefix ) {
editAttachments [ k [ len ( editPrefix ) : ] ] = v [ 0 ]
}
}
2017-01-15 17:57:00 +03:00
}
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
2023-09-25 16:17:37 +03:00
if err = releaseservice . UpdateRelease ( ctx , ctx . Doer , ctx . Repo . GitRepo ,
2021-03-22 19:09:51 +03:00
rel , addAttachmentUUIDs , delAttachmentUUIDs , editAttachments ) ; err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "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
Fix various typos (#20338)
* Fix various typos
Found via `codespell -q 3 -S ./options/locale,./options/license,./public/vendor -L actived,allways,attachements,ba,befores,commiter,pullrequest,pullrequests,readby,splitted,te,unknwon`
Co-authored-by: zeripath <art27@cantab.net>
2022-07-13 00:32:37 +03:00
// DeleteRelease deletes a release
2016-03-11 19:56:52 +03:00
func DeleteRelease ( ctx * context . Context ) {
2020-11-03 02:10:22 +03:00
deleteReleaseOrTag ( ctx , false )
}
Fix various typos (#20338)
* Fix various typos
Found via `codespell -q 3 -S ./options/locale,./options/license,./public/vendor -L actived,allways,attachements,ba,befores,commiter,pullrequest,pullrequests,readby,splitted,te,unknwon`
Co-authored-by: zeripath <art27@cantab.net>
2022-07-13 00:32:37 +03:00
// DeleteTag deletes a tag
2020-11-03 02:10:22 +03:00
func DeleteTag ( ctx * context . Context ) {
deleteReleaseOrTag ( ctx , true )
}
func deleteReleaseOrTag ( ctx * context . Context , isDelTag bool ) {
2023-11-25 20:21:21 +03:00
redirect := func ( ) {
if isDelTag {
ctx . JSONRedirect ( ctx . Repo . RepoLink + "/tags" )
return
}
ctx . JSONRedirect ( ctx . Repo . RepoLink + "/releases" )
}
rel , err := repo_model . GetReleaseForRepoByID ( ctx , ctx . Repo . Repository . ID , ctx . FormInt64 ( "id" ) )
if err != nil {
if repo_model . IsErrReleaseNotExist ( err ) {
ctx . NotFound ( "GetReleaseForRepoByID" , err )
} else {
ctx . Flash . Error ( "DeleteReleaseByID: " + err . Error ( ) )
redirect ( )
}
return
}
if err := releaseservice . DeleteReleaseByID ( ctx , ctx . Repo . Repository , rel , ctx . Doer , isDelTag ) ; err != nil {
2022-06-16 23:03:03 +03:00
if models . IsErrProtectedTagName ( err ) {
ctx . Flash . Error ( ctx . Tr ( "repo.release.tag_name_protected" ) )
} else {
ctx . Flash . Error ( "DeleteReleaseByID: " + err . Error ( ) )
}
2015-11-20 10:38:41 +03:00
} else {
2020-11-03 02:10:22 +03:00
if isDelTag {
ctx . Flash . Success ( ctx . Tr ( "repo.release.deletion_tag_success" ) )
} else {
ctx . Flash . Success ( ctx . Tr ( "repo.release.deletion_success" ) )
}
}
2023-11-25 20:21:21 +03:00
redirect ( )
2015-11-20 10:38:41 +03:00
}