178 lines
3.4 KiB
Go
178 lines
3.4 KiB
Go
package convids
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"os/exec"
|
|
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)
|
|
|
|
var ErrNoFiles = errors.New("no files processed")
|
|
var ErrSkipped = errors.New("skipped")
|
|
|
|
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
|
|
if file.IsDir() {
|
|
return
|
|
}
|
|
if !input.extRe.MatchString(file.Name()) {
|
|
return
|
|
}
|
|
show := input.show
|
|
var found bool
|
|
found, processError = show.Match(file.Name())
|
|
if processError != nil || !found {
|
|
return
|
|
}
|
|
|
|
path := fp.Join(input.source, file.Name())
|
|
for _, ext := range input.skips {
|
|
if !strings.HasPrefix(ext, ".") {
|
|
ext = "." + ext
|
|
}
|
|
skipper := path + ext
|
|
_, statErr := os.Stat(skipper)
|
|
if !errors.Is(statErr, os.ErrNotExist) {
|
|
return processed, ErrSkipped, cbError
|
|
}
|
|
}
|
|
|
|
cbError = input.walk(show, path)
|
|
if cbError == nil {
|
|
processed = true
|
|
}
|
|
return
|
|
}
|
|
|
|
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) {
|
|
err = ensureExtRe(d.Config)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if cb == nil {
|
|
cb = DryRun(os.Stdout)
|
|
}
|
|
count := 0
|
|
allFiles := fileMap{}
|
|
var files []os.DirEntry
|
|
|
|
if err != nil {
|
|
return
|
|
}
|
|
for s := range d.AllShows(gp) {
|
|
if len(s.Sources) == 0 {
|
|
s.Sources = []string{d.Config.Source}
|
|
}
|
|
showstart:
|
|
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
|
|
}
|
|
}
|
|
}
|
|
if err == nil && count < 1 {
|
|
fmt.Println("Found nothing")
|
|
return ErrNoFiles
|
|
}
|
|
return
|
|
}
|
|
|
|
func DryRun(out io.Writer) ShowWalker {
|
|
return func(s *Show, path string) error {
|
|
fmt.Fprintf(out, "Saving %s to %s\n", path, s.Folder)
|
|
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)
|
|
}
|
|
}
|