Skip to content

Commit

Permalink
Add some changes and fixes around how the output file is handled
Browse files Browse the repository at this point in the history
See changelog for details
  • Loading branch information
shssoichiro committed Jan 11, 2018
1 parent d204427 commit e3ba535
Show file tree
Hide file tree
Showing 8 changed files with 276 additions and 265 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
### Version 0.18.4
### Version 0.19.0
- [SEMVER_MAJOR] Default to overwriting the input file if `out_file` is not set.
This does not affect the CLI, but with the library, it was easy to forget to set the `out_file`,
and there was no warning that no output file would be written.
- Bump dependencies, reduces binary size by a considerable amount
- Hide all modules from documentation, and only export the specific structures that should be public.
Previously there were too many implementation details made public. The modules are still public for the purposes of our integration tests,
but we strongly advice against using undocumented modules. These may become private in the future.
- Internal refactoring and code cleanup
- Fix an error message that was displaying the wrong file path
- Fix an issue where the output file would not be written if the input was already optimized,
even if the output path was different from the input path

### Version 0.18.3
- Return exit code of 1 if an error occurred while processing a file using the CLI app ([#93](https://github.com/shssoichiro/oxipng/issues/93))
Expand Down
51 changes: 29 additions & 22 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ pub struct Options {
/// Whether the input file should be backed up before writing the output
/// Default: `false`
pub backup: bool,
/// Path to write the output file to
pub out_file: PathBuf,
/// Path to write the output file to. If not set, the application will default to
/// overwriting the input file.
pub out_file: Option<PathBuf>,
/// Used only in CLI interface
#[doc(hidden)]
pub out_dir: Option<PathBuf>,
/// Write to stdout instead of a file
/// Default: `false`
Expand All @@ -59,6 +61,7 @@ pub struct Options {
/// Default: `false`
pub pretend: bool,
/// Used only in CLI interface
#[doc(hidden)]
pub recursive: bool,
/// Overwrite existing output files
/// Default: `true`
Expand Down Expand Up @@ -279,7 +282,7 @@ impl Default for Options {

Options {
backup: false,
out_file: PathBuf::new(),
out_file: None,
out_dir: None,
stdout: false,
pretend: false,
Expand Down Expand Up @@ -310,26 +313,32 @@ impl Default for Options {
}

/// Perform optimization on the input file using the options provided
pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), PngError> {
pub fn optimize(input_path: &Path, opts: &Options) -> Result<(), PngError> {
// Initialize the thread pool with correct number of threads
let thread_count = opts.threads;
let _ = rayon::initialize(rayon::Configuration::new().num_threads(thread_count));

// Read in the file and try to decode as PNG.
if opts.verbosity.is_some() {
eprintln!("Processing: {}", filepath.to_str().unwrap());
eprintln!("Processing: {}", input_path.to_str().unwrap());
}

let in_file = Path::new(filepath);
let in_data = PngData::read_file(in_file)?;
let in_data = PngData::read_file(input_path)?;
let mut png = PngData::from_slice(&in_data, opts.fix_errors)?;
let output_path = opts.out_file
.clone()
.unwrap_or_else(|| input_path.to_path_buf());

// Run the optimizer on the decoded PNG.
let optimized_output = optimize_png(&mut png, &in_data, opts)?;
let mut optimized_output = optimize_png(&mut png, &in_data, opts)?;

if is_fully_optimized(in_data.len(), optimized_output.len(), opts) {
eprintln!("File already optimized");
return Ok(());
if input_path == output_path {
return Ok(());
} else {
optimized_output = in_data;
}
}

if opts.pretend {
Expand All @@ -338,18 +347,16 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), PngError> {
}
} else {
if opts.backup {
match copy(
in_file,
in_file.with_extension(format!(
"bak.{}",
in_file.extension().unwrap().to_str().unwrap()
)),
) {
let backup_file = input_path.with_extension(format!(
"bak.{}",
input_path.extension().unwrap().to_str().unwrap()
));
match copy(input_path, &backup_file) {
Ok(x) => x,
Err(_) => {
return Err(PngError::new(&format!(
"Unable to write to backup file at {}",
opts.out_file.display()
backup_file.display()
)))
}
};
Expand All @@ -362,18 +369,18 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), PngError> {
Err(_) => return Err(PngError::new("Unable to write to stdout")),
}
} else {
let out_file = match File::create(&opts.out_file) {
let out_file = match File::create(&output_path) {
Ok(x) => x,
Err(_) => {
return Err(PngError::new(&format!(
"Unable to write to file {}",
opts.out_file.display()
output_path.display()
)))
}
};

if opts.preserve_attrs {
match File::open(filepath) {
match File::open(input_path) {
Ok(f) => {
match f.metadata() {
Ok(metadata) => {
Expand Down Expand Up @@ -406,12 +413,12 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), PngError> {
let mut buffer = BufWriter::new(out_file);
match buffer.write_all(&optimized_output) {
Ok(_) => if opts.verbosity.is_some() {
eprintln!("Output: {}", opts.out_file.display());
eprintln!("Output: {}", output_path.display());
},
Err(_) => {
return Err(PngError::new(&format!(
"Unable to write to file {}",
opts.out_file.display()
output_path.display()
)))
}
}
Expand Down
6 changes: 2 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,7 @@ fn handle_optimization(inputs: Vec<PathBuf>, opts: &Options) -> Result<(), PngEr
return res;
}
if let Some(ref out_dir) = current_opts.out_dir {
current_opts.out_file = out_dir.join(input.file_name().unwrap());
} else if current_opts.out_file.components().count() == 0 {
current_opts.out_file = input.clone();
current_opts.out_file = Some(out_dir.join(input.file_name().unwrap()));
}
let cur_result = oxipng::optimize(&input, &current_opts);
res.and(cur_result)
Expand Down Expand Up @@ -342,7 +340,7 @@ fn parse_opts_into_struct(matches: &ArgMatches) -> Result<Options, String> {
}

if let Some(x) = matches.value_of("output_file") {
opts.out_file = PathBuf::from(x);
opts.out_file = Some(PathBuf::from(x));
}

if matches.is_present("stdout") {
Expand Down
Loading

0 comments on commit e3ba535

Please sign in to comment.