Skip to content

Commit b02f061

Browse files
user2kousu
authored andcommitted
Avoid re-scanning directories when searching for READMEs.
When rendering a directory's README we have scanned its Tree once, looking for the README; but we allow READMEs in some special subfolders too (docs/, .gitea/, .github/), and may need to scan them. Since we've already scanned the top Tree, we have the subfolders' SHA1 object IDs cached, so, as a minor optimization, instead of calling SubTree(path string), which re-scans the Tree before using Repository.getTree() to actually produce their Tree objects, call Repository.getTree() directly. But it's a private method, so first expose it via new TreeEntry.Tree(). Feedback from @lunny: https://github.com/go-gitea/gitea/pull/22177/files#r1053953034
1 parent 950f54b commit b02f061

File tree

2 files changed

+47
-13
lines changed

2 files changed

+47
-13
lines changed

modules/git/tree_entry.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,15 @@ func (te *TreeEntry) FollowLinks() (*TreeEntry, error) {
101101
return entry, nil
102102
}
103103

104+
// returns the subtree, or nil if this is not a tree
105+
func (te *TreeEntry) Tree() *Tree {
106+
t, err := te.ptree.repo.getTree(te.ID)
107+
if err != nil {
108+
return nil
109+
}
110+
return t
111+
}
112+
104113
// GetSubJumpablePathName return the full path of subdirectory jumpable ( contains only one directory )
105114
func (te *TreeEntry) GetSubJumpablePathName() string {
106115
if te.IsSubModule() || !te.IsDir() {

routers/web/repo/view.go

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,7 @@ func isReadmeFileExtension(name string, ext ...string) (int, bool) {
9595
}
9696

9797
// FIXME: There has to be a more efficient way of doing this
98-
func findReadmeFileInPath(ctx *context.Context, treePath string) (*namedBlob, error) {
99-
tree, err := ctx.Repo.Commit.SubTree(treePath)
100-
if err != nil {
101-
return nil, err
102-
}
103-
98+
func findReadmeFileInTree(ctx *context.Context, tree *git.Tree, searchSubtrees bool) (*namedBlob, error) {
10499
entries, err := tree.ListEntries()
105100
if err != nil {
106101
return nil, err
@@ -113,8 +108,28 @@ func findReadmeFileInPath(ctx *context.Context, treePath string) (*namedBlob, er
113108
exts := append(localizedExtensions(".md", ctx.Language()), ".txt", "") // sorted by priority
114109
extCount := len(exts)
115110
readmeFiles := make([]*namedBlob, extCount+1)
111+
112+
docsEntries := make([]*git.TreeEntry, 3) // (one of docs/, .gitea/ or .github/)
116113
for _, entry := range entries {
117114
if entry.IsDir() {
115+
// as a special case for the top-level repo introduction README,
116+
// fall back to subfolders, looking for e.g. docs/README.md, .gitea/README.zh-CN.txt, .github/README.txt, ...
117+
// (note that docsEntries is ignored unless searchSubtrees)
118+
lowerName := strings.ToLower(entry.Name())
119+
switch lowerName {
120+
case "docs":
121+
if entry.Name() == "docs" || docsEntries[0] == nil {
122+
docsEntries[0] = entry
123+
}
124+
case ".gitea":
125+
if entry.Name() == ".gitea" || docsEntries[1] == nil {
126+
docsEntries[1] = entry
127+
}
128+
case ".github":
129+
if entry.Name() == ".github" || docsEntries[2] == nil {
130+
docsEntries[2] = entry
131+
}
132+
}
118133
continue
119134
}
120135
if i, ok := isReadmeFileExtension(entry.Name(), exts...); ok {
@@ -147,17 +162,23 @@ func findReadmeFileInPath(ctx *context.Context, treePath string) (*namedBlob, er
147162
}
148163
}
149164

150-
// as a special case for the top-level repo introduction README,
151-
// fall back to subfolders, looking for e.g. docs/README.md, .gitea/README.zh-CN.txt, .github/README.txt, ...
152-
if treePath == "" && readmeFile == nil {
153-
for _, subfolder := range []string{"docs", ".gitea", ".github"} {
165+
if searchSubtrees && readmeFile == nil {
166+
for _, subTreeEntry := range docsEntries {
167+
if subTreeEntry == nil {
168+
continue
169+
}
170+
subTree := subTreeEntry.Tree()
171+
if subTree == nil {
172+
// this should be impossible; if subTreeEntry exists so should this.
173+
continue
174+
}
154175
var err error
155-
readmeFile, err = findReadmeFileInPath(ctx, subfolder)
176+
readmeFile, err = findReadmeFileInTree(ctx, subTree, false)
156177
if err != nil && !git.IsErrNotExist(err) {
157178
return nil, err
158179
}
159180
if readmeFile != nil {
160-
readmeFile.name = subfolder + "/" + readmeFile.name
181+
readmeFile.name = subTreeEntry.Name() + "/" + readmeFile.name
161182
break
162183
}
163184
}
@@ -222,7 +243,11 @@ func localizedExtensions(ext, languageCode string) (localizedExts []string) {
222243
}
223244

224245
func findReadmeFile(ctx *context.Context) (*namedBlob, error) {
225-
readmeFile, err := findReadmeFileInPath(ctx, ctx.Repo.TreePath)
246+
tree, err := ctx.Repo.Commit.SubTree(ctx.Repo.TreePath)
247+
if err != nil {
248+
return nil, err
249+
}
250+
readmeFile, err := findReadmeFileInTree(ctx, tree, (ctx.Repo.TreePath == ""))
226251
if err != nil {
227252
return nil, err
228253
}

0 commit comments

Comments
 (0)