Skip to content

Commit 3f8a4ea

Browse files
make a new subcrate clite for different features/opt flags
1 parent 886c8d4 commit 3f8a4ea

File tree

9 files changed

+189
-98
lines changed

9 files changed

+189
-98
lines changed

Cargo.toml

+1-25
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,6 @@ build = "src/build.rs"
2323
all-features = true
2424
rustdoc-args = ["--cfg", "docsrs"]
2525

26-
[workspace]
27-
members = [
28-
".",
29-
"cli",
30-
"fuzz",
31-
]
32-
default-members = [
33-
".",
34-
]
35-
resolver = "2"
36-
3726
[workspace.dependencies]
3827
arbitrary = { version = "1.3.2", features = ["derive"] }
3928
time = { version = "0.3.36", default-features = false }
@@ -75,7 +64,7 @@ getrandom = { version = "0.2.15", features = ["js", "std"] }
7564
walkdir = "2.5.0"
7665
time = { workspace = true, features = ["formatting", "macros"] }
7766
anyhow = "1"
78-
clap = { version = "4", features = ["derive"] }
67+
clap = { version = "=4.4.18", features = ["derive"] }
7968
tempdir = "0.3.7"
8069

8170
[features]
@@ -115,16 +104,3 @@ harness = false
115104
[[bench]]
116105
name = "merge_archive"
117106
harness = false
118-
119-
# Reduce the size of the zip-cli binary.
120-
[profile.release]
121-
strip = true
122-
# This is necessary for fuzzing, which can only use dev or release profiles, and breaks if LTO
123-
# is specified.
124-
lto = false
125-
opt-level = "z"
126-
127-
[profile.release-lto]
128-
inherits = "release"
129-
# This slightly reduces the size of the output binary.
130-
lto = true

cli/Cargo.toml

+35-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ Binary for creation and manipulation of zip files.
1515
"""
1616
edition = "2021"
1717

18+
# Prevent this from interfering with workspaces
19+
[workspace]
20+
members = ["."]
21+
22+
[lib]
23+
1824
[[bin]]
1925
name = "zip-cli"
2026

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

2531
[dependencies.zip]
26-
workspace = true
27-
features = [
32+
path = ".."
33+
default-features = false
34+
35+
[features]
36+
aes-crypto = ["zip/aes-crypto"]
37+
bzip2 = ["zip/bzip2"]
38+
chrono = ["zip/chrono"]
39+
deflate64 = ["zip/deflate64"]
40+
deflate = ["zip/deflate"]
41+
deflate-flate2 = ["zip/deflate-flate2"]
42+
deflate-zlib = ["zip/deflate-zlib"]
43+
deflate-zlib-ng = ["zip/deflate-zlib-ng"]
44+
deflate-zopfli = ["zip/deflate-zopfli"]
45+
lzma = ["zip/lzma"]
46+
time = ["zip/time"]
47+
xz = ["zip/xz"]
48+
zstd = ["zip/zstd"]
49+
default = [
50+
"aes-crypto",
2851
"bzip2",
2952
"deflate64",
3053
"deflate",
3154
"lzma",
32-
"zstd",
55+
"time",
3356
"xz",
57+
"zstd",
3458
]
59+
60+
61+
# Reduce the size of the zip-cli binary.
62+
[profile.release]
63+
strip = true
64+
lto = true
65+
opt-level = 3
66+
codegen-units = 1

cli/clite/Cargo.toml

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
[package]
2+
name = "zip-clite"
3+
version = "0.0.1"
4+
authors = [
5+
"Danny McClanahan <[email protected]>",
6+
]
7+
license = "MIT"
8+
repository = "https://github.com/zip-rs/zip2.git"
9+
keywords = ["zip", "archive", "compression", "cli"]
10+
categories = ["command-line-utilities", "compression", "filesystem", "development-tools::build-utils"]
11+
# Keep this up to date with clap!
12+
rust-version = "1.74.0"
13+
description = """
14+
Binary for creation and manipulation of zip files.
15+
"""
16+
edition = "2021"
17+
18+
# Prevent this from interfering with workspaces
19+
[workspace]
20+
members = ["."]
21+
22+
[[bin]]
23+
name = "zip-clite"
24+
25+
[dependencies]
26+
clap = { version = "4.5.15", features = ["derive"] }
27+
eyre = "0.6"
28+
29+
[dependencies.zip-cli]
30+
path = ".."
31+
default-features = false
32+
features = ["deflate-flate2", "deflate-zlib"]
33+
34+
# Reduce the size of the zip-cli binary.
35+
[profile.release]
36+
strip = true
37+
lto = true
38+
opt-level = "s"
39+
codegen-units = 1

cli/clite/src/main.rs

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use std::io;
2+
3+
use clap::{error::ErrorKind, Parser};
4+
use eyre::Report;
5+
6+
use zip_cli::args::*;
7+
use zip_cli::compress::execute_compress;
8+
use zip_cli::ErrHandle;
9+
10+
fn main() -> Result<(), Report> {
11+
let ZipCli { verbose, command } = match ZipCli::try_parse() {
12+
Ok(args) => args,
13+
Err(e) => match e.kind() {
14+
ErrorKind::Format | ErrorKind::Io | ErrorKind::InvalidUtf8 => return Err(e.into()),
15+
_ => e.exit(),
16+
},
17+
};
18+
let mut err = if verbose {
19+
ErrHandle::Output(io::stderr())
20+
} else {
21+
ErrHandle::NoOutput
22+
};
23+
24+
match command {
25+
ZipCommand::Info | ZipCommand::Extract => Ok(()),
26+
ZipCommand::Compress(compress) => execute_compress(&mut err, compress),
27+
}
28+
}

cli/src/args.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,15 @@ pub enum CompressionMethodArg {
3333
/// uncompressed
3434
Stored,
3535
/// with deflate (default)
36-
Deflate,
36+
Deflate, /* requires having zip/_deflate-any set to compile */
3737
/// with deflate64
38+
#[cfg(feature = "deflate64")]
3839
Deflate64,
3940
/// with bzip2
41+
#[cfg(feature = "bzip2")]
4042
Bzip2,
4143
/// with zstd
44+
#[cfg(feature = "zstd")]
4245
Zstd,
4346
}
4447

cli/src/compress.rs

+37-37
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ fn enter_recursive_dir_entries(
5555
.unwrap_or_else(|| path_to_string(root).into())
5656
.trim_end_matches('/')
5757
.to_string();
58-
write!(
58+
writeln!(
5959
err,
60-
"writing top-level directory entry for {base_dirname:?}\n"
60+
"writing top-level directory entry for {base_dirname:?}"
6161
)?;
6262
writer.add_directory(&base_dirname, options)?;
6363

@@ -78,29 +78,26 @@ fn enter_recursive_dir_entries(
7878
let file_type = dir_entry.file_type()?;
7979
if file_type.is_symlink() {
8080
let target: String = path_to_string(fs::read_link(dir_entry.path())?).into();
81-
write!(
81+
writeln!(
8282
err,
83-
"writing recursive symlink entry with name {full_path:?} and target {target:?}\n"
83+
"writing recursive symlink entry with name {full_path:?} and target {target:?}"
8484
)?;
8585
writer.add_symlink(full_path, target, options)?;
8686
} else if file_type.is_file() {
87-
write!(
88-
err,
89-
"writing recursive file entry with name {full_path:?}\n"
90-
)?;
87+
writeln!(err, "writing recursive file entry with name {full_path:?}")?;
9188
writer.start_file(full_path, options)?;
9289
let mut f = fs::File::open(dir_entry.path())?;
9390
io::copy(&mut f, writer)?;
9491
} else {
9592
assert!(file_type.is_dir());
96-
write!(
93+
writeln!(
9794
err,
98-
"writing recursive directory entry with name {full_path:?}\n"
95+
"writing recursive directory entry with name {full_path:?}"
9996
)?;
10097
writer.add_directory(full_path, options)?;
101-
write!(
98+
writeln!(
10299
err,
103-
"adding subdirectories depth-first for recursive directory entry {entry_basename:?}\n"
100+
"adding subdirectories depth-first for recursive directory entry {entry_basename:?}"
104101
)?;
105102
let new_readdir = fs::read_dir(dir_entry.path())?;
106103
readdir_stack.push((new_readdir, entry_basename));
@@ -123,13 +120,13 @@ pub fn execute_compress(
123120

124121
let out = match output_path {
125122
Some(path) => {
126-
write!(err, "writing compressed zip to output file path {path:?}\n")?;
123+
writeln!(err, "writing compressed zip to output file path {path:?}")?;
127124
OutputHandle::File(fs::File::create(path)?)
128125
}
129126
None => {
130-
write!(
127+
writeln!(
131128
err,
132-
"writing to stdout and buffering compressed zip in memory\n"
129+
"writing to stdout and buffering compressed zip in memory"
133130
)?;
134131
if io::stdout().is_terminal() && !allow_stdout {
135132
return Err(eyre!("stdout is a tty, but --stdout was not set"));
@@ -142,7 +139,7 @@ pub fn execute_compress(
142139
let mut options = SimpleFileOptions::default()
143140
.compression_method(CompressionMethod::Deflated)
144141
.large_file(false);
145-
write!(err, "default zip entry options: {options:?}\n")?;
142+
writeln!(err, "default zip entry options: {options:?}")?;
146143
let mut last_name: Option<String> = None;
147144
let mut symlink_flag: bool = false;
148145

@@ -152,27 +149,30 @@ pub fn execute_compress(
152149
let method = match method {
153150
CompressionMethodArg::Stored => CompressionMethod::Stored,
154151
CompressionMethodArg::Deflate => CompressionMethod::Deflated,
152+
#[cfg(feature = "deflate64")]
155153
CompressionMethodArg::Deflate64 => CompressionMethod::Deflate64,
154+
#[cfg(feature = "bzip2")]
156155
CompressionMethodArg::Bzip2 => CompressionMethod::Bzip2,
156+
#[cfg(feature = "zstd")]
157157
CompressionMethodArg::Zstd => CompressionMethod::Zstd,
158158
};
159-
write!(err, "setting compression method {method:?}\n")?;
159+
writeln!(err, "setting compression method {method:?}")?;
160160
options = options.compression_method(method);
161161
}
162162
CompressionArg::Level(CompressionLevel(level)) => {
163-
write!(err, "setting compression level {level:?}\n")?;
163+
writeln!(err, "setting compression level {level:?}")?;
164164
options = options.compression_level(Some(level));
165165
}
166166
CompressionArg::Mode(Mode(mode)) => {
167-
write!(err, "setting file mode {mode:#o}\n")?;
167+
writeln!(err, "setting file mode {mode:#o}")?;
168168
options = options.unix_permissions(mode);
169169
}
170170
CompressionArg::LargeFile(large_file) => {
171-
write!(err, "setting large file flag to {large_file:?}\n")?;
171+
writeln!(err, "setting large file flag to {large_file:?}")?;
172172
options = options.large_file(large_file);
173173
}
174174
CompressionArg::Name(name) => {
175-
write!(err, "setting name of next entry to {name:?}\n")?;
175+
writeln!(err, "setting name of next entry to {name:?}")?;
176176
if let Some(last_name) = last_name {
177177
return Err(eyre!(
178178
"got two names before an entry: {last_name} and {name}"
@@ -181,7 +181,7 @@ pub fn execute_compress(
181181
last_name = Some(name);
182182
}
183183
CompressionArg::Dir => {
184-
write!(err, "writing dir entry\n")?;
184+
writeln!(err, "writing dir entry")?;
185185
if symlink_flag {
186186
return Err(eyre!("symlink flag provided before dir entry with "));
187187
}
@@ -191,7 +191,7 @@ pub fn execute_compress(
191191
writer.add_directory(dirname, options)?;
192192
}
193193
CompressionArg::Symlink => {
194-
write!(err, "setting symlink flag for next entry\n")?;
194+
writeln!(err, "setting symlink flag for next entry")?;
195195
if symlink_flag {
196196
/* TODO: make this a warning? */
197197
return Err(eyre!("symlink flag provided twice before entry"));
@@ -207,18 +207,18 @@ pub fn execute_compress(
207207
let target = data
208208
.into_string()
209209
.map_err(|target| eyre!("failed to decode symlink target {target:?}"))?;
210-
write!(
210+
writeln!(
211211
err,
212-
"writing immediate symlink entry with name {name:?} and target {target:?}\n"
212+
"writing immediate symlink entry with name {name:?} and target {target:?}"
213213
)?;
214214
/* TODO: .add_symlink() should support OsString targets! */
215215
writer.add_symlink(name, target, options)?;
216216
symlink_flag = false;
217217
} else {
218218
/* This is a file entry. */
219-
write!(
219+
writeln!(
220220
err,
221-
"writing immediate file entry with name {name:?} and data {data:?}\n"
221+
"writing immediate file entry with name {name:?} and data {data:?}"
222222
)?;
223223
let data = data.into_encoded_bytes();
224224
writer.start_file(name, options)?;
@@ -232,14 +232,14 @@ pub fn execute_compress(
232232
if symlink_flag {
233233
/* This is a symlink entry. */
234234
let target: String = path_to_string(fs::read_link(&path)?).into();
235-
write!(err, "writing symlink entry from path {path:?} with name {name:?} and target {target:?}\n")?;
235+
writeln!(err, "writing symlink entry from path {path:?} with name {name:?} and target {target:?}")?;
236236
writer.add_symlink(name, target, options)?;
237237
symlink_flag = false;
238238
} else {
239239
/* This is a file entry. */
240-
write!(
240+
writeln!(
241241
err,
242-
"writing file entry from path {path:?} with name {name:?}\n"
242+
"writing file entry from path {path:?} with name {name:?}"
243243
)?;
244244
writer.start_file(name, options)?;
245245
let mut f = fs::File::open(path)?;
@@ -250,9 +250,9 @@ pub fn execute_compress(
250250
if symlink_flag {
251251
return Err(eyre!("symlink flag provided before recursive dir entry"));
252252
}
253-
write!(
253+
writeln!(
254254
err,
255-
"writing recursive dir entries for path {r:?} with name {last_name:?}\n"
255+
"writing recursive dir entries for path {r:?} with name {last_name:?}"
256256
)?;
257257
enter_recursive_dir_entries(err, last_name.take(), &r, &mut writer, options)?;
258258
}
@@ -272,21 +272,21 @@ pub fn execute_compress(
272272
let file_type = fs::symlink_metadata(&pos_arg)?.file_type();
273273
if file_type.is_symlink() {
274274
let target = fs::read_link(&pos_arg)?;
275-
write!(
275+
writeln!(
276276
err,
277-
"writing positional symlink entry with path {pos_arg:?} and target {target:?}\n"
277+
"writing positional symlink entry with path {pos_arg:?} and target {target:?}"
278278
)?;
279279
writer.add_symlink_from_path(pos_arg, target, options)?;
280280
} else if file_type.is_file() {
281-
write!(err, "writing positional file entry with path {pos_arg:?}\n")?;
281+
writeln!(err, "writing positional file entry with path {pos_arg:?}")?;
282282
writer.start_file_from_path(&pos_arg, options)?;
283283
let mut f = fs::File::open(pos_arg)?;
284284
io::copy(&mut f, &mut writer)?;
285285
} else {
286286
assert!(file_type.is_dir());
287-
write!(
287+
writeln!(
288288
err,
289-
"writing positional recursive dir entry for {pos_arg:?}\n"
289+
"writing positional recursive dir entry for {pos_arg:?}"
290290
)?;
291291
enter_recursive_dir_entries(err, None, &pos_arg, &mut writer, options)?;
292292
}

0 commit comments

Comments
 (0)