Merge pull request #520 from iamkartiknayak/master
Fix extraction folder naming issues and handle existing folders correctly
This commit is contained in:
commit
ad03ea7234
1 changed files with 51 additions and 28 deletions
|
|
@ -91,6 +91,17 @@ fn handle_progress_state(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_directory_name(file_name: &str) -> &str {
|
||||||
|
const SUPPORTED_EXTENSIONS: [&str; 4] = [".tar.gz", ".tgz", ".tar", ".zip"];
|
||||||
|
|
||||||
|
for ext in &SUPPORTED_EXTENSIONS {
|
||||||
|
if file_name.ends_with(ext) {
|
||||||
|
return &file_name[..file_name.len() - ext.len()];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_name
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||||
pub enum ReplaceResult {
|
pub enum ReplaceResult {
|
||||||
Replace(bool),
|
Replace(bool),
|
||||||
|
|
@ -319,30 +330,38 @@ async fn copy_or_move(
|
||||||
|
|
||||||
fn copy_unique_path(from: &Path, to: &Path) -> PathBuf {
|
fn copy_unique_path(from: &Path, to: &Path) -> PathBuf {
|
||||||
let mut to = to.to_owned();
|
let mut to = to.to_owned();
|
||||||
// Separate the full file name into its file name plus extension.
|
if let Some(file_name) = from.file_name().and_then(|name| name.to_str()) {
|
||||||
// `[Path::file_stem]` returns the full name for dotfiles (e.g.
|
let is_dir = from.is_dir();
|
||||||
// .someconf is the file name)
|
let (stem, ext) = if !is_dir {
|
||||||
if let (Some(stem), ext) = (
|
match from.extension().and_then(|e| e.to_str()) {
|
||||||
// FIXME: Replace `[Path::file_stem]` with `[Path::file_prefix]` when stablized to handle .tar.gz et al. better
|
Some(ext) => {
|
||||||
from.file_stem().and_then(|name| name.to_str()),
|
let stem = from
|
||||||
from.extension()
|
.file_stem()
|
||||||
.and_then(|ext| ext.to_str())
|
.and_then(|s| s.to_str())
|
||||||
.unwrap_or_default(),
|
.unwrap_or(file_name);
|
||||||
) {
|
(stem.to_string(), Some(ext.to_string()))
|
||||||
// '.' needs to be re-added for paths with extensions.
|
}
|
||||||
let dot = if ext.is_empty() { "" } else { "." };
|
None => (file_name.to_string(), None),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(file_name.to_string(), None)
|
||||||
|
};
|
||||||
|
|
||||||
let mut n = 0u32;
|
let mut n = 0u32;
|
||||||
// Loop until a valid `copy n` variant is found
|
|
||||||
loop {
|
loop {
|
||||||
n = if let Some(n) = n.checked_add(1) {
|
let new_name = if n == 0 {
|
||||||
n
|
file_name.to_string()
|
||||||
} else {
|
} else {
|
||||||
// TODO: Return error? fs_extra will handle it anyway
|
if is_dir {
|
||||||
break to;
|
format!("{} ({} {})", file_name, fl!("copy_noun"), n)
|
||||||
|
} else {
|
||||||
|
match &ext {
|
||||||
|
Some(ext) => format!("{} ({} {}).{}", stem, fl!("copy_noun"), n, ext),
|
||||||
|
None => format!("{} ({} {})", stem, fl!("copy_noun"), n),
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Rebuild file name
|
|
||||||
let new_name = format!("{stem} ({} {n}){dot}{ext}", fl!("copy_noun"));
|
|
||||||
to = to.join(new_name);
|
to = to.join(new_name);
|
||||||
|
|
||||||
if !matches!(to.try_exists(), Ok(true)) {
|
if !matches!(to.try_exists(), Ok(true)) {
|
||||||
|
|
@ -350,6 +369,12 @@ fn copy_unique_path(from: &Path, to: &Path) -> PathBuf {
|
||||||
}
|
}
|
||||||
// Continue if a copy with index exists
|
// Continue if a copy with index exists
|
||||||
to.pop();
|
to.pop();
|
||||||
|
|
||||||
|
n = if let Some(n) = n.checked_add(1) {
|
||||||
|
n
|
||||||
|
} else {
|
||||||
|
break to;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
to
|
to
|
||||||
|
|
@ -683,12 +708,10 @@ impl Operation {
|
||||||
|
|
||||||
let to = to.to_owned();
|
let to = to.to_owned();
|
||||||
|
|
||||||
if let Some(file_stem) = path.file_stem() {
|
if let Some(file_name) = path.file_name().and_then(|f| f.to_str()) {
|
||||||
let mut new_dir = to.join(file_stem);
|
let dir_name = get_directory_name(file_name);
|
||||||
// Make sure all extension parts are removed (file_stem may still contain them)
|
let mut new_dir = to.join(dir_name);
|
||||||
while new_dir.extension().is_some() {
|
|
||||||
new_dir.set_extension("");
|
|
||||||
}
|
|
||||||
if new_dir.exists() {
|
if new_dir.exists() {
|
||||||
if let Some(new_dir_parent) = new_dir.parent() {
|
if let Some(new_dir_parent) = new_dir.parent() {
|
||||||
new_dir = copy_unique_path(&new_dir, new_dir_parent);
|
new_dir = copy_unique_path(&new_dir, new_dir_parent);
|
||||||
|
|
@ -702,19 +725,19 @@ impl Operation {
|
||||||
.map(io::BufReader::new)
|
.map(io::BufReader::new)
|
||||||
.map(flate2::read::GzDecoder::new)
|
.map(flate2::read::GzDecoder::new)
|
||||||
.map(tar::Archive::new)
|
.map(tar::Archive::new)
|
||||||
.and_then(|mut archive| archive.unpack(new_dir))
|
.and_then(|mut archive| archive.unpack(&new_dir))
|
||||||
.map_err(err_str)?
|
.map_err(err_str)?
|
||||||
}
|
}
|
||||||
"application/x-tar" => fs::File::open(path)
|
"application/x-tar" => fs::File::open(path)
|
||||||
.map(io::BufReader::new)
|
.map(io::BufReader::new)
|
||||||
.map(tar::Archive::new)
|
.map(tar::Archive::new)
|
||||||
.and_then(|mut archive| archive.unpack(new_dir))
|
.and_then(|mut archive| archive.unpack(&new_dir))
|
||||||
.map_err(err_str)?,
|
.map_err(err_str)?,
|
||||||
"application/zip" => fs::File::open(path)
|
"application/zip" => fs::File::open(path)
|
||||||
.map(io::BufReader::new)
|
.map(io::BufReader::new)
|
||||||
.map(zip::ZipArchive::new)
|
.map(zip::ZipArchive::new)
|
||||||
.map_err(err_str)?
|
.map_err(err_str)?
|
||||||
.and_then(|mut archive| archive.extract(new_dir))
|
.and_then(|mut archive| archive.extract(&new_dir))
|
||||||
.map_err(err_str)?,
|
.map_err(err_str)?,
|
||||||
#[cfg(feature = "bzip2")]
|
#[cfg(feature = "bzip2")]
|
||||||
"application/x-bzip" | "application/x-bzip-compressed-tar" => {
|
"application/x-bzip" | "application/x-bzip-compressed-tar" => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue