this repo has no description
0
fork

Configure Feed

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

feat(gzip): adding gzip support

+126 -5
+35
Cargo.lock
··· 3 3 version = 3 4 4 5 5 [[package]] 6 + name = "adler" 7 + version = "1.0.2" 8 + source = "registry+https://github.com/rust-lang/crates.io-index" 9 + checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 10 + 11 + [[package]] 6 12 name = "anstream" 7 13 version = "0.2.6" 8 14 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 107 113 version = "0.0.1" 108 114 dependencies = [ 109 115 "clap", 116 + "flate2", 110 117 "tar", 111 118 ] 112 119 ··· 123 130 checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf" 124 131 dependencies = [ 125 132 "windows-sys", 133 + ] 134 + 135 + [[package]] 136 + name = "crc32fast" 137 + version = "1.3.2" 138 + source = "registry+https://github.com/rust-lang/crates.io-index" 139 + checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" 140 + dependencies = [ 141 + "cfg-if", 126 142 ] 127 143 128 144 [[package]] ··· 159 175 ] 160 176 161 177 [[package]] 178 + name = "flate2" 179 + version = "1.0.25" 180 + source = "registry+https://github.com/rust-lang/crates.io-index" 181 + checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" 182 + dependencies = [ 183 + "crc32fast", 184 + "miniz_oxide", 185 + ] 186 + 187 + [[package]] 162 188 name = "heck" 163 189 version = "0.4.1" 164 190 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 204 230 version = "0.3.1" 205 231 source = "registry+https://github.com/rust-lang/crates.io-index" 206 232 checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" 233 + 234 + [[package]] 235 + name = "miniz_oxide" 236 + version = "0.6.2" 237 + source = "registry+https://github.com/rust-lang/crates.io-index" 238 + checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" 239 + dependencies = [ 240 + "adler", 241 + ] 207 242 208 243 [[package]] 209 244 name = "once_cell"
+1
Cargo.toml
··· 13 13 14 14 [dependencies] 15 15 clap = { version = "4.2.1", features = ["derive"] } 16 + flate2 = "1.0" 16 17 tar = "0.4.38" 17 18
+2 -1
README.md
··· 4 4 5 5 A compression multi-tool for the CLI. 6 6 7 - Currently supports basic operations on `tar` archives. 7 + Currently supports basic operations on `tar` and `gzip` archives. 8 8 9 9 ## Supported formats 10 10 11 + - gzip 11 12 - tar
+33
src/gzip.rs
··· 1 + extern crate flate2; 2 + 3 + use flate2::write::GzEncoder; 4 + use flate2::{read::GzDecoder, Compression}; 5 + use std::fs::File; 6 + use std::io::{Read, Write}; 7 + use std::path::Path; 8 + 9 + /// The standard extension for the gzip format. 10 + pub const EXT: &str = "gz"; 11 + 12 + pub fn compress_file<I: AsRef<Path>, O: Write>(in_file: I, output: O, level: u32) { 13 + compress(File::open(in_file).unwrap(), output, level); 14 + } 15 + 16 + /// Compress an input file or directory into a gzip archive. 17 + pub fn compress<I: Read, O: Write>(mut input: I, output: O, level: u32) { 18 + let mut encoder = GzEncoder::new(output, Compression::new(level)); 19 + 20 + std::io::copy(&mut input, &mut encoder).unwrap(); 21 + encoder.finish().unwrap(); 22 + } 23 + 24 + /// Extract a gzipped file 25 + pub fn extract_file<I: AsRef<Path>, O: Write>(in_file: I, output: O) { 26 + extract(File::open(in_file).unwrap(), output); 27 + } 28 + 29 + /// Extract the gzip compressed data 30 + pub fn extract<I: Read, O: Write>(input: I, mut output: O) { 31 + let mut decoder = GzDecoder::new(input); 32 + std::io::copy(&mut decoder, &mut output).unwrap(); 33 + }
+55 -4
src/main.rs
··· 1 + mod gzip; 1 2 mod tar; 2 3 3 4 use clap::{Args, Parser, Subcommand}; ··· 20 21 21 22 /// extract by guessing the format 22 23 Extract(ExtractArgs), 24 + 25 + /// gzip compression 26 + Gzip(GzipArgs), 23 27 } 24 28 25 29 #[derive(Args, Debug)] ··· 40 44 input: String, 41 45 42 46 /// Output file/directory 43 - /// 44 - /// If it's not provided, the extension is inferred from the compression type. 45 47 #[arg(index = 2)] 46 48 output: Option<String>, 47 49 ··· 49 51 #[arg(short, long)] 50 52 compress: bool, 51 53 52 - /// Extract the input file 54 + /// Extract the input 53 55 #[arg(short, long)] 54 56 extract: bool, 55 57 } 56 58 59 + #[derive(Args, Debug)] 60 + struct GzipArgs { 61 + /// Input file 62 + #[arg(index = 1)] 63 + input: String, 64 + 65 + /// Output file/directory 66 + #[arg(index = 2)] 67 + output: Option<String>, 68 + 69 + /// Compress the input (default) 70 + #[arg(short, long)] 71 + compress: bool, 72 + 73 + /// Extract the input 74 + #[arg(short, long)] 75 + extract: bool, 76 + 77 + /// Level of compression 78 + /// 79 + /// This is an int 0-9, with 0 being no compression and 9 being highest compression. 80 + #[arg(long, default_value_t = 6)] 81 + compression: u32, 82 + } 83 + 57 84 /// Generates the output filename. 58 85 /// This either takes the given name or guesses the name based on the extension 59 86 fn output_filename(input: &Path, output: Option<String>, extension: &str) -> String { ··· 82 109 // Compress by default, warn if if looks like an archive. 83 110 if input_path.extension().unwrap() == tar::EXT { 84 111 println!( 85 - "error: input appears to be a tar archive, exiting. Use '--compress' if needed." 112 + "error: input appears to already be a tar archive, exiting. Use '--compress' if needed." 86 113 ) 87 114 } else { 88 115 let out = output_filename(input_path, args.output, tar::EXT); ··· 91 118 } 92 119 } 93 120 121 + /// Execute a gzip command 122 + fn command_gzip(args: GzipArgs) { 123 + let input_path = Path::new(&args.input); 124 + if args.compress { 125 + let out = output_filename(input_path, args.output, gzip::EXT); 126 + gzip::compress_file(input_path, File::create(out).unwrap(), args.compression); 127 + } else if args.extract { 128 + assert!(args.output.is_some(), "error: output filename required"); 129 + gzip::extract_file(input_path, File::create(args.output.unwrap()).unwrap()); 130 + } else { 131 + // Neither is set. 132 + // Compress by default, warn if if looks like an archive. 133 + if input_path.extension().unwrap() == gzip::EXT { 134 + println!( 135 + "error: input appears to already be a gzip archive, exiting. Use '--compress' if needed." 136 + ) 137 + } else { 138 + let out = output_filename(input_path, args.output, gzip::EXT); 139 + gzip::compress_file(input_path, File::create(out).unwrap(), args.compression); 140 + } 141 + } 142 + } 143 + 94 144 /// Execute an extract command. 95 145 /// 96 146 /// Attempts to extract based on the file extension. ··· 107 157 match args.format { 108 158 Some(Format::Tar(a)) => command_tar(a), 109 159 Some(Format::Extract(a)) => command_extract(a), 160 + Some(Format::Gzip(a)) => command_gzip(a), 110 161 None => println!("none"), 111 162 }; 112 163 }