Skip to content

Commit ad03ea7

Browse files
authored
Merge pull request #520 from iamkartiknayak/master
Fix extraction folder naming issues and handle existing folders correctly
2 parents 78eea8d + fa5eb85 commit ad03ea7

File tree

1 file changed

+51
-28
lines changed

1 file changed

+51
-28
lines changed

src/operation.rs

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,17 @@ fn handle_progress_state(
9191
}
9292
}
9393

94+
fn get_directory_name(file_name: &str) -> &str {
95+
const SUPPORTED_EXTENSIONS: [&str; 4] = [".tar.gz", ".tgz", ".tar", ".zip"];
96+
97+
for ext in &SUPPORTED_EXTENSIONS {
98+
if file_name.ends_with(ext) {
99+
return &file_name[..file_name.len() - ext.len()];
100+
}
101+
}
102+
file_name
103+
}
104+
94105
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
95106
pub enum ReplaceResult {
96107
Replace(bool),
@@ -319,37 +330,51 @@ async fn copy_or_move(
319330

320331
fn copy_unique_path(from: &Path, to: &Path) -> PathBuf {
321332
let mut to = to.to_owned();
322-
// Separate the full file name into its file name plus extension.
323-
// `[Path::file_stem]` returns the full name for dotfiles (e.g.
324-
// .someconf is the file name)
325-
if let (Some(stem), ext) = (
326-
// FIXME: Replace `[Path::file_stem]` with `[Path::file_prefix]` when stablized to handle .tar.gz et al. better
327-
from.file_stem().and_then(|name| name.to_str()),
328-
from.extension()
329-
.and_then(|ext| ext.to_str())
330-
.unwrap_or_default(),
331-
) {
332-
// '.' needs to be re-added for paths with extensions.
333-
let dot = if ext.is_empty() { "" } else { "." };
333+
if let Some(file_name) = from.file_name().and_then(|name| name.to_str()) {
334+
let is_dir = from.is_dir();
335+
let (stem, ext) = if !is_dir {
336+
match from.extension().and_then(|e| e.to_str()) {
337+
Some(ext) => {
338+
let stem = from
339+
.file_stem()
340+
.and_then(|s| s.to_str())
341+
.unwrap_or(file_name);
342+
(stem.to_string(), Some(ext.to_string()))
343+
}
344+
None => (file_name.to_string(), None),
345+
}
346+
} else {
347+
(file_name.to_string(), None)
348+
};
349+
334350
let mut n = 0u32;
335-
// Loop until a valid `copy n` variant is found
336351
loop {
337-
n = if let Some(n) = n.checked_add(1) {
338-
n
352+
let new_name = if n == 0 {
353+
file_name.to_string()
339354
} else {
340-
// TODO: Return error? fs_extra will handle it anyway
341-
break to;
355+
if is_dir {
356+
format!("{} ({} {})", file_name, fl!("copy_noun"), n)
357+
} else {
358+
match &ext {
359+
Some(ext) => format!("{} ({} {}).{}", stem, fl!("copy_noun"), n, ext),
360+
None => format!("{} ({} {})", stem, fl!("copy_noun"), n),
361+
}
362+
}
342363
};
343364

344-
// Rebuild file name
345-
let new_name = format!("{stem} ({} {n}){dot}{ext}", fl!("copy_noun"));
346365
to = to.join(new_name);
347366

348367
if !matches!(to.try_exists(), Ok(true)) {
349368
break to;
350369
}
351370
// Continue if a copy with index exists
352371
to.pop();
372+
373+
n = if let Some(n) = n.checked_add(1) {
374+
n
375+
} else {
376+
break to;
377+
};
353378
}
354379
} else {
355380
to
@@ -683,12 +708,10 @@ impl Operation {
683708

684709
let to = to.to_owned();
685710

686-
if let Some(file_stem) = path.file_stem() {
687-
let mut new_dir = to.join(file_stem);
688-
// Make sure all extension parts are removed (file_stem may still contain them)
689-
while new_dir.extension().is_some() {
690-
new_dir.set_extension("");
691-
}
711+
if let Some(file_name) = path.file_name().and_then(|f| f.to_str()) {
712+
let dir_name = get_directory_name(file_name);
713+
let mut new_dir = to.join(dir_name);
714+
692715
if new_dir.exists() {
693716
if let Some(new_dir_parent) = new_dir.parent() {
694717
new_dir = copy_unique_path(&new_dir, new_dir_parent);
@@ -702,19 +725,19 @@ impl Operation {
702725
.map(io::BufReader::new)
703726
.map(flate2::read::GzDecoder::new)
704727
.map(tar::Archive::new)
705-
.and_then(|mut archive| archive.unpack(new_dir))
728+
.and_then(|mut archive| archive.unpack(&new_dir))
706729
.map_err(err_str)?
707730
}
708731
"application/x-tar" => fs::File::open(path)
709732
.map(io::BufReader::new)
710733
.map(tar::Archive::new)
711-
.and_then(|mut archive| archive.unpack(new_dir))
734+
.and_then(|mut archive| archive.unpack(&new_dir))
712735
.map_err(err_str)?,
713736
"application/zip" => fs::File::open(path)
714737
.map(io::BufReader::new)
715738
.map(zip::ZipArchive::new)
716739
.map_err(err_str)?
717-
.and_then(|mut archive| archive.extract(new_dir))
740+
.and_then(|mut archive| archive.extract(&new_dir))
718741
.map_err(err_str)?,
719742
#[cfg(feature = "bzip2")]
720743
"application/x-bzip" | "application/x-bzip-compressed-tar" => {

0 commit comments

Comments
 (0)