1use std::io;
2use std::path::{Path, PathBuf};
3
4use polars_error::PolarsResult;
5use polars_utils::io::_limit_path_len_io_err;
6use polars_utils::pl_path::PlRefPath;
7
8use crate::path_utils::resolve_homedir;
9
10pub fn mkdir_recursive(path: &PlRefPath) -> PolarsResult<()> {
14 let Some(parent) = writable_parent(path)? else {
15 return Ok(());
16 };
17
18 std::fs::DirBuilder::new()
19 .recursive(true)
20 .create(&parent)
21 .map_err(|err| _limit_path_len_io_err(&parent, err))
22}
23
24pub async fn tokio_mkdir_recursive(path: &PlRefPath) -> PolarsResult<()> {
26 let Some(parent) = writable_parent(path)? else {
27 return Ok(());
28 };
29
30 tokio::fs::DirBuilder::new()
31 .recursive(true)
32 .create(&parent)
33 .await
34 .map_err(|err| _limit_path_len_io_err(&parent, err))
35}
36
37fn writable_parent(path: &PlRefPath) -> PolarsResult<Option<PathBuf>> {
40 if path.has_scheme() {
41 return Ok(None);
42 }
43
44 let Some(parent) = path.parent() else {
45 return Err(io::Error::other(format!("path is not a file: {path}")).into());
46 };
47
48 if parent.is_empty() {
50 return Ok(None);
51 }
52
53 Ok(Some(resolve_homedir(Path::new(parent)).into_owned()))
54}