github.com/danhper/asdf-exec@v0.1.3-0.20230723223931-b71340b83071/version_manager.go (about)

     1  package main
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"os/exec"
     7  	"path"
     8  	"strings"
     9  )
    10  
    11  const (
    12  	toolVersionsFile      string = ".tool-versions"
    13  	legacyFileNamesScript string = "list-legacy-filenames"
    14  	parseLegacyFileScript string = "parse-legacy-file"
    15  )
    16  
    17  var legacyFileNamesCache = make(map[string][]string)
    18  
    19  // ParseVersion parses the raw version
    20  func ParseVersion(rawVersions string) []string {
    21  	var versions []string
    22  	for _, version := range strings.Split(rawVersions, " ") {
    23  		version = strings.TrimSpace(version)
    24  		if len(version) > 0 {
    25  			versions = append(versions, version)
    26  		}
    27  	}
    28  	return versions
    29  }
    30  
    31  // FindVersionsInEnv returns the version from the environment if present
    32  func FindVersionsInEnv(plugin string) ([]string, bool) {
    33  	envVariableName := "ASDF_" + strings.ToUpper(plugin) + "_VERSION"
    34  	versionString := os.Getenv(envVariableName)
    35  	if versionString == "" {
    36  		return nil, false
    37  	}
    38  	return ParseVersion(versionString), true
    39  }
    40  
    41  // GetLegacyFilenames retrieves the legacy filenames of the plugin
    42  func GetLegacyFilenames(plugin string) ([]string, error) {
    43  	pluginPath := GetPluginPath(plugin)
    44  	listFilenames := path.Join(pluginPath, "bin", legacyFileNamesScript)
    45  	if _, err := os.Stat(listFilenames); err != nil {
    46  		return []string{}, nil
    47  	}
    48  	result, err := exec.Command("bash", listFilenames).Output()
    49  	if err != nil {
    50  		return nil, err
    51  	}
    52  	return strings.Split(string(result), " "), nil
    53  }
    54  
    55  // GetVersionsFromLegacyfile returns the versions in the legacy file
    56  func GetVersionsFromLegacyfile(plugin string, legacyFilepath string) (versions []string, err error) {
    57  	pluginPath := GetPluginPath(plugin)
    58  	parseScriptPath := path.Join(pluginPath, "bin", parseLegacyFileScript)
    59  
    60  	var rawVersions []byte
    61  	if _, err := os.Stat(parseScriptPath); err == nil {
    62  		rawVersions, err = exec.Command("bash", parseScriptPath, legacyFilepath).Output()
    63  	} else {
    64  		rawVersions, err = ioutil.ReadFile(legacyFilepath)
    65  	}
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  
    70  	for _, version := range strings.Split(string(rawVersions), " ") {
    71  		versions = append(versions, strings.TrimSpace(version))
    72  	}
    73  	return
    74  }
    75  
    76  // FindVersionsInLegacyFile returns the version from the legacy file if found
    77  func FindVersionsInLegacyFile(dir string, plugin string) (versions []string, found bool, err error) {
    78  	var legacyFileNames []string
    79  	if names, ok := legacyFileNamesCache[plugin]; ok {
    80  		legacyFileNames = names
    81  	} else {
    82  		legacyFileNames, err = GetLegacyFilenames(plugin)
    83  		if err != nil {
    84  			return
    85  		}
    86  		legacyFileNamesCache[plugin] = legacyFileNames
    87  	}
    88  	for _, filename := range legacyFileNames {
    89  		filename = strings.TrimSpace(filename)
    90  		filepath := path.Join(dir, filename)
    91  		if _, err := os.Stat(filepath); err == nil {
    92  			versions, err := GetVersionsFromLegacyfile(plugin, filepath)
    93  			if len(versions) == 0 || (len(versions) == 1 && versions[0] == "") {
    94  				return nil, false, nil
    95  			}
    96  			return versions, err == nil, err
    97  		}
    98  	}
    99  	return nil, false, nil
   100  }
   101  
   102  // FindVersionsInDir returns the version from the current directory
   103  func FindVersionsInDir(dir string, plugin string, config Config) ([]string, bool, error) {
   104  	filepath := path.Join(dir, toolVersionsFile)
   105  	if _, err := os.Stat(filepath); err == nil {
   106  		versions, found, err := FindVersionsInToolFile(filepath, plugin)
   107  		if found || err != nil {
   108  			return versions, found, err
   109  		}
   110  	}
   111  	if config.LegacyVersionFile {
   112  		return FindVersionsInLegacyFile(dir, plugin)
   113  
   114  	}
   115  	return nil, false, nil
   116  }
   117  
   118  // FindVersionsInToolFileContent returns the version of a plugin from the toolsfile content
   119  func FindVersionsInToolFileContent(plugin string, content string) ([]string, bool) {
   120  	for _, line := range ReadLines(content) {
   121  		tokens := strings.SplitN(line, " ", 2)
   122  		if strings.TrimSpace(tokens[0]) == plugin {
   123  			return ParseVersion(tokens[1]), true
   124  		}
   125  	}
   126  	return nil, false
   127  }
   128  
   129  // FindVersionsInToolFile returns the version of a plugin from the toolsfile at the given path
   130  func FindVersionsInToolFile(filepath string, plugin string) ([]string, bool, error) {
   131  	content, err := ioutil.ReadFile(filepath)
   132  	if err != nil {
   133  		return nil, false, err
   134  	}
   135  	versions, found := FindVersionsInToolFileContent(plugin, string(content))
   136  	return versions, found, nil
   137  }
   138  
   139  // FindVersions returns the current versions for the plugin
   140  func FindVersions(plugin string, config Config) ([]string, bool, error) {
   141  	version, found := FindVersionsInEnv(plugin)
   142  	dir, err := os.Getwd()
   143  	if err != nil {
   144  		return nil, false, err
   145  	}
   146  	for !found {
   147  		version, found, err = FindVersionsInDir(dir, plugin, config)
   148  		if err != nil {
   149  			return nil, false, err
   150  		}
   151  		nextDir := path.Dir(dir)
   152  		if nextDir == dir {
   153  			break
   154  		}
   155  		dir = nextDir
   156  	}
   157  	if !found {
   158  		homeToolsFile := path.Join(os.Getenv("HOME"), toolVersionsFile)
   159  		if _, err := os.Stat(homeToolsFile); err == nil {
   160  			version, found, err = FindVersionsInToolFile(homeToolsFile, plugin)
   161  		}
   162  	}
   163  	return version, found, err
   164  }