aboutsummaryrefslogtreecommitdiffstats
path: root/routers
diff options
context:
space:
mode:
authorNick <nick.guenther@polymtl.ca>2023-02-12 02:08:10 -0500
committerGitHub <noreply@github.com>2023-02-12 15:08:10 +0800
commite1aca7cbddea61f0802810cd2a05fa121c3d15ef (patch)
treecd405aa2a759e5980e3ea9cfc584648d17a04c18 /routers
parentb0f18726a34edeb47b6442ce06ebee102b9c8a83 (diff)
downloadgitea-e1aca7cbddea61f0802810cd2a05fa121c3d15ef.tar.gz
gitea-e1aca7cbddea61f0802810cd2a05fa121c3d15ef.zip
Deduplicate findReadmeFile() (#22177)
This code was copy-pasted at some point. Revisit it to reunify it. ~~Doing that then encouraged simplifying the types of a couple of related functions.~~ ~~As a follow-up, move two helper functions, `isReadmeFile()` and `isReadmeFileExtension()`, intimately tied to `findReadmeFile()`, in as package-private.~~ Signed-off-by: Nick Guenther <nick.guenther@polymtl.ca>
Diffstat (limited to 'routers')
-rw-r--r--routers/web/repo/view.go167
1 files changed, 69 insertions, 98 deletions
diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go
index 70f2a941be..ca86c744d1 100644
--- a/routers/web/repo/view.go
+++ b/routers/web/repo/view.go
@@ -56,18 +56,15 @@ type namedBlob struct {
blob *git.Blob
}
+// locate a README for a tree in one of the supported paths.
+//
+// entries is passed to reduce calls to ListEntries(), so
+// this has precondition:
+//
+// entries == ctx.Repo.Commit.SubTree(ctx.Repo.TreePath).ListEntries()
+//
// FIXME: There has to be a more efficient way of doing this
-func getReadmeFileFromPath(ctx *context.Context, commit *git.Commit, treePath string) (*namedBlob, error) {
- tree, err := commit.SubTree(treePath)
- if err != nil {
- return nil, err
- }
-
- entries, err := tree.ListEntries()
- if err != nil {
- return nil, err
- }
-
+func findReadmeFileInEntries(ctx *context.Context, entries []*git.TreeEntry) (*namedBlob, error) {
// Create a list of extensions in priority order
// 1. Markdown files - with and without localisation - e.g. README.en-us.md or README.md
// 2. Txt files - e.g. README.txt
@@ -75,16 +72,38 @@ func getReadmeFileFromPath(ctx *context.Context, commit *git.Commit, treePath st
exts := append(localizedExtensions(".md", ctx.Language()), ".txt", "") // sorted by priority
extCount := len(exts)
readmeFiles := make([]*namedBlob, extCount+1)
+
+ docsEntries := make([]*git.TreeEntry, 3) // (one of docs/, .gitea/ or .github/)
for _, entry := range entries {
if entry.IsDir() {
+ // as a special case for the top-level repo introduction README,
+ // fall back to subfolders, looking for e.g. docs/README.md, .gitea/README.zh-CN.txt, .github/README.txt, ...
+ // (note that docsEntries is ignored unless we are at the root)
+ lowerName := strings.ToLower(entry.Name())
+ switch lowerName {
+ case "docs":
+ if entry.Name() == "docs" || docsEntries[0] == nil {
+ docsEntries[0] = entry
+ }
+ case ".gitea":
+ if entry.Name() == ".gitea" || docsEntries[1] == nil {
+ docsEntries[1] = entry
+ }
+ case ".github":
+ if entry.Name() == ".github" || docsEntries[2] == nil {
+ docsEntries[2] = entry
+ }
+ }
continue
}
if i, ok := markup.IsReadmeFileExtension(entry.Name(), exts...); ok {
+ log.Debug("Potential readme file: %s", entry.Name())
if readmeFiles[i] == nil || base.NaturalSortLess(readmeFiles[i].name, entry.Blob().Name()) {
name := entry.Name()
isSymlink := entry.IsLink()
target := entry
if isSymlink {
+ var err error
target, err = entry.FollowLinks()
if err != nil && !git.IsErrBadLink(err) {
return nil, err
@@ -107,6 +126,33 @@ func getReadmeFileFromPath(ctx *context.Context, commit *git.Commit, treePath st
break
}
}
+
+ if ctx.Repo.TreePath == "" && readmeFile == nil {
+ for _, subTreeEntry := range docsEntries {
+ if subTreeEntry == nil {
+ continue
+ }
+ subTree := subTreeEntry.Tree()
+ if subTree == nil {
+ // this should be impossible; if subTreeEntry exists so should this.
+ continue
+ }
+ var err error
+ childEntries, err := subTree.ListEntries()
+ if err != nil {
+ return nil, err
+ }
+ readmeFile, err = findReadmeFileInEntries(ctx, childEntries)
+ if err != nil && !git.IsErrNotExist(err) {
+ return nil, err
+ }
+ if readmeFile != nil {
+ readmeFile.name = subTreeEntry.Name() + "/" + readmeFile.name
+ break
+ }
+ }
+ }
+
return readmeFile, nil
}
@@ -127,12 +173,20 @@ func renderDirectory(ctx *context.Context, treeLink string) {
ctx.Data["CanUploadFile"] = setting.Repository.Upload.Enabled && !ctx.Repo.Repository.IsArchived
}
- readmeFile, readmeTreelink := findReadmeFile(ctx, entries, treeLink)
- if ctx.Written() || readmeFile == nil {
+ if ctx.Written() {
+ return
+ }
+
+ readmeFile, err := findReadmeFileInEntries(ctx, entries)
+ if err != nil {
+ ctx.ServerError("findReadmeFileInEntries", err)
+ return
+ }
+ if readmeFile == nil {
return
}
- renderReadmeFile(ctx, readmeFile, readmeTreelink)
+ renderReadmeFile(ctx, readmeFile, treeLink)
}
// localizedExtensions prepends the provided language code with and without a
@@ -157,89 +211,6 @@ func localizedExtensions(ext, languageCode string) (localizedExts []string) {
return []string{lowerLangCode + ext, ext}
}
-func findReadmeFile(ctx *context.Context, entries git.Entries, treeLink string) (*namedBlob, string) {
- // Create a list of extensions in priority order
- // 1. Markdown files - with and without localisation - e.g. README.en-us.md or README.md
- // 2. Txt files - e.g. README.txt
- // 3. No extension - e.g. README
- exts := append(localizedExtensions(".md", ctx.Language()), ".txt", "") // sorted by priority
- extCount := len(exts)
- readmeFiles := make([]*namedBlob, extCount+1)
-
- docsEntries := make([]*git.TreeEntry, 3) // (one of docs/, .gitea/ or .github/)
- for _, entry := range entries {
- if entry.IsDir() {
- lowerName := strings.ToLower(entry.Name())
- switch lowerName {
- case "docs":
- if entry.Name() == "docs" || docsEntries[0] == nil {
- docsEntries[0] = entry
- }
- case ".gitea":
- if entry.Name() == ".gitea" || docsEntries[1] == nil {
- docsEntries[1] = entry
- }
- case ".github":
- if entry.Name() == ".github" || docsEntries[2] == nil {
- docsEntries[2] = entry
- }
- }
- continue
- }
-
- if i, ok := markup.IsReadmeFileExtension(entry.Name(), exts...); ok {
- log.Debug("Potential readme file: %s", entry.Name())
- name := entry.Name()
- isSymlink := entry.IsLink()
- target := entry
- if isSymlink {
- var err error
- target, err = entry.FollowLinks()
- if err != nil && !git.IsErrBadLink(err) {
- ctx.ServerError("FollowLinks", err)
- return nil, ""
- }
- }
- if target != nil && (target.IsExecutable() || target.IsRegular()) {
- readmeFiles[i] = &namedBlob{
- name,
- isSymlink,
- target.Blob(),
- }
- }
- }
- }
-
- var readmeFile *namedBlob
- readmeTreelink := treeLink
- for _, f := range readmeFiles {
- if f != nil {
- readmeFile = f
- break
- }
- }
-
- if ctx.Repo.TreePath == "" && readmeFile == nil {
- for _, entry := range docsEntries {
- if entry == nil {
- continue
- }
- var err error
- readmeFile, err = getReadmeFileFromPath(ctx, ctx.Repo.Commit, entry.GetSubJumpablePathName())
- if err != nil {
- ctx.ServerError("getReadmeFileFromPath", err)
- return nil, ""
- }
- if readmeFile != nil {
- readmeFile.name = entry.Name() + "/" + readmeFile.name
- readmeTreelink = treeLink + "/" + util.PathEscapeSegments(entry.GetSubJumpablePathName())
- break
- }
- }
- }
- return readmeFile, readmeTreelink
-}
-
type fileInfo struct {
isTextFile bool
isLFSFile bool
@@ -342,7 +313,7 @@ func renderReadmeFile(ctx *context.Context, readmeFile *namedBlob, readmeTreelin
ctx.Data["EscapeStatus"], ctx.Data["FileContent"], err = markupRender(ctx, &markup.RenderContext{
Ctx: ctx,
RelativePath: path.Join(ctx.Repo.TreePath, readmeFile.name), // ctx.Repo.TreePath is the directory not the Readme so we must append the Readme filename (and path).
- URLPrefix: readmeTreelink,
+ URLPrefix: path.Dir(readmeTreelink),
Metas: ctx.Repo.Repository.ComposeDocumentMetas(),
GitRepo: ctx.Repo.GitRepo,
}, rd)