From 34a287a38e3af080ec3d3c42bbca5ef06b2311f8 Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Thu, 5 Dec 2024 12:37:07 -0600 Subject: [PATCH] work on config file save --- config.go | 141 ++++++++++++++++++++++++---------------------- configBackup.go | 4 +- forgeConfig.proto | 3 +- init.go | 15 ++++- 4 files changed, 91 insertions(+), 72 deletions(-) diff --git a/config.go b/config.go index 80e3e83..fcd3b4d 100644 --- a/config.go +++ b/config.go @@ -7,24 +7,38 @@ import ( "errors" "os" "path/filepath" + "time" "go.wit.com/log" ) -// write to ~/.config/forge/ unless ENV{FORGE_HOME} is set func (f *Forge) ConfigSave() error { - // f.Config.Lock() - // defer f.Config.UnLock() - if os.Getenv("FORGE_HOME") == "" { - homeDir, _ := os.UserHomeDir() - fullpath := filepath.Join(homeDir, ".config/forge") - os.Setenv("FORGE_HOME", fullpath) + var err error + // backup the current config files + if e := backupConfig(); e != nil { + log.Info("forge.BackupConfig() error", e) + err = e + // continue here? notsure. could be bad either way + // out of disk space? } - // try to backup the current cluster config files - if err := backupConfig(); err != nil { - return err + if f.Config != nil { + if e := f.Config.ConfigSave(); e != nil { + log.Info("forge.Config.ConfigSave() error", e) + err = e + } } - data, err := f.Config.Marshal() + if f.Repos != nil { + if e := f.Repos.ConfigSave(); e != nil { + log.Info("forge.Repos.ConfigSave() error", e) + err = e + } + } + return err +} + +// write to ~/.config/forge/ unless ENV{FORGE_CONFIG} is set +func (f *ForgeConfigs) ConfigSave() error { + data, err := f.Marshal() if err != nil { log.Info("proto.Marshal() failed len", len(data), err) return err @@ -32,88 +46,83 @@ func (f *Forge) ConfigSave() error { log.Info("forgepb.ConfigSave() proto.Marshal() worked len", len(data)) configWrite("forge.pb", data) - s := f.Config.FormatTEXT() + s := f.FormatTEXT() configWrite("forge.text", []byte(s)) - s = f.Config.FormatJSON() + s = f.FormatJSON() configWrite("forge.json", []byte(s)) - if f.Repos != nil { - f.Repos.ConfigSave() - } return nil } // load the ~/.config/forge/ files func (c *ForgeConfigs) ConfigLoad() error { - if os.Getenv("FORGE_HOME") == "" { + if os.Getenv("FORGE_CONFIG") == "" { homeDir, _ := os.UserHomeDir() fullpath := filepath.Join(homeDir, ".config/forge") - os.Setenv("FORGE_HOME", fullpath) + os.Setenv("FORGE_CONFIG", fullpath) } - var data []byte - var err error + // var data []byte + // var err error if c == nil { // can't safely do c = new(ForgeConfig) if c is in a struct from the caller. notsure why return errors.New("It's not safe to run ConfigLoad() on a nil") } - if data, err = loadFile("forge.pb"); err != nil { - // something went wrong loading the file - return err - } - if data != nil { - // this means the forge.pb file exists and was read - if len(data) == 0 { - // todo: error out if the file is empty? - // try forge.text & forge.json? + if data, err := loadFile("forge.pb"); err == nil { + if data != nil { + if len(data) != 0 { + if err = c.Unmarshal(data); err == nil { + log.Info("forge.ConfigLoad()", len(c.ForgeConfigs), "entries in ~/.config/forge") + return nil + } + } } - if err = c.Unmarshal(data); err != nil { - log.Warn("broken forge.pb config file") - return err - } - log.Info("found", len(c.ForgeConfigs), "entries in ~/.config/forge") - return nil } + log.Warn("broken forge.pb config file") // forge.db doesn't exist. try forge.text // this lets the user hand edit the config - if data, err = loadFile("forge.text"); err != nil { - // something went wrong loading the file - return err - } - - if data != nil { - // this means the forge.text file exists and was read - if len(data) == 0 { - // todo: error out if the file is empty? + if data, err := loadFile("forge.text"); err == nil { + if data != nil { + // this means the forge.text file exists and was read + if len(data) != 0 { + if err = c.UnmarshalTEXT(data); err != nil { + log.Info("forge.ConfigLoad()", len(c.ForgeConfigs), "entries in ~/.config/forge") + // forge.pb file was broken. save on load right away + log.Info("attempting forge.ConfigSave()") + c.ConfigSave() + return nil + } + // todo: error out if the file is empty? + } } - if err = c.UnmarshalTEXT(data); err != nil { - log.Warn("broken forge.text config file") - return err - } - log.Info("found", len(c.ForgeConfigs), "entries in ~/.config/forge") - return nil } // forge.text doesn't exist. try forge.json // this lets the user hand edit the config - if data, err = loadFile("forge.json"); err != nil { - // something went wrong loading the file - return err + if data, err := loadFile("forge.json"); err != nil { + if data != nil { + // this means the forge.json file exists and was read + if len(data) != 0 { + if err = c.UnmarshalJSON(data); err == nil { + log.Info("forge.ConfigLoad()", len(c.ForgeConfigs), "entries in ~/.config/forge") + // forge.pb file was broken. save on load right away + log.Info("attempting forge.ConfigSave()") + c.ConfigSave() + return nil + } + } + } } - if data != nil { - // this means the forge.text file exists and was read - if len(data) == 0 { - // todo: error out if the file is empty? - } - if err = c.UnmarshalJSON(data); err != nil { - log.Warn("broken forge.json config file") - return err - } - log.Info("found", len(c.ForgeConfigs), "entries in ~/.config/forge") - return nil + cpath := filepath.Join(os.Getenv("FORGE_CONFIG"), ".") + if _, err := os.Stat(cpath); err == nil { + log.Info("Something has gone wrong. Your", os.Getenv("FORGE_CONFIG"), "directory exists") + log.Info("However, the config files could not be loaded") + time.Sleep(2 * time.Second) + os.Exit(-1) + // return errors.New("config files can not be loaded from" + os.Getenv("FORGE_CONFIG")) } // first time user. make a template config file @@ -123,7 +132,7 @@ func (c *ForgeConfigs) ConfigLoad() error { } func loadFile(filename string) ([]byte, error) { - fullname := filepath.Join(os.Getenv("FORGE_HOME"), filename) + fullname := filepath.Join(os.Getenv("FORGE_CONFIG"), filename) data, err := os.ReadFile(fullname) if errors.Is(err, os.ErrNotExist) { // if file does not exist, just return nil. this @@ -139,7 +148,7 @@ func loadFile(filename string) ([]byte, error) { } func configWrite(filename string, data []byte) error { - fullname := filepath.Join(os.Getenv("FORGE_HOME"), filename) + fullname := filepath.Join(os.Getenv("FORGE_CONFIG"), filename) cfgfile, err := os.OpenFile(fullname, os.O_RDWR|os.O_CREATE, 0666) defer cfgfile.Close() diff --git a/configBackup.go b/configBackup.go index ee019ae..d9bc396 100644 --- a/configBackup.go +++ b/configBackup.go @@ -18,8 +18,8 @@ func backupConfig() error { now := time.Now() // timestamp := now.Format("2022.07.18.190545") // 50yr shout out to K&R timestamp := now.Format("2006.01.02.150405") // bummer. other date doesn't work? - srcDir := filepath.Join(os.Getenv("FORGE_HOME")) - destDir := filepath.Join(os.Getenv("FORGE_HOME"), timestamp) + srcDir := filepath.Join(os.Getenv("FORGE_CONFIG")) + destDir := filepath.Join(os.Getenv("FORGE_CONFIG"), timestamp) return backupFiles(srcDir, destDir) } diff --git a/forgeConfig.proto b/forgeConfig.proto index de60159..70f9f1d 100644 --- a/forgeConfig.proto +++ b/forgeConfig.proto @@ -27,10 +27,11 @@ message ForgeConfig { string userBranchName = 10; // whatever your username branch is string debName = 11; // the actual name used with 'apt install' (or distro apt equivalent. -// todo: appeal to everyone to alias 'apt' on rhat, gentoo, arch, etc to alias 'apt install' +// todo: appeal to everyone to alias 'apt' on fedora, gentoo, arch, etc to alias 'apt install' // so we can make easier instructions for new linux users. KISS google.protobuf.Timestamp verstamp = 12; // the git commit timestamp of the version + string goSrc = 13; // is ~/go/src unless a go.work file is found } message ForgeConfigs { // `autogenpb:marshal` diff --git a/init.go b/init.go index 3986bc0..1d41d62 100644 --- a/init.go +++ b/init.go @@ -2,6 +2,7 @@ package forgepb import ( "os" + "path/filepath" "go.wit.com/lib/protobuf/gitpb" "go.wit.com/lib/protobuf/zoopb" @@ -23,6 +24,13 @@ func Init() *Forge { } f.goSrc = os.Getenv("FORGE_GOSRC") + // also rethink this, but maybe this is the right thing to do + if os.Getenv("FORGE_CONFIG") == "" { + homeDir, _ := os.UserHomeDir() + fullpath := filepath.Join(homeDir, ".config/forge") + os.Setenv("FORGE_CONFIG", fullpath) + } + // cache.go has Do() // f.initOnce.Do(f.initWork) @@ -42,10 +50,11 @@ func Init() *Forge { log.Warn("zoopb.ConfigLoad() failed", err) os.Exit(-1) } - f.Machine.InitWit() + // f.Machine.InitWit() - log.Info("forge pre scan ", f.Repos.Len(), "repos in", f.goSrc) + start := f.Repos.Len() f.ScanGoSrc() - log.Info("forge.Init() found", f.Repos.Len(), "repos in", f.goSrc) + end := f.Repos.Len() + log.Info("forge.ScanGoSrc() Found", end-start, "new repos in", f.goSrc) return f }