this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: avoid panics on non-UTF8 filenames

Replace unwrap() chains in guess_from_filenames() and
default_compressed_filename() with fallible .and_then() + .ok_or_else()
chains. Non-UTF8 filenames are valid on Linux/macOS and should not
cause a crash.

+25 -20
+20 -10
src/job.rs
··· 462 462 (Some(c), Some(e)) => { 463 463 // Both sides carry a known extension — decide whether this is 464 464 // adding or stripping a single outer layer (e.g. tar → tar.gz). 465 - let input_file = input.file_name().unwrap().to_str().unwrap(); 466 - let input_ext = input.extension().unwrap_or_default(); 467 - let output_file = output.file_name().unwrap().to_str().unwrap(); 468 - let output_ext = output.extension().unwrap_or_default(); 469 - let layer_added = input_file.to_string() + "." + output_ext.to_str().unwrap(); 470 - let layer_stripped = output_file.to_string() + "." + input_ext.to_str().unwrap(); 465 + let input_file = input 466 + .file_name() 467 + .and_then(|f| f.to_str()) 468 + .ok_or_else(|| anyhow!("Could not parse input filename"))?; 469 + let input_ext = input 470 + .extension() 471 + .and_then(|e| e.to_str()) 472 + .ok_or_else(|| anyhow!("Could not parse input extension"))?; 473 + let output_file = output 474 + .file_name() 475 + .and_then(|f| f.to_str()) 476 + .ok_or_else(|| anyhow!("Could not parse output filename"))?; 477 + let output_ext = output 478 + .extension() 479 + .and_then(|e| e.to_str()) 480 + .ok_or_else(|| anyhow!("Could not parse output extension"))?; 481 + let layer_added = format!("{input_file}.{output_ext}"); 482 + let layer_stripped = format!("{output_file}.{input_ext}"); 471 483 472 484 if layer_added == output_file { 473 485 // input="archive.tar", output="archive.tar.gz" — add the outer layer only. 474 - let single = 475 - backends::compressor_from_str(output_ext.to_str().unwrap_or("")).unwrap_or(c); 486 + let single = backends::compressor_from_str(output_ext).unwrap_or(c); 476 487 Ok((single, Action::Compress)) 477 488 } else if layer_stripped == input_file { 478 489 // input="archive.tar.gz", output="archive.tar" — strip the outer layer only. 479 - let single = 480 - backends::compressor_from_str(input_ext.to_str().unwrap_or("")).unwrap_or(e); 490 + let single = backends::compressor_from_str(input_ext).unwrap_or(e); 481 491 Ok((single, Action::Extract)) 482 492 } else if c.name() == e.name() { 483 493 // Same format on both sides: only meaningful when the output
+5 -10
src/utils.rs
··· 1 1 use clap::Args; 2 - use std::ffi::OsStr; 3 2 use std::fmt; 4 3 use std::io; 5 4 use std::io::{Read, Write}; ··· 208 207 209 208 /// Generate the default name for the compressed file 210 209 fn default_compressed_filename(&self, in_path: &Path) -> String { 211 - format!( 212 - "{}.{}", 213 - in_path 214 - .file_name() 215 - .unwrap_or_else(|| OsStr::new("archive")) 216 - .to_str() 217 - .unwrap(), 218 - self.extension() 219 - ) 210 + let name = in_path 211 + .file_name() 212 + .and_then(|f| f.to_str()) 213 + .unwrap_or("archive"); 214 + format!("{name}.{}", self.extension()) 220 215 } 221 216 222 217 /// Generate the default extracted filename