| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- // Copyright 2022 The Gitea Authors. All rights reserved.
- // SPDX-License-Identifier: MIT
-
- package repo
-
- import (
- "html/template"
- "net/http"
- "path"
- "strings"
-
- pull_model "code.gitea.io/gitea/models/pull"
- "code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/fileicon"
- "code.gitea.io/gitea/modules/git"
- "code.gitea.io/gitea/services/context"
- "code.gitea.io/gitea/services/gitdiff"
- files_service "code.gitea.io/gitea/services/repository/files"
-
- "github.com/go-enry/go-enry/v2"
- )
-
- // TreeList get all files' entries of a repository
- func TreeList(ctx *context.Context) {
- tree, err := ctx.Repo.Commit.SubTree("/")
- if err != nil {
- ctx.ServerError("Repo.Commit.SubTree", err)
- return
- }
-
- entries, err := tree.ListEntriesRecursiveFast()
- if err != nil {
- ctx.ServerError("ListEntriesRecursiveFast", err)
- return
- }
- entries.CustomSort(base.NaturalSortLess)
-
- files := make([]string, 0, len(entries))
- for _, entry := range entries {
- if !isExcludedEntry(entry) {
- files = append(files, entry.Name())
- }
- }
- ctx.JSON(http.StatusOK, files)
- }
-
- func isExcludedEntry(entry *git.TreeEntry) bool {
- if entry.IsDir() {
- return true
- }
-
- if entry.IsSubModule() {
- return true
- }
-
- if enry.IsVendor(entry.Name()) {
- return true
- }
-
- return false
- }
-
- // WebDiffFileItem is used by frontend, check the field names in frontend before changing
- type WebDiffFileItem struct {
- FullName string
- DisplayName string
- NameHash string
- DiffStatus string
- EntryMode string
- IsViewed bool
- Children []*WebDiffFileItem
- FileIcon template.HTML
- }
-
- // WebDiffFileTree is used by frontend, check the field names in frontend before changing
- type WebDiffFileTree struct {
- TreeRoot WebDiffFileItem
- }
-
- // transformDiffTreeForWeb transforms a gitdiff.DiffTree into a WebDiffFileTree for Web UI rendering
- // it also takes a map of file names to their viewed state, which is used to mark files as viewed
- func transformDiffTreeForWeb(renderedIconPool *fileicon.RenderedIconPool, diffTree *gitdiff.DiffTree, filesViewedState map[string]pull_model.ViewedState) (dft WebDiffFileTree) {
- dirNodes := map[string]*WebDiffFileItem{"": &dft.TreeRoot}
- addItem := func(item *WebDiffFileItem) {
- var parentPath string
- pos := strings.LastIndexByte(item.FullName, '/')
- if pos == -1 {
- item.DisplayName = item.FullName
- } else {
- parentPath = item.FullName[:pos]
- item.DisplayName = item.FullName[pos+1:]
- }
- parentNode, parentExists := dirNodes[parentPath]
- if !parentExists {
- parentNode = &dft.TreeRoot
- fields := strings.Split(parentPath, "/")
- for idx, field := range fields {
- nodePath := strings.Join(fields[:idx+1], "/")
- node, ok := dirNodes[nodePath]
- if !ok {
- node = &WebDiffFileItem{EntryMode: "tree", DisplayName: field, FullName: nodePath}
- dirNodes[nodePath] = node
- parentNode.Children = append(parentNode.Children, node)
- }
- parentNode = node
- }
- }
- parentNode.Children = append(parentNode.Children, item)
- }
-
- for _, file := range diffTree.Files {
- item := &WebDiffFileItem{FullName: file.HeadPath, DiffStatus: file.Status}
- item.IsViewed = filesViewedState[item.FullName] == pull_model.Viewed
- item.NameHash = git.HashFilePathForWebUI(item.FullName)
- item.FileIcon = fileicon.RenderEntryIconHTML(renderedIconPool, &fileicon.EntryInfo{BaseName: path.Base(file.HeadPath), EntryMode: file.HeadMode})
-
- switch file.HeadMode {
- case git.EntryModeTree:
- item.EntryMode = "tree"
- case git.EntryModeCommit:
- item.EntryMode = "commit" // submodule
- default:
- // default to empty, and will be treated as "blob" file because there is no "symlink" support yet
- }
- addItem(item)
- }
-
- var mergeSingleDir func(node *WebDiffFileItem)
- mergeSingleDir = func(node *WebDiffFileItem) {
- if len(node.Children) == 1 {
- if child := node.Children[0]; child.EntryMode == "tree" {
- node.FullName = child.FullName
- node.DisplayName = node.DisplayName + "/" + child.DisplayName
- node.Children = child.Children
- mergeSingleDir(node)
- }
- }
- }
- for _, node := range dft.TreeRoot.Children {
- mergeSingleDir(node)
- }
- return dft
- }
-
- func TreeViewNodes(ctx *context.Context) {
- renderedIconPool := fileicon.NewRenderedIconPool()
- results, err := files_service.GetTreeViewNodes(ctx, ctx.Repo.RepoLink, renderedIconPool, ctx.Repo.Commit, ctx.Repo.TreePath, ctx.FormString("sub_path"))
- if err != nil {
- ctx.ServerError("GetTreeViewNodes", err)
- return
- }
- ctx.JSON(http.StatusOK, map[string]any{"fileTreeNodes": results, "renderedIconPool": renderedIconPool.IconSVGs})
- }
|