@@ -5,6 +5,7 @@ package repo
55
66import (
77 "net/http"
8+ "strings"
89
910 pull_model "code.gitea.io/gitea/models/pull"
1011 "code.gitea.io/gitea/modules/base"
@@ -57,34 +58,85 @@ func isExcludedEntry(entry *git.TreeEntry) bool {
5758 return false
5859}
5960
60- type FileDiffFile struct {
61- Name string
61+ // WebDiffFileItem is used by frontend, check the field names in frontend before changing
62+ type WebDiffFileItem struct {
63+ FullName string
64+ DisplayName string
6265 NameHash string
63- IsSubmodule bool
66+ DiffStatus string
67+ EntryMode string
6468 IsViewed bool
65- Status string
69+ Children []* WebDiffFileItem
70+ // TODO: add icon support in the future
6671}
6772
68- // transformDiffTreeForUI transforms a DiffTree into a slice of FileDiffFile for UI rendering
73+ // WebDiffFileTree is used by frontend, check the field names in frontend before changing
74+ type WebDiffFileTree struct {
75+ TreeRoot WebDiffFileItem
76+ }
77+
78+ // transformDiffTreeForWeb transforms a gitdiff.DiffTree into a WebDiffFileTree for Web UI rendering
6979// it also takes a map of file names to their viewed state, which is used to mark files as viewed
70- func transformDiffTreeForUI (diffTree * gitdiff.DiffTree , filesViewedState map [string ]pull_model.ViewedState ) []FileDiffFile {
71- files := make ([]FileDiffFile , 0 , len (diffTree .Files ))
80+ func transformDiffTreeForWeb (diffTree * gitdiff.DiffTree , filesViewedState map [string ]pull_model.ViewedState ) (dft WebDiffFileTree ) {
81+ dirNodes := map [string ]* WebDiffFileItem {"" : & dft .TreeRoot }
82+ addItem := func (item * WebDiffFileItem ) {
83+ var parentPath string
84+ pos := strings .LastIndexByte (item .FullName , '/' )
85+ if pos == - 1 {
86+ item .DisplayName = item .FullName
87+ } else {
88+ parentPath = item .FullName [:pos ]
89+ item .DisplayName = item .FullName [pos + 1 :]
90+ }
91+ parentNode , parentExists := dirNodes [parentPath ]
92+ if ! parentExists {
93+ parentNode = & dft .TreeRoot
94+ fields := strings .Split (parentPath , "/" )
95+ for idx , field := range fields {
96+ nodePath := strings .Join (fields [:idx + 1 ], "/" )
97+ node , ok := dirNodes [nodePath ]
98+ if ! ok {
99+ node = & WebDiffFileItem {EntryMode : "tree" , DisplayName : field , FullName : nodePath }
100+ dirNodes [nodePath ] = node
101+ parentNode .Children = append (parentNode .Children , node )
102+ }
103+ parentNode = node
104+ }
105+ }
106+ parentNode .Children = append (parentNode .Children , item )
107+ }
72108
73109 for _ , file := range diffTree .Files {
74- nameHash := git .HashFilePathForWebUI (file .HeadPath )
75- isSubmodule := file .HeadMode == git .EntryModeCommit
76- isViewed := filesViewedState [file .HeadPath ] == pull_model .Viewed
77-
78- files = append (files , FileDiffFile {
79- Name : file .HeadPath ,
80- NameHash : nameHash ,
81- IsSubmodule : isSubmodule ,
82- IsViewed : isViewed ,
83- Status : file .Status ,
84- })
110+ item := & WebDiffFileItem {FullName : file .HeadPath , DiffStatus : file .Status }
111+ item .IsViewed = filesViewedState [item .FullName ] == pull_model .Viewed
112+ item .NameHash = git .HashFilePathForWebUI (item .FullName )
113+
114+ switch file .HeadMode {
115+ case git .EntryModeTree :
116+ item .EntryMode = "tree"
117+ case git .EntryModeCommit :
118+ item .EntryMode = "commit" // submodule
119+ default :
120+ // default to empty, and will be treated as "blob" file because there is no "symlink" support yet
121+ }
122+ addItem (item )
85123 }
86124
87- return files
125+ var mergeSingleDir func (node * WebDiffFileItem )
126+ mergeSingleDir = func (node * WebDiffFileItem ) {
127+ if len (node .Children ) == 1 {
128+ if child := node .Children [0 ]; child .EntryMode == "tree" {
129+ node .FullName = child .FullName
130+ node .DisplayName = node .DisplayName + "/" + child .DisplayName
131+ node .Children = child .Children
132+ mergeSingleDir (node )
133+ }
134+ }
135+ }
136+ for _ , node := range dft .TreeRoot .Children {
137+ mergeSingleDir (node )
138+ }
139+ return dft
88140}
89141
90142func TreeViewNodes (ctx * context.Context ) {
0 commit comments