* Refactor: dont expose help functions * repofiles GetContents: dont ignore executables * CI.restart()
		
			
				
	
	
		
			218 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			218 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// 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
 | 
						|
	}
 | 
						|
	defer gitRepo.Close()
 | 
						|
 | 
						|
	// 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
 | 
						|
	}
 | 
						|
	defer gitRepo.Close()
 | 
						|
 | 
						|
	// 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() || entry.IsExecutable() {
 | 
						|
		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
 | 
						|
}
 |