From ddd9d1d63de1b886b316ee6852fc078fa6f1b930 Mon Sep 17 00:00:00 2001 From: Arsen Musayelyan Date: Wed, 11 Jan 2023 13:37:52 -0800 Subject: [PATCH] Add languages to overrides --- info.go | 5 ++- internal/overrides/overrides.go | 54 ++++++++++++++++++++++++++-- internal/overrides/overrides_test.go | 54 +++++++++++++++++++++++++--- internal/shutils/decoder/decoder.go | 12 +++++-- 4 files changed, 115 insertions(+), 10 deletions(-) diff --git a/info.go b/info.go index c1e0ea6..a1fbf7f 100644 --- a/info.go +++ b/info.go @@ -62,7 +62,10 @@ func infoCmd(c *cli.Context) error { if err != nil { log.Fatal("Error parsing os-release file").Err(err).Send() } - names = overrides.Resolve(info, overrides.DefaultOpts) + names, err = overrides.Resolve(info, overrides.DefaultOpts) + if err != nil { + log.Fatal("Error resolving overrides").Err(err).Send() + } } for _, pkg := range pkgs { diff --git a/internal/overrides/overrides.go b/internal/overrides/overrides.go index 3b9d03f..a7a156e 100644 --- a/internal/overrides/overrides.go +++ b/internal/overrides/overrides.go @@ -1,32 +1,42 @@ package overrides import ( + "os" "runtime" "strings" "go.arsenm.dev/lure/distro" "go.arsenm.dev/lure/internal/cpu" + "golang.org/x/exp/slices" + "golang.org/x/text/language" ) type Opts struct { Name string Overrides bool LikeDistros bool + Languages []string } var DefaultOpts = &Opts{ Overrides: true, LikeDistros: true, + Languages: []string{"en"}, } // Resolve generates a slice of possible override names in the order that they should be checked -func Resolve(info *distro.OSRelease, opts *Opts) []string { +func Resolve(info *distro.OSRelease, opts *Opts) ([]string, error) { if opts == nil { opts = DefaultOpts } if !opts.Overrides { - return []string{opts.Name} + return []string{opts.Name}, nil + } + + langs, err := parseLangs(opts.Languages) + if err != nil { + return nil, err } architectures := []string{runtime.GOARCH} @@ -71,7 +81,22 @@ func Resolve(info *distro.OSRelease, opts *Opts) []string { out[index] = strings.ReplaceAll(item, "-", "_") } - return out + if len(langs) > 0 { + tmp := out + out = make([]string, 0, len(tmp)+(len(tmp)*len(langs))) + for _, lang := range langs { + for _, val := range tmp { + if val == "" { + continue + } + + out = append(out, val+"_"+lang) + } + } + out = append(out, tmp...) + } + + return out, nil } func (o *Opts) WithName(name string) *Opts { @@ -97,3 +122,26 @@ func (o *Opts) WithLikeDistros(v bool) *Opts { out.LikeDistros = v return out } + +func parseLangs(langs []string) ([]string, error) { + out := make([]string, len(langs)) + for i, lang := range langs { + tag, err := language.Parse(lang) + if err != nil { + return nil, err + } + base, _ := tag.Base() + out[i] = base.String() + } + slices.Sort(out) + out = slices.Compact(out) + return out, nil +} + +func SystemLang() string { + lang := os.Getenv("LANG") + if lang == "" { + lang = "en" + } + return lang +} \ No newline at end of file diff --git a/internal/overrides/overrides_test.go b/internal/overrides/overrides_test.go index 9a2d7cd..3b28159 100644 --- a/internal/overrides/overrides_test.go +++ b/internal/overrides/overrides_test.go @@ -14,9 +14,19 @@ var info = &distro.OSRelease{ } func TestResolve(t *testing.T) { - names := overrides.Resolve(info, nil) + names, err := overrides.Resolve(info, nil) + if err != nil { + t.Fatalf("Expected no error, got %s", err) + } expected := []string{ + "amd64_centos_en", + "centos_en", + "amd64_rhel_en", + "rhel_en", + "amd64_fedora_en", + "fedora_en", + "amd64_en", "amd64_centos", "centos", "amd64_rhel", @@ -33,11 +43,14 @@ func TestResolve(t *testing.T) { } func TestResolveName(t *testing.T) { - names := overrides.Resolve(info, &overrides.Opts{ + names, err := overrides.Resolve(info, &overrides.Opts{ Name: "deps", Overrides: true, LikeDistros: true, }) + if err != nil { + t.Fatalf("Expected no error, got %s", err) + } expected := []string{ "deps_amd64_centos", @@ -56,10 +69,13 @@ func TestResolveName(t *testing.T) { } func TestResolveNoLikeDistros(t *testing.T) { - names := overrides.Resolve(info, &overrides.Opts{ + names, err := overrides.Resolve(info, &overrides.Opts{ Overrides: true, LikeDistros: false, }) + if err != nil { + t.Fatalf("Expected no error, got %s", err) + } expected := []string{ "amd64_centos", @@ -74,11 +90,14 @@ func TestResolveNoLikeDistros(t *testing.T) { } func TestResolveNoOverrides(t *testing.T) { - names := overrides.Resolve(info, &overrides.Opts{ + names, err := overrides.Resolve(info, &overrides.Opts{ Name: "deps", Overrides: false, LikeDistros: false, }) + if err != nil { + t.Fatalf("Expected no error, got %s", err) + } expected := []string{"deps"} @@ -86,3 +105,30 @@ func TestResolveNoOverrides(t *testing.T) { t.Errorf("expected %v, got %v", expected, names) } } + +func TestResolveLangs(t *testing.T) { + names, err := overrides.Resolve(info, &overrides.Opts{ + Overrides: true, + Languages: []string{"ru_RU", "en", "en_US"}, + }) + if err != nil { + t.Fatalf("Expected no error, got %s", err) + } + + expected := []string{ + "amd64_centos_en", + "centos_en", + "amd64_en", + "amd64_centos_ru", + "centos_ru", + "amd64_ru", + "amd64_centos", + "centos", + "amd64", + "", + } + + if !reflect.DeepEqual(names, expected) { + t.Errorf("expected %v, got %v", expected, names) + } +} diff --git a/internal/shutils/decoder/decoder.go b/internal/shutils/decoder/decoder.go index 0f2c12f..359d07c 100644 --- a/internal/shutils/decoder/decoder.go +++ b/internal/shutils/decoder/decoder.go @@ -182,7 +182,11 @@ func (d *Decoder) GetFunc(name string) (ScriptFunc, bool) { } func (d *Decoder) getFunc(name string) *syntax.Stmt { - names := overrides.Resolve(d.info, overrides.DefaultOpts.WithName(name)) + names, err := overrides.Resolve(d.info, overrides.DefaultOpts.WithName(name)) + if err != nil { + return nil + } + for _, fnName := range names { fn, ok := d.runner.Funcs[fnName] if ok { @@ -195,7 +199,11 @@ func (d *Decoder) getFunc(name string) *syntax.Stmt { // getVar gets a variable based on its name, taking into account // override variables and nameref variables. func (d *Decoder) getVar(name string) *expand.Variable { - names := overrides.Resolve(d.info, overrides.DefaultOpts.WithName(name)) + names, err := overrides.Resolve(d.info, overrides.DefaultOpts.WithName(name)) + if err != nil { + return nil + } + for _, varName := range names { val, ok := d.runner.Vars[varName] if ok {