Repository: gohugoio/hugo (language: go)

Issue:
Use Go's BuildInfo to produce (some of) the output of "hugo version" etc.
https://pkg.go.dev/runtime/debug#BuildInfo


Discussion / hints:

Fix patch:
diff --git a/common/hugo/hugo.go b/common/hugo/hugo.go
index 5bbfe7c6538..2c6e5f2a0e3 100644
--- a/common/hugo/hugo.go
+++ b/common/hugo/hugo.go
@@ -21,6 +21,7 @@ import (
 	"runtime/debug"
 	"sort"
 	"strings"
+	"sync"
 	"time"
 
 	"github.com/gohugoio/hugo/hugofs/files"
@@ -37,13 +38,6 @@ const (
 )
 
 var (
-	// commitHash contains the current Git revision.
-	// Use mage to build to make sure this gets set.
-	commitHash string
-
-	// buildDate contains the date of the current build.
-	buildDate string
-
 	// vendorInfo contains vendor notes about the current build.
 	vendorInfo string
 )
@@ -90,6 +84,17 @@ func NewInfo(environment string, deps []*Dependency) Info {
 	if environment == "" {
 		environment = EnvironmentProduction
 	}
+	var (
+		commitHash string
+		buildDate  string
+	)
+
+	bi := getBuildInfo()
+	if bi != nil {
+		commitHash = bi.Revision
+		buildDate = bi.RevisionTime
+	}
+
 	return Info{
 		CommitHash:  commitHash,
 		BuildDate:   buildDate,
@@ -125,6 +130,52 @@ func GetExecEnviron(workDir string, cfg config.Provider, fs afero.Fs) []string {
 	return env
 }
 
+type buildInfo struct {
+	VersionControlSystem string
+	Revision             string
+	RevisionTime         string
+	Modified             bool
+
+	GoOS   string
+	GoArch string
+
+	*debug.BuildInfo
+}
+
+var bInfo *buildInfo
+var bInfoInit sync.Once
+
+func getBuildInfo() *buildInfo {
+	bInfoInit.Do(func() {
+		bi, ok := debug.ReadBuildInfo()
+		if !ok {
+			return
+		}
+
+		bInfo = &buildInfo{BuildInfo: bi}
+
+		for _, s := range bInfo.Settings {
+			switch s.Key {
+			case "vcs":
+				bInfo.VersionControlSystem = s.Value
+			case "vcs.revision":
+				bInfo.Revision = s.Value
+			case "vcs.time":
+				bInfo.RevisionTime = s.Value
+			case "vcs.modified":
+				bInfo.Modified = s.Value == "true"
+			case "GOOS":
+				bInfo.GoOS = s.Value
+			case "GOARCH":
+				bInfo.GoArch = s.Value
+			}
+		}
+
+	})
+
+	return bInfo
+}
+
 // GetDependencyList returns a sorted dependency list on the format package="version".
 // It includes both Go dependencies and (a manually maintained) list of C(++) dependencies.
 func GetDependencyList() []string {
@@ -143,8 +194,8 @@ func GetDependencyList() []string {
 		)
 	}
 
-	bi, ok := debug.ReadBuildInfo()
-	if !ok {
+	bi := getBuildInfo()
+	if bi == nil {
 		return deps
 	}
 
diff --git a/common/hugo/version.go b/common/hugo/version.go
index 531f4483dfa..b085744c918 100644
--- a/common/hugo/version.go
+++ b/common/hugo/version.go
@@ -131,16 +131,21 @@ func BuildVersionString() string {
 	program := "hugo"
 
 	version := "v" + CurrentVersion.String()
-	if commitHash != "" {
-		version += "-" + strings.ToUpper(commitHash)
+
+	bi := getBuildInfo()
+	if bi == nil {
+		return version
+	}
+	if bi.Revision != "" {
+		version += "-" + bi.Revision
 	}
 	if IsExtended {
 		version += "+extended"
 	}
 
-	osArch := runtime.GOOS + "/" + runtime.GOARCH
+	osArch := bi.GoOS + "/" + bi.GoArch
 
-	date := buildDate
+	date := bi.RevisionTime
 	if date == "" {
 		date = "unknown"
 	}
diff --git a/goreleaser.yml b/goreleaser.yml
index af887e512cf..0d1389b6a03 100644
--- a/goreleaser.yml
+++ b/goreleaser.yml
@@ -9,7 +9,7 @@ builds:
   -
     binary: hugo
     id: hugo
-    ldflags: -s -w -X github.com/gohugoio/hugo/common/hugo.buildDate={{.Date}} -X github.com/gohugoio/hugo/common/hugo.commitHash={{ .ShortCommit }} -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio
+    ldflags: -s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio
     env:
       - CGO_ENABLED=0
     flags:
@@ -32,7 +32,7 @@ builds:
   -
       binary: hugo
       id: hugo_unix
-      ldflags: -s -w -X github.com/gohugoio/hugo/common/hugo.buildDate={{.Date}} -X github.com/gohugoio/hugo/common/hugo.commitHash={{ .ShortCommit }} -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio
+      ldflags: -s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio
       env:
         - CGO_ENABLED=0
       flags:
@@ -49,7 +49,7 @@ builds:
     binary: hugo
     id: hugo_extended_windows
     ldflags:
-      - -s -w -X github.com/gohugoio/hugo/common/hugo.buildDate={{.Date}} -X github.com/gohugoio/hugo/common/hugo.commitHash={{ .ShortCommit }} -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio
+      - -s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio
       - "-extldflags '-static'"
     env:
       - CGO_ENABLED=1
@@ -66,7 +66,7 @@ builds:
       - amd64
   - binary: hugo
     id: hugo_extended_darwin
-    ldflags: -s -w -X github.com/gohugoio/hugo/common/hugo.buildDate={{.Date}} -X github.com/gohugoio/hugo/common/hugo.commitHash={{ .ShortCommit }} -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio
+    ldflags: -s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio
     env:
       - CGO_ENABLED=1
       - CC=o64-clang
@@ -83,7 +83,7 @@ builds:
       - arm64
   - binary: hugo
     id: hugo_extended_linux
-    ldflags: -s -w -X github.com/gohugoio/hugo/common/hugo.buildDate={{.Date}} -X github.com/gohugoio/hugo/common/hugo.commitHash={{ .ShortCommit }} -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio
+    ldflags: -s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio
     env:
       - CGO_ENABLED=1
     flags:
diff --git a/magefile.go b/magefile.go
index a406664cb73..c016a57e47c 100644
--- a/magefile.go
+++ b/magefile.go
@@ -25,10 +25,10 @@ import (
 
 const (
 	packageName  = "github.com/gohugoio/hugo"
-	noGitLdflags = "-X $PACKAGE/common/hugo.buildDate=$BUILD_DATE"
+	noGitLdflags = "-X github.com/gohugoio/hugo/common/hugo.vendorInfo=mage"
 )
 
-var ldflags = "-X $PACKAGE/common/hugo.commitHash=$COMMIT_HASH -X $PACKAGE/common/hugo.buildDate=$BUILD_DATE"
+var ldflags = noGitLdflags
 
 // allow user to override go executable by running as GOEXE=xxx make ... on unix-like systems
 var goexe = "go"


Test patch:
diff --git a/common/hugo/hugo_test.go b/common/hugo/hugo_test.go
index ff36cab7cef..3bc95684b8d 100644
--- a/common/hugo/hugo_test.go
+++ b/common/hugo/hugo_test.go
@@ -27,8 +27,12 @@ func TestHugoInfo(t *testing.T) {
 
 	c.Assert(hugoInfo.Version(), qt.Equals, CurrentVersion.Version())
 	c.Assert(fmt.Sprintf("%T", VersionString("")), qt.Equals, fmt.Sprintf("%T", hugoInfo.Version()))
-	c.Assert(hugoInfo.CommitHash, qt.Equals, commitHash)
-	c.Assert(hugoInfo.BuildDate, qt.Equals, buildDate)
+
+	bi := getBuildInfo()
+	if bi != nil {
+		c.Assert(hugoInfo.CommitHash, qt.Equals, bi.Revision)
+		c.Assert(hugoInfo.BuildDate, qt.Equals, bi.RevisionTime)
+	}
 	c.Assert(hugoInfo.Environment, qt.Equals, "production")
 	c.Assert(string(hugoInfo.Generator()), qt.Contains, fmt.Sprintf("Hugo %s", hugoInfo.Version()))
 	c.Assert(hugoInfo.IsProduction(), qt.Equals, true)