@@ -50,12 +50,6 @@ const (
50
50
tplMigrating base.TplName = "repo/migrate/migrating"
51
51
)
52
52
53
- type namedBlob struct {
54
- name string
55
- isSymlink bool
56
- blob * git.Blob
57
- }
58
-
59
53
// locate a README for a tree in one of the supported paths.
60
54
//
61
55
// entries is passed to reduce calls to ListEntries(), so
@@ -64,14 +58,14 @@ type namedBlob struct {
64
58
// entries == ctx.Repo.Commit.SubTree(ctx.Repo.TreePath).ListEntries()
65
59
//
66
60
// 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 ) {
68
62
// Create a list of extensions in priority order
69
63
// 1. Markdown files - with and without localisation - e.g. README.en-us.md or README.md
70
64
// 2. Txt files - e.g. README.txt
71
65
// 3. No extension - e.g. README
72
66
exts := append (localizedExtensions (".md" , ctx .Language ()), ".txt" , "" ) // sorted by priority
73
67
extCount := len (exts )
74
- readmeFiles := make ([]* namedBlob , extCount + 1 )
68
+ readmeFiles := make ([]* git. TreeEntry , extCount + 1 )
75
69
76
70
docsEntries := make ([]* git.TreeEntry , 3 ) // (one of docs/, .gitea/ or .github/)
77
71
for _ , entry := range entries {
@@ -98,28 +92,21 @@ func findReadmeFileInEntries(ctx *context.Context, entries []*git.TreeEntry) (*n
98
92
}
99
93
if i , ok := util .IsReadmeFileExtension (entry .Name (), exts ... ); ok {
100
94
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 ()
108
98
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
117
102
}
103
+ } else {
104
+ readmeFiles [i ] = entry
118
105
}
119
106
}
120
107
}
121
108
}
122
- var readmeFile * namedBlob
109
+ var readmeFile * git. TreeEntry
123
110
for _ , f := range readmeFiles {
124
111
if f != nil {
125
112
readmeFile = f
@@ -140,20 +127,20 @@ func findReadmeFileInEntries(ctx *context.Context, entries []*git.TreeEntry) (*n
140
127
var err error
141
128
childEntries , err := subTree .ListEntries ()
142
129
if err != nil {
143
- return nil , err
130
+ return "" , nil , err
144
131
}
145
- readmeFile , err = findReadmeFileInEntries (ctx , childEntries )
132
+
133
+ subfolder , readmeFile , err := findReadmeFileInEntries (ctx , childEntries )
146
134
if err != nil && ! git .IsErrNotExist (err ) {
147
- return nil , err
135
+ return "" , nil , err
148
136
}
149
137
if readmeFile != nil {
150
- readmeFile .name = subTreeEntry .Name () + "/" + readmeFile .name
151
- break
138
+ return path .Join (subTreeEntry .Name (), subfolder ), readmeFile , nil
152
139
}
153
140
}
154
141
}
155
142
156
- return readmeFile , nil
143
+ return "" , readmeFile , nil
157
144
}
158
145
159
146
func renderDirectory (ctx * context.Context , treeLink string ) {
@@ -177,16 +164,13 @@ func renderDirectory(ctx *context.Context, treeLink string) {
177
164
return
178
165
}
179
166
180
- readmeFile , err := findReadmeFileInEntries (ctx , entries )
167
+ subfolder , readmeFile , err := findReadmeFileInEntries (ctx , entries )
181
168
if err != nil {
182
169
ctx .ServerError ("findReadmeFileInEntries" , err )
183
170
return
184
171
}
185
- if readmeFile == nil {
186
- return
187
- }
188
172
189
- renderReadmeFile (ctx , readmeFile , fmt . Sprintf ( "%s/%s" , treeLink , readmeFile . name ) )
173
+ renderReadmeFile (ctx , subfolder , readmeFile , treeLink )
190
174
}
191
175
192
176
// 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
270
254
return buf , dataRc , & fileInfo {st .IsText (), true , meta .Size , & meta .Pointer , st }, nil
271
255
}
272
256
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
+
274
268
ctx .Data ["RawFileLink" ] = ""
275
269
ctx .Data ["ReadmeInList" ] = true
276
270
ctx .Data ["ReadmeExist" ] = true
277
- ctx .Data ["FileIsSymlink" ] = readmeFile .isSymlink
271
+ ctx .Data ["FileIsSymlink" ] = readmeFile .IsLink ()
278
272
279
- buf , dataRc , fInfo , err := getFileReader (ctx .Repo .Repository .ID , readmeFile . blob )
273
+ buf , dataRc , fInfo , err := getFileReader (ctx .Repo .Repository .ID , target . Blob () )
280
274
if err != nil {
281
275
ctx .ServerError ("getFileReader" , err )
282
276
return
283
277
}
284
278
defer dataRc .Close ()
285
279
286
280
ctx .Data ["FileIsText" ] = fInfo .isTextFile
287
- ctx .Data ["FileName" ] = readmeFile .name
281
+ ctx .Data ["FileName" ] = path . Join ( subfolder , readmeFile .Name ())
288
282
ctx .Data ["IsLFSFile" ] = fInfo .isLFSFile
289
283
290
284
if fInfo .isLFSFile {
291
- filenameBase64 := base64 .RawURLEncoding .EncodeToString ([]byte (readmeFile .name ))
285
+ filenameBase64 := base64 .RawURLEncoding .EncodeToString ([]byte (readmeFile .Name () ))
292
286
ctx .Data ["RawFileLink" ] = fmt .Sprintf ("%s.git/info/lfs/objects/%s/%s" , ctx .Repo .Repository .Link (), url .PathEscape (fInfo .lfsMeta .Oid ), url .PathEscape (filenameBase64 ))
293
287
}
294
288
@@ -306,19 +300,19 @@ func renderReadmeFile(ctx *context.Context, readmeFile *namedBlob, readmeTreelin
306
300
307
301
rd := charset .ToUTF8WithFallbackReader (io .MultiReader (bytes .NewReader (buf ), dataRc ))
308
302
309
- if markupType := markup .Type (readmeFile .name ); markupType != "" {
303
+ if markupType := markup .Type (readmeFile .Name () ); markupType != "" {
310
304
ctx .Data ["IsMarkup" ] = true
311
305
ctx .Data ["MarkupType" ] = markupType
312
306
313
307
ctx .Data ["EscapeStatus" ], ctx .Data ["FileContent" ], err = markupRender (ctx , & markup.RenderContext {
314
308
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 ),
317
311
Metas : ctx .Repo .Repository .ComposeDocumentMetas (),
318
312
GitRepo : ctx .Repo .GitRepo ,
319
313
}, rd )
320
314
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 )
322
316
buf := & bytes.Buffer {}
323
317
ctx .Data ["EscapeStatus" ], _ = charset .EscapeControlStringReader (rd , buf , ctx .Locale )
324
318
ctx .Data ["FileContent" ] = buf .String ()
0 commit comments