complete first version

This commit is contained in:
Lunny Xiao 2024-12-23 20:54:17 -08:00
parent b60ee86a24
commit a28b65d69b
No known key found for this signature in database
GPG Key ID: C3B7C91B632F738A
4 changed files with 149 additions and 29 deletions

View File

@ -5,12 +5,11 @@ package repo
import (
"net/http"
"path"
"strings"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/services/context"
files_service "code.gitea.io/gitea/services/repository/files"
"github.com/go-enry/go-enry/v2"
)
@ -55,26 +54,17 @@ func isExcludedEntry(entry *git.TreeEntry) bool {
return false
}
func getPossibleBranches(dir string) []string {
cnt := strings.Count(dir, "/")
branches := make([]string, cnt, cnt)
for i := 0; i < cnt; i++ {
branches[i] = dir
dir = path.Dir(dir)
}
return branches
}
func guessRefInfoAndDir(ctx *context.Context, dir string) (git.RefName, string, error) {
branches := getPossibleBranches(dir)
}
func Tree(ctx *context.Context) {
pathParam := ctx.PathParam("*")
dir := path.Dir(pathParam)
refName, realDir, err := guessRefInfoAndDir(ctx, dir)
dir := ctx.PathParam("*")
ref := ctx.FormTrim("ref")
recursive := ctx.FormBool("recursive")
// TODO: Only support branch for now
results, err := files_service.GetTreeList(ctx, ctx.Repo.Repository, dir, git.RefNameFromBranch(ref), recursive)
if err != nil {
ctx.ServerError("guessRefInfoAndDir", err)
return
}
ctx.JSON(http.StatusOK, results)
}

View File

@ -1,10 +0,0 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package repo
import "testing"
func Test_getPossibleBranches(t *testing.T) {
getPossibleBranches("")
}

View File

@ -7,10 +7,13 @@ import (
"context"
"fmt"
"net/url"
"path"
"strings"
"code.gitea.io/gitea/models"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
)
@ -99,3 +102,92 @@ func GetTreeBySHA(ctx context.Context, repo *repo_model.Repository, gitRepo *git
}
return tree, nil
}
type TreeEntry struct {
Name string `json:"name"`
IsFile bool `json:"isFile"`
Path string `json:"path"`
Children []*TreeEntry `json:"children"`
}
func GetTreeList(ctx context.Context, repo *repo_model.Repository, treePath string, ref git.RefName, recursive bool) ([]*TreeEntry, error) {
if repo.IsEmpty {
return nil, nil
}
if ref == "" {
ref = git.RefNameFromBranch(repo.DefaultBranch)
}
// 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, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo)
if err != nil {
return nil, err
}
defer closer.Close()
// Get the commit object for the ref
commit, err := gitRepo.GetCommit(ref.String())
if err != nil {
return nil, err
}
entry, err := commit.GetTreeEntryByPath(treePath)
if err != nil {
return nil, err
}
// If the entry is a file, we return a FileContentResponse object
if entry.Type() != "tree" {
return nil, fmt.Errorf("%s is not a tree", treePath)
}
gitTree, err := commit.SubTree(treePath)
if err != nil {
return nil, err
}
var entries git.Entries
if recursive {
entries, err = gitTree.ListEntriesRecursiveFast()
} else {
entries, err = gitTree.ListEntries()
}
if err != nil {
return nil, err
}
var treeList []*TreeEntry
mapTree := make(map[string][]*TreeEntry)
for _, e := range entries {
subTreePath := path.Join(treePath, e.Name())
if strings.Contains(e.Name(), "/") {
mapTree[path.Dir(e.Name())] = append(mapTree[path.Dir(e.Name())], &TreeEntry{
Name: path.Base(e.Name()),
IsFile: e.Mode() != git.EntryModeTree,
Path: subTreePath,
})
} else {
treeList = append(treeList, &TreeEntry{
Name: e.Name(),
IsFile: e.Mode() != git.EntryModeTree,
Path: subTreePath,
})
}
}
for _, tree := range treeList {
if !tree.IsFile {
tree.Children = mapTree[tree.Path]
}
}
return treeList, nil
}

View File

@ -7,6 +7,7 @@ import (
"testing"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/git"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/services/contexttest"
@ -50,3 +51,50 @@ func TestGetTreeBySHA(t *testing.T) {
assert.EqualValues(t, expectedTree, tree)
}
func Test_GetTreeList(t *testing.T) {
unittest.PrepareTestEnv(t)
ctx1, _ := contexttest.MockContext(t, "user2/repo1")
contexttest.LoadRepo(t, ctx1, 1)
contexttest.LoadRepoCommit(t, ctx1)
contexttest.LoadUser(t, ctx1, 2)
contexttest.LoadGitRepo(t, ctx1)
defer ctx1.Repo.GitRepo.Close()
refName := git.RefNameFromBranch(ctx1.Repo.Repository.DefaultBranch)
treeList, err := GetTreeList(ctx1, ctx1.Repo.Repository, "", refName, true)
assert.NoError(t, err)
assert.Len(t, treeList, 1)
assert.EqualValues(t, "README.md", treeList[0].Name)
assert.EqualValues(t, "README.md", treeList[0].Path)
assert.True(t, treeList[0].IsFile)
assert.Empty(t, treeList[0].Children)
ctx2, _ := contexttest.MockContext(t, "org3/repo3")
contexttest.LoadRepo(t, ctx2, 3)
contexttest.LoadRepoCommit(t, ctx2)
contexttest.LoadUser(t, ctx2, 2)
contexttest.LoadGitRepo(t, ctx2)
defer ctx2.Repo.GitRepo.Close()
refName = git.RefNameFromBranch(ctx2.Repo.Repository.DefaultBranch)
treeList, err = GetTreeList(ctx2, ctx2.Repo.Repository, "", refName, true)
assert.NoError(t, err)
assert.Len(t, treeList, 2)
assert.EqualValues(t, "README.md", treeList[0].Name)
assert.EqualValues(t, "README.md", treeList[0].Path)
assert.True(t, treeList[0].IsFile)
assert.Empty(t, treeList[0].Children)
assert.EqualValues(t, "doc", treeList[1].Name)
assert.EqualValues(t, "doc", treeList[1].Path)
assert.False(t, treeList[1].IsFile)
assert.Len(t, treeList[1].Children, 1)
assert.EqualValues(t, "doc.md", treeList[1].Children[0].Name)
assert.EqualValues(t, "doc/doc.md", treeList[1].Children[0].Path)
assert.True(t, treeList[1].Children[0].IsFile)
assert.Empty(t, treeList[1].Children[0].Children)
}