From a6d1755e32fdc72e3170e12765b9ea0d80d51dc8 Mon Sep 17 00:00:00 2001 From: rjshrjndrn Date: Mon, 3 Nov 2025 18:08:15 +0100 Subject: [PATCH] feat: add template variable support in asset_filters Add support for {{.OS}} and {{.Arch}} template variables in the asset_filters configuration setting. These variables are automatically replaced with the target system's OS and architecture values. The substitution considers: - The --system flag if provided - The system setting in repository config - The runtime system as fallback This allows portable configuration that adapts to different platforms without hardcoding system-specific values. Signed-off-by: rjshrjndrn --- README.md | 27 ++++++++++++++++++++++++++- config.go | 42 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b6dbd45b..200d1aff 100644 --- a/README.md +++ b/README.md @@ -182,6 +182,27 @@ target = "~/bin" target = "~/.local/bin" ``` +## Template Variables in Asset Filters + +The `asset_filters` setting supports template variables that are automatically replaced with the appropriate values based on your target system: + +- `{{.OS}}` - Replaced with the target operating system (e.g., `linux`, `darwin`, `windows`) +- `{{.Arch}}` - Replaced with the target architecture (e.g., `amd64`, `arm64`, `386`) + +The values are determined by: +1. The `--system` flag if provided (e.g., `--system linux/amd64`) +2. The `system` setting in the repository configuration +3. The runtime system (detected automatically from your current OS/architecture) + +Example: +```toml +["junegunn/fzf"] +asset_filters = ["{{.OS}}_{{.Arch}}.tar.gz"] +``` + +When running `eget junegunn/fzf` on a Linux AMD64 system, this will match assets containing `linux_amd64.tar.gz`. +When running `eget junegunn/fzf --system darwin/arm64`, it will match assets containing `darwin_arm64.tar.gz`. + ## Available settings - global section | Setting | Related Flag | Description | Default | @@ -202,7 +223,7 @@ target = "~/.local/bin" | Setting | Related Flag | Description | Default | | --- | --- | --- | --- | | `all` | `--all` | Whether to extract all candidate files. | `false` | -| `asset_filters` | `--asset` | An array of partial asset names to filter the available assets for download. | `[]` | +| `asset_filters` | `--asset` | An array of partial asset names to filter the available assets for download. Supports template variables `{{.OS}}` and `{{.Arch}}` which will be replaced with the target OS and architecture. | `[]` | | `download_only` | `--download-only` | Whether to stop after downloading the asset (no extraction). | `false` | | `download_source` | `--source` | Whether to download the source code for the target repo instead of a release. | `false` | | `file` | `--file` | The glob to select files for extraction. | `*` | @@ -229,6 +250,10 @@ target = "~/.local/bin" show_hash = true asset_filters = [ "static", ".tar.gz" ] target = "~/.local/bin/micro" + +["junegunn/fzf"] + asset_filters = ["{{.OS}}_{{.Arch}}.tar.gz"] + target = "~/bin" ``` By using the configuration above, you could run the following command to download the latest release of `micro`: diff --git a/config.go b/config.go index 7ab42a9d..069e8e20 100644 --- a/config.go +++ b/config.go @@ -6,6 +6,7 @@ import ( "os" "path/filepath" "runtime" + "strings" "github.com/BurntSushi/toml" "github.com/jessevdk/go-flags" @@ -221,6 +222,26 @@ func update[T any](config T, cli *T) T { return *cli } +// substituteTemplateVars replaces {{.OS}} and {{.Arch}} in asset filter strings +// with the actual OS and architecture values based on the system parameter. +func substituteTemplateVars(filter string, system string) string { + goos := runtime.GOOS + goarch := runtime.GOARCH + + // If system is specified, parse it to extract OS and Arch + if system != "" && system != "all" { + parts := strings.Split(system, "/") + if len(parts) >= 2 { + goos = parts[0] + goarch = parts[1] + } + } + + result := strings.ReplaceAll(filter, "{{.OS}}", goos) + result = strings.ReplaceAll(result, "{{.Arch}}", goarch) + return result +} + // Move the loaded configuration file global options into the opts variable func SetGlobalOptionsFromConfig(config *Config, parser *flags.Parser, opts *Flags, cli CliFlags) error { if config.Global.GithubToken != "" && os.Getenv("EGET_GITHUB_TOKEN") == "" { @@ -255,7 +276,6 @@ func SetProjectOptionsFromConfig(config *Config, parser *flags.Parser, opts *Fla for name, repo := range config.Repositories { if name == projectName { opts.All = update(repo.All, cli.All) - opts.Asset = update(repo.AssetFilters, cli.Asset) opts.DLOnly = update(repo.DownloadOnly, cli.DLOnly) opts.ExtractFile = update(repo.File, cli.ExtractFile) opts.Hash = update(repo.ShowHash, cli.Hash) @@ -271,6 +291,26 @@ func SetProjectOptionsFromConfig(config *Config, parser *flags.Parser, opts *Fla opts.UpgradeOnly = update(repo.UpgradeOnly, cli.UpgradeOnly) opts.Verify = update(repo.Verify, cli.Verify) opts.DisableSSL = update(repo.DisableSSL, cli.DisableSSL) + + // Apply template substitution to asset_filters + // We need to determine the system value to use for substitution + systemForTemplate := opts.System + if systemForTemplate == "" { + systemForTemplate = fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH) + } + + assetFilters := repo.AssetFilters + if cli.Asset == nil && len(assetFilters) > 0 { + // Only apply template substitution if we're using config asset_filters + substitutedFilters := make([]string, len(assetFilters)) + for i, filter := range assetFilters { + substitutedFilters[i] = substituteTemplateVars(filter, systemForTemplate) + } + opts.Asset = substitutedFilters + } else { + opts.Asset = update(assetFilters, cli.Asset) + } + break } }