2014-04-27 01:05:13 -06: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.
2014-04-11 10:27:13 +08:00
package models
import (
2014-06-23 16:22:34 -04:00
"fmt"
2014-04-11 10:27:13 +08:00
"strings"
2017-10-26 10:45:14 +03:00
"time"
2014-04-11 10:27:13 +08:00
2019-03-27 17:33:00 +08:00
"code.gitea.io/gitea/modules/git"
2019-08-15 22:46:21 +08:00
"code.gitea.io/gitea/modules/timeutil"
2014-04-11 10:27:13 +08:00
)
2017-02-25 22:54:40 +08:00
// env keys for git hooks need
const (
EnvRepoName = "GITEA_REPO_NAME"
EnvRepoUsername = "GITEA_REPO_USER_NAME"
EnvRepoIsWiki = "GITEA_REPO_IS_WIKI"
EnvPusherName = "GITEA_PUSHER_NAME"
2018-07-26 18:38:55 +02:00
EnvPusherEmail = "GITEA_PUSHER_EMAIL"
2017-02-25 22:54:40 +08:00
EnvPusherID = "GITEA_PUSHER_ID"
2019-10-21 09:21:45 +01:00
EnvKeyID = "GITEA_KEY_ID"
EnvIsDeployKey = "GITEA_IS_DEPLOY_KEY"
2019-12-27 21:15:04 +00:00
EnvIsInternal = "GITEA_INTERNAL_PUSH"
2017-02-25 22:54:40 +08:00
)
2014-06-28 23:56:41 +08:00
2019-12-26 11:29:45 +00:00
// PushUpdateAddDeleteTags updates a number of added and delete tags
func PushUpdateAddDeleteTags ( repo * Repository , gitRepo * git . Repository , addTags , delTags [ ] string ) error {
sess := x . NewSession ( )
defer sess . Close ( )
if err := sess . Begin ( ) ; err != nil {
return fmt . Errorf ( "Unable to begin sess in PushUpdateDeleteTags: %v" , err )
}
if err := pushUpdateDeleteTags ( sess , repo , delTags ) ; err != nil {
return err
}
if err := pushUpdateAddTags ( sess , repo , gitRepo , addTags ) ; err != nil {
return err
}
return sess . Commit ( )
}
// PushUpdateDeleteTags updates a number of delete tags
func PushUpdateDeleteTags ( repo * Repository , tags [ ] string ) error {
sess := x . NewSession ( )
defer sess . Close ( )
if err := sess . Begin ( ) ; err != nil {
return fmt . Errorf ( "Unable to begin sess in PushUpdateDeleteTags: %v" , err )
}
if err := pushUpdateDeleteTags ( sess , repo , tags ) ; err != nil {
return err
}
return sess . Commit ( )
}
func pushUpdateDeleteTags ( e Engine , repo * Repository , tags [ ] string ) error {
if len ( tags ) == 0 {
return nil
}
lowerTags := make ( [ ] string , 0 , len ( tags ) )
for _ , tag := range tags {
lowerTags = append ( lowerTags , strings . ToLower ( tag ) )
}
if _ , err := e .
Where ( "repo_id = ? AND is_tag = ?" , repo . ID , true ) .
In ( "lower_tag_name" , lowerTags ) .
Delete ( new ( Release ) ) ; err != nil {
return fmt . Errorf ( "Delete: %v" , err )
}
if _ , err := e .
Where ( "repo_id = ? AND is_tag = ?" , repo . ID , false ) .
In ( "lower_tag_name" , lowerTags ) .
2019-12-27 22:18:07 +08:00
Cols ( "is_draft" , "num_commits" , "sha1" ) .
Update ( & Release {
IsDraft : true ,
} ) ; err != nil {
2019-12-26 11:29:45 +00:00
return fmt . Errorf ( "Update: %v" , err )
}
return nil
}
2019-07-24 15:13:26 +08:00
// PushUpdateDeleteTag must be called for any push actions to delete tag
func PushUpdateDeleteTag ( repo * Repository , tagName string ) error {
2017-09-20 08:26:49 +03:00
rel , err := GetRelease ( repo . ID , tagName )
if err != nil {
if IsErrReleaseNotExist ( err ) {
return nil
}
return fmt . Errorf ( "GetRelease: %v" , err )
}
if rel . IsTag {
2017-10-04 21:43:04 -07:00
if _ , err = x . ID ( rel . ID ) . Delete ( new ( Release ) ) ; err != nil {
2017-09-20 08:26:49 +03:00
return fmt . Errorf ( "Delete: %v" , err )
}
} else {
rel . IsDraft = true
rel . NumCommits = 0
rel . Sha1 = ""
2017-10-04 21:43:04 -07:00
if _ , err = x . ID ( rel . ID ) . AllCols ( ) . Update ( rel ) ; err != nil {
2017-09-20 08:26:49 +03:00
return fmt . Errorf ( "Update: %v" , err )
}
}
return nil
}
2019-12-26 11:29:45 +00:00
// PushUpdateAddTags updates a number of add tags
func PushUpdateAddTags ( repo * Repository , gitRepo * git . Repository , tags [ ] string ) error {
sess := x . NewSession ( )
defer sess . Close ( )
if err := sess . Begin ( ) ; err != nil {
return fmt . Errorf ( "Unable to begin sess in PushUpdateAddTags: %v" , err )
}
if err := pushUpdateAddTags ( sess , repo , gitRepo , tags ) ; err != nil {
return err
}
return sess . Commit ( )
}
func pushUpdateAddTags ( e Engine , repo * Repository , gitRepo * git . Repository , tags [ ] string ) error {
if len ( tags ) == 0 {
return nil
}
lowerTags := make ( [ ] string , 0 , len ( tags ) )
for _ , tag := range tags {
lowerTags = append ( lowerTags , strings . ToLower ( tag ) )
}
releases := make ( [ ] Release , 0 , len ( tags ) )
if err := e . Where ( "repo_id = ?" , repo . ID ) .
In ( "lower_tag_name" , lowerTags ) . Find ( & releases ) ; err != nil {
return fmt . Errorf ( "GetRelease: %v" , err )
}
relMap := make ( map [ string ] * Release )
for _ , rel := range releases {
relMap [ rel . LowerTagName ] = & rel
}
newReleases := make ( [ ] * Release , 0 , len ( lowerTags ) - len ( relMap ) )
emailToUser := make ( map [ string ] * User )
for i , lowerTag := range lowerTags {
tag , err := gitRepo . GetTag ( tags [ i ] )
if err != nil {
return fmt . Errorf ( "GetTag: %v" , err )
}
commit , err := tag . Commit ( )
if err != nil {
return fmt . Errorf ( "Commit: %v" , err )
}
sig := tag . Tagger
if sig == nil {
sig = commit . Author
}
if sig == nil {
sig = commit . Committer
}
var author * User
var createdAt = time . Unix ( 1 , 0 )
if sig != nil {
var ok bool
author , ok = emailToUser [ sig . Email ]
if ! ok {
author , err = GetUserByEmail ( sig . Email )
if err != nil && ! IsErrUserNotExist ( err ) {
return fmt . Errorf ( "GetUserByEmail: %v" , err )
}
}
createdAt = sig . When
}
commitsCount , err := commit . CommitsCount ( )
if err != nil {
return fmt . Errorf ( "CommitsCount: %v" , err )
}
rel , has := relMap [ lowerTag ]
if ! has {
rel = & Release {
RepoID : repo . ID ,
Title : "" ,
TagName : tags [ i ] ,
LowerTagName : lowerTag ,
Target : "" ,
Sha1 : commit . ID . String ( ) ,
NumCommits : commitsCount ,
Note : "" ,
IsDraft : false ,
IsPrerelease : false ,
IsTag : true ,
CreatedUnix : timeutil . TimeStamp ( createdAt . Unix ( ) ) ,
}
if author != nil {
rel . PublisherID = author . ID
}
newReleases = append ( newReleases , rel )
} else {
rel . Sha1 = commit . ID . String ( )
rel . CreatedUnix = timeutil . TimeStamp ( createdAt . Unix ( ) )
rel . NumCommits = commitsCount
rel . IsDraft = false
if rel . IsTag && author != nil {
rel . PublisherID = author . ID
}
if _ , err = e . ID ( rel . ID ) . AllCols ( ) . Update ( rel ) ; err != nil {
return fmt . Errorf ( "Update: %v" , err )
}
}
}
if len ( newReleases ) > 0 {
if _ , err := e . Insert ( newReleases ) ; err != nil {
return fmt . Errorf ( "Insert: %v" , err )
}
}
return nil
}
2020-01-10 17:34:21 +08:00
// SaveOrUpdateTag must be called for any push actions to add tag
func SaveOrUpdateTag ( repo * Repository , newRel * Release ) error {
rel , err := GetRelease ( repo . ID , newRel . TagName )
2017-09-20 08:26:49 +03:00
if err != nil && ! IsErrReleaseNotExist ( err ) {
return fmt . Errorf ( "GetRelease: %v" , err )
}
if rel == nil {
2020-01-10 17:34:21 +08:00
rel = newRel
if _ , err = x . Insert ( rel ) ; err != nil {
2017-09-20 08:26:49 +03:00
return fmt . Errorf ( "InsertOne: %v" , err )
}
} else {
2020-01-10 17:34:21 +08:00
rel . Sha1 = newRel . Sha1
rel . CreatedUnix = newRel . CreatedUnix
rel . NumCommits = newRel . NumCommits
2017-09-20 08:26:49 +03:00
rel . IsDraft = false
2020-01-10 17:34:21 +08:00
if rel . IsTag && newRel . PublisherID > 0 {
rel . PublisherID = newRel . PublisherID
2017-09-20 08:26:49 +03:00
}
2017-10-04 21:43:04 -07:00
if _ , err = x . ID ( rel . ID ) . AllCols ( ) . Update ( rel ) ; err != nil {
2017-09-20 08:26:49 +03:00
return fmt . Errorf ( "Update: %v" , err )
}
}
return nil
}