summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cacheDir.go68
-rw-r--r--configDir.go88
-rw-r--r--load.go170
-rw-r--r--loadByAppname.go51
-rw-r--r--loadCache.go318
-rw-r--r--loadConfig.go176
-rw-r--r--makeFilenames.go4
-rw-r--r--panic.go19
-rw-r--r--save.go17
-rw-r--r--versionCheck.go53
10 files changed, 404 insertions, 560 deletions
diff --git a/cacheDir.go b/cacheDir.go
new file mode 100644
index 0000000..370b619
--- /dev/null
+++ b/cacheDir.go
@@ -0,0 +1,68 @@
+package config
+
+// loads from the users .cache/ dir
+//
+// GOAL: always work. When in doubt, delete things in ~/.cache/
+// RULE: always use raw .pb files, never human readable .text or .json files
+//
+// deletes files when versions don't match
+// deletes files when filenames can't be set
+// deletes anything that doesn't work
+//
+// This is important to avoid unmarshalling garbage protobuf data
+
+import (
+ "errors"
+ "os"
+
+ "go.wit.com/lib/ENV"
+ "go.wit.com/log"
+ "google.golang.org/protobuf/proto"
+)
+
+// loads foo.proto from ~/.cache/<appname>/foo.pb
+func LoadCacheDir(pb proto.Message) error {
+ appname, err := ENV.GetAppname() // already configured by your application
+ if err != nil {
+ return err
+ }
+
+ err = LoadCacheDirByAppname(pb, appname)
+ return err
+}
+
+// loads foo.proto from ~/.cache/<appname>/foo.pb
+func LoadCacheDirByAppname(pb proto.Message, appname string) error {
+ protoname, err := GetProtobufName(pb) // defined in the foo.proto file
+ if err != nil {
+ return err
+ }
+
+ err = CreateCacheDirPB(pb, appname, protoname)
+ return err
+}
+
+// checks the UUID and Version of the .pb file
+func CreateCacheDirPB(pb proto.Message, appname string, protoname string) error {
+ // Get ~/.cache/appname/protoname.text
+ fullname := MakeCacheFilename(appname, protoname)
+
+ _, err := SetFilename(pb, fullname)
+ if err != nil {
+ log.Info("lib/config PB file does not support Filename")
+ }
+ newver, curver, err := VersionCheckFile(pb, fullname)
+ _, _ = newver, curver
+ if err == nil {
+ // everything is fine. Versions match. load file
+ err = LoadFromFilename(pb, fullname)
+ return err
+ }
+ if errors.Is(err, os.ErrNotExist) {
+ // file is new, create the file
+ err = SaveToFilename(pb, fullname)
+ return err
+ }
+ // some other bad error
+ return err
+}
diff --git a/configDir.go b/configDir.go
new file mode 100644
index 0000000..2f034f3
--- /dev/null
+++ b/configDir.go
@@ -0,0 +1,88 @@
+package config
+
+import (
+ "errors"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "go.wit.com/lib/ENV"
+ "go.wit.com/log"
+ "google.golang.org/protobuf/proto"
+)
+
+// loads foo.proto from ~/.config/<appname>/foo.text
+func LoadConfigDir(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
+ }
+
+ curfilename, err := GetFilename(pb)
+ if err == nil {
+ return err
+ }
+
+ // Get ~/.config/appname/protoname.text
+ fullname := MakeConfigFilename(appname, protoname)
+
+ if err = loadTEXT(pb, fullname); err == nil {
+ // If the config is old or broken, this sets the filename
+ 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
+ } else {
+ if strings.HasSuffix(fullname, ".text") {
+ fulljson := fullname + ".json"
+ // If the config is old or broken, this sets the filename
+ if err := loadJSON(pb, fulljson); err == nil {
+ 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
+ }
+ }
+ }
+ return ErrMarshal
+}
+
+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
+}
diff --git a/load.go b/load.go
new file mode 100644
index 0000000..1fbd2ca
--- /dev/null
+++ b/load.go
@@ -0,0 +1,170 @@
+package config
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "strings"
+
+ "google.golang.org/protobuf/encoding/protojson"
+ "google.golang.org/protobuf/encoding/prototext"
+ "google.golang.org/protobuf/proto"
+)
+
+func LoadPB(pb proto.Message) error {
+ return ReLoad(pb)
+}
+
+// uses the version to die. This is needed because loading binary
+// protobuf files with rearranged messages is indeterminate
+func ReLoad(pb proto.Message) error {
+ fullname, err := GetFilename(pb)
+ if (fullname == "") || (err != nil) {
+ panic("config.LoadPB() got blank filename = ''")
+ }
+ // this code needs work
+ newver, pbver, err := VersionCheckFile(pb, fullname)
+ if errors.Is(err, os.ErrNotExist) {
+ //
+ err = SaveToFilename(pb, fullname)
+ 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 {
+ 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 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
+}
+
+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
+}
+
+/* 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
+}
+*/
diff --git a/loadByAppname.go b/loadByAppname.go
deleted file mode 100644
index 40ae9a4..0000000
--- a/loadByAppname.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package config
-
-import (
- "errors"
- "os"
-
- "go.wit.com/log"
- "google.golang.org/protobuf/proto"
-)
-
-// loads foo.proto from ~/.cache/<appname>/foo.pb
-func LoadAppnameCache(pb proto.Message, appname string) error {
- 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)
- }
-
- if !Exists(fullname) {
- SetFilename(pb, fullname)
- return os.ErrNotExist
- }
-
- 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
-}
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
-}
diff --git a/loadConfig.go b/loadConfig.go
deleted file mode 100644
index 8c7cee8..0000000
--- a/loadConfig.go
+++ /dev/null
@@ -1,176 +0,0 @@
-package config
-
-import (
- "errors"
- "strings"
-
- "go.wit.com/lib/ENV"
- "go.wit.com/log"
- "google.golang.org/protobuf/proto"
-)
-
-// loads foo.proto from ~/.config/<appname>/foo.text
-func ConfigLoad(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
- }
-
- curfilename, err := GetFilename(pb)
- if err == nil {
- return err
- }
-
- // Get ~/.config/appname/protoname.text
- fullname := makeConfigFilename(appname, protoname)
-
- if err = loadTEXT(pb, fullname); err == nil {
- // If the config is old or broken, this sets the filename
- 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
- } else {
- if strings.HasSuffix(fullname, ".text") {
- fulljson := fullname + ".json"
- // If the config is old or broken, this sets the filename
- if err := loadJSON(pb, fulljson); err == nil {
- 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
- }
- }
- }
- return ErrMarshal
-}
-
-// loads foo.proto from ~/.config/<appname>/customName.text
-func ConfigLoadByName(pb proto.Message, customName string) (string, error) {
- if customName == "" {
- return "", errors.New("config.Load() customName can not be blank")
- }
- appname, err := ENV.GetAppname() // already configured by your application
- if err != nil {
- return "", err
- }
-
- // Get ~/.config/appname/customName.text
- fullname := makeConfigFilename(appname, customName)
-
- curfilename, err := GetFilename(pb)
- if err != nil {
- // pb doesn't have 'Filename'
- // probably try to load anyway?
- log.Info("ConfigLoadByName() FILENAME old=", curfilename)
- log.Info("ConfigLoadByName() FILENAME new=", fullname)
- log.Info("pb doesn't have 'Filename'")
- log.Printf("err = (%v)\n", err)
- panic("blah")
- // return fullname, err
- }
- if curfilename == "" {
- // log.Printf("ConfigLoadByName() read in %s\n", fullname)
- }
-
- if err = loadTEXT(pb, fullname); err == nil {
- // If the config is old or broken, this sets the filename
- 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 fullname, errors.Join(err, errors.New("something is wrong in lib/config"))
- }
- }
- return fullname, nil
- } else {
- if strings.HasSuffix(fullname, ".text") {
- fulljson := fullname + ".json"
- // If the config is old or broken, this sets the filename
- if err := loadJSON(pb, fulljson); err == nil {
- 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 fullname, errors.Join(err, errors.New("something is wrong in lib/config"))
- }
- }
- return fullname, nil
- }
- }
- }
- return fullname, ErrMarshal
-}
-
-func LoadByAppName(pb proto.Message, customName string, appName string) (string, error) {
- if customName == "" {
- return "", errors.New("config.LoadByAppName() customName can not be blank")
- }
- if appName == "" {
- return "", errors.New("config.LoadByAppName() appName can not be blank")
- }
-
- // Get ~/.config/appname/customName.text
- fullname := makeConfigFilename(appName, customName)
-
- curfilename, err := GetFilename(pb)
- if err != nil {
- // pb doesn't have 'Filename'
- // probably try to load anyway?
- log.Info("ConfigLoadByName() FILENAME old=", curfilename)
- log.Info("ConfigLoadByName() FILENAME new=", fullname)
- log.Info("pb doesn't have 'Filename'")
- log.Printf("err = (%v)\n", err)
- panic("blah")
- // return fullname, err
- }
- if curfilename == "" {
- // log.Printf("ConfigLoadByName() read in %s\n", fullname)
- }
-
- if err = loadTEXT(pb, fullname); err == nil {
- // If the config is old or broken, this sets the filename
- 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 fullname, errors.Join(err, errors.New("something is wrong in lib/config"))
- }
- }
- return fullname, nil
- } else {
- if strings.HasSuffix(fullname, ".text") {
- fulljson := fullname + ".json"
- // If the config is old or broken, this sets the filename
- if err := loadJSON(pb, fulljson); err == nil {
- 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 fullname, errors.Join(err, errors.New("something is wrong in lib/config"))
- }
- }
- return fullname, nil
- }
- }
- }
- return fullname, ErrMarshal
-}
diff --git a/makeFilenames.go b/makeFilenames.go
index 6ade093..7c1b86a 100644
--- a/makeFilenames.go
+++ b/makeFilenames.go
@@ -9,7 +9,7 @@ import (
)
// ~/.config/appname/protoname.text
-func makeConfigFilename(appname string, protoname string) string {
+func MakeConfigFilename(appname string, protoname string) string {
var err error
configDir, err := os.UserConfigDir()
if err != nil {
@@ -20,7 +20,7 @@ func makeConfigFilename(appname string, protoname string) string {
}
// ~/.cache/appname/protoname.pb
-func makeCacheFilename(appname string, protoname string) string {
+func MakeCacheFilename(appname string, protoname string) string {
var err error
cacheDir, err := os.UserCacheDir()
if err != nil {
diff --git a/panic.go b/panic.go
index 8ed4df7..efab850 100644
--- a/panic.go
+++ b/panic.go
@@ -1,15 +1,24 @@
package config
-import "google.golang.org/protobuf/proto"
+import (
+ "fmt"
+
+ "google.golang.org/protobuf/proto"
+)
// should this be a function?
-func LoadPanicPB(pb proto.Message) error {
+func LoadPanic(pb proto.Message) error {
fullname, err := GetFilename(pb)
if err != nil {
- panic("config.LoadPB() err")
+ panic("config.LoadPanic() pb doesn't have pb.Filename")
}
if fullname == "" {
- panic("config.LoadPB() got blank filename = ''")
+ panic("config.LoadPanic() got blank filename = ''")
+ }
+ err = ReLoad(pb)
+ if err != nil {
+ panic(fmt.Sprintf("config.LoadPanic() err (%v)", err))
}
- return LoadPB(pb)
+
+ return nil
}
diff --git a/save.go b/save.go
index 01dcd0c..b352601 100644
--- a/save.go
+++ b/save.go
@@ -13,13 +13,13 @@ import (
var ErrProtoFilename error = fmt.Errorf("proto does not have Filename")
-func ConfigSave(pb proto.Message) error {
- return saveTEXT(pb, "")
+func SavePB(pb proto.Message) error {
+ return Save(pb)
}
// writes the protobuf to disk
// uses the already configured Filename
-func SavePB(pb proto.Message) error {
+func Save(pb proto.Message) error {
fullname, err := GetFilename(pb)
if err != nil {
return err
@@ -27,6 +27,12 @@ func SavePB(pb proto.Message) error {
return SaveToFilename(pb, fullname)
}
+// special case. adds a header to the TEXT output
+func SaveWithHeader(pb proto.Message, header string) error {
+ err := saveTEXT(pb, header)
+ return err
+}
+
// writes the protobuf to disk (sets Filename if PB has 'Filename')
func SaveToFilename(pb proto.Message, fullname string) error {
basedir, _ := filepath.Split(fullname)
@@ -67,11 +73,6 @@ func saveProto(pb proto.Message, fullname string) error {
return configWrite(fullname, data)
}
-func SaveWithHeader(pb proto.Message, header string) error {
- err := saveTEXT(pb, header)
- return err
-}
-
func saveTEXT(pb proto.Message, header string) error {
// get pb.Filename if it is there in the .proto file
fullname, err := GetFilename(pb)
diff --git a/versionCheck.go b/versionCheck.go
new file mode 100644
index 0000000..1beb7a5
--- /dev/null
+++ b/versionCheck.go
@@ -0,0 +1,53 @@
+package config
+
+import (
+ "errors"
+
+ "go.wit.com/lib/protobuf/filepb"
+ "google.golang.org/protobuf/proto"
+)
+
+// verify 'version' for .pb files
+// application should die if they don't match
+// returns (newVersion, oldVersion, error)
+func VersionCheck(pb proto.Message) (string, string, error) {
+ fullname, err := GetFilename(pb)
+ if err != nil {
+ return "", "", err
+ }
+ return VersionCheckFile(pb, fullname)
+}
+
+// verify 'version' for .pb files
+// application should die if they don't match
+// returns (newVersion, oldVersion, error)
+func VersionCheckFile(pb proto.Message, filename string) (string, string, error) {
+ var newVersion string
+ var newUuid string
+ var err error
+
+ newVersion, err = GetString(pb, "version")
+ if err != nil {
+ return newVersion, "", err
+ }
+
+ newUuid, err = GetString(pb, "uuid")
+ if err != nil {
+ return newVersion, newUuid, err
+ }
+
+ oldVersion, oldUuid, err := filepb.IdentifyPB(filename)
+ if err != nil {
+ return newVersion, newUuid, err
+ }
+
+ if newVersion != oldVersion {
+ return newVersion, oldVersion, errors.New("version mismatch")
+ }
+
+ if newUuid != oldUuid {
+ return newVersion, oldVersion, errors.New("UUID mismatch")
+ }
+
+ return newVersion, oldVersion, nil
+}