github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/libgo/go/runtime/debug/mod.go (about)

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package debug
     6  
     7  import (
     8  	"strings"
     9  	_ "unsafe" // for go:linkname
    10  )
    11  
    12  // exported from runtime
    13  func modinfo() string
    14  
    15  // ReadBuildInfo returns the build information embedded
    16  // in the running binary. The information is available only
    17  // in binaries built with module support.
    18  func ReadBuildInfo() (info *BuildInfo, ok bool) {
    19  	return readBuildInfo(modinfo())
    20  }
    21  
    22  // BuildInfo represents the build information read from
    23  // the running binary.
    24  type BuildInfo struct {
    25  	Path string    // The main package path
    26  	Main Module    // The module containing the main package
    27  	Deps []*Module // Module dependencies
    28  }
    29  
    30  // Module represents a module.
    31  type Module struct {
    32  	Path    string  // module path
    33  	Version string  // module version
    34  	Sum     string  // checksum
    35  	Replace *Module // replaced by this module
    36  }
    37  
    38  func readBuildInfo(data string) (*BuildInfo, bool) {
    39  	if len(data) < 32 {
    40  		return nil, false
    41  	}
    42  	data = data[16 : len(data)-16]
    43  
    44  	const (
    45  		pathLine = "path\t"
    46  		modLine  = "mod\t"
    47  		depLine  = "dep\t"
    48  		repLine  = "=>\t"
    49  	)
    50  
    51  	info := &BuildInfo{}
    52  
    53  	var line string
    54  	// Reverse of cmd/go/internal/modload.PackageBuildInfo
    55  	for len(data) > 0 {
    56  		i := strings.IndexByte(data, '\n')
    57  		if i < 0 {
    58  			break
    59  		}
    60  		line, data = data[:i], data[i+1:]
    61  		switch {
    62  		case strings.HasPrefix(line, pathLine):
    63  			elem := line[len(pathLine):]
    64  			info.Path = elem
    65  		case strings.HasPrefix(line, modLine):
    66  			elem := strings.Split(line[len(modLine):], "\t")
    67  			if len(elem) != 3 {
    68  				return nil, false
    69  			}
    70  			info.Main = Module{
    71  				Path:    elem[0],
    72  				Version: elem[1],
    73  				Sum:     elem[2],
    74  			}
    75  		case strings.HasPrefix(line, depLine):
    76  			elem := strings.Split(line[len(depLine):], "\t")
    77  			if len(elem) != 2 && len(elem) != 3 {
    78  				return nil, false
    79  			}
    80  			sum := ""
    81  			if len(elem) == 3 {
    82  				sum = elem[2]
    83  			}
    84  			info.Deps = append(info.Deps, &Module{
    85  				Path:    elem[0],
    86  				Version: elem[1],
    87  				Sum:     sum,
    88  			})
    89  		case strings.HasPrefix(line, repLine):
    90  			elem := strings.Split(line[len(repLine):], "\t")
    91  			if len(elem) != 3 {
    92  				return nil, false
    93  			}
    94  			last := len(info.Deps) - 1
    95  			if last < 0 {
    96  				return nil, false
    97  			}
    98  			info.Deps[last].Replace = &Module{
    99  				Path:    elem[0],
   100  				Version: elem[1],
   101  				Sum:     elem[2],
   102  			}
   103  		}
   104  	}
   105  	return info, true
   106  }