@@ -241,18 +241,19 @@ func findReadmeFile(ctx *context.Context, entries git.Entries, treeLink string)
241241 return readmeFile , readmeTreelink
242242}
243243
244- func renderReadmeFile (ctx * context.Context , readmeFile * namedBlob , readmeTreelink string ) {
245- ctx .Data ["RawFileLink" ] = ""
246- ctx .Data ["ReadmeInList" ] = true
247- ctx .Data ["ReadmeExist" ] = true
248- ctx .Data ["FileIsSymlink" ] = readmeFile .isSymlink
244+ type fileInfo struct {
245+ isTextFile bool
246+ isLFSFile bool
247+ fileSize int64
248+ lfsMeta * lfs.Pointer
249+ st typesniffer.SniffedType
250+ }
249251
250- dataRc , err := readmeFile .blob .DataAsync ()
252+ func getFileReader (repoID int64 , blob * git.Blob ) ([]byte , io.ReadCloser , * fileInfo , error ) {
253+ dataRc , err := blob .DataAsync ()
251254 if err != nil {
252- ctx .ServerError ("Data" , err )
253- return
255+ return nil , nil , nil , err
254256 }
255- defer dataRc .Close ()
256257
257258 buf := make ([]byte , 1024 )
258259 n , _ := util .ReadAtMost (dataRc , buf )
@@ -261,67 +262,75 @@ func renderReadmeFile(ctx *context.Context, readmeFile *namedBlob, readmeTreelin
261262 st := typesniffer .DetectContentType (buf )
262263 isTextFile := st .IsText ()
263264
264- ctx .Data ["FileIsText" ] = isTextFile
265- ctx .Data ["FileName" ] = readmeFile .name
266- fileSize := int64 (0 )
267- isLFSFile := false
268- ctx .Data ["IsLFSFile" ] = false
269-
270265 // FIXME: what happens when README file is an image?
271- if isTextFile && setting .LFS .StartServer {
272- pointer , _ := lfs .ReadPointerFromBuffer (buf )
273- if pointer .IsValid () {
274- meta , err := git_model .GetLFSMetaObjectByOid (ctx .Repo .Repository .ID , pointer .Oid )
275- if err != nil && err != git_model .ErrLFSObjectNotExist {
276- ctx .ServerError ("GetLFSMetaObject" , err )
277- return
278- }
279- if meta != nil {
280- ctx .Data ["IsLFSFile" ] = true
281- isLFSFile = true
266+ if ! isTextFile || ! setting .LFS .StartServer {
267+ return buf , dataRc , & fileInfo {isTextFile , false , blob .Size (), nil , st }, nil
268+ }
282269
283- // OK read the lfs object
284- var err error
285- dataRc , err = lfs .ReadMetaObject (pointer )
286- if err != nil {
287- ctx .ServerError ("ReadMetaObject" , err )
288- return
289- }
290- defer dataRc .Close ()
270+ pointer , _ := lfs .ReadPointerFromBuffer (buf )
271+ if ! pointer .IsValid () { // fallback to plain file
272+ return buf , dataRc , & fileInfo {isTextFile , false , blob .Size (), nil , st }, nil
273+ }
291274
292- buf = make ([]byte , 1024 )
293- n , err = util .ReadAtMost (dataRc , buf )
294- if err != nil {
295- ctx .ServerError ("Data" , err )
296- return
297- }
298- buf = buf [:n ]
275+ meta , err := git_model .GetLFSMetaObjectByOid (repoID , pointer .Oid )
276+ if err != git_model .ErrLFSObjectNotExist { // fallback to plain file
277+ return buf , dataRc , & fileInfo {isTextFile , false , blob .Size (), nil , st }, nil
278+ }
299279
300- st = typesniffer .DetectContentType (buf )
301- isTextFile = st .IsText ()
302- ctx .Data ["IsTextFile" ] = isTextFile
280+ dataRc .Close ()
281+ if err != nil {
282+ return nil , nil , nil , err
283+ }
303284
304- fileSize = meta .Size
305- ctx .Data ["FileSize" ] = meta .Size
306- filenameBase64 := base64 .RawURLEncoding .EncodeToString ([]byte (readmeFile .name ))
307- ctx .Data ["RawFileLink" ] = fmt .Sprintf ("%s.git/info/lfs/objects/%s/%s" , ctx .Repo .Repository .HTMLURL (), url .PathEscape (meta .Oid ), url .PathEscape (filenameBase64 ))
308- }
309- }
285+ dataRc , err = lfs .ReadMetaObject (pointer )
286+ if err != nil {
287+ return nil , nil , nil , err
310288 }
311289
312- if ! isTextFile {
290+ buf = make ([]byte , 1024 )
291+ n , err = util .ReadAtMost (dataRc , buf )
292+ if err != nil {
293+ dataRc .Close ()
294+ return nil , nil , nil , err
295+ }
296+ buf = buf [:n ]
297+
298+ st = typesniffer .DetectContentType (buf )
299+
300+ return buf , dataRc , & fileInfo {st .IsText (), true , meta .Size , & meta .Pointer , st }, nil
301+ }
302+
303+ func renderReadmeFile (ctx * context.Context , readmeFile * namedBlob , readmeTreelink string ) {
304+ ctx .Data ["RawFileLink" ] = ""
305+ ctx .Data ["ReadmeInList" ] = true
306+ ctx .Data ["ReadmeExist" ] = true
307+ ctx .Data ["FileIsSymlink" ] = readmeFile .isSymlink
308+
309+ buf , dataRc , fInfo , err := getFileReader (ctx .Repo .Repository .ID , readmeFile .blob )
310+ if err != nil {
311+ ctx .ServerError ("getFileReader" , err )
313312 return
314313 }
314+ defer dataRc .Close ()
315+
316+ ctx .Data ["FileIsText" ] = fInfo .isTextFile
317+ ctx .Data ["FileName" ] = readmeFile .name
318+ ctx .Data ["IsLFSFile" ] = fInfo .isLFSFile
319+
320+ if fInfo .isLFSFile {
321+ filenameBase64 := base64 .RawURLEncoding .EncodeToString ([]byte (readmeFile .name ))
322+ ctx .Data ["RawFileLink" ] = fmt .Sprintf ("%s.git/info/lfs/objects/%s/%s" , ctx .Repo .Repository .HTMLURL (), url .PathEscape (fInfo .lfsMeta .Oid ), url .PathEscape (filenameBase64 ))
323+ }
315324
316- if ! isLFSFile {
317- fileSize = readmeFile . blob . Size ()
325+ if ! fInfo . isTextFile {
326+ return
318327 }
319328
320- if fileSize >= setting .UI .MaxDisplayFileSize {
329+ if fInfo . fileSize >= setting .UI .MaxDisplayFileSize {
321330 // Pretend that this is a normal text file to display 'This file is too large to be shown'
322331 ctx .Data ["IsFileTooLarge" ] = true
323332 ctx .Data ["IsTextFile" ] = true
324- ctx .Data ["FileSize" ] = fileSize
333+ ctx .Data ["FileSize" ] = fInfo . fileSize
325334 return
326335 }
327336
@@ -362,16 +371,14 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
362371 ctx .Data ["IsViewFile" ] = true
363372 ctx .Data ["HideRepoInfo" ] = true
364373 blob := entry .Blob ()
365- dataRc , err := blob . DataAsync ( )
374+ buf , dataRc , fInfo , err := getFileReader ( ctx . Repo . Repository . ID , blob )
366375 if err != nil {
367- ctx .ServerError ("DataAsync " , err )
376+ ctx .ServerError ("getFileReader " , err )
368377 return
369378 }
370379 defer dataRc .Close ()
371380
372381 ctx .Data ["Title" ] = ctx .Tr ("repo.file.title" , ctx .Repo .Repository .Name + "/" + path .Base (ctx .Repo .TreePath ), ctx .Repo .RefName )
373-
374- fileSize := blob .Size ()
375382 ctx .Data ["FileIsSymlink" ] = entry .IsLink ()
376383 ctx .Data ["FileName" ] = blob .Name ()
377384 ctx .Data ["RawFileLink" ] = rawLink + "/" + util .PathEscapeSegments (ctx .Repo .TreePath )
@@ -381,69 +388,27 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
381388 ctx .Data ["FileError" ] = editorconfigErr
382389 }
383390
384- buf := make ([]byte , 1024 )
385- n , _ := util .ReadAtMost (dataRc , buf )
386- buf = buf [:n ]
387-
388- st := typesniffer .DetectContentType (buf )
389- isTextFile := st .IsText ()
390-
391- isLFSFile := false
392391 isDisplayingSource := ctx .FormString ("display" ) == "source"
393392 isDisplayingRendered := ! isDisplayingSource
394393
395- // Check for LFS meta file
396- if isTextFile && setting .LFS .StartServer {
397- pointer , _ := lfs .ReadPointerFromBuffer (buf )
398- if pointer .IsValid () {
399- meta , err := git_model .GetLFSMetaObjectByOid (ctx .Repo .Repository .ID , pointer .Oid )
400- if err != nil && err != git_model .ErrLFSObjectNotExist {
401- ctx .ServerError ("GetLFSMetaObject" , err )
402- return
403- }
404- if meta != nil {
405- isLFSFile = true
406-
407- // OK read the lfs object
408- var err error
409- dataRc , err = lfs .ReadMetaObject (pointer )
410- if err != nil {
411- ctx .ServerError ("ReadMetaObject" , err )
412- return
413- }
414- defer dataRc .Close ()
415-
416- buf = make ([]byte , 1024 )
417- n , err = util .ReadAtMost (dataRc , buf )
418- if err != nil {
419- ctx .ServerError ("Data" , err )
420- return
421- }
422- buf = buf [:n ]
423-
424- st = typesniffer .DetectContentType (buf )
425- isTextFile = st .IsText ()
426-
427- fileSize = meta .Size
428- ctx .Data ["RawFileLink" ] = ctx .Repo .RepoLink + "/media/" + ctx .Repo .BranchNameSubURL () + "/" + util .PathEscapeSegments (ctx .Repo .TreePath )
429- }
430- }
394+ if fInfo .isLFSFile {
395+ ctx .Data ["RawFileLink" ] = ctx .Repo .RepoLink + "/media/" + ctx .Repo .BranchNameSubURL () + "/" + util .PathEscapeSegments (ctx .Repo .TreePath )
431396 }
432397
433- isRepresentableAsText := st .IsRepresentableAsText ()
398+ isRepresentableAsText := fInfo . st .IsRepresentableAsText ()
434399 if ! isRepresentableAsText {
435400 // If we can't show plain text, always try to render.
436401 isDisplayingSource = false
437402 isDisplayingRendered = true
438403 }
439- ctx .Data ["IsLFSFile" ] = isLFSFile
440- ctx .Data ["FileSize" ] = fileSize
441- ctx .Data ["IsTextFile" ] = isTextFile
404+ ctx .Data ["IsLFSFile" ] = fInfo . isLFSFile
405+ ctx .Data ["FileSize" ] = fInfo . fileSize
406+ ctx .Data ["IsTextFile" ] = fInfo . isTextFile
442407 ctx .Data ["IsRepresentableAsText" ] = isRepresentableAsText
443408 ctx .Data ["IsDisplayingSource" ] = isDisplayingSource
444409 ctx .Data ["IsDisplayingRendered" ] = isDisplayingRendered
445410
446- isTextSource := isTextFile || isDisplayingSource
411+ isTextSource := fInfo . isTextFile || isDisplayingSource
447412 ctx .Data ["IsTextSource" ] = isTextSource
448413 if isTextSource {
449414 ctx .Data ["CanCopyContent" ] = true
@@ -468,21 +433,21 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
468433 }
469434
470435 // Assume file is not editable first.
471- if isLFSFile {
436+ if fInfo . isLFSFile {
472437 ctx .Data ["EditFileTooltip" ] = ctx .Tr ("repo.editor.cannot_edit_lfs_files" )
473438 } else if ! isRepresentableAsText {
474439 ctx .Data ["EditFileTooltip" ] = ctx .Tr ("repo.editor.cannot_edit_non_text_files" )
475440 }
476441
477442 switch {
478443 case isRepresentableAsText :
479- if st .IsSvgImage () {
444+ if fInfo . st .IsSvgImage () {
480445 ctx .Data ["IsImageFile" ] = true
481446 ctx .Data ["CanCopyContent" ] = true
482447 ctx .Data ["HasSourceRenderedToggle" ] = true
483448 }
484449
485- if fileSize >= setting .UI .MaxDisplayFileSize {
450+ if fInfo . fileSize >= setting .UI .MaxDisplayFileSize {
486451 ctx .Data ["IsFileTooLarge" ] = true
487452 break
488453 }
@@ -589,7 +554,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
589554 ctx .Data ["FileContent" ] = fileContent
590555 ctx .Data ["LineEscapeStatus" ] = statuses
591556 }
592- if ! isLFSFile {
557+ if ! fInfo . isLFSFile {
593558 if ctx .Repo .CanEnableEditor (ctx .Doer ) {
594559 if lfsLock != nil && lfsLock .OwnerID != ctx .Doer .ID {
595560 ctx .Data ["CanEditFile" ] = false
@@ -605,17 +570,17 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
605570 }
606571 }
607572
608- case st .IsPDF ():
573+ case fInfo . st .IsPDF ():
609574 ctx .Data ["IsPDFFile" ] = true
610- case st .IsVideo ():
575+ case fInfo . st .IsVideo ():
611576 ctx .Data ["IsVideoFile" ] = true
612- case st .IsAudio ():
577+ case fInfo . st .IsAudio ():
613578 ctx .Data ["IsAudioFile" ] = true
614- case st .IsImage () && (setting .UI .SVG .Enabled || ! st .IsSvgImage ()):
579+ case fInfo . st .IsImage () && (setting .UI .SVG .Enabled || ! fInfo . st .IsSvgImage ()):
615580 ctx .Data ["IsImageFile" ] = true
616581 ctx .Data ["CanCopyContent" ] = true
617582 default :
618- if fileSize >= setting .UI .MaxDisplayFileSize {
583+ if fInfo . fileSize >= setting .UI .MaxDisplayFileSize {
619584 ctx .Data ["IsFileTooLarge" ] = true
620585 break
621586 }
0 commit comments