Skip to content

classifier multiple classifier*.yml configurations #379

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion internal/classifier/classifier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,8 @@ func TestClassifier(t *testing.T) {
t.Parallel()

mocks := newTestClassifierMocks(t)
source, sourceErr := coreSourceProvider{}.provider().source()

source, sourceErr := yamlSourceProvider{rawSourceProvider: coreSourceProvider{}}.source()
if sourceErr != nil {
t.Fatal(sourceErr)
return
Expand Down
2 changes: 1 addition & 1 deletion internal/classifier/json_schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func TestJSONSchema(t *testing.T) {
require.NoError(t, err)
assert.True(t, metaResult.Valid())

coreClassifier, err := yamlSourceProvider{rawSourceProvider: coreSourceProvider{}}.source()
coreClassifier, err := coreSourceProvider{}.provider().source()
require.NoError(t, err)
coreClassifierJSON, err := json.Marshal(coreClassifier)
require.NoError(t, err)
Expand Down
108 changes: 71 additions & 37 deletions internal/classifier/source_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,26 @@ package classifier

import (
"os"
"path/filepath"
"strings"

"github.com/adrg/xdg"
"github.com/bitmagnet-io/bitmagnet/internal/tmdb"
"gopkg.in/yaml.v3"
)

func newSourceProvider(config Config, tmdbConfig tmdb.Config) sourceProvider {
return mergeSourceProvider{
providers: []sourceProvider{
yamlSourceProvider{rawSourceProvider: coreSourceProvider{}},
yamlSourceProvider{rawSourceProvider: xdgSourceProvider{}},
yamlSourceProvider{rawSourceProvider: cwdSourceProvider{}},
configSourceProvider{
config: config,
tmdbEnabled: tmdbConfig.Enabled,
},
},
}
var providers []sourceProvider
providers = append(providers, coreSourceProvider{}.provider())
providers = append(providers, xdgSourceProvider{}.providers()...)
providers = append(providers, cwdSourceProvider{}.providers()...)
providers = append(providers, extraSourceProvider{}.providers()...)
providers = append(providers, configSourceProvider{
config: config,
tmdbEnabled: tmdbConfig.Enabled,
})

return mergeSourceProvider{providers: providers}
}

type sourceProvider interface {
Expand Down Expand Up @@ -49,23 +51,19 @@ func (m mergeSourceProvider) source() (Source, error) {
return source, nil
}

type rawSourceProvider interface {
source() ([]byte, error)
}

type yamlSourceProvider struct {
rawSourceProvider
raw []byte
err error
}

func (y yamlSourceProvider) source() (Source, error) {
raw, err := y.rawSourceProvider.source()
if err != nil {
return Source{}, err
if y.err != nil {
return Source{}, y.err
}

rawWorkflow := make(map[string]interface{})

parseErr := yaml.Unmarshal(raw, &rawWorkflow)
parseErr := yaml.Unmarshal(y.raw, &rawWorkflow)
if parseErr != nil {
return Source{}, parseErr
}
Expand All @@ -86,34 +84,68 @@ func (y yamlSourceProvider) source() (Source, error) {

type coreSourceProvider struct{}

func (coreSourceProvider) source() ([]byte, error) {
return classifierCoreYaml, nil
func (coreSourceProvider) provider() sourceProvider {
return yamlSourceProvider{raw: classifierCoreYaml}
}

type xdgSourceProvider struct{}

func (xdgSourceProvider) source() ([]byte, error) {
if path, pathErr := xdg.ConfigFile("bitmagnet/classifier.yml"); pathErr == nil {
if bytes, readErr := os.ReadFile(path); readErr == nil {
return bytes, nil
} else if !os.IsNotExist(readErr) {
return nil, readErr
}
func (yamlSourceProvider) providers(path string, wildcard bool) []sourceProvider {
glob := path

if wildcard {
dir, fname := filepath.Split(path)
glob = dir + "classifier*" + filepath.Ext(fname)
}

paths, err := filepath.Glob(glob)
if err != nil {
return []sourceProvider{yamlSourceProvider{err: err}}
}

return []byte{'{', '}'}, nil
providers := make([]sourceProvider, len(paths))

for i, path := range paths {
bytes, readErr := os.ReadFile(path)
providers[i] = yamlSourceProvider{raw: bytes, err: readErr}
}

return providers
}

type cwdSourceProvider struct{}
func (xdgSourceProvider) providers() []sourceProvider {
path, err := xdg.ConfigFile("bitmagnet/classifier.yml")
if err != nil {
return []sourceProvider{yamlSourceProvider{err: err}}
}

return yamlSourceProvider{}.providers(path, true)
}

type extraSourceProvider struct{}

func (cwdSourceProvider) source() ([]byte, error) {
if bytes, readErr := os.ReadFile("./classifier.yml"); readErr == nil {
return bytes, nil
} else if !os.IsNotExist(readErr) {
return nil, readErr
func (extraSourceProvider) providers() []sourceProvider {
var extraConfigFiles []string

for _, rawEnvEntry := range os.Environ() {
parts := strings.SplitN(rawEnvEntry, "=", 2)
if parts[0] == extraFilesKey {
extraConfigFiles = strings.Split(parts[1], ",")
}
}

return []byte{'{', '}'}, nil
var providers []sourceProvider
for _, path := range extraConfigFiles {
providers = append(providers, yamlSourceProvider{}.providers(path, false)...)
}

return providers
}

type cwdSourceProvider struct{}

func (cwdSourceProvider) providers() []sourceProvider {
return yamlSourceProvider{}.providers("./classifier.yml", true)
}

type configSourceProvider struct {
Expand Down Expand Up @@ -141,3 +173,5 @@ func (c configSourceProvider) source() (Source, error) {
Flags: fs,
}, nil
}

const extraFilesKey = "EXTRA_CLASSIFIER_FILES"