use anyhow::Context; use config::runner::RunnerConfig; use std::path::PathBuf; use crate::config::ensure_parent; pub fn credential_path(cfg: &RunnerConfig) -> PathBuf { PathBuf::from(&cfg.credential_path) } pub fn load_credential(cfg: &RunnerConfig) -> anyhow::Result> { let path = credential_path(cfg); match std::fs::read_to_string(&path) { Ok(text) => { let trimmed = text.trim().to_string(); if trimmed.is_empty() { return Ok(None); } Ok(Some(trimmed)) } Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(None), Err(error) => Err(error).with_context(|| format!("reading {}", path.display())), } } pub fn store_credential(cfg: &RunnerConfig, credential: &str) -> anyhow::Result<()> { let path = credential_path(cfg); ensure_parent(&path)?; std::fs::write(&path, credential).with_context(|| format!("writing {}", path.display()))?; restrict_permissions(&path)?; Ok(()) } #[cfg(unix)] fn restrict_permissions(path: &std::path::Path) -> anyhow::Result<()> { use std::os::unix::fs::PermissionsExt; std::fs::set_permissions(path, std::fs::Permissions::from_mode(0o600)) .with_context(|| format!("setting permissions on {}", path.display()))?; Ok(()) } #[cfg(not(unix))] fn restrict_permissions(_path: &std::path::Path) -> anyhow::Result<()> { Ok(()) }