package version import ( "fmt" "strings" "golang.org/x/mod/semver" ) // Detail returns a multiline string containing every possible piece of information we collect. func (b *BuildInfo) Detail() (ver string) { var sb strings.Builder sb.WriteString(fmt.Sprintf("%v\n\n", b.short)) sb.WriteString(fmt.Sprintf("====\nSource Control: %v\n", b.SourceControl)) if b.TagVersion != "" { if b.PostTagCommits > 0 { sb.WriteString(fmt.Sprintf("Version Base: %v\nCommit Hash: %v\n", b.TagVersion, b.CommitHash)) } else { sb.WriteString(fmt.Sprintf("Version: %v\n", b.TagVersion)) } } else { sb.WriteString(fmt.Sprintf("Version: (Unversioned)\nCommit Hash: %v\n", b.CommitHash)) } // Post-commits if b.TagVersion != "" { sb.WriteString(fmt.Sprintf("# of Commits Since %v: %v\n", b.TagVersion, b.PostTagCommits)) } else { sb.WriteString(fmt.Sprintf("# of Commits Since %v: %v\n", b.CommitId, b.PostTagCommits)) } sb.WriteString("Uncommitted/Unstaged Changes: ") if b.Dirty { sb.WriteString("yes (dirty/monkeypatched build)\n") } else { sb.WriteString("no (clean build)\n") } if b.TagVersion != "" { sb.WriteString( fmt.Sprintf( "====\nMajor: %v\nMinor: %v\nPatch: %v\n", b.Major, b.Minor, b.Patch, ), ) } sb.WriteString("====\n") sb.WriteString(b.Meta()) ver = sb.String() return } // Short returns a uniquely identifiable version string. func (b *BuildInfo) Short() (ver string) { ver = b.short return } // Meta returns the build/compile-time info. func (b *BuildInfo) Meta() (meta string) { var sb strings.Builder if b.RealBuildUser != b.BuildUser && b.RealBuildUser != "" { sb.WriteString(fmt.Sprintf("Real Build User: %v\n", b.RealBuildUser)) sb.WriteString(fmt.Sprintf("Sudo Build User: %v\n", b.BuildUser)) } else { sb.WriteString(fmt.Sprintf("Build User: %v\n", b.BuildUser)) } sb.WriteString(fmt.Sprintf("Build Time: %v\nBuild Host: %v\n", b.BuildTime, b.BuildHost)) meta = sb.String() return } // getReMap gets a regex map of map[pattern]match. func (b *BuildInfo) getReMap() (matches map[string]string) { var s string = b.Short() var sections []string if !semver.IsValid(s) { return } sections = strings.Split(s, ".") // The split should contain everything in the third element. // Or, if using a "simplified" semver, the last element. matches = make(map[string]string) for idx, str := range patchRe.FindStringSubmatch(sections[len(sections)-1]) { matches[patchRe.SubexpNames()[idx]] = str } return }