@@ -16,12 +16,14 @@ import (
1616 "text/template"
1717 "time"
1818
19+ "github.com/coreos/go-semver/semver"
1920 "github.com/docker/go-units"
2021 hostagentclient "github.com/lima-vm/lima/pkg/hostagent/api/client"
2122 "github.com/lima-vm/lima/pkg/limayaml"
2223 "github.com/lima-vm/lima/pkg/store/dirnames"
2324 "github.com/lima-vm/lima/pkg/store/filenames"
2425 "github.com/lima-vm/lima/pkg/textutil"
26+ "github.com/sirupsen/logrus"
2527)
2628
2729type Status = string
@@ -56,6 +58,7 @@ type Instance struct {
5658 Config * limayaml.LimaYAML `json:"config,omitempty"`
5759 SSHAddress string `json:"sshAddress,omitempty"`
5860 Protected bool `json:"protected"`
61+ LimaVersion string `json:"limaVersion"`
5962}
6063
6164func (inst * Instance ) LoadYAML () (* limayaml.LimaYAML , error ) {
@@ -167,6 +170,16 @@ func Inspect(instName string) (*Instance, error) {
167170 }
168171 }
169172 }
173+
174+ limaVersionFile := filepath .Join (instDir , filenames .LimaVersion )
175+ if version , err := os .ReadFile (limaVersionFile ); err == nil {
176+ inst .LimaVersion = strings .TrimSpace (string (version ))
177+ if _ , err = parseLimaVersion (inst .LimaVersion ); err != nil {
178+ logrus .Warnf ("treating lima version %q from %q as very latest release" , inst .LimaVersion , limaVersionFile )
179+ }
180+ } else if ! errors .Is (err , os .ErrNotExist ) {
181+ inst .Errors = append (inst .Errors , err )
182+ }
170183 return inst , nil
171184}
172185
@@ -423,3 +436,36 @@ func (inst *Instance) Unprotect() error {
423436 inst .Protected = false
424437 return nil
425438}
439+
440+ // parseLimaVersion parses a Lima version string by removing the leading "v" character and
441+ // stripping everything from the first "-" forward (which are `git describe` artifacts and
442+ // not semver pre-release markers). So "v0.19.1-16-gf3dc6ed.m" will be parsed as "0.19.1".
443+ func parseLimaVersion (version string ) (* semver.Version , error ) {
444+ version = strings .TrimPrefix (version , "v" )
445+ version , _ , _ = strings .Cut (version , "-" )
446+ return semver .NewVersion (version )
447+ }
448+
449+ // LimaVersionGreaterThan returns true if the Lima version used to create an instance is greater
450+ // than a specific older version. Always returns false if the Lima version is the empty string.
451+ // Unparsable lima versions (like SHA1 commit ids) are treated as the latest version and return true.
452+ // limaVersion is a `github describe` string, not a semantic version. So "0.19.1-16-gf3dc6ed.m"
453+ // will be considered greater than "0.19.1".
454+ func LimaVersionGreaterThan (limaVersion , oldVersion string ) bool {
455+ if limaVersion == "" {
456+ return false
457+ }
458+ version , err := parseLimaVersion (limaVersion )
459+ if err != nil {
460+ return true
461+ }
462+ switch version .Compare (* semver .New (oldVersion )) {
463+ case - 1 :
464+ return false
465+ case + 1 :
466+ return true
467+ case 0 :
468+ return strings .Contains (limaVersion , "-" )
469+ }
470+ panic ("unreachable" )
471+ }
0 commit comments