From e552035142b36fa1da78faed5cf83ff89f4506c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustav=20S=C3=B6rn=C3=A4s?= Date: Mon, 19 Oct 2020 01:32:50 +0200 Subject: initial reading of config file --- mumlib/Cargo.toml | 1 + mumlib/src/config.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++ mumlib/src/lib.rs | 1 + 3 files changed, 62 insertions(+) create mode 100644 mumlib/src/config.rs (limited to 'mumlib') diff --git a/mumlib/Cargo.toml b/mumlib/Cargo.toml index a2627d4..471a1fe 100644 --- a/mumlib/Cargo.toml +++ b/mumlib/Cargo.toml @@ -13,3 +13,4 @@ fern = "0.5" log = "0.4" mumble-protocol = "0.3" serde = { version = "1.0", features = ["derive"] } +toml = "0.5" diff --git a/mumlib/src/config.rs b/mumlib/src/config.rs new file mode 100644 index 0000000..0012cc6 --- /dev/null +++ b/mumlib/src/config.rs @@ -0,0 +1,60 @@ +use serde::Deserialize; +use std::fs; +use toml::value::Array; + +#[derive(Debug, Deserialize)] +struct TOMLConfig { + audio: Option, + servers: Option, +} + +#[derive(Debug, Deserialize)] +pub struct Config { + pub audio: Option, + pub servers: Option>, +} + +#[derive(Debug, Deserialize)] +pub struct AudioConfig { + pub input_volume: Option, +} + +#[derive(Debug, Deserialize)] +pub struct ServerConfig { + pub name: String, + pub host: String, + pub port: u16, + pub username: Option, + pub password: Option, +} + +fn get_cfg_path() -> String { + "~/.mumdrc".to_string() //TODO XDG_CONFIG and whatever +} + +impl From for Config { + fn from(config: TOMLConfig) -> Self { + Config { + audio: config.audio, + servers: if let Some(servers) = config.servers { + Some(servers + .into_iter() + .map(|s| s.try_into::().expect("invalid server config format")) + .collect()) + } else { + None + }, + } + } +} + +pub fn read_default_cfg() -> Config { + //TODO ignore when config file doesn't exist + Config::from( + toml::from_str::( + &fs::read_to_string( + get_cfg_path()) + .expect("config file not found") + .to_string()) + .unwrap()) +} diff --git a/mumlib/src/lib.rs b/mumlib/src/lib.rs index b26db13..93b7682 100644 --- a/mumlib/src/lib.rs +++ b/mumlib/src/lib.rs @@ -1,4 +1,5 @@ pub mod command; +pub mod config; pub mod error; pub mod state; -- cgit v1.2.1 From 3e61f2d4a48b621c4cef820e24cd2515cbc1c919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustav=20S=C3=B6rn=C3=A4s?= Date: Mon, 19 Oct 2020 02:40:43 +0200 Subject: convert config to string --- mumlib/src/config.rs | 53 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 6 deletions(-) (limited to 'mumlib') diff --git a/mumlib/src/config.rs b/mumlib/src/config.rs index 0012cc6..d6550c1 100644 --- a/mumlib/src/config.rs +++ b/mumlib/src/config.rs @@ -1,25 +1,34 @@ -use serde::Deserialize; +use log::*; +use serde::{Deserialize, Serialize}; use std::fs; +use toml::Value; use toml::value::Array; -#[derive(Debug, Deserialize)] +#[derive(Debug, Deserialize, Serialize)] struct TOMLConfig { audio: Option, servers: Option, } -#[derive(Debug, Deserialize)] +#[derive(Debug)] pub struct Config { pub audio: Option, pub servers: Option>, } -#[derive(Debug, Deserialize)] +impl Config { + pub fn write_default_cfg(&self) { + debug!("{}", toml::to_string(&(TOMLConfig::from(self))).unwrap()); + //fs::write(, get_cfg_path()) + } +} + +#[derive(Clone, Debug, Deserialize, Serialize)] pub struct AudioConfig { pub input_volume: Option, } -#[derive(Debug, Deserialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] pub struct ServerConfig { pub name: String, pub host: String, @@ -29,7 +38,7 @@ pub struct ServerConfig { } fn get_cfg_path() -> String { - "~/.mumdrc".to_string() //TODO XDG_CONFIG and whatever + ".mumdrc".to_string() //TODO XDG_CONFIG and whatever } impl From for Config { @@ -48,6 +57,38 @@ impl From for Config { } } +impl From for TOMLConfig { + fn from(config: Config) -> Self { + TOMLConfig { + audio: config.audio, + servers: if let Some(servers) = config.servers { + Some(servers + .into_iter() + .map(|s| Value::try_from::(s).unwrap()) + .collect()) + } else { + None + }, + } + } +} + +impl From<&Config> for TOMLConfig { + fn from(config: &Config) -> Self { + TOMLConfig { + audio: config.audio.clone(), + servers: if let Some(servers) = config.servers.clone() { + Some(servers + .into_iter() + .map(|s| Value::try_from::(s).unwrap()) + .collect()) + } else { + None + }, + } + } +} + pub fn read_default_cfg() -> Config { //TODO ignore when config file doesn't exist Config::from( -- cgit v1.2.1 From 26ccc76b3fcab00d21f88346d816fb83c2ae7563 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustav=20S=C3=B6rn=C3=A4s?= Date: Mon, 19 Oct 2020 02:50:45 +0200 Subject: write config to file --- mumlib/src/config.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mumlib') diff --git a/mumlib/src/config.rs b/mumlib/src/config.rs index d6550c1..e2ede02 100644 --- a/mumlib/src/config.rs +++ b/mumlib/src/config.rs @@ -18,8 +18,8 @@ pub struct Config { impl Config { pub fn write_default_cfg(&self) { - debug!("{}", toml::to_string(&(TOMLConfig::from(self))).unwrap()); - //fs::write(, get_cfg_path()) + debug!("{}", toml::to_string(&TOMLConfig::from(self)).unwrap()); + fs::write(get_cfg_path(), toml::to_string(&TOMLConfig::from(self)).unwrap()).unwrap(); } } -- cgit v1.2.1 From 00f95b860b30923016ebf5d9e78c520b95afb9d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustav=20S=C3=B6rn=C3=A4s?= Date: Mon, 19 Oct 2020 03:28:02 +0200 Subject: server config subcommand --- mumlib/src/config.rs | 2 -- 1 file changed, 2 deletions(-) (limited to 'mumlib') diff --git a/mumlib/src/config.rs b/mumlib/src/config.rs index e2ede02..d93b172 100644 --- a/mumlib/src/config.rs +++ b/mumlib/src/config.rs @@ -1,4 +1,3 @@ -use log::*; use serde::{Deserialize, Serialize}; use std::fs; use toml::Value; @@ -18,7 +17,6 @@ pub struct Config { impl Config { pub fn write_default_cfg(&self) { - debug!("{}", toml::to_string(&TOMLConfig::from(self)).unwrap()); fs::write(get_cfg_path(), toml::to_string(&TOMLConfig::from(self)).unwrap()).unwrap(); } } -- cgit v1.2.1 From d75bc24bdd176786a1340e16f7aa3db6e3e6a093 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustav=20S=C3=B6rn=C3=A4s?= Date: Mon, 19 Oct 2020 23:34:39 +0200 Subject: send config-reload-command --- mumlib/src/command.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'mumlib') diff --git a/mumlib/src/command.rs b/mumlib/src/command.rs index b4ab07a..05702f0 100644 --- a/mumlib/src/command.rs +++ b/mumlib/src/command.rs @@ -8,6 +8,7 @@ pub enum Command { channel_identifier: String, }, ChannelList, + ConfigReload, InputVolumeSet(f32), ServerConnect { host: String, -- cgit v1.2.1 From d290a6926b2c495d04396924985ac87e632de1da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustav=20S=C3=B6rn=C3=A4s?= Date: Mon, 19 Oct 2020 23:35:21 +0200 Subject: some changes They got a bit bundled together but they at least do the following: - read_default_cfg returns a result - command to print all server config values - command to print a single server config value - command to remove servers - Option::map instead of if let Some()-... - TryFrom instead of Try --- mumlib/src/config.rs | 64 ++++++++++++++++++---------------------------------- 1 file changed, 22 insertions(+), 42 deletions(-) (limited to 'mumlib') diff --git a/mumlib/src/config.rs b/mumlib/src/config.rs index d93b172..3e55607 100644 --- a/mumlib/src/config.rs +++ b/mumlib/src/config.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +use std::convert::TryFrom; use std::fs; use toml::Value; use toml::value::Array; @@ -9,7 +10,7 @@ struct TOMLConfig { servers: Option, } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Config { pub audio: Option, pub servers: Option>, @@ -17,7 +18,7 @@ pub struct Config { impl Config { pub fn write_default_cfg(&self) { - fs::write(get_cfg_path(), toml::to_string(&TOMLConfig::from(self)).unwrap()).unwrap(); + fs::write(get_cfg_path(), toml::to_string(&TOMLConfig::from(self.clone())).unwrap()).unwrap(); } } @@ -30,7 +31,7 @@ pub struct AudioConfig { pub struct ServerConfig { pub name: String, pub host: String, - pub port: u16, + pub port: Option, pub username: Option, pub password: Option, } @@ -39,19 +40,18 @@ fn get_cfg_path() -> String { ".mumdrc".to_string() //TODO XDG_CONFIG and whatever } -impl From for Config { - fn from(config: TOMLConfig) -> Self { - Config { +impl TryFrom for Config { + type Error = toml::de::Error; + + fn try_from(config: TOMLConfig) -> Result { + Ok(Config { audio: config.audio, - servers: if let Some(servers) = config.servers { - Some(servers - .into_iter() - .map(|s| s.try_into::().expect("invalid server config format")) - .collect()) - } else { - None - }, - } + servers: config.servers.map(|servers| servers + .into_iter() + .map(|s| s.try_into::()) + .collect()) + .transpose()?, + }) } } @@ -59,37 +59,17 @@ impl From for TOMLConfig { fn from(config: Config) -> Self { TOMLConfig { audio: config.audio, - servers: if let Some(servers) = config.servers { - Some(servers - .into_iter() - .map(|s| Value::try_from::(s).unwrap()) - .collect()) - } else { - None - }, - } - } -} - -impl From<&Config> for TOMLConfig { - fn from(config: &Config) -> Self { - TOMLConfig { - audio: config.audio.clone(), - servers: if let Some(servers) = config.servers.clone() { - Some(servers - .into_iter() - .map(|s| Value::try_from::(s).unwrap()) - .collect()) - } else { - None - }, + servers: config.servers.map(|servers| servers + .into_iter() + .map(|s| Value::try_from::(s).unwrap()) + .collect()), } } } -pub fn read_default_cfg() -> Config { - //TODO ignore when config file doesn't exist - Config::from( +pub fn read_default_cfg() -> Result { + //TODO return None if file doesn't exist (Option::map) + Config::try_from( toml::from_str::( &fs::read_to_string( get_cfg_path()) -- cgit v1.2.1 From 6a136ac842dd601ce7f68566c27b5262d221872c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustav=20S=C3=B6rn=C3=A4s?= Date: Wed, 21 Oct 2020 00:57:37 +0200 Subject: default cfg is option None if the file doesn't exist --- mumlib/src/config.rs | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) (limited to 'mumlib') diff --git a/mumlib/src/config.rs b/mumlib/src/config.rs index 3e55607..aa8a8ed 100644 --- a/mumlib/src/config.rs +++ b/mumlib/src/config.rs @@ -1,3 +1,4 @@ +use log::*; use serde::{Deserialize, Serialize}; use std::convert::TryFrom; use std::fs; @@ -17,8 +18,23 @@ pub struct Config { } impl Config { - pub fn write_default_cfg(&self) { - fs::write(get_cfg_path(), toml::to_string(&TOMLConfig::from(self.clone())).unwrap()).unwrap(); + pub fn write_default_cfg(&self) -> Result<(), std::io::Error> { + let path = get_cfg_path(); + let path = std::path::Path::new(&path); + // Possible race here. It's fine since it shows when: + // 1) the file doesn't exist when checked and is then created + // 2) the file exists when checked but is then removed + // If 1) we don't do anything anyway so it's fine, and if 2) we + // immediately re-create the file which, while not perfect, at least + // should work. Unless the file is removed AND the permissions + // change, but then we don't have permissions so we can't + // do anything anyways. + if !path.exists() { + warn!("config file {} does not exist, ignoring", path.display()); + Ok(()) + } else { + fs::write(path, toml::to_string(&TOMLConfig::from(self.clone())).unwrap()) + } } } @@ -67,13 +83,17 @@ impl From for TOMLConfig { } } -pub fn read_default_cfg() -> Result { - //TODO return None if file doesn't exist (Option::map) - Config::try_from( +pub fn read_default_cfg() -> Option { + Some(Config::try_from( toml::from_str::( - &fs::read_to_string( - get_cfg_path()) - .expect("config file not found") - .to_string()) - .unwrap()) + &match fs::read_to_string(get_cfg_path()) { + Ok(f) => { + f.to_string() + }, + Err(_) => { + return None + } + } + ).expect("invalid TOML in config file") //TODO + ).expect("invalid config in TOML")) //TODO } -- cgit v1.2.1