From 082038a161e4e3f01f1b5a14d692b77bc8d91396 Mon Sep 17 00:00:00 2001 From: Will Roden Date: Mon, 20 Nov 2023 17:22:27 -0600 Subject: [PATCH 1/2] Add install --to-cache and --wrapper --- cmd/bindown/cli.go | 135 ++++++++++++------------- internal/bindown/config.go | 97 +++++++++++++----- internal/bindown/config_test.go | 27 +++-- internal/bindown/dependency.go | 25 ++++- internal/bindown/download.go | 4 +- internal/bindown/install.go | 172 ++++++++++++++++++++++++++++++-- internal/bindown/util.go | 20 +++- internal/bindown/wrapper.gotmpl | 13 +++ script/fmt | 5 +- script/lint | 2 +- 10 files changed, 383 insertions(+), 117 deletions(-) create mode 100644 internal/bindown/wrapper.gotmpl diff --git a/cmd/bindown/cli.go b/cmd/bindown/cli.go index cb40661..e6f6bc5 100644 --- a/cmd/bindown/cli.go +++ b/cmd/bindown/cli.go @@ -27,19 +27,19 @@ var kongVars = kong.Vars{ "config_install_completions_help": `install shell completions`, "config_extract_path_help": `output path to directory where the downloaded archive is extracted`, "install_force_help": `force install even if it already exists`, - "install_target_file_help": `where to write the file`, - "install_dependency_help": `dependency to install`, + "install_target_file_help": `where to write the file. when multiple dependencies are selected, this is the directory to write to.`, "download_force_help": `force download even if the file already exists`, "download_target_file_help": `filename and path for the downloaded file. Default downloads to cache.`, - "download_dependency_help": `name of the dependency to download`, "allow_missing_checksum": `allow missing checksums`, "download_help": `download a dependency but don't extract or install it`, - "extract_dependency_help": `name of the dependency to extract`, "extract_help": `download and extract a dependency but don't install it`, "extract_target_dir_help": `path to extract to. Default extracts to cache.`, "checksums_dep_help": `name of the dependency to update`, - "trust_cache_help": `trust the cache contents and do not recheck existing downloads and extracts in the cache`, "all_deps_help": `select all dependencies`, + "dependency_help": `name of dependency`, + "install_to_cache_help": `install to cache instead of install dir`, + "install_wrapper_help": `install a wrapper script instead of the binary`, + "install_bindown_help": `path to bindown executable to use in wrapper`, } type rootCmd struct { @@ -252,17 +252,14 @@ func (c fmtCmd) Run(ctx *runContext, cli *rootCmd) error { } type installCmd struct { + dependencySelector Force bool `kong:"help=${install_force_help}"` - Dependency []string `kong:"arg,name=dependency,help=${download_dependency_help},predictor=bin"` - All bool `kong:"help=${all_deps_help}"` TargetFile string `kong:"type=path,name=output,type=file,help=${install_target_file_help}"` System bindown.System `kong:"name=system,default=${system_default},help=${system_help},predictor=allSystems"` AllowMissingChecksum bool `kong:"name=allow-missing-checksum,help=${allow_missing_checksum}"` -} - -func (d *installCmd) BeforeApply(k *kong.Context) error { - optionalDependency(k) - return nil + ToCache bool `kong:"name=to-cache,help=${install_to_cache_help}"` + Wrapper bool `kong:"name=wrapper,help=${install_wrapper_help}"` + BindownExec string `kong:"name=bindown,help=${install_bindown_help}"` } func (d *installCmd) Run(ctx *runContext) error { @@ -270,62 +267,53 @@ func (d *installCmd) Run(ctx *runContext) error { if err != nil { return err } - if d.All { - if len(d.Dependency) > 0 { - return fmt.Errorf("cannot specify dependencies when using --all") - } - d.Dependency = allDependencies(config) + err = d.setDependencies(config) + if err != nil { + return err } - switch len(d.Dependency) { - case 0: - return fmt.Errorf("must specify at least one dependency") - case 1: - default: - if d.TargetFile != "" { - return fmt.Errorf("cannot specify --output when installing multiple dependencies") - } + if d.ToCache && d.Wrapper { + return fmt.Errorf("cannot use --to-cache and --wrapper together") } - for _, dep := range d.Dependency { - var pth string - pth, err = config.InstallDependency(dep, d.System, &bindown.ConfigInstallDependencyOpts{ - TargetPath: d.TargetFile, - Force: d.Force, - AllowMissingChecksum: d.AllowMissingChecksum, - }) - if err != nil { - return err + if d.BindownExec != "" && !d.Wrapper { + return fmt.Errorf("--bindown can only be used with --wrapper") + } + if d.Force && d.Wrapper { + return fmt.Errorf("cannot use --force and --wrapper together") + } + opts := bindown.ConfigInstallDependenciesOpts{ + TargetFile: d.TargetFile, + Force: d.Force, + AllowMissingChecksum: d.AllowMissingChecksum, + ToCache: d.ToCache, + Wrapper: d.Wrapper, + BindownPath: d.BindownExec, + Stdout: ctx.stdout, + } + if d.All || len(d.Dependency) > 1 { + opts.TargetFile = "" + opts.TargetDir = d.TargetFile + if opts.TargetDir == "" { + opts.TargetDir = config.InstallDir } - fmt.Fprintf(ctx.stdout, "installed %s to %s\n", dep, pth) } - return nil + return config.InstallDependencies(d.Dependency, d.System, &opts) } type downloadCmd struct { + dependencySelector Force bool `kong:"help=${download_force_help}"` System bindown.System `kong:"name=system,default=${system_default},help=${system_help},predictor=allSystems"` - Dependency []string `kong:"arg,help=${download_dependency_help},predictor=bin"` - All bool `kong:"help=${all_deps_help}"` AllowMissingChecksum bool `kong:"name=allow-missing-checksum,help=${allow_missing_checksum}"` } -func (d *downloadCmd) BeforeApply(k *kong.Context) error { - optionalDependency(k) - return nil -} - func (d *downloadCmd) Run(ctx *runContext) error { config, err := loadConfigFile(ctx, false) if err != nil { return err } - if d.All { - if len(d.Dependency) > 0 { - return fmt.Errorf("cannot specify dependencies when using --all") - } - d.Dependency = allDependencies(config) - } - if len(d.Dependency) == 0 { - return fmt.Errorf("must specify at least one dependency") + err = d.setDependencies(config) + if err != nil { + return err } for _, dep := range d.Dependency { var pth string @@ -342,30 +330,19 @@ func (d *downloadCmd) Run(ctx *runContext) error { } type extractCmd struct { + dependencySelector System bindown.System `kong:"name=system,default=${system_default},help=${system_help},predictor=allSystems"` - Dependency []string `kong:"arg,help=${extract_dependency_help},predictor=bin"` - All bool `kong:"help=${all_deps_help}"` AllowMissingChecksum bool `kong:"name=allow-missing-checksum,help=${allow_missing_checksum}"` } -func (d *extractCmd) BeforeApply(k *kong.Context) error { - optionalDependency(k) - return nil -} - func (d *extractCmd) Run(ctx *runContext) error { config, err := loadConfigFile(ctx, false) if err != nil { return err } - if d.All { - if len(d.Dependency) > 0 { - return fmt.Errorf("cannot specify dependencies when using --all") - } - d.Dependency = allDependencies(config) - } - if len(d.Dependency) == 0 { - return fmt.Errorf("must specify at least one dependency") + err = d.setDependencies(config) + if err != nil { + return err } for _, dep := range d.Dependency { var pth string @@ -380,12 +357,32 @@ func (d *extractCmd) Run(ctx *runContext) error { return nil } -// optionalDependency sets dependency positional to optional. We do this because we want to allow --all to be -// equivalent to specifying all dependencies but want the help output to indicate that a dependency is required. -func optionalDependency(k *kong.Context) { +type dependencySelector struct { + Dependency []string `kong:"arg,name=dependency,help=${dependency_help},predictor=bin"` + All bool `kong:"help=${all_deps_help}"` +} + +func (d *dependencySelector) BeforeApply(k *kong.Context) error { + // sets dependency positional to optional. We do this because we want to allow --all to be + // equivalent to specifying all dependencies but want the help output to indicate that a + // dependency is required. for _, pos := range k.Selected().Positional { if pos.Name == "dependency" { pos.Required = false } } + return nil +} + +func (d *dependencySelector) setDependencies(config *bindown.Config) error { + if d.All { + if len(d.Dependency) > 0 { + return fmt.Errorf("cannot specify dependencies when using --all") + } + d.Dependency = allDependencies(config) + } + if len(d.Dependency) == 0 { + return fmt.Errorf("must specify at least one dependency") + } + return nil } diff --git a/internal/bindown/config.go b/internal/bindown/config.go index 959ff71..83017c1 100644 --- a/internal/bindown/config.go +++ b/internal/bindown/config.go @@ -295,7 +295,7 @@ func (c *Config) Validate(depName string, systems []System) (errOut error) { } } for _, system := range depSystems { - _, err = c.InstallDependency(depName, system, &ConfigInstallDependencyOpts{ + err = c.InstallDependencies([]string{depName}, system, &ConfigInstallDependenciesOpts{ Force: true, }) if err != nil { @@ -413,38 +413,89 @@ type ConfigInstallDependencyOpts struct { Force bool // AllowMissingChecksum - whether to allow missing checksum AllowMissingChecksum bool + // ToCache - if set, the dependency will be installed to a cache directory. ToCache overrides TargetPath. + ToCache bool } -// InstallDependency downloads, extracts and installs a dependency -func (c *Config) InstallDependency(dependencyName string, system System, opts *ConfigInstallDependencyOpts) (_ string, errOut error) { +// ConfigInstallDependenciesOpts provides options for Config.InstallDependencies +type ConfigInstallDependenciesOpts struct { + TargetFile string + TargetDir string + BindownPath string + Stdout io.Writer + Force bool + AllowMissingChecksum bool + ToCache bool + Wrapper bool +} + +func (c *Config) InstallDependencies(deps []string, system System, opts *ConfigInstallDependenciesOpts) (errOut error) { if opts == nil { - opts = &ConfigInstallDependencyOpts{} + opts = &ConfigInstallDependenciesOpts{} } - dep, err := c.BuildDependency(dependencyName, system) - if err != nil { - return "", err + targetDir := opts.TargetDir + if targetDir == "" { + targetDir = c.InstallDir } - dlFile, key, dlUnlock, err := downloadDependency(dep, c.downloadsCache(), opts.AllowMissingChecksum, opts.Force) - if err != nil { - return "", err + if opts.Wrapper { + cacheDir := c.Cache + configFile := c.Filename + err := createWrappers(deps, opts.TargetFile, targetDir, opts.BindownPath, cacheDir, configFile, opts.AllowMissingChecksum, opts.Stdout) + if err != nil { + return err + } + return nil } - defer deferErr(&errOut, dlUnlock) - - extractDir, exUnlock, err := extractDependencyToCache(dlFile, c.Cache, key, c.extractsCache(), opts.Force) - if err != nil { - return "", err + for _, name := range deps { + dep, err := c.BuildDependency(name, system) + if err != nil { + return err + } + target := opts.TargetFile + if target == "" { + target = filepath.Join(targetDir, name) + } + out, err := install(dep, target, c.Cache, opts.Force, opts.ToCache, opts.AllowMissingChecksum) + if err != nil { + return err + } + if opts.Stdout == nil { + continue + } + if !opts.ToCache { + out = fmt.Sprintf("installed %s to %s", dep.name, out) + } + _, err = fmt.Fprintln(opts.Stdout, out) + if err != nil { + return err + } } - defer deferErr(&errOut, exUnlock) - targetPath := opts.TargetPath - if targetPath == "" { - var binName string - binName, err = c.BinName(dependencyName, system) + return nil +} + +func createWrappers( + deps []string, targetFile, targetDir, bindownExec, cacheDir, configFile string, + missingSums bool, + stdout io.Writer, +) error { + for _, name := range deps { + target := targetFile + if target == "" { + target = filepath.Join(targetDir, name) + } + out, err := createWrapper(name, target, bindownExec, cacheDir, configFile, missingSums) + if err != nil { + return err + } + if stdout == nil { + continue + } + _, err = fmt.Fprintln(stdout, out) if err != nil { - return "", err + return err } - targetPath = filepath.Join(c.InstallDir, binName) } - return install(dep, targetPath, extractDir) + return nil } // AddDependencyFromTemplateOpts options for AddDependencyFromTemplate diff --git a/internal/bindown/config_test.go b/internal/bindown/config_test.go index e4336f3..87fbb53 100644 --- a/internal/bindown/config_test.go +++ b/internal/bindown/config_test.go @@ -1,6 +1,7 @@ package bindown import ( + "bytes" "context" "fmt" "os" @@ -192,7 +193,7 @@ func TestConfig_addTemplateFromSource(t *testing.T) { }) } -func TestConfig_InstallDependency(t *testing.T) { +func TestConfig_InstallDependencies(t *testing.T) { t.Run("raw file", func(t *testing.T) { dir := t.TempDir() servePath := filepath.Join("testdata", "downloadables", "rawfile", "foo") @@ -212,10 +213,14 @@ dependencies: `, binDir, cacheDir, depURL, depURL)) t.Cleanup(func() { require.NoError(t, config.ClearCache()) }) wantBin := filepath.Join(binDir, "foo") - gotPath, err := config.InstallDependency("foo", "darwin/amd64", &ConfigInstallDependencyOpts{}) + wantStdout := fmt.Sprintf("installed foo to %s\n", wantBin) + var stdout bytes.Buffer + err := config.InstallDependencies([]string{"foo"}, "darwin/amd64", &ConfigInstallDependenciesOpts{ + Stdout: &stdout, + }) require.NoError(t, err) - require.Equal(t, wantBin, gotPath) - require.True(t, fileExists(wantBin)) + require.Equal(t, wantStdout, stdout.String()) + require.True(t, FileExists(wantBin)) stat, err := os.Stat(wantBin) require.NoError(t, err) require.False(t, stat.IsDir()) @@ -241,10 +246,14 @@ dependencies: `, binDir, cacheDir, depURL, depURL)) t.Cleanup(func() { require.NoError(t, config.ClearCache()) }) wantBin := filepath.Join(binDir, "foo") - gotPath, err := config.InstallDependency("foo", "darwin/amd64", &ConfigInstallDependencyOpts{}) + var stdout bytes.Buffer + wantStdout := fmt.Sprintf("installed foo to %s\n", wantBin) + err := config.InstallDependencies([]string{"foo"}, "darwin/amd64", &ConfigInstallDependenciesOpts{ + Stdout: &stdout, + }) require.NoError(t, err) - require.Equal(t, wantBin, gotPath) - require.True(t, fileExists(wantBin)) + require.Equal(t, wantStdout, stdout.String()) + require.True(t, FileExists(wantBin)) stat, err := os.Stat(wantBin) require.NoError(t, err) require.False(t, stat.IsDir()) @@ -274,9 +283,9 @@ dependencies: `, binDir, cacheDir, depURL, depURL)) t.Cleanup(func() { require.NoError(t, config.ClearCache()) }) wantBin := filepath.Join(binDir, "foo") - _, err := config.InstallDependency("foo", "darwin/amd64", &ConfigInstallDependencyOpts{}) + err := config.InstallDependencies([]string{"foo"}, "darwin/amd64", &ConfigInstallDependenciesOpts{}) require.Error(t, err) - require.False(t, fileExists(wantBin)) + require.False(t, FileExists(wantBin)) }) } diff --git a/internal/bindown/dependency.go b/internal/bindown/dependency.go index bf4e833..d1f46c5 100644 --- a/internal/bindown/dependency.go +++ b/internal/bindown/dependency.go @@ -1,6 +1,7 @@ package bindown import ( + "encoding/json" "fmt" "maps" "os" @@ -139,6 +140,14 @@ func (d *Dependency) clone() *Dependency { return dd } +func (d *Dependency) binName() string { + d.mustBeBuilt() + if d.BinName != nil && *d.BinName != "" { + return *d.BinName + } + return d.name +} + // interpolateVars executes go templates in values func (d *Dependency) interpolateVars(system System) error { for _, p := range []*string{d.URL, d.ArchivePath, d.BinName} { @@ -200,6 +209,20 @@ func (d *Dependency) applyTemplate(templates map[string]*Dependency, depth int) return nil } +func (d *Dependency) mustBeBuilt() { + if !d.built { + panic("dependency must be built") + } +} + +func (d *Dependency) cacheKey() string { + b, err := json.Marshal(d) + if err != nil { + panic(err) + } + return cacheKey(string(b) + d.name + d.checksum + d.url + string(d.system)) +} + const maxOverrideDepth = 10 func (d *Overrideable) applyOverrides(system System, depth int) error { @@ -309,5 +332,5 @@ func linkBin(link, src string) error { if err != nil { return err } - return os.Chmod(link, info.Mode().Perm()|0o750) + return os.Chmod(link, addExec(info.Mode())) } diff --git a/internal/bindown/download.go b/internal/bindown/download.go index 9ba85d6..1656268 100644 --- a/internal/bindown/download.go +++ b/internal/bindown/download.go @@ -17,9 +17,7 @@ func downloadDependency( dlCache *cache.Cache, allowMissingChecksum, force bool, ) (cachedFile, key string, unlock func() error, errOut error) { - if !dep.built { - panic("downloadDependency called on non-built dependency") - } + dep.mustBeBuilt() dlFile, err := urlFilename(dep.url) if err != nil { return "", "", nil, err diff --git a/internal/bindown/install.go b/internal/bindown/install.go index 90722d7..107c6bc 100644 --- a/internal/bindown/install.go +++ b/internal/bindown/install.go @@ -1,14 +1,60 @@ package bindown import ( + _ "embed" + "fmt" "os" "path/filepath" + "strings" + "text/template" + + "github.com/willabides/bindown/v4/internal/cache" ) -func install(dep *Dependency, targetPath, extractDir string) (string, error) { - if !dep.built { - panic("install called on non-built dependency") +//go:embed wrapper.gotmpl +var wrapperTmplText string + +func install( + dep *Dependency, + targetPath, cacheDir string, + force, toCache, missingSums bool, +) (_ string, errOut error) { + dep.mustBeBuilt() + if toCache { + instCache := &cache.Cache{Root: filepath.Join(cacheDir, "bin")} + key := dep.cacheKey() + dir, unlock, err := instCache.Dir(key, nil, func(dir string) error { + filename := filepath.Join(dir, dep.binName()) + if FileExists(filename) { + return nil + } + _, err := install(dep, filename, cacheDir, force, false, missingSums) + return err + }) + if err != nil { + return "", err + } + err = unlock() + if err != nil { + return "", err + } + return filepath.Join(dir, dep.binName()), nil + } + + dlCache := cache.Cache{Root: filepath.Join(cacheDir, "downloads")} + dlFile, key, dlUnlock, err := downloadDependency(dep, &dlCache, missingSums, force) + if err != nil { + return "", err + } + defer deferErr(&errOut, dlUnlock) + + extractsCache := cache.Cache{Root: filepath.Join(cacheDir, "extracts")} + extractDir, exUnlock, err := extractDependencyToCache(dlFile, cacheDir, key, &extractsCache, force) + if err != nil { + return "", err } + defer deferErr(&errOut, exUnlock) + var binName string if dep.BinName != nil { binName = *dep.BinName @@ -24,13 +70,13 @@ func install(dep *Dependency, targetPath, extractDir string) (string, error) { if dep.Link != nil && *dep.Link { return targetPath, linkBin(targetPath, extractBin) } - if fileExists(targetPath) { - err := os.RemoveAll(targetPath) + if FileExists(targetPath) { + err = os.RemoveAll(targetPath) if err != nil { return "", err } } - err := os.MkdirAll(filepath.Dir(targetPath), 0o755) + err = os.MkdirAll(filepath.Dir(targetPath), 0o755) if err != nil { return "", err } @@ -42,9 +88,121 @@ func install(dep *Dependency, targetPath, extractDir string) (string, error) { if err != nil { return "", err } - err = os.Chmod(targetPath, targetStat.Mode()|0o750) + err = os.Chmod(targetPath, addExec(targetStat.Mode())) if err != nil { return "", err } return targetPath, nil } + +type wrapperTmplVars struct { + DependencyName string + BindownExec string + ConfigFile string + FlagArgs string +} + +var wrapperTmpl = template.Must(template.New("wrapper").Parse(wrapperTmplText)) + +func createWrapper(name, target, bindownExec, cacheDir, configFile string, missingSums bool) (string, error) { + wrapperDir := filepath.Dir(target) + err := os.MkdirAll(wrapperDir, 0o750) + if err != nil { + return "", err + } + if bindownExec == "" { + bindownExec = "bindown" + } else { + bindownExec, err = relPath(wrapperDir, bindownExec) + if err != nil { + return "", err + } + if !strings.HasPrefix(bindownExec, ".") && !filepath.IsAbs(bindownExec) { + bindownExec = "./" + bindownExec + } + } + + configFile, err = relPath(wrapperDir, configFile) + if err != nil { + return "", err + } + + flagArgs := `--to-cache` + if missingSums { + flagArgs += " \\\n --allow-missing-checksum" + } + addFlagArg := func(name, value string) { + flagArgs += fmt.Sprintf(" \\\n %s %q", name, value) + } + addFlagArg("--configfile", configFile) + + err = os.MkdirAll(cacheDir, 0o750) + if err != nil { + return "", err + } + cacheDir, err = relPath(wrapperDir, cacheDir) + if err != nil { + return "", err + } + addFlagArg("--cache", cacheDir) + + file, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o750) + if err != nil { + return "", err + } + + err = wrapperTmpl.Execute(file, wrapperTmplVars{ + DependencyName: name, + BindownExec: bindownExec, + ConfigFile: configFile, + FlagArgs: flagArgs, + }) + if err != nil { + return "", err + } + err = file.Close() + if err != nil { + return "", err + } + return target, nil +} + +// relPath returns target relative to base and converted to slash-separated path. +// Unlike filepath.Rel, it converts both paths to absolute paths before calculating the relative path. +func relPath(base, target string) (string, error) { + absBase, err := filepath.Abs(base) + if err != nil { + return "", err + } + absBase, err = filepath.EvalSymlinks(absBase) + if err != nil { + return "", err + } + absTarget, err := filepath.Abs(target) + if err != nil { + return "", err + } + absTarget, err = filepath.EvalSymlinks(absTarget) + if err != nil { + return "", err + } + rel, err := filepath.Rel(absBase, absTarget) + if err != nil { + return "", err + } + return filepath.ToSlash(rel), nil +} + +// addExec adds exec for each read bit in mode +func addExec(mode os.FileMode) os.FileMode { + if mode&0o4 != 0 { + mode |= 0o1 + } + if mode&0o40 != 0 { + mode |= 0o10 + } + if mode&0o400 != 0 { + mode |= 0o100 + } + return mode +} diff --git a/internal/bindown/util.go b/internal/bindown/util.go index f0706d2..bda7fe1 100644 --- a/internal/bindown/util.go +++ b/internal/bindown/util.go @@ -115,16 +115,16 @@ func fileChecksum(filename string) (string, error) { return hex.EncodeToString(hasher.Sum(nil)), nil } -// fileExists asserts that a file exist or symlink exists. +// FileExists asserts that a file exist or symlink exists. // Returns false for symlinks pointing to non-existent files. -func fileExists(path string) bool { +func FileExists(path string) bool { _, statErr := os.Stat(filepath.FromSlash(path)) return !os.IsNotExist(statErr) } // fileExistsWithChecksum returns true if the file both exists and has a matching checksum func fileExistsWithChecksum(filename, checksum string) (bool, error) { - if !fileExists(filename) { + if !FileExists(filename) { return false, nil } got, err := fileChecksum(filename) @@ -316,3 +316,17 @@ func MapKeys[M ~map[K]V, K comparable, V any](m M) []K { } return r } + +// DefaultValue returns the first argument that isn't zero +func DefaultValue[T comparable](val T, def ...T) T { + var zero T + if val != zero { + return val + } + for _, d := range def { + if d != zero { + return d + } + } + return zero +} diff --git a/internal/bindown/wrapper.gotmpl b/internal/bindown/wrapper.gotmpl new file mode 100644 index 0000000..e78b19b --- /dev/null +++ b/internal/bindown/wrapper.gotmpl @@ -0,0 +1,13 @@ +#!/bin/sh +# Code generated by bindown. DO NOT EDIT. + +set -e + +bindown_bin="$( + CDPATH="" cd -- "$(dirname -- "$0")" + + "{{ .BindownExec }}" install "{{.DependencyName}}" \ + {{ .FlagArgs }} +)" + +exec "$bindown_bin" "$@" diff --git a/script/fmt b/script/fmt index 0c0e954..0577df9 100755 --- a/script/fmt +++ b/script/fmt @@ -8,5 +8,8 @@ script/bindown -q install gofumpt shfmt bin/gofumpt -w internal/*/*.go cmd/*/*.go -find script -type f -not -name 'bootstrap-bindown.sh' -print0 | xargs -0 bin/shfmt -w -i 2 -ci -sr +find script -type f -not -name 'bootstrap-bindown.sh' | + grep -v "/.*/" | + xargs bin/shfmt -w -i 2 -ci -sr + bin/shfmt -w -i 2 -ci -sr internal/build-bootstrapper/assets/*.sh diff --git a/script/lint b/script/lint index 579d82e..1610641 100755 --- a/script/lint +++ b/script/lint @@ -2,7 +2,7 @@ set -e -CDPATH="" cd -- "$(dirname -- "$(dirname -- "$0")")" +CDPATH="" cd -- "$(dirname -- "$0")/.." script/bindown -q install golangci-lint shellcheck From a51f0da24430a800739a781a95e362662df2dd0c Mon Sep 17 00:00:00 2001 From: Will Roden Date: Mon, 20 Nov 2023 17:29:45 -0600 Subject: [PATCH 2/2] remove unused --- internal/bindown/util.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/internal/bindown/util.go b/internal/bindown/util.go index bda7fe1..c4ae4bf 100644 --- a/internal/bindown/util.go +++ b/internal/bindown/util.go @@ -316,17 +316,3 @@ func MapKeys[M ~map[K]V, K comparable, V any](m M) []K { } return r } - -// DefaultValue returns the first argument that isn't zero -func DefaultValue[T comparable](val T, def ...T) T { - var zero T - if val != zero { - return val - } - for _, d := range def { - if d != zero { - return d - } - } - return zero -}