11package filesystem
22
33import (
4+ "context"
45 "fmt"
56 "io"
67 "os"
@@ -13,8 +14,7 @@ import (
1314 "time"
1415
1516 "emperror.dev/errors"
16- "github.com/apex/log"
17- "github.com/gabriel-vasile/mimetype"
17+ // "github.com/apex/log" // Was only used for the listDirectory function for Mimetype which has now been removed for performance.
1818 ignore "github.com/sabhiram/go-gitignore"
1919
2020 "github.com/pyrohost/elytra/src/config"
@@ -429,64 +429,81 @@ func (fs *Filesystem) ListDirectory(p string) ([]Stat, error) {
429429 return Stat {}, err
430430 }
431431
432- var d string
432+ mt := "application/octet-stream"
433433 if e .Type ().IsDir () {
434- d = "inode/directory"
435- } else {
436- d = "application/octet-stream"
434+ mt = "inode/directory"
437435 }
438- var m * mimetype.MIME
439- if e .Type ().IsRegular () {
440- // TODO: I should probably find a better way to do this.
441- eO := e .(interface {
442- Open () (ufs.File , error )
443- })
444- f , err := eO .Open ()
445- if err != nil {
446- return Stat {}, err
447- }
448- m , err = mimetype .DetectReader (f )
449- if err != nil {
450- log .Error (err .Error ())
451- }
452- _ = f .Close ()
453- }
454-
455- st := Stat {FileInfo : info , Mimetype : d }
456- if m != nil {
457- st .Mimetype = m .String ()
458- }
459- return st , nil
436+ return Stat {FileInfo : info , Mimetype : mt }, nil
460437 })
461438 if err != nil {
462439 return nil , err
463440 }
464441
465- // Sort entries alphabetically.
466- slices .SortStableFunc (out , func (a , b Stat ) int {
467- switch {
468- case a .Name () == b . Name ():
469- return 0
470- case a . Name () > b . Name ():
442+ // Sort: dirs first, then name
443+ slices .SortFunc (out , func (a , b Stat ) int {
444+ if a . IsDir () != b . IsDir () {
445+ if a .IsDir () {
446+ return - 1
447+ }
471448 return 1
472- default :
473- return - 1
474449 }
450+ return strings .Compare (a .Name (), b .Name ())
475451 })
452+ return out , nil
453+ }
476454
477- // Sort folders before other file types.
478- slices .SortStableFunc (out , func (a , b Stat ) int {
479- switch {
480- case a .IsDir () && b .IsDir ():
481- return 0
482- case a .IsDir ():
483- return - 1
484- default :
455+ func (fs * Filesystem ) ListDirectoryPaged (ctx context.Context , p string , offset , limit int ) ([]Stat , int , error ) {
456+ if offset < 0 {
457+ offset = 0
458+ }
459+
460+ if limit <= 0 {
461+ return []Stat {}, 0 , nil
462+ }
463+
464+ entries , err := fs .unixFS .ReadDir (p )
465+ if err != nil {
466+ return nil , 0 , err
467+ }
468+ total := len (entries )
469+ if offset >= total {
470+ return []Stat {}, total , nil
471+ }
472+
473+ // Sort dirs first, then name
474+ slices .SortFunc (entries , func (a , b ufs.DirEntry ) int {
475+ if a .Type ().IsDir () != b .Type ().IsDir () {
476+ if a .Type ().IsDir () {
477+ return - 1
478+ }
485479 return 1
486480 }
481+ return strings .Compare (a .Name (), b .Name ())
487482 })
488483
489- return out , nil
484+ end := offset + limit
485+ if end > total {
486+ end = total
487+ }
488+
489+ out := make ([]Stat , 0 , end - offset )
490+ for _ , e := range entries [offset :end ] {
491+ select {
492+ case <- ctx .Done ():
493+ return nil , 0 , ctx .Err ()
494+ default :
495+ }
496+ info , err := e .Info ()
497+ if err != nil {
498+ return nil , 0 , err
499+ }
500+ mt := "application/octet-stream"
501+ if e .Type ().IsDir () {
502+ mt = "inode/directory"
503+ }
504+ out = append (out , Stat {FileInfo : info , Mimetype : mt })
505+ }
506+ return out , total , nil
490507}
491508
492509func (fs * Filesystem ) Chtimes (path string , atime , mtime time.Time ) error {
0 commit comments