Skip to content
49 changes: 32 additions & 17 deletions library/std/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3333,26 +3333,41 @@ impl DirBuilder {
return Ok(());
}

match self.inner.mkdir(path) {
Ok(()) => return Ok(()),
Err(ref e) if e.kind() == io::ErrorKind::NotFound => {}
Err(_) if path.is_dir() => return Ok(()),
Err(e) => return Err(e),
}
match path.parent() {
Some(p) => self.create_dir_all(p)?,
None => {
return Err(io::const_error!(
io::ErrorKind::Uncategorized,
"failed to create whole tree",
));
let mut uncreated_dirs = Vec::new();
let mut current = path;

loop {
match self.inner.mkdir(current) {
Ok(()) => break,
Err(e) if e.kind() == io::ErrorKind::NotFound => {}
// we check if the err is AlreadyExists for two reasons
// - in case the path exists as a *file*
// - and to avoid calls to .is_dir() in case of other errs
// (i.e. PermissionDenied)
Err(e) if e.kind() == io::ErrorKind::AlreadyExists && current.is_dir() => break,
Err(e) => return Err(e),
}

if let Some(parent) = current.parent() {
if parent == Path::new("") {
break;
}
uncreated_dirs.push(current);
current = parent;
} else {
break;
}
}
match self.inner.mkdir(path) {
Ok(()) => Ok(()),
Err(_) if path.is_dir() => Ok(()),
Err(e) => Err(e),

for uncreated_dir in uncreated_dirs.iter().rev() {
if let Err(e) = self.inner.mkdir(uncreated_dir) {
if !uncreated_dir.is_dir() {
return Err(e);
}
}
}

Ok(())
}
}

Expand Down
Loading