summaryrefslogtreecommitdiff
path: root/internal/mod/mod.go
blob: c1b35e10d5666047bc690cfea81c31c90dc67bf8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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
}