2020-09-18 15:09:26 +03:00
// Copyright 2020 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2020-09-18 15:09:26 +03:00
package convert
import (
2021-11-16 21:18:25 +03:00
"net/url"
2020-09-18 15:09:26 +03:00
"time"
2021-12-10 04:27:50 +03:00
repo_model "code.gitea.io/gitea/models/repo"
2021-11-24 12:49:20 +03:00
user_model "code.gitea.io/gitea/models/user"
2020-09-18 15:09:26 +03:00
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
2022-03-29 18:47:44 +03:00
"code.gitea.io/gitea/services/gitdiff"
2020-09-18 15:09:26 +03:00
)
// ToCommitUser convert a git.Signature to an api.CommitUser
func ToCommitUser ( sig * git . Signature ) * api . CommitUser {
return & api . CommitUser {
Identity : api . Identity {
Name : sig . Name ,
Email : sig . Email ,
} ,
Date : sig . When . UTC ( ) . Format ( time . RFC3339 ) ,
}
}
// ToCommitMeta convert a git.Tag to an api.CommitMeta
2021-12-10 04:27:50 +03:00
func ToCommitMeta ( repo * repo_model . Repository , tag * git . Tag ) * api . CommitMeta {
2020-09-18 15:09:26 +03:00
return & api . CommitMeta {
2020-10-05 07:07:54 +03:00
SHA : tag . Object . String ( ) ,
URL : util . URLJoin ( repo . APIURL ( ) , "git/commits" , tag . ID . String ( ) ) ,
Created : tag . Tagger . When ,
2020-09-18 15:09:26 +03:00
}
}
// ToPayloadCommit convert a git.Commit to api.PayloadCommit
2021-12-10 04:27:50 +03:00
func ToPayloadCommit ( repo * repo_model . Repository , c * git . Commit ) * api . PayloadCommit {
2020-09-18 15:09:26 +03:00
authorUsername := ""
2021-11-24 12:49:20 +03:00
if author , err := user_model . GetUserByEmail ( c . Author . Email ) ; err == nil {
2020-09-18 15:09:26 +03:00
authorUsername = author . Name
2021-11-24 12:49:20 +03:00
} else if ! user_model . IsErrUserNotExist ( err ) {
2020-09-18 15:09:26 +03:00
log . Error ( "GetUserByEmail: %v" , err )
}
committerUsername := ""
2021-11-24 12:49:20 +03:00
if committer , err := user_model . GetUserByEmail ( c . Committer . Email ) ; err == nil {
2020-09-18 15:09:26 +03:00
committerUsername = committer . Name
2021-11-24 12:49:20 +03:00
} else if ! user_model . IsErrUserNotExist ( err ) {
2020-09-18 15:09:26 +03:00
log . Error ( "GetUserByEmail: %v" , err )
}
return & api . PayloadCommit {
ID : c . ID . String ( ) ,
Message : c . Message ( ) ,
URL : util . URLJoin ( repo . HTMLURL ( ) , "commit" , c . ID . String ( ) ) ,
Author : & api . PayloadUser {
Name : c . Author . Name ,
Email : c . Author . Email ,
UserName : authorUsername ,
} ,
Committer : & api . PayloadUser {
Name : c . Committer . Name ,
Email : c . Committer . Email ,
UserName : committerUsername ,
} ,
Timestamp : c . Author . When ,
Verification : ToVerification ( c ) ,
}
}
// ToCommit convert a git.Commit to api.Commit
2022-10-06 06:21:04 +03:00
func ToCommit ( repo * repo_model . Repository , gitRepo * git . Repository , commit * git . Commit , userCache map [ string ] * user_model . User , stat bool ) ( * api . Commit , error ) {
2020-09-18 15:09:26 +03:00
var apiAuthor , apiCommitter * api . User
// Retrieve author and committer information
2021-11-24 12:49:20 +03:00
var cacheAuthor * user_model . User
2020-09-18 15:09:26 +03:00
var ok bool
if userCache == nil {
2021-11-24 12:49:20 +03:00
cacheAuthor = ( * user_model . User ) ( nil )
2020-09-18 15:09:26 +03:00
ok = false
} else {
cacheAuthor , ok = userCache [ commit . Author . Email ]
}
if ok {
2021-03-27 19:45:26 +03:00
apiAuthor = ToUser ( cacheAuthor , nil )
2020-09-18 15:09:26 +03:00
} else {
2021-11-24 12:49:20 +03:00
author , err := user_model . GetUserByEmail ( commit . Author . Email )
if err != nil && ! user_model . IsErrUserNotExist ( err ) {
2020-09-18 15:09:26 +03:00
return nil , err
} else if err == nil {
2021-03-27 19:45:26 +03:00
apiAuthor = ToUser ( author , nil )
2020-09-18 15:09:26 +03:00
if userCache != nil {
userCache [ commit . Author . Email ] = author
}
}
}
2021-11-24 12:49:20 +03:00
var cacheCommitter * user_model . User
2020-09-18 15:09:26 +03:00
if userCache == nil {
2021-11-24 12:49:20 +03:00
cacheCommitter = ( * user_model . User ) ( nil )
2020-09-18 15:09:26 +03:00
ok = false
} else {
cacheCommitter , ok = userCache [ commit . Committer . Email ]
}
if ok {
2021-03-27 19:45:26 +03:00
apiCommitter = ToUser ( cacheCommitter , nil )
2020-09-18 15:09:26 +03:00
} else {
2021-11-24 12:49:20 +03:00
committer , err := user_model . GetUserByEmail ( commit . Committer . Email )
if err != nil && ! user_model . IsErrUserNotExist ( err ) {
2020-09-18 15:09:26 +03:00
return nil , err
} else if err == nil {
2021-03-27 19:45:26 +03:00
apiCommitter = ToUser ( committer , nil )
2020-09-18 15:09:26 +03:00
if userCache != nil {
userCache [ commit . Committer . Email ] = committer
}
}
}
// Retrieve parent(s) of the commit
apiParents := make ( [ ] * api . CommitMeta , commit . ParentCount ( ) )
for i := 0 ; i < commit . ParentCount ( ) ; i ++ {
sha , _ := commit . ParentID ( i )
apiParents [ i ] = & api . CommitMeta {
2021-11-16 21:18:25 +03:00
URL : repo . APIURL ( ) + "/git/commits/" + url . PathEscape ( sha . String ( ) ) ,
2020-09-18 15:09:26 +03:00
SHA : sha . String ( ) ,
}
}
2022-10-06 06:21:04 +03:00
res := & api . Commit {
2020-09-18 15:09:26 +03:00
CommitMeta : & api . CommitMeta {
2021-11-16 21:18:25 +03:00
URL : repo . APIURL ( ) + "/git/commits/" + url . PathEscape ( commit . ID . String ( ) ) ,
2021-11-05 08:30:46 +03:00
SHA : commit . ID . String ( ) ,
Created : commit . Committer . When ,
2020-09-18 15:09:26 +03:00
} ,
2021-11-16 21:18:25 +03:00
HTMLURL : repo . HTMLURL ( ) + "/commit/" + url . PathEscape ( commit . ID . String ( ) ) ,
2020-09-18 15:09:26 +03:00
RepoCommit : & api . RepoCommit {
2021-11-16 21:18:25 +03:00
URL : repo . APIURL ( ) + "/git/commits/" + url . PathEscape ( commit . ID . String ( ) ) ,
2020-09-18 15:09:26 +03:00
Author : & api . CommitUser {
Identity : api . Identity {
2021-06-28 01:15:42 +03:00
Name : commit . Author . Name ,
Email : commit . Author . Email ,
2020-09-18 15:09:26 +03:00
} ,
Date : commit . Author . When . Format ( time . RFC3339 ) ,
} ,
Committer : & api . CommitUser {
Identity : api . Identity {
Name : commit . Committer . Name ,
Email : commit . Committer . Email ,
} ,
Date : commit . Committer . When . Format ( time . RFC3339 ) ,
} ,
Message : commit . Message ( ) ,
Tree : & api . CommitMeta {
2021-11-16 21:18:25 +03:00
URL : repo . APIURL ( ) + "/git/trees/" + url . PathEscape ( commit . ID . String ( ) ) ,
2021-11-05 08:30:46 +03:00
SHA : commit . ID . String ( ) ,
Created : commit . Committer . When ,
2020-09-18 15:09:26 +03:00
} ,
2022-03-29 18:47:44 +03:00
Verification : ToVerification ( commit ) ,
2020-09-18 15:09:26 +03:00
} ,
Author : apiAuthor ,
Committer : apiCommitter ,
Parents : apiParents ,
2022-10-06 06:21:04 +03:00
}
// Retrieve files affected by the commit
if stat {
fileStatus , err := git . GetCommitFileStatus ( gitRepo . Ctx , repo . RepoPath ( ) , commit . ID . String ( ) )
if err != nil {
return nil , err
}
affectedFileList := make ( [ ] * api . CommitAffectedFiles , 0 , len ( fileStatus . Added ) + len ( fileStatus . Removed ) + len ( fileStatus . Modified ) )
for _ , files := range [ ] [ ] string { fileStatus . Added , fileStatus . Removed , fileStatus . Modified } {
for _ , filename := range files {
affectedFileList = append ( affectedFileList , & api . CommitAffectedFiles {
Filename : filename ,
} )
}
}
diff , err := gitdiff . GetDiff ( gitRepo , & gitdiff . DiffOptions {
AfterCommitID : commit . ID . String ( ) ,
} )
if err != nil {
return nil , err
}
res . Files = affectedFileList
res . Stats = & api . CommitStats {
2022-03-29 18:47:44 +03:00
Total : diff . TotalAddition + diff . TotalDeletion ,
Additions : diff . TotalAddition ,
Deletions : diff . TotalDeletion ,
2022-10-06 06:21:04 +03:00
}
}
return res , nil
2020-09-18 15:09:26 +03:00
}