From 82443337546478c91bf97f71295e98d31bb13c67 Mon Sep 17 00:00:00 2001 From: Eduardo Trujillo <ed@chromabits.com> Date: Tue, 15 Nov 2022 12:47:41 -0800 Subject: [PATCH] refactor(bundle): Use rundir module from collective crate --- src/bundle/mod.rs | 9 +- src/bundle/rundir.rs | 266 ------------------------------------------- 2 files changed, 4 insertions(+), 271 deletions(-) delete mode 100644 src/bundle/rundir.rs diff --git a/src/bundle/mod.rs b/src/bundle/mod.rs index 69f291f..1ec4c56 100644 --- a/src/bundle/mod.rs +++ b/src/bundle/mod.rs @@ -1,5 +1,5 @@ use crate::config::Config; -use rundir::RunDir; +use collective::rundir::{self, RunDir}; use s3::packager::S3BundlePackager; use serde::Serialize; use snafu::{ResultExt, Snafu}; @@ -14,19 +14,18 @@ use self::{local_dir::poller::LocalBundlePoller, s3::poller::S3BundlePoller}; pub mod local_dir; pub mod packager; pub mod poller; -pub mod rundir; pub mod s3; #[derive(Snafu, Debug)] pub enum Error { - InitRunDir { source: rundir::Error }, - DeinitRunDir { source: rundir::Error }, + InitRunDir { source: rundir::RunDirError }, + DeinitRunDir { source: rundir::RunDirError }, LockRead, LockWrite, AttachSignalHook { source: std::io::Error }, MissingETag, PollError { source: poller::Error }, - SubDirError { source: rundir::Error }, + SubDirError { source: rundir::RunDirError }, } type Result<T, E = Error> = std::result::Result<T, E>; diff --git a/src/bundle/rundir.rs b/src/bundle/rundir.rs deleted file mode 100644 index fca7507..0000000 --- a/src/bundle/rundir.rs +++ /dev/null @@ -1,266 +0,0 @@ -use snafu::{ResultExt, Snafu}; -use std::path::{Path, PathBuf}; - -#[derive(Snafu, Debug)] -pub enum Error { - Initialize { - path: PathBuf, - }, - PathIsNotDir { - path: PathBuf, - }, - DirIsNotEmpty { - path: PathBuf, - child_path: PathBuf, - }, - CreateDir { - path: PathBuf, - source: std::io::Error, - }, - ScanDir { - path: PathBuf, - source: std::io::Error, - }, - RecreateDir { - path: PathBuf, - source: std::io::Error, - }, - RemoveSubDir { - path: PathBuf, - source: std::io::Error, - }, - InvalidSubDirName { - name: String, - inner_error: Option<std::io::Error>, - }, -} - -type Result<T, E = Error> = std::result::Result<T, E>; - -pub struct RunDir { - path: PathBuf, - allow_cleaning: bool, -} - -impl RunDir { - pub fn new<T: Into<PathBuf>>(path: T) -> RunDir { - RunDir { - path: path.into(), - allow_cleaning: false, - } - } - - /// Set whether the directory can perform cleanup operations. - /// - /// Use with caution. This will clear existing directories on initialization - /// and cleanup. - pub fn allow_cleaning(mut self, allow_cleaning: bool) -> RunDir { - self.allow_cleaning = allow_cleaning; - - self - } - - /// Creates the initial `RunDir`. - /// - /// # Examples - /// - /// ``` - /// use espresso::bundle::rundir::RunDir; - /// - /// let rundir = RunDir::new("tests/rundir").allow_cleaning(true); - /// - /// rundir.initialize().unwrap(); - /// - /// rundir.cleanup().unwrap(); - /// ``` - pub fn initialize(&self) -> Result<()> { - if Path::exists(&self.path) { - info!("RunDir already exists: {}", self.path.display()); - - if !Path::is_dir(&self.path) { - error!("RunDir is not a directory: {}", self.path.display()); - - return Err(Error::PathIsNotDir { - path: self.path.clone(), - }); - } else { - // Scan dir - let mut dir_iterator = std::fs::read_dir(&self.path).context(ScanDir { - path: self.path.clone(), - })?; - - let existing_child_path = dir_iterator - .next() - .map(|entry_result| entry_result.map(|entry| entry.path())); - - if let Some(child_path) = existing_child_path { - let child_path = child_path.context(ScanDir { - path: self.path.clone(), - })?; - - if self.allow_cleaning { - info!("Recreating RunDir."); - - std::fs::remove_dir_all(&self.path).context(RecreateDir { - path: self.path.clone(), - })?; - - std::fs::create_dir_all(&self.path).context(RecreateDir { - path: self.path.clone(), - })?; - } else { - return Err(Error::DirIsNotEmpty { - path: self.path.clone(), - child_path, - }); - } - } - } - } else { - info!("Creating new RunDir: {}", self.path.display()); - - std::fs::create_dir_all(&self.path).context(CreateDir { - path: self.path.clone(), - })? - } - - Ok(()) - } - - pub fn cleanup(&self) -> Result<()> { - if self.allow_cleaning { - std::fs::remove_dir_all(&self.path).context(RecreateDir { - path: self.path.clone(), - })?; - - info!("Cleaned up RunDir: {}", self.path.display()); - } else { - warn!("Leaving RunDir unmodified. Manual cleanup may be needed."); - } - - Ok(()) - } - - /// Creates a subdir within the `RunDir`. - pub fn create_subdir(&self, name: &str) -> Result<PathBuf> { - let pathbuf = self.validate_subdir_name(name)?; - - std::fs::create_dir(&pathbuf).context(CreateDir { - path: pathbuf.clone(), - })?; - - Ok(pathbuf) - } - - /// Removes a subdir and all its contents from the `RunDir`. - pub fn remove_subdir_all(&self, name: &str) -> Result<()> { - let pathbuf = self.validate_subdir_name(name)?; - - std::fs::remove_dir_all(&pathbuf).context(RemoveSubDir { path: pathbuf })?; - - Ok(()) - } - - /// Checks if a subdir exists within the `RunDir`. - pub fn subdir_exists(&self, name: &str) -> Result<bool> { - let pathbuf = self.validate_subdir_name(name)?; - - Ok(pathbuf.exists()) - } - - fn validate_subdir_name(&self, name: &str) -> Result<PathBuf> { - // Check that the name results in a dir exactly one level below the current one. - let mut pathbuf = self.path.clone(); - - pathbuf.push(name); - - if let Some(parent) = pathbuf.parent() { - if *parent != self.path { - return Err(Error::InvalidSubDirName { - name: String::from(name), - inner_error: None, - }); - } - } else { - return Err(Error::InvalidSubDirName { - name: String::from(name), - inner_error: None, - }); - } - - Ok(pathbuf) - } -} - -#[cfg(test)] -mod tests { - use super::{Error, RunDir}; - use std::path::PathBuf; - - #[test] - fn test_initialize() -> () { - // Create dir for the first time. - let result = RunDir::new("tests/rundir").initialize(); - - assert!(result.is_ok()); - - // Use existing empty dir. - let result = RunDir::new("tests/rundir").initialize(); - - assert!(result.is_ok()); - - // Fail when dir is not empty and allow_cleaning is not set. - std::fs::write("tests/rundir/hello.world", "test").unwrap(); - let result = RunDir::new("tests/rundir").initialize(); - - match result { - Err(Error::DirIsNotEmpty { path, child_path }) => { - assert_eq!(path, PathBuf::from("tests/rundir")); - assert_eq!(child_path, PathBuf::from("tests/rundir/hello.world")); - } - _ => panic!("Expected an error."), - } - - // Clean existing dir. - let result = RunDir::new("tests/rundir") - .allow_cleaning(true) - .initialize(); - - assert!(result.is_ok()); - - std::fs::remove_dir("tests/rundir").unwrap(); - - // Fail when dir is not a directory. - std::fs::write("tests/rundir", "hello").unwrap(); - let result = RunDir::new("tests/rundir").initialize(); - - match result { - Err(Error::PathIsNotDir { path }) => { - assert_eq!(path, PathBuf::from("tests/rundir")); - } - _ => panic!("Expected an error."), - } - - std::fs::remove_file("tests/rundir").unwrap(); - } - - #[test] - fn test_subdirs() -> () { - let rundir = RunDir::new("tests/rundir2").allow_cleaning(true); - - rundir.initialize().unwrap(); - - assert_eq!(PathBuf::from("tests/rundir2/subtest").exists(), false); - assert_eq!(rundir.subdir_exists("subtest").unwrap(), false); - - rundir.create_subdir("subtest").unwrap(); - assert_eq!(PathBuf::from("tests/rundir2/subtest").exists(), true); - assert_eq!(rundir.subdir_exists("subtest").unwrap(), true); - - rundir.remove_subdir_all("subtest").unwrap(); - assert_eq!(PathBuf::from("tests/rundir2/subtest").exists(), false); - assert_eq!(rundir.subdir_exists("subtest").unwrap(), false); - - rundir.cleanup().unwrap(); - } -} -- GitLab