Source file src/cmd/go/internal/toolchain/path_windows.go

     1  // Copyright 2023 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 toolchain
     6  
     7  import (
     8  	"io/fs"
     9  	"os"
    10  	"path/filepath"
    11  	"strings"
    12  	"sync"
    13  
    14  	"cmd/go/internal/gover"
    15  )
    16  
    17  // pathExts is a cached PATHEXT list.
    18  var pathExts struct {
    19  	once sync.Once
    20  	list []string
    21  }
    22  
    23  func initPathExts() {
    24  	var exts []string
    25  	x := os.Getenv(`PATHEXT`)
    26  	if x != "" {
    27  		for _, e := range strings.Split(strings.ToLower(x), `;`) {
    28  			if e == "" {
    29  				continue
    30  			}
    31  			if e[0] != '.' {
    32  				e = "." + e
    33  			}
    34  			exts = append(exts, e)
    35  		}
    36  	} else {
    37  		exts = []string{".com", ".exe", ".bat", ".cmd"}
    38  	}
    39  	pathExts.list = exts
    40  }
    41  
    42  // pathDirs returns the directories in the system search path.
    43  func pathDirs() []string {
    44  	return filepath.SplitList(os.Getenv("PATH"))
    45  }
    46  
    47  // pathVersion returns the Go version implemented by the file
    48  // described by de and info in directory dir.
    49  // The analysis only uses the name itself; it does not run the program.
    50  func pathVersion(dir string, de fs.DirEntry, info fs.FileInfo) (string, bool) {
    51  	pathExts.once.Do(initPathExts)
    52  	name, _, ok := cutExt(de.Name(), pathExts.list)
    53  	if !ok {
    54  		return "", false
    55  	}
    56  	v := gover.FromToolchain(name)
    57  	if v == "" {
    58  		return "", false
    59  	}
    60  	return v, true
    61  }
    62  
    63  // cutExt looks for any of the known extensions at the end of file.
    64  // If one is found, cutExt returns the file name with the extension trimmed,
    65  // the extension itself, and true to signal that an extension was found.
    66  // Otherwise cutExt returns file, "", false.
    67  func cutExt(file string, exts []string) (name, ext string, found bool) {
    68  	i := strings.LastIndex(file, ".")
    69  	if i < 0 {
    70  		return file, "", false
    71  	}
    72  	for _, x := range exts {
    73  		if strings.EqualFold(file[i:], x) {
    74  			return file[:i], file[i:], true
    75  		}
    76  	}
    77  	return file, "", false
    78  }
    79  

View as plain text