diff options
| author | Jeff Carr <[email protected]> | 2025-10-22 09:19:26 -0500 |
|---|---|---|
| committer | Jeff Carr <[email protected]> | 2025-10-22 09:19:26 -0500 |
| commit | 23b2d19bc03b4db253b15cc6fef7176ab31d4f18 (patch) | |
| tree | 275cb2d3fc92cb5af997582c715f4619eb1d68d2 /loadCache.go | |
| parent | 820fa4b7e71690accbd17063894032140bd9c4b6 (diff) | |
finally can fix the Load() and Save() names
Diffstat (limited to 'loadCache.go')
| -rw-r--r-- | loadCache.go | 318 |
1 files changed, 0 insertions, 318 deletions
diff --git a/loadCache.go b/loadCache.go deleted file mode 100644 index 2c8b9a9..0000000 --- a/loadCache.go +++ /dev/null @@ -1,318 +0,0 @@ -package config - -import ( - "errors" - "fmt" - "os" - "path/filepath" - "strings" - - "go.wit.com/lib/ENV" - "go.wit.com/log" - "google.golang.org/protobuf/encoding/protojson" - "google.golang.org/protobuf/encoding/prototext" - "google.golang.org/protobuf/proto" -) - -// loads foo.proto from ~/.cache/<appname>/foo.text -func CacheLoad(pb proto.Message) error { - appname, err := ENV.GetAppname() // already configured by your application - if err != nil { - return err - } - protoname, err := GetProtobufName(pb) // defined in the foo.proto file - if err != nil { - return err - } - - // Get ~/.cache/appname/protoname.text - fullname := makeCacheFilename(appname, protoname) - - // get the current filename in the protobuf file - curfilename, err := GetFilename(pb) - if err != nil { - return err - } - if curfilename == "" { - // log.Printf("ConfigLoad() read in %s\n", fullname) - } - - err = loadPB(pb, fullname) - if err != nil { - return ErrMarshal - } - - // If the cache file is new or has moved, this updates it to correct filename - // (the filename is what is used by pb.Save() - if curfilename != fullname { - _, err := SetFilename(pb, fullname) - if err != nil { - log.Info("FILENAME COULD NOT BE SET old=", curfilename) - log.Info("FILENAME COULD NOT BE SET new=", fullname) - return errors.Join(err, errors.New("something is wrong in lib/config")) - } - } - return nil -} - -// loads from the users .cache dir -// if the .proto file version changes, automatically delete the .pb -// file. This is important to avoid marshalling garbage data -// .cache files are treated as such, a "cache" file. don't keep important -// things in here. argv stores the information here for autodelete -func LoadCache(pb proto.Message, appname string, protoname string) error { - cacheDir, _ := os.UserCacheDir() - fullpath := filepath.Join(cacheDir, appname) - os.MkdirAll(fullpath, os.ModePerm) - fullname := filepath.Join(fullpath, protoname+".pb") - _, err := SetFilename(pb, fullname) - if err != nil { - pb = nil - os.Remove(fullname) - return err - } - newver, curver, err := LoadVersionCheckPB(pb) - if err != nil { - pb = nil - os.Remove(fullname) - return err - } - _, _ = newver, curver - return nil -} - -func LoadVersionCheckPB(pb proto.Message) (string, string, error) { - var newver string - var pbver string - var err error - - fullname, err := GetFilename(pb) - if err != nil { - return newver, pbver, err - } - // text is supposed to be "easy". Don't verify 'version' - if strings.HasSuffix(fullname, ".text") { - err = loadTEXT(pb, fullname) - return newver, pbver, err - } - - // verify 'version' for .pb files - // application should die if they don't match - var worked bool - newver, err = GetString(pb, "version") - if err != nil { - return newver, pbver, err - } - // maybe don't really verify .json files (?) - // doing it for now anyway. maybe just return an error - if strings.HasSuffix(fullname, ".json") { - if err = loadJSON(pb, fullname); err != nil { - return newver, pbver, err - } - worked = true - } - if strings.HasSuffix(fullname, ".pb") { - if err = loadPB(pb, fullname); err != nil { - return newver, pbver, err - } - _, err = SetFilename(pb, fullname) - if err != nil { - return newver, pbver, err - } - worked = true - } - if !worked { - return newver, pbver, fmt.Errorf("unknown filetype '%s'", fullname) - } - // get the version from the current PB saved on disk - pbver, _ = GetString(pb, "version") - if newver != pbver { - return newver, pbver, VersionMismatch - } - return newver, pbver, nil -} - -// uses the version to die. This is needed because loading binary -// protobuf files with rearranged messages is indeterminate -func LoadPB(pb proto.Message) error { - fullname, err := GetFilename(pb) - if fullname == "" { - panic("config.LoadPB() got blank filename = ''") - } - if err != nil { - return err - } - // this code needs work - newver, pbver, err := LoadVersionCheckPB(pb) - if errors.Is(err, os.ErrNotExist) { - return err - } - if errors.Is(err, VersionMismatch) || (newver != pbver) { - fmt.Println("") - fmt.Printf("VERSION new '%s' != cur PB '%s'\n", newver, pbver) - fmt.Println("") - fmt.Println("Your protobuf file is old and can not be loaded") - fmt.Println("your application must decide how to handle this (delete or fix)") - fmt.Println("always die here. application is broken") - fmt.Println("You must delete or convert the file", fullname) - fmt.Println("") - // probably should ALWAYS PANIC HERE - // upon further study, always die here is better than not - s := fmt.Sprintf("protobuf version wrong. delete or fix %s", fullname) - panic(s) - } - if err != nil { - // return to let the application figure this out - return err - } - return nil -} - -func LoadFromFilename(pb proto.Message, fullname string) error { - return LoadFile(pb, fullname) -} - -func LoadFile(pb proto.Message, fullname string) error { - if strings.HasSuffix(fullname, ".text") { - return loadTEXT(pb, fullname) - } - if strings.HasSuffix(fullname, ".json") { - return loadJSON(pb, fullname) - } - if strings.HasSuffix(fullname, ".pb") { - return loadPB(pb, fullname) - } - - return fmt.Errorf("unknown filetype '%s'", fullname) -} - -func loadPB(pb proto.Message, fullname string) error { - data, err := loadFile(fullname) - if err != nil { - // set pb.Filename that was attempted - return err - } - - if err = proto.Unmarshal(data, pb); err != nil { - return err - } - - return nil -} - -func LoadConfigPB(pb proto.Message, appname string, protoname string) (string, error) { - var fullname string - if strings.HasPrefix(appname, "/") { - fullname = filepath.Join(appname, protoname+".pb") - } else { - configDir, err := os.UserConfigDir() - if err != nil { - return "", err - } - - fullname = filepath.Join(configDir, appname, protoname+".pb") - } - - data, err := loadFile(fullname) - if err != nil { - return fullname, err - } - - // Unmarshal() - if err = proto.Unmarshal(data, pb); err != nil { - return fullname, err - } - - return fullname, nil -} - -func loadTEXT(pb proto.Message, fullname string) error { - var data []byte - var err error - SetFilename(pb, fullname) - if data, err = loadFile(fullname); err != nil { - return err - } - - // don't even bother with Marshal() - if data == nil { - return ErrEmpty // file is empty - } - - // Unmarshal() - if err = prototext.Unmarshal(data, pb); err != nil { - return ErrMarshal - } - - if fn, err := GetFilename(pb); err != nil { - if fn != fullname { - SetFilename(pb, fullname) - } - } - return nil -} - -// json files are backup Marshal() data in case .text Unmarshal() fails -// they always should have the ".text" filename in them -func loadJSON(pb proto.Message, fullname string) error { - var data []byte - var err error - if data, err = loadFile(fullname); err != nil { - return err - } - - // don't even bother with Marshal() - if data == nil { - return ErrEmpty // file is empty - } - - // Unmarshal() - if err = protojson.Unmarshal(data, pb); err != nil { - return ErrMarshal - } - - if fn, err := GetFilename(pb); err != nil { - if fn != fullname { - SetFilename(pb, fullname) - } - } - return nil -} - -/* left this here to remind myself just how dumb I can be - -// dumb but simple to read logic -func missingConfig(fullname string) error { - data1, err1 := os.ReadFile(fullname) - if !errors.Is(err1, os.ErrNotExist) { - return err1 - } - - data2, err2 := os.ReadFile(fullname + ".json") - if !errors.Is(err2, os.ErrNotExist) { - return err2 - } - if errors.Is(err1, os.ErrNotExist) && errors.Is(err2, os.ErrNotExist) { - return os.ErrNotExist - } - if (len(data1) == 0) && (len(data2) == 0) { - return ErrEmpty - } - return nil -} -*/ - -func loadFile(fullname string) ([]byte, error) { - data, err := os.ReadFile(fullname) - if errors.Is(err, os.ErrNotExist) { - // if file does not exist, just return nil. this - return nil, err - } - if err != nil { - return nil, err - } - if len(data) == 0 { - return data, ErrEmpty - } - return data, nil -} |
