From a43508218068cf3e8ed3aec75262a648c51e03cf Mon Sep 17 00:00:00 2001 From: "Nathan J. Mehl" Date: Tue, 9 Jul 2024 16:42:47 -0400 Subject: [PATCH] attempt to handle --version even in untagged builds If we are installed via `go-install` rather than downloading a tagged binary from github, the `Tag` etc variables will all be empty, and therefore the `--version` flag is diked out. But there is a way around this! If the version info is not filled in via build-time flags, use `debug.BuildInfo` to introspect as much information as we can out of the module metadata: ``` $ go install github.com/odenio/goimports-reviser/v3@v3.6.6-pre5 go: downloading github.com/odenio/goimports-reviser/v3 v3.6.6-pre5 $ ~/go/bin/goimports-reviser --version version: 3.6.6-pre5 built with: go1.22.4 tag: v3.6.6-pre5 commit: n/a source: github.com/odenio/goimports-reviser/v3 ``` Additionally, add a `--version-only` flag that prints only the version string itself, handy for use in shell pipelines. Can be used on its own or in combination with the `--version` flag: ``` $ ./go/bin/goimports-reviser --version-only 3.6.6-pre5 ``` --- main.go | 93 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 80 insertions(+), 13 deletions(-) diff --git a/main.go b/main.go index b376175..26847b6 100644 --- a/main.go +++ b/main.go @@ -10,6 +10,7 @@ import ( "os/user" "path" "path/filepath" + "runtime/debug" "strings" "github.com/incu6us/goimports-reviser/v3/helper" @@ -19,6 +20,7 @@ import ( const ( projectNameArg = "project-name" versionArg = "version" + versionOnlyArg = "version-only" removeUnusedImportsArg = "rm-unused" setAliasArg = "set-alias" companyPkgPrefixesArg = "company-prefixes" @@ -31,6 +33,7 @@ const ( useCacheArg = "use-cache" applyToGeneratedFiles = "apply-to-generated-files" excludesArg = "excludes" + modulePath = "github.com/incu6us/goimports-reviser" // Deprecated options localArg = "local" @@ -45,6 +48,7 @@ var ( GoVersion string shouldShowVersion *bool + shouldShowVersionOnly *bool shouldRemoveUnusedImports *bool shouldSetAlias *bool shouldFormat *bool @@ -168,13 +172,18 @@ Optional parameter.`, "Apply imports sorting and formatting(if the option is set) to generated files. Generated file is a file with first comment which starts with comment '// Code generated'. Optional parameter.", ) - if Tag != "" { - shouldShowVersion = flag.Bool( - versionArg, - false, - "Show version.", - ) - } + shouldShowVersion = flag.Bool( + versionArg, + false, + "Show version information", + ) + + shouldShowVersionOnly = flag.Bool( + versionOnlyArg, + false, + "Show only the version string", + ) + } func printUsage() { @@ -185,27 +194,85 @@ func printUsage() { flag.PrintDefaults() } +func getBuildInfo() *debug.BuildInfo { + bi, ok := debug.ReadBuildInfo() + if !ok { + return nil + } + return bi +} + +func getMyModuleInfo(bi *debug.BuildInfo) (*debug.Module, error) { + if bi == nil { + return nil, fmt.Errorf("no build info available") + } + if bi.Main.Path != "" { + return &bi.Main, nil + } + for _, m := range bi.Deps { + if strings.HasPrefix(m.Path, modulePath) { + return m, nil + } + } + return nil, fmt.Errorf("weird: no matching dependency found in build info") +} + func printVersion() { + if Tag != "" { + fmt.Printf( + "version: %s\nbuilt with: %s\ntag: %s\ncommit: %s\nsource: %s\n", + strings.TrimPrefix(Tag, "v"), + GoVersion, + Tag, + Commit, + SourceURL, + ) + return + } + bi := getBuildInfo() + myModule, err := getMyModuleInfo(bi) + if err != nil { + log.Fatalf("failed to get my module info: %s", err) + } fmt.Printf( - "version: %s\nbuild with: %s\ntag: %s\ncommit: %s\nsource: %s\n", - strings.TrimPrefix(Tag, "v"), - GoVersion, - Tag, - Commit, - SourceURL, + "version: %s\nbuilt with: %s\ntag: %s\ncommit: %s\nsource: %s\n", + strings.TrimPrefix(myModule.Version, "v"), + bi.GoVersion, + myModule.Version, + "n/a", + myModule.Path, ) } +func printVersionOnly() { + if Tag != "" { + fmt.Println(strings.TrimPrefix(Tag, "v")) + return + } + bi := getBuildInfo() + myModule, err := getMyModuleInfo(bi) + if err != nil { + log.Fatalf("failed to get my module info: %s", err) + } + fmt.Println(strings.TrimPrefix(myModule.Version, "v")) +} + func main() { deprecatedMessagesCh := make(chan string, 10) flag.Parse() + if shouldShowVersionOnly != nil && *shouldShowVersionOnly { + printVersionOnly() + return + } + if shouldShowVersion != nil && *shouldShowVersion { printVersion() return } originPath := flag.Arg(0) + if filePath != "" { deprecatedMessagesCh <- fmt.Sprintf("-%s is deprecated. Put file name as last argument to the command(Example: goimports-reviser -rm-unused -set-alias -format goimports-reviser/main.go)", filePathArg) originPath = filePath