package config // functions to import and export the protobuf // data to and from config files import ( "errors" "os" "path/filepath" "strings" "go.wit.com/log" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/prototext" "google.golang.org/protobuf/proto" ) /* // loads a file from ~/.config// func Load(argname string) ([]byte, string) { } */ var ErrEmpty error = log.Errorf("file was empty") // returns: // - Full path to the config file. usually: ~/.config/ // - []byte : the contents of the file // - error on read func ConfigLoad(pb proto.Message, argname string, protoname string) error { var fullname string homeDir, err := os.UserHomeDir() if err != nil { log.Warn("ConfigLoad() UserHomeDir() err", err) return err } fullname = filepath.Join(homeDir, ".config", argname, protoname+".text") if err := loadTEXT(pb, fullname); err == nil { return nil } if strings.HasSuffix(fullname, ".text") { fullname = strings.TrimSuffix(fullname, ".text") fullname += ".json" if err := loadJSON(pb, fullname); err != nil { return err } return nil } log.Info("Config file load failed:", fullname) return log.Errorf("could not load config file") } func loadTEXT(pb proto.Message, fullname string) error { var data []byte var err error if data, err = loadFile(fullname); err != nil { log.Warn("config file failed to load", err) // set pb.Filename that was attempted SetFilename(pb, fullname) return err } // don't even bother with Marshal() if data == nil { log.Warn("ConfigLoad() config file was empty", fullname) return ErrEmpty // file is empty } // Unmarshal() if err = prototext.Unmarshal(data, pb); err != nil { log.Warn("ConfigLoad() file", fullname) log.Warn("ConfigLoad() Unmarshal() err", err) return err } if fn, ok := GetFilename(pb); ok { if fn != fullname { log.Info("config.ConfigLoad() new filename:", fullname) SetFilename(pb, fullname) } } if os.Getenv("CONFIG_VERBOSE") == "true" { log.Infof("ConfigLoad() %s len()=%d\n", fullname, len(data)) } return nil } func loadJSON(pb proto.Message, fullname string) error { var data []byte var err error if data, err = loadFile(fullname); err != nil { log.Warn("config file failed to load", err) // set pb.Filename that was attempted SetFilename(pb, fullname) return err } // don't even bother with Marshal() if data == nil { log.Warn("ConfigLoad() config file was empty", fullname) return ErrEmpty // file is empty } // Unmarshal() if err = protojson.Unmarshal(data, pb); err != nil { log.Warn("ConfigLoad() file", fullname) log.Warn("ConfigLoad() Unmarshal() err", err) return err } if fn, ok := GetFilename(pb); ok { if fn != fullname { log.Info("config.ConfigLoad() new filename:", fullname) SetFilename(pb, fullname) } } if os.Getenv("CONFIG_VERBOSE") == "true" { log.Infof("ConfigLoad() %s len()=%d\n", fullname, len(data)) } 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 { // log.Info("open config file :", err) return nil, err } return data, nil }