History

[tempfile] handle interrupts and assure there is an end to it

Sebastian Thiel committed 5 years ago

Commit dc0afbd1 parent b01faa91 file · +37 −9Browse files

Unified · Split

git-tempfile/src/create_dir.rs+37−9
@@ -1,6 +1,20 @@
11 #![allow(missing_docs)]
22 use std::path::Path;
33
4+#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)]
5+pub struct Options {
6+ /// How often to retry if an interrupt happens.
7+ retries_on_interrupt: usize,
8+}
9+
10+impl Default for Options {
11+ fn default() -> Self {
12+ Options {
13+ retries_on_interrupt: 10,
14+ }
15+ }
16+}
17+
418 mod error {
519 use quick_error::quick_error;
620 use std::path::PathBuf;
@@ -37,20 +51,28 @@ pub use error::Error; · 30 unmodified lines
3751 /// * `Some(Err(Error::Permanent))` is yielded exactly once on failure.
3852 pub struct Iter<'a> {
3953 cursors: Vec<&'a Path>,
54+ options: Options,
4055 }
4156
4257 impl<'a> Iter<'a> {
4358 pub fn new(target: &'a Path) -> Self {
44− Iter { cursors: vec![target] }
59+ Iter {
60+ cursors: vec![target],
61+ options: Default::default(),
62+ }
4563 }
4664
47− fn fail_permanently(&mut self, dir: &Path, err: impl Into<std::io::Error>) -> Option<Result<&'a Path, Error>> {
65+ fn pernanent_failure(&mut self, dir: &Path, err: impl Into<std::io::Error>) -> Option<Result<&'a Path, Error>> {
4866 self.cursors.clear();
4967 Some(Err(Error::Permanent {
5068 err: err.into(),
5169 dir: dir.to_owned(),
5270 }))
5371 }
72+
73+ fn intermediate_failure(&self, err: std::io::Error) -> Option<Result<&'a Path, Error>> {
74+ Some(Err(Error::Intermediate(err.kind())))
75+ }
5476 }
5577
5678 impl<'a> Iterator for Iter<'a> {
@@ -59,17 +81,23 @@ impl<'a> Iterator for Iter<'a> { · 2 unmodified lines
5981 fn next(&mut self) -> Option<Self::Item> {
6082 use std::io::ErrorKind::*;
6183 match self.cursors.pop() {
62− Some(cursor) => match std::fs::create_dir(cursor) {
63− Ok(()) => Some(Ok(cursor)),
84+ Some(dir) => match std::fs::create_dir(dir) {
85+ Ok(()) => Some(Ok(dir)),
6486 Err(err) => match err.kind() {
65− AlreadyExists => Some(Ok(cursor)),
87+ AlreadyExists => Some(Ok(dir)),
6688 NotFound => {
67− self.cursors.push(cursor);
68− self.cursors.push(match cursor.parent() {
69− None => return self.fail_permanently(cursor, InvalidInput),
89+ self.cursors.push(dir);
90+ self.cursors.push(match dir.parent() {
91+ None => return self.pernanent_failure(dir, InvalidInput),
7092 Some(parent) => parent,
7193 });
72− Some(Err(Error::Intermediate(err.kind())))
94+ self.intermediate_failure(err)
95+ }
96+ Interrupted if self.options.retries_on_interrupt == 0 => self.pernanent_failure(dir, Interrupted),
97+ Interrupted => {
98+ self.options.retries_on_interrupt -= 1;
99+ self.cursors.push(dir);
100+ self.intermediate_failure(err)
73101 }
74102 kind => todo!("{:?}", kind),
75103 },