Source file src/cmd/go/internal/doc/mod.go

     1  // Copyright 2024 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 doc
     6  
     7  import (
     8  	"context"
     9  	"debug/buildinfo"
    10  	"fmt"
    11  	"go/build"
    12  	"os/exec"
    13  
    14  	"cmd/go/internal/load"
    15  	"cmd/go/internal/modload"
    16  )
    17  
    18  // loadVersioned loads a package at a specific version.
    19  func loadVersioned(ctx context.Context, pkgPath, version string) (*build.Package, error) {
    20  	loaderState := modload.NewState()
    21  	loaderState.ForceUseModules = true
    22  	loaderState.RootMode = modload.NoRoot
    23  	modload.Init(loaderState)
    24  
    25  	var opts load.PackageOpts
    26  	args := []string{
    27  		fmt.Sprintf("%s@%s", pkgPath, version),
    28  	}
    29  	pkgs, err := load.PackagesAndErrorsOutsideModule(loaderState, ctx, opts, args)
    30  	if err != nil {
    31  		return nil, err
    32  	}
    33  	if len(pkgs) != 1 {
    34  		return nil, fmt.Errorf("incorrect number of packages: want 1, got %d", len(pkgs))
    35  	}
    36  	return pkgs[0].Internal.Build, nil
    37  }
    38  
    39  // inferVersion checks if the argument matches a command on $PATH and returns its module path and version.
    40  func inferVersion(arg string) (pkgPath, version string, ok bool) {
    41  	path, err := exec.LookPath(arg)
    42  	if err != nil {
    43  		return "", "", false
    44  	}
    45  	bi, err := buildinfo.ReadFile(path)
    46  	if err != nil {
    47  		return "", "", false
    48  	}
    49  	if bi.Main.Path == "" || bi.Main.Version == "" {
    50  		return "", "", false
    51  	}
    52  	// bi.Path is the package path for the main package.
    53  	return bi.Path, bi.Main.Version, true
    54  }
    55  

View as plain text