utils/convids/logic.go

179 lines
3.4 KiB
Go
Raw Normal View History

2024-10-23 21:24:10 -05:00
package convids
import (
2024-11-07 05:56:06 -06:00
"context"
2024-11-04 15:50:34 -06:00
"errors"
"fmt"
"io"
2024-10-23 21:24:10 -05:00
"os"
2024-11-07 05:56:06 -06:00
"os/exec"
2024-10-23 21:24:10 -05:00
fp "path/filepath"
"regexp"
"strings"
"gopkg.in/yaml.v3"
)
func NewData(path string) (*Data, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
ydec := yaml.NewDecoder(f)
var data Data
err = ydec.Decode(&data)
return &data, err
}
func ensureExtRe(c *Config) (err error) {
if c.extRe != nil {
return nil
}
c.extRe, err = regexp.Compile("(" + strings.Join(c.Extensions, "|") + ")$")
return
}
type ShowWalker func(show *Show, path string) error
type GroupPrinter func(name string, group Shows)
2024-11-07 05:56:06 -06:00
var ErrNoFiles = errors.New("no files processed")
var ErrSkipped = errors.New("skipped")
2024-11-16 23:38:44 -06:00
type processInput struct {
file os.DirEntry
source string
show *Show
extRe *regexp.Regexp
skips []string
walk ShowWalker
}
func processFile(input processInput) (processed bool, processError, cbError error) {
file := input.file
2024-11-07 05:56:06 -06:00
if file.IsDir() {
return
}
2024-11-16 23:38:44 -06:00
if !input.extRe.MatchString(file.Name()) {
2024-11-07 05:56:06 -06:00
return
}
2024-11-16 23:38:44 -06:00
show := input.show
2024-11-07 05:56:06 -06:00
var found bool
found, processError = show.Match(file.Name())
if processError != nil || !found {
return
}
2024-11-16 23:38:44 -06:00
path := fp.Join(input.source, file.Name())
for _, ext := range input.skips {
2024-11-07 05:56:06 -06:00
if !strings.HasPrefix(ext, ".") {
ext = "." + ext
}
skipper := path + ext
_, statErr := os.Stat(skipper)
if !errors.Is(statErr, os.ErrNotExist) {
return processed, ErrSkipped, cbError
}
}
2024-11-16 23:38:44 -06:00
cbError = input.walk(show, path)
2024-11-07 05:56:06 -06:00
if cbError == nil {
processed = true
}
return
}
2024-11-16 23:38:44 -06:00
type fileMap map[string][]os.DirEntry
func (fm fileMap) GetFiles(path string) []os.DirEntry {
files, ok := fm[path]
if ok {
return files
}
fm.ReadPath(path)
return fm[path]
}
func (fm fileMap) ReadPath(path string) {
if _, ok := fm[path]; ok {
return
}
fm[path], _ = os.ReadDir(path)
}
func WalkFiles(d *Data, stopOnError bool, gp GroupPrinter, cb ShowWalker) (err error) {
2024-10-23 21:24:10 -05:00
err = ensureExtRe(d.Config)
if err != nil {
return
}
if cb == nil {
cb = DryRun(os.Stdout)
}
2024-11-07 05:56:06 -06:00
count := 0
2024-11-16 23:38:44 -06:00
allFiles := fileMap{}
2024-10-23 21:24:10 -05:00
var files []os.DirEntry
2024-11-16 23:38:44 -06:00
2024-10-23 21:24:10 -05:00
if err != nil {
return
}
for s := range d.AllShows(gp) {
2024-11-16 23:38:44 -06:00
if len(s.Sources) == 0 {
s.Sources = []string{d.Config.Source}
}
showstart:
2024-11-16 23:38:44 -06:00
for _, source := range s.Sources {
files = allFiles.GetFiles(source)
for _, file := range files {
pIn := processInput{file, source, s, d.Config.extRe, d.Config.Skip, cb}
processed, processErr, cbErr := processFile(pIn)
if !processed && processErr == nil && cbErr == nil {
continue
}
if errors.Is(processErr, ErrSkipped) {
continue
}
if processErr != nil {
return processErr
}
if cbErr != nil && stopOnError {
return cbErr
}
if cbErr == nil && processed {
count++
}
if cbErr != nil {
err = cbErr
}
break showstart
2024-11-04 15:50:34 -06:00
}
2024-10-23 21:24:10 -05:00
}
}
2024-11-07 05:56:06 -06:00
if err == nil && count < 1 {
fmt.Println("Found nothing")
return ErrNoFiles
}
return
2024-10-23 21:24:10 -05:00
}
func DryRun(out io.Writer) ShowWalker {
return func(s *Show, path string) error {
fmt.Fprintf(out, "Saving %s to %s\n", path, s.Folder)
2024-11-07 05:56:06 -06:00
return ErrSkipped
}
}
func GetShow(ctx context.Context) ShowWalker {
return func(s *Show, path string) error {
cmd := exec.CommandContext(ctx, "get-shows", s.Folder, path)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}
}
func PrintGroupName(out io.Writer) GroupPrinter {
return func(name string, group Shows) {
fmt.Fprintf(out, "Checking %s shows\n\n", name)
}
}