Skip to content

Commit 2041ab5

Browse files
committed
Refactor readme file renderer
1 parent 6cc8aed commit 2041ab5

File tree

1 file changed

+130
-112
lines changed

1 file changed

+130
-112
lines changed

routers/web/repo/view.go

Lines changed: 130 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,30 @@ func renderDirectory(ctx *context.Context, treeLink string) {
142142
return
143143
}
144144

145+
renderDirectoryDefaultFile(ctx, entries, treeLink)
146+
}
147+
148+
// renderDirectoryDefaultFile render the default file when render a root directory or a sub directory
149+
func renderDirectoryDefaultFile(ctx *context.Context, entries git.Entries, treeLink string) {
145150
if ctx.Repo.TreePath != "" {
146151
ctx.Data["Title"] = ctx.Tr("repo.file.title", ctx.Repo.Repository.Name+"/"+path.Base(ctx.Repo.TreePath), ctx.Repo.RefName)
147152
}
148153

154+
// Check permission to add or upload new file.
155+
if ctx.Repo.CanWrite(unit_model.TypeCode) && ctx.Repo.IsViewBranch {
156+
ctx.Data["CanAddFile"] = !ctx.Repo.Repository.IsArchived
157+
ctx.Data["CanUploadFile"] = setting.Repository.Upload.Enabled && !ctx.Repo.Repository.IsArchived
158+
}
159+
160+
readmeFile, readmeTreelink := findReadmeFile(ctx, entries, treeLink)
161+
if ctx.Written() || readmeFile == nil {
162+
return
163+
}
164+
165+
renderReadmeFile(ctx, readmeFile, readmeTreelink)
166+
}
167+
168+
func findReadmeFile(ctx *context.Context, entries git.Entries, treeLink string) (*namedBlob, string) {
149169
// 3 for the extensions in exts[] in order
150170
// the last one is for a readme that doesn't
151171
// strictly match an extension
@@ -183,7 +203,7 @@ func renderDirectory(ctx *context.Context, treeLink string) {
183203
target, err = entry.FollowLinks()
184204
if err != nil && !git.IsErrBadLink(err) {
185205
ctx.ServerError("FollowLinks", err)
186-
return
206+
return nil, ""
187207
}
188208
}
189209
log.Debug("%t", target == nil)
@@ -205,7 +225,7 @@ func renderDirectory(ctx *context.Context, treeLink string) {
205225
entry, err = entry.FollowLinks()
206226
if err != nil && !git.IsErrBadLink(err) {
207227
ctx.ServerError("FollowLinks", err)
208-
return
228+
return nil, ""
209229
}
210230
}
211231
if entry != nil && (entry.IsExecutable() || entry.IsRegular()) {
@@ -236,7 +256,7 @@ func renderDirectory(ctx *context.Context, treeLink string) {
236256
readmeFile, err = getReadmeFileFromPath(ctx.Repo.Commit, entry.GetSubJumpablePathName())
237257
if err != nil {
238258
ctx.ServerError("getReadmeFileFromPath", err)
239-
return
259+
return nil, ""
240260
}
241261
if readmeFile != nil {
242262
readmeFile.name = entry.Name() + "/" + readmeFile.name
@@ -245,129 +265,127 @@ func renderDirectory(ctx *context.Context, treeLink string) {
245265
}
246266
}
247267
}
268+
return readmeFile, readmeTreelink
269+
}
248270

249-
if readmeFile != nil {
250-
ctx.Data["RawFileLink"] = ""
251-
ctx.Data["ReadmeInList"] = true
252-
ctx.Data["ReadmeExist"] = true
253-
ctx.Data["FileIsSymlink"] = readmeFile.isSymlink
271+
func renderReadmeFile(ctx *context.Context, readmeFile *namedBlob, readmeTreelink string) {
272+
ctx.Data["RawFileLink"] = ""
273+
ctx.Data["ReadmeInList"] = true
274+
ctx.Data["ReadmeExist"] = true
275+
ctx.Data["FileIsSymlink"] = readmeFile.isSymlink
254276

255-
dataRc, err := readmeFile.blob.DataAsync()
256-
if err != nil {
257-
ctx.ServerError("Data", err)
258-
return
259-
}
260-
defer dataRc.Close()
261-
262-
buf := make([]byte, 1024)
263-
n, _ := util.ReadAtMost(dataRc, buf)
264-
buf = buf[:n]
265-
266-
st := typesniffer.DetectContentType(buf)
267-
isTextFile := st.IsText()
268-
269-
ctx.Data["FileIsText"] = isTextFile
270-
ctx.Data["FileName"] = readmeFile.name
271-
fileSize := int64(0)
272-
isLFSFile := false
273-
ctx.Data["IsLFSFile"] = false
274-
275-
// FIXME: what happens when README file is an image?
276-
if isTextFile && setting.LFS.StartServer {
277-
pointer, _ := lfs.ReadPointerFromBuffer(buf)
278-
if pointer.IsValid() {
279-
meta, err := models.GetLFSMetaObjectByOid(ctx.Repo.Repository.ID, pointer.Oid)
280-
if err != nil && err != models.ErrLFSObjectNotExist {
281-
ctx.ServerError("GetLFSMetaObject", err)
282-
return
283-
}
284-
if meta != nil {
285-
ctx.Data["IsLFSFile"] = true
286-
isLFSFile = true
277+
dataRc, err := readmeFile.blob.DataAsync()
278+
if err != nil {
279+
ctx.ServerError("Data", err)
280+
return
281+
}
282+
defer dataRc.Close()
287283

288-
// OK read the lfs object
289-
var err error
290-
dataRc, err = lfs.ReadMetaObject(pointer)
291-
if err != nil {
292-
ctx.ServerError("ReadMetaObject", err)
293-
return
294-
}
295-
defer dataRc.Close()
284+
buf := make([]byte, 1024)
285+
n, _ := util.ReadAtMost(dataRc, buf)
286+
buf = buf[:n]
296287

297-
buf = make([]byte, 1024)
298-
n, err = util.ReadAtMost(dataRc, buf)
299-
if err != nil {
300-
ctx.ServerError("Data", err)
301-
return
302-
}
303-
buf = buf[:n]
288+
st := typesniffer.DetectContentType(buf)
289+
isTextFile := st.IsText()
304290

305-
st = typesniffer.DetectContentType(buf)
306-
isTextFile = st.IsText()
307-
ctx.Data["IsTextFile"] = isTextFile
291+
ctx.Data["FileIsText"] = isTextFile
292+
ctx.Data["FileName"] = readmeFile.name
293+
fileSize := int64(0)
294+
isLFSFile := false
295+
ctx.Data["IsLFSFile"] = false
308296

309-
fileSize = meta.Size
310-
ctx.Data["FileSize"] = meta.Size
311-
filenameBase64 := base64.RawURLEncoding.EncodeToString([]byte(readmeFile.name))
312-
ctx.Data["RawFileLink"] = fmt.Sprintf("%s.git/info/lfs/objects/%s/%s", ctx.Repo.Repository.HTMLURL(), url.PathEscape(meta.Oid), url.PathEscape(filenameBase64))
313-
}
297+
// FIXME: what happens when README file is an image?
298+
if isTextFile && setting.LFS.StartServer {
299+
pointer, _ := lfs.ReadPointerFromBuffer(buf)
300+
if pointer.IsValid() {
301+
meta, err := models.GetLFSMetaObjectByOid(ctx.Repo.Repository.ID, pointer.Oid)
302+
if err != nil && err != models.ErrLFSObjectNotExist {
303+
ctx.ServerError("GetLFSMetaObject", err)
304+
return
314305
}
315-
}
316-
317-
if !isLFSFile {
318-
fileSize = readmeFile.blob.Size()
319-
}
306+
if meta != nil {
307+
ctx.Data["IsLFSFile"] = true
308+
isLFSFile = true
320309

321-
if isTextFile {
322-
if fileSize >= setting.UI.MaxDisplayFileSize {
323-
// Pretend that this is a normal text file to display 'This file is too large to be shown'
324-
ctx.Data["IsFileTooLarge"] = true
325-
ctx.Data["IsTextFile"] = true
326-
ctx.Data["FileSize"] = fileSize
327-
} else {
328-
rd := charset.ToUTF8WithFallbackReader(io.MultiReader(bytes.NewReader(buf), dataRc))
329-
330-
if markupType := markup.Type(readmeFile.name); markupType != "" {
331-
ctx.Data["IsMarkup"] = true
332-
ctx.Data["MarkupType"] = string(markupType)
333-
var result strings.Builder
334-
err := markup.Render(&markup.RenderContext{
335-
Ctx: ctx,
336-
Filename: readmeFile.name,
337-
URLPrefix: readmeTreelink,
338-
Metas: ctx.Repo.Repository.ComposeDocumentMetas(),
339-
GitRepo: ctx.Repo.GitRepo,
340-
}, rd, &result)
341-
if err != nil {
342-
log.Error("Render failed: %v then fallback", err)
343-
buf := &bytes.Buffer{}
344-
ctx.Data["EscapeStatus"], _ = charset.EscapeControlReader(rd, buf)
345-
ctx.Data["FileContent"] = strings.ReplaceAll(
346-
gotemplate.HTMLEscapeString(buf.String()), "\n", `<br>`,
347-
)
348-
} else {
349-
ctx.Data["EscapeStatus"], ctx.Data["FileContent"] = charset.EscapeControlString(result.String())
350-
}
351-
} else {
352-
ctx.Data["IsRenderedHTML"] = true
353-
buf := &bytes.Buffer{}
354-
ctx.Data["EscapeStatus"], err = charset.EscapeControlReader(rd, buf)
355-
if err != nil {
356-
log.Error("Read failed: %v", err)
357-
}
310+
// OK read the lfs object
311+
var err error
312+
dataRc, err = lfs.ReadMetaObject(pointer)
313+
if err != nil {
314+
ctx.ServerError("ReadMetaObject", err)
315+
return
316+
}
317+
defer dataRc.Close()
358318

359-
ctx.Data["FileContent"] = strings.ReplaceAll(
360-
gotemplate.HTMLEscapeString(buf.String()), "\n", `<br>`,
361-
)
319+
buf = make([]byte, 1024)
320+
n, err = util.ReadAtMost(dataRc, buf)
321+
if err != nil {
322+
ctx.ServerError("Data", err)
323+
return
362324
}
325+
buf = buf[:n]
326+
327+
st = typesniffer.DetectContentType(buf)
328+
isTextFile = st.IsText()
329+
ctx.Data["IsTextFile"] = isTextFile
330+
331+
fileSize = meta.Size
332+
ctx.Data["FileSize"] = meta.Size
333+
filenameBase64 := base64.RawURLEncoding.EncodeToString([]byte(readmeFile.name))
334+
ctx.Data["RawFileLink"] = fmt.Sprintf("%s.git/info/lfs/objects/%s/%s", ctx.Repo.Repository.HTMLURL(), url.PathEscape(meta.Oid), url.PathEscape(filenameBase64))
363335
}
364336
}
365337
}
366338

367-
// Check permission to add or upload new file.
368-
if ctx.Repo.CanWrite(unit_model.TypeCode) && ctx.Repo.IsViewBranch {
369-
ctx.Data["CanAddFile"] = !ctx.Repo.Repository.IsArchived
370-
ctx.Data["CanUploadFile"] = setting.Repository.Upload.Enabled && !ctx.Repo.Repository.IsArchived
339+
if !isTextFile {
340+
return
341+
}
342+
343+
if !isLFSFile {
344+
fileSize = readmeFile.blob.Size()
345+
}
346+
347+
if fileSize >= setting.UI.MaxDisplayFileSize {
348+
// Pretend that this is a normal text file to display 'This file is too large to be shown'
349+
ctx.Data["IsFileTooLarge"] = true
350+
ctx.Data["IsTextFile"] = true
351+
ctx.Data["FileSize"] = fileSize
352+
return
353+
}
354+
355+
rd := charset.ToUTF8WithFallbackReader(io.MultiReader(bytes.NewReader(buf), dataRc))
356+
357+
if markupType := markup.Type(readmeFile.name); markupType != "" {
358+
ctx.Data["IsMarkup"] = true
359+
ctx.Data["MarkupType"] = string(markupType)
360+
var result strings.Builder
361+
err := markup.Render(&markup.RenderContext{
362+
Ctx: ctx,
363+
Filename: readmeFile.name,
364+
URLPrefix: readmeTreelink,
365+
Metas: ctx.Repo.Repository.ComposeDocumentMetas(),
366+
GitRepo: ctx.Repo.GitRepo,
367+
}, rd, &result)
368+
if err != nil {
369+
log.Error("Render failed: %v then fallback", err)
370+
buf := &bytes.Buffer{}
371+
ctx.Data["EscapeStatus"], _ = charset.EscapeControlReader(rd, buf)
372+
ctx.Data["FileContent"] = strings.ReplaceAll(
373+
gotemplate.HTMLEscapeString(buf.String()), "\n", `<br>`,
374+
)
375+
} else {
376+
ctx.Data["EscapeStatus"], ctx.Data["FileContent"] = charset.EscapeControlString(result.String())
377+
}
378+
} else {
379+
ctx.Data["IsRenderedHTML"] = true
380+
buf := &bytes.Buffer{}
381+
ctx.Data["EscapeStatus"], err = charset.EscapeControlReader(rd, buf)
382+
if err != nil {
383+
log.Error("Read failed: %v", err)
384+
}
385+
386+
ctx.Data["FileContent"] = strings.ReplaceAll(
387+
gotemplate.HTMLEscapeString(buf.String()), "\n", `<br>`,
388+
)
371389
}
372390
}
373391

0 commit comments

Comments
 (0)