From d1349018d6bf27be6688b2eba84c716bbea61714 Mon Sep 17 00:00:00 2001 From: Michel Blanc Date: Tue, 26 Sep 2023 08:45:22 +0200 Subject: [PATCH] fixed erroneous matches in tarballs Matcher was searching for files ending with binary listed in distributions thus, `_rg` would match `rg` specification, and since the former appears after the latter in the tarball, `_ rg` would be installed as the binary (but the file contains the completion). To solve this, added support for regexps in distribution binaries specification. Fixes #239 --- README.md | 15 +++++++++++++-- distributions/distributions.yaml | 2 +- internal/app/definitions.go | 2 +- internal/tpl/tpl.go | 27 +++++++++++++++++++++++---- 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 0428c925..e28b0d36 100644 --- a/README.md +++ b/README.md @@ -696,8 +696,19 @@ sources: `binaries_config`: ```yaml -# Array of binaries names that will be downloaded - - +# Array of binaries names that will be installed. +# The string provided is treated as a regexp. +# This regexp is compared to the filenames found in packages. +# Note that filenames contains their path in the package with the top level +# directory removed, e.g.: +# software-13.0.0-x86_64-unknown-linux-musl/foo/bar/zebinary +# becomes +# foo/bar/zebinary +# Also note that, since all binaries will be installed as the distribution +# entry name, only one (the latest match) will survive for now. +# The list is just here to allow alternate names, not real multiple binaries +# installation. + - ``` `supported_platforms`: diff --git a/distributions/distributions.yaml b/distributions/distributions.yaml index 8df3c162..d76f701f 100644 --- a/distributions/distributions.yaml +++ b/distributions/distributions.yaml @@ -3248,7 +3248,7 @@ sources: install: type: tgz binaries: - - rg + - "^rg$" # ripgrep binary is named rg ruflood: description: Helping Ukraine by flooding russian state-controlled media/bureau/bank websites. diff --git a/internal/app/definitions.go b/internal/app/definitions.go index f4281782..01b6e737 100644 --- a/internal/app/definitions.go +++ b/internal/app/definitions.go @@ -8,7 +8,7 @@ import ( "github.com/devops-works/binenv/internal/platform" ) -// Distributions holds the liste of available software sources +// Distributions holds the list of available software sources type Distributions struct { Sources map[string]Sources `yaml:"sources"` } diff --git a/internal/tpl/tpl.go b/internal/tpl/tpl.go index f893525c..cb4576e4 100644 --- a/internal/tpl/tpl.go +++ b/internal/tpl/tpl.go @@ -2,6 +2,7 @@ package tpl import ( "bytes" + "regexp" "runtime" "strings" "sync" @@ -62,13 +63,21 @@ func (a Args) Interpolate(m map[string]string) { } // MatchFilters matches a file against a list of template filters +// +// We use a template to allow interpolation in binaries list (e.g. {{.OS}}-{{.Arch}}-{{.Version}}) +// Also, the top level directory, if present, is removed to allow an easier search +// For instance : +// ripgrep-13.0.0-x86_64-unknown-linux-musl/rg +// becomes +// ^rg$ func (a Args) MatchFilters(file string, filters []string) (bool, error) { - var once sync.Once + var ( + once sync.Once + onceErr error + ) tpls := []*template.Template{} - var onceErr error - onceBody := func() { for _, v := range filters { tpl, err := template.New("matcher").Parse(v) @@ -85,6 +94,11 @@ func (a Args) MatchFilters(file string, filters []string) (bool, error) { return false, onceErr } + // Remove first directory if present + if strings.Contains(file, "/") { + file = strings.Join(strings.Split(file, "/")[1:], "/") + } + for _, t := range tpls { buf := bytes.Buffer{} err := t.Execute(&buf, a) @@ -93,7 +107,12 @@ func (a Args) MatchFilters(file string, filters []string) (bool, error) { } // fmt.Printf("trying to match %s against %s\n", file, buf.String()) - if strings.HasSuffix(file, buf.String()) { + patt, err := regexp.Compile(buf.String()) + if err != nil { + return false, err + } + + if patt.MatchString(file) { // fmt.Printf("file %s matches filters\n", file) return true, nil }