From 232fad205ff17970d2c30625c0fccf8b31842d9d Mon Sep 17 00:00:00 2001 From: Casey Rodarmor Date: Fri, 11 Oct 2024 20:05:07 -0700 Subject: [PATCH] Avoid using `std::fs` directly (#73) --- src/filesystem.rs | 25 +++++++++++++++++++------ src/io_result_ext.rs | 39 --------------------------------------- src/main.rs | 13 ++++++------- src/manifest.rs | 6 +++--- src/metadata.rs | 4 ++-- src/private_key.rs | 10 +++------- src/public_key.rs | 10 +++------- src/subcommand/create.rs | 14 +++++--------- src/subcommand/keygen.rs | 11 +++++------ src/subcommand/sign.rs | 2 +- src/subcommand/verify.rs | 26 +++++++++----------------- tests/create.rs | 30 +++++++++++++++++------------- 12 files changed, 73 insertions(+), 117 deletions(-) delete mode 100644 src/io_result_ext.rs diff --git a/src/filesystem.rs b/src/filesystem.rs index 11a9895..2c25be2 100644 --- a/src/filesystem.rs +++ b/src/filesystem.rs @@ -1,17 +1,30 @@ use super::*; -pub(crate) fn read_to_string(path: &Utf8Path) -> Result { - std::fs::read_to_string(path).context(error::Io { path }) +pub(crate) fn create_dir_all(path: &Utf8Path) -> Result<()> { + std::fs::create_dir_all(path).context(error::Io { path }) +} + +pub(crate) fn exists(path: &Utf8Path) -> Result { + path.try_exists().context(error::Io { path }) } pub(crate) fn metadata(path: &Utf8Path) -> Result { std::fs::metadata(path).context(error::Io { path }) } -pub(crate) fn write(path: &Utf8Path, contents: &[u8]) -> Result { - std::fs::write(path, contents).context(error::Io { path }) +pub(crate) fn read_to_string(path: impl AsRef) -> Result { + std::fs::read_to_string(path.as_ref()).context(error::Io { + path: path.as_ref(), + }) } -pub(crate) fn exists(path: &Utf8Path) -> Result { - path.try_exists().context(error::Io { path }) +pub(crate) fn read_to_string_opt(path: &Utf8Path) -> Result> { + match std::fs::read_to_string(path) { + Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(None), + result => result.map(Some).context(error::Io { path }), + } +} + +pub(crate) fn write(path: &Utf8Path, contents: impl AsRef<[u8]>) -> Result { + std::fs::write(path, contents).context(error::Io { path }) } diff --git a/src/io_result_ext.rs b/src/io_result_ext.rs deleted file mode 100644 index 810ab6a..0000000 --- a/src/io_result_ext.rs +++ /dev/null @@ -1,39 +0,0 @@ -use super::*; - -pub(crate) trait IoResultExt { - fn into_option(self) -> io::Result>; -} - -impl IoResultExt for io::Result { - fn into_option(self) -> io::Result> { - match self { - Err(err) => { - if err.kind() == io::ErrorKind::NotFound { - Ok(None) - } else { - Err(err) - } - } - Ok(value) => Ok(Some(value)), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn into_option() { - Err::<(), io::Error>(io::Error::new(io::ErrorKind::InvalidInput, "foo")) - .into_option() - .unwrap_err(); - - assert_eq!( - Err::<(), io::Error>(io::Error::new(io::ErrorKind::NotFound, "foo")) - .into_option() - .unwrap(), - None, - ); - } -} diff --git a/src/main.rs b/src/main.rs index e534af4..d1d52eb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,11 @@ use { self::{ arguments::Arguments, bytes::Bytes, display_path::DisplayPath, display_secret::DisplaySecret, - entry::Entry, error::Error, hash::Hash, io_result_ext::IoResultExt, lint::Lint, - lint_group::LintGroup, list::List, manifest::Manifest, metadata::Metadata, options::Options, - owo_colorize_ext::OwoColorizeExt, page::Page, private_key::PrivateKey, public_key::PublicKey, - relative_path::RelativePath, signature::Signature, signature_error::SignatureError, - style::Style, subcommand::Subcommand, template::Template, utf8_path_ext::Utf8PathExt, + entry::Entry, error::Error, hash::Hash, lint::Lint, lint_group::LintGroup, list::List, + manifest::Manifest, metadata::Metadata, options::Options, owo_colorize_ext::OwoColorizeExt, + page::Page, private_key::PrivateKey, public_key::PublicKey, relative_path::RelativePath, + signature::Signature, signature_error::SignatureError, style::Style, subcommand::Subcommand, + template::Template, utf8_path_ext::Utf8PathExt, }, blake3::Hasher, boilerplate::Boilerplate, @@ -25,7 +25,7 @@ use { collections::{BTreeMap, HashMap, HashSet}, env, fmt::{self, Display, Formatter}, - fs::{self, File}, + fs::File, io::{self, IsTerminal}, path::{Path, PathBuf}, process, @@ -45,7 +45,6 @@ mod entry; mod error; mod filesystem; mod hash; -mod io_result_ext; mod lint; mod lint_group; mod list; diff --git a/src/manifest.rs b/src/manifest.rs index 9bb2a5e..cd2cca1 100644 --- a/src/manifest.rs +++ b/src/manifest.rs @@ -30,8 +30,8 @@ impl Manifest { .context(error::DeserializeManifest { path }) } - pub(crate) fn to_json(&self) -> String { - serde_json::to_string(self).unwrap() + pub(crate) fn store(&self, path: &Utf8Path) -> Result<()> { + filesystem::write(path, format!("{}\n", serde_json::to_string(self).unwrap())) } pub(crate) fn total_size(&self) -> u64 { @@ -45,7 +45,7 @@ mod tests { #[test] fn manifests_in_readme_are_valid() { - let readme = fs::read_to_string("README.md").unwrap(); + let readme = filesystem::read_to_string("README.md").unwrap(); let re = Regex::new(r"(?s)```json(.*?)```").unwrap(); diff --git a/src/metadata.rs b/src/metadata.rs index 2971d1f..6928205 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -14,8 +14,8 @@ impl Metadata { .context(error::DeserializeMetadata { path }) } - pub(crate) fn to_json(&self) -> String { - serde_json::to_string(self).unwrap() + pub(crate) fn store(&self, path: &Utf8Path) -> Result<()> { + filesystem::write(path, format!("{}\n", serde_json::to_string(self).unwrap())) } } diff --git a/src/private_key.rs b/src/private_key.rs index 95a160f..3172b02 100644 --- a/src/private_key.rs +++ b/src/private_key.rs @@ -37,12 +37,8 @@ impl PrivateKey { } pub(crate) fn load(path: &Utf8Path) -> Result { - let private_key = match fs::read_to_string(path) { - Err(err) if err.kind() == io::ErrorKind::NotFound => { - return Err(error::PrivateKeyNotFound { path }.build()) - } - result => result.context(error::Io { path })?, - }; + let private_key = filesystem::read_to_string_opt(path)? + .ok_or_else(|| error::PrivateKeyNotFound { path }.build())?; let private_key = private_key .trim() @@ -129,7 +125,7 @@ mod tests { .parse::() .unwrap(); - fs::write(&path, format!(" \t{}\n", key.display_secret())).unwrap(); + filesystem::write(&path, format!(" \t{}\n", key.display_secret())).unwrap(); assert_eq!(PrivateKey::load(&path).unwrap(), key); } diff --git a/src/public_key.rs b/src/public_key.rs index 874693b..ef861af 100644 --- a/src/public_key.rs +++ b/src/public_key.rs @@ -27,12 +27,8 @@ impl PublicKey { const LEN: usize = ed25519_dalek::PUBLIC_KEY_LENGTH; pub(crate) fn load(path: &Utf8Path) -> Result { - let public_key = match fs::read_to_string(path) { - Err(err) if err.kind() == io::ErrorKind::NotFound => { - return Err(error::PublicKeyNotFound { path }.build()) - } - result => result.context(error::Io { path })?, - }; + let public_key = filesystem::read_to_string_opt(path)? + .ok_or_else(|| error::PublicKeyNotFound { path }.build())?; let public_key = public_key .trim() @@ -132,7 +128,7 @@ mod tests { .parse::() .unwrap(); - fs::write(&path, format!(" \t{key}\n")).unwrap(); + filesystem::write(&path, format!(" \t{key}\n")).unwrap(); assert_eq!(PublicKey::load(&path).unwrap(), key); } diff --git a/src/subcommand/create.rs b/src/subcommand/create.rs index 5d4dcd3..e1f63de 100644 --- a/src/subcommand/create.rs +++ b/src/subcommand/create.rs @@ -32,17 +32,15 @@ impl Create { }; if let Some(path) = &self.metadata { - let yaml = fs::read_to_string(path).context(error::Io { path })?; + let yaml = filesystem::read_to_string(path)?; let template = serde_yaml::from_str::