diff --git a/.golangci.yaml b/.golangci.yaml index 766ec2a..3f33683 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -1,7 +1,8 @@ +version: "2" + linters: enable: - errcheck - - gosimple - govet - ineffassign - staticcheck @@ -22,18 +23,17 @@ linters: - gosec - perfsprint - testifylint - -linters-settings: - testifylint: - enable-all: true - disable: - - require-error - gocognit: - min-complexity: 16 - gocyclo: - min-complexity: 15 - gocritic: - enable-all: true - settings: - hugeParam: - sizeThreshold: 255 + settings: + testifylint: + enable-all: true + disable: + - require-error + gocognit: + min-complexity: 16 + gocyclo: + min-complexity: 15 + gocritic: + enable-all: true + settings: + hugeParam: + sizeThreshold: 255 diff --git a/cmd/ic-merge/main.go b/cmd/ic-merge/main.go index 63563b2..477317c 100644 --- a/cmd/ic-merge/main.go +++ b/cmd/ic-merge/main.go @@ -16,6 +16,7 @@ func main() { m, err := ic.NewMerger(os.Args[1:]) e.HandleErr(err) + //nolint:errcheck // I don't care about this defer m.Close() err = m.ParseFiles() diff --git a/convids/logic.go b/convids/logic.go index 3786295..029e6df 100644 --- a/convids/logic.go +++ b/convids/logic.go @@ -1,6 +1,8 @@ package convids import ( + "bufio" + "cmp" "context" "errors" "fmt" @@ -16,7 +18,16 @@ import ( "gopkg.in/yaml.v3" ) +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") +var ErrMissingConfig = errors.New("missing config") +var ErrMissingShows = errors.New("missing shows") + func NewData(path string) (*Data, error) { + //nolint:gosec // I don't care if this is user input f, err := os.Open(path) if err != nil { return nil, err @@ -24,7 +35,17 @@ func NewData(path string) (*Data, error) { ydec := yaml.NewDecoder(f) var data Data err = ydec.Decode(&data) - return &data, err + if err != nil { + return nil, err + } + + if data.Config == nil { + return nil, ErrMissingConfig + } + if data.Shows == nil || len(*(data.Shows)) == 0 { + return nil, ErrMissingShows + } + return &data, nil } func ensureExtRe(c *Config) (err error) { @@ -35,12 +56,6 @@ func ensureExtRe(c *Config) (err error) { 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 @@ -152,8 +167,8 @@ func WalkFiles(d *Data, stopOnError bool, gp GroupPrinter, cb ShowWalker) (err e 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 + _, err := fmt.Fprintf(out, "Saving %s to %s\n", path, s.Folder) + return cmp.Or(err, ErrSkipped) } } @@ -163,18 +178,53 @@ func GetShow(ctx context.Context) ShowWalker { func GetShowWithIO(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer) ShowWalker { return func(s *Show, path string) error { - //nolint:gosec // I don't care if this is using user input - cmd := exec.CommandContext(ctx, "get-shows", s.Folder, path) - cmd.Stdin = stdin - cmd.Stdout = stdout - cmd.Stderr = stderr - return cmd.Run() - } + if !s.Url { + return runGetShowsCmd(ctx, s.Folder, path, stdin, stdout, stderr) + } + orig := path + //nolint:gosec // I don't care if this is user input + readFile, err := os.Open(orig) + if err != nil { + return err + } + //nolint:errcheck // I don't care + defer readFile.Close() + + fileScan := bufio.NewScanner(readFile) + fileScan.Split(bufio.ScanLines) + + for fileScan.Scan() { + path = fileScan.Text() + err := runGetShowsCmd(ctx, s.Folder, path, stdin, stdout, stderr) + if err != nil { + return err + } + } + + if s.Backup != "" { + err = os.Rename(orig, fp.Join(s.Backup, fp.Base(orig))) + if err != nil { + _, _ = fmt.Fprintf(stdout, "Moved %s to %s\n", orig, s.Backup) + } + } else { + err = os.Remove(orig) + } + return err + } +} + +func runGetShowsCmd(ctx context.Context, folder, path string, stdin io.Reader, stdout, stderr io.Writer) error { + //nolint:gosec // I don't care if this is using user input + cmd := exec.CommandContext(ctx, "get-shows", folder, path) + cmd.Stdin = stdin + cmd.Stdout = stdout + cmd.Stderr = 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) + _, _ = fmt.Fprintf(out, "Checking %s shows\n\n", name) } } diff --git a/convids/models.go b/convids/models.go index 58b8992..ce23ca8 100644 --- a/convids/models.go +++ b/convids/models.go @@ -25,6 +25,8 @@ type Show struct { Pattern string Name string Anime bool + Url bool + Backup string Sources []string re *regexp.Regexp diff --git a/infinitecraft/merger.go b/infinitecraft/merger.go index 36d2ef8..1ac8ca7 100644 --- a/infinitecraft/merger.go +++ b/infinitecraft/merger.go @@ -7,6 +7,7 @@ import ( "encoding/json" "errors" "os" + "slices" _ "github.com/glebarez/go-sqlite" "github.com/jmoiron/sqlx" @@ -196,13 +197,35 @@ func (m *Merger) getRecipes(ctx context.Context, items []Item) (err error) { if recs, found = rm[items[idx].Id]; found { items[idx].Recipes = make([][]int32, 0, len(recs)) for _, rec := range recs { - items[idx].Recipes = append(items[idx].Recipes, rec) + addRecs(&(items[idx].Recipes), rec) } } } return } +func addRecs(recs *[][]int32, rec []int32) { + slices.Sort(rec) + if !slices.ContainsFunc(*recs, recSorter(rec)) { + *recs = append(*recs, rec) + } +} + +func recSorter(rec []int32) func([]int32) bool { + return func(v []int32) bool { + slices.Sort(v) + if !(len(v) == len(rec)) { + return false + } + for idx, i := range v { + if !(i == rec[idx]) { + return false + } + } + return true + } +} + func (m *Merger) Merge(ctx context.Context) (g Game, err error) { if err = m.getGameDetails(ctx, &g); err != nil { return diff --git a/internal/cli/convids/app.go b/internal/cli/convids/app.go index 6bd349b..950dfaf 100644 --- a/internal/cli/convids/app.go +++ b/internal/cli/convids/app.go @@ -50,11 +50,11 @@ func (a *App) run(ctx context.Context) error { } func (a *App) runInLoop(ctx context.Context) error { - fmt.Fprintln(a.stdout, "Looping") + _, _ = fmt.Fprintln(a.stdout, "Looping") var err error for err == nil { err = a.run(ctx) - fmt.Fprintln(a.stdout, err) + _, _ = fmt.Fprintln(a.stdout, err) } return err }