diff --git a/src/file.rs b/src/file.rs index 2f5a8c2326..13f6b6244b 100644 --- a/src/file.rs +++ b/src/file.rs @@ -813,22 +813,29 @@ fn strip_archive_path_components(dir: &Path, strip_depth: usize) -> Result<()> { } let top_level_paths = ls(dir)?; - let entries: Vec = top_level_paths - .iter() - .map(|p| ls(p)) - .collect::>>()? - .into_iter() - .flatten() - .collect::>(); - for entry in entries { - let mut new_dir = dir.to_path_buf(); - new_dir.push(entry.file_name().unwrap()); - fs::rename(entry, new_dir)?; - } + for path in top_level_paths { - if path.symlink_metadata()?.is_dir() { - remove_dir(path)?; + if !path.symlink_metadata()?.is_dir() { + continue; } + + // rename the directory to a temp name to avoid conflicts when moving files + let temp_path = path.with_file_name(format!( + "{}_tmp_strip", + path.file_name().unwrap().to_string_lossy() + )); + fs::rename(&path, &temp_path)?; + + for entry in ls(&temp_path)? { + if let Some(file_name) = entry.file_name() { + let dest_path = dir.join(file_name); + fs::rename(entry, dest_path)?; + } else { + continue; + } + } + + remove_dir(temp_path)?; } Ok(()) }