Skip to content

Commit

Permalink
make a new subcrate clite for different features/opt flags
Browse files Browse the repository at this point in the history
  • Loading branch information
cosmicexplorer committed Aug 13, 2024
1 parent 886c8d4 commit 3f8a4ea
Show file tree
Hide file tree
Showing 9 changed files with 189 additions and 98 deletions.
26 changes: 1 addition & 25 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,6 @@ build = "src/build.rs"
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[workspace]
members = [
".",
"cli",
"fuzz",
]
default-members = [
".",
]
resolver = "2"

[workspace.dependencies]
arbitrary = { version = "1.3.2", features = ["derive"] }
time = { version = "0.3.36", default-features = false }
Expand Down Expand Up @@ -75,7 +64,7 @@ getrandom = { version = "0.2.15", features = ["js", "std"] }
walkdir = "2.5.0"
time = { workspace = true, features = ["formatting", "macros"] }
anyhow = "1"
clap = { version = "4", features = ["derive"] }
clap = { version = "=4.4.18", features = ["derive"] }
tempdir = "0.3.7"

[features]
Expand Down Expand Up @@ -115,16 +104,3 @@ harness = false
[[bench]]
name = "merge_archive"
harness = false

# Reduce the size of the zip-cli binary.
[profile.release]
strip = true
# This is necessary for fuzzing, which can only use dev or release profiles, and breaks if LTO
# is specified.
lto = false
opt-level = "z"

[profile.release-lto]
inherits = "release"
# This slightly reduces the size of the output binary.
lto = true
38 changes: 35 additions & 3 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ Binary for creation and manipulation of zip files.
"""
edition = "2021"

# Prevent this from interfering with workspaces
[workspace]
members = ["."]

[lib]

[[bin]]
name = "zip-cli"

Expand All @@ -23,12 +29,38 @@ clap = { version = "4.5.15", features = ["derive"] }
eyre = "0.6"

[dependencies.zip]
workspace = true
features = [
path = ".."
default-features = false

[features]
aes-crypto = ["zip/aes-crypto"]
bzip2 = ["zip/bzip2"]
chrono = ["zip/chrono"]
deflate64 = ["zip/deflate64"]
deflate = ["zip/deflate"]
deflate-flate2 = ["zip/deflate-flate2"]
deflate-zlib = ["zip/deflate-zlib"]
deflate-zlib-ng = ["zip/deflate-zlib-ng"]
deflate-zopfli = ["zip/deflate-zopfli"]
lzma = ["zip/lzma"]
time = ["zip/time"]
xz = ["zip/xz"]
zstd = ["zip/zstd"]
default = [
"aes-crypto",
"bzip2",
"deflate64",
"deflate",
"lzma",
"zstd",
"time",
"xz",
"zstd",
]


# Reduce the size of the zip-cli binary.
[profile.release]
strip = true
lto = true
opt-level = 3
codegen-units = 1
39 changes: 39 additions & 0 deletions cli/clite/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[package]
name = "zip-clite"
version = "0.0.1"
authors = [
"Danny McClanahan <dmcC2@hypnicjerk.ai>",
]
license = "MIT"
repository = "https://github.com/zip-rs/zip2.git"
keywords = ["zip", "archive", "compression", "cli"]
categories = ["command-line-utilities", "compression", "filesystem", "development-tools::build-utils"]
# Keep this up to date with clap!
rust-version = "1.74.0"
description = """
Binary for creation and manipulation of zip files.
"""
edition = "2021"

# Prevent this from interfering with workspaces
[workspace]
members = ["."]

[[bin]]
name = "zip-clite"

[dependencies]
clap = { version = "4.5.15", features = ["derive"] }
eyre = "0.6"

[dependencies.zip-cli]
path = ".."
default-features = false
features = ["deflate-flate2", "deflate-zlib"]

# Reduce the size of the zip-cli binary.
[profile.release]
strip = true
lto = true
opt-level = "s"
codegen-units = 1
28 changes: 28 additions & 0 deletions cli/clite/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use std::io;

use clap::{error::ErrorKind, Parser};
use eyre::Report;

use zip_cli::args::*;
use zip_cli::compress::execute_compress;
use zip_cli::ErrHandle;

fn main() -> Result<(), Report> {
let ZipCli { verbose, command } = match ZipCli::try_parse() {
Ok(args) => args,
Err(e) => match e.kind() {
ErrorKind::Format | ErrorKind::Io | ErrorKind::InvalidUtf8 => return Err(e.into()),
_ => e.exit(),
},
};
let mut err = if verbose {
ErrHandle::Output(io::stderr())
} else {
ErrHandle::NoOutput
};

match command {
ZipCommand::Info | ZipCommand::Extract => Ok(()),
ZipCommand::Compress(compress) => execute_compress(&mut err, compress),
}
}
5 changes: 4 additions & 1 deletion cli/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,15 @@ pub enum CompressionMethodArg {
/// uncompressed
Stored,
/// with deflate (default)
Deflate,
Deflate, /* requires having zip/_deflate-any set to compile */
/// with deflate64
#[cfg(feature = "deflate64")]
Deflate64,
/// with bzip2
#[cfg(feature = "bzip2")]
Bzip2,
/// with zstd
#[cfg(feature = "zstd")]
Zstd,
}

Expand Down
74 changes: 37 additions & 37 deletions cli/src/compress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ fn enter_recursive_dir_entries(
.unwrap_or_else(|| path_to_string(root).into())
.trim_end_matches('/')
.to_string();
write!(
writeln!(
err,
"writing top-level directory entry for {base_dirname:?}\n"
"writing top-level directory entry for {base_dirname:?}"
)?;
writer.add_directory(&base_dirname, options)?;

Expand All @@ -78,29 +78,26 @@ fn enter_recursive_dir_entries(
let file_type = dir_entry.file_type()?;
if file_type.is_symlink() {
let target: String = path_to_string(fs::read_link(dir_entry.path())?).into();
write!(
writeln!(
err,
"writing recursive symlink entry with name {full_path:?} and target {target:?}\n"
"writing recursive symlink entry with name {full_path:?} and target {target:?}"
)?;
writer.add_symlink(full_path, target, options)?;
} else if file_type.is_file() {
write!(
err,
"writing recursive file entry with name {full_path:?}\n"
)?;
writeln!(err, "writing recursive file entry with name {full_path:?}")?;
writer.start_file(full_path, options)?;
let mut f = fs::File::open(dir_entry.path())?;
io::copy(&mut f, writer)?;
} else {
assert!(file_type.is_dir());
write!(
writeln!(
err,
"writing recursive directory entry with name {full_path:?}\n"
"writing recursive directory entry with name {full_path:?}"
)?;
writer.add_directory(full_path, options)?;
write!(
writeln!(
err,
"adding subdirectories depth-first for recursive directory entry {entry_basename:?}\n"
"adding subdirectories depth-first for recursive directory entry {entry_basename:?}"
)?;
let new_readdir = fs::read_dir(dir_entry.path())?;
readdir_stack.push((new_readdir, entry_basename));
Expand All @@ -123,13 +120,13 @@ pub fn execute_compress(

let out = match output_path {
Some(path) => {
write!(err, "writing compressed zip to output file path {path:?}\n")?;
writeln!(err, "writing compressed zip to output file path {path:?}")?;
OutputHandle::File(fs::File::create(path)?)
}
None => {
write!(
writeln!(
err,
"writing to stdout and buffering compressed zip in memory\n"
"writing to stdout and buffering compressed zip in memory"
)?;
if io::stdout().is_terminal() && !allow_stdout {
return Err(eyre!("stdout is a tty, but --stdout was not set"));
Expand All @@ -142,7 +139,7 @@ pub fn execute_compress(
let mut options = SimpleFileOptions::default()
.compression_method(CompressionMethod::Deflated)
.large_file(false);
write!(err, "default zip entry options: {options:?}\n")?;
writeln!(err, "default zip entry options: {options:?}")?;
let mut last_name: Option<String> = None;
let mut symlink_flag: bool = false;

Expand All @@ -152,27 +149,30 @@ pub fn execute_compress(
let method = match method {
CompressionMethodArg::Stored => CompressionMethod::Stored,
CompressionMethodArg::Deflate => CompressionMethod::Deflated,
#[cfg(feature = "deflate64")]
CompressionMethodArg::Deflate64 => CompressionMethod::Deflate64,
#[cfg(feature = "bzip2")]
CompressionMethodArg::Bzip2 => CompressionMethod::Bzip2,
#[cfg(feature = "zstd")]
CompressionMethodArg::Zstd => CompressionMethod::Zstd,
};
write!(err, "setting compression method {method:?}\n")?;
writeln!(err, "setting compression method {method:?}")?;
options = options.compression_method(method);
}
CompressionArg::Level(CompressionLevel(level)) => {
write!(err, "setting compression level {level:?}\n")?;
writeln!(err, "setting compression level {level:?}")?;
options = options.compression_level(Some(level));
}
CompressionArg::Mode(Mode(mode)) => {
write!(err, "setting file mode {mode:#o}\n")?;
writeln!(err, "setting file mode {mode:#o}")?;
options = options.unix_permissions(mode);
}
CompressionArg::LargeFile(large_file) => {
write!(err, "setting large file flag to {large_file:?}\n")?;
writeln!(err, "setting large file flag to {large_file:?}")?;
options = options.large_file(large_file);
}
CompressionArg::Name(name) => {
write!(err, "setting name of next entry to {name:?}\n")?;
writeln!(err, "setting name of next entry to {name:?}")?;
if let Some(last_name) = last_name {
return Err(eyre!(
"got two names before an entry: {last_name} and {name}"
Expand All @@ -181,7 +181,7 @@ pub fn execute_compress(
last_name = Some(name);
}
CompressionArg::Dir => {
write!(err, "writing dir entry\n")?;
writeln!(err, "writing dir entry")?;
if symlink_flag {
return Err(eyre!("symlink flag provided before dir entry with "));
}
Expand All @@ -191,7 +191,7 @@ pub fn execute_compress(
writer.add_directory(dirname, options)?;
}
CompressionArg::Symlink => {
write!(err, "setting symlink flag for next entry\n")?;
writeln!(err, "setting symlink flag for next entry")?;
if symlink_flag {
/* TODO: make this a warning? */

Check notice

Code scanning / devskim

A "TODO" or similar was left in source code, possibly indicating incomplete functionality Note

Suspicious comment
return Err(eyre!("symlink flag provided twice before entry"));
Expand All @@ -207,18 +207,18 @@ pub fn execute_compress(
let target = data
.into_string()
.map_err(|target| eyre!("failed to decode symlink target {target:?}"))?;
write!(
writeln!(
err,
"writing immediate symlink entry with name {name:?} and target {target:?}\n"
"writing immediate symlink entry with name {name:?} and target {target:?}"
)?;
/* TODO: .add_symlink() should support OsString targets! */

Check notice

Code scanning / devskim

A "TODO" or similar was left in source code, possibly indicating incomplete functionality Note

Suspicious comment
writer.add_symlink(name, target, options)?;
symlink_flag = false;
} else {
/* This is a file entry. */
write!(
writeln!(
err,
"writing immediate file entry with name {name:?} and data {data:?}\n"
"writing immediate file entry with name {name:?} and data {data:?}"
)?;
let data = data.into_encoded_bytes();
writer.start_file(name, options)?;
Expand All @@ -232,14 +232,14 @@ pub fn execute_compress(
if symlink_flag {
/* This is a symlink entry. */
let target: String = path_to_string(fs::read_link(&path)?).into();
write!(err, "writing symlink entry from path {path:?} with name {name:?} and target {target:?}\n")?;
writeln!(err, "writing symlink entry from path {path:?} with name {name:?} and target {target:?}")?;
writer.add_symlink(name, target, options)?;
symlink_flag = false;
} else {
/* This is a file entry. */
write!(
writeln!(
err,
"writing file entry from path {path:?} with name {name:?}\n"
"writing file entry from path {path:?} with name {name:?}"
)?;
writer.start_file(name, options)?;
let mut f = fs::File::open(path)?;
Expand All @@ -250,9 +250,9 @@ pub fn execute_compress(
if symlink_flag {
return Err(eyre!("symlink flag provided before recursive dir entry"));
}
write!(
writeln!(
err,
"writing recursive dir entries for path {r:?} with name {last_name:?}\n"
"writing recursive dir entries for path {r:?} with name {last_name:?}"
)?;
enter_recursive_dir_entries(err, last_name.take(), &r, &mut writer, options)?;
}
Expand All @@ -272,21 +272,21 @@ pub fn execute_compress(
let file_type = fs::symlink_metadata(&pos_arg)?.file_type();
if file_type.is_symlink() {
let target = fs::read_link(&pos_arg)?;
write!(
writeln!(
err,
"writing positional symlink entry with path {pos_arg:?} and target {target:?}\n"
"writing positional symlink entry with path {pos_arg:?} and target {target:?}"
)?;
writer.add_symlink_from_path(pos_arg, target, options)?;
} else if file_type.is_file() {
write!(err, "writing positional file entry with path {pos_arg:?}\n")?;
writeln!(err, "writing positional file entry with path {pos_arg:?}")?;
writer.start_file_from_path(&pos_arg, options)?;
let mut f = fs::File::open(pos_arg)?;
io::copy(&mut f, &mut writer)?;
} else {
assert!(file_type.is_dir());
write!(
writeln!(
err,
"writing positional recursive dir entry for {pos_arg:?}\n"
"writing positional recursive dir entry for {pos_arg:?}"
)?;
enter_recursive_dir_entries(err, None, &pos_arg, &mut writer, options)?;
}
Expand Down
Loading

0 comments on commit 3f8a4ea

Please sign in to comment.