github.com/databricks/cli@v0.203.0/internal/build/info.go (about)

     1  package build
     2  
     3  import (
     4  	"fmt"
     5  	"runtime/debug"
     6  	"strconv"
     7  	"sync"
     8  	"time"
     9  
    10  	"golang.org/x/mod/semver"
    11  )
    12  
    13  type Info struct {
    14  	ProjectName string
    15  	Version     string
    16  
    17  	Branch      string
    18  	Tag         string
    19  	ShortCommit string
    20  	FullCommit  string
    21  	CommitTime  time.Time
    22  	Summary     string
    23  
    24  	Major      int64
    25  	Minor      int64
    26  	Patch      int64
    27  	Prerelease string
    28  	IsSnapshot bool
    29  	BuildTime  time.Time
    30  }
    31  
    32  var info Info
    33  
    34  var once sync.Once
    35  
    36  // getDefaultBuildVersion uses build information stored by Go itself
    37  // to synthesize a build version if one wasn't set.
    38  // This is necessary if the binary was not built through goreleaser.
    39  func getDefaultBuildVersion() string {
    40  	bi, ok := debug.ReadBuildInfo()
    41  	if !ok {
    42  		panic("unable to read build info")
    43  	}
    44  
    45  	m := make(map[string]string)
    46  	for _, s := range bi.Settings {
    47  		m[s.Key] = s.Value
    48  	}
    49  
    50  	out := "0.0.0-dev"
    51  
    52  	// Append revision as build metadata.
    53  	if v, ok := m["vcs.revision"]; ok {
    54  		// First 12 characters of the commit SHA is plenty to identify one.
    55  		out = fmt.Sprintf("%s+%s", out, v[0:12])
    56  	}
    57  
    58  	return out
    59  }
    60  
    61  func initialize() {
    62  	// If buildVersion is empty it means the binary was NOT built through goreleaser.
    63  	// We try to pull version information from debug.BuildInfo().
    64  	if buildVersion == "" {
    65  		buildVersion = getDefaultBuildVersion()
    66  	}
    67  
    68  	// Confirm that buildVersion is valid semver.
    69  	// Note that the semver package requires a leading 'v'.
    70  	if !semver.IsValid("v" + buildVersion) {
    71  		panic(fmt.Sprintf(`version is not a valid semver string: "%s"`, buildVersion))
    72  	}
    73  
    74  	info = Info{
    75  		ProjectName: buildProjectName,
    76  		Version:     buildVersion,
    77  
    78  		Branch:      buildBranch,
    79  		Tag:         buildTag,
    80  		ShortCommit: buildShortCommit,
    81  		FullCommit:  buildFullCommit,
    82  		CommitTime:  parseTime(buildCommitTimestamp),
    83  		Summary:     buildSummary,
    84  
    85  		Major:      parseInt(buildMajor),
    86  		Minor:      parseInt(buildMinor),
    87  		Patch:      parseInt(buildPatch),
    88  		Prerelease: buildPrerelease,
    89  		IsSnapshot: parseBool(buildIsSnapshot),
    90  		BuildTime:  parseTime(buildTimestamp),
    91  	}
    92  }
    93  
    94  func GetInfo() Info {
    95  	once.Do(initialize)
    96  	return info
    97  }
    98  
    99  func parseInt(s string) int64 {
   100  	i, err := strconv.ParseInt(s, 10, 64)
   101  	if err != nil {
   102  		panic(err)
   103  	}
   104  	return i
   105  }
   106  
   107  func parseBool(s string) bool {
   108  	b, err := strconv.ParseBool(s)
   109  	if err != nil {
   110  		panic(err)
   111  	}
   112  	return b
   113  }
   114  
   115  func parseTime(s string) time.Time {
   116  	return time.Unix(parseInt(s), 0)
   117  }