@@ -5,6 +5,7 @@ package resolve
55
66import (
77 "fmt"
8+ "iter"
89 "os"
910 "path"
1011 "strings"
@@ -21,54 +22,100 @@ type ToolVersions struct {
2122 Source string
2223}
2324
25+ // AllVersions takes a set of plugins and a directory and resolves all tools to one or more
26+ // versions. This includes tools without a corresponding plugin.
27+ func AllVersions (conf config.Config , plugins []plugins.Plugin , directory string ) (versions map [string ]ToolVersions , err error ) {
28+ resolvedToolVersions := map [string ]ToolVersions {}
29+ for _ , plugin := range plugins {
30+ version , envVariableName , found := findVersionsInEnv (plugin .Name )
31+ if found {
32+ resolvedToolVersions [plugin .Name ] = ToolVersions {Versions : version , Source : envVariableName }
33+ }
34+ }
35+
36+ for iterDir := range iterDirectories (conf , directory ) {
37+ for _ , plugin := range plugins {
38+ if _ , isPluginResolved := resolvedToolVersions [plugin .Name ]; ! isPluginResolved {
39+ version , found , err := findLegacyVersionsInDir (conf , plugin , iterDir )
40+ if err != nil {
41+ return versions , err
42+ }
43+ if found {
44+ resolvedToolVersions [plugin .Name ] = version
45+ }
46+ }
47+ }
48+
49+ filepath := path .Join (iterDir , conf .DefaultToolVersionsFilename )
50+ if _ , err = os .Stat (filepath ); err == nil {
51+ if allVersions , err := toolversions .GetAllToolsAndVersions (filepath ); err == nil {
52+ for _ , v := range allVersions {
53+ if _ , isPluginResolved := resolvedToolVersions [v .Name ]; ! isPluginResolved {
54+ resolvedToolVersions [v .Name ] = ToolVersions {Versions : v .Versions , Source : conf .DefaultToolVersionsFilename , Directory : iterDir }
55+ }
56+ }
57+ }
58+ }
59+ }
60+ return resolvedToolVersions , nil
61+ }
62+
2463// Version takes a plugin and a directory and resolves the tool to one or more
25- // versions.
64+ // versions. Only returns results for the provided plugin.
2665func Version (conf config.Config , plugin plugins.Plugin , directory string ) (versions ToolVersions , found bool , err error ) {
2766 version , envVariableName , found := findVersionsInEnv (plugin .Name )
2867 if found {
2968 return ToolVersions {Versions : version , Source : envVariableName }, true , nil
3069 }
3170
32- for ! found {
33- versions , found , err = findVersionsInDir (conf , plugin , directory )
71+ for iterDir := range iterDirectories ( conf , directory ) {
72+ versions , found , err = findVersionsInDir (conf , plugin , iterDir )
3473 if err != nil {
3574 return versions , false , err
3675 }
76+ if found {
77+ return versions , found , err
78+ }
79+ }
80+ return versions , found , err
81+ }
3782
38- nextDir := path .Dir (directory )
39- // If current dir and next dir are the same it means we've reached `/` and
40- // have no more parent directories to search.
41- if nextDir == directory {
42- // If no version found, try current users home directory. I'd like to
43- // eventually remove this feature.
44- homeDir , osErr := os .UserHomeDir ()
45- if osErr != nil {
83+ func iterDirectories (conf config.Config , directory string ) iter.Seq [string ] {
84+ return func (yield func (string ) bool ) {
85+ if ! yield (directory ) {
86+ return
87+ }
88+ iterDir := directory
89+ for {
90+ nextDir := path .Dir (iterDir )
91+ // If current dir and next dir are the same it means we've reached `/` and
92+ // have no more parent directories to search.
93+ if nextDir == iterDir {
4694 break
4795 }
48-
49- versions , found , err = findVersionsInDir (conf , plugin , homeDir )
50- break
96+ if ! yield (iterDir ) {
97+ return
98+ }
99+ iterDir = nextDir
100+ }
101+ // If no version found, try current users home directory. I'd like to
102+ // eventually remove this feature.
103+ homeDir := conf .Home
104+ // homeDir, osErr := os.UserHomeDir()
105+ if homeDir != "" {
106+ if ! yield (homeDir ) {
107+ return
108+ }
51109 }
52- directory = nextDir
53110 }
54-
55- return versions , found , err
56111}
57112
58113func findVersionsInDir (conf config.Config , plugin plugins.Plugin , directory string ) (versions ToolVersions , found bool , err error ) {
59- legacyFiles , err := conf . LegacyVersionFile ( )
60- if err != nil {
114+ versions , found , err = findLegacyVersionsInDir ( conf , plugin , directory )
115+ if found || err != nil {
61116 return versions , found , err
62117 }
63118
64- if legacyFiles {
65- versions , found , err := findVersionsInLegacyFile (plugin , directory )
66-
67- if found || err != nil {
68- return versions , found , err
69- }
70- }
71-
72119 filepath := path .Join (directory , conf .DefaultToolVersionsFilename )
73120
74121 if _ , err = os .Stat (filepath ); err == nil {
@@ -81,6 +128,22 @@ func findVersionsInDir(conf config.Config, plugin plugins.Plugin, directory stri
81128 return versions , found , nil
82129}
83130
131+ func findLegacyVersionsInDir (conf config.Config , plugin plugins.Plugin , directory string ) (versions ToolVersions , found bool , err error ) {
132+ legacyFiles , err := conf .LegacyVersionFile ()
133+ if err != nil {
134+ return versions , found , err
135+ }
136+
137+ if legacyFiles {
138+ versions , found , err := findVersionsInLegacyFile (plugin , directory )
139+
140+ if found || err != nil {
141+ return versions , found , err
142+ }
143+ }
144+ return versions , false , nil
145+ }
146+
84147// findVersionsInEnv returns the version from the environment if present
85148func findVersionsInEnv (pluginName string ) ([]string , string , bool ) {
86149 envVariableName := variableVersionName (pluginName )
0 commit comments