github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/pkg/platform/runtime/store/marker.go (about) 1 package store 2 3 import ( 4 "encoding/json" 5 "path/filepath" 6 "strings" 7 8 "github.com/ActiveState/cli/internal/constants" 9 "github.com/ActiveState/cli/internal/errs" 10 "github.com/ActiveState/cli/internal/fileutils" 11 "github.com/ActiveState/cli/internal/logging" 12 "github.com/go-openapi/strfmt" 13 ) 14 15 type Marker struct { 16 CommitID string `json:"commitID"` 17 Namespace string `json:"namespace"` 18 Version string `json:"version"` 19 } 20 21 func (s *Store) markerFile() string { 22 return filepath.Join(s.storagePath, constants.RuntimeInstallationCompleteMarker) 23 } 24 25 func (s *Store) HasMarker() bool { 26 return fileutils.FileExists(s.markerFile()) 27 } 28 29 // MarkerIsValid checks if stored runtime is complete and can be loaded 30 func (s *Store) MarkerIsValid(commitID strfmt.UUID) bool { 31 marker, err := s.parseMarker() 32 if err != nil { 33 logging.Debug("Unable to parse marker file %s: %v", marker, err) 34 return false 35 } 36 37 if marker.CommitID != commitID.String() { 38 logging.Debug("Could not match commitID in %s, expected: %s, got: %s", marker, commitID.String(), marker.CommitID) 39 return false 40 } 41 42 if marker.Version != constants.Version { 43 logging.Debug("Could not match State Tool version in %s, expected: %s, got: %s", marker, constants.Version, marker.Version) 44 return false 45 } 46 47 return true 48 } 49 50 // VersionMarkerIsValid checks if stored runtime was installed with the current state tool version 51 func (s *Store) VersionMarkerIsValid() bool { 52 marker, err := s.parseMarker() 53 if err != nil { 54 logging.Debug("Unable to parse marker file %s: %v", marker, err) 55 return false 56 } 57 58 if marker.Version != constants.Version { 59 logging.Debug("Could not match State Tool version in %s, expected: %s, got: %s", marker, constants.Version, marker.Version) 60 return false 61 } 62 63 return true 64 } 65 66 func (s *Store) parseMarker() (*Marker, error) { 67 if !s.HasMarker() { 68 return nil, errs.New(`Marker file "%s" does not exist`, s.markerFile()) 69 } 70 71 contents, err := fileutils.ReadFile(s.markerFile()) 72 if err != nil { 73 return nil, errs.Wrap(err, "Could not read marker file %s", s.markerFile()) 74 } 75 76 if !json.Valid(contents) { 77 return s.updateMarker(contents) 78 } 79 80 marker := &Marker{} 81 err = json.Unmarshal(contents, marker) 82 if err != nil { 83 return nil, errs.Wrap(err, "Could not unmasrshal marker file") 84 } 85 86 return marker, nil 87 } 88 89 // updateMarker updates old marker files to the new format and 90 // returns the stored marker data 91 func (s *Store) updateMarker(contents []byte) (*Marker, error) { 92 lines := strings.Split(string(contents), "\n") 93 if len(lines) == 0 { 94 // No marker data, nothing to transition 95 return nil, nil 96 } 97 98 marker := &Marker{} 99 for i, line := range lines { 100 if i == 0 { 101 marker.CommitID = strings.TrimSpace(line) 102 } else if i == 1 { 103 marker.Version = strings.TrimSpace(line) 104 } 105 } 106 107 data, err := json.Marshal(marker) 108 if err != nil { 109 return nil, errs.Wrap(err, "Could not marshal marker data") 110 } 111 112 err = fileutils.WriteFile(s.markerFile(), data) 113 if err != nil { 114 return nil, errs.Wrap(err, "could not set completion marker") 115 } 116 117 return marker, nil 118 } 119 120 // MarkInstallationComplete writes the installation complete marker to the runtime directory 121 func (s *Store) MarkInstallationComplete(commitID strfmt.UUID, namespace string) error { 122 markerFile := s.markerFile() 123 markerDir := filepath.Dir(markerFile) 124 err := fileutils.MkdirUnlessExists(markerDir) 125 if err != nil { 126 return errs.Wrap(err, "could not create completion marker directory") 127 } 128 129 data, err := json.Marshal(Marker{commitID.String(), namespace, constants.Version}) 130 if err != nil { 131 return errs.Wrap(err, "Could not marshal marker data") 132 } 133 134 err = fileutils.WriteFile(markerFile, data) 135 if err != nil { 136 return errs.Wrap(err, "could not set completion marker") 137 } 138 139 return nil 140 } 141 142 func (s *Store) CommitID() (string, error) { 143 marker, err := s.parseMarker() 144 if err != nil { 145 return "", errs.Wrap(err, "Could not parse marker file") 146 } 147 148 return marker.CommitID, nil 149 } 150 151 func (s *Store) Namespace() (string, error) { 152 marker, err := s.parseMarker() 153 if err != nil { 154 return "", errs.Wrap(err, "Could not parse marker file") 155 } 156 157 return marker.Namespace, nil 158 }