2019-02-03 11:35:17 +08:00
// Copyright 2018 The Gogs Authors. All rights reserved.
// Copyright 2019 The Gitea 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 (
2019-08-26 16:09:10 +02:00
"math"
"strconv"
2019-02-03 11:35:17 +08:00
"time"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
2019-03-27 17:33:00 +08:00
"code.gitea.io/gitea/modules/git"
2019-02-03 11:35:17 +08:00
"code.gitea.io/gitea/modules/setting"
2019-05-11 18:21:34 +08:00
api "code.gitea.io/gitea/modules/structs"
2019-02-03 11:35:17 +08:00
)
// GetSingleCommit get a commit via
func GetSingleCommit ( ctx * context . APIContext ) {
// swagger:operation GET /repos/{owner}/{repo}/git/commits/{sha} repository repoGetSingleCommit
// ---
// summary: Get a single commit from a repository
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: owner of the repo
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repo
// type: string
// required: true
// - name: sha
// in: path
// description: the commit hash
// type: string
// required: true
// responses:
// "200":
// "$ref": "#/responses/Commit"
// "404":
// "$ref": "#/responses/notFound"
gitRepo , err := git . OpenRepository ( ctx . Repo . Repository . RepoPath ( ) )
if err != nil {
ctx . ServerError ( "OpenRepository" , err )
return
}
commit , err := gitRepo . GetCommit ( ctx . Params ( ":sha" ) )
if err != nil {
ctx . NotFoundOrServerError ( "GetCommit" , git . IsErrNotExist , err )
return
}
2019-08-26 16:09:10 +02:00
json , err := toCommit ( ctx , ctx . Repo . Repository , commit , nil )
if err != nil {
ctx . ServerError ( "toCommit" , err )
return
}
ctx . JSON ( 200 , json )
}
// GetAllCommits get all commits via
func GetAllCommits ( ctx * context . APIContext ) {
// swagger:operation GET /repos/{owner}/{repo}/commits repository repoGetAllCommits
// ---
// summary: Get a list of all commits from a repository
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: owner of the repo
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repo
// type: string
// required: true
// - name: sha
// in: query
// description: SHA or branch to start listing commits from (usually 'master')
// type: string
// - name: page
// in: query
// description: page number of requested commits
// type: integer
// responses:
// "200":
// "$ref": "#/responses/CommitList"
// "404":
// "$ref": "#/responses/notFound"
// "409":
// "$ref": "#/responses/EmptyRepository"
if ctx . Repo . Repository . IsEmpty {
ctx . JSON ( 409 , api . APIError {
Message : "Git Repository is empty." ,
URL : setting . API . SwaggerURL ,
} )
return
}
gitRepo , err := git . OpenRepository ( ctx . Repo . Repository . RepoPath ( ) )
if err != nil {
ctx . ServerError ( "OpenRepository" , err )
return
}
page := ctx . QueryInt ( "page" )
if page <= 0 {
page = 1
}
sha := ctx . Query ( "sha" )
var baseCommit * git . Commit
if len ( sha ) == 0 {
// no sha supplied - use default branch
head , err := gitRepo . GetHEADBranch ( )
if err != nil {
ctx . ServerError ( "GetHEADBranch" , err )
return
}
baseCommit , err = gitRepo . GetBranchCommit ( head . Name )
if err != nil {
ctx . ServerError ( "GetCommit" , err )
return
}
} else {
// get commit specified by sha
baseCommit , err = gitRepo . GetCommit ( sha )
if err != nil {
ctx . ServerError ( "GetCommit" , err )
return
}
}
// Total commit count
commitsCountTotal , err := baseCommit . CommitsCount ( )
if err != nil {
ctx . ServerError ( "GetCommitsCount" , err )
return
}
pageCount := int ( math . Ceil ( float64 ( commitsCountTotal ) / float64 ( git . CommitsRangeSize ) ) )
// Query commits
commits , err := baseCommit . CommitsByRange ( page )
if err != nil {
ctx . ServerError ( "CommitsByRange" , err )
2019-02-03 11:35:17 +08:00
return
}
2019-08-26 16:09:10 +02:00
userCache := make ( map [ string ] * models . User )
apiCommits := make ( [ ] * api . Commit , commits . Len ( ) )
i := 0
for commitPointer := commits . Front ( ) ; commitPointer != nil ; commitPointer = commitPointer . Next ( ) {
commit := commitPointer . Value . ( * git . Commit )
// Create json struct
apiCommits [ i ] , err = toCommit ( ctx , ctx . Repo . Repository , commit , userCache )
if err != nil {
ctx . ServerError ( "toCommit" , err )
return
}
i ++
}
ctx . SetLinkHeader ( int ( commitsCountTotal ) , git . CommitsRangeSize )
ctx . Header ( ) . Set ( "X-Page" , strconv . Itoa ( page ) )
ctx . Header ( ) . Set ( "X-PerPage" , strconv . Itoa ( git . CommitsRangeSize ) )
ctx . Header ( ) . Set ( "X-Total" , strconv . FormatInt ( commitsCountTotal , 10 ) )
ctx . Header ( ) . Set ( "X-PageCount" , strconv . Itoa ( pageCount ) )
ctx . Header ( ) . Set ( "X-HasMore" , strconv . FormatBool ( page < pageCount ) )
ctx . JSON ( 200 , & apiCommits )
}
func toCommit ( ctx * context . APIContext , repo * models . Repository , commit * git . Commit , userCache map [ string ] * models . User ) ( * api . Commit , error ) {
var apiAuthor , apiCommitter * api . User
// Retrieve author and committer information
var cacheAuthor * models . User
var ok bool
if userCache == nil {
cacheAuthor = ( ( * models . User ) ( nil ) )
ok = false
} else {
cacheAuthor , ok = userCache [ commit . Author . Email ]
}
if ok {
apiAuthor = cacheAuthor . APIFormat ( )
} else {
author , err := models . GetUserByEmail ( commit . Author . Email )
if err != nil && ! models . IsErrUserNotExist ( err ) {
return nil , err
} else if err == nil {
apiAuthor = author . APIFormat ( )
if userCache != nil {
userCache [ commit . Author . Email ] = author
}
}
}
var cacheCommitter * models . User
if userCache == nil {
cacheCommitter = ( ( * models . User ) ( nil ) )
ok = false
} else {
cacheCommitter , ok = userCache [ commit . Committer . Email ]
}
if ok {
apiCommitter = cacheCommitter . APIFormat ( )
2019-02-03 11:35:17 +08:00
} else {
committer , err := models . GetUserByEmail ( commit . Committer . Email )
if err != nil && ! models . IsErrUserNotExist ( err ) {
2019-08-26 16:09:10 +02:00
return nil , err
2019-02-03 11:35:17 +08:00
} else if err == nil {
apiCommitter = committer . APIFormat ( )
2019-08-26 16:09:10 +02:00
if userCache != nil {
userCache [ commit . Committer . Email ] = committer
}
2019-02-03 11:35:17 +08:00
}
}
// 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 {
2019-08-26 16:09:10 +02:00
URL : repo . APIURL ( ) + "/git/commits/" + sha . String ( ) ,
2019-02-03 11:35:17 +08:00
SHA : sha . String ( ) ,
}
}
2019-08-26 16:09:10 +02:00
return & api . Commit {
2019-02-03 11:35:17 +08:00
CommitMeta : & api . CommitMeta {
2019-08-26 16:09:10 +02:00
URL : repo . APIURL ( ) + "/git/commits/" + commit . ID . String ( ) ,
2019-02-03 11:35:17 +08:00
SHA : commit . ID . String ( ) ,
} ,
2019-08-26 16:09:10 +02:00
HTMLURL : repo . HTMLURL ( ) + "/commit/" + commit . ID . String ( ) ,
2019-02-03 11:35:17 +08:00
RepoCommit : & api . RepoCommit {
2019-08-26 16:09:10 +02:00
URL : repo . APIURL ( ) + "/git/commits/" + commit . ID . String ( ) ,
2019-02-03 11:35:17 +08:00
Author : & api . CommitUser {
2019-03-22 09:38:49 -06:00
Identity : api . Identity {
2019-08-26 16:09:10 +02:00
Name : commit . Committer . Name ,
Email : commit . Committer . Email ,
2019-03-22 09:38:49 -06:00
} ,
Date : commit . Author . When . Format ( time . RFC3339 ) ,
2019-02-03 11:35:17 +08:00
} ,
Committer : & api . CommitUser {
2019-03-22 09:38:49 -06:00
Identity : api . Identity {
Name : commit . Committer . Name ,
Email : commit . Committer . Email ,
} ,
Date : commit . Committer . When . Format ( time . RFC3339 ) ,
2019-02-03 11:35:17 +08:00
} ,
2019-08-26 16:09:10 +02:00
Message : commit . Summary ( ) ,
2019-02-03 11:35:17 +08:00
Tree : & api . CommitMeta {
2019-08-26 16:09:10 +02:00
URL : repo . APIURL ( ) + "/git/trees/" + commit . ID . String ( ) ,
2019-02-03 11:35:17 +08:00
SHA : commit . ID . String ( ) ,
} ,
} ,
Author : apiAuthor ,
Committer : apiCommitter ,
Parents : apiParents ,
2019-08-26 16:09:10 +02:00
} , nil
2019-02-03 11:35:17 +08:00
}