feat(ffmpeg): add ffmpegdist classifier for eugeneware/ffmpeg-static

Upstream uses non-standard OS/arch names (x64, ia32, win32, arm) and
ships both bare binaries and .gz-compressed copies. classifyFFmpegDist
maps those to canonical names and keeps only bare binaries.

Also adds source-override logic to installerconf so that
github_releases + source = ffmpegdist works: GitHub is used for
fetching while the custom classifier handles classification.
This commit is contained in:
AJ ONeal
2026-05-16 21:23:52 -06:00
parent 1e499ed6c8
commit bf5cafac18
3 changed files with 92 additions and 0 deletions

View File

@@ -1,3 +1,4 @@
source = ffmpegdist
github_releases = eugeneware/ffmpeg-static
asset_filter = ffmpeg
version_prefix = b

View File

@@ -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

View File

@@ -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).