diff options
Diffstat (limited to 'vendor/gix-tempfile/src/fs/create_dir.rs')
-rw-r--r-- | vendor/gix-tempfile/src/fs/create_dir.rs | 202 |
1 files changed, 0 insertions, 202 deletions
diff --git a/vendor/gix-tempfile/src/fs/create_dir.rs b/vendor/gix-tempfile/src/fs/create_dir.rs deleted file mode 100644 index 65efdb2b8..000000000 --- a/vendor/gix-tempfile/src/fs/create_dir.rs +++ /dev/null @@ -1,202 +0,0 @@ -//! -use std::path::Path; - -/// The amount of retries to do during various aspects of the directory creation. -#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)] -pub struct Retries { - /// How many times the whole directory can be created in the light of racy interference. - /// This count combats racy situations where another process is trying to remove a directory that we want to create, - /// and is deliberately higher than those who do deletion. That way, creation usually wins. - pub to_create_entire_directory: usize, - /// The amount of times we can try to create a directory because we couldn't as the parent didn't exist. - /// This amounts to the maximum subdirectory depth we allow to be created. Counts once per attempt to create the entire directory. - pub on_create_directory_failure: usize, - /// How often to retry to create a single directory if an interrupt happens, as caused by signals. - pub on_interrupt: usize, -} - -impl Default for Retries { - fn default() -> Self { - Retries { - on_interrupt: 10, - to_create_entire_directory: 5, - on_create_directory_failure: 25, - } - } -} - -mod error { - use std::{fmt, path::Path}; - - use crate::fs::create_dir::Retries; - - /// The error returned by [all()][super::all()]. - #[allow(missing_docs)] - #[derive(Debug)] - pub enum Error<'a> { - /// A failure we will probably recover from by trying again. - Intermediate { dir: &'a Path, kind: std::io::ErrorKind }, - /// A failure that ends the operation. - Permanent { - dir: &'a Path, - err: std::io::Error, - /// The retries left after running the operation - retries_left: Retries, - /// The original amount of retries to allow determining how many were actually used - retries: Retries, - }, - } - - impl<'a> fmt::Display for Error<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Error::Intermediate { dir, kind } => write!( - f, - "Intermediae failure creating {:?} with error: {:?}", - dir.display(), - kind - ), - Error::Permanent { - err: _, - dir, - retries_left, - retries, - } => write!( - f, - "Permanently failing to create directory {dir:?} ({retries_left:?} of {retries:?})", - ), - } - } - } - - impl<'a> std::error::Error for Error<'a> { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - Error::Permanent { err, .. } => Some(err), - _ => None, - } - } - } -} -pub use error::Error; - -enum State { - CurrentlyCreatingDirectories, - SearchingUpwardsForExistingDirectory, -} - -/// A special iterator which communicates its operation through results where… -/// -/// * `Some(Ok(created_directory))` is yielded once or more success, followed by `None` -/// * `Some(Err(Error::Intermediate))` is yielded zero or more times while trying to create the directory. -/// * `Some(Err(Error::Permanent))` is yielded exactly once on failure. -pub struct Iter<'a> { - cursors: Vec<&'a Path>, - retries: Retries, - original_retries: Retries, - state: State, -} - -/// Construction -impl<'a> Iter<'a> { - /// Create a new instance that creates `target` when iterated with the default amount of [`Retries`]. - pub fn new(target: &'a Path) -> Self { - Self::new_with_retries(target, Default::default()) - } - - /// Create a new instance that creates `target` when iterated with the specified amount of `retries`. - pub fn new_with_retries(target: &'a Path, retries: Retries) -> Self { - Iter { - cursors: vec![target], - original_retries: retries, - retries, - state: State::SearchingUpwardsForExistingDirectory, - } - } -} - -impl<'a> Iter<'a> { - fn pernanent_failure( - &mut self, - dir: &'a Path, - err: impl Into<std::io::Error>, - ) -> Option<Result<&'a Path, Error<'a>>> { - self.cursors.clear(); - Some(Err(Error::Permanent { - err: err.into(), - dir, - retries_left: self.retries, - retries: self.original_retries, - })) - } - - fn intermediate_failure(&self, dir: &'a Path, err: std::io::Error) -> Option<Result<&'a Path, Error<'a>>> { - Some(Err(Error::Intermediate { dir, kind: err.kind() })) - } -} - -impl<'a> Iterator for Iter<'a> { - type Item = Result<&'a Path, Error<'a>>; - - fn next(&mut self) -> Option<Self::Item> { - use std::io::ErrorKind::*; - match self.cursors.pop() { - Some(dir) => match std::fs::create_dir(dir) { - Ok(()) => { - self.state = State::CurrentlyCreatingDirectories; - Some(Ok(dir)) - } - Err(err) => match err.kind() { - AlreadyExists if dir.is_dir() => { - self.state = State::CurrentlyCreatingDirectories; - Some(Ok(dir)) - } - AlreadyExists => self.pernanent_failure(dir, err), // is non-directory - NotFound => { - self.retries.on_create_directory_failure -= 1; - if let State::CurrentlyCreatingDirectories = self.state { - self.state = State::SearchingUpwardsForExistingDirectory; - self.retries.to_create_entire_directory -= 1; - if self.retries.to_create_entire_directory < 1 { - return self.pernanent_failure(dir, NotFound); - } - self.retries.on_create_directory_failure = - self.original_retries.on_create_directory_failure; - } - if self.retries.on_create_directory_failure < 1 { - return self.pernanent_failure(dir, NotFound); - }; - self.cursors.push(dir); - self.cursors.push(match dir.parent() { - None => return self.pernanent_failure(dir, InvalidInput), - Some(parent) => parent, - }); - self.intermediate_failure(dir, err) - } - Interrupted => { - self.retries.on_interrupt -= 1; - if self.retries.on_interrupt <= 1 { - return self.pernanent_failure(dir, Interrupted); - }; - self.cursors.push(dir); - self.intermediate_failure(dir, err) - } - _unexpected_kind => self.pernanent_failure(dir, err), - }, - }, - None => None, - } - } -} - -/// Create all directories leading to `dir` including `dir` itself with the specified amount of `retries`. -/// Returns the input `dir` on success that make it useful in expressions. -pub fn all(dir: &Path, retries: Retries) -> std::io::Result<&Path> { - for res in Iter::new_with_retries(dir, retries) { - match res { - Err(Error::Permanent { err, .. }) => return Err(err), - Err(Error::Intermediate { .. }) | Ok(_) => continue, - } - } - Ok(dir) -} |