@@ -50,12 +50,6 @@ const (
5050 tplMigrating base.TplName = "repo/migrate/migrating"
5151)
5252
53- type namedBlob struct {
54- name string
55- isSymlink bool
56- blob * git.Blob
57- }
58-
5953// locate a README for a tree in one of the supported paths.
6054//
6155// entries is passed to reduce calls to ListEntries(), so
@@ -64,14 +58,14 @@ type namedBlob struct {
6458// entries == ctx.Repo.Commit.SubTree(ctx.Repo.TreePath).ListEntries()
6559//
6660// FIXME: There has to be a more efficient way of doing this
67- func findReadmeFileInEntries (ctx * context.Context , entries []* git.TreeEntry ) (* namedBlob , error ) {
61+ func findReadmeFileInEntries (ctx * context.Context , entries []* git.TreeEntry ) (string , * git. TreeEntry , error ) {
6862 // Create a list of extensions in priority order
6963 // 1. Markdown files - with and without localisation - e.g. README.en-us.md or README.md
7064 // 2. Txt files - e.g. README.txt
7165 // 3. No extension - e.g. README
7266 exts := append (localizedExtensions (".md" , ctx .Language ()), ".txt" , "" ) // sorted by priority
7367 extCount := len (exts )
74- readmeFiles := make ([]* namedBlob , extCount + 1 )
68+ readmeFiles := make ([]* git. TreeEntry , extCount + 1 )
7569
7670 docsEntries := make ([]* git.TreeEntry , 3 ) // (one of docs/, .gitea/ or .github/)
7771 for _ , entry := range entries {
@@ -98,28 +92,21 @@ func findReadmeFileInEntries(ctx *context.Context, entries []*git.TreeEntry) (*n
9892 }
9993 if i , ok := util .IsReadmeFileExtension (entry .Name (), exts ... ); ok {
10094 log .Debug ("Potential readme file: %s" , entry .Name ())
101- if readmeFiles [i ] == nil || base .NaturalSortLess (readmeFiles [i ].name , entry .Blob ().Name ()) {
102- name := entry .Name ()
103- isSymlink := entry .IsLink ()
104- target := entry
105- if isSymlink {
106- var err error
107- target , err = entry .FollowLinks ()
95+ if readmeFiles [i ] == nil || base .NaturalSortLess (readmeFiles [i ].Name (), entry .Blob ().Name ()) {
96+ if entry .IsLink () {
97+ target , err := entry .FollowLinks ()
10898 if err != nil && ! git .IsErrBadLink (err ) {
109- return nil , err
110- }
111- }
112- if target != nil && (target .IsExecutable () || target .IsRegular ()) {
113- readmeFiles [i ] = & namedBlob {
114- name ,
115- isSymlink ,
116- target .Blob (),
99+ return "" , nil , err
100+ } else if target != nil && (target .IsExecutable () || target .IsRegular ()) {
101+ readmeFiles [i ] = entry
117102 }
103+ } else {
104+ readmeFiles [i ] = entry
118105 }
119106 }
120107 }
121108 }
122- var readmeFile * namedBlob
109+ var readmeFile * git. TreeEntry
123110 for _ , f := range readmeFiles {
124111 if f != nil {
125112 readmeFile = f
@@ -140,20 +127,20 @@ func findReadmeFileInEntries(ctx *context.Context, entries []*git.TreeEntry) (*n
140127 var err error
141128 childEntries , err := subTree .ListEntries ()
142129 if err != nil {
143- return nil , err
130+ return "" , nil , err
144131 }
145- readmeFile , err = findReadmeFileInEntries (ctx , childEntries )
132+
133+ subfolder , readmeFile , err := findReadmeFileInEntries (ctx , childEntries )
146134 if err != nil && ! git .IsErrNotExist (err ) {
147- return nil , err
135+ return "" , nil , err
148136 }
149137 if readmeFile != nil {
150- readmeFile .name = subTreeEntry .Name () + "/" + readmeFile .name
151- break
138+ return path .Join (subTreeEntry .Name (), subfolder ), readmeFile , nil
152139 }
153140 }
154141 }
155142
156- return readmeFile , nil
143+ return "" , readmeFile , nil
157144}
158145
159146func renderDirectory (ctx * context.Context , treeLink string ) {
@@ -177,16 +164,13 @@ func renderDirectory(ctx *context.Context, treeLink string) {
177164 return
178165 }
179166
180- readmeFile , err := findReadmeFileInEntries (ctx , entries )
167+ subfolder , readmeFile , err := findReadmeFileInEntries (ctx , entries )
181168 if err != nil {
182169 ctx .ServerError ("findReadmeFileInEntries" , err )
183170 return
184171 }
185- if readmeFile == nil {
186- return
187- }
188172
189- renderReadmeFile (ctx , readmeFile , fmt . Sprintf ( "%s/%s" , treeLink , readmeFile . name ) )
173+ renderReadmeFile (ctx , subfolder , readmeFile , treeLink )
190174}
191175
192176// localizedExtensions prepends the provided language code with and without a
@@ -270,25 +254,35 @@ func getFileReader(repoID int64, blob *git.Blob) ([]byte, io.ReadCloser, *fileIn
270254 return buf , dataRc , & fileInfo {st .IsText (), true , meta .Size , & meta .Pointer , st }, nil
271255}
272256
273- func renderReadmeFile (ctx * context.Context , readmeFile * namedBlob , readmeTreelink string ) {
257+ func renderReadmeFile (ctx * context.Context , subfolder string , readmeFile * git.TreeEntry , readmeTreelink string ) {
258+ target := readmeFile
259+ if readmeFile != nil && readmeFile .IsLink () {
260+ target , _ = readmeFile .FollowLinks ()
261+ }
262+ if target == nil {
263+ // if findReadmeFile() failed and/or gave us a broken symlink (which it shouldn't)
264+ // simply skip rendering the README
265+ return
266+ }
267+
274268 ctx .Data ["RawFileLink" ] = ""
275269 ctx .Data ["ReadmeInList" ] = true
276270 ctx .Data ["ReadmeExist" ] = true
277- ctx .Data ["FileIsSymlink" ] = readmeFile .isSymlink
271+ ctx .Data ["FileIsSymlink" ] = readmeFile .IsLink ()
278272
279- buf , dataRc , fInfo , err := getFileReader (ctx .Repo .Repository .ID , readmeFile . blob )
273+ buf , dataRc , fInfo , err := getFileReader (ctx .Repo .Repository .ID , target . Blob () )
280274 if err != nil {
281275 ctx .ServerError ("getFileReader" , err )
282276 return
283277 }
284278 defer dataRc .Close ()
285279
286280 ctx .Data ["FileIsText" ] = fInfo .isTextFile
287- ctx .Data ["FileName" ] = readmeFile .name
281+ ctx .Data ["FileName" ] = path . Join ( subfolder , readmeFile .Name ())
288282 ctx .Data ["IsLFSFile" ] = fInfo .isLFSFile
289283
290284 if fInfo .isLFSFile {
291- filenameBase64 := base64 .RawURLEncoding .EncodeToString ([]byte (readmeFile .name ))
285+ filenameBase64 := base64 .RawURLEncoding .EncodeToString ([]byte (readmeFile .Name () ))
292286 ctx .Data ["RawFileLink" ] = fmt .Sprintf ("%s.git/info/lfs/objects/%s/%s" , ctx .Repo .Repository .Link (), url .PathEscape (fInfo .lfsMeta .Oid ), url .PathEscape (filenameBase64 ))
293287 }
294288
@@ -306,19 +300,19 @@ func renderReadmeFile(ctx *context.Context, readmeFile *namedBlob, readmeTreelin
306300
307301 rd := charset .ToUTF8WithFallbackReader (io .MultiReader (bytes .NewReader (buf ), dataRc ))
308302
309- if markupType := markup .Type (readmeFile .name ); markupType != "" {
303+ if markupType := markup .Type (readmeFile .Name () ); markupType != "" {
310304 ctx .Data ["IsMarkup" ] = true
311305 ctx .Data ["MarkupType" ] = markupType
312306
313307 ctx .Data ["EscapeStatus" ], ctx .Data ["FileContent" ], err = markupRender (ctx , & markup.RenderContext {
314308 Ctx : ctx ,
315- 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).
316- URLPrefix : path .Dir (readmeTreelink ),
309+ 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).
310+ URLPrefix : path .Join (readmeTreelink , subfolder ),
317311 Metas : ctx .Repo .Repository .ComposeDocumentMetas (),
318312 GitRepo : ctx .Repo .GitRepo ,
319313 }, rd )
320314 if err != nil {
321- log .Error ("Render failed for %s in %-v: %v Falling back to rendering source" , readmeFile .name , ctx .Repo .Repository , err )
315+ log .Error ("Render failed for %s in %-v: %v Falling back to rendering source" , readmeFile .Name () , ctx .Repo .Repository , err )
322316 buf := & bytes.Buffer {}
323317 ctx .Data ["EscapeStatus" ], _ = charset .EscapeControlStringReader (rd , buf , ctx .Locale )
324318 ctx .Data ["FileContent" ] = buf .String ()
0 commit comments