From 1bc9e40bf6130bca9a1582cc0850898858630813 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 8 May 2026 11:37:24 -0600 Subject: [PATCH] feat(ffmpeg): custom ffmpegdist classifier for non-standard release names eugeneware/ffmpeg-static uses non-standard filenames (x64, ia32, win32, arm) and ships both bare binaries and .gz variants. The generic classifier mishandles the arch mapping and the installer has no bare .gz handler. Add ffmpegdist custom classifier that: - Maps non-standard OS/arch names to canonical values - Filters to bare binaries only (skips .gz, ffprobe, LICENSE, README) - Strips 'b' version prefix from tags Also fix installerconf to allow explicit 'source' to override the inferred source when both are present (e.g. source=ffmpegdist + github_releases for fetching). Closes #947 --- internal/classifypkg/classifypkg.go | 82 +++++++++++++++++++++++++ internal/installerconf/installerconf.go | 9 +++ 2 files changed, 91 insertions(+) diff --git a/internal/classifypkg/classifypkg.go b/internal/classifypkg/classifypkg.go index 646494e..42a7c6c 100644 --- a/internal/classifypkg/classifypkg.go +++ b/internal/classifypkg/classifypkg.go @@ -166,6 +166,8 @@ func classifySource(pkg string, conf *installerconf.Conf, d *rawcache.Dir) ([]st return classifyMariaDBDist(d) case "zigdist": return classifyZigDist(d) + case "ffmpegdist": + return classifyFFmpegDist(d) default: return nil, nil } @@ -464,6 +466,86 @@ func classifyGitHub(pkg string, conf *installerconf.Conf, d *rawcache.Dir) ([]st return assets, nil } +var ffmpegOSMap = map[string]string{ + "linux": "linux", + "darwin": "darwin", + "win32": "windows", +} + +var ffmpegArchMap = map[string]string{ + "x64": "x86_64", + "ia32": "x86", + "arm64": "aarch64", + "arm": "armv7", +} + +// classifyFFmpegDist handles eugeneware/ffmpeg-static releases. +// Upstream uses non-standard names (x64, ia32, win32, arm) and ships both +// bare binaries and .gz-compressed copies. Only bare binaries are kept — +// the install template has no handler for single-file .gz extraction. +func classifyFFmpegDist(d *rawcache.Dir) ([]storage.Asset, error) { + releases, err := ReadAllRaw(d) + if err != nil { + return nil, err + } + + var assets []storage.Asset + for _, data := range releases { + var rel ghRelease + if err := json.Unmarshal(data, &rel); err != nil { + continue + } + if rel.Draft { + continue + } + + version := strings.TrimPrefix(rel.TagName, "b") + + channel := "stable" + if rel.Prerelease { + channel = "beta" + } + + date := "" + if len(rel.PublishedAt) >= 10 { + date = rel.PublishedAt[:10] + } + + for _, a := range rel.Assets { + if strings.Contains(a.Name, ".") { + continue + } + if !strings.HasPrefix(a.Name, "ffmpeg-") { + continue + } + + parts := strings.SplitN(a.Name, "-", 3) + if len(parts) != 3 { + continue + } + + os, osOK := ffmpegOSMap[parts[1]] + arch, archOK := ffmpegArchMap[parts[2]] + if !osOK || !archOK { + continue + } + + assets = append(assets, storage.Asset{ + Filename: a.Name, + Version: version, + Channel: channel, + OS: os, + Arch: arch, + Format: "", + Download: a.BrowserDownloadURL, + Date: date, + }) + } + } + + return assets, nil +} + // classifyServiceman handles serviceman's dual-repo layout: binary releases // from therootcompany/serviceman (≤v0.8.x) and source-only releases from // bnnanet/serviceman (v0.9.x+). Emits binary assets where available, plus diff --git a/internal/installerconf/installerconf.go b/internal/installerconf/installerconf.go index 3795c0c..3b51ff5 100644 --- a/internal/installerconf/installerconf.go +++ b/internal/installerconf/installerconf.go @@ -162,6 +162,8 @@ func Read(path string) (*Conf, error) { c := &Conf{} // Infer source from primary key, falling back to explicit "source". + // When both github_releases and source are set, parse the repo ref + // from github_releases but use the explicit source for classification. switch { // GitHub binary releases. case raw["github_releases"] != "": @@ -213,6 +215,13 @@ func Read(path string) (*Conf, error) { default: } + // Explicit "source" overrides the inferred source when both are present. + // This lets packages like ffmpeg use github_releases for fetching but + // a custom classifier for classification. + if raw["source"] != "" && c.Source != "" { + c.Source = raw["source"] + } + // git_url can appear alongside any source type (e.g. github_sources) // to provide a git clone fallback. When it's the only key, it's the // primary source (gittag).