package config import ( "fmt" "os" "path/filepath" "strings" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/prototext" "google.golang.org/protobuf/proto" ) var ErrProtoFilename error = fmt.Errorf("proto does not have Filename") // writes the protobuf to disk // uses the already configured Filename func Save(pb proto.Message) error { fullname, err := GetFilename(pb) if err != nil { return err } 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) if err := os.MkdirAll(basedir, os.ModePerm); err != nil { return err } if strings.HasSuffix(fullname, ".pb") { return saveProto(pb, fullname) } if strings.HasSuffix(fullname, ".text") { return saveTEXT(pb, "") } if strings.HasSuffix(fullname, ".json") { return saveJSON(pb) } return fmt.Errorf("unknown filetype '%s'", fullname) } func saveProto(pb proto.Message, fullname string) error { if !strings.HasSuffix(fullname, ".pb") { // todo: append .text here? return fmt.Errorf("%s needs to end in '.pb'", fullname) } dir, name := filepath.Split(fullname) if name == "" { return fmt.Errorf("filename was blank") } if err := os.MkdirAll(dir, os.ModePerm); err != nil { return err } data, err := proto.Marshal(pb) if err != nil { return err } return configWrite(fullname, data) } func saveTEXT(pb proto.Message, header string) error { // get pb.Filename if it is there in the .proto file fullname, err := GetFilename(pb) if err != nil { return err } fullname = strings.TrimSpace(fullname) if fullname == "" { return fmt.Errorf("saveTEXT() pb.Filename was blank") } if !strings.HasSuffix(fullname, ".text") { // todo: append .text here? return fmt.Errorf("not .text file: %s", fullname) } dir, name := filepath.Split(fullname) if name == "" { return fmt.Errorf("filename was blank") } if err := os.MkdirAll(dir, os.ModePerm); err != nil { return err } data := prototext.Format(pb) err = configWrite(fullname, []byte(data)) if err != nil { return err } return nil } func saveJSON(pb proto.Message) error { // get pb.Filename if it is there in the .proto file fullname, err := GetFilename(pb) if err != nil { return err } if !strings.HasSuffix(fullname, ".text") { // todo: append .text here? return fmt.Errorf("not .text file: %s", fullname) } dir, name := filepath.Split(fullname) if name == "" { return fmt.Errorf("filename was blank") } if err := os.MkdirAll(dir, os.ModePerm); err != nil { return err } data := protojson.Format(pb) fullname += ".json" err = configWrite(fullname, []byte(data)) if err != nil { return err } return nil } func configWrite(fullname string, data []byte) error { cfgfile, err := os.OpenFile(fullname, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) defer cfgfile.Close() if err != nil { return err } _, err = cfgfile.Write(data) return err }