Library indexing and filesystem scanner with incremental rescans

This commit is contained in:
2026-08-22 23:31:17 -05:00
parent d4ea7a4ca9
commit 49dbee617a
5 changed files with 915 additions and 0 deletions
+58
View File
@@ -0,0 +1,58 @@
package library
import (
"database/sql"
"strings"
"git.noroutes.net/NoRoutes/vibetunes/internal/database"
)
// DirEntry is one immediate child of a directory in filesystem-style
// browsing (Subsonic's getIndexes/getMusicDirectory): either a
// subdirectory (Dir=true) or a media file.
type DirEntry struct {
Name string
Dir bool
File *database.MediaFile // set when Dir is false
}
// ListDirectory returns the immediate children of subPath within a music
// folder ("" for the folder root), built from media_files.relative_path.
// This is the foundation for filesystem-style browsing, kept separate
// from the ID3/tag model in library/index.go so neither is faked in
// terms of the other.
func ListDirectory(db *sql.DB, folderID, subPath string) ([]DirEntry, error) {
files, err := database.ListMediaFilesForFolder(db, folderID)
if err != nil {
return nil, err
}
prefix := strings.Trim(subPath, "/")
seen := make(map[string]bool)
var out []DirEntry
for _, f := range files {
if f.Missing {
continue
}
rel := f.RelativePath
if prefix != "" {
if !strings.HasPrefix(rel, prefix+"/") {
continue
}
rel = rel[len(prefix)+1:]
}
parts := strings.SplitN(rel, "/", 2)
name := parts[0]
if name == "" || seen[name] {
continue
}
if len(parts) == 2 {
seen[name] = true
out = append(out, DirEntry{Name: name, Dir: true})
continue
}
seen[name] = true
out = append(out, DirEntry{Name: name, Dir: false, File: f})
}
return out, nil
}