chore: apply cargo fmt to core crate

config.rs had two single-line struct variants and a let-chain that
rustfmt (edition 2024) wants expanded; db.rs test module picked up the
same treatment. Whitespace-only - no behaviour change.

Why: 'cargo fmt --check' is part of every task's definition of done,
and main was handing over slightly dirty.
This commit is contained in:
hermes
2026-10-08 12:38:56 +02:00
parent a350afc053
commit e7acfcf899
2 changed files with 89 additions and 26 deletions
+50 -17
View File
@@ -18,9 +18,17 @@ pub enum ConfigError {
#[error("config file not found: {0}")]
NotFound(PathBuf),
#[error("failed to read config file {path}: {source}")]
Io { path: PathBuf, #[source] source: std::io::Error },
Io {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("failed to parse config file {path}: {source}")]
Parse { path: PathBuf, #[source] source: toml::de::Error },
Parse {
path: PathBuf,
#[source]
source: toml::de::Error,
},
#[error("invalid config: {field} — {message}")]
Invalid { field: String, message: String },
}
@@ -145,12 +153,13 @@ pub const DEFAULT_WEB_PORT: u16 = 8080;
impl Config {
/// Load from `path`, deriving the default state dir from `$HOME`.
pub fn load(path: &Path) -> Result<Config, ConfigError> {
let home = std::env::var_os("HOME").map(PathBuf::from).ok_or_else(|| {
ConfigError::Invalid {
field: "state.dir".to_string(),
message: "$HOME is unset; set [state].dir explicitly".to_string(),
}
})?;
let home =
std::env::var_os("HOME")
.map(PathBuf::from)
.ok_or_else(|| ConfigError::Invalid {
field: "state.dir".to_string(),
message: "$HOME is unset; set [state].dir explicitly".to_string(),
})?;
Self::load_with(path, &home)
}
@@ -160,17 +169,25 @@ impl Config {
if e.kind() == std::io::ErrorKind::NotFound {
ConfigError::NotFound(path.to_path_buf())
} else {
ConfigError::Io { path: path.to_path_buf(), source: e }
ConfigError::Io {
path: path.to_path_buf(),
source: e,
}
}
})?;
let raw: RawConfig =
toml::from_str(&text).map_err(|e| ConfigError::Parse { path: path.to_path_buf(), source: e })?;
let raw: RawConfig = toml::from_str(&text).map_err(|e| ConfigError::Parse {
path: path.to_path_buf(),
source: e,
})?;
Self::from_raw(raw, home)
}
fn from_raw(raw: RawConfig, home: &Path) -> Result<Config, ConfigError> {
let state = if raw.state.dir.is_empty() {
home.join(".config").join("rpn").to_string_lossy().into_owned()
home.join(".config")
.join("rpn")
.to_string_lossy()
.into_owned()
} else {
raw.state.dir.clone()
};
@@ -186,7 +203,10 @@ impl Config {
Ok(Config {
database: DatabaseConfig {
host: raw.database.host,
port: raw.database.port.as_port("database.port", DEFAULT_DATABASE_PORT)?,
port: raw
.database
.port
.as_port("database.port", DEFAULT_DATABASE_PORT)?,
user: raw.database.user,
password: raw.database.password,
name: raw.database.name,
@@ -202,7 +222,13 @@ impl Config {
/// Human-readable rendering with the password masked.
pub fn show(&self) -> String {
let mask = |s: &str| if s.is_empty() { String::new() } else { "***".to_string() };
let mask = |s: &str| {
if s.is_empty() {
String::new()
} else {
"***".to_string()
}
};
format!(
"[database]\n\
host = \"{}\"\n\
@@ -320,7 +346,10 @@ dir = "/var/backup/rpn"
let d = tempfile::tempdir().unwrap();
let p = d.path().join("nope.toml");
let err = Config::load_with(&p, Path::new("/home/u")).unwrap_err();
assert!(matches!(err, ConfigError::NotFound(ref q) if *q == p), "{err:?}");
assert!(
matches!(err, ConfigError::NotFound(ref q) if *q == p),
"{err:?}"
);
}
#[test]
@@ -424,7 +453,10 @@ dir = \"/opt/rpn\"
let (_d, p) = dir_with("config.toml", FULL_TOML);
let cfg = Config::load_with(&p, Path::new("/home/u")).unwrap();
let s = cfg.show();
assert!(!s.contains("hunter2"), "password leaked into show output:\n{s}");
assert!(
!s.contains("hunter2"),
"password leaked into show output:\n{s}"
);
assert!(s.contains("***"), "{s}");
assert!(s.contains("alice"), "user should remain visible:\n{s}");
}
@@ -441,7 +473,8 @@ dir = \"/opt/rpn\"
#[test]
fn validate_database_requires_host_user_name() {
let body = "[database]\nhost = \"\"\nport = \"\"\nuser = \"u\"\npassword = \"\"\nname = \"\"\n";
let body =
"[database]\nhost = \"\"\nport = \"\"\nuser = \"u\"\npassword = \"\"\nname = \"\"\n";
let (_d, p) = dir_with("config.toml", body);
let cfg = Config::load_with(&p, Path::new("/home/u")).unwrap();
let err = cfg.validate_database().unwrap_err();
+39 -9
View File
@@ -22,9 +22,16 @@ mod tests {
password: "pw".into(),
name: "rpn".into(),
},
web: WebConfig { port: 8080, fqdn: String::new() },
state: StateConfig { dir: "/tmp/rpn".into() },
backup: BackupConfig { dir: "/tmp/rpn/backups".into() },
web: WebConfig {
port: 8080,
fqdn: String::new(),
},
state: StateConfig {
dir: "/tmp/rpn".into(),
},
backup: BackupConfig {
dir: "/tmp/rpn/backups".into(),
},
}
}
@@ -37,7 +44,10 @@ mod tests {
#[test]
fn connection_url_with_database() {
let cfg = test_config();
assert_eq!(connection_url(&cfg, true), "mysql://u:***@db.example:3307/rpn");
assert_eq!(
connection_url(&cfg, true),
"mysql://u:***@db.example:3307/rpn"
);
}
#[test]
@@ -82,8 +92,19 @@ mod tests {
#[test]
fn embedded_migration_is_schema_v1() {
for table in ["files", "customers", "batches", "cards", "transactions", "invoices", "invoice_items"] {
assert!(MIGRATION_V1.contains(&format!("CREATE TABLE {table}")), "{table}");
for table in [
"files",
"customers",
"batches",
"cards",
"transactions",
"invoices",
"invoice_items",
] {
assert!(
MIGRATION_V1.contains(&format!("CREATE TABLE {table}")),
"{table}"
);
}
// the migrations bookkeeping table is created by the app, not the file
assert!(!MIGRATION_V1.contains("CREATE TABLE schema_migrations"));
@@ -92,11 +113,17 @@ mod tests {
#[test]
fn backup_command_uses_dump_client() {
let (program, args, use_pwd) = backup_command(&test_config());
assert!(program == "mariadb-dump" || program == "mysqldump", "{program}");
assert!(
program == "mariadb-dump" || program == "mysqldump",
"{program}"
);
assert!(args.iter().any(|a| a == "--host=db.example"), "{args:?}");
assert!(args.iter().any(|a| a == "--port=3307"), "{args:?}");
assert!(args.iter().any(|a| a == "--user=u"), "{args:?}");
assert!(!args.iter().any(|a| a.contains("pw")), "password on argv: {args:?}");
assert!(
!args.iter().any(|a| a.contains("pw")),
"password on argv: {args:?}"
);
assert!(use_pwd, "MYSQL_PWD must be set for the dump client");
assert!(args.iter().any(|a| a == "--single-transaction"), "{args:?}");
assert!(args.iter().any(|a| a == "--databases"), "{args:?}");
@@ -113,7 +140,10 @@ mod tests {
assert!(program == "mariadb" || program == "mysql", "{program}");
assert!(args.iter().any(|a| a == "--host=db.example"), "{args:?}");
assert!(args.iter().any(|a| a == "rpn"), "{args:?}");
assert!(!args.iter().any(|a| a.contains(".sql")), "file must not be on argv: {args:?}");
assert!(
!args.iter().any(|a| a.contains(".sql")),
"file must not be on argv: {args:?}"
);
assert!(use_pwd);
}