diff --git a/.righteous-sandbox.json b/.righteous-sandbox.json index 6337fd7..98d84be 100644 --- a/.righteous-sandbox.json +++ b/.righteous-sandbox.json @@ -1,5 +1,4 @@ { "rust_update": true, - "just_init": "_init", "just_list": true } diff --git a/CREDITS.md b/CREDITS.md index a5d4a7f..d849835 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -1,21 +1,21 @@ # Project Dependencies Package: channelz - Version: 0.8.1 - Generated: 2023-12-28 19:11:09 UTC + Version: 0.8.2 + Generated: 2024-01-21 07:03:07 UTC | Package | Version | Author(s) | License | | ---- | ---- | ---- | ---- | -| [ahash](https://github.com/tkaitchuck/ahash) | 0.8.6 | [Tom Kaitchuck](mailto:tom.kaitchuck@gmail.com) | Apache-2.0 or MIT | +| [ahash](https://github.com/tkaitchuck/ahash) | 0.8.7 | [Tom Kaitchuck](mailto:tom.kaitchuck@gmail.com) | Apache-2.0 or MIT | | [alloc-no-stdlib](https://github.com/dropbox/rust-alloc-no-stdlib) | 2.0.4 | [Daniel Reiter Horn](mailto:danielrh@dropbox.com) | BSD-3-Clause | | [alloc-stdlib](https://github.com/dropbox/rust-alloc-no-stdlib) | 0.2.2 | [Daniel Reiter Horn](mailto:danielrh@dropbox.com) | BSD-3-Clause | -| [argyle](https://github.com/Blobfolio/argyle) | 0.6.8 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL | +| [argyle](https://github.com/Blobfolio/argyle) | 0.7.0 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL | | [brotli](https://github.com/dropbox/rust-brotli) | 3.4.0 | [Daniel Reiter Horn](mailto:danielrh@dropbox.com) and The Brotli Authors | BSD-3-Clause or MIT | | [brotli-decompressor](https://github.com/dropbox/rust-brotli-decompressor) | 2.5.1 | [Daniel Reiter Horn](mailto:danielrh@dropbox.com) and The Brotli Authors | BSD-3-Clause or MIT | | [bytecount](https://github.com/llogiq/bytecount) | 0.6.7 | [Andre Bogus](mailto:bogusandre@gmail.de) and [Joshua Landau](mailto:joshua@landau.ws) | Apache-2.0 or MIT | | [cfg-if](https://github.com/alexcrichton/cfg-if) | 1.0.0 | [Alex Crichton](mailto:alex@alexcrichton.com) | Apache-2.0 or MIT | -| [crossbeam-deque](https://github.com/crossbeam-rs/crossbeam) | 0.8.4 | | Apache-2.0 or MIT | -| [crossbeam-epoch](https://github.com/crossbeam-rs/crossbeam) | 0.9.17 | | Apache-2.0 or MIT | -| [crossbeam-utils](https://github.com/crossbeam-rs/crossbeam) | 0.8.18 | | Apache-2.0 or MIT | +| [crossbeam-deque](https://github.com/crossbeam-rs/crossbeam) | 0.8.5 | | Apache-2.0 or MIT | +| [crossbeam-epoch](https://github.com/crossbeam-rs/crossbeam) | 0.9.18 | | Apache-2.0 or MIT | +| [crossbeam-utils](https://github.com/crossbeam-rs/crossbeam) | 0.8.19 | | Apache-2.0 or MIT | | [ctrlc](https://github.com/Detegr/rust-ctrlc.git) | 3.4.2 | [Antti Keränen](mailto:detegr@gmail.com) | Apache-2.0 or MIT | | [dactyl](https://github.com/Blobfolio/dactyl) | 0.6.0 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL | | [dowser](https://github.com/Blobfolio/dowser) | 0.8.1 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL | @@ -24,8 +24,8 @@ | [fyi_msg](https://github.com/Blobfolio/fyi) | 0.11.8 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL | | [libdeflate-sys](https://github.com/adamkewley/libdeflater) | 1.19.0 | [Adam Kewley](mailto:contact@adamkewley.com) | Apache-2.0 | | [libdeflater](https://github.com/adamkewley/libdeflater) | 1.19.0 | [Adam Kewley](mailto:contact@adamkewley.com) | Apache-2.0 | -| [rayon](https://github.com/rayon-rs/rayon) | 1.8.0 | [Niko Matsakis](mailto:niko@alum.mit.edu) and [Josh Stone](mailto:cuviper@gmail.com) | Apache-2.0 or MIT | -| [rayon-core](https://github.com/rayon-rs/rayon) | 1.12.0 | [Niko Matsakis](mailto:niko@alum.mit.edu) and [Josh Stone](mailto:cuviper@gmail.com) | Apache-2.0 or MIT | +| [rayon](https://github.com/rayon-rs/rayon) | 1.8.1 | [Niko Matsakis](mailto:niko@alum.mit.edu) and [Josh Stone](mailto:cuviper@gmail.com) | Apache-2.0 or MIT | +| [rayon-core](https://github.com/rayon-rs/rayon) | 1.12.1 | [Niko Matsakis](mailto:niko@alum.mit.edu) and [Josh Stone](mailto:cuviper@gmail.com) | Apache-2.0 or MIT | | [tempfile](https://github.com/Stebalien/tempfile) | 3.9.0 | [Steven Allen](mailto:steven@stebalien.com), The Rust Project Developers, [Ashley Mannix](mailto:ashleymannix@live.com.au), and [Jason White](mailto:me@jasonwhite.io) | Apache-2.0 or MIT | | [term_size](https://github.com/kbknapp/term_size-rs.git) | 0.3.2 | [Kevin K.](mailto:kbknapp@gmail.com) and [Benjamin Sago](mailto:ogham@bsago.me) | Apache-2.0 or MIT | | [unicode-width](https://github.com/unicode-rs/unicode-width) | 0.1.11 | [kwantam](mailto:kwantam@gmail.com) and [Manish Goregaokar](mailto:manishsmail@gmail.com) | Apache-2.0 or MIT | diff --git a/Cargo.toml b/Cargo.toml index a625111..193914d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "channelz" -version = "0.8.1" +version = "0.8.2" license = "WTFPL" authors = ["Josh Stoik "] edition = "2021" @@ -12,7 +12,7 @@ publish = false [package.metadata.deb] maintainer = "Josh Stoik " -copyright = "2022, Blobfolio, LLC " +copyright = "2024, Blobfolio, LLC " license-file = ["./LICENSE", "0"] revision = "1" depends = "$auto" @@ -26,7 +26,7 @@ appcache; atom; bmp; css; csv; doc(x); eot; geojson; htc; htm(l); ico; ics; js;\ json; jsonld; manifest; md; mjs; otf; pdf; rdf; rss; svg; ttf; txt; vcard; vcs;\n\ vtt; wasm; webmanifest; xhtm(l); xls(x); xml; xsl; y(a)ml""" assets = [ - ["./target/x86_64-unknown-linux-gnu/release/channelz", "usr/bin/", "755"], + ["./target/release/channelz", "usr/bin/", "755"], ["./release/completions/channelz.bash", "etc/bash_completion.d/", "644"], ["./release/man/channelz.1.gz", "usr/share/man/man1/", "644"], ] @@ -68,7 +68,7 @@ description = "Print version information and exit." short = "-l" long = "--list" label = "" -description = "Read (absolute) file and/or directory paths from this text file, one entry per line." +description = "Read (absolute) file and/or directory paths to compress from this text file — or STDIN if '-' — one entry per line, instead of or in addition to specifying directly at the end of the command." path = true [[package.metadata.bashman.arguments]] @@ -89,7 +89,7 @@ lines = [ dactyl = "0.6.*" [dependencies] -argyle = "0.6.*" +argyle = "0.7.*" ctrlc = "3.4.*" dactyl = "0.6.*" dowser = "0.8.*" diff --git a/README.md b/README.md index beedd2f..78b27fd 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ These benchmarks were performed on a Intel® Core™ i7-10610U with four discret See also: [CREDITS.md](CREDITS.md) -Copyright © 2023 [Blobfolio, LLC](https://blobfolio.com) <hello@blobfolio.com> +Copyright © 2024 [Blobfolio, LLC](https://blobfolio.com) <hello@blobfolio.com> This work is free. You can redistribute it and/or modify it under the terms of the Do What The Fuck You Want To Public License, Version 2. diff --git a/justfile b/justfile index f1a4cdb..5f41b35 100644 --- a/justfile +++ b/justfile @@ -19,11 +19,13 @@ pkg_id := "channelz" pkg_name := "ChannelZ" cargo_dir := "/tmp/" + pkg_id + "-cargo" -cargo_bin := cargo_dir + "/x86_64-unknown-linux-gnu/release/" + pkg_id +cargo_bin := cargo_dir + "/release/" + pkg_id data_dir := "/tmp/bench-data" doc_dir := justfile_directory() + "/doc" release_dir := justfile_directory() + "/release" +export RUSTFLAGS := "-C target-cpu=x86-64-v3" + # Build Release! @@ -32,7 +34,6 @@ release_dir := justfile_directory() + "/release" cargo build \ --bin "{{ pkg_id }}" \ --release \ - --target x86_64-unknown-linux-gnu \ --target-dir "{{ cargo_dir }}" @@ -52,30 +53,6 @@ release_dir := justfile_directory() + "/release" mv "{{ justfile_directory() }}/target" "{{ cargo_dir }}" -@build-pgo: clean - [ ! -d "/tmp/pgo-data" ] || rm -rf /tmp/pgo-data - - RUSTFLAGS="-Cprofile-generate=/tmp/pgo-data" cargo build \ - --bin "{{ pkg_id }}" \ - --release \ - --target x86_64-unknown-linux-gnu \ - --target-dir "{{ cargo_dir }}" - - just _bench-reset - "{{ cargo_bin }}" -p "{{ data_dir }}/test" - "{{ cargo_bin }}" -p --force "{{ justfile_directory() }}/Cargo.lock" "{{ justfile_directory() }}/Cargo.toml" - rm Cargo*.gz Cargo*.br - - /usr/local/rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-profdata \ - merge -o /tmp/pgo-data/merged.profdata /tmp/pgo-data - - RUSTFLAGS="-Cprofile-use=/tmp/pgo-data/merged.profdata -Cllvm-args=-pgo-warn-missing-function" cargo build \ - --bin "{{ pkg_id }}" \ - --release \ - --target x86_64-unknown-linux-gnu \ - --target-dir "{{ cargo_dir }}" - - @clean: # Most things go here. [ ! -d "{{ cargo_dir }}" ] || rm -rf "{{ cargo_dir }}" @@ -91,7 +68,6 @@ release_dir := justfile_directory() + "/release" cargo clippy \ --release \ --all-features \ - --target x86_64-unknown-linux-gnu \ --target-dir "{{ cargo_dir }}" @@ -108,12 +84,11 @@ release_dir := justfile_directory() + "/release" cargo doc \ --release \ --no-deps \ - --target x86_64-unknown-linux-gnu \ --target-dir "{{ cargo_dir }}" # Move the docs and clean up ownership. [ ! -d "{{ doc_dir }}" ] || rm -rf "{{ doc_dir }}" - mv "{{ cargo_dir }}/x86_64-unknown-linux-gnu/doc" "{{ justfile_directory() }}" + mv "{{ cargo_dir }}/doc" "{{ justfile_directory() }}" just _fix-chown "{{ doc_dir }}" exit 0 @@ -124,7 +99,6 @@ release_dir := justfile_directory() + "/release" cargo run \ --bin "{{ pkg_id }}" \ --release \ - --target x86_64-unknown-linux-gnu \ --target-dir "{{ cargo_dir }}" \ -- {{ ARGS }} @@ -133,11 +107,9 @@ release_dir := justfile_directory() + "/release" @test: clear cargo test \ - --target x86_64-unknown-linux-gnu \ --target-dir "{{ cargo_dir }}" cargo test \ --release \ - --target x86_64-unknown-linux-gnu \ --target-dir "{{ cargo_dir }}" @@ -204,13 +176,6 @@ _bench-init: cp -aR "{{ data_dir }}/raw" "{{ data_dir }}/test" -# Init dependencies. -@_init: - # We need beta until 1.51 is stable. - # env RUSTUP_PERMIT_COPY_RENAME=true rustup default beta - # env RUSTUP_PERMIT_COPY_RENAME=true rustup component add clippy - - # Fix file/directory permissions. @_fix-chmod PATH: [ ! -e "{{ PATH }}" ] || find "{{ PATH }}" -type f -exec chmod 0644 {} + diff --git a/release/man/channelz.1 b/release/man/channelz.1 index e99631c..bdd4f61 100644 --- a/release/man/channelz.1 +++ b/release/man/channelz.1 @@ -1,6 +1,6 @@ -.TH "CHANNELZ" "1" "December 2023" "ChannelZ v0.8.1" "User Commands" +.TH "CHANNELZ" "1" "January 2024" "ChannelZ v0.8.2" "User Commands" .SH NAME -ChannelZ \- Manual page for channelz v0.8.1. +ChannelZ \- Manual page for channelz v0.8.2. .SH DESCRIPTION Fast, multi\-threaded static Gzip/Brotli encoding tool for the CLI. .SS USAGE: @@ -28,7 +28,7 @@ Print version information and exit. .SS OPTIONS: .TP \fB\-l\fR, \fB\-\-list\fR -Read (absolute) file and/or directory paths from this text file, one entry per line. +Read (absolute) file and/or directory paths to compress from this text file — or STDIN if '\-' — one entry per line, instead of or in addition to specifying directly at the end of the command. .SS : .TP One or more file and/or directory paths to compress and/or (recursively) crawl. diff --git a/src/enc.rs b/src/enc.rs index 7015781..b010132 100644 --- a/src/enc.rs +++ b/src/enc.rs @@ -2,9 +2,20 @@ # ChannelZ: Encoding */ +use brotli::enc::{ + BrotliCompress, + backward_references::BrotliEncoderParams, +}; +use libdeflater::{ + CompressionLvl, + Compressor, +}; use std::{ io::Cursor, - path::Path, + path::{ + Path, + PathBuf, + }, }; @@ -26,27 +37,30 @@ pub(super) fn encode(src: &Path) -> Option<(u64, u64, u64)> { let len = raw.len(); #[cfg(target_pointer_width = "128")] - if 0 == len || len > 18_446_744_073_709_551_615 { return None; } + if 0 == len || len > u128::from(u64::MAX) { return None; } #[cfg(not(target_pointer_width = "128"))] if len == 0 { return None; } - // Do Gzip first because it will likely be bigger than Brotli, saving us - // the trouble of allocating additional buffer space down the road. + // A shared buffer for our encoded copies. let mut buf: Vec = Vec::new(); - let mut src = src.to_path_buf(); // Own it for later. - // The output path. - let gz_dst = { - let mut tmp = src.clone(); - tmp.as_mut_os_string().push(".gz"); - tmp - }; - let len_gz = encode_gzip(&gz_dst, &raw, &mut buf).unwrap_or(len); - - // Change the output path, then do Brotli. - src.as_mut_os_string().push(".br"); - let len_br = encode_brotli(&src, &raw, &mut buf).unwrap_or(len); + // Start with gzip since it will likely be larger, saving us the trouble + // of having to increase the buffer size a second time. + let dst_gz = join_ext(src, ".gz"); + let len_gz = encode_gzip(&dst_gz, &raw, &mut buf) + .unwrap_or_else(|| { + remove_if(&dst_gz); + len + }); + + // Now brotli! + let dst_br = join_ext(src, ".br"); + let len_br = encode_brotli(&dst_br, &raw, &mut buf) + .unwrap_or_else(|| { + remove_if(&dst_br); + len + }); // Done! Some((len as u64, len_br as u64, len_gz as u64)) @@ -57,22 +71,13 @@ pub(super) fn encode(src: &Path) -> Option<(u64, u64, u64)> { /// This will attempt to encode `raw` using Brotli, writing the result to disk /// if it is smaller than the original. fn encode_brotli(path: &Path, raw: &[u8], buf: &mut Vec) -> Option { - use brotli::enc::{ - BrotliCompress, - backward_references::BrotliEncoderParams, - }; - buf.truncate(0); let config = BrotliEncoderParams::default(); - let size = BrotliCompress(&mut Cursor::new(raw), buf, &config).ok()?; - if size != 0 && size < raw.len() { - if write_atomic::write_file(path, &buf[..size]).is_ok() { - return Some(size); - } - remove_if(path); + let len = BrotliCompress(&mut Cursor::new(raw), buf, &config).ok()?; + if len != 0 && len < raw.len() && write_atomic::write_file(path, &buf[..len]).is_ok() { + Some(len) } - - None + else { None } } /// # Encode Gzip. @@ -80,26 +85,25 @@ fn encode_brotli(path: &Path, raw: &[u8], buf: &mut Vec) -> Option { /// This will attempt to encode `raw` using Gzip, writing the result to disk /// if it is smaller than the original. fn encode_gzip(path: &Path, raw: &[u8], buf: &mut Vec) -> Option { - use libdeflater::{ - CompressionLvl, - Compressor, - }; - // Set up the buffer/writer. - let old_len = raw.len(); let mut writer = Compressor::new(CompressionLvl::best()); - buf.resize(writer.gzip_compress_bound(old_len), 0); + buf.resize(writer.gzip_compress_bound(raw.len()), 0); // Encode! - if let Ok(len) = writer.gzip_compress(raw, buf) { - if 0 < len && len < old_len && write_atomic::write_file(path, &buf[..len]).is_ok() { - return Some(len); - } + let len = writer.gzip_compress(raw, buf).ok()?; + if len != 0 && len < raw.len() && write_atomic::write_file(path, &buf[..len]).is_ok() { + Some(len) } + else { None } +} - // Clean up. - remove_if(path); - None +/// # Push Extension. +/// +/// Create a new path by appending .gz/.br to it. +fn join_ext(src: &Path, ext: &str) -> PathBuf { + let mut dst = src.to_path_buf(); + dst.as_mut_os_string().push(ext); + dst } /// # Remove If It Exists. diff --git a/src/main.rs b/src/main.rs index 18e779d..881e052 100644 --- a/src/main.rs +++ b/src/main.rs @@ -205,7 +205,7 @@ fn helper() { `-( / -=`\ | .==`=( -= = _/ /`--. (M==M=M==M=M==M==M==M==M) - \=N=N==N=N==N=N==N=NN=/ ", "\x1b[38;5;199mChannelZ\x1b[0;38;5;69m v", env!("CARGO_PKG_VERSION"), "\x1b[0m", r" + \=N=N==N=N==N=N==N=NN=/ ", "\x1b[38;5;199mChannelZ\x1b[0;38;5;69m v", env!("CARGO_PKG_VERSION"), "\x1b[0m", r#" \M==M=M==M=M==M===M=/ Fast, recursive, multi-threaded \N=N==N=N==N=NN=N=/ static Brotli and Gzip encoding. \M==M==M=M==M==M/ @@ -226,8 +226,10 @@ FLAGS: -V, --version Print version information and exit. OPTIONS: - -l, --list Read (absolute) file and/or directory paths from this - text file, one entry per line. + -l, --list Read (absolute) file and/or directory paths to compress + from this text file — or STDIN if "-" — one entry per + line, instead of or in addition to specifying + directly at the end of the command. ARGS: ... One or more file and/or directory paths to compress @@ -240,7 +242,7 @@ Note: static copies will only be generated for files with these extensions: appcache; atom; bmp; css; csv; doc(x); eot; geojson; htc; htm(l); ico; ics; js; json; jsonld; manifest; md; mjs; otf; pdf; rdf; rss; svg; ttf; txt; vcard; vcs; vtt; wasm; webmanifest; xhtm(l); xls(x); xml; xsl; y(a)ml -" +"# )); }