diff --git a/Cargo.lock b/Cargo.lock index 73da79e71..0cc2e5e72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -62,12 +62,6 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - [[package]] name = "arti" version = "0.0.4" @@ -628,12 +622,14 @@ dependencies = [ [[package]] name = "config" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1b9d958c2b1368a663f05538fc1b5975adce1e19f435acceae987aceeeb369" +checksum = "54ad70579325f1a38ea4c13412b82241c5900700a69785d73e2736bd65a33f86" dependencies = [ + "async-trait", "lazy_static", "nom", + "pathdiff", "serde", "toml", ] @@ -1561,19 +1557,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" -[[package]] -name = "lexical-core" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" -dependencies = [ - "arrayvec", - "bitflags", - "cfg-if 1.0.0", - "ryu", - "static_assertions", -] - [[package]] name = "libc" version = "0.2.115" @@ -1678,6 +1661,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.4.4" @@ -1797,12 +1786,12 @@ dependencies = [ [[package]] name = "nom" -version = "5.1.2" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" dependencies = [ - "lexical-core", "memchr", + "minimal-lexical", "version_check", ] @@ -2007,6 +1996,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + [[package]] name = "pem-rfc7468" version = "0.2.4" @@ -2868,9 +2863,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.6.9" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" +checksum = "64910e1b9c1901aaf5375561e35b9c057d95ff41a44ede043a03e09279eabaf1" dependencies = [ "bytes", "futures-core", diff --git a/crates/arti-bench/src/main.rs b/crates/arti-bench/src/main.rs index a7fd446a6..ba0233d8a 100644 --- a/crates/arti-bench/src/main.rs +++ b/crates/arti-bench/src/main.rs @@ -46,6 +46,7 @@ use rand::distributions::Standard; use rand::Rng; use serde::{Deserialize, Serialize}; use std::collections::HashMap; +use std::convert::TryInto; use std::fmt; use std::fmt::Formatter; use std::future::Future; diff --git a/crates/arti-config/Cargo.toml b/crates/arti-config/Cargo.toml index 242932a38..5e4f0731f 100644 --- a/crates/arti-config/Cargo.toml +++ b/crates/arti-config/Cargo.toml @@ -14,7 +14,7 @@ repository="https://gitlab.torproject.org/tpo/core/arti.git/" arti-client = { package="arti-client", path = "../arti-client", version = "0.0.4"} tor-circmgr = { package="tor-circmgr", path="../tor-circmgr", version = "0.0.4"} tor-config = { package="tor-config", path = "../tor-config", version = "0.0.4", features = ["expand-paths"]} -config = { version = "0.11.0", default-features = false, features = ["toml"] } +config = { version = "0.12.0", default-features = false, features = ["toml"] } once_cell = "1" serde = { version = "1.0.103", features = ["derive"] } toml = "0.5" diff --git a/crates/arti-config/src/lib.rs b/crates/arti-config/src/lib.rs index 926bbf278..07b5a89cf 100644 --- a/crates/arti-config/src/lib.rs +++ b/crates/arti-config/src/lib.rs @@ -51,6 +51,11 @@ pub use options::{ }; use tor_config::CfgPath; +/// The synchronous configuration builder type we use. +/// +/// (This is a type alias that config should really provide.) +type ConfigBuilder = config::builder::ConfigBuilder; + use std::path::{Path, PathBuf}; /// A description of where to find our configuration options. @@ -116,38 +121,41 @@ impl ConfigurationSources { /// Load the configuration into a new [`config::Config`]. pub fn load(&self) -> Result { - let mut config = config::Config::new(); - config.merge(config::File::from_str( + let mut builder = config::Config::builder(); + builder = builder.add_source(config::File::from_str( options::ARTI_DEFAULTS, config::FileFormat::Toml, - ))?; - load_mut(&mut config, &self.files, &self.options)?; - Ok(config) + )); + builder = add_sources(builder, &self.files, &self.options); + builder.build() } } -/// As [`ConfigurationSources::load()`], but load into a mutable `Config` -/// object. -fn load_mut>( - cfg: &mut config::Config, +/// Add every file and commandline source to `builder`, returning a new +/// builder. +fn add_sources

( + mut builder: ConfigBuilder, files: &[(P, MustRead)], opts: &[String], -) -> Result<(), config::ConfigError> { +) -> ConfigBuilder +where + P: AsRef, +{ for (path, must_read) in files { // Not going to use File::with_name here, since it doesn't // quite do what we want. - let f: config::File<_> = path.as_ref().into(); + let f: config::File<_, _> = path.as_ref().into(); let required = must_read == &MustRead::MustRead; - cfg.merge(f.format(config::FileFormat::Toml).required(required))?; + builder = builder.add_source(f.format(config::FileFormat::Toml).required(required)); } let mut cmdline = CmdLine::new(); for opt in opts { cmdline.push_toml_line(opt.clone()); } - cfg.merge(cmdline)?; + builder = builder.add_source(cmdline); - Ok(()) + builder } /// Return a filename for the default user configuration file. @@ -167,13 +175,21 @@ world = \"stuff\" friends = 4242 "; + /// Load from a set of files and option strings, without taking + /// the arti defaults into account. + fn load_nodefaults>( + files: &[(P, MustRead)], + opts: &[String], + ) -> Result { + add_sources(config::Config::builder(), files, opts).build() + } + #[test] fn non_required_file() { let td = tempdir().unwrap(); let dflt = td.path().join("a_file"); let files = vec![(dflt, MustRead::TolerateAbsence)]; - let mut c = config::Config::new(); - load_mut(&mut c, &files, Default::default()).unwrap(); + load_nodefaults(&files, Default::default()).unwrap(); } static EX2_TOML: &str = " @@ -186,13 +202,12 @@ world = \"nonsense\" let td = tempdir().unwrap(); let dflt = td.path().join("a_file"); let cf = td.path().join("other_file"); - let mut c = config::Config::new(); std::fs::write(&cf, EX2_TOML).unwrap(); let files = vec![(dflt, MustRead::TolerateAbsence), (cf, MustRead::MustRead)]; - load_mut(&mut c, &files, Default::default()).unwrap(); + let c = load_nodefaults(&files, Default::default()).unwrap(); - assert!(c.get_str("hello.friends").is_err()); - assert_eq!(c.get_str("hello.world").unwrap(), "nonsense".to_string()); + assert!(c.get_string("hello.friends").is_err()); + assert_eq!(c.get_string("hello.world").unwrap(), "nonsense".to_string()); } #[test] @@ -200,16 +215,15 @@ world = \"nonsense\" let td = tempdir().unwrap(); let cf1 = td.path().join("a_file"); let cf2 = td.path().join("other_file"); - let mut c = config::Config::new(); std::fs::write(&cf1, EX_TOML).unwrap(); std::fs::write(&cf2, EX2_TOML).unwrap(); let v = vec![(cf1, MustRead::TolerateAbsence), (cf2, MustRead::MustRead)]; let v2 = vec!["other.var=present".to_string()]; - load_mut(&mut c, &v, &v2).unwrap(); + let c = load_nodefaults(&v, &v2).unwrap(); - assert_eq!(c.get_str("hello.friends").unwrap(), "4242".to_string()); - assert_eq!(c.get_str("hello.world").unwrap(), "nonsense".to_string()); - assert_eq!(c.get_str("other.var").unwrap(), "present".to_string()); + assert_eq!(c.get_string("hello.friends").unwrap(), "4242".to_string()); + assert_eq!(c.get_string("hello.world").unwrap(), "nonsense".to_string()); + assert_eq!(c.get_string("other.var").unwrap(), "present".to_string()); } #[test] diff --git a/crates/arti-config/src/options.rs b/crates/arti-config/src/options.rs index 3e65c1d13..4d832f424 100644 --- a/crates/arti-config/src/options.rs +++ b/crates/arti-config/src/options.rs @@ -10,6 +10,7 @@ use arti_client::config::{ use derive_builder::Builder; use serde::Deserialize; use std::collections::HashMap; +use std::convert::TryFrom; use tor_config::{CfgPath, ConfigBuildError}; /// Default options to use for our configuration. @@ -288,6 +289,13 @@ pub struct ArtiConfig { system: SystemConfig, } +impl TryFrom for ArtiConfig { + type Error = config::ConfigError; + fn try_from(cfg: config::Config) -> Result { + cfg.try_deserialize() + } +} + impl From for TorClientConfigBuilder { fn from(cfg: ArtiConfig) -> TorClientConfigBuilder { let mut builder = TorClientConfig::builder(); @@ -570,6 +578,7 @@ impl From for ArtiConfigBuilder { mod test { #![allow(clippy::unwrap_used)] + use std::convert::TryInto; use std::time::Duration; use super::*; @@ -577,12 +586,13 @@ mod test { #[test] fn default_config() { // TODO: this is duplicate code. - let mut cfg = config::Config::new(); - cfg.merge(config::File::from_str( - ARTI_DEFAULTS, - config::FileFormat::Toml, - )) - .unwrap(); + let cfg = config::Config::builder() + .add_source(config::File::from_str( + ARTI_DEFAULTS, + config::FileFormat::Toml, + )) + .build() + .unwrap(); let parsed: ArtiConfig = cfg.try_into().unwrap(); let default = ArtiConfig::default(); diff --git a/crates/arti/Cargo.toml b/crates/arti/Cargo.toml index 4daad924a..4e83e59a9 100644 --- a/crates/arti/Cargo.toml +++ b/crates/arti/Cargo.toml @@ -28,7 +28,7 @@ arti-config = { path="../arti-config", version = "0.0.4"} anyhow = "1.0.23" async-ctrlc = { version = "1.2.0", optional = true } -config = { version = "0.11.0", default-features = false } +config = { version = "0.12.0", default-features = false } cfg-if = "1.0.0" futures = "0.3.14" tracing = "0.1.18" diff --git a/crates/arti/src/main.rs b/crates/arti/src/main.rs index 448591e8e..46d1b2580 100644 --- a/crates/arti/src/main.rs +++ b/crates/arti/src/main.rs @@ -101,6 +101,8 @@ use anyhow::{Context, Result}; use clap::{App, AppSettings, Arg, SubCommand}; use tracing::{info, warn}; +use std::convert::TryInto; + /// Run the main loop of the proxy. async fn run( runtime: R, diff --git a/crates/arti/src/watch_cfg.rs b/crates/arti/src/watch_cfg.rs index 8655cb032..f126a7c96 100644 --- a/crates/arti/src/watch_cfg.rs +++ b/crates/arti/src/watch_cfg.rs @@ -1,6 +1,7 @@ //! Code to watch configuration files for any changes. use std::collections::HashSet; +use std::convert::TryInto; use std::path::{Path, PathBuf}; use std::sync::mpsc::channel as std_channel; use std::time::Duration;