Skip to content

Commit 35ca507

Browse files
committed
fix: better error message while creating directory over existing file
Signed-off-by: Gaoyang Zhang <gy@blurgy.xyz>
1 parent 2924c1b commit 35ca507

1 file changed

Lines changed: 38 additions & 6 deletions

File tree

dt-core/src/item.rs

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,18 @@ where
4040
fn non_host_specific(self, hostname_sep: &str) -> Self {
4141
unimplemented!()
4242
}
43+
/// Gets the nearest existing parent component of `self`.
44+
fn nearest_existing_parent(&self) -> Self {
45+
unimplemented!()
46+
}
4347
/// Checks whether any of the component above `self` is readonly.
4448
fn is_parent_readonly(&self) -> bool {
4549
unimplemented!()
4650
}
51+
/// Checks whether any component of `self`'s parent is not a directory.
52+
fn has_file_as_parent(&self) -> bool {
53+
unimplemented!()
54+
}
4755
/// Checks whether any of the component refernces its parent.
4856
fn is_twisted(&self) -> bool {
4957
unimplemented!()
@@ -232,22 +240,32 @@ impl Operate for PathBuf {
232240
.collect::<PathBuf>()
233241
}
234242

235-
/// Checks whether any of the component above `self` is readonly.
236-
fn is_parent_readonly(&self) -> bool {
243+
/// Gets the nearest existing parent component of `self`.
244+
fn nearest_existing_parent(&self) -> Self {
237245
let mut p: &Path = self.as_ref();
238-
let first_existing_parent = loop {
246+
let p = loop {
239247
if p.exists() {
240248
break p;
241249
}
242250
p = p.parent().unwrap();
243251
};
244-
first_existing_parent
252+
p.into()
253+
}
254+
255+
/// Checks whether any of the component above `self` is readonly.
256+
fn is_parent_readonly(&self) -> bool {
257+
self.nearest_existing_parent()
245258
.metadata()
246259
.unwrap()
247260
.permissions()
248261
.readonly()
249262
}
250263

264+
/// Checks whether any component of `self`'s parent is not a directory.
265+
fn has_file_as_parent(&self) -> bool {
266+
self.nearest_existing_parent().metadata().unwrap().is_file()
267+
}
268+
251269
/// Checks whether any of the component refernces its parent.
252270
fn is_twisted(&self) -> bool {
253271
self.iter().any(|comp| comp == "..")
@@ -460,7 +478,14 @@ impl Operate for PathBuf {
460478
&group.target,
461479
group.get_renaming_rules(),
462480
)?;
463-
std::fs::create_dir_all(tpath.parent().unwrap())?;
481+
let tparent = tpath.parent().unwrap().to_owned();
482+
if tparent.has_file_as_parent() {
483+
return Err(AppError::PathError(format!(
484+
"target path's parent '{}' contains one or more file components thus can not be created as a directory",
485+
tparent.display()
486+
)));
487+
}
488+
std::fs::create_dir_all(tparent)?;
464489
if group.target.canonicalize()? == group.base.canonicalize()? {
465490
return Err(AppError::PathError(format!(
466491
"base directory and its target point to the same path in group '{}'",
@@ -580,7 +605,14 @@ impl Operate for PathBuf {
580605
&group.get_staging_dir(),
581606
Vec::new(), // Do not apply renaming on staging path
582607
)?;
583-
std::fs::create_dir_all(staging_path.parent().unwrap())?;
608+
let sparent = staging_path.parent().unwrap().to_owned();
609+
if sparent.has_file_as_parent() {
610+
return Err(AppError::PathError(format!(
611+
"staging path's parent '{}' contains one or more file component thus can not be created as a directory",
612+
sparent.display()
613+
)));
614+
}
615+
std::fs::create_dir_all(sparent)?;
584616
if group.global.staging.0.canonicalize()?
585617
== group.base.canonicalize()?
586618
{

0 commit comments

Comments
 (0)