package config // The exported clone surface. Deep copying lives in the config package so // data/integration code needs neither protobuf cloning nor a storage-specific // serializer to hand out a snapshot a caller may safely mutate. Each function // returns nil for a nil input. func Clone(value *Config) *Config { return cloneConfig(value) } func CloneData(value *Data) *Data { return cloneData(value) } func CloneAdmin(value *Admin) *Admin { return cloneAdmin(value) } func CloneDatabase(value *Database) *Database { return clonePtr(value) } func CloneStorage(value *Storage) *Storage { return cloneStorage(value) } func CloneEmail(value *Email) *Email { return clonePtr(value) } // MergeRuntimeConfig applies the runtime replacement contract shared by file // watching and management updates. Omitted top-level sections keep their // current values, while database-backed storage/email settings are never // erased merely because they are absent from config.yaml. func MergeRuntimeConfig(current, next *Config) *Config { merged := cloneConfig(next) if merged == nil { merged = &Config{} } if current == nil { if merged.Admin == nil { merged.Admin = &Admin{} } return merged } if merged.Server == nil { merged.Server = clonePtr(current.Server) } if merged.Data == nil { merged.Data = cloneData(current.Data) } else if current.Data != nil { if merged.Data.Database == nil { merged.Data.Database = clonePtr(current.Data.Database) } if merged.Data.Redis == nil { merged.Data.Redis = cloneRedis(current.Data.Redis) } if merged.Data.Mongo == nil { merged.Data.Mongo = cloneMongo(current.Data.Mongo) } if merged.Data.DatabaseList == nil { merged.Data.DatabaseList = cloneSlice(current.Data.DatabaseList, clonePtr) } if merged.Data.RedisList == nil { merged.Data.RedisList = cloneSlice(current.Data.RedisList, cloneRedis) } } if merged.Admin == nil { merged.Admin = cloneAdmin(current.Admin) } if merged.Admin == nil { merged.Admin = &Admin{} } if current.Admin != nil { if merged.Admin.Storage == nil { merged.Admin.Storage = cloneStorage(current.Admin.Storage) } if merged.Admin.Email == nil { merged.Admin.Email = clonePtr(current.Admin.Email) } if merged.Admin.ConfigPath == "" { merged.Admin.ConfigPath = current.Admin.ConfigPath } } return merged }