make ConfigSave() ConfigLoad()
This commit is contained in:
parent
6e40b1bab4
commit
d7dec7865a
|
@ -0,0 +1,150 @@
|
|||
package chatpb
|
||||
|
||||
// functions to import and export the protobuf
|
||||
// data to and from config files
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"go.wit.com/lib/protobuf/bugpb"
|
||||
"go.wit.com/log"
|
||||
)
|
||||
|
||||
// write to ~/.config/gemini/ unless ENV{GEMINI_HOME} is set
|
||||
func (all *Chats) ConfigSave() error {
|
||||
if os.Getenv("GEMINI_HOME") == "" {
|
||||
homeDir, _ := os.UserHomeDir()
|
||||
fullpath := filepath.Join(homeDir, ".config/gemini")
|
||||
os.Setenv("GEMINI_HOME", fullpath)
|
||||
}
|
||||
if all == nil {
|
||||
log.Warn("chatpb all == nil")
|
||||
return errors.New("chatpb.ConfigSave() all == nil")
|
||||
}
|
||||
|
||||
data, err := all.Marshal()
|
||||
if err != nil {
|
||||
log.Info("chatpb proto.Marshal() failed len", len(data), err)
|
||||
// often this is because strings have invalid UTF-8. This should probably be fixed in the protobuf code
|
||||
if err := all.tryValidate(); err != nil {
|
||||
return err
|
||||
} else {
|
||||
// re-attempt Marshal() here
|
||||
data, err = all.Marshal()
|
||||
if err == nil {
|
||||
// validate & sanitize strings worked
|
||||
log.Info("chatpb.ConfigSave() pb.Marshal() worked len", len(all.Chats), "chats")
|
||||
configWrite("gemini.pb", data)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
if err := configWrite("gemini.pb", data); err != nil {
|
||||
log.Infof("chatpb.ConfigSave() failed len(Chats)=%d bytes=%d", len(all.Chats), len(data))
|
||||
return err
|
||||
}
|
||||
configWrite("gemini.text", []byte(all.FormatTEXT()))
|
||||
log.Infof("chatpb.ConfigSave() worked len(Chats)=%d bytes=%d", len(all.Chats), len(data))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (all *Chats) tryValidate() error {
|
||||
|
||||
err := bugpb.ValidateProtoUTF8(all)
|
||||
if err != nil {
|
||||
log.Printf("Protobuf UTF-8 validation failed: %v\n", err)
|
||||
}
|
||||
if err := bugpb.SanitizeProtoUTF8(all); err != nil {
|
||||
log.Warn("Sanitation failed:", err)
|
||||
// log.Fatalf("Sanitization failed: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// load the gemini.pb file. I shouldn't really matter if this
|
||||
// fails. the file should be autogenerated. This is used
|
||||
// locally just for speed
|
||||
func (all *Chats) ConfigLoad() error {
|
||||
if os.Getenv("GEMINI_HOME") == "" {
|
||||
homeDir, _ := os.UserHomeDir()
|
||||
fullpath := filepath.Join(homeDir, ".config/gemini")
|
||||
os.Setenv("GEMINI_HOME", fullpath)
|
||||
}
|
||||
var data []byte
|
||||
var err error
|
||||
|
||||
cfgname := filepath.Join(os.Getenv("GEMINI_HOME"), "gemini.pb")
|
||||
if data, err = loadFile(cfgname); err != nil {
|
||||
// something went wrong loading the file
|
||||
// all.sampleConfig() // causes nil panic
|
||||
return err
|
||||
}
|
||||
// this means the gemini.pb file exists and was read
|
||||
if len(data) == 0 {
|
||||
// todo: add default data here since it's blank? // might cause nil panic?
|
||||
return errors.New("chatpb.ConfigLoad() gemini.pb is empty")
|
||||
}
|
||||
err = all.Unmarshal(data)
|
||||
test := NewChats()
|
||||
if test.Uuid != all.Uuid {
|
||||
log.Warn("uuids do not match", test.Uuid, all.Uuid)
|
||||
deleteProtobufFile(cfgname)
|
||||
}
|
||||
if test.Version != all.Version {
|
||||
log.Warn("versions do not match", test.Version, all.Version)
|
||||
deleteProtobufFile(cfgname)
|
||||
}
|
||||
log.Info(cfgname, "protobuf versions and uuid match", all.Uuid, all.Version)
|
||||
return err
|
||||
}
|
||||
|
||||
func deleteProtobufFile(filename string) {
|
||||
log.Warn("The protobuf file format has changed for", filename)
|
||||
log.Warn("Deleting old file:", filename)
|
||||
log.Warn("This file will be recreated on the next run.")
|
||||
err := os.Remove(filename)
|
||||
if err != nil {
|
||||
log.Warn("failed to remove old protobuf file", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// will cause ConfigLoad() to try the next config file like "gemini.text"
|
||||
// because the user might want to edit the .config by hand
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
// log.Info("open config file :", err)
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func configWrite(filename string, data []byte) error {
|
||||
fullname := filepath.Join(os.Getenv("GEMINI_HOME"), filename)
|
||||
|
||||
cfgfile, err := os.OpenFile(fullname, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
|
||||
defer cfgfile.Close()
|
||||
if err != nil {
|
||||
log.Warn("open config file :", err)
|
||||
return err
|
||||
}
|
||||
if filename == "gemini.text" {
|
||||
// add header
|
||||
cfgfile.Write([]byte("# this file is automatically re-generated from gemini.pb, however,\n"))
|
||||
cfgfile.Write([]byte("# if you want to edit it by hand, you can:\n"))
|
||||
cfgfile.Write([]byte("# stop gemini; remove gemini.pb; edit gemini.text; start gemini\n"))
|
||||
cfgfile.Write([]byte("# this will cause the default behavior to fallback to parsing this file for the config\n"))
|
||||
cfgfile.Write([]byte("\n"))
|
||||
cfgfile.Write([]byte("# this file is intended to be used to customize settings on what\n"))
|
||||
}
|
||||
cfgfile.Write(data)
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package chatpb
|
||||
|
||||
import (
|
||||
"go.wit.com/log"
|
||||
)
|
||||
|
||||
func ExampleChat() *Chats {
|
||||
conversation := NewChats()
|
||||
|
||||
t := conversation.AddTable()
|
||||
t.AddRow([]string{"apple", "pear"})
|
||||
|
||||
conversation.AddGeminiComment("funny")
|
||||
conversation.AddUserComment("yes")
|
||||
|
||||
conversation.AddGeminiComment("I like astronomy")
|
||||
|
||||
dump := conversation.FormatTEXT()
|
||||
|
||||
log.Println(dump)
|
||||
return conversation
|
||||
}
|
Loading…
Reference in New Issue