2019-04-17 19:06:35 +03:00
// Copyright 2019 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2019-04-17 19:06:35 +03:00
2021-11-24 10:56:24 +03:00
package files
2019-04-17 19:06:35 +03:00
import (
2022-01-20 02:26:57 +03:00
"context"
2019-04-17 19:06:35 +03:00
"fmt"
2021-11-16 21:18:25 +03:00
"net/url"
2019-04-17 19:06:35 +03:00
"code.gitea.io/gitea/models"
2021-12-10 04:27:50 +03:00
repo_model "code.gitea.io/gitea/models/repo"
2019-04-17 19:06:35 +03:00
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
2019-05-11 13:21:34 +03:00
api "code.gitea.io/gitea/modules/structs"
2019-04-17 19:06:35 +03:00
)
// GetTreeBySHA get the GitTreeResponse of a repository using a sha hash.
2022-01-20 02:26:57 +03:00
func GetTreeBySHA ( ctx context . Context , repo * repo_model . Repository , gitRepo * git . Repository , sha string , page , perPage int , recursive bool ) ( * api . GitTreeResponse , error ) {
2019-04-17 19:06:35 +03:00
gitTree , err := gitRepo . GetTree ( sha )
if err != nil || gitTree == nil {
return nil , models . ErrSHANotFound {
SHA : sha ,
}
}
tree := new ( api . GitTreeResponse )
2019-05-03 03:33:11 +03:00
tree . SHA = gitTree . ResolvedID . String ( )
2021-11-16 21:18:25 +03:00
tree . URL = repo . APIURL ( ) + "/git/trees/" + url . PathEscape ( tree . SHA )
2019-04-17 19:06:35 +03:00
var entries git . Entries
if recursive {
2022-10-07 20:20:53 +03:00
entries , err = gitTree . ListEntriesRecursiveWithSize ( )
2019-04-17 19:06:35 +03:00
} else {
entries , err = gitTree . ListEntries ( )
}
if err != nil {
return nil , err
}
apiURL := repo . APIURL ( )
apiURLLen := len ( apiURL )
2024-02-24 09:55:19 +03:00
objectFormat := git . ObjectFormatFromName ( repo . ObjectFormatName )
2023-12-14 00:02:00 +03:00
hashLen := objectFormat . FullLength ( )
2019-04-17 19:06:35 +03:00
2023-12-14 00:02:00 +03:00
const gitBlobsPath = "/git/blobs/"
blobURL := make ( [ ] byte , apiURLLen + hashLen + len ( gitBlobsPath ) )
2019-06-12 22:41:28 +03:00
copy ( blobURL , apiURL )
2023-12-14 00:02:00 +03:00
copy ( blobURL [ apiURLLen : ] , [ ] byte ( gitBlobsPath ) )
2019-04-17 19:06:35 +03:00
2023-12-14 00:02:00 +03:00
const gitTreePath = "/git/trees/"
treeURL := make ( [ ] byte , apiURLLen + hashLen + len ( gitTreePath ) )
2019-06-12 22:41:28 +03:00
copy ( treeURL , apiURL )
2023-12-14 00:02:00 +03:00
copy ( treeURL [ apiURLLen : ] , [ ] byte ( gitTreePath ) )
2019-04-17 19:06:35 +03:00
2023-12-14 00:02:00 +03:00
// copyPos is at the start of the hash
copyPos := len ( treeURL ) - hashLen
2019-04-17 19:06:35 +03:00
if perPage <= 0 || perPage > setting . API . DefaultGitTreesPerPage {
perPage = setting . API . DefaultGitTreesPerPage
}
if page <= 0 {
page = 1
}
tree . Page = page
tree . TotalCount = len ( entries )
rangeStart := perPage * ( page - 1 )
if rangeStart >= len ( entries ) {
return tree , nil
}
var rangeEnd int
if len ( entries ) > perPage {
tree . Truncated = true
}
if rangeStart + perPage < len ( entries ) {
rangeEnd = rangeStart + perPage
} else {
rangeEnd = len ( entries )
}
tree . Entries = make ( [ ] api . GitEntry , rangeEnd - rangeStart )
for e := rangeStart ; e < rangeEnd ; e ++ {
i := e - rangeStart
2019-04-19 15:17:27 +03:00
2019-12-22 03:16:21 +03:00
tree . Entries [ i ] . Path = entries [ e ] . Name ( )
tree . Entries [ i ] . Mode = fmt . Sprintf ( "%06o" , entries [ e ] . Mode ( ) )
tree . Entries [ i ] . Type = entries [ e ] . Type ( )
tree . Entries [ i ] . Size = entries [ e ] . Size ( )
tree . Entries [ i ] . SHA = entries [ e ] . ID . String ( )
2019-04-17 19:06:35 +03:00
if entries [ e ] . IsDir ( ) {
copy ( treeURL [ copyPos : ] , entries [ e ] . ID . String ( ) )
2019-06-12 22:41:28 +03:00
tree . Entries [ i ] . URL = string ( treeURL )
2023-02-21 20:31:17 +03:00
} else if entries [ e ] . IsSubModule ( ) {
// In Github Rest API Version=2022-11-28, if a tree entry is a submodule,
// its url will be returned as an empty string.
// So the URL will be set to "" here.
tree . Entries [ i ] . URL = ""
2019-04-17 19:06:35 +03:00
} else {
copy ( blobURL [ copyPos : ] , entries [ e ] . ID . String ( ) )
2019-06-12 22:41:28 +03:00
tree . Entries [ i ] . URL = string ( blobURL )
2019-04-17 19:06:35 +03:00
}
}
return tree , nil
}