|
- // 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"
- "net/url"
- "path"
- "strings"
-
- "code.gitea.io/gitea/models"
- "code.gitea.io/gitea/modules/git"
- api "code.gitea.io/gitea/modules/structs"
- )
-
- // ContentType repo content type
- type ContentType string
-
- // The string representations of different content types
- const (
- // ContentTypeRegular regular content type (file)
- ContentTypeRegular ContentType = "file"
- // ContentTypeDir dir content type (dir)
- ContentTypeDir ContentType = "dir"
- // ContentLink link content type (symlink)
- ContentTypeLink ContentType = "symlink"
- // ContentTag submodule content type (submodule)
- ContentTypeSubmodule ContentType = "submodule"
- )
-
- // String gets the string of ContentType
- func (ct *ContentType) String() string {
- return string(*ct)
- }
-
- // GetContentsOrList gets the meta data of a file's contents (*ContentsResponse) if treePath not a tree
- // directory, otherwise a listing of file contents ([]*ContentsResponse). Ref can be a branch, commit or tag
- func GetContentsOrList(repo *models.Repository, treePath, ref string) (interface{}, error) {
- if repo.IsEmpty {
- return make([]interface{}, 0), nil
- }
- if ref == "" {
- ref = repo.DefaultBranch
- }
- origRef := ref
-
- // Check that the path given in opts.treePath is valid (not a git path)
- cleanTreePath := CleanUploadFileName(treePath)
- if cleanTreePath == "" && treePath != "" {
- return nil, models.ErrFilenameInvalid{
- Path: treePath,
- }
- }
- treePath = cleanTreePath
-
- gitRepo, err := git.OpenRepository(repo.RepoPath())
- if err != nil {
- return nil, err
- }
-
- // Get the commit object for the ref
- commit, err := gitRepo.GetCommit(ref)
- if err != nil {
- return nil, err
- }
-
- entry, err := commit.GetTreeEntryByPath(treePath)
- if err != nil {
- return nil, err
- }
-
- if entry.Type() != "tree" {
- return GetContents(repo, treePath, origRef, false)
- }
-
- // We are in a directory, so we return a list of FileContentResponse objects
- var fileList []*api.ContentsResponse
-
- gitTree, err := commit.SubTree(treePath)
- if err != nil {
- return nil, err
- }
- entries, err := gitTree.ListEntries()
- if err != nil {
- return nil, err
- }
- for _, e := range entries {
- subTreePath := path.Join(treePath, e.Name())
- fileContentResponse, err := GetContents(repo, subTreePath, origRef, true)
- if err != nil {
- return nil, err
- }
- fileList = append(fileList, fileContentResponse)
- }
- return fileList, nil
- }
-
- // GetContents gets the meta data on a file's contents. Ref can be a branch, commit or tag
- func GetContents(repo *models.Repository, treePath, ref string, forList bool) (*api.ContentsResponse, error) {
- if ref == "" {
- ref = repo.DefaultBranch
- }
- origRef := ref
-
- // Check that the path given in opts.treePath is valid (not a git path)
- cleanTreePath := CleanUploadFileName(treePath)
- if cleanTreePath == "" && treePath != "" {
- return nil, models.ErrFilenameInvalid{
- Path: treePath,
- }
- }
- treePath = cleanTreePath
-
- gitRepo, err := git.OpenRepository(repo.RepoPath())
- if err != nil {
- return nil, err
- }
-
- // Get the commit object for the ref
- commit, err := gitRepo.GetCommit(ref)
- if err != nil {
- return nil, err
- }
- commitID := commit.ID.String()
- if len(ref) >= 4 && strings.HasPrefix(commitID, ref) {
- ref = commit.ID.String()
- }
-
- entry, err := commit.GetTreeEntryByPath(treePath)
- if err != nil {
- return nil, err
- }
-
- refType := gitRepo.GetRefType(ref)
- if refType == "invalid" {
- return nil, fmt.Errorf("no commit found for the ref [ref: %s]", ref)
- }
-
- selfURL, err := url.Parse(fmt.Sprintf("%s/contents/%s?ref=%s", repo.APIURL(), treePath, origRef))
- if err != nil {
- return nil, err
- }
- selfURLString := selfURL.String()
-
- // All content types have these fields in populated
- contentsResponse := &api.ContentsResponse{
- Name: entry.Name(),
- Path: treePath,
- SHA: entry.ID.String(),
- Size: entry.Size(),
- URL: &selfURLString,
- Links: &api.FileLinksResponse{
- Self: &selfURLString,
- },
- }
-
- // Now populate the rest of the ContentsResponse based on entry type
- if entry.IsRegular() {
- contentsResponse.Type = string(ContentTypeRegular)
- if blobResponse, err := GetBlobBySHA(repo, entry.ID.String()); err != nil {
- return nil, err
- } else if !forList {
- // We don't show the content if we are getting a list of FileContentResponses
- contentsResponse.Encoding = &blobResponse.Encoding
- contentsResponse.Content = &blobResponse.Content
- }
- } else if entry.IsDir() {
- contentsResponse.Type = string(ContentTypeDir)
- } else if entry.IsLink() {
- contentsResponse.Type = string(ContentTypeLink)
- // The target of a symlink file is the content of the file
- targetFromContent, err := entry.Blob().GetBlobContent()
- if err != nil {
- return nil, err
- }
- contentsResponse.Target = &targetFromContent
- } else if entry.IsSubModule() {
- contentsResponse.Type = string(ContentTypeSubmodule)
- submodule, err := commit.GetSubModule(treePath)
- if err != nil {
- return nil, err
- }
- contentsResponse.SubmoduleGitURL = &submodule.URL
- }
- // Handle links
- if entry.IsRegular() || entry.IsLink() {
- downloadURL, err := url.Parse(fmt.Sprintf("%s/raw/%s/%s/%s", repo.HTMLURL(), refType, ref, treePath))
- if err != nil {
- return nil, err
- }
- downloadURLString := downloadURL.String()
- contentsResponse.DownloadURL = &downloadURLString
- }
- if !entry.IsSubModule() {
- htmlURL, err := url.Parse(fmt.Sprintf("%s/src/%s/%s/%s", repo.HTMLURL(), refType, ref, treePath))
- if err != nil {
- return nil, err
- }
- htmlURLString := htmlURL.String()
- contentsResponse.HTMLURL = &htmlURLString
- contentsResponse.Links.HTMLURL = &htmlURLString
-
- gitURL, err := url.Parse(fmt.Sprintf("%s/git/blobs/%s", repo.APIURL(), entry.ID.String()))
- if err != nil {
- return nil, err
- }
- gitURLString := gitURL.String()
- contentsResponse.GitURL = &gitURLString
- contentsResponse.Links.GitURL = &gitURLString
- }
-
- return contentsResponse, nil
- }
|