package mod import ( "runtime/debug" "sync" "golang.org/x/mod/module" "golang.org/x/mod/semver" ) var ( buildInfoOnce sync.Once buildInfo *debug.BuildInfo ) func Version(name string) (modVersion string) { return moduleVersion(name, readBuildInfo()) } func moduleVersion(name string, bi *debug.BuildInfo) (modVersion string) { if bi == nil { return } // iterate over all dependencies and find buildkit for _, dep := range bi.Deps { if dep.Path != name { continue } // get the version of buildkit dependency modVersion = dep.Version if dep.Replace != nil { // if the version is replaced, get the replaced version modVersion = dep.Replace.Version } if !module.IsPseudoVersion(modVersion) { return } // if the version is a pseudo version, get the base version // e.g. v0.10.7-0.20230306143919-70f2ad56d3e5 => v0.10.6 if base, err := module.PseudoVersionBase(modVersion); err == nil && base != "" { // set canonical version of the base version (removes +incompatible suffix) // e.g. v2.1.2+incompatible => v2.1.2 base = semver.Canonical(base) // if the version is a pseudo version, get the revision // e.g. v0.10.7-0.20230306143919-70f2ad56d3e5 => 70f2ad56d3e5 if rev, err := module.PseudoVersionRev(modVersion); err == nil && rev != "" { // append the revision to the version // e.g. v0.10.7-0.20230306143919-70f2ad56d3e5 => v0.10.6+70f2ad56d3e5 modVersion = base + "+" + rev } else { // if the revision is not available, use the base version modVersion = base } } break } return } func readBuildInfo() *debug.BuildInfo { buildInfoOnce.Do(func() { buildInfo, _ = debug.ReadBuildInfo() }) return buildInfo }