diff options
Diffstat (limited to 'modules/repofiles/tree.go')
-rw-r--r-- | modules/repofiles/tree.go | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/modules/repofiles/tree.go b/modules/repofiles/tree.go new file mode 100644 index 0000000000..8766ed36d0 --- /dev/null +++ b/modules/repofiles/tree.go @@ -0,0 +1,92 @@ +// 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 repofiles + +import ( + "fmt" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/setting" + api "code.gitea.io/sdk/gitea" +) + +// GetTreeBySHA get the GitTreeResponse of a repository using a sha hash. +func GetTreeBySHA(repo *models.Repository, sha string, page, perPage int, recursive bool) (*api.GitTreeResponse, error) { + gitRepo, err := git.OpenRepository(repo.RepoPath()) + gitTree, err := gitRepo.GetTree(sha) + if err != nil || gitTree == nil { + return nil, models.ErrSHANotFound{ + SHA: sha, + } + } + tree := new(api.GitTreeResponse) + tree.SHA = gitTree.ID.String() + tree.URL = repo.APIURL() + "/git/trees/" + tree.SHA + var entries git.Entries + if recursive { + entries, err = gitTree.ListEntriesRecursive() + } else { + entries, err = gitTree.ListEntries() + } + if err != nil { + return nil, err + } + apiURL := repo.APIURL() + apiURLLen := len(apiURL) + + // 51 is len(sha1) + len("/git/blobs/"). 40 + 11. + blobURL := make([]byte, apiURLLen+51) + copy(blobURL[:], apiURL) + copy(blobURL[apiURLLen:], "/git/blobs/") + + // 51 is len(sha1) + len("/git/trees/"). 40 + 11. + treeURL := make([]byte, apiURLLen+51) + copy(treeURL[:], apiURL) + copy(treeURL[apiURLLen:], "/git/trees/") + + // 40 is the size of the sha1 hash in hexadecimal format. + copyPos := len(treeURL) - 40 + + 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 + tree.Entries[i].Path = entries[e].Name() + tree.Entries[i].Mode = fmt.Sprintf("%06x", entries[e].Mode()) + tree.Entries[i].Type = string(entries[e].Type) + tree.Entries[i].Size = entries[e].Size() + tree.Entries[i].SHA = entries[e].ID.String() + + if entries[e].IsDir() { + copy(treeURL[copyPos:], entries[e].ID.String()) + tree.Entries[i].URL = string(treeURL[:]) + } else { + copy(blobURL[copyPos:], entries[e].ID.String()) + tree.Entries[i].URL = string(blobURL[:]) + } + } + return tree, nil +} |