@@ -44,18 +44,24 @@ type PHPStore struct {
4444
4545// New creates a new PHP store
4646func New (configDir string , reload bool , logger func (msg string , a ... interface {})) * PHPStore {
47- s := & PHPStore {
48- configDir : configDir ,
49- seen : make (map [string ]int ),
50- discoveryLogFunc : logger ,
51- }
47+ s := newEmpty (configDir , logger )
48+
5249 if reload {
5350 _ = os .Remove (filepath .Join (configDir , "php_versions.json" ))
5451 }
5552 s .loadVersions ()
5653 return s
5754}
5855
56+ // newEmpty creates a new "empty" (without loading versions) PHP store
57+ func newEmpty (configDir string , logger func (msg string , a ... interface {})) * PHPStore {
58+ return & PHPStore {
59+ configDir : configDir ,
60+ seen : make (map [string ]int ),
61+ discoveryLogFunc : logger ,
62+ }
63+ }
64+
5965// Versions returns all available PHP versions
6066func (s * PHPStore ) Versions () []* Version {
6167 return s .versions
@@ -136,47 +142,51 @@ func (s *PHPStore) BestVersionForDir(dir string) (*Version, string, string, erro
136142 return s .fallbackVersion ("" )
137143}
138144
139- // bestVersion returns the latest patch version for the given major (X), minor (X.Y), or patch (X.Y.Z)
140- // version can be 7 or 7.1 or 7.1.2
141- // non-symlinked versions have priority
145+ // bestVersion returns the latest patch version for the given major (X),
146+ // minor (X.Y), or patch (X.Y.Z).
147+ // Version can be 7 or 7.1 or 7.1.2 and optionally suffixed with a flavor.
148+ // Non-symlinked versions have priority.
149+ // If the asked version contains a flavor (e.g. "7.4-fpm"), it will only accept
150+ // versions supporting this flavor.
142151// If the asked version is a patch one (X.Y.Z) and is not available, the lookup
143- // will fallback to the last path version for the minor version (X.Y).
152+ // will fallback to the last patch version for the minor version (X.Y).
144153// There's no fallback to the major version because PHP is known to occasionally
145154// break BC in minor versions, so we can't safely fall back.
146155func (s * PHPStore ) bestVersion (versionPrefix , source string ) (* Version , string , string , error ) {
147156 warning := ""
157+ flavor := ""
148158
149- isPatchVersion := false
150- pos := strings .LastIndexByte (versionPrefix , '.' )
151- if pos != strings .IndexByte (versionPrefix , '.' ) {
152- if versionPrefix [pos + 1 :] == "99" {
153- versionPrefix = versionPrefix [:pos ]
154- pos = strings .LastIndexByte (versionPrefix , '.' )
155- } else {
156- isPatchVersion = true
157- }
159+ // Check if versionPrefix has an expected-flavor constraint, if so first do an
160+ // exact match lookup and fallback to a minor version check
161+ if pos := strings .LastIndexByte (versionPrefix , '-' ); pos != - 1 {
162+ flavor = versionPrefix [pos + 1 :]
163+ versionPrefix = versionPrefix [:pos ]
158164 }
159165
160166 // Check if versionPrefix is actually a patch version, if so first do an
161167 // exact match lookup and fallback to a minor version check
162- if isPatchVersion {
168+ if pos := strings . LastIndexByte ( versionPrefix , '.' ); pos != strings . IndexByte ( versionPrefix , '.' ) {
163169 // look for an exact match, the order does not matter here
164170 for _ , v := range s .versions {
165- if v .Version == versionPrefix {
171+ if v .Version == versionPrefix && v .SupportsFlavor (flavor ) {
172+ v .ForceFlavor (flavor )
166173 return v , source , "" , nil
167174 }
168175 }
169176
170177 // exact match not found, fallback to minor version check
171178 newVersionPrefix := versionPrefix [:pos ]
172- warning = fmt .Sprintf (`the current dir requires PHP %s (%s), but this version is not available: fallback to %s` , versionPrefix , source , newVersionPrefix )
179+ if versionPrefix [pos + 1 :] != "99" {
180+ warning = fmt .Sprintf (`the current dir requires PHP %s (%s), but this version is not available: fallback to %s` , versionPrefix , source , newVersionPrefix )
181+ }
173182 versionPrefix = newVersionPrefix
174183 }
175184
176185 // start from the end as versions are always sorted
177186 for i := len (s .versions ) - 1 ; i >= 0 ; i -- {
178187 v := s .versions [i ]
179- if strings .HasPrefix (v .Version , versionPrefix ) {
188+ if strings .HasPrefix (v .Version , versionPrefix ) && v .SupportsFlavor (flavor ) {
189+ v .ForceFlavor (flavor )
180190 return v , source , warning , nil
181191 }
182192 }
0 commit comments