github.com/ava-labs/subnet-evm@v0.6.4/internal/version/version.go (about) 1 // (c) 2023, Ava Labs, Inc. 2 // 3 // This file is a derived work, based on the go-ethereum library whose original 4 // notices appear below. 5 // 6 // It is distributed under a license compatible with the licensing terms of the 7 // original code from which it is derived. 8 // 9 // Much love to the original authors for their work. 10 // ********** 11 // Copyright 2022 The go-ethereum Authors 12 // This file is part of the go-ethereum library. 13 // 14 // The go-ethereum library is free software: you can redistribute it and/or modify 15 // it under the terms of the GNU Lesser General Public License as published by 16 // the Free Software Foundation, either version 3 of the License, or 17 // (at your option) any later version. 18 // 19 // The go-ethereum library is distributed in the hope that it will be useful, 20 // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 // GNU Lesser General Public License for more details. 23 // 24 // You should have received a copy of the GNU Lesser General Public License 25 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 26 27 // Package version implements reading of build version information. 28 package version 29 30 import ( 31 "fmt" 32 "runtime" 33 "runtime/debug" 34 "strings" 35 36 "github.com/ava-labs/subnet-evm/params" 37 ) 38 39 const ourPath = "github.com/ava-labs/subnet-evm" // Path to our module 40 41 // These variables are set at build-time by the linker when the build is 42 // done by build/ci.go. 43 var gitCommit, gitDate string 44 45 // VCSInfo represents the git repository state. 46 type VCSInfo struct { 47 Commit string // head commit hash 48 Date string // commit time in YYYYMMDD format 49 Dirty bool 50 } 51 52 // VCS returns version control information of the current executable. 53 func VCS() (VCSInfo, bool) { 54 if gitCommit != "" { 55 // Use information set by the build script if present. 56 return VCSInfo{Commit: gitCommit, Date: gitDate}, true 57 } 58 if buildInfo, ok := debug.ReadBuildInfo(); ok { 59 if buildInfo.Main.Path == ourPath { 60 return buildInfoVCS(buildInfo) 61 } 62 } 63 return VCSInfo{}, false 64 } 65 66 // ClientName creates a software name/version identifier according to common 67 // conventions in the Ethereum p2p network. 68 func ClientName(clientIdentifier string) string { 69 git, _ := VCS() 70 return fmt.Sprintf("%s/v%v/%v-%v/%v", 71 strings.Title(clientIdentifier), 72 params.VersionWithCommit(git.Commit, git.Date), 73 runtime.GOOS, runtime.GOARCH, 74 runtime.Version(), 75 ) 76 } 77 78 // runtimeInfo returns build and platform information about the current binary. 79 // 80 // If the package that is currently executing is a prefixed by our go-ethereum 81 // module path, it will print out commit and date VCS information. Otherwise, 82 // it will assume it's imported by a third-party and will return the imported 83 // version and whether it was replaced by another module. 84 func Info() (version, vcs string) { 85 version = params.VersionWithMeta 86 buildInfo, ok := debug.ReadBuildInfo() 87 if !ok { 88 return version, "" 89 } 90 version = versionInfo(buildInfo) 91 if status, ok := VCS(); ok { 92 modified := "" 93 if status.Dirty { 94 modified = " (dirty)" 95 } 96 commit := status.Commit 97 if len(commit) > 8 { 98 commit = commit[:8] 99 } 100 vcs = commit + "-" + status.Date + modified 101 } 102 return version, vcs 103 } 104 105 // versionInfo returns version information for the currently executing 106 // implementation. 107 // 108 // Depending on how the code is instantiated, it returns different amounts of 109 // information. If it is unable to determine which module is related to our 110 // package it falls back to the hardcoded values in the params package. 111 func versionInfo(info *debug.BuildInfo) string { 112 // If the main package is from our repo, prefix version with "geth". 113 if strings.HasPrefix(info.Path, ourPath) { 114 return fmt.Sprintf("geth %s", info.Main.Version) 115 } 116 // Not our main package, so explicitly print out the module path and 117 // version. 118 var version string 119 if info.Main.Path != "" && info.Main.Version != "" { 120 // These can be empty when invoked with "go run". 121 version = fmt.Sprintf("%s@%s ", info.Main.Path, info.Main.Version) 122 } 123 mod := findModule(info, ourPath) 124 if mod == nil { 125 // If our module path wasn't imported, it's unclear which 126 // version of our code they are running. Fallback to hardcoded 127 // version. 128 return version + fmt.Sprintf("geth %s", params.VersionWithMeta) 129 } 130 // Our package is a dependency for the main module. Return path and 131 // version data for both. 132 version += fmt.Sprintf("%s@%s", mod.Path, mod.Version) 133 if mod.Replace != nil { 134 // If our package was replaced by something else, also note that. 135 version += fmt.Sprintf(" (replaced by %s@%s)", mod.Replace.Path, mod.Replace.Version) 136 } 137 return version 138 } 139 140 // findModule returns the module at path. 141 func findModule(info *debug.BuildInfo, path string) *debug.Module { 142 if info.Path == ourPath { 143 return &info.Main 144 } 145 for _, mod := range info.Deps { 146 if mod.Path == path { 147 return mod 148 } 149 } 150 return nil 151 }