Compare commits

...

5 commits

8 changed files with 211 additions and 78 deletions

View file

@ -7,7 +7,11 @@ import (
"syscall" "syscall"
) )
func SelfCancelingCotext(ctx context.Context) (context.Context, context.CancelFunc) { func SelfCancelingContextFromBackground() (context.Context, context.CancelFunc) {
return SelfCancelingContext(context.Background())
}
func SelfCancelingContext(ctx context.Context) (context.Context, context.CancelFunc) {
c, done := context.WithCancel(ctx) c, done := context.WithCancel(ctx)
ch := make(chan os.Signal, 1) ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)

View file

@ -1,67 +1,24 @@
package main package main
import ( import (
"context"
"fmt" "fmt"
"os" "os"
"codeberg.org/danjones000/utils/chill"
c "codeberg.org/danjones000/utils/cli/context" c "codeberg.org/danjones000/utils/cli/context"
e "codeberg.org/danjones000/utils/cli/err" e "codeberg.org/danjones000/utils/cli/err"
"codeberg.org/danjones000/utils/cli/spin" ccli "codeberg.org/danjones000/utils/internal/cli/convids"
"codeberg.org/danjones000/utils/convids"
"github.com/spf13/pflag"
) )
const dataPath = "shows.yml" const dataPath = "shows.yml"
func main() { func main() {
loop := pflag.BoolP("loop", "l", false, "Loop") ctx, done := c.SelfCancelingContextFromBackground()
help := pflag.BoolP("help", "h", false, "Get Help")
dryRun := pflag.BoolP("dry-run", "d", false, "Do a dry run")
pflag.Parse()
if *help {
pflag.Usage()
os.Exit(2)
}
ctx, done := c.SelfCancelingCotext(context.Background())
defer done() defer done()
var walker convids.ShowWalker app, err := ccli.NewApp(ctx, os.Args[0], os.Args[1:], dataPath, os.Stdout, os.Stdin, os.Stderr)
if *dryRun {
*loop = false
walker = convids.DryRun(os.Stdout)
} else {
gs := convids.GetShow(ctx)
walker = func(s *convids.Show, path string) error {
ct := chill.Chill(ctx)
msg := fmt.Sprintf("Waiting for CPU to cool, for %s", path)
sp := spin.Spin(ct, msg)
err := sp.Wait()
if err != nil {
return err
}
return gs(s, path)
}
}
data, err := convids.NewData(dataPath)
e.HandleErr(err) e.HandleErr(err)
groupPrinter := convids.PrintGroupName(os.Stdout) err = app.Run(ctx)
if *loop {
fmt.Println("looping")
for err == nil {
err = convids.WalkFiles(data, false, groupPrinter, walker)
fmt.Println(err)
}
} else {
err = convids.WalkFiles(data, false, groupPrinter, walker)
}
e.HandleErr(err) e.HandleErr(err)
fmt.Println("Done!") fmt.Println("Done!")

View file

@ -10,7 +10,7 @@ import (
) )
func main() { func main() {
ctx, done := c.SelfCancelingCotext(context.Background()) ctx, done := c.SelfCancelingContext(context.Background())
defer done() defer done()
ctx = chill.Chill(ctx) ctx = chill.Chill(ctx)
s := spin.Spin(ctx, "Waiting for CPU to cool...") s := spin.Spin(ctx, "Waiting for CPU to cool...")

View file

@ -39,21 +39,32 @@ type GroupPrinter func(name string, group Shows)
var ErrNoFiles = errors.New("no files processed") var ErrNoFiles = errors.New("no files processed")
var ErrSkipped = errors.New("skipped") var ErrSkipped = errors.New("skipped")
func processFile(conf *Config, walk ShowWalker, show *Show, file os.DirEntry) (processed bool, processError, cbError error) { 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() { if file.IsDir() {
return return
} }
if !conf.extRe.MatchString(file.Name()) { if !input.extRe.MatchString(file.Name()) {
return return
} }
show := input.show
var found bool var found bool
found, processError = show.Match(file.Name()) found, processError = show.Match(file.Name())
if processError != nil || !found { if processError != nil || !found {
return return
} }
path := fp.Join(conf.Source, file.Name()) path := fp.Join(input.source, file.Name())
for _, ext := range conf.Skip { for _, ext := range input.skips {
if !strings.HasPrefix(ext, ".") { if !strings.HasPrefix(ext, ".") {
ext = "." + ext ext = "." + ext
} }
@ -64,13 +75,31 @@ func processFile(conf *Config, walk ShowWalker, show *Show, file os.DirEntry) (p
} }
} }
cbError = walk(show, path) cbError = input.walk(show, path)
if cbError == nil { if cbError == nil {
processed = true processed = true
} }
return 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) { func WalkFiles(d *Data, stopOnError bool, gp GroupPrinter, cb ShowWalker) (err error) {
err = ensureExtRe(d.Config) err = ensureExtRe(d.Config)
if err != nil { if err != nil {
@ -80,14 +109,22 @@ func WalkFiles(d *Data, stopOnError bool, gp GroupPrinter, cb ShowWalker) (err e
cb = DryRun(os.Stdout) cb = DryRun(os.Stdout)
} }
count := 0 count := 0
allFiles := fileMap{}
var files []os.DirEntry var files []os.DirEntry
files, err = os.ReadDir(d.Config.Source)
if err != nil { if err != nil {
return return
} }
for s := range d.AllShows(gp) { 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 { for _, file := range files {
processed, processErr, cbErr := processFile(d.Config, cb, s, file) pIn := processInput{file, source, s, d.Config.extRe, d.Config.Skip, cb}
processed, processErr, cbErr := processFile(pIn)
if !processed && processErr == nil && cbErr == nil { if !processed && processErr == nil && cbErr == nil {
continue continue
} }
@ -106,7 +143,8 @@ func WalkFiles(d *Data, stopOnError bool, gp GroupPrinter, cb ShowWalker) (err e
if cbErr != nil { if cbErr != nil {
err = cbErr err = cbErr
} }
break break showstart
}
} }
} }
if err == nil && count < 1 { if err == nil && count < 1 {
@ -124,13 +162,18 @@ func DryRun(out io.Writer) ShowWalker {
} }
func GetShow(ctx context.Context) ShowWalker { func GetShow(ctx context.Context) ShowWalker {
return GetShowWithIO(ctx, os.Stdin, os.Stdout, os.Stderr)
}
func GetShowWithIO(ctx context.Context, stdin io.Reader, stdout io.Writer, stderr io.Writer) ShowWalker {
return func(s *Show, path string) error { return func(s *Show, path string) error {
cmd := exec.CommandContext(ctx, "get-shows", s.Folder, path) cmd := exec.CommandContext(ctx, "get-shows", s.Folder, path)
cmd.Stdin = os.Stdin cmd.Stdin = stdin
cmd.Stdout = os.Stdout cmd.Stdout = stdout
cmd.Stderr = os.Stderr cmd.Stderr = stderr
return cmd.Run() return cmd.Run()
} }
} }
func PrintGroupName(out io.Writer) GroupPrinter { func PrintGroupName(out io.Writer) GroupPrinter {

View file

@ -25,6 +25,7 @@ type Show struct {
Pattern string Pattern string
Name string Name string
Anime bool Anime bool
Sources []string
re *regexp.Regexp re *regexp.Regexp
} }

View file

@ -0,0 +1,60 @@
package convids
import (
"context"
"fmt"
"io"
conutils "codeberg.org/danjones000/utils/convids"
"github.com/spf13/pflag"
)
type App struct {
Name string
Data *conutils.Data
flags *pflag.FlagSet
stdout io.Writer
stderr io.Writer
stdin io.Reader
walker conutils.ShowWalker
groupPrinter conutils.GroupPrinter
}
func NewApp(ctx context.Context, name string, args []string, dataPath string, stdout io.Writer, stdin io.Reader, stderr io.Writer) (*App, error) {
a := App{Name: name, stdout: stdout, stdin: stdin, stderr: stderr}
var err error
a.flags, err = ParseFlags(name, args)
if err != nil {
return nil, err
}
a.walker = GetWalker(ctx, *DryRun, stdin, stdout, stderr)
a.Data, err = conutils.NewData(dataPath)
if err != nil {
return nil, err
}
a.groupPrinter = conutils.PrintGroupName(stdout)
return &a, nil
}
func (a *App) Run(ctx context.Context) error {
if *Loop {
return a.runInLoop(ctx)
}
return a.run(ctx)
}
func (a *App) run(ctx context.Context) error {
return conutils.WalkFiles(a.Data, false, a.groupPrinter, a.walker)
}
func (a *App) runInLoop(ctx context.Context) error {
fmt.Fprintln(a.stdout, "Looping")
var err error
for err == nil {
err = a.run(ctx)
fmt.Fprintln(a.stdout, err)
}
return err
}

View file

@ -0,0 +1,39 @@
package convids
import (
"fmt"
"github.com/spf13/pflag"
)
var Help *bool
var Loop *bool
var DryRun *bool
func GetFlags(name string) *pflag.FlagSet {
flags := pflag.NewFlagSet(name, pflag.ExitOnError)
Help = flags.BoolP("help", "h", false, "Get Help")
Loop = flags.BoolP("loop", "l", false, "Loop")
DryRun = flags.BoolP("dry-run", "d", false, "Do a dry run (won't loop)")
flags.Usage = func() {
fmt.Printf("Usage of %s:\n", name)
flags.PrintDefaults()
}
return flags
}
func ParseFlags(name string, args []string) (*pflag.FlagSet, error) {
flags := GetFlags(name)
err := flags.Parse(args)
if err != nil {
return nil, err
}
if *DryRun {
flags.Set("loop", "false")
}
return flags, nil
}

View file

@ -0,0 +1,29 @@
package convids
import (
"context"
"fmt"
"io"
"codeberg.org/danjones000/utils/chill"
"codeberg.org/danjones000/utils/cli/spin"
conutils "codeberg.org/danjones000/utils/convids"
)
func GetWalker(ctx context.Context, dryRun bool, in io.Reader, out, errOut io.Writer) conutils.ShowWalker {
if dryRun {
return conutils.DryRun(out)
}
gs := conutils.GetShowWithIO(ctx, in, out, errOut)
return func(s *conutils.Show, path string) error {
ct := chill.Chill(ctx)
msg := fmt.Sprintf("Waiting for CPU to cool, for %s", path)
sp := spin.Spin(ct, msg)
err := sp.Wait()
if err != nil {
return err
}
return gs(s, path)
}
}