Add configurable allowed file types
This commit is contained in:
@@ -22,14 +22,15 @@ import (
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
DiskID string
|
||||
MountPath string
|
||||
MediaPath string
|
||||
DestFolder string // subfolder on disk, default "media"
|
||||
SourceRules []config.SourceFolder
|
||||
ReserveFreeGB float64
|
||||
OverwriteMode config.OverwriteMode
|
||||
FileSelectMode config.FileSelectMode
|
||||
DiskID string
|
||||
MountPath string
|
||||
MediaPath string
|
||||
DestFolder string // subfolder on disk, default "media"
|
||||
SourceRules []config.SourceFolder
|
||||
AllowedExtensions []string
|
||||
ReserveFreeGB float64
|
||||
OverwriteMode config.OverwriteMode
|
||||
FileSelectMode config.FileSelectMode
|
||||
}
|
||||
|
||||
type Copier struct {
|
||||
@@ -241,7 +242,7 @@ func (c *Copier) run(ctx context.Context, taskID string, opts Options, database
|
||||
if t, ok := c.tasks.Get(taskID); ok {
|
||||
_ = database.UpdateTask(*t)
|
||||
}
|
||||
files, err := buildFileList(opts.MediaPath, opts.SourceRules, copiedPaths)
|
||||
files, err := buildFileList(opts.MediaPath, opts.SourceRules, copiedPaths, opts.AllowedExtensions)
|
||||
if err != nil {
|
||||
fail(err)
|
||||
return
|
||||
@@ -358,10 +359,11 @@ type fileEntry struct {
|
||||
size int64
|
||||
}
|
||||
|
||||
func buildFileList(mediaPath string, rules []config.SourceFolder, skip map[string]struct{}) ([]fileEntry, error) {
|
||||
func buildFileList(mediaPath string, rules []config.SourceFolder, skip map[string]struct{}, allowedExtensions []string) ([]fileEntry, error) {
|
||||
_ = mediaPath
|
||||
roots, selectedRoots, ruleMap := normalizeSourceRules(rules)
|
||||
aliases := sourceAliases(roots)
|
||||
allowedExts := makeAllowedExtensionSet(allowedExtensions)
|
||||
|
||||
var result []fileEntry
|
||||
for _, src := range selectedRoots {
|
||||
@@ -398,6 +400,9 @@ func buildFileList(mediaPath string, rules []config.SourceFolder, skip map[strin
|
||||
if !isPathEnabled(path, ruleMap) {
|
||||
return nil
|
||||
}
|
||||
if !isExtensionAllowed(path, allowedExts) {
|
||||
return nil
|
||||
}
|
||||
rel, _ := filepath.Rel(root, path)
|
||||
rel = filepath.ToSlash(rel)
|
||||
destRel := filepath.ToSlash(filepath.Join(alias, rel))
|
||||
@@ -421,6 +426,27 @@ func buildFileList(mediaPath string, rules []config.SourceFolder, skip map[strin
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func makeAllowedExtensionSet(items []string) map[string]struct{} {
|
||||
normalized := config.NormalizeExtensions(items)
|
||||
if len(normalized) == 0 {
|
||||
normalized = config.DefaultAllowedExtensions()
|
||||
}
|
||||
result := make(map[string]struct{}, len(normalized))
|
||||
for _, item := range normalized {
|
||||
result[item] = struct{}{}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func isExtensionAllowed(path string, allowed map[string]struct{}) bool {
|
||||
ext := strings.ToLower(filepath.Ext(path))
|
||||
if ext == "" {
|
||||
return false
|
||||
}
|
||||
_, ok := allowed[ext]
|
||||
return ok
|
||||
}
|
||||
|
||||
func normalizeSourceRules(rules []config.SourceFolder) ([]string, []string, map[string]bool) {
|
||||
ruleMap := make(map[string]bool, len(rules))
|
||||
rootSet := make(map[string]struct{})
|
||||
|
||||
54
internal/copier/copier_test.go
Normal file
54
internal/copier/copier_test.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package copier
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"jukebox_maker/internal/config"
|
||||
)
|
||||
|
||||
func TestBuildFileListFiltersAllowedExtensions(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
source := filepath.Join(root, "music")
|
||||
if err := os.MkdirAll(filepath.Join(source, "nested"), 0o755); err != nil {
|
||||
t.Fatalf("MkdirAll() error = %v", err)
|
||||
}
|
||||
|
||||
files := map[string]string{
|
||||
filepath.Join(source, "track.mp3"): "audio",
|
||||
filepath.Join(source, "clip.mp4"): "video",
|
||||
filepath.Join(source, "cover.jpg"): "photo",
|
||||
filepath.Join(source, "nested", "note.txt"): "text",
|
||||
}
|
||||
for path, body := range files {
|
||||
if err := os.WriteFile(path, []byte(body), 0o644); err != nil {
|
||||
t.Fatalf("WriteFile(%q) error = %v", path, err)
|
||||
}
|
||||
}
|
||||
|
||||
items, err := buildFileList("", []config.SourceFolder{
|
||||
{Path: source, Enabled: true, Root: true},
|
||||
}, nil, config.DefaultAllowedExtensions())
|
||||
if err != nil {
|
||||
t.Fatalf("buildFileList() error = %v", err)
|
||||
}
|
||||
|
||||
if len(items) != 2 {
|
||||
t.Fatalf("buildFileList() len = %d, want 2", len(items))
|
||||
}
|
||||
|
||||
got := make(map[string]struct{}, len(items))
|
||||
for _, item := range items {
|
||||
got[filepath.Base(item.relPath)] = struct{}{}
|
||||
}
|
||||
if _, ok := got["track.mp3"]; !ok {
|
||||
t.Fatalf("missing mp3 file: %v", got)
|
||||
}
|
||||
if _, ok := got["clip.mp4"]; !ok {
|
||||
t.Fatalf("missing mp4 file: %v", got)
|
||||
}
|
||||
if _, ok := got["cover.jpg"]; ok {
|
||||
t.Fatalf("unexpected jpg file: %v", got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user