github.com/ethereum/go-ethereum@v1.16.1/internal/version/version.go (about)

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