Skip to content

Commit d14091e

Browse files
authored
Add basic config parsing (#10)
* Add README with example configuration * Add high level configuration struct * Enable loading configuration from TOML * Add test to parse example configuration * Add saving configuration todo * Use String for now in `Config` intead of `SshPublicKey` directly to pass tests * Add default configuration path * Add benchmark for loading configuration * Make all config keys optional * Add default sources in config
1 parent 355f51d commit d14091e

File tree

8 files changed

+369
-7
lines changed

8 files changed

+369
-7
lines changed

Cargo.lock

+103
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+7-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ edition = "2021"
88
[dependencies]
99
async-trait = "0.1.79"
1010
chrono = "0.4.37"
11-
clap = { version = "4.5.4", features = ["derive"] }
11+
clap = { version = "4.5.4", features = ["derive", "env", "string"] }
12+
figment = { version = "0.10.16", features = ["toml"] }
1213
reqwest = { version = "0.12.2", features = ["json"] }
1314
serde = { version = "1.0.197", features = ["derive"] }
1415
tokio = { version = "1.37.0", features = ["full"] }
@@ -17,9 +18,14 @@ tokio = { version = "1.37.0", features = ["full"] }
1718
codspeed-criterion-compat = "2.4.1"
1819
criterion = "0.5.1"
1920
httpmock = "0.7.0"
21+
indoc = "2.0.5"
2022
rstest = "0.19.0"
2123
tempfile = "3.10.1"
2224

2325
[[bench]]
2426
name = "write_allowed_signers"
2527
harness = false
28+
29+
[[bench]]
30+
name = "load_configuration"
31+
harness = false

README.md

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Example Configuration
2+
3+
```toml
4+
users = [
5+
{ name = "torvalds", sources = ["github"] },
6+
{ name = "gvanrossum", sources = ["github", "gitlab"] },
7+
{ name = "graydon", sources = ["github"] },
8+
{ name = "cwoods", sources = ["acme-corp"] },
9+
{ name = "rdavis", sources = ["acme-corp"] },
10+
{ name = "pbrock", sources = ["acme-corp"] }
11+
]
12+
organizations = [
13+
{ name = "rust-lang", sources = ["github"] }
14+
]
15+
local = [
16+
"jdoe@example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJHDGMF+tZQL3dcr1arPst+YP8v33Is0kAJVvyTKrxMw"
17+
]
18+
19+
[[sources]]
20+
name = "acme-corp"
21+
provider = "gitlab"
22+
url = "https://git.acme.corp"
23+
```

benches/load_configuration.rs

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
use codspeed_criterion_compat::{criterion_group, criterion_main, Criterion};
2+
use hanko::Config;
3+
use indoc::indoc;
4+
use std::{io::Write, path::Path};
5+
6+
pub fn criterion_benchmark(c: &mut Criterion) {
7+
let toml = indoc! {r#"
8+
users = [
9+
{ name = "torvalds", sources = ["github"] },
10+
{ name = "gvanrossum", sources = ["github", "gitlab"] },
11+
{ name = "graydon", sources = ["github"] },
12+
{ name = "cwoods", sources = ["acme-corp"] },
13+
{ name = "rdavis", sources = ["acme-corp"] },
14+
{ name = "pbrock", sources = ["acme-corp"] }
15+
]
16+
organizations = [
17+
{ name = "rust-lang", sources = ["github"] }
18+
]
19+
local = [
20+
"jdoe@example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJHDGMF+tZQL3dcr1arPst+YP8v33Is0kAJVvyTKrxMw"
21+
]
22+
23+
[[sources]]
24+
name = "acme-corp"
25+
provider = "gitlab"
26+
url = "https://git.acme.corp"
27+
"#};
28+
let mut file = tempfile::NamedTempFile::new().unwrap();
29+
file.write_all(toml.as_bytes()).unwrap();
30+
let path: &Path = &file.into_temp_path();
31+
32+
c.bench_function("load the example configuration", |b| {
33+
b.iter(|| Config::load(path).unwrap());
34+
});
35+
}
36+
37+
criterion_group!(benches, criterion_benchmark);
38+
criterion_main!(benches);

src/cli/main.rs

+28-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
use super::{manage_signers::ManageSigners, manage_sources::ManageSources};
2-
use clap::{Args, Parser, Subcommand};
3-
use std::path::PathBuf;
2+
use clap::{
3+
builder::{OsStr, Resettable},
4+
Args, Parser, Subcommand,
5+
};
6+
use std::{env, path::PathBuf};
47

58
#[derive(Parser)]
69
#[command(version, about, long_about = None)]
710
pub struct Cli {
811
/// The path to the configuration file.
9-
#[arg(short, long, value_name = "FILE")]
10-
config: Option<PathBuf>,
12+
#[arg(
13+
short,
14+
long,
15+
value_name = "FILE",
16+
env = "HANKO_CONFIG",
17+
default_value = default_config_path()
18+
)]
19+
pub config: PathBuf,
1120

1221
#[command(flatten)]
1322
logging: Logging,
@@ -42,6 +51,21 @@ enum Commands {
4251
Source(ManageSources),
4352
}
4453

54+
/// The default configuration file path according to the XDG Base Directory Specification.
55+
/// If neither `$XDG_CONFIG_HOME` nor `$HOME` are set, `Resettable::Reset` is returned, forcing the user to specify the path.
56+
fn default_config_path() -> Resettable<OsStr> {
57+
let dirname = env!("CARGO_PKG_NAME");
58+
let filename = "config.toml";
59+
60+
if let Ok(xdg_config_home) = env::var("XDG_CONFIG_HOME") {
61+
Resettable::Value(format!("{}/{}/{}", xdg_config_home, dirname, filename).into())
62+
} else if let Ok(home) = env::var("HOME") {
63+
Resettable::Value(format!("{}/.config/{}/{}", home, dirname, filename).into())
64+
} else {
65+
Resettable::Reset
66+
}
67+
}
68+
4569
#[cfg(test)]
4670
mod tests {
4771
use super::*;

0 commit comments

Comments
 (0)