2014-04-14 09:57:25 +04:00
// Copyright 2014 The Gogs Authors. All rights reserved.
2019-09-22 12:05:48 +03:00
// Copyright 2019 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2014-04-14 09:57:25 +04:00
2022-08-25 05:31:57 +03:00
package repo
2014-04-14 09:57:25 +04:00
import (
2021-09-23 18:45:36 +03:00
"context"
2021-03-22 19:09:51 +03:00
"errors"
2015-11-20 10:38:41 +03:00
"fmt"
2014-06-13 01:47:23 +04:00
"sort"
2021-11-16 21:18:25 +03:00
"strconv"
2014-04-14 09:57:25 +04:00
"strings"
2021-09-19 14:49:59 +03:00
"code.gitea.io/gitea/models/db"
2021-11-24 12:49:20 +03:00
user_model "code.gitea.io/gitea/models/user"
2019-10-14 09:10:42 +03:00
"code.gitea.io/gitea/modules/structs"
2019-08-15 17:46:21 +03:00
"code.gitea.io/gitea/modules/timeutil"
2021-06-17 11:58:10 +03:00
"code.gitea.io/gitea/modules/util"
2019-03-27 12:33:00 +03:00
2019-06-23 18:22:43 +03:00
"xorm.io/builder"
2014-04-14 09:57:25 +04:00
)
2022-08-25 05:31:57 +03:00
// ErrReleaseAlreadyExist represents a "ReleaseAlreadyExist" kind of error.
type ErrReleaseAlreadyExist struct {
TagName string
}
// IsErrReleaseAlreadyExist checks if an error is a ErrReleaseAlreadyExist.
func IsErrReleaseAlreadyExist ( err error ) bool {
_ , ok := err . ( ErrReleaseAlreadyExist )
return ok
}
func ( err ErrReleaseAlreadyExist ) Error ( ) string {
return fmt . Sprintf ( "release tag already exist [tag_name: %s]" , err . TagName )
}
2022-10-18 08:50:37 +03:00
func ( err ErrReleaseAlreadyExist ) Unwrap ( ) error {
return util . ErrAlreadyExist
}
2022-08-25 05:31:57 +03:00
// ErrReleaseNotExist represents a "ReleaseNotExist" kind of error.
type ErrReleaseNotExist struct {
ID int64
TagName string
}
// IsErrReleaseNotExist checks if an error is a ErrReleaseNotExist.
func IsErrReleaseNotExist ( err error ) bool {
_ , ok := err . ( ErrReleaseNotExist )
return ok
}
func ( err ErrReleaseNotExist ) Error ( ) string {
return fmt . Sprintf ( "release tag does not exist [id: %d, tag_name: %s]" , err . ID , err . TagName )
}
2022-10-18 08:50:37 +03:00
func ( err ErrReleaseNotExist ) Unwrap ( ) error {
return util . ErrNotExist
}
2014-04-14 09:57:25 +04:00
// Release represents a release of repository.
type Release struct {
2022-08-25 05:31:57 +03:00
ID int64 ` xorm:"pk autoincr" `
RepoID int64 ` xorm:"INDEX UNIQUE(n)" `
Repo * Repository ` xorm:"-" `
PublisherID int64 ` xorm:"INDEX" `
Publisher * user_model . User ` xorm:"-" `
TagName string ` xorm:"INDEX UNIQUE(n)" `
2019-10-05 14:09:27 +03:00
OriginalAuthor string
OriginalAuthorID int64 ` xorm:"index" `
2014-04-14 09:57:25 +04:00
LowerTagName string
2014-06-12 17:10:39 +04:00
Target string
2014-06-13 01:47:23 +04:00
Title string
2014-06-12 17:10:39 +04:00
Sha1 string ` xorm:"VARCHAR(40)" `
2015-12-10 04:46:05 +03:00
NumCommits int64
2022-08-25 05:31:57 +03:00
NumCommitsBehind int64 ` xorm:"-" `
Note string ` xorm:"TEXT" `
RenderedNote string ` xorm:"-" `
IsDraft bool ` xorm:"NOT NULL DEFAULT false" `
IsPrerelease bool ` xorm:"NOT NULL DEFAULT false" `
IsTag bool ` xorm:"NOT NULL DEFAULT false" `
Attachments [ ] * Attachment ` xorm:"-" `
CreatedUnix timeutil . TimeStamp ` xorm:"INDEX" `
2015-08-24 16:01:23 +03:00
}
2021-09-19 14:49:59 +03:00
func init ( ) {
db . RegisterModel ( new ( Release ) )
}
2022-11-19 11:12:33 +03:00
// LoadAttributes load repo and publisher attributes for a release
func ( r * Release ) LoadAttributes ( ctx context . Context ) error {
2016-12-31 19:51:22 +03:00
var err error
if r . Repo == nil {
2022-08-25 05:31:57 +03:00
r . Repo , err = GetRepositoryByIDCtx ( ctx , r . RepoID )
2016-12-31 19:51:22 +03:00
if err != nil {
return err
}
}
if r . Publisher == nil {
2022-05-20 17:08:52 +03:00
r . Publisher , err = user_model . GetUserByIDCtx ( ctx , r . PublisherID )
2016-12-31 19:51:22 +03:00
if err != nil {
2021-11-24 12:49:20 +03:00
if user_model . IsErrUserNotExist ( err ) {
r . Publisher = user_model . NewGhostUser ( )
2020-11-03 02:10:22 +03:00
} else {
return err
}
2016-12-31 19:51:22 +03:00
}
}
2022-05-20 17:08:52 +03:00
return GetReleaseAttachments ( ctx , r )
2016-12-31 19:51:22 +03:00
}
// APIURL the api url for a release. release must have attributes loaded
func ( r * Release ) APIURL ( ) string {
2021-11-16 21:18:25 +03:00
return r . Repo . APIURL ( ) + "/releases/" + strconv . FormatInt ( r . ID , 10 )
2016-12-31 19:51:22 +03:00
}
// ZipURL the zip url for a release. release must have attributes loaded
func ( r * Release ) ZipURL ( ) string {
2021-11-16 21:18:25 +03:00
return r . Repo . HTMLURL ( ) + "/archive/" + util . PathEscapeSegments ( r . TagName ) + ".zip"
2016-12-31 19:51:22 +03:00
}
// TarURL the tar.gz url for a release. release must have attributes loaded
func ( r * Release ) TarURL ( ) string {
2021-11-16 21:18:25 +03:00
return r . Repo . HTMLURL ( ) + "/archive/" + util . PathEscapeSegments ( r . TagName ) + ".tar.gz"
2016-12-31 19:51:22 +03:00
}
2020-04-18 17:47:15 +03:00
// HTMLURL the url for a release on the web UI. release must have attributes loaded
func ( r * Release ) HTMLURL ( ) string {
2021-11-16 21:18:25 +03:00
return r . Repo . HTMLURL ( ) + "/releases/tag/" + util . PathEscapeSegments ( r . TagName )
2020-04-18 17:47:15 +03:00
}
2014-04-14 09:57:25 +04:00
// IsReleaseExist returns true if release with given tag name already exists.
2022-06-03 09:13:58 +03:00
func IsReleaseExist ( ctx context . Context , repoID int64 , tagName string ) ( bool , error ) {
2014-04-14 09:57:25 +04:00
if len ( tagName ) == 0 {
return false , nil
}
2022-06-03 09:13:58 +03:00
return db . GetEngine ( ctx ) . Exist ( & Release { RepoID : repoID , LowerTagName : strings . ToLower ( tagName ) } )
2020-02-03 11:47:04 +03:00
}
2019-09-15 18:28:25 +03:00
// UpdateRelease updates all columns of a release
2021-09-23 18:45:36 +03:00
func UpdateRelease ( ctx context . Context , rel * Release ) error {
_ , err := db . GetEngine ( ctx ) . ID ( rel . ID ) . AllCols ( ) . Update ( rel )
2019-09-15 18:28:25 +03:00
return err
2014-06-13 01:47:23 +04:00
}
2019-09-15 18:28:25 +03:00
// AddReleaseAttachments adds a release attachments
2021-09-23 18:45:36 +03:00
func AddReleaseAttachments ( ctx context . Context , releaseID int64 , attachmentUUIDs [ ] string ) ( err error ) {
2017-01-15 17:57:00 +03:00
// Check attachments
2022-08-25 05:31:57 +03:00
attachments , err := GetAttachmentsByUUIDs ( ctx , attachmentUUIDs )
2019-12-11 03:01:52 +03:00
if err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "GetAttachmentsByUUIDs [uuids: %v]: %w" , attachmentUUIDs , err )
2017-01-15 17:57:00 +03:00
}
for i := range attachments {
2021-03-22 19:09:51 +03:00
if attachments [ i ] . ReleaseID != 0 {
return errors . New ( "release permission denied" )
}
2017-01-15 17:57:00 +03:00
attachments [ i ] . ReleaseID = releaseID
// No assign value could be 0, so ignore AllCols().
2021-09-23 18:45:36 +03:00
if _ , err = db . GetEngine ( ctx ) . ID ( attachments [ i ] . ID ) . Update ( attachments [ i ] ) ; err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "update attachment [%d]: %w" , attachments [ i ] . ID , err )
2017-01-15 17:57:00 +03:00
}
}
2022-06-20 13:02:49 +03:00
return err
2017-01-15 17:57:00 +03:00
}
2014-06-13 01:47:23 +04:00
// GetRelease returns release by given ID.
2015-11-16 07:52:46 +03:00
func GetRelease ( repoID int64 , tagName string ) ( * Release , error ) {
2022-06-03 09:13:58 +03:00
rel := & Release { RepoID : repoID , LowerTagName : strings . ToLower ( tagName ) }
has , err := db . GetEngine ( db . DefaultContext ) . Get ( rel )
2014-06-13 01:47:23 +04:00
if err != nil {
return nil , err
2022-06-03 09:13:58 +03:00
} else if ! has {
2015-11-20 10:38:41 +03:00
return nil , ErrReleaseNotExist { 0 , tagName }
2014-06-13 01:47:23 +04:00
}
2022-06-03 09:13:58 +03:00
return rel , nil
2014-06-13 01:47:23 +04:00
}
2015-11-20 10:38:41 +03:00
// GetReleaseByID returns release with given ID.
2022-06-03 09:13:58 +03:00
func GetReleaseByID ( ctx context . Context , id int64 ) ( * Release , error ) {
2015-11-20 10:38:41 +03:00
rel := new ( Release )
2022-06-03 09:13:58 +03:00
has , err := db . GetEngine ( ctx ) .
2017-10-05 07:43:04 +03:00
ID ( id ) .
2016-11-10 18:16:32 +03:00
Get ( rel )
2015-11-20 10:38:41 +03:00
if err != nil {
return nil , err
} else if ! has {
return nil , ErrReleaseNotExist { id , "" }
}
return rel , nil
}
2017-06-29 18:11:38 +03:00
// FindReleasesOptions describes the conditions to Find releases
type FindReleasesOptions struct {
2021-09-24 14:32:56 +03:00
db . ListOptions
2017-06-29 18:11:38 +03:00
IncludeDrafts bool
2017-09-20 08:26:49 +03:00
IncludeTags bool
2021-06-17 11:58:10 +03:00
IsPreRelease util . OptionalBool
IsDraft util . OptionalBool
2017-06-29 18:11:38 +03:00
TagNames [ ] string
2022-10-03 15:05:53 +03:00
HasSha1 util . OptionalBool // useful to find draft releases which are created with existing tags
2014-06-13 01:47:23 +04:00
}
2017-06-29 18:11:38 +03:00
func ( opts * FindReleasesOptions ) toConds ( repoID int64 ) builder . Cond {
2021-03-14 21:52:12 +03:00
cond := builder . NewCond ( )
2017-06-28 17:47:00 +03:00
cond = cond . And ( builder . Eq { "repo_id" : repoID } )
2017-06-29 18:11:38 +03:00
if ! opts . IncludeDrafts {
cond = cond . And ( builder . Eq { "is_draft" : false } )
2017-06-28 17:47:00 +03:00
}
2017-09-20 08:26:49 +03:00
if ! opts . IncludeTags {
cond = cond . And ( builder . Eq { "is_tag" : false } )
}
2017-06-29 18:11:38 +03:00
if len ( opts . TagNames ) > 0 {
cond = cond . And ( builder . In ( "tag_name" , opts . TagNames ) )
}
2021-06-17 11:58:10 +03:00
if ! opts . IsPreRelease . IsNone ( ) {
cond = cond . And ( builder . Eq { "is_prerelease" : opts . IsPreRelease . IsTrue ( ) } )
}
if ! opts . IsDraft . IsNone ( ) {
cond = cond . And ( builder . Eq { "is_draft" : opts . IsDraft . IsTrue ( ) } )
}
2022-10-03 15:05:53 +03:00
if ! opts . HasSha1 . IsNone ( ) {
if opts . HasSha1 . IsTrue ( ) {
cond = cond . And ( builder . Neq { "sha1" : "" } )
} else {
cond = cond . And ( builder . Eq { "sha1" : "" } )
}
}
2017-06-29 18:11:38 +03:00
return cond
2017-06-28 17:47:00 +03:00
}
2017-06-29 18:11:38 +03:00
// GetReleasesByRepoID returns a list of releases of repository.
2022-11-19 11:12:33 +03:00
func GetReleasesByRepoID ( ctx context . Context , repoID int64 , opts FindReleasesOptions ) ( [ ] * Release , error ) {
sess := db . GetEngine ( ctx ) .
2020-01-24 22:00:29 +03:00
Desc ( "created_unix" , "id" ) .
Where ( opts . toConds ( repoID ) )
if opts . PageSize != 0 {
2021-09-24 14:32:56 +03:00
sess = db . SetSessionPagination ( sess , & opts . ListOptions )
2017-06-29 18:11:38 +03:00
}
2020-01-24 22:00:29 +03:00
rels := make ( [ ] * Release , 0 , opts . PageSize )
return rels , sess . Find ( & rels )
2017-01-06 04:51:15 +03:00
}
2021-06-17 11:58:10 +03:00
// CountReleasesByRepoID returns a number of releases matching FindReleaseOptions and RepoID.
func CountReleasesByRepoID ( repoID int64 , opts FindReleasesOptions ) ( int64 , error ) {
2021-09-23 18:45:36 +03:00
return db . GetEngine ( db . DefaultContext ) . Where ( opts . toConds ( repoID ) ) . Count ( new ( Release ) )
2021-06-17 11:58:10 +03:00
}
2020-04-18 17:47:15 +03:00
// GetLatestReleaseByRepoID returns the latest release for a repository
func GetLatestReleaseByRepoID ( repoID int64 ) ( * Release , error ) {
cond := builder . NewCond ( ) .
And ( builder . Eq { "repo_id" : repoID } ) .
And ( builder . Eq { "is_draft" : false } ) .
And ( builder . Eq { "is_prerelease" : false } ) .
And ( builder . Eq { "is_tag" : false } )
rel := new ( Release )
2021-09-23 18:45:36 +03:00
has , err := db . GetEngine ( db . DefaultContext ) .
2020-04-18 17:47:15 +03:00
Desc ( "created_unix" , "id" ) .
Where ( cond ) .
Get ( rel )
if err != nil {
return nil , err
} else if ! has {
return nil , ErrReleaseNotExist { 0 , "latest" }
}
return rel , nil
}
2019-01-07 01:37:30 +03:00
// GetReleasesByRepoIDAndNames returns a list of releases of repository according repoID and tagNames.
2021-09-23 18:45:36 +03:00
func GetReleasesByRepoIDAndNames ( ctx context . Context , repoID int64 , tagNames [ ] string ) ( rels [ ] * Release , err error ) {
err = db . GetEngine ( ctx ) .
2019-01-07 01:37:30 +03:00
In ( "tag_name" , tagNames ) .
2020-02-03 11:47:04 +03:00
Desc ( "created_unix" ) .
2019-01-07 01:37:30 +03:00
Find ( & rels , Release { RepoID : repoID } )
return rels , err
}
2017-06-29 18:11:38 +03:00
// GetReleaseCountByRepoID returns the count of releases of repository
func GetReleaseCountByRepoID ( repoID int64 , opts FindReleasesOptions ) ( int64 , error ) {
2021-09-23 18:45:36 +03:00
return db . GetEngine ( db . DefaultContext ) . Where ( opts . toConds ( repoID ) ) . Count ( & Release { } )
2017-06-29 18:11:38 +03:00
}
2017-01-15 17:57:00 +03:00
type releaseMetaSearch struct {
2017-01-17 08:58:58 +03:00
ID [ ] int64
Rel [ ] * Release
2017-01-15 17:57:00 +03:00
}
2017-01-17 08:58:58 +03:00
2017-01-15 17:57:00 +03:00
func ( s releaseMetaSearch ) Len ( ) int {
return len ( s . ID )
}
2021-03-14 21:52:12 +03:00
2017-01-15 17:57:00 +03:00
func ( s releaseMetaSearch ) Swap ( i , j int ) {
s . ID [ i ] , s . ID [ j ] = s . ID [ j ] , s . ID [ i ]
s . Rel [ i ] , s . Rel [ j ] = s . Rel [ j ] , s . Rel [ i ]
}
2021-03-14 21:52:12 +03:00
2017-01-15 17:57:00 +03:00
func ( s releaseMetaSearch ) Less ( i , j int ) bool {
return s . ID [ i ] < s . ID [ j ]
}
// GetReleaseAttachments retrieves the attachments for releases
2022-05-20 17:08:52 +03:00
func GetReleaseAttachments ( ctx context . Context , rels ... * Release ) ( err error ) {
2017-01-15 17:57:00 +03:00
if len ( rels ) == 0 {
return
}
2017-01-17 08:58:58 +03:00
// To keep this efficient as possible sort all releases by id,
2017-01-15 17:57:00 +03:00
// select attachments by release id,
// then merge join them
// Sort
2021-03-14 21:52:12 +03:00
sortedRels := releaseMetaSearch { ID : make ( [ ] int64 , len ( rels ) ) , Rel : make ( [ ] * Release , len ( rels ) ) }
2022-08-25 05:31:57 +03:00
var attachments [ ] * Attachment
2017-01-15 17:57:00 +03:00
for index , element := range rels {
2022-08-25 05:31:57 +03:00
element . Attachments = [ ] * Attachment { }
2017-01-15 17:57:00 +03:00
sortedRels . ID [ index ] = element . ID
sortedRels . Rel [ index ] = element
}
sort . Sort ( sortedRels )
// Select attachments
2022-05-20 17:08:52 +03:00
err = db . GetEngine ( ctx ) .
2021-03-17 12:25:49 +03:00
Asc ( "release_id" , "name" ) .
2017-01-15 17:57:00 +03:00
In ( "release_id" , sortedRels . ID ) .
2022-08-25 05:31:57 +03:00
Find ( & attachments , Attachment { } )
2017-01-15 17:57:00 +03:00
if err != nil {
return err
}
// merge join
2021-03-14 21:52:12 +03:00
currentIndex := 0
2017-01-15 17:57:00 +03:00
for _ , attachment := range attachments {
for sortedRels . ID [ currentIndex ] < attachment . ReleaseID {
currentIndex ++
}
sortedRels . Rel [ currentIndex ] . Attachments = append ( sortedRels . Rel [ currentIndex ] . Attachments , attachment )
}
2022-06-20 13:02:49 +03:00
return err
2017-01-15 17:57:00 +03:00
}
2016-11-25 11:11:12 +03:00
type releaseSorter struct {
2014-06-13 01:47:23 +04:00
rels [ ] * Release
}
2016-11-25 11:11:12 +03:00
func ( rs * releaseSorter ) Len ( ) int {
2014-06-13 01:47:23 +04:00
return len ( rs . rels )
}
2016-11-25 11:11:12 +03:00
func ( rs * releaseSorter ) Less ( i , j int ) bool {
2014-06-13 01:47:23 +04:00
diffNum := rs . rels [ i ] . NumCommits - rs . rels [ j ] . NumCommits
if diffNum != 0 {
return diffNum > 0
2014-04-14 09:57:25 +04:00
}
2017-12-11 07:37:04 +03:00
return rs . rels [ i ] . CreatedUnix > rs . rels [ j ] . CreatedUnix
2014-06-13 01:47:23 +04:00
}
2014-04-14 09:57:25 +04:00
2016-11-25 11:11:12 +03:00
func ( rs * releaseSorter ) Swap ( i , j int ) {
2014-06-13 01:47:23 +04:00
rs . rels [ i ] , rs . rels [ j ] = rs . rels [ j ] , rs . rels [ i ]
}
// SortReleases sorts releases by number of commits and created time.
func SortReleases ( rels [ ] * Release ) {
2016-11-25 11:11:12 +03:00
sorter := & releaseSorter { rels : rels }
2014-06-13 01:47:23 +04:00
sort . Sort ( sorter )
}
2019-09-30 19:10:00 +03:00
// DeleteReleaseByID deletes a release from database by given ID.
2022-11-19 11:12:33 +03:00
func DeleteReleaseByID ( ctx context . Context , id int64 ) error {
_ , err := db . GetEngine ( ctx ) . ID ( id ) . Delete ( new ( Release ) )
2019-09-30 19:10:00 +03:00
return err
2015-11-20 10:38:41 +03:00
}
2017-09-20 08:26:49 +03:00
2019-10-14 09:10:42 +03:00
// UpdateReleasesMigrationsByType updates all migrated repositories' releases from gitServiceType to replace originalAuthorID to posterID
2019-10-17 05:06:28 +03:00
func UpdateReleasesMigrationsByType ( gitServiceType structs . GitServiceType , originalAuthorID string , posterID int64 ) error {
2021-09-23 18:45:36 +03:00
_ , err := db . GetEngine ( db . DefaultContext ) . Table ( "release" ) .
2019-10-14 09:10:42 +03:00
Where ( "repo_id IN (SELECT id FROM repository WHERE original_service_type = ?)" , gitServiceType ) .
And ( "original_author_id = ?" , originalAuthorID ) .
Update ( map [ string ] interface { } {
"publisher_id" : posterID ,
"original_author" : "" ,
"original_author_id" : 0 ,
} )
return err
}
2021-12-12 18:48:20 +03:00
// PushUpdateDeleteTagsContext updates a number of delete tags with context
2022-08-25 05:31:57 +03:00
func PushUpdateDeleteTagsContext ( ctx context . Context , repo * Repository , tags [ ] string ) error {
2021-12-12 18:48:20 +03:00
if len ( tags ) == 0 {
return nil
}
lowerTags := make ( [ ] string , 0 , len ( tags ) )
for _ , tag := range tags {
lowerTags = append ( lowerTags , strings . ToLower ( tag ) )
}
2022-05-20 17:08:52 +03:00
if _ , err := db . GetEngine ( ctx ) .
2021-12-12 18:48:20 +03:00
Where ( "repo_id = ? AND is_tag = ?" , repo . ID , true ) .
In ( "lower_tag_name" , lowerTags ) .
Delete ( new ( Release ) ) ; err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "Delete: %w" , err )
2021-12-12 18:48:20 +03:00
}
2022-05-20 17:08:52 +03:00
if _ , err := db . GetEngine ( ctx ) .
2021-12-12 18:48:20 +03:00
Where ( "repo_id = ? AND is_tag = ?" , repo . ID , false ) .
In ( "lower_tag_name" , lowerTags ) .
Cols ( "is_draft" , "num_commits" , "sha1" ) .
Update ( & Release {
IsDraft : true ,
} ) ; err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "Update: %w" , err )
2021-12-12 18:48:20 +03:00
}
return nil
}
// PushUpdateDeleteTag must be called for any push actions to delete tag
2022-08-25 05:31:57 +03:00
func PushUpdateDeleteTag ( repo * Repository , tagName string ) error {
2021-12-12 18:48:20 +03:00
rel , err := GetRelease ( repo . ID , tagName )
if err != nil {
if IsErrReleaseNotExist ( err ) {
return nil
}
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "GetRelease: %w" , err )
2021-12-12 18:48:20 +03:00
}
if rel . IsTag {
if _ , err = db . GetEngine ( db . DefaultContext ) . ID ( rel . ID ) . Delete ( new ( Release ) ) ; err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "Delete: %w" , err )
2021-12-12 18:48:20 +03:00
}
} else {
rel . IsDraft = true
rel . NumCommits = 0
rel . Sha1 = ""
if _ , err = db . GetEngine ( db . DefaultContext ) . ID ( rel . ID ) . AllCols ( ) . Update ( rel ) ; err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "Update: %w" , err )
2021-12-12 18:48:20 +03:00
}
}
return nil
}
// SaveOrUpdateTag must be called for any push actions to add tag
2022-08-25 05:31:57 +03:00
func SaveOrUpdateTag ( repo * Repository , newRel * Release ) error {
2021-12-12 18:48:20 +03:00
rel , err := GetRelease ( repo . ID , newRel . TagName )
if err != nil && ! IsErrReleaseNotExist ( err ) {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "GetRelease: %w" , err )
2021-12-12 18:48:20 +03:00
}
if rel == nil {
rel = newRel
if _ , err = db . GetEngine ( db . DefaultContext ) . Insert ( rel ) ; err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "InsertOne: %w" , err )
2021-12-12 18:48:20 +03:00
}
} else {
rel . Sha1 = newRel . Sha1
rel . CreatedUnix = newRel . CreatedUnix
rel . NumCommits = newRel . NumCommits
rel . IsDraft = false
if rel . IsTag && newRel . PublisherID > 0 {
rel . PublisherID = newRel . PublisherID
}
if _ , err = db . GetEngine ( db . DefaultContext ) . ID ( rel . ID ) . AllCols ( ) . Update ( rel ) ; err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "Update: %w" , err )
2021-12-12 18:48:20 +03:00
}
}
return nil
}
2022-02-01 21:20:28 +03:00
// RemapExternalUser ExternalUserRemappable interface
func ( r * Release ) RemapExternalUser ( externalName string , externalID , userID int64 ) error {
r . OriginalAuthor = externalName
r . OriginalAuthorID = externalID
r . PublisherID = userID
return nil
}
// UserID ExternalUserRemappable interface
func ( r * Release ) GetUserID ( ) int64 { return r . PublisherID }
// ExternalName ExternalUserRemappable interface
func ( r * Release ) GetExternalName ( ) string { return r . OriginalAuthor }
// ExternalID ExternalUserRemappable interface
func ( r * Release ) GetExternalID ( ) int64 { return r . OriginalAuthorID }