package cli import ( "errors" "fmt" "io" "runtime/debug" "strings" "github.com/spf13/cobra" ) // ErrNoBuildInfo is returned by `sutil info` when the binary carries no // Go build information, which only happens for binaries not built with // module support. var ErrNoBuildInfo = errors.New("sutil: no build information in this binary") // noConfigFile is what `sutil info` prints when no config file was loaded. const noConfigFile = "(none)" // newInfoCommand returns `sutil info`, which prints the build version, the // Go toolchain version, the module path, the configuration file in use, // and the VCS metadata recorded by the Go toolchain at build time. func newInfoCommand(a *app) *cobra.Command { return &cobra.Command{ Use: "info", Short: "Print build information", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { return writeBuildInfo( cmd.OutOrStdout(), a.params.Version, a.configFileUsed(), ) }, } } // writeBuildInfo writes one "key: value" line per fact to w. func writeBuildInfo(w io.Writer, version, configFile string) error { info, ok := debug.ReadBuildInfo() if !ok { return ErrNoBuildInfo } if configFile == "" { configFile = noConfigFile } lines := []string{ "version: " + version, "go: " + info.GoVersion, "module: " + info.Main.Path, "config: " + configFile, } for _, setting := range info.Settings { if strings.HasPrefix(setting.Key, "vcs.") { lines = append(lines, setting.Key+": "+setting.Value) } } _, err := fmt.Fprintln(w, strings.Join(lines, "\n")) return err }