package restic import ( "encoding/json" "errors" "fmt" "github.com/rs/zerolog/log" "os" "path/filepath" "time" ) type Config struct { Repository string `json:"repository"` Backup string `json:"backup"` BackupTimeInHours int `json:"backupTimeInHours"` } func (c *Config) BackupTimeInDuration() time.Duration { return time.Duration(c.BackupTimeInHours) * time.Hour } const ( DefaultBackupTimeInHours int = 24 ShortTimeFormat string = "2006-01-02T15:04:05" ) func IsDev() bool { return isDev != "" } func PasswordFile() string { return filepath.Join(configDir, "password.txt") } func LogFile() string { return filepath.Join(configDir, "log.txt") } func ExcludeFile() string { return filepath.Join(configDir, "excludes.txt") } func ConfigFile() string { return filepath.Join(configDir, "config.json") } func MountDir() string { return filepath.Join(configDir, "mnt") } func (cnf *Config) CreateMountDirIfDoesntExist() error { if _, err := os.Stat(MountDir()); os.IsNotExist(err) { return os.Mkdir(MountDir(), os.ModePerm) } return nil } func defaultConfig() *Config { return &Config{ BackupTimeInHours: DefaultBackupTimeInHours, Backup: home, Repository: os.TempDir(), } } func ReadConfig() (*Config, error) { confData, err := os.ReadFile(ConfigFile()) conf := &Config{} if err != nil { log.Warn().Err(err).Msg("No config.json found, writing default") // in case the base config dir doesn't exist, create it if _, err := os.Stat(configDir); os.IsNotExist(err) { err = os.Mkdir(configDir, os.ModePerm) if err != nil { return nil, err } } conf = defaultConfig() confData, _ := json.Marshal(conf) os.WriteFile(ConfigFile(), confData, os.ModePerm) } err = json.Unmarshal(confData, conf) if err != nil { return nil, fmt.Errorf("config.json malformed JSON: %w", err) } if conf.Repository == "" || conf.Backup == "" { err := errors.New("config.json is missing required keys 'Backup' or 'Repository'") return nil, err } if conf.BackupTimeInHours == 0 { log.Warn().Msg("backupTimeInHours missing in config, reverting to 24hrs") conf.BackupTimeInHours = DefaultBackupTimeInHours } if _, err := os.Stat(ExcludeFile()); os.IsNotExist(err) { os.WriteFile(ExcludeFile(), []byte("node_modules"), os.ModePerm) } if _, err := os.Stat(PasswordFile()); os.IsNotExist(err) { os.WriteFile(PasswordFile(), []byte("password"), os.ModePerm) } return conf, nil }