mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-14 17:35:07 +02:00
Merge pull request #2 from lunny/add-file-tree-to-file-view-page
Add some backend logic
This commit is contained in:
commit
6cb22e5046
@ -9,6 +9,7 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/services/context"
|
"code.gitea.io/gitea/services/context"
|
||||||
|
files_service "code.gitea.io/gitea/services/repository/files"
|
||||||
|
|
||||||
"github.com/go-enry/go-enry/v2"
|
"github.com/go-enry/go-enry/v2"
|
||||||
)
|
)
|
||||||
@ -52,3 +53,18 @@ func isExcludedEntry(entry *git.TreeEntry) bool {
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Tree(ctx *context.Context) {
|
||||||
|
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)
|
||||||
|
}
|
@ -1157,14 +1157,14 @@ func registerRoutes(m *web.Router) {
|
|||||||
|
|
||||||
m.Group("/{username}/{reponame}", func() {
|
m.Group("/{username}/{reponame}", func() {
|
||||||
m.Get("/find/*", repo.FindFiles)
|
m.Get("/find/*", repo.FindFiles)
|
||||||
m.Group("/tree-list", func() {
|
m.Group("/tree-list", func() { // for find files
|
||||||
m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.TreeList)
|
m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.TreeList)
|
||||||
m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.TreeList)
|
m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.TreeList)
|
||||||
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.TreeList)
|
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.TreeList)
|
||||||
})
|
})
|
||||||
m.Group("/contents", func() {
|
m.Group("/tree", func() {
|
||||||
m.Get("", repo.GetContentsList)
|
m.Get("", repo.Tree)
|
||||||
m.Get("/*", repo.GetContents)
|
m.Get("/*", repo.Tree)
|
||||||
})
|
})
|
||||||
m.Get("/compare", repo.MustBeNotEmpty, repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.CompareDiff)
|
m.Get("/compare", repo.MustBeNotEmpty, repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.CompareDiff)
|
||||||
m.Combo("/compare/*", repo.MustBeNotEmpty, repo.SetEditorconfigIfExists).
|
m.Combo("/compare/*", repo.MustBeNotEmpty, repo.SetEditorconfigIfExists).
|
||||||
|
@ -7,9 +7,12 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
"code.gitea.io/gitea/modules/gitrepo"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
@ -118,3 +121,92 @@ func GetTreeBySHA(ctx context.Context, repo *repo_model.Repository, gitRepo *git
|
|||||||
}
|
}
|
||||||
return tree, nil
|
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
|
||||||
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
"code.gitea.io/gitea/modules/git"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/services/contexttest"
|
"code.gitea.io/gitea/services/contexttest"
|
||||||
|
|
||||||
@ -50,3 +51,50 @@ func TestGetTreeBySHA(t *testing.T) {
|
|||||||
|
|
||||||
assert.EqualValues(t, expectedTree, tree)
|
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)
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user