From c4c165b6d6332d60f1efa82bba75d86f579dcb4f Mon Sep 17 00:00:00 2001 From: Kirill Taran Date: Mon, 10 Jan 2022 11:45:09 +0100 Subject: [PATCH 01/23] Initial commit --- ark-cli/LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 ark-cli/LICENSE diff --git a/ark-cli/LICENSE b/ark-cli/LICENSE new file mode 100644 index 00000000..ea8b0971 --- /dev/null +++ b/ark-cli/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 ARK Builders + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From bd9a0c5b6baf98c926810a2dc876cd312ebf7bb8 Mon Sep 17 00:00:00 2001 From: Kirill Taran Date: Wed, 19 Jan 2022 16:08:48 +0200 Subject: [PATCH 02/23] Tag storages backup implemented --- ark-cli/.github/workflows/rust.yml | 28 +++ ark-cli/Cargo.lock | 328 +++++++++++++++++++++++++++++ ark-cli/Cargo.toml | 13 ++ ark-cli/rustfmt.toml | 17 ++ ark-cli/src/main.rs | 167 +++++++++++++++ 5 files changed, 553 insertions(+) create mode 100644 ark-cli/.github/workflows/rust.yml create mode 100644 ark-cli/Cargo.lock create mode 100644 ark-cli/Cargo.toml create mode 100644 ark-cli/rustfmt.toml create mode 100644 ark-cli/src/main.rs diff --git a/ark-cli/.github/workflows/rust.yml b/ark-cli/.github/workflows/rust.yml new file mode 100644 index 00000000..9388010e --- /dev/null +++ b/ark-cli/.github/workflows/rust.yml @@ -0,0 +1,28 @@ +name: Build CLI tool + +on: [push] + +env: + CARGO_TERM_COLOR: always +jobs: + check: + name: Build ARK-CLI + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + components: rustfmt, clippy + + - name: Check + run: cargo check + + - name: Format + run: cargo fmt --all -- --check + + - name: Build Release + run: cargo build --verbose --release diff --git a/ark-cli/Cargo.lock b/ark-cli/Cargo.lock new file mode 100644 index 00000000..11211b0a --- /dev/null +++ b/ark-cli/Cargo.lock @@ -0,0 +1,328 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "ark-cli" +version = "0.1.0" +dependencies = [ + "arklib", + "clap", + "home", +] + +[[package]] +name = "arklib" +version = "0.1.0" +source = "git+https://github.com/ARK-Builders/arklib?rev=508526d3#508526d3b7e896b52bcb036275afceb7755a871f" +dependencies = [ + "crc32fast", + "env_logger", + "log", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a30c3bf9ff12dfe5dae53f0a96e0febcd18420d1c0e7fad77796d9d5c4b5375" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "indexmap", + "lazy_static", + "os_str_bytes", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_derive" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "517358c28fcef6607bf6f76108e02afad7e82297d132a6b846dcc1fc3efcd153" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "crc32fast" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "env_logger" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "home" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2456aef2e6b6a9784192ae780c0f15bc57df0e918585282325e8c8ac27737654" +dependencies = [ + "winapi", +] + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "indexmap" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +dependencies = [ + "memchr", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/ark-cli/Cargo.toml b/ark-cli/Cargo.toml new file mode 100644 index 00000000..80a82dec --- /dev/null +++ b/ark-cli/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "ark-cli" +version = "0.1.0" +edition = "2021" + +[[bin]] +name = "ark-cli" + +[dependencies] +arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "508526d3" } + +clap = { version = "3.0.10", features = ["derive"] } +home = "0.5.3" diff --git a/ark-cli/rustfmt.toml b/ark-cli/rustfmt.toml new file mode 100644 index 00000000..2f7bc3e1 --- /dev/null +++ b/ark-cli/rustfmt.toml @@ -0,0 +1,17 @@ +verbose = "Verbose" +tab_spaces = 4 + +max_width = 80 +chain_width = 50 +single_line_if_else_max_width = 30 + +force_explicit_abi = true + +report_todo = "Always" +report_fixme = "Always" + +reorder_imports = true + +wrap_comments = true + +newline_style = "Unix" diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs new file mode 100644 index 00000000..6d9d56e7 --- /dev/null +++ b/ark-cli/src/main.rs @@ -0,0 +1,167 @@ +use std::fs::{canonicalize, copy, create_dir_all, File}; +use std::io::prelude::*; +use std::io::BufReader; +use std::path::{Path, PathBuf}; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; + +use clap::{Parser, Subcommand}; +use home::home_dir; + +use arklib::TAG_STORAGE_FILENAME; + +#[derive(Parser, Debug)] +#[clap(name = "ark-cli")] +#[clap(about = "Manage ARK tag storages and indexes", long_about = None)] +struct Cli { + #[clap(subcommand)] + command: Command, +} + +#[derive(Subcommand, Debug)] +enum Command { + Backup { + #[clap(parse(from_os_str))] + roots_cfg: Option, + }, +} + +const ARK_HOME: &str = ".ark"; + +const ROOTS_CFG_FILENAME: &str = "roots"; +const HOME_BACKUPS_DIRNAME: &str = "backups"; + +fn main() { + let args = Cli::parse(); + + match &args.command { + Command::Backup { roots_cfg } => { + let timestamp = timestamp().as_secs(); + let backup_dir = home_dir() + .expect("Couldn't retrieve home directory!") + .join(&ARK_HOME) + .join(&HOME_BACKUPS_DIRNAME) + .join(×tamp.to_string()); + + if backup_dir.is_dir() { + println!("Wait at least 1 second, please!"); + std::process::exit(0) + } + + println!("Preparing backup:"); + let roots = if let Some(path) = roots_cfg { + println!( + "\tRoots config provided explicitly:\n\t\t{}", + path.display() + ); + let config = File::open(&path).expect("File doesn't exist!"); + + parse_roots(config) + } else { + let roots_cfg = home_roots_cfg(); + + if let Ok(config) = File::open(&roots_cfg) { + println!( + "\tRoots config was found automatically:\n\t\t{}", + roots_cfg.display() + ); + + parse_roots(config) + } else { + println!("\tRoots config wasn't found."); + + println!("Looking for a folder containing tag storage:"); + let path = canonicalize(PathBuf::from(".")) + .expect("Couldn't canonicalize working directory!"); + + let result = path.ancestors().find(|path| { + println!("\t{}", path.display()); + tag_storage_exists(path) + }); + + if let Some(root) = result { + println!("Root folder found:\n\t{}", root.display()); + vec![root.to_path_buf()] + } else { + println!("Root folder wasn't found."); + vec![] + } + } + }; + + let (valid, invalid): (Vec, Vec) = roots + .into_iter() + .partition(|root| tag_storage_exists(&root)); + + if !invalid.is_empty() { + println!("These folders don't contain tag storages:"); + invalid + .into_iter() + .for_each(|root| println!("\t{}", root.display())); + } + + if valid.is_empty() { + println!("Nothing to backup. Bye!"); + std::process::exit(0) + } + + create_dir_all(&backup_dir) + .expect("Couldn't create backup directory!"); + + let mut roots_cfg_backup = + File::create(&backup_dir.join(&ROOTS_CFG_FILENAME)) + .expect("Couldn't backup roots config!"); + + valid.iter().for_each(|root| { + writeln!(roots_cfg_backup, "{}", root.display()) + .expect("Couldn't write to roots config backup!") + }); + + println!("Performing backups:"); + valid + .into_iter() + .enumerate() + .for_each(|(i, root)| { + println!("\tRoot {}", root.display()); + let storage_backup = backup_dir.join(&i.to_string()); + let result = + copy(root.join(&TAG_STORAGE_FILENAME), storage_backup); + if let Err(e) = result { + println!("\t\tFailed to copy tag storage!\n\t\t{}", e); + } + }); + + println!("Backup created:\n\t{}", backup_dir.display()); + } + } +} + +fn home_roots_cfg() -> PathBuf { + return home_dir() + .expect("Couldn't retrieve home directory!") + .join(&ARK_HOME) + .join(&ROOTS_CFG_FILENAME); +} + +fn tag_storage_exists(path: &Path) -> bool { + return File::open(path.join(&TAG_STORAGE_FILENAME)).is_ok(); +} + +fn parse_roots(config: File) -> Vec { + return BufReader::new(config) + .lines() + .filter_map(|line| match line { + Ok(path) => Some(PathBuf::from(path)), + Err(msg) => { + println!("{:?}", msg); + None + } + }) + .collect(); +} + +fn timestamp() -> Duration { + let start = SystemTime::now(); + return start + .duration_since(UNIX_EPOCH) + .expect("Time went backwards!"); +} From 127f8ae3dbe989cc730356c96e3c2400475bf2d2 Mon Sep 17 00:00:00 2001 From: Kirill Taran Date: Sun, 23 Jan 2022 21:39:35 +0200 Subject: [PATCH 03/23] Collisions detection subcommand --- ark-cli/Cargo.lock | 23 ++++++++++++++++++- ark-cli/Cargo.toml | 3 ++- ark-cli/src/main.rs | 56 ++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 77 insertions(+), 5 deletions(-) diff --git a/ark-cli/Cargo.lock b/ark-cli/Cargo.lock index 11211b0a..7d5bd044 100644 --- a/ark-cli/Cargo.lock +++ b/ark-cli/Cargo.lock @@ -18,12 +18,13 @@ dependencies = [ "arklib", "clap", "home", + "walkdir", ] [[package]] name = "arklib" version = "0.1.0" -source = "git+https://github.com/ARK-Builders/arklib?rev=508526d3#508526d3b7e896b52bcb036275afceb7755a871f" +source = "git+https://github.com/ARK-Builders/arklib?rev=a127c38e#a127c38eef1436a9c385b81a50ebbdfce57597ff" dependencies = [ "crc32fast", "env_logger", @@ -252,6 +253,15 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "strsim" version = "0.10.0" @@ -296,6 +306,17 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/ark-cli/Cargo.toml b/ark-cli/Cargo.toml index 80a82dec..0d060de2 100644 --- a/ark-cli/Cargo.toml +++ b/ark-cli/Cargo.toml @@ -7,7 +7,8 @@ edition = "2021" name = "ark-cli" [dependencies] -arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "508526d3" } +arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "a127c38e" } clap = { version = "3.0.10", features = ["derive"] } +walkdir = "2.3.2" home = "0.5.3" diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs index 6d9d56e7..c2ff3187 100644 --- a/ark-cli/src/main.rs +++ b/ark-cli/src/main.rs @@ -1,4 +1,5 @@ -use std::fs::{canonicalize, copy, create_dir_all, File}; +use std::env::current_dir; +use std::fs::{canonicalize, copy, create_dir_all, metadata, File}; use std::io::prelude::*; use std::io::BufReader; use std::path::{Path, PathBuf}; @@ -6,7 +7,9 @@ use std::time::{Duration, SystemTime, UNIX_EPOCH}; use clap::{Parser, Subcommand}; use home::home_dir; +use walkdir::WalkDir; +use arklib::resource_id; use arklib::TAG_STORAGE_FILENAME; #[derive(Parser, Debug)] @@ -23,6 +26,11 @@ enum Command { #[clap(parse(from_os_str))] roots_cfg: Option, }, + + Collisions { + #[clap(parse(from_os_str))] + target_dir: Option, + }, } const ARK_HOME: &str = ".ark"; @@ -70,8 +78,10 @@ fn main() { println!("\tRoots config wasn't found."); println!("Looking for a folder containing tag storage:"); - let path = canonicalize(PathBuf::from(".")) - .expect("Couldn't canonicalize working directory!"); + let path = canonicalize( + current_dir().expect("Can't open current directory!"), + ) + .expect("Couldn't canonicalize working directory!"); let result = path.ancestors().find(|path| { println!("\t{}", path.display()); @@ -132,6 +142,46 @@ fn main() { println!("Backup created:\n\t{}", backup_dir.display()); } + + Command::Collisions { target_dir } => { + use std::collections::HashMap; + + let dir_path = if let Some(path) = target_dir { + path.clone() + } else { + current_dir() + .expect("Can't open current directory!") + .clone() + }; + + println!( + "Calculating IDs of all files by path:\n\t{}", + dir_path.display() + ); + + let mut index = HashMap::::new(); + for entry in WalkDir::new(dir_path).into_iter() { + let entry2 = entry.expect("whatever").clone(); + let path = entry2.path(); + if !path.is_dir() { + let size = metadata(&path).expect("whatever").len(); + let id = resource_id::compute_id(size, path); + + let count = index.get_mut(&id); + if let Some(nonempty) = count { + *nonempty += 1; + } else { + index.insert(id, 1); + } + } + } + + for (key, count) in index.into_iter() { + if count > 1 { + println!("{}: {} times", key, count); + } + } + } } } From 97a12a96bd8de93470ef0041f730ea9b37c64f83 Mon Sep 17 00:00:00 2001 From: Kirill Taran Date: Tue, 25 Jan 2022 00:18:32 +0200 Subject: [PATCH 04/23] Moved index construction into the lib --- ark-cli/.github/workflows/rust.yml | 2 + ark-cli/Cargo.lock | 11 +++++- ark-cli/Cargo.toml | 2 +- ark-cli/src/main.rs | 63 ++++++++++++------------------ 4 files changed, 38 insertions(+), 40 deletions(-) diff --git a/ark-cli/.github/workflows/rust.yml b/ark-cli/.github/workflows/rust.yml index 9388010e..e99544f4 100644 --- a/ark-cli/.github/workflows/rust.yml +++ b/ark-cli/.github/workflows/rust.yml @@ -4,10 +4,12 @@ on: [push] env: CARGO_TERM_COLOR: always + jobs: check: name: Build ARK-CLI runs-on: ubuntu-latest + steps: - uses: actions/checkout@v2 diff --git a/ark-cli/Cargo.lock b/ark-cli/Cargo.lock index 7d5bd044..af2aa3c5 100644 --- a/ark-cli/Cargo.lock +++ b/ark-cli/Cargo.lock @@ -11,6 +11,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "anyhow" +version = "1.0.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0" + [[package]] name = "ark-cli" version = "0.1.0" @@ -24,11 +30,14 @@ dependencies = [ [[package]] name = "arklib" version = "0.1.0" -source = "git+https://github.com/ARK-Builders/arklib?rev=a127c38e#a127c38eef1436a9c385b81a50ebbdfce57597ff" +source = "git+https://github.com/ARK-Builders/arklib?rev=0de0e27#0de0e272913dee116cb4bb55b736a8a82c0b7bb6" dependencies = [ + "anyhow", "crc32fast", "env_logger", + "lazy_static", "log", + "walkdir", ] [[package]] diff --git a/ark-cli/Cargo.toml b/ark-cli/Cargo.toml index 0d060de2..00053177 100644 --- a/ark-cli/Cargo.toml +++ b/ark-cli/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" name = "ark-cli" [dependencies] -arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "a127c38e" } +arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "0de0e27" } clap = { version = "3.0.10", features = ["derive"] } walkdir = "2.3.2" diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs index c2ff3187..b125ece3 100644 --- a/ark-cli/src/main.rs +++ b/ark-cli/src/main.rs @@ -1,16 +1,12 @@ use std::env::current_dir; -use std::fs::{canonicalize, copy, create_dir_all, metadata, File}; +use std::fs::{canonicalize, copy, create_dir_all, File}; use std::io::prelude::*; use std::io::BufReader; use std::path::{Path, PathBuf}; -use std::time::{Duration, SystemTime, UNIX_EPOCH}; +use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; use clap::{Parser, Subcommand}; use home::home_dir; -use walkdir::WalkDir; - -use arklib::resource_id; -use arklib::TAG_STORAGE_FILENAME; #[derive(Parser, Debug)] #[clap(name = "ark-cli")] @@ -29,7 +25,7 @@ enum Command { Collisions { #[clap(parse(from_os_str))] - target_dir: Option, + root_dir: Option, }, } @@ -133,8 +129,10 @@ fn main() { .for_each(|(i, root)| { println!("\tRoot {}", root.display()); let storage_backup = backup_dir.join(&i.to_string()); - let result = - copy(root.join(&TAG_STORAGE_FILENAME), storage_backup); + let result = copy( + root.join(&arklib::TAG_STORAGE_FILENAME), + storage_backup, + ); if let Err(e) = result { println!("\t\tFailed to copy tag storage!\n\t\t{}", e); } @@ -143,10 +141,8 @@ fn main() { println!("Backup created:\n\t{}", backup_dir.display()); } - Command::Collisions { target_dir } => { - use std::collections::HashMap; - - let dir_path = if let Some(path) = target_dir { + Command::Collisions { root_dir } => { + let dir_path = if let Some(path) = root_dir { path.clone() } else { current_dir() @@ -154,32 +150,23 @@ fn main() { .clone() }; - println!( - "Calculating IDs of all files by path:\n\t{}", - dir_path.display() - ); - - let mut index = HashMap::::new(); - for entry in WalkDir::new(dir_path).into_iter() { - let entry2 = entry.expect("whatever").clone(); - let path = entry2.path(); - if !path.is_dir() { - let size = metadata(&path).expect("whatever").len(); - let id = resource_id::compute_id(size, path); - - let count = index.get_mut(&id); - if let Some(nonempty) = count { - *nonempty += 1; - } else { - index.insert(id, 1); - } - } + println!("Building index of folder {}", dir_path.display()); + let start = Instant::now(); + let result = arklib::build_index(dir_path); + let duration = start.elapsed(); + + match result { + Ok(()) => println!("Success, took {:?}", duration), + Err(err) => println!("Failure: {:?}", err), } + println!(); - for (key, count) in index.into_iter() { - if count > 1 { - println!("{}: {} times", key, count); - } + let index = arklib::INDEX.read().unwrap(); + println!("Here are {} entries in the index", index.len()); + + let collisions = arklib::COLLISIONS.read().unwrap(); + for (key, count) in collisions.iter() { + println!("Id {} calculated {} times", key, count); } } } @@ -193,7 +180,7 @@ fn home_roots_cfg() -> PathBuf { } fn tag_storage_exists(path: &Path) -> bool { - return File::open(path.join(&TAG_STORAGE_FILENAME)).is_ok(); + return File::open(path.join(&arklib::TAG_STORAGE_FILENAME)).is_ok(); } fn parse_roots(config: File) -> Vec { From ffe96f7d8e58532ff9d1d3f8cf9250c786528b40 Mon Sep 17 00:00:00 2001 From: Kirill Taran Date: Thu, 10 Feb 2022 00:30:34 +0200 Subject: [PATCH 05/23] Updating dependency to arklib --- ark-cli/Cargo.lock | 25 +++++++++++++++++++++++-- ark-cli/Cargo.toml | 3 ++- ark-cli/src/main.rs | 22 ++++++++++++---------- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/ark-cli/Cargo.lock b/ark-cli/Cargo.lock index af2aa3c5..7bad110f 100644 --- a/ark-cli/Cargo.lock +++ b/ark-cli/Cargo.lock @@ -23,6 +23,7 @@ version = "0.1.0" dependencies = [ "arklib", "clap", + "env_logger 0.8.4", "home", "walkdir", ] @@ -30,11 +31,12 @@ dependencies = [ [[package]] name = "arklib" version = "0.1.0" -source = "git+https://github.com/ARK-Builders/arklib?rev=0de0e27#0de0e272913dee116cb4bb55b736a8a82c0b7bb6" +source = "git+https://github.com/ARK-Builders/arklib?rev=bdf2377#bdf2377ac4492ded2fea925e060e47187008a9f5" dependencies = [ "anyhow", + "canonical-path", "crc32fast", - "env_logger", + "env_logger 0.9.0", "lazy_static", "log", "walkdir", @@ -63,6 +65,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "canonical-path" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e9e01327e6c86e92ec72b1c798d4a94810f147209bbe3ffab6a86954937a6f" + [[package]] name = "cfg-if" version = "1.0.0" @@ -108,6 +116,19 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "env_logger" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + [[package]] name = "env_logger" version = "0.9.0" diff --git a/ark-cli/Cargo.toml b/ark-cli/Cargo.toml index 00053177..f71c5c9f 100644 --- a/ark-cli/Cargo.toml +++ b/ark-cli/Cargo.toml @@ -7,8 +7,9 @@ edition = "2021" name = "ark-cli" [dependencies] -arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "0de0e27" } +arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "bdf2377" } clap = { version = "3.0.10", features = ["derive"] } +env_logger = "0.8.4" walkdir = "2.3.2" home = "0.5.3" diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs index b125ece3..c6b9db28 100644 --- a/ark-cli/src/main.rs +++ b/ark-cli/src/main.rs @@ -35,6 +35,8 @@ const ROOTS_CFG_FILENAME: &str = "roots"; const HOME_BACKUPS_DIRNAME: &str = "backups"; fn main() { + env_logger::init(); + let args = Cli::parse(); match &args.command { @@ -152,21 +154,21 @@ fn main() { println!("Building index of folder {}", dir_path.display()); let start = Instant::now(); - let result = arklib::build_index(dir_path); + let result = arklib::provide_index(dir_path); let duration = start.elapsed(); match result { - Ok(()) => println!("Success, took {:?}", duration), - Err(err) => println!("Failure: {:?}", err), - } - println!(); + Ok(rwlock) => { + println!("Success, took {:?}\n", duration); - let index = arklib::INDEX.read().unwrap(); - println!("Here are {} entries in the index", index.len()); + let index = rwlock.read().unwrap(); + println!("Here are {} entries in the index", index.size()); - let collisions = arklib::COLLISIONS.read().unwrap(); - for (key, count) in collisions.iter() { - println!("Id {} calculated {} times", key, count); + for (key, count) in index.collisions.iter() { + println!("Id {:?} calculated {} times", key, count); + } + } + Err(err) => println!("Failure: {:?}", err), } } } From 47d1d54c3399ce454416640a141f5b761de1efab Mon Sep 17 00:00:00 2001 From: Kirill Taran Date: Thu, 10 Feb 2022 21:45:54 +0200 Subject: [PATCH 06/23] Folder monitoring --- ark-cli/Cargo.lock | 2 +- ark-cli/Cargo.toml | 2 +- ark-cli/src/main.rs | 70 +++++++++++++++++++++++++++++++-------------- 3 files changed, 50 insertions(+), 24 deletions(-) diff --git a/ark-cli/Cargo.lock b/ark-cli/Cargo.lock index 7bad110f..e3e86992 100644 --- a/ark-cli/Cargo.lock +++ b/ark-cli/Cargo.lock @@ -31,7 +31,7 @@ dependencies = [ [[package]] name = "arklib" version = "0.1.0" -source = "git+https://github.com/ARK-Builders/arklib?rev=bdf2377#bdf2377ac4492ded2fea925e060e47187008a9f5" +source = "git+https://github.com/ARK-Builders/arklib?rev=0c3cdd3#0c3cdd3a070a3e50043826b6b3a932421f014d7f" dependencies = [ "anyhow", "canonical-path", diff --git a/ark-cli/Cargo.toml b/ark-cli/Cargo.toml index f71c5c9f..27e195ca 100644 --- a/ark-cli/Cargo.toml +++ b/ark-cli/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" name = "ark-cli" [dependencies] -arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "bdf2377" } +arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "0c3cdd3" } clap = { version = "3.0.10", features = ["derive"] } env_logger = "0.8.4" diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs index c6b9db28..06fa5cda 100644 --- a/ark-cli/src/main.rs +++ b/ark-cli/src/main.rs @@ -27,6 +27,11 @@ enum Command { #[clap(parse(from_os_str))] root_dir: Option, }, + + Monitor { + #[clap(parse(from_os_str))] + root_dir: Option, + }, } const ARK_HOME: &str = ".ark"; @@ -143,34 +148,55 @@ fn main() { println!("Backup created:\n\t{}", backup_dir.display()); } - Command::Collisions { root_dir } => { - let dir_path = if let Some(path) = root_dir { - path.clone() - } else { - current_dir() - .expect("Can't open current directory!") - .clone() - }; - - println!("Building index of folder {}", dir_path.display()); - let start = Instant::now(); - let result = arklib::provide_index(dir_path); - let duration = start.elapsed(); + Command::Collisions { root_dir } => build_index(&root_dir, false), + Command::Monitor { root_dir } => build_index(&root_dir, true), + } +} - match result { - Ok(rwlock) => { - println!("Success, took {:?}\n", duration); +fn build_index(root_dir: &Option, monitor: bool) { + let dir_path = if let Some(path) = root_dir { + path.clone() + } else { + current_dir() + .expect("Can't open current directory!") + .clone() + }; + + println!("Building index of folder {}", dir_path.display()); + let start = Instant::now(); + let result = arklib::provide_index(dir_path); + let duration = start.elapsed(); + + match result { + Ok(rwlock) => { + println!("Success, took {:?}\n", duration); + + if monitor { + let mut index = rwlock.write().unwrap(); + loop { + match index.update() { + Err(msg) => println!("Oops! {}", msg), + Ok(diff) => { + if !diff.deleted.is_empty() { + println!("Deleted: {:?}", diff.deleted); + } + if !diff.added.is_empty() { + println!("Added: {:?}", diff.added); + } + } + } + } + } else { + let index = rwlock.read().unwrap(); - let index = rwlock.read().unwrap(); - println!("Here are {} entries in the index", index.size()); + println!("Here are {} entries in the index", index.size()); - for (key, count) in index.collisions.iter() { - println!("Id {:?} calculated {} times", key, count); - } + for (key, count) in index.collisions.iter() { + println!("Id {:?} calculated {} times", key, count); } - Err(err) => println!("Failure: {:?}", err), } } + Err(err) => println!("Failure: {:?}", err), } } From 739fec60e914e1d3e00e9dd87cbe452a155c8679 Mon Sep 17 00:00:00 2001 From: Kirill Taran Date: Fri, 11 Feb 2022 17:59:15 +0200 Subject: [PATCH 07/23] Refreshing interval for folder monitoring --- ark-cli/Cargo.lock | 2 +- ark-cli/Cargo.toml | 2 +- ark-cli/src/main.rs | 16 ++++++++++++---- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/ark-cli/Cargo.lock b/ark-cli/Cargo.lock index e3e86992..a280377b 100644 --- a/ark-cli/Cargo.lock +++ b/ark-cli/Cargo.lock @@ -31,7 +31,7 @@ dependencies = [ [[package]] name = "arklib" version = "0.1.0" -source = "git+https://github.com/ARK-Builders/arklib?rev=0c3cdd3#0c3cdd3a070a3e50043826b6b3a932421f014d7f" +source = "git+https://github.com/ARK-Builders/arklib?rev=e834f48#e834f48e88a01562034bca5b83e21dd490586d6d" dependencies = [ "anyhow", "canonical-path", diff --git a/ark-cli/Cargo.toml b/ark-cli/Cargo.toml index 27e195ca..19c1c460 100644 --- a/ark-cli/Cargo.toml +++ b/ark-cli/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" name = "ark-cli" [dependencies] -arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "0c3cdd3" } +arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "e834f48" } clap = { version = "3.0.10", features = ["derive"] } env_logger = "0.8.4" diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs index 06fa5cda..dc091b42 100644 --- a/ark-cli/src/main.rs +++ b/ark-cli/src/main.rs @@ -3,6 +3,7 @@ use std::fs::{canonicalize, copy, create_dir_all, File}; use std::io::prelude::*; use std::io::BufReader; use std::path::{Path, PathBuf}; +use std::thread; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; use clap::{Parser, Subcommand}; @@ -31,6 +32,7 @@ enum Command { Monitor { #[clap(parse(from_os_str))] root_dir: Option, + interval: Option, }, } @@ -148,12 +150,15 @@ fn main() { println!("Backup created:\n\t{}", backup_dir.display()); } - Command::Collisions { root_dir } => build_index(&root_dir, false), - Command::Monitor { root_dir } => build_index(&root_dir, true), + Command::Collisions { root_dir } => build_index(&root_dir, None), + Command::Monitor { root_dir, interval } => { + let millis = interval.unwrap_or(1000); + build_index(&root_dir, Some(millis)) + } } } -fn build_index(root_dir: &Option, monitor: bool) { +fn build_index(root_dir: &Option, interval: Option) { let dir_path = if let Some(path) = root_dir { path.clone() } else { @@ -171,9 +176,12 @@ fn build_index(root_dir: &Option, monitor: bool) { Ok(rwlock) => { println!("Success, took {:?}\n", duration); - if monitor { + if let Some(millis) = interval { let mut index = rwlock.write().unwrap(); loop { + let pause = Duration::from_millis(millis); + thread::sleep(pause); + match index.update() { Err(msg) => println!("Oops! {}", msg), Ok(diff) => { From a35c4a07189e20e40e53f2aed7009d6d56419191 Mon Sep 17 00:00:00 2001 From: Jerry Wong Date: Wed, 15 Jun 2022 00:53:01 +0800 Subject: [PATCH 08/23] Adding PDF rendering command (#2) --- ark-cli/.gitignore | 1 + ark-cli/Cargo.lock | 926 +++++++++++++++++++++++++++++++++++++++++++- ark-cli/Cargo.toml | 2 +- ark-cli/src/main.rs | 30 +- 4 files changed, 956 insertions(+), 3 deletions(-) create mode 100644 ark-cli/.gitignore diff --git a/ark-cli/.gitignore b/ark-cli/.gitignore new file mode 100644 index 00000000..1de56593 --- /dev/null +++ b/ark-cli/.gitignore @@ -0,0 +1 @@ +target \ No newline at end of file diff --git a/ark-cli/Cargo.lock b/ark-cli/Cargo.lock index a280377b..fb13c9f3 100644 --- a/ark-cli/Cargo.lock +++ b/ark-cli/Cargo.lock @@ -2,6 +2,18 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "adler32" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" + [[package]] name = "aho-corasick" version = "0.7.18" @@ -31,14 +43,21 @@ dependencies = [ [[package]] name = "arklib" version = "0.1.0" -source = "git+https://github.com/ARK-Builders/arklib?rev=e834f48#e834f48e88a01562034bca5b83e21dd490586d6d" dependencies = [ "anyhow", "canonical-path", "crc32fast", "env_logger 0.9.0", + "flate2", + "fs_extra", + "image", "lazy_static", + "libloading", "log", + "pdfium-render", + "tar", + "target-lexicon", + "ureq", "walkdir", ] @@ -59,24 +78,115 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bindgen" +version = "0.60.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "062dddbc1ba4aca46de6338e2bf87771414c335f7b2f2036e8f3e9befebf88e6" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "clap", + "env_logger 0.9.0", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "which", +] + +[[package]] +name = "bit_field" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bumpalo" +version = "3.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" + +[[package]] +name = "bytemuck" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + [[package]] name = "canonical-path" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e9e01327e6c86e92ec72b1c798d4a94810f147209bbe3ffab6a86954937a6f" +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chunked_transfer" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e" + +[[package]] +name = "clang-sys" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a050e2153c5be08febd6734e29298e844fdb0fa21aeddd63b4eb7baa106c69b" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "3.0.10" @@ -107,6 +217,32 @@ dependencies = [ "syn", ] +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "console_log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501a375961cef1a0d44767200e66e4a559283097e91d0730b1d75dfb2f8a1494" +dependencies = [ + "log", + "web-sys", +] + [[package]] name = "crc32fast" version = "1.3.0" @@ -116,6 +252,66 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "lazy_static", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +dependencies = [ + "cfg-if", + "lazy_static", +] + +[[package]] +name = "deflate" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c86f7e25f518f4b81808a2cf1c50996a61f5c2eb394b2393bd87f2a4780a432f" +dependencies = [ + "adler32", +] + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + [[package]] name = "env_logger" version = "0.8.4" @@ -142,6 +338,120 @@ dependencies = [ "termcolor", ] +[[package]] +name = "exr" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14cc0e06fb5f67e5d6beadf3a382fec9baca1aa751c6d5368fdeee7e5932c215" +dependencies = [ + "bit_field", + "deflate", + "flume", + "half", + "inflate", + "lebe", + "smallvec", + "threadpool", +] + +[[package]] +name = "filetime" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0408e2626025178a6a7f7ffc05a25bc47103229f19c113755de7bf63816290c" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "winapi", +] + +[[package]] +name = "flate2" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "flume" +version = "0.10.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843c03199d0c0ca54bc1ea90ac0d507274c28abcc4f691ae8b4eaa375087c76a" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "pin-project", + "spin 0.9.3", +] + +[[package]] +name = "form_urlencoded" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +dependencies = [ + "matches", + "percent-encoding", +] + +[[package]] +name = "fs_extra" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-sink" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" + +[[package]] +name = "getrandom" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gif" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3a7187e78088aead22ceedeee99779455b23fc231fe13ec443f99bb71694e5b" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + +[[package]] +name = "half" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + [[package]] name = "hashbrown" version = "0.11.2" @@ -178,6 +488,37 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "image" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28edd9d7bc256be2502e325ac0628bde30b7001b9b52e0abe31a1a9dc2701212" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "exr", + "gif", + "jpeg-decoder", + "num-iter", + "num-rational", + "num-traits", + "png", + "scoped_threadpool", + "tiff", +] + [[package]] name = "indexmap" version = "1.8.0" @@ -188,18 +529,76 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "inflate" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" +dependencies = [ + "adler32", +] + +[[package]] +name = "jpeg-decoder" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9478aa10f73e7528198d75109c8be5cd7d15fb530238040148d5f9a22d4c5b3b" +dependencies = [ + "rayon", +] + +[[package]] +name = "js-sys" +version = "0.3.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "lebe" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7efd1d698db0759e6ef11a7cd44407407399a910c774dd804c64c032da7826ff" + [[package]] name = "libc" version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +[[package]] +name = "libloading" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "lock_api" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.4.14" @@ -209,12 +608,118 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "matches" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" + [[package]] name = "memchr" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +dependencies = [ + "adler", +] + +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom", +] + +[[package]] +name = "nom" +version = "7.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" + [[package]] name = "os_str_bytes" version = "6.0.0" @@ -224,6 +729,72 @@ dependencies = [ "memchr", ] +[[package]] +name = "pdfium-render" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d72399eb4ce95d62e736511558420d079f65880e5f1fa175cb4567e738f3341" +dependencies = [ + "bindgen", + "bitflags", + "bytes", + "console_error_panic_hook", + "console_log", + "image", + "js-sys", + "lazy_static", + "libloading", + "log", + "utf16string", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + +[[package]] +name = "pin-project" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "png" +version = "0.17.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc38c0ad57efb786dd57b9864e5b18bae478c00c824dc55a38bbc9da95dde3ba" +dependencies = [ + "bitflags", + "crc32fast", + "deflate", + "miniz_oxide", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -266,6 +837,39 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rayon" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +dependencies = [ + "autocfg", + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "redox_syscall" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +dependencies = [ + "bitflags", +] + [[package]] name = "regex" version = "1.5.4" @@ -283,6 +887,39 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustls" +version = "0.20.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" +dependencies = [ + "log", + "ring", + "sct", + "webpki", +] + [[package]] name = "same-file" version = "1.0.6" @@ -292,6 +929,55 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scoped_threadpool" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "shlex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" + +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spin" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c530c2b0d0bf8b69304b39fe2001993e267461948b890cd037d8ad4293fa1a0d" +dependencies = [ + "lock_api", +] + [[package]] name = "strsim" version = "0.10.0" @@ -309,6 +995,23 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "tar" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" +dependencies = [ + "filetime", + "libc", + "xattr", +] + +[[package]] +name = "target-lexicon" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1" + [[package]] name = "termcolor" version = "1.1.2" @@ -324,12 +1027,106 @@ version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "tiff" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cfada0986f446a770eca461e8c6566cb879682f7d687c8348aa0c857bd52286" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "unicode-bidi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] +name = "unicode-normalization" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-xid" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "ureq" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9399fa2f927a3d327187cbd201480cee55bee6ac5d3c77dd27f0c6814cff16d5" +dependencies = [ + "base64", + "chunked_transfer", + "flate2", + "log", + "once_cell", + "rustls", + "url", + "webpki", + "webpki-roots", +] + +[[package]] +name = "url" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +dependencies = [ + "form_urlencoded", + "idna", + "matches", + "percent-encoding", +] + +[[package]] +name = "utf16string" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b62a1e85e12d5d712bf47a85f426b73d303e2d00a90de5f3004df3596e9d216" +dependencies = [ + "byteorder", +] + [[package]] name = "version_check" version = "0.9.4" @@ -347,6 +1144,124 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "wasm-bindgen" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" + +[[package]] +name = "web-sys" +version = "0.3.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d8de8415c823c8abd270ad483c6feeac771fad964890779f9a8cb24fbbc1bf" +dependencies = [ + "webpki", +] + +[[package]] +name = "weezl" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c97e489d8f836838d497091de568cf16b117486d529ec5579233521065bd5e4" + +[[package]] +name = "which" +version = "4.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a5a7e487e921cf220206864a94a89b6c6905bfc19f1057fa26a4cb360e5c1d2" +dependencies = [ + "either", + "lazy_static", + "libc", +] + [[package]] name = "winapi" version = "0.3.9" @@ -377,3 +1292,12 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "xattr" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" +dependencies = [ + "libc", +] diff --git a/ark-cli/Cargo.toml b/ark-cli/Cargo.toml index 19c1c460..67aff1e2 100644 --- a/ark-cli/Cargo.toml +++ b/ark-cli/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" name = "ark-cli" [dependencies] -arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "e834f48" } +arklib = { git = "https://github.com/nagato-chan/arklib" } clap = { version = "3.0.10", features = ["derive"] } env_logger = "0.8.4" diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs index dc091b42..32c76051 100644 --- a/ark-cli/src/main.rs +++ b/ark-cli/src/main.rs @@ -1,11 +1,12 @@ -use std::env::current_dir; use std::fs::{canonicalize, copy, create_dir_all, File}; use std::io::prelude::*; use std::io::BufReader; use std::path::{Path, PathBuf}; use std::thread; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; +use std::{env::current_dir, fs}; +use arklib::pdf::PDFQuailty; use clap::{Parser, Subcommand}; use home::home_dir; @@ -34,6 +35,12 @@ enum Command { root_dir: Option, interval: Option, }, + + Render { + #[clap(parse(from_os_str))] + path: Option, + quality: Option, + }, } const ARK_HOME: &str = ".ark"; @@ -155,6 +162,27 @@ fn main() { let millis = interval.unwrap_or(1000); build_index(&root_dir, Some(millis)) } + Command::Render { path, quality } => { + let filepath = path.to_owned().unwrap(); + let quality = match quality.to_owned().unwrap().as_str() { + "high" => PDFQuailty::High, + "medium" => PDFQuailty::Medium, + "low" => PDFQuailty::Low, + _ => panic!("unknown render option"), + }; + let buf = fs::read(&filepath).unwrap(); + let dest_path = filepath.with_file_name( + filepath + .file_stem() + .unwrap() + .to_str() + .unwrap() + .to_owned() + + ".png", + ); + let img = arklib::pdf::render_preview_page(buf.as_slice(), quality); + img.save(PathBuf::from(dest_path)).unwrap(); + } } } From 7f4220ef10a29fc979872fa9dc8009d2e991b10a Mon Sep 17 00:00:00 2001 From: Kirill Taran Date: Tue, 14 Jun 2022 19:55:35 +0300 Subject: [PATCH 09/23] Repo link and typo fixed --- ark-cli/Cargo.lock | 1 + ark-cli/Cargo.toml | 2 +- ark-cli/src/main.rs | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/ark-cli/Cargo.lock b/ark-cli/Cargo.lock index fb13c9f3..bd1b5701 100644 --- a/ark-cli/Cargo.lock +++ b/ark-cli/Cargo.lock @@ -43,6 +43,7 @@ dependencies = [ [[package]] name = "arklib" version = "0.1.0" +source = "git+https://github.com/ARK-Builders/arklib#e32c78112ad8b2e045755aea8b6e5a5087bee9eb" dependencies = [ "anyhow", "canonical-path", diff --git a/ark-cli/Cargo.toml b/ark-cli/Cargo.toml index 67aff1e2..c8610072 100644 --- a/ark-cli/Cargo.toml +++ b/ark-cli/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" name = "ark-cli" [dependencies] -arklib = { git = "https://github.com/nagato-chan/arklib" } +arklib = { git = "https://github.com/ARK-Builders/arklib" } clap = { version = "3.0.10", features = ["derive"] } env_logger = "0.8.4" diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs index 32c76051..0b6cbee7 100644 --- a/ark-cli/src/main.rs +++ b/ark-cli/src/main.rs @@ -6,7 +6,7 @@ use std::thread; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; use std::{env::current_dir, fs}; -use arklib::pdf::PDFQuailty; +use arklib::pdf::PDFQuality; use clap::{Parser, Subcommand}; use home::home_dir; @@ -165,9 +165,9 @@ fn main() { Command::Render { path, quality } => { let filepath = path.to_owned().unwrap(); let quality = match quality.to_owned().unwrap().as_str() { - "high" => PDFQuailty::High, - "medium" => PDFQuailty::Medium, - "low" => PDFQuailty::Low, + "high" => PDFQuality::High, + "medium" => PDFQuality::Medium, + "low" => PDFQuality::Low, _ => panic!("unknown render option"), }; let buf = fs::read(&filepath).unwrap(); From 206532bb9157b4c82c5f7dc9d3239c45633f372a Mon Sep 17 00:00:00 2001 From: Kirill Taran Date: Fri, 19 Aug 2022 15:58:22 +0300 Subject: [PATCH 10/23] Add subcommand for working with Link-to-Web resources --- ark-cli/Cargo.lock | 1948 +++++++++++++++++++++++++++++++++++++------ ark-cli/Cargo.toml | 6 +- ark-cli/src/main.rs | 54 +- 3 files changed, 1738 insertions(+), 270 deletions(-) diff --git a/ark-cli/Cargo.lock b/ark-cli/Cargo.lock index bd1b5701..dae89486 100644 --- a/ark-cli/Cargo.lock +++ b/ark-cli/Cargo.lock @@ -14,6 +14,18 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "opaque-debug", +] + [[package]] name = "aho-corasick" version = "0.7.18" @@ -25,9 +37,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.53" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0" +checksum = "508b352bb5c066aac251f6daf6b36eccd03e8a88e8081cd44959ea277a3af9a8" [[package]] name = "ark-cli" @@ -35,20 +47,21 @@ version = "0.1.0" dependencies = [ "arklib", "clap", - "env_logger 0.8.4", + "env_logger", "home", + "url", "walkdir", ] [[package]] name = "arklib" version = "0.1.0" -source = "git+https://github.com/ARK-Builders/arklib#e32c78112ad8b2e045755aea8b6e5a5087bee9eb" +source = "git+https://github.com/hhio618/arklib#f16127cd8736d855740eb9564665f38b0ca6d810" dependencies = [ "anyhow", "canonical-path", "crc32fast", - "env_logger 0.9.0", + "env_logger", "flate2", "fs_extra", "image", @@ -56,10 +69,17 @@ dependencies = [ "libloading", "log", "pdfium-render", + "reqwest", + "scraper", + "serde", + "serde_json", "tar", "target-lexicon", + "tokio", "ureq", + "url", "walkdir", + "zip", ] [[package]] @@ -75,9 +95,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" @@ -85,6 +105,12 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "base64ct" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a32fd6af2b5827bce66c29053ba0e7c42b9dcab01835835058558c10851a46b" + [[package]] name = "bindgen" version = "0.60.1" @@ -95,7 +121,7 @@ dependencies = [ "cexpr", "clang-sys", "clap", - "env_logger 0.9.0", + "env_logger", "lazy_static", "lazycell", "log", @@ -120,6 +146,15 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "block-buffer" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +dependencies = [ + "generic-array", +] + [[package]] name = "bumpalo" version = "3.10.0" @@ -128,9 +163,9 @@ checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" [[package]] name = "bytemuck" -version = "1.9.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc" +checksum = "a5377c8865e74a160d21f29c2d40669f53286db6eab59b88540cbb12ffc8b835" [[package]] name = "byteorder" @@ -140,9 +175,30 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.1.0" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" + +[[package]] +name = "bzip2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] [[package]] name = "canonical-path" @@ -155,6 +211,9 @@ name = "cc" version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +dependencies = [ + "jobserver", +] [[package]] name = "cexpr" @@ -177,6 +236,15 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e" +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + [[package]] name = "clang-sys" version = "1.3.3" @@ -190,16 +258,16 @@ dependencies = [ [[package]] name = "clap" -version = "3.0.10" +version = "3.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a30c3bf9ff12dfe5dae53f0a96e0febcd18420d1c0e7fad77796d9d5c4b5375" +checksum = "a3dbbb6653e7c55cc8595ad3e1f7be8f32aba4eb7ff7f0fd1163d4f3d137c0a9" dependencies = [ "atty", "bitflags", "clap_derive", + "clap_lex", "indexmap", - "lazy_static", - "os_str_bytes", + "once_cell", "strsim", "termcolor", "textwrap", @@ -207,9 +275,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "3.0.6" +version = "3.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "517358c28fcef6607bf6f76108e02afad7e82297d132a6b846dcc1fc3efcd153" +checksum = "9ba52acd3b0a5c33aeada5cdaa3267cdc7c594a98731d4268cdc1532f4264cb4" dependencies = [ "heck", "proc-macro-error", @@ -218,6 +286,15 @@ dependencies = [ "syn", ] +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -244,20 +321,57 @@ dependencies = [ "web-sys", ] +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "cpufeatures" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" -version = "1.3.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ "cfg-if", "crossbeam-utils", @@ -265,9 +379,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -276,26 +390,63 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.8" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" +checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", - "lazy_static", "memoffset", + "once_cell", "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" dependencies = [ "cfg-if", - "lazy_static", + "once_cell", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cssparser" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa 0.4.8", + "matches", + "phf 0.8.0", + "proc-macro2", + "quote", + "smallvec", + "syn", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e" +dependencies = [ + "quote", + "syn", ] [[package]] @@ -307,23 +458,64 @@ dependencies = [ "adler32", ] +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn", +] + +[[package]] +name = "digest" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "dtoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" + +[[package]] +name = "dtoa-short" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde03329ae10e79ede66c9ce4dc930aa8599043b0743008548680f25b91502d6" +dependencies = [ + "dtoa", +] + +[[package]] +name = "ego-tree" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a68a4904193147e0a8dec3314640e6db742afd5f6e634f428a6af230d9b3591" + [[package]] name = "either" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" [[package]] -name = "env_logger" -version = "0.8.4" +name = "encoding_rs" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", + "cfg-if", ] [[package]] @@ -355,16 +547,25 @@ dependencies = [ "threadpool", ] +[[package]] +name = "fastrand" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +dependencies = [ + "instant", +] + [[package]] name = "filetime" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0408e2626025178a6a7f7ffc05a25bc47103229f19c113755de7bf63816290c" +checksum = "e94a7bbaa59354bc20dd75b67f23e2797b4490e9d6928203fb105c79e448c86c" dependencies = [ "cfg-if", "libc", "redox_syscall", - "winapi", + "windows-sys", ] [[package]] @@ -379,17 +580,38 @@ dependencies = [ [[package]] name = "flume" -version = "0.10.12" +version = "0.10.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843c03199d0c0ca54bc1ea90ac0d507274c28abcc4f691ae8b4eaa375087c76a" +checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" dependencies = [ "futures-core", "futures-sink", "nanorand", "pin-project", - "spin 0.9.3", + "spin 0.9.4", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", ] +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.0.1" @@ -406,6 +628,25 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", +] + [[package]] name = "futures-core" version = "0.3.21" @@ -418,24 +659,81 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "wasm-bindgen", ] [[package]] name = "gif" -version = "0.11.3" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a7187e78088aead22ceedeee99779455b23fc231fe13ec443f99bb71694e5b" +checksum = "3edd93c6756b4dfaf2709eafcc345ba2636565295c198a9cfbf75fa5e3e00b06" dependencies = [ "color_quant", "weezl", @@ -447,6 +745,25 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +[[package]] +name = "h2" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "half" version = "1.8.2" @@ -455,9 +772,9 @@ checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "heck" @@ -474,6 +791,15 @@ dependencies = [ "libc", ] +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "home" version = "0.5.3" @@ -484,50 +810,134 @@ dependencies = [ ] [[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "idna" -version = "0.2.3" +name = "html5ever" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "image" -version = "0.24.2" +name = "http" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28edd9d7bc256be2502e325ac0628bde30b7001b9b52e0abe31a1a9dc2701212" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "exr", - "gif", - "jpeg-decoder", - "num-iter", - "num-rational", - "num-traits", - "png", - "scoped_threadpool", - "tiff", + "bytes", + "fnv", + "itoa 1.0.3", ] [[package]] -name = "indexmap" -version = "1.8.0" +name = "http-body" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ - "autocfg", - "hashbrown", + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "0.14.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa 1.0.3", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "image" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e30ca2ecf7666107ff827a8e481de6a132a9b687ed3bb20bb1c144a36c00964" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "exr", + "gif", + "jpeg-decoder", + "num-rational", + "num-traits", + "png", + "scoped_threadpool", + "tiff", +] + +[[package]] +name = "indexmap" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +dependencies = [ + "autocfg", + "hashbrown", ] [[package]] @@ -539,6 +949,60 @@ dependencies = [ "adler32", ] +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ipnet" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" + +[[package]] +name = "iter_tools" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "531cafdc99b3b3252bb32f5620e61d56b19415efc19900b12d1b2e7483854897" +dependencies = [ + "itertools", +] + +[[package]] +name = "itertools" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" + +[[package]] +name = "jobserver" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +dependencies = [ + "libc", +] + [[package]] name = "jpeg-decoder" version = "0.2.6" @@ -550,9 +1014,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.57" +version = "0.3.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" +checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" dependencies = [ "wasm-bindgen", ] @@ -577,9 +1041,9 @@ checksum = "7efd1d698db0759e6ef11a7cd44407407399a910c774dd804c64c032da7826ff" [[package]] name = "libc" -version = "0.2.112" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +checksum = "64de3cc433455c14174d42e554d4027ee631c4d046d43e3ecc6efc4636cdc7a7" [[package]] name = "libloading" @@ -593,33 +1057,60 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" dependencies = [ + "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "markup5ever" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" +dependencies = [ + "log", + "phf 0.10.1", + "phf_codegen 0.10.0", + "string_cache", + "string_cache_codegen", + "tendril", +] + [[package]] name = "matches" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +[[package]] +name = "maybe-owned" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" + [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" @@ -630,6 +1121,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -645,15 +1142,57 @@ dependencies = [ "adler", ] +[[package]] +name = "mio" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys", +] + [[package]] name = "nanorand" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" dependencies = [ - "getrandom", + "getrandom 0.2.7", +] + +[[package]] +name = "native-tls" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + [[package]] name = "nom" version = "7.1.1" @@ -674,22 +1213,11 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-iter" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-rational" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ "autocfg", "num-integer", @@ -715,26 +1243,129 @@ dependencies = [ "libc", ] +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + [[package]] name = "once_cell" -version = "1.12.0" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "openssl" +version = "0.10.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" +checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] [[package]] name = "os_str_bytes" -version = "6.0.0" +version = "6.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "648001efe5d5c0102d8cea768e348da85d90af8ba91f0bea908f157951493cd4" + +[[package]] +name = "parking_lot" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ - "memchr", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "password-hash" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d791538a6dcc1e7cb7fe6f6b58aca40e7f79403c45b2bc274008b5e647af1d8" +dependencies = [ + "base64ct", + "rand_core 0.6.3", + "subtle", +] + +[[package]] +name = "pbkdf2" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271779f35b581956db91a3e55737327a03aa051e90b1c47aeb189508533adfd7" +dependencies = [ + "digest", + "hmac", + "password-hash", + "sha2", ] [[package]] name = "pdfium-render" -version = "0.7.1" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d72399eb4ce95d62e736511558420d079f65880e5f1fa175cb4567e738f3341" +checksum = "d23ff46f6e747af4762874b660f88a79356e9e38731f1f5a2f5d73d8ff2bbb0a" dependencies = [ "bindgen", "bitflags", @@ -742,11 +1373,14 @@ dependencies = [ "console_error_panic_hook", "console_log", "image", + "iter_tools", "js-sys", "lazy_static", "libloading", "log", + "maybe-owned", "utf16string", + "vecmath", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -765,94 +1399,309 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] -name = "pin-project" -version = "1.0.10" +name = "phf" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "pin-project-internal", + "phf_macros", + "phf_shared 0.8.0", + "proc-macro-hack", ] [[package]] -name = "pin-project-internal" -version = "1.0.10" +name = "phf" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" dependencies = [ - "proc-macro2", - "quote", - "syn", + "phf_shared 0.10.0", ] [[package]] -name = "png" -version = "0.17.5" +name = "phf_codegen" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc38c0ad57efb786dd57b9864e5b18bae478c00c824dc55a38bbc9da95dde3ba" +checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" dependencies = [ - "bitflags", - "crc32fast", - "deflate", - "miniz_oxide", + "phf_generator 0.8.0", + "phf_shared 0.8.0", ] [[package]] -name = "proc-macro-error" -version = "1.0.4" +name = "phf_codegen" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", + "phf_generator 0.10.0", + "phf_shared 0.10.0", ] [[package]] -name = "proc-macro-error-attr" -version = "1.0.4" +name = "phf_generator" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" dependencies = [ - "proc-macro2", - "quote", - "version_check", + "phf_shared 0.8.0", + "rand 0.7.3", ] [[package]] -name = "proc-macro2" -version = "1.0.36" +name = "phf_generator" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" dependencies = [ - "unicode-xid", + "phf_shared 0.10.0", + "rand 0.8.5", ] [[package]] -name = "quote" -version = "1.0.14" +name = "phf_macros" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" +checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", + "proc-macro-hack", "proc-macro2", + "quote", + "syn", ] [[package]] -name = "rayon" -version = "1.5.3" +name = "phf_shared" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" dependencies = [ - "autocfg", - "crossbeam-deque", - "either", - "rayon-core", + "siphasher", ] [[package]] -name = "rayon-core" -version = "1.9.3" +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78203e83c48cffbe01e4a2d35d566ca4de445d79a85372fc64e378bfc812a260" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "710faf75e1b33345361201d36d04e98ac1ed8909151a017ed384700836104c74" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "piston-float" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad78bf43dcf80e8f950c92b84f938a0fc7590b7f6866fbcbeca781609c115590" + +[[package]] +name = "pkg-config" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" + +[[package]] +name = "png" +version = "0.17.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc38c0ad57efb786dd57b9864e5b18bae478c00c824dc55a38bbc9da95dde3ba" +dependencies = [ + "bitflags", + "crc32fast", + "deflate", + "miniz_oxide", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + +[[package]] +name = "proc-macro2" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", + "rand_pcg", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.3", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.3", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom 0.2.7", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rayon" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +dependencies = [ + "autocfg", + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" dependencies = [ @@ -864,119 +1713,396 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.13" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "reqwest" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "lazy_static", + "log", + "mime", + "native-tls", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustls" +version = "0.20.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" +dependencies = [ + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "ryu" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +dependencies = [ + "lazy_static", + "windows-sys", +] + +[[package]] +name = "scoped_threadpool" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "scraper" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5684396b456f3eb69ceeb34d1b5cb1a2f6acf7ca4452131efa3ba0ee2c2d0a70" +dependencies = [ + "cssparser", + "ego-tree", + "getopts", + "html5ever", + "matches", + "selectors", + "smallvec", + "tendril", +] + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "security-framework" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "selectors" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" dependencies = [ "bitflags", + "cssparser", + "derive_more", + "fxhash", + "log", + "matches", + "phf 0.8.0", + "phf_codegen 0.8.0", + "precomputed-hash", + "servo_arc", + "smallvec", + "thin-slice", +] + +[[package]] +name = "semver" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711" + +[[package]] +name = "serde" +version = "1.0.143" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.143" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" +dependencies = [ + "itoa 1.0.3", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa 1.0.3", + "ryu", + "serde", +] + +[[package]] +name = "servo_arc" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432" +dependencies = [ + "nodrop", + "stable_deref_trait", +] + +[[package]] +name = "sha1" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77f4e7f65455545c2153c1253d25056825e77ee2533f0e41deb65a93a34852f" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", ] [[package]] -name = "regex" -version = "1.5.4" +name = "sha2" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", + "cfg-if", + "cpufeatures", + "digest", ] [[package]] -name = "regex-syntax" -version = "0.6.25" +name = "shlex" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" [[package]] -name = "ring" -version = "0.16.20" +name = "signal-hook-registry" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" dependencies = [ - "cc", "libc", - "once_cell", - "spin 0.5.2", - "untrusted", - "web-sys", - "winapi", ] [[package]] -name = "rustc-hash" -version = "1.1.0" +name = "siphasher" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" [[package]] -name = "rustls" -version = "0.20.6" +name = "slab" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" dependencies = [ - "log", - "ring", - "sct", - "webpki", + "autocfg", ] [[package]] -name = "same-file" -version = "1.0.6" +name = "smallvec" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] -name = "scoped_threadpool" -version = "0.1.9" +name = "socket2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +dependencies = [ + "libc", + "winapi", +] [[package]] -name = "scopeguard" -version = "1.1.0" +name = "spin" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] -name = "sct" -version = "0.7.0" +name = "spin" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" dependencies = [ - "ring", - "untrusted", + "lock_api", ] [[package]] -name = "shlex" -version = "1.1.0" +name = "stable_deref_trait" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] -name = "smallvec" -version = "1.8.0" +name = "string_cache" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] [[package]] -name = "spin" +name = "string_cache_codegen" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "spin" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c530c2b0d0bf8b69304b39fe2001993e267461948b890cd037d8ad4293fa1a0d" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" dependencies = [ - "lock_api", + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", ] [[package]] @@ -985,15 +2111,21 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + [[package]] name = "syn" -version = "1.0.85" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] @@ -1013,20 +2145,51 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1" +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + [[package]] name = "termcolor" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] [[package]] name = "textwrap" -version = "0.14.2" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" + +[[package]] +name = "thin-slice" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" +checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" [[package]] name = "threadpool" @@ -1039,15 +2202,33 @@ dependencies = [ [[package]] name = "tiff" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cfada0986f446a770eca461e8c6566cb879682f7d687c8348aa0c857bd52286" +checksum = "7259662e32d1e219321eb309d5f9d898b779769d81b76e762c07c8e5d38fcb65" dependencies = [ "flate2", "jpeg-decoder", "weezl", ] +[[package]] +name = "time" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db76ff9fa4b1458b3c7f077f3ff9887394058460d21e634355b273aaf11eea45" +dependencies = [ + "itoa 1.0.3", + "libc", + "num_threads", + "time-macros", +] + +[[package]] +name = "time-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" + [[package]] name = "tinyvec" version = "1.6.0" @@ -1063,26 +2244,126 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +[[package]] +name = "tokio" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "once_cell", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + [[package]] name = "unicode-bidi" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +[[package]] +name = "unicode-ident" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" + [[package]] name = "unicode-normalization" -version = "0.1.19" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" dependencies = [ "tinyvec", ] [[package]] -name = "unicode-xid" -version = "0.2.2" +name = "unicode-width" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" [[package]] name = "untrusted" @@ -1092,9 +2373,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "ureq" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9399fa2f927a3d327187cbd201480cee55bee6ac5d3c77dd27f0c6814cff16d5" +checksum = "b97acb4c28a254fd7a4aeec976c46a7fa404eac4d7c134b30c75144846d7cb8f" dependencies = [ "base64", "chunked_transfer", @@ -1117,8 +2398,15 @@ dependencies = [ "idna", "matches", "percent-encoding", + "serde", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "utf16string" version = "0.2.0" @@ -1128,6 +2416,21 @@ dependencies = [ "byteorder", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "vecmath" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ae1e0d85bca567dee1dcf87fb1ca2e792792f66f87dced8381f99cd91156a" +dependencies = [ + "piston-float", +] + [[package]] name = "version_check" version = "0.9.4" @@ -1145,17 +2448,33 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" +checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1163,13 +2482,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" +checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" dependencies = [ "bumpalo", - "lazy_static", "log", + "once_cell", "proc-macro2", "quote", "syn", @@ -1178,9 +2497,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.30" +version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" +checksum = "fa76fb221a1f8acddf5b54ace85912606980ad661ac7a503b4570ffd3a624dad" dependencies = [ "cfg-if", "js-sys", @@ -1190,9 +2509,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" +checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1200,9 +2519,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" +checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" dependencies = [ "proc-macro2", "quote", @@ -1213,15 +2532,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" +checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" [[package]] name = "web-sys" -version = "0.3.57" +version = "0.3.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" +checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1" dependencies = [ "js-sys", "wasm-bindgen", @@ -1239,24 +2558,24 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.22.3" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d8de8415c823c8abd270ad483c6feeac771fad964890779f9a8cb24fbbc1bf" +checksum = "f1c760f0d366a6c24a02ed7816e23e691f5d92291f94d15e836006fd11b04daf" dependencies = [ "webpki", ] [[package]] name = "weezl" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c97e489d8f836838d497091de568cf16b117486d529ec5579233521065bd5e4" +checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" [[package]] name = "which" -version = "4.2.4" +version = "4.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a5a7e487e921cf220206864a94a89b6c6905bfc19f1057fa26a4cb360e5c1d2" +checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae" dependencies = [ "either", "lazy_static", @@ -1294,6 +2613,58 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + [[package]] name = "xattr" version = "0.2.3" @@ -1302,3 +2673,52 @@ checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" dependencies = [ "libc", ] + +[[package]] +name = "zip" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf225bcf73bb52cbb496e70475c7bd7a3f769df699c0020f6c7bd9a96dcf0b8d" +dependencies = [ + "aes", + "byteorder", + "bzip2", + "constant_time_eq", + "crc32fast", + "crossbeam-utils", + "flate2", + "hmac", + "pbkdf2", + "sha1", + "time", + "zstd", +] + +[[package]] +name = "zstd" +version = "0.10.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4a6bd64f22b5e3e94b4e238669ff9f10815c27a5180108b849d24174a83847" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "4.1.6+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b61c51bb270702d6167b8ce67340d2754b088d0c091b06e593aa772c3ee9bb" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "1.6.3+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc49afa5c8d634e75761feda8c592051e7eeb4683ba827211eb0d731d3402ea8" +dependencies = [ + "cc", + "libc", +] diff --git a/ark-cli/Cargo.toml b/ark-cli/Cargo.toml index c8610072..1505cc9c 100644 --- a/ark-cli/Cargo.toml +++ b/ark-cli/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" name = "ark-cli" [dependencies] -arklib = { git = "https://github.com/ARK-Builders/arklib" } - +arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "b743977" } clap = { version = "3.0.10", features = ["derive"] } -env_logger = "0.8.4" +env_logger = "0.9.0" walkdir = "2.3.2" home = "0.5.3" +url = { version = "2.2.2", features = ["serde"] } diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs index 0b6cbee7..3d033ee9 100644 --- a/ark-cli/src/main.rs +++ b/ark-cli/src/main.rs @@ -1,14 +1,15 @@ +use std::env::current_dir; use std::fs::{canonicalize, copy, create_dir_all, File}; use std::io::prelude::*; use std::io::BufReader; use std::path::{Path, PathBuf}; use std::thread; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; -use std::{env::current_dir, fs}; use arklib::pdf::PDFQuality; use clap::{Parser, Subcommand}; use home::home_dir; +use url::Url; #[derive(Parser, Debug)] #[clap(name = "ark-cli")] @@ -41,6 +42,23 @@ enum Command { path: Option, quality: Option, }, + #[clap(subcommand)] + Link(Link), +} + +#[derive(Subcommand, Debug)] +enum Link { + Create { + #[clap(parse(from_os_str))] + path: Option, + title: Option, + desc: Option, + url: Option, + }, + Load { + #[clap(parse(from_os_str))] + file_path: Option, + }, } const ARK_HOME: &str = ".ark"; @@ -170,7 +188,7 @@ fn main() { "low" => PDFQuality::Low, _ => panic!("unknown render option"), }; - let buf = fs::read(&filepath).unwrap(); + let buf = File::open(&filepath).unwrap(); let dest_path = filepath.with_file_name( filepath .file_stem() @@ -180,9 +198,39 @@ fn main() { .to_owned() + ".png", ); - let img = arklib::pdf::render_preview_page(buf.as_slice(), quality); + let img = arklib::pdf::render_preview_page(buf, quality); img.save(PathBuf::from(dest_path)).unwrap(); } + Command::Link(link) => match &link { + Link::Create { + title, + desc, + url, + path, + } => { + let _url = Url::parse(url.as_deref().unwrap()); + let mut _link: arklib::link::Link = arklib::link::Link::new( + title.to_owned().unwrap(), + desc.to_owned().unwrap(), + _url.unwrap(), + ); + let file_path = Path::join( + path.to_owned().unwrap().as_path(), + format!("{}.link", _link.format_name()), + ); + _link.write_to_path_sync(file_path.clone(), true); + println!( + "Link saved successfully: {:?}", + file_path.clone().display() + ) + } + Link::Load { file_path } => { + let link = arklib::link::Link::load_json( + file_path.to_owned().unwrap().as_path(), + ); + println!("Link data:\n{}", link.unwrap()); + } + }, } } From 749da4b25c88989ba874911da1452ebd2f80c873 Mon Sep 17 00:00:00 2001 From: Kirill Taran Date: Thu, 24 Nov 2022 02:24:27 +0300 Subject: [PATCH 11/23] #15: Persisted index and metadata storage (#8) --- ark-cli/Cargo.lock | 14 ++- ark-cli/Cargo.toml | 2 +- ark-cli/src/main.rs | 213 +++++++++++++++++++++++++++++--------------- 3 files changed, 153 insertions(+), 76 deletions(-) diff --git a/ark-cli/Cargo.lock b/ark-cli/Cargo.lock index dae89486..46f1746e 100644 --- a/ark-cli/Cargo.lock +++ b/ark-cli/Cargo.lock @@ -56,7 +56,7 @@ dependencies = [ [[package]] name = "arklib" version = "0.1.0" -source = "git+https://github.com/hhio618/arklib#f16127cd8736d855740eb9564665f38b0ca6d810" +source = "git+https://github.com/ARK-Builders/arklib?rev=fea125e#fea125e8330243522183c187a467dc762dec1fb7" dependencies = [ "anyhow", "canonical-path", @@ -65,9 +65,11 @@ dependencies = [ "flate2", "fs_extra", "image", + "itertools", "lazy_static", "libloading", "log", + "pathdiff", "pdfium-render", "reqwest", "scraper", @@ -975,9 +977,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] @@ -1349,6 +1351,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + [[package]] name = "pbkdf2" version = "0.10.1" diff --git a/ark-cli/Cargo.toml b/ark-cli/Cargo.toml index 1505cc9c..7ae40b84 100644 --- a/ark-cli/Cargo.toml +++ b/ark-cli/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" name = "ark-cli" [dependencies] -arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "b743977" } +arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "fea125e" } clap = { version = "3.0.10", features = ["derive"] } env_logger = "0.9.0" walkdir = "2.3.2" diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs index 3d033ee9..747147c0 100644 --- a/ark-cli/src/main.rs +++ b/ark-cli/src/main.rs @@ -6,6 +6,8 @@ use std::path::{Path, PathBuf}; use std::thread; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; +use arklib::id::ResourceId; +use arklib::index::ResourceIndex; use arklib::pdf::PDFQuality; use clap::{Parser, Subcommand}; use home::home_dir; @@ -42,6 +44,7 @@ enum Command { path: Option, quality: Option, }, + #[clap(subcommand)] Link(Link), } @@ -50,14 +53,21 @@ enum Command { enum Link { Create { #[clap(parse(from_os_str))] - path: Option, + root_dir: Option, + + url: Option, title: Option, desc: Option, - url: Option, }, + Load { + #[clap(parse(from_os_str))] + root_dir: Option, + #[clap(parse(from_os_str))] file_path: Option, + + id: Option, }, } @@ -86,51 +96,11 @@ fn main() { } println!("Preparing backup:"); - let roots = if let Some(path) = roots_cfg { - println!( - "\tRoots config provided explicitly:\n\t\t{}", - path.display() - ); - let config = File::open(&path).expect("File doesn't exist!"); - - parse_roots(config) - } else { - let roots_cfg = home_roots_cfg(); - - if let Ok(config) = File::open(&roots_cfg) { - println!( - "\tRoots config was found automatically:\n\t\t{}", - roots_cfg.display() - ); - - parse_roots(config) - } else { - println!("\tRoots config wasn't found."); - - println!("Looking for a folder containing tag storage:"); - let path = canonicalize( - current_dir().expect("Can't open current directory!"), - ) - .expect("Couldn't canonicalize working directory!"); - - let result = path.ancestors().find(|path| { - println!("\t{}", path.display()); - tag_storage_exists(path) - }); - - if let Some(root) = result { - println!("Root folder found:\n\t{}", root.display()); - vec![root.to_path_buf()] - } else { - println!("Root folder wasn't found."); - vec![] - } - } - }; + let roots = discover_roots(roots_cfg); let (valid, invalid): (Vec, Vec) = roots .into_iter() - .partition(|root| tag_storage_exists(&root)); + .partition(|root| storages_exists(&root)); if !invalid.is_empty() { println!("These folders don't contain tag storages:"); @@ -164,7 +134,7 @@ fn main() { println!("\tRoot {}", root.display()); let storage_backup = backup_dir.join(&i.to_string()); let result = copy( - root.join(&arklib::TAG_STORAGE_FILENAME), + root.join(&arklib::STORAGES_FOLDER), storage_backup, ); if let Err(e) = result { @@ -175,11 +145,13 @@ fn main() { println!("Backup created:\n\t{}", backup_dir.display()); } - Command::Collisions { root_dir } => build_index(&root_dir, None), + Command::Collisions { root_dir } => monitor_index(&root_dir, None), + Command::Monitor { root_dir, interval } => { let millis = interval.unwrap_or(1000); - build_index(&root_dir, Some(millis)) + monitor_index(&root_dir, Some(millis)) } + Command::Render { path, quality } => { let filepath = path.to_owned().unwrap(); let quality = match quality.to_owned().unwrap().as_str() { @@ -201,56 +173,149 @@ fn main() { let img = arklib::pdf::render_preview_page(buf, quality); img.save(PathBuf::from(dest_path)).unwrap(); } + Command::Link(link) => match &link { Link::Create { + root_dir, + url, title, desc, - url, - path, } => { - let _url = Url::parse(url.as_deref().unwrap()); - let mut _link: arklib::link::Link = arklib::link::Link::new( + let root = provide_root(root_dir); + + let url = Url::parse(url.as_deref().unwrap()); + let mut link: arklib::link::Link = arklib::link::Link::new( + url.unwrap(), title.to_owned().unwrap(), - desc.to_owned().unwrap(), - _url.unwrap(), + desc.to_owned(), ); - let file_path = Path::join( - path.to_owned().unwrap().as_path(), - format!("{}.link", _link.format_name()), + + let timestamp = timestamp().as_secs(); + let path = Path::join( + &root, + format!("{}.link", ×tamp.to_string()), ); - _link.write_to_path_sync(file_path.clone(), true); - println!( - "Link saved successfully: {:?}", - file_path.clone().display() - ) + link.write_to_path_sync(root, path.clone(), true) + .unwrap(); + println!("Link saved successfully: {:?}", path.display()) } - Link::Load { file_path } => { - let link = arklib::link::Link::load_json( - file_path.to_owned().unwrap().as_path(), - ); - println!("Link data:\n{}", link.unwrap()); + + Link::Load { + root_dir, + file_path, + id, + } => { + let root = provide_root(root_dir); + + let path_from_index = id.map(|id| { + let index = provide_index(&root); + index.id2path[&id].as_path().to_path_buf() + }); + let path_from_user = file_path; + + let path = match (path_from_user, path_from_index) { + (Some(path), Some(path2)) => { + if path.canonicalize().unwrap() != path2 { + println!("Path {:?} was requested.", path); + println!( + "But id {} maps to path {:?}", + id.unwrap(), + path2 + ); + panic!() + } else { + path.to_path_buf() + } + } + (Some(path), None) => path.to_path_buf(), + (None, Some(path)) => path, + (None, None) => { + println!("Provide a path or id for request."); + panic!() + } + }; + + let link = arklib::link::Link::load(root, path); + println!("Link data:\n{:?}", link.unwrap()); } }, } } -fn build_index(root_dir: &Option, interval: Option) { - let dir_path = if let Some(path) = root_dir { +fn discover_roots(roots_cfg: &Option) -> Vec { + if let Some(path) = roots_cfg { + println!( + "\tRoots config provided explicitly:\n\t\t{}", + path.display() + ); + let config = File::open(&path).expect("File doesn't exist!"); + + parse_roots(config) + } else { + let roots_cfg = home_roots_cfg(); + + if let Ok(config) = File::open(&roots_cfg) { + println!( + "\tRoots config was found automatically:\n\t\t{}", + roots_cfg.display() + ); + + parse_roots(config) + } else { + println!("\tRoots config wasn't found."); + + println!("Looking for a folder containing tag storage:"); + let path = canonicalize( + current_dir().expect("Can't open current directory!"), + ) + .expect("Couldn't canonicalize working directory!"); + + let result = path.ancestors().find(|path| { + println!("\t{}", path.display()); + storages_exists(path) + }); + + if let Some(root) = result { + println!("Root folder found:\n\t{}", root.display()); + vec![root.to_path_buf()] + } else { + println!("Root folder wasn't found."); + vec![] + } + } + } +} + +fn provide_root(root_dir: &Option) -> PathBuf { + if let Some(path) = root_dir { path.clone() } else { current_dir() .expect("Can't open current directory!") .clone() - }; + } +} + +// Read-only structure +fn provide_index(root_dir: &PathBuf) -> ResourceIndex { + let rwlock = + arklib::provide_index(root_dir).expect("Failed to retrieve index"); + let index = &*rwlock.read().unwrap(); + index.clone() +} + +fn monitor_index(root_dir: &Option, interval: Option) { + let dir_path = provide_root(root_dir); println!("Building index of folder {}", dir_path.display()); let start = Instant::now(); + let dir_path = provide_root(root_dir); let result = arklib::provide_index(dir_path); let duration = start.elapsed(); match result { Ok(rwlock) => { - println!("Success, took {:?}\n", duration); + println!("Build succeeded in {:?}\n", duration); if let Some(millis) = interval { let mut index = rwlock.write().unwrap(); @@ -258,9 +323,13 @@ fn build_index(root_dir: &Option, interval: Option) { let pause = Duration::from_millis(millis); thread::sleep(pause); + let start = Instant::now(); match index.update() { Err(msg) => println!("Oops! {}", msg), Ok(diff) => { + let duration = start.elapsed(); + println!("Updating succeeded in {:?}\n", duration); + if !diff.deleted.is_empty() { println!("Deleted: {:?}", diff.deleted); } @@ -291,8 +360,8 @@ fn home_roots_cfg() -> PathBuf { .join(&ROOTS_CFG_FILENAME); } -fn tag_storage_exists(path: &Path) -> bool { - return File::open(path.join(&arklib::TAG_STORAGE_FILENAME)).is_ok(); +fn storages_exists(path: &Path) -> bool { + return File::open(path.join(&arklib::STORAGES_FOLDER)).is_ok(); } fn parse_roots(config: File) -> Vec { From 2b26a64065648899e73e67cf7ea31881e0a8d2fd Mon Sep 17 00:00:00 2001 From: Kirill Taran Date: Tue, 17 Jan 2023 22:03:08 +0300 Subject: [PATCH 12/23] Updating backup tool --- ark-cli/Cargo.lock | 1 + ark-cli/Cargo.toml | 1 + ark-cli/src/main.rs | 44 +++++++++++++++++++++++--------------------- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/ark-cli/Cargo.lock b/ark-cli/Cargo.lock index 46f1746e..df6e67bc 100644 --- a/ark-cli/Cargo.lock +++ b/ark-cli/Cargo.lock @@ -48,6 +48,7 @@ dependencies = [ "arklib", "clap", "env_logger", + "fs_extra", "home", "url", "walkdir", diff --git a/ark-cli/Cargo.toml b/ark-cli/Cargo.toml index 7ae40b84..9fb63e8a 100644 --- a/ark-cli/Cargo.toml +++ b/ark-cli/Cargo.toml @@ -10,6 +10,7 @@ name = "ark-cli" arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "fea125e" } clap = { version = "3.0.10", features = ["derive"] } env_logger = "0.9.0" +fs_extra = "1.2.0" walkdir = "2.3.2" home = "0.5.3" url = { version = "2.2.2", features = ["serde"] } diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs index 747147c0..f8b0b05f 100644 --- a/ark-cli/src/main.rs +++ b/ark-cli/src/main.rs @@ -1,5 +1,5 @@ use std::env::current_dir; -use std::fs::{canonicalize, copy, create_dir_all, File}; +use std::fs::{canonicalize, create_dir_all, metadata, File}; use std::io::prelude::*; use std::io::BufReader; use std::path::{Path, PathBuf}; @@ -10,6 +10,7 @@ use arklib::id::ResourceId; use arklib::index::ResourceIndex; use arklib::pdf::PDFQuality; use clap::{Parser, Subcommand}; +use fs_extra::dir::{self, CopyOptions}; use home::home_dir; use url::Url; @@ -71,10 +72,9 @@ enum Link { }, } -const ARK_HOME: &str = ".ark"; - +const ARK_CONFIG: &str = ".config/ark"; +const ARK_BACKUPS_PATH: &str = ".ark-backups"; const ROOTS_CFG_FILENAME: &str = "roots"; -const HOME_BACKUPS_DIRNAME: &str = "backups"; fn main() { env_logger::init(); @@ -86,8 +86,7 @@ fn main() { let timestamp = timestamp().as_secs(); let backup_dir = home_dir() .expect("Couldn't retrieve home directory!") - .join(&ARK_HOME) - .join(&HOME_BACKUPS_DIRNAME) + .join(&ARK_BACKUPS_PATH) .join(×tamp.to_string()); if backup_dir.is_dir() { @@ -103,7 +102,7 @@ fn main() { .partition(|root| storages_exists(&root)); if !invalid.is_empty() { - println!("These folders don't contain tag storages:"); + println!("These folders don't contain any storages:"); invalid .into_iter() .for_each(|root| println!("\t{}", root.display())); @@ -133,12 +132,19 @@ fn main() { .for_each(|(i, root)| { println!("\tRoot {}", root.display()); let storage_backup = backup_dir.join(&i.to_string()); - let result = copy( + + let mut options = CopyOptions::new(); + options.overwrite = true; + options.copy_inside = true; + + let result = dir::copy( root.join(&arklib::STORAGES_FOLDER), storage_backup, + &options, ); + if let Err(e) = result { - println!("\t\tFailed to copy tag storage!\n\t\t{}", e); + println!("\t\tFailed to copy storages!\n\t\t{}", e); } }); @@ -252,12 +258,10 @@ fn discover_roots(roots_cfg: &Option) -> Vec { parse_roots(config) } else { - let roots_cfg = home_roots_cfg(); - - if let Ok(config) = File::open(&roots_cfg) { + if let Ok(config) = File::open(&ARK_CONFIG) { println!( "\tRoots config was found automatically:\n\t\t{}", - roots_cfg.display() + &ARK_CONFIG ); parse_roots(config) @@ -353,15 +357,13 @@ fn monitor_index(root_dir: &Option, interval: Option) { } } -fn home_roots_cfg() -> PathBuf { - return home_dir() - .expect("Couldn't retrieve home directory!") - .join(&ARK_HOME) - .join(&ROOTS_CFG_FILENAME); -} - fn storages_exists(path: &Path) -> bool { - return File::open(path.join(&arklib::STORAGES_FOLDER)).is_ok(); + let meta = metadata(path.join(&arklib::STORAGES_FOLDER)); + if let Ok(meta) = meta { + return meta.is_dir(); + } + + false } fn parse_roots(config: File) -> Vec { From 812cd04f2f114f88dc178b3e606aac652bf9758d Mon Sep 17 00:00:00 2001 From: Mitchell Berry Date: Thu, 21 Sep 2023 03:11:28 +0800 Subject: [PATCH 13/23] Add README.md --- ark-cli/README.md | 111 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 ark-cli/README.md diff --git a/ark-cli/README.md b/ark-cli/README.md new file mode 100644 index 00000000..da191e1e --- /dev/null +++ b/ark-cli/README.md @@ -0,0 +1,111 @@ +# Ark-CLI + +### Installation + +To compile you will need openssl libraries and headers: + +```shell +# macOS (Homebrew) +$ brew install openssl@3 + +# macOS (MacPorts) +$ sudo port install openssl + +# macOS (pkgsrc) +$ sudo pkgin install openssl + +# Arch Linux +$ sudo pacman -S pkg-config openssl + +# Debian and Ubuntu +$ sudo apt-get install pkg-config libssl-dev + +# Fedora +$ sudo dnf install pkg-config perl-FindBin openssl-devel + +# Alpine Linux +$ apk add pkgconfig openssl-dev +``` + +### Usage + +```shell +ark-cli + +OPTIONS: + -h, --help Print help information + +SUBCOMMANDS: + backup + collisions + help Print this message or the help of the given subcommand(s) + link + monitor + render + +``` + +#### Backup +```shell +USAGE: + ark-cli backup [ROOTS_CFG] + +ARGS: + + +OPTIONS: + -h, --help Print help information +``` + +#### Collisions +```shell +USAGE: + ark-cli collisions [ROOT_DIR] + +ARGS: + + +OPTIONS: + -h, --help Print help information +``` + +#### Link +```shell +USAGE: + ark-cli link + +OPTIONS: + -h, --help Print help information + +SUBCOMMANDS: + create + help Print this message or the help of the given subcommand(s) + load +``` + +#### Monitor +```shell +USAGE: + ark-cli monitor [ARGS] + +ARGS: + + + +OPTIONS: + -h, --help Print help information +``` + +#### Render +```shell +USAGE: + ark-cli render [ARGS] + +ARGS: + + + +OPTIONS: + -h, --help Print help information + +``` \ No newline at end of file From 3a140aa6a7309d0e98fe32c5a0c2bf67a8347a48 Mon Sep 17 00:00:00 2001 From: Kirill Taran Date: Wed, 3 Jan 2024 20:04:49 +0400 Subject: [PATCH 14/23] Bump arklib version to `0d25eb0` (#14) * Bump arklib version * Added tokio to deal with futures * Updating the index when links are added * Update GitHub Actions --------- Co-authored-by: Alvi Hysa --- ark-cli/.github/workflows/rust.yml | 10 +- ark-cli/Cargo.lock | 1361 ++++++++++++++++------------ ark-cli/Cargo.toml | 3 +- ark-cli/src/main.rs | 34 +- 4 files changed, 821 insertions(+), 587 deletions(-) diff --git a/ark-cli/.github/workflows/rust.yml b/ark-cli/.github/workflows/rust.yml index e99544f4..84779b0a 100644 --- a/ark-cli/.github/workflows/rust.yml +++ b/ark-cli/.github/workflows/rust.yml @@ -11,20 +11,20 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install Rust - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: - toolchain: stable - override: true components: rustfmt, clippy - name: Check run: cargo check - name: Format - run: cargo fmt --all -- --check + run: | + cargo fmt --all -- --check + cargo clippy - name: Build Release run: cargo build --verbose --release diff --git a/ark-cli/Cargo.lock b/ark-cli/Cargo.lock index df6e67bc..13d212ef 100644 --- a/ark-cli/Cargo.lock +++ b/ark-cli/Cargo.lock @@ -3,43 +3,45 @@ version = 3 [[package]] -name = "adler" -version = "1.0.2" +name = "addr2line" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] [[package]] -name = "adler32" -version = "1.2.0" +name = "adler" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aes" -version = "0.7.5" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" dependencies = [ "cfg-if", "cipher", "cpufeatures", - "opaque-debug", ] [[package]] name = "aho-corasick" -version = "0.7.18" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] [[package]] name = "anyhow" -version = "1.0.61" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "508b352bb5c066aac251f6daf6b36eccd03e8a88e8081cd44959ea277a3af9a8" +checksum = "59d2a3357dde987206219e78ecfbbb6e8dad06cbb65292758d3270e6254f7355" [[package]] name = "ark-cli" @@ -50,6 +52,7 @@ dependencies = [ "env_logger", "fs_extra", "home", + "tokio", "url", "walkdir", ] @@ -57,12 +60,13 @@ dependencies = [ [[package]] name = "arklib" version = "0.1.0" -source = "git+https://github.com/ARK-Builders/arklib?rev=fea125e#fea125e8330243522183c187a467dc762dec1fb7" +source = "git+https://github.com/ARK-Builders/arklib?rev=0d25eb0#0d25eb0eb9d59405857e4129f0617046a1ebe159" dependencies = [ "anyhow", "canonical-path", "crc32fast", "env_logger", + "fastrand", "flate2", "fs_extra", "image", @@ -70,14 +74,18 @@ dependencies = [ "lazy_static", "libloading", "log", + "machine-uid", + "once_cell", "pathdiff", "pdfium-render", "reqwest", + "ring", "scraper", "serde", "serde_json", "tar", "target-lexicon", + "thiserror", "tokio", "ureq", "url", @@ -91,7 +99,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -102,46 +110,84 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base64" -version = "0.13.0" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" [[package]] name = "base64ct" -version = "1.0.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a32fd6af2b5827bce66c29053ba0e7c42b9dcab01835835058558c10851a46b" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bindgen" -version = "0.60.1" +version = "0.66.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "062dddbc1ba4aca46de6338e2bf87771414c335f7b2f2036e8f3e9befebf88e6" +checksum = "f2b84e06fc203107bfbad243f4aba2af864eb7db3b1cf46ea0a023b0b433d2a7" dependencies = [ - "bitflags", + "bitflags 2.4.1", "cexpr", "clang-sys", - "clap", - "env_logger", "lazy_static", "lazycell", "log", "peeking_take_while", + "prettyplease", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", + "syn 2.0.42", + "which", +] + +[[package]] +name = "bindgen" +version = "0.69.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ffcebc3849946a7170a05992aac39da343a90676ab392c51a4280981d6379c2" +dependencies = [ + "bitflags 2.4.1", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.42", "which", ] [[package]] name = "bit_field" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" [[package]] name = "bitflags" @@ -149,44 +195,50 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + [[package]] name = "block-buffer" -version = "0.10.2" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] [[package]] name = "bumpalo" -version = "3.10.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytemuck" -version = "1.11.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5377c8865e74a160d21f29c2d40669f53286db6eab59b88540cbb12ffc8b835" +checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.2.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "bzip2" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" dependencies = [ "bzip2-sys", "libc", @@ -211,11 +263,12 @@ checksum = "e6e9e01327e6c86e92ec72b1c798d4a94810f147209bbe3ffab6a86954937a6f" [[package]] name = "cc" -version = "1.0.73" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "jobserver", + "libc", ] [[package]] @@ -233,26 +286,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "chunked_transfer" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e" - [[package]] name = "cipher" -version = "0.3.0" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "generic-array", + "crypto-common", + "inout", ] [[package]] name = "clang-sys" -version = "1.3.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a050e2153c5be08febd6734e29298e844fdb0fa21aeddd63b4eb7baa106c69b" +checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" dependencies = [ "glob", "libc", @@ -261,15 +309,15 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.16" +version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3dbbb6653e7c55cc8595ad3e1f7be8f32aba4eb7ff7f0fd1163d4f3d137c0a9" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ "atty", - "bitflags", + "bitflags 1.3.2", "clap_derive", "clap_lex", - "indexmap", + "indexmap 1.9.3", "once_cell", "strsim", "termcolor", @@ -278,15 +326,15 @@ dependencies = [ [[package]] name = "clap_derive" -version = "3.2.15" +version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba52acd3b0a5c33aeada5cdaa3267cdc7c594a98731d4268cdc1532f4264cb4" +checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" dependencies = [ "heck", "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -316,9 +364,9 @@ dependencies = [ [[package]] name = "console_log" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501a375961cef1a0d44767200e66e4a559283097e91d0730b1d75dfb2f8a1494" +checksum = "e89f72f65e8501878b8a004d5a1afb780987e2ce2b4532c562e367a72c57499f" dependencies = [ "log", "web-sys", @@ -338,9 +386,9 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -348,15 +396,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.2" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] @@ -370,21 +418,11 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - [[package]] name = "crossbeam-deque" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -393,28 +431,31 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.10" +version = "0.9.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" +checksum = "2d2fe95351b870527a5d09bf563ed3c97c0cffb87cf1c78a591bf48bb218d9aa" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", "memoffset", - "once_cell", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.11" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" +checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f" dependencies = [ "cfg-if", - "once_cell", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-common" version = "0.1.6" @@ -439,26 +480,26 @@ dependencies = [ "proc-macro2", "quote", "smallvec", - "syn", + "syn 1.0.109", ] [[package]] name = "cssparser-macros" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn", + "syn 2.0.42", ] [[package]] -name = "deflate" -version = "1.0.0" +name = "deranged" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c86f7e25f518f4b81808a2cf1c50996a61f5c2eb394b2393bd87f2a4780a432f" +checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" dependencies = [ - "adler32", + "powerfmt", ] [[package]] @@ -471,14 +512,14 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn", + "syn 1.0.109", ] [[package]] name = "digest" -version = "0.10.3" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", @@ -487,15 +528,15 @@ dependencies = [ [[package]] name = "dtoa" -version = "0.4.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" [[package]] name = "dtoa-short" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde03329ae10e79ede66c9ce4dc930aa8599043b0743008548680f25b91502d6" +checksum = "dbaceec3c6e4211c79e7b1800fb9680527106beb2f9c51904a3210c03a448c74" dependencies = [ "dtoa", ] @@ -508,24 +549,24 @@ checksum = "3a68a4904193147e0a8dec3314640e6db742afd5f6e634f428a6af230d9b3591" [[package]] name = "either" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "encoding_rs" -version = "0.8.31" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if", ] [[package]] name = "env_logger" -version = "0.9.0" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" dependencies = [ "atty", "humantime", @@ -534,48 +575,70 @@ dependencies = [ "termcolor", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "exr" -version = "1.4.2" +version = "1.71.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14cc0e06fb5f67e5d6beadf3a382fec9baca1aa751c6d5368fdeee7e5932c215" +checksum = "832a761f35ab3e6664babfbdc6cef35a4860e816ec3916dcfd0882954e98a8a8" dependencies = [ "bit_field", - "deflate", "flume", "half", - "inflate", "lebe", + "miniz_oxide", + "rayon-core", "smallvec", - "threadpool", + "zune-inflate", ] [[package]] name = "fastrand" -version = "1.8.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "fdeflate" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d6dafc854908ff5da46ff3f8f473c6984119a2876a383a860246dd7841a868" dependencies = [ - "instant", + "simd-adler32", ] [[package]] name = "filetime" -version = "0.2.17" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94a7bbaa59354bc20dd75b67f23e2797b4490e9d6928203fb105c79e448c86c" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ "cfg-if", "libc", "redox_syscall", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "flate2" -version = "1.0.24" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", "miniz_oxide", @@ -583,15 +646,11 @@ dependencies = [ [[package]] name = "flume" -version = "0.10.14" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ - "futures-core", - "futures-sink", - "nanorand", - "pin-project", - "spin 0.9.4", + "spin", ] [[package]] @@ -617,19 +676,18 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ - "matches", "percent-encoding", ] [[package]] name = "fs_extra" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "futf" @@ -643,36 +701,36 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ "futures-core", "futures-task", @@ -691,9 +749,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.6" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -721,38 +779,42 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.7" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "wasm-bindgen", ] [[package]] name = "gif" -version = "0.11.4" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3edd93c6756b4dfaf2709eafcc345ba2636565295c198a9cfbf75fa5e3e00b06" +checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" dependencies = [ "color_quant", "weezl", ] +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + [[package]] name = "glob" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "h2" -version = "0.3.13" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" +checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" dependencies = [ "bytes", "fnv", @@ -760,7 +822,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 2.1.0", "slab", "tokio", "tokio-util", @@ -769,9 +831,12 @@ dependencies = [ [[package]] name = "half" -version = "1.8.2" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" +dependencies = [ + "crunchy", +] [[package]] name = "hashbrown" @@ -779,11 +844,17 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" @@ -794,6 +865,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + [[package]] name = "hmac" version = "0.12.1" @@ -805,11 +882,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.3" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2456aef2e6b6a9784192ae780c0f15bc57df0e918585282325e8c8ac27737654" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -823,25 +900,25 @@ dependencies = [ "markup5ever", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "http" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", - "itoa 1.0.3", + "itoa 1.0.10", ] [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -850,15 +927,15 @@ dependencies = [ [[package]] name = "httparse" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" @@ -868,9 +945,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.20" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", @@ -881,7 +958,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.3", + "itoa 1.0.10", "pin-project-lite", "socket2", "tokio", @@ -905,20 +982,19 @@ dependencies = [ [[package]] name = "idna" -version = "0.2.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] [[package]] name = "image" -version = "0.24.3" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e30ca2ecf7666107ff827a8e481de6a132a9b687ed3bb20bb1c144a36c00964" +checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" dependencies = [ "bytemuck", "byteorder", @@ -929,43 +1005,44 @@ dependencies = [ "num-rational", "num-traits", "png", - "scoped_threadpool", + "qoi", "tiff", ] [[package]] name = "indexmap" -version = "1.9.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", ] [[package]] -name = "inflate" -version = "0.4.5" +name = "indexmap" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ - "adler32", + "equivalent", + "hashbrown 0.14.3", ] [[package]] -name = "instant" -version = "0.1.12" +name = "inout" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" dependencies = [ - "cfg-if", + "generic-array", ] [[package]] name = "ipnet" -version = "2.5.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "iter_tools" @@ -993,33 +1070,33 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.3" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jobserver" -version = "0.1.24" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" dependencies = [ "libc", ] [[package]] name = "jpeg-decoder" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9478aa10f73e7528198d75109c8be5cd7d15fb530238040148d5f9a22d4c5b3b" +checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" dependencies = [ "rayon", ] [[package]] name = "js-sys" -version = "0.3.59" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" +checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" dependencies = [ "wasm-bindgen", ] @@ -1038,31 +1115,37 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "lebe" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7efd1d698db0759e6ef11a7cd44407407399a910c774dd804c64c032da7826ff" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.129" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64de3cc433455c14174d42e554d4027ee631c4d046d43e3ecc6efc4636cdc7a7" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "libloading" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ "cfg-if", "winapi", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" + [[package]] name = "lock_api" -version = "0.4.7" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -1070,12 +1153,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "mac" @@ -1083,6 +1163,17 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" +[[package]] +name = "machine-uid" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958d2e0ee250103b08a70a5785ca5abcd077a47584b35087248a93758c699f29" +dependencies = [ + "bindgen 0.66.1", + "cc", + "winreg", +] + [[package]] name = "markup5ever" version = "0.11.0" @@ -1099,9 +1190,9 @@ dependencies = [ [[package]] name = "matches" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "maybe-owned" @@ -1111,24 +1202,24 @@ checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memoffset" -version = "0.6.5" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] [[package]] name = "mime" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "minimal-lexical" @@ -1138,39 +1229,30 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.5.3" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", + "simd-adler32", ] [[package]] name = "mio" -version = "0.8.4" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", - "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", -] - -[[package]] -name = "nanorand" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" -dependencies = [ - "getrandom 0.2.7", + "windows-sys 0.48.0", ] [[package]] name = "native-tls" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" dependencies = [ "lazy_static", "libc", @@ -1198,9 +1280,9 @@ checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" [[package]] name = "nom" -version = "7.1.1" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", @@ -1229,51 +1311,45 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.3", "libc", ] [[package]] -name = "num_threads" -version = "0.1.6" +name = "object" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ - "libc", + "memchr", ] [[package]] name = "once_cell" -version = "1.13.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl" -version = "0.10.41" +version = "0.10.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0" +checksum = "8cde4d2d9200ad5909f8dac647e29482e07c3a35de8a13fce7c9c7747ad9f671" dependencies = [ - "bitflags", + "bitflags 2.4.1", "cfg-if", "foreign-types", "libc", @@ -1284,13 +1360,13 @@ dependencies = [ [[package]] name = "openssl-macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.42", ] [[package]] @@ -1301,11 +1377,10 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.75" +version = "0.9.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f" +checksum = "c1665caf8ab2dc9aef43d1c0023bd904633a6a05cb30b0ad59bec2ae986e57a7" dependencies = [ - "autocfg", "cc", "libc", "pkg-config", @@ -1314,9 +1389,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.2.0" +version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "648001efe5d5c0102d8cea768e348da85d90af8ba91f0bea908f157951493cd4" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" [[package]] name = "parking_lot" @@ -1330,25 +1405,25 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.3" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-targets 0.48.5", ] [[package]] name = "password-hash" -version = "0.3.2" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d791538a6dcc1e7cb7fe6f6b58aca40e7f79403c45b2bc274008b5e647af1d8" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" dependencies = [ "base64ct", - "rand_core 0.6.3", + "rand_core 0.6.4", "subtle", ] @@ -1360,9 +1435,9 @@ checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" [[package]] name = "pbkdf2" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271779f35b581956db91a3e55737327a03aa051e90b1c47aeb189508533adfd7" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ "digest", "hmac", @@ -1372,12 +1447,11 @@ dependencies = [ [[package]] name = "pdfium-render" -version = "0.7.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d23ff46f6e747af4762874b660f88a79356e9e38731f1f5a2f5d73d8ff2bbb0a" +version = "0.7.26" +source = "git+https://github.com/ajrcarey/pdfium-render?rev=d2559c1#d2559c10d27392cc48e51a55d80fffbe6fc87b5c" dependencies = [ - "bindgen", - "bitflags", + "bindgen 0.69.1", + "bitflags 1.3.2", "bytes", "console_error_panic_hook", "console_log", @@ -1403,9 +1477,9 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "phf" @@ -1478,7 +1552,7 @@ dependencies = [ "proc-macro-hack", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1499,31 +1573,11 @@ dependencies = [ "siphasher", ] -[[package]] -name = "pin-project" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78203e83c48cffbe01e4a2d35d566ca4de445d79a85372fc64e378bfc812a260" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "710faf75e1b33345361201d36d04e98ac1ed8909151a017ed384700836104c74" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -1539,27 +1593,34 @@ checksum = "ad78bf43dcf80e8f950c92b84f938a0fc7590b7f6866fbcbeca781609c115590" [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" [[package]] name = "png" -version = "0.17.5" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc38c0ad57efb786dd57b9864e5b18bae478c00c824dc55a38bbc9da95dde3ba" +checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" dependencies = [ - "bitflags", + "bitflags 1.3.2", "crc32fast", - "deflate", + "fdeflate", + "flate2", "miniz_oxide", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "precomputed-hash" @@ -1567,6 +1628,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "prettyplease" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +dependencies = [ + "proc-macro2", + "syn 2.0.42", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -1576,7 +1647,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "version_check", ] @@ -1593,24 +1664,33 @@ dependencies = [ [[package]] name = "proc-macro-hack" -version = "0.5.19" +version = "0.5.20+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.43" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" dependencies = [ "unicode-ident", ] +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + [[package]] name = "quote" -version = "1.0.21" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -1637,7 +1717,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.1", - "rand_core 0.6.3", + "rand_core 0.6.4", ] [[package]] @@ -1657,7 +1737,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.3", + "rand_core 0.6.4", ] [[package]] @@ -1671,11 +1751,11 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.7", + "getrandom 0.2.11", ] [[package]] @@ -1698,68 +1778,67 @@ dependencies = [ [[package]] name = "rayon" -version = "1.5.3" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" dependencies = [ - "autocfg", - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.9.3" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] name = "regex" -version = "1.6.0" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", + "regex-automata", "regex-syntax", ] [[package]] -name = "regex-syntax" -version = "0.6.27" +name = "regex-automata" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] [[package]] -name = "remove_dir_all" -version = "0.5.3" +name = "regex-syntax" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.11" +version = "0.11.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" +checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" dependencies = [ "base64", "bytes", @@ -1773,15 +1852,16 @@ dependencies = [ "hyper-tls", "ipnet", "js-sys", - "lazy_static", "log", "mime", "native-tls", + "once_cell", "percent-encoding", "pin-project-lite", "serde", "serde_json", "serde_urlencoded", + "system-configuration", "tokio", "tokio-native-tls", "tower-service", @@ -1794,19 +1874,24 @@ dependencies = [ [[package]] name = "ring" -version = "0.16.20" +version = "0.17.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" dependencies = [ "cc", + "getrandom 0.2.11", "libc", - "once_cell", - "spin 0.5.2", + "spin", "untrusted", - "web-sys", - "winapi", + "windows-sys 0.48.0", ] +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "rustc-hash" version = "1.1.0" @@ -1822,23 +1907,46 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.38.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + [[package]] name = "rustls" -version = "0.20.6" +version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", "ring", + "rustls-webpki", "sct", - "webpki", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", ] [[package]] name = "ryu" -version = "1.0.11" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "same-file" @@ -1851,25 +1959,18 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.20" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" dependencies = [ - "lazy_static", - "windows-sys", + "windows-sys 0.48.0", ] -[[package]] -name = "scoped_threadpool" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" - [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "scraper" @@ -1889,9 +1990,9 @@ dependencies = [ [[package]] name = "sct" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ "ring", "untrusted", @@ -1899,11 +2000,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.6.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -1912,9 +2013,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.6.1" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -1926,7 +2027,7 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cssparser", "derive_more", "fxhash", @@ -1942,37 +2043,37 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.13" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" [[package]] name = "serde" -version = "1.0.143" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.143" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.42", ] [[package]] name = "serde_json" -version = "1.0.83" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ - "itoa 1.0.3", + "itoa 1.0.10", "ryu", "serde", ] @@ -1984,7 +2085,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.3", + "itoa 1.0.10", "ryu", "serde", ] @@ -2001,9 +2102,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.1" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77f4e7f65455545c2153c1253d25056825e77ee2533f0e41deb65a93a34852f" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", @@ -2012,9 +2113,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.2" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -2023,61 +2124,61 @@ dependencies = [ [[package]] name = "shlex" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" [[package]] name = "signal-hook-registry" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" dependencies = [ "libc", ] +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "siphasher" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "slab" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "smallvec" -version = "1.9.0" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "socket2" -version = "0.4.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", - "winapi", + "windows-sys 0.48.0", ] [[package]] name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "spin" -version = "0.9.4" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" dependencies = [ "lock_api", ] @@ -2090,9 +2191,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "string_cache" -version = "0.8.4" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" dependencies = [ "new_debug_unreachable", "once_cell", @@ -2122,26 +2223,58 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "subtle" -version = "2.4.1" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] [[package]] name = "syn" -version = "1.0.99" +version = "2.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +checksum = "5b7d0a2c048d661a1a59fcd7355baa232f7ed34e0ee4df2eef3c1c1c0d3852d8" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tar" -version = "0.4.38" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" +checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" dependencies = [ "filetime", "libc", @@ -2150,22 +2283,21 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.4" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1" +checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] name = "tempfile" -version = "3.3.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", "fastrand", - "libc", "redox_syscall", - "remove_dir_all", - "winapi", + "rustix", + "windows-sys 0.48.0", ] [[package]] @@ -2181,18 +2313,18 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.3" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" dependencies = [ "winapi-util", ] [[package]] name = "textwrap" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thin-slice" @@ -2201,19 +2333,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" [[package]] -name = "threadpool" -version = "1.8.1" +name = "thiserror" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7" dependencies = [ - "num_cpus", + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.42", ] [[package]] name = "tiff" -version = "0.7.3" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7259662e32d1e219321eb309d5f9d898b779769d81b76e762c07c8e5d38fcb65" +checksum = "6d172b0f4d3fba17ba89811858b9d3d97f928aece846475bbda076ca46736211" dependencies = [ "flate2", "jpeg-decoder", @@ -2222,21 +2365,21 @@ dependencies = [ [[package]] name = "time" -version = "0.3.13" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db76ff9fa4b1458b3c7f077f3ff9887394058460d21e634355b273aaf11eea45" +checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" dependencies = [ - "itoa 1.0.3", - "libc", - "num_threads", - "time-macros", + "deranged", + "powerfmt", + "serde", + "time-core", ] [[package]] -name = "time-macros" -version = "0.2.4" +name = "time-core" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "tinyvec" @@ -2249,47 +2392,45 @@ dependencies = [ [[package]] name = "tinyvec_macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.20.1" +version = "1.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581" +checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" dependencies = [ - "autocfg", + "backtrace", "bytes", "libc", - "memchr", "mio", "num_cpus", - "once_cell", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "winapi", + "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "1.8.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.42", ] [[package]] name = "tokio-native-tls" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ "native-tls", "tokio", @@ -2297,9 +2438,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.3" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", @@ -2317,95 +2458,92 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.36" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-core", ] [[package]] name = "tracing-core" -version = "0.1.29" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", ] [[package]] name = "try-lock" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" -version = "1.15.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-bidi" -version = "0.3.8" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" [[package]] name = "unicode-ident" -version = "1.0.3" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-width" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "untrusted" -version = "0.7.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.5.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97acb4c28a254fd7a4aeec976c46a7fa404eac4d7c134b30c75144846d7cb8f" +checksum = "f8cdd25c339e200129fe4de81451814e5228c9b771d57378817d6117cc2b3f97" dependencies = [ "base64", - "chunked_transfer", "flate2", "log", "once_cell", "rustls", + "rustls-webpki", "url", - "webpki", "webpki-roots", ] [[package]] name = "url" -version = "2.2.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", - "matches", "percent-encoding", "serde", ] @@ -2448,22 +2586,20 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" -version = "2.3.2" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", - "winapi", "winapi-util", ] [[package]] name = "want" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "log", "try-lock", ] @@ -2481,9 +2617,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.82" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" +checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2491,24 +2627,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.82" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" +checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn", + "syn 2.0.42", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.32" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa76fb221a1f8acddf5b54ace85912606980ad661ac7a503b4570ffd3a624dad" +checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" dependencies = [ "cfg-if", "js-sys", @@ -2518,9 +2654,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.82" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" +checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2528,51 +2664,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.82" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" +checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.42", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.82" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" +checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" [[package]] name = "web-sys" -version = "0.3.59" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1" +checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" dependencies = [ "js-sys", "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "webpki-roots" -version = "0.22.4" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1c760f0d366a6c24a02ed7816e23e691f5d92291f94d15e836006fd11b04daf" -dependencies = [ - "webpki", -] +checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" [[package]] name = "weezl" @@ -2582,13 +2705,14 @@ checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" [[package]] name = "which" -version = "4.2.5" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" dependencies = [ "either", - "lazy_static", - "libc", + "home", + "once_cell", + "rustix", ] [[package]] @@ -2609,9 +2733,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -2624,70 +2748,162 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.36.1" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows-targets 0.48.5", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" -version = "0.36.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" [[package]] name = "windows_i686_msvc" -version = "0.36.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winreg" -version = "0.10.1" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "winapi", + "cfg-if", + "windows-sys 0.48.0", ] [[package]] name = "xattr" -version = "0.2.3" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" +checksum = "a7dae5072fe1f8db8f8d29059189ac175196e410e40ba42d5d4684ae2f750995" dependencies = [ "libc", + "linux-raw-sys", + "rustix", ] [[package]] name = "zip" -version = "0.6.2" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf225bcf73bb52cbb496e70475c7bd7a3f769df699c0020f6c7bd9a96dcf0b8d" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" dependencies = [ "aes", "byteorder", @@ -2705,18 +2921,18 @@ dependencies = [ [[package]] name = "zstd" -version = "0.10.2+zstd.1.5.2" +version = "0.11.2+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4a6bd64f22b5e3e94b4e238669ff9f10815c27a5180108b849d24174a83847" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "4.1.6+zstd.1.5.2" +version = "5.0.2+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b61c51bb270702d6167b8ce67340d2754b088d0c091b06e593aa772c3ee9bb" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" dependencies = [ "libc", "zstd-sys", @@ -2724,10 +2940,19 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "1.6.3+zstd.1.5.2" +version = "2.0.9+zstd.1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc49afa5c8d634e75761feda8c592051e7eeb4683ba827211eb0d731d3402ea8" +checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" dependencies = [ "cc", - "libc", + "pkg-config", +] + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", ] diff --git a/ark-cli/Cargo.toml b/ark-cli/Cargo.toml index 9fb63e8a..ea46bd61 100644 --- a/ark-cli/Cargo.toml +++ b/ark-cli/Cargo.toml @@ -7,7 +7,8 @@ edition = "2021" name = "ark-cli" [dependencies] -arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "fea125e" } +tokio = { version = "1.35.1", features = ["full"] } +arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "0d25eb0" } clap = { version = "3.0.10", features = ["derive"] } env_logger = "0.9.0" fs_extra = "1.2.0" diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs index f8b0b05f..a8ab9bd9 100644 --- a/ark-cli/src/main.rs +++ b/ark-cli/src/main.rs @@ -76,7 +76,8 @@ const ARK_CONFIG: &str = ".config/ark"; const ARK_BACKUPS_PATH: &str = ".ark-backups"; const ROOTS_CFG_FILENAME: &str = "roots"; -fn main() { +#[tokio::main] +async fn main() { env_logger::init(); let args = Cli::parse(); @@ -138,7 +139,7 @@ fn main() { options.copy_inside = true; let result = dir::copy( - root.join(&arklib::STORAGES_FOLDER), + root.join(&arklib::ARK_FOLDER), storage_backup, &options, ); @@ -190,20 +191,26 @@ fn main() { let root = provide_root(root_dir); let url = Url::parse(url.as_deref().unwrap()); - let mut link: arklib::link::Link = arklib::link::Link::new( + let link: arklib::link::Link = arklib::link::Link::new( url.unwrap(), title.to_owned().unwrap(), desc.to_owned(), ); - let timestamp = timestamp().as_secs(); - let path = Path::join( - &root, - format!("{}.link", ×tamp.to_string()), - ); - link.write_to_path_sync(root, path.clone(), true) - .unwrap(); - println!("Link saved successfully: {:?}", path.display()) + let future = link.save(&root, true); + + println!("Saving link..."); + + match future.await { + Ok(_) => { + println!("Link saved successfully!"); + match provide_index(&root).store() { + Ok(_) => println!("Index stored successfully!"), + Err(e) => println!("Error: {}", e), + } + } + Err(e) => println!("Error: {}", e), + } } Link::Load { @@ -328,9 +335,10 @@ fn monitor_index(root_dir: &Option, interval: Option) { thread::sleep(pause); let start = Instant::now(); - match index.update() { + match index.update_all() { Err(msg) => println!("Oops! {}", msg), Ok(diff) => { + index.store().expect("Could not store index"); let duration = start.elapsed(); println!("Updating succeeded in {:?}\n", duration); @@ -358,7 +366,7 @@ fn monitor_index(root_dir: &Option, interval: Option) { } fn storages_exists(path: &Path) -> bool { - let meta = metadata(path.join(&arklib::STORAGES_FOLDER)); + let meta = metadata(path.join(&arklib::ARK_FOLDER)); if let Ok(meta) = meta { return meta.is_dir(); } From df1fc37ebaa080eadb45ea0b6562dcdd88e1e8c8 Mon Sep 17 00:00:00 2001 From: Alvi Hysa Date: Fri, 5 Jan 2024 13:35:48 +0100 Subject: [PATCH 15/23] Added storage commands --- ark-cli/.gitignore | 3 +- ark-cli/Cargo.lock | 51 ++---- ark-cli/Cargo.toml | 4 +- ark-cli/src/main.rs | 370 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 386 insertions(+), 42 deletions(-) diff --git a/ark-cli/.gitignore b/ark-cli/.gitignore index 1de56593..55f04984 100644 --- a/ark-cli/.gitignore +++ b/ark-cli/.gitignore @@ -1 +1,2 @@ -target \ No newline at end of file +target +.ark \ No newline at end of file diff --git a/ark-cli/Cargo.lock b/ark-cli/Cargo.lock index 13d212ef..cb73f7a0 100644 --- a/ark-cli/Cargo.lock +++ b/ark-cli/Cargo.lock @@ -52,6 +52,8 @@ dependencies = [ "env_logger", "fs_extra", "home", + "serde", + "serde_json", "tokio", "url", "walkdir", @@ -60,7 +62,7 @@ dependencies = [ [[package]] name = "arklib" version = "0.1.0" -source = "git+https://github.com/ARK-Builders/arklib?rev=0d25eb0#0d25eb0eb9d59405857e4129f0617046a1ebe159" +source = "git+https://github.com/ARK-Builders/arklib?rev=1249e6c#1249e6c547da47f1a48570f7e03b899768575b3c" dependencies = [ "anyhow", "canonical-path", @@ -74,7 +76,6 @@ dependencies = [ "lazy_static", "libloading", "log", - "machine-uid", "once_cell", "pathdiff", "pdfium-render", @@ -89,6 +90,7 @@ dependencies = [ "tokio", "ureq", "url", + "uuid", "walkdir", "zip", ] @@ -137,29 +139,6 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" -[[package]] -name = "bindgen" -version = "0.66.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b84e06fc203107bfbad243f4aba2af864eb7db3b1cf46ea0a023b0b433d2a7" -dependencies = [ - "bitflags 2.4.1", - "cexpr", - "clang-sys", - "lazy_static", - "lazycell", - "log", - "peeking_take_while", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.42", - "which", -] - [[package]] name = "bindgen" version = "0.69.1" @@ -1163,17 +1142,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" -[[package]] -name = "machine-uid" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958d2e0ee250103b08a70a5785ca5abcd077a47584b35087248a93758c699f29" -dependencies = [ - "bindgen 0.66.1", - "cc", - "winreg", -] - [[package]] name = "markup5ever" version = "0.11.0" @@ -1450,7 +1418,7 @@ name = "pdfium-render" version = "0.7.26" source = "git+https://github.com/ajrcarey/pdfium-render?rev=d2559c1#d2559c10d27392cc48e51a55d80fffbe6fc87b5c" dependencies = [ - "bindgen 0.69.1", + "bindgen", "bitflags 1.3.2", "bytes", "console_error_panic_hook", @@ -2563,6 +2531,15 @@ dependencies = [ "byteorder", ] +[[package]] +name = "uuid" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +dependencies = [ + "getrandom 0.2.11", +] + [[package]] name = "vcpkg" version = "0.2.15" diff --git a/ark-cli/Cargo.toml b/ark-cli/Cargo.toml index ea46bd61..8af2d0a6 100644 --- a/ark-cli/Cargo.toml +++ b/ark-cli/Cargo.toml @@ -8,10 +8,12 @@ name = "ark-cli" [dependencies] tokio = { version = "1.35.1", features = ["full"] } -arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "0d25eb0" } +arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "1249e6c" } clap = { version = "3.0.10", features = ["derive"] } env_logger = "0.9.0" fs_extra = "1.2.0" walkdir = "2.3.2" home = "0.5.3" url = { version = "2.2.2", features = ["serde"] } +serde_json = "1.0.82" +serde = { version = "1.0.138", features = ["derive"] } \ No newline at end of file diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs index a8ab9bd9..1ed9c1b6 100644 --- a/ark-cli/src/main.rs +++ b/ark-cli/src/main.rs @@ -1,18 +1,27 @@ -use std::env::current_dir; +use std::env::{self, current_dir}; use std::fs::{canonicalize, create_dir_all, metadata, File}; use std::io::prelude::*; use std::io::BufReader; -use std::path::{Path, PathBuf}; +use std::path::{Display, Path, PathBuf}; +use std::str::FromStr; use std::thread; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; -use arklib::id::ResourceId; +use arklib::id::{app_id, ResourceId}; use arklib::index::ResourceIndex; use arklib::pdf::PDFQuality; +use arklib::{ + modify, modify_json, AtomicFile, ARK_FOLDER, DEVICE_ID, FAVORITES_FILE, + METADATA_STORAGE_FOLDER, PREVIEWS_STORAGE_FOLDER, + PROPERTIES_STORAGE_FOLDER, SCORE_STORAGE_FILE, STATS_FOLDER, + TAG_STORAGE_FILE, THUMBNAILS_STORAGE_FOLDER, +}; use clap::{Parser, Subcommand}; use fs_extra::dir::{self, CopyOptions}; use home::home_dir; +use std::io::{Result, Write}; use url::Url; +use walkdir::WalkDir; #[derive(Parser, Debug)] #[clap(name = "ark-cli")] @@ -22,6 +31,46 @@ struct Cli { command: Command, } +#[derive(Debug)] +enum InsertContent { + Values(Vec<(String, String)>), + String(String), +} + +impl FromStr for InsertContent { + type Err = &'static str; + + fn from_str(s: &str) -> std::result::Result { + let pairs: Vec<&str> = s.split(',').collect(); + + if pairs.len() == 1 { + let key_value: Vec<&str> = pairs[0].split(':').collect(); + if key_value.len() == 2 { + let key = key_value[0].trim().to_string(); + let value = key_value[1].trim().to_string(); + return Ok(InsertContent::Values(vec![(key, value)])); + } else { + return Ok(InsertContent::String(s.to_string())); + } + } + + let mut values = Vec::new(); + + for pair in pairs { + let key_value: Vec<&str> = pair.split(':').collect(); + if key_value.len() == 2 { + let key = key_value[0].trim().to_string(); + let value = key_value[1].trim().to_string(); + values.push((key, value)); + } else { + return Err("Invalid key-value pair format"); + } + } + + Ok(InsertContent::Values(values)) + } +} + #[derive(Subcommand, Debug)] enum Command { Backup { @@ -48,6 +97,39 @@ enum Command { #[clap(subcommand)] Link(Link), + + #[clap(subcommand)] + File(FileCommand), +} + +#[derive(Subcommand, Debug)] +enum FileCommand { + Append { + #[clap(parse(from_os_str))] + storage: Option, + + content: Option, + }, + + Insert { + #[clap(parse(from_os_str))] + storage: Option, + + content: Option, + }, + + Read { + #[clap(parse(from_os_str))] + storage: Option, + }, + + List { + #[clap(parse(from_os_str))] + storage: Option, + + #[clap(short, long)] + all: bool, + }, } #[derive(Subcommand, Debug)] @@ -82,6 +164,17 @@ async fn main() { let args = Cli::parse(); + let app_id_dir = home_dir().expect("Couldn't retrieve home directory!"); + let ark_dir = app_id_dir.join(".ark"); + if !ark_dir.exists() { + std::fs::create_dir(&ark_dir).unwrap(); + } + println!("Loading app id at {}...", ark_dir.display()); + let _ = app_id::load(ark_dir).map_err(|e| { + println!("Couldn't load app id: {}", e); + std::process::exit(1); + }); + match &args.command { Command::Backup { roots_cfg } => { let timestamp = timestamp().as_secs(); @@ -252,9 +345,280 @@ async fn main() { println!("Link data:\n{:?}", link.unwrap()); } }, + + Command::File(file) => match &file { + FileCommand::Append { storage, content } => { + let root = provide_root(&None); + let storage = storage.as_ref().unwrap_or(&root); + let file_path = get_storage_from_path(storage) + .expect("Could not find storage folder"); + + let atomic_file = arklib::AtomicFile::new(file_path).unwrap(); + + if let Some(content) = content { + match content { + InsertContent::String(content) => { + modify(&atomic_file, |current| { + let mut combined_vec: Vec = + current.to_vec(); + combined_vec + .extend_from_slice(content.as_bytes()); + combined_vec + }) + .expect("Could not append string") + } + InsertContent::Values(values) => { + append_json(&atomic_file, values.to_vec()) + .expect("Could not append json"); + } + } + } else { + println!("Provide content to insert"); + } + } + + FileCommand::Insert { storage, content } => { + let root = provide_root(&None); + let storage = storage.as_ref().unwrap_or(&root); + let file_path = get_storage_from_path(storage) + .expect("Could not find storage folder"); + + let atomic_file = arklib::AtomicFile::new(file_path).unwrap(); + + if let Some(content) = content { + match content { + InsertContent::String(content) => { + modify(&atomic_file, |_| { + content.as_bytes().to_vec() + }) + .expect("Could not insert string"); + } + InsertContent::Values(values) => { + modify_json( + &atomic_file, + |current: &mut Option| { + let mut new = serde_json::Map::new(); + for (key, value) in values { + new.insert( + key.clone(), + serde_json::Value::String( + value.clone(), + ), + ); + } + *current = + Some(serde_json::Value::Object(new)); + }, + ) + .expect("Could not insert json"); + } + } + } else { + println!("Provide content to insert"); + } + } + + FileCommand::Read { storage } => { + let root = provide_root(&None); + let storage = storage.as_ref().unwrap_or(&root); + let file_path = get_storage_from_path(storage) + .expect("Could not find storage folder"); + + let atomic_file = arklib::AtomicFile::new(&file_path).unwrap(); + + if let Some(file) = format_file(&atomic_file, true) { + println!("{}", file); + } else { + println!( + "FILE: {} is not a valid atomic file", + file_path.display() + ); + } + } + + FileCommand::List { storage, all } => { + let root = provide_root(&None); + let storage = storage.as_ref().unwrap_or(&root); + let file_path = get_storage_from_path(storage) + .expect("Could not find storage folder"); + + if !all { + let file = AtomicFile::new(&file_path).unwrap(); + if let Some(file) = format_file(&file, false) { + println!("{}", file); + } else { + println!( + "FILE: {} is not a valid atomic file", + file_path.display() + ); + } + } else { + let files: Vec = WalkDir::new(file_path) + .into_iter() + .filter_entry(|e| e.file_type().is_dir()) + .filter_map(|v| v.ok()) + .filter_map(|e| match AtomicFile::new(e.path()) { + Ok(file) => Some(file), + Err(_) => None, + }) + .collect(); + + for file in files { + if let Some(file) = format_file(&file, false) { + println!("{}", file); + } + } + } + } + }, } } +pub fn append_json( + atomic_file: &AtomicFile, + data: Vec<(String, String)>, +) -> Result<()> { + modify_json(&atomic_file, |current: &mut Option| { + let current_data = match current { + Some(current) => { + if let Ok(value) = serde_json::to_value(current) { + match value { + serde_json::Value::Object(map) => Some(map), + _ => None, + } + } else { + None + } + } + + None => None, + }; + let mut new = serde_json::Map::new(); + + if let None = current_data { + for (key, value) in &data { + new.insert( + key.clone(), + serde_json::Value::String(value.clone()), + ); + } + *current = Some(serde_json::Value::Object(new)); + } else if let Some(values) = current_data { + for (key, value) in &values { + new.insert(key.clone(), value.clone()); + } + + for (key, value) in &data { + new.insert( + key.clone(), + serde_json::Value::String(value.clone()), + ); + } + *current = Some(serde_json::Value::Object(new)); + } + }) +} + +fn get_storage_from_path(storage: &PathBuf) -> Option { + if storage.exists() { + Some(storage.clone()) + } else { + match storage + .clone() + .into_os_string() + .into_string() + .unwrap() + .to_lowercase() + .as_str() + { + "favorites" => Some( + provide_root(&None) + .join(ARK_FOLDER) + .join(FAVORITES_FILE), + ), + "device" => Some( + provide_root(&None) + .join(ARK_FOLDER) + .join(DEVICE_ID), + ), + "tage" => Some( + provide_root(&None) + .join(ARK_FOLDER) + .join(TAG_STORAGE_FILE), + ), + "score" => Some( + provide_root(&None) + .join(ARK_FOLDER) + .join(SCORE_STORAGE_FILE), + ), + "stats" => Some( + provide_root(&None) + .join(ARK_FOLDER) + .join(STATS_FOLDER), + ), + "properties" => Some( + provide_root(&None) + .join(ARK_FOLDER) + .join(PROPERTIES_STORAGE_FOLDER), + ), + "metadata" => Some( + provide_root(&None) + .join(ARK_FOLDER) + .join(METADATA_STORAGE_FOLDER), + ), + "previews" => Some( + provide_root(&None) + .join(ARK_FOLDER) + .join(PREVIEWS_STORAGE_FOLDER), + ), + "thumbnails" => Some( + provide_root(&None) + .join(ARK_FOLDER) + .join(THUMBNAILS_STORAGE_FOLDER), + ), + + _ => None, + } + } +} + +fn format_file(file: &AtomicFile, show_content: bool) -> Option { + let current = file.load().ok()?; + + if current.version == 0 { + return None; + } + + let mut split = current + .path + .file_name() + .expect("Not a file") + .to_str() + .unwrap() + .split("_"); + + let mut output = format!( + "{}: [{} - {}]", + current.version, + split.next().unwrap(), + split.next().unwrap() + ); + + if show_content { + let data = current.read_to_string().ok()?; + if let Ok(json) = serde_json::from_str::(&data) { + output.push_str(&format!( + "\n\n{}", + serde_json::to_string_pretty(&json).unwrap() + )); + } else { + output.push_str(&format!("\n\n{}", data)); + } + } + + Some(output) +} + fn discover_roots(roots_cfg: &Option) -> Vec { if let Some(path) = roots_cfg { println!( From 4ee759f2700747f7722ac3cdecc6fc2cff2d6cee Mon Sep 17 00:00:00 2001 From: Kirill Taran Date: Sat, 13 Jan 2024 19:57:37 +0300 Subject: [PATCH 16/23] Adjust to new commit in arklib --- ark-cli/Cargo.lock | 2 +- ark-cli/Cargo.toml | 2 +- ark-cli/src/main.rs | 7 ++++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/ark-cli/Cargo.lock b/ark-cli/Cargo.lock index cb73f7a0..a0d34719 100644 --- a/ark-cli/Cargo.lock +++ b/ark-cli/Cargo.lock @@ -62,7 +62,7 @@ dependencies = [ [[package]] name = "arklib" version = "0.1.0" -source = "git+https://github.com/ARK-Builders/arklib?rev=1249e6c#1249e6c547da47f1a48570f7e03b899768575b3c" +source = "git+https://github.com/ARK-Builders/arklib?rev=2c7ceda#2c7ceda1a6c7285e406b64762d6a977c5ab8000a" dependencies = [ "anyhow", "canonical-path", diff --git a/ark-cli/Cargo.toml b/ark-cli/Cargo.toml index 8af2d0a6..c7f30a7e 100644 --- a/ark-cli/Cargo.toml +++ b/ark-cli/Cargo.toml @@ -8,7 +8,7 @@ name = "ark-cli" [dependencies] tokio = { version = "1.35.1", features = ["full"] } -arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "1249e6c" } +arklib = { git = "https://github.com/ARK-Builders/arklib", rev = "2c7ceda" } clap = { version = "3.0.10", features = ["derive"] } env_logger = "0.9.0" fs_extra = "1.2.0" diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs index 1ed9c1b6..b926af7d 100644 --- a/ark-cli/src/main.rs +++ b/ark-cli/src/main.rs @@ -1,4 +1,4 @@ -use std::env::{self, current_dir}; +use std::env::current_dir; use std::fs::{canonicalize, create_dir_all, metadata, File}; use std::io::prelude::*; use std::io::BufReader; @@ -7,11 +7,12 @@ use std::str::FromStr; use std::thread; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; -use arklib::id::{app_id, ResourceId}; +use arklib::app_id; +use arklib::id::ResourceId; use arklib::index::ResourceIndex; use arklib::pdf::PDFQuality; use arklib::{ - modify, modify_json, AtomicFile, ARK_FOLDER, DEVICE_ID, FAVORITES_FILE, + modify, AtomicFile, APP_ID_FILE, ARK_FOLDER, FAVORITES_FILE, METADATA_STORAGE_FOLDER, PREVIEWS_STORAGE_FOLDER, PROPERTIES_STORAGE_FOLDER, SCORE_STORAGE_FILE, STATS_FOLDER, TAG_STORAGE_FILE, THUMBNAILS_STORAGE_FOLDER, From 600e6e4787389ba2b55402ec3cea8667e44149c9 Mon Sep 17 00:00:00 2001 From: Alvi Hysa Date: Sat, 20 Jan 2024 13:44:12 +0100 Subject: [PATCH 17/23] Links handling and file command --- ark-cli/src/commands/file.rs | 237 ++++++++++++++++ ark-cli/src/commands/link.rs | 51 ++++ ark-cli/src/commands/mod.rs | 2 + ark-cli/src/main.rs | 536 +++++++++++++---------------------- ark-cli/src/parsers/mod.rs | 36 +++ 5 files changed, 522 insertions(+), 340 deletions(-) create mode 100644 ark-cli/src/commands/file.rs create mode 100644 ark-cli/src/commands/link.rs create mode 100644 ark-cli/src/commands/mod.rs create mode 100644 ark-cli/src/parsers/mod.rs diff --git a/ark-cli/src/commands/file.rs b/ark-cli/src/commands/file.rs new file mode 100644 index 00000000..afdc6051 --- /dev/null +++ b/ark-cli/src/commands/file.rs @@ -0,0 +1,237 @@ +use crate::parsers::{self, Format}; +use arklib::{modify, modify_json, AtomicFile}; +use std::{fmt::Write, path::PathBuf, process::Output}; +use walkdir::WalkDir; + +pub fn file_append( + atomic_file: &AtomicFile, + content: &str, + format: Format, +) -> Result<(), String> { + match format { + parsers::Format::Raw => modify(&atomic_file, |current| { + let mut combined_vec: Vec = current.to_vec(); + combined_vec.extend_from_slice(content.as_bytes()); + combined_vec + }) + .map_err(|_| "ERROR: Could not append string".to_string()), + parsers::Format::Json => { + let values = parsers::key_value_to_str(&content) + .map_err(|_| "ERROR: Could not parse json".to_string())?; + + append_json(&atomic_file, values.to_vec()) + .map_err(|_| "ERROR: Could not append json".to_string()) + } + } +} + +pub fn file_insert( + atomic_file: &AtomicFile, + content: &str, + format: Format, +) -> Result<(), String> { + match format { + parsers::Format::Raw => { + modify(&atomic_file, |_| content.as_bytes().to_vec()) + .map_err(|_| "ERROR: Could not insert string".to_string()) + } + parsers::Format::Json => { + let values = parsers::key_value_to_str(&content) + .map_err(|_| "ERROR: Could not parse json".to_string())?; + + modify_json( + &atomic_file, + |current: &mut Option| { + let mut new = serde_json::Map::new(); + for (key, value) in &values { + new.insert( + key.clone(), + serde_json::Value::String(value.clone()), + ); + } + *current = Some(serde_json::Value::Object(new)); + }, + ) + .map_err(|_| "ERROR:Could not insert json".to_string()) + } + } +} + +pub fn file_read( + atomic_file: &AtomicFile, + key: &Option, +) -> Result { + if let Some(file) = format_file(&atomic_file) { + let mut output = String::new(); + writeln!( + output, + "{}", + format_line("version", "name", "machine", "path"), + ) + .map_err(|_| "Could not write to output".to_string())?; + + writeln!(output, "{}", file) + .map_err(|_| "Could not write to output".to_string())?; + + let current = atomic_file + .load() + .map_err(|_| "Could not load atomic file.".to_string())?; + + let data = current + .read_to_string() + .map_err(|_| "Could not read atomic file content.".to_string())?; + + if let Ok(json) = serde_json::from_str::(&data) { + if let Some(key) = key { + if let Some(value) = json.get(key) { + writeln!(output, "\n{}", value) + .map_err(|_| "Could not write to output".to_string())?; + } else { + return Err(format!("Key {} not found", key)); + } + } else { + writeln!( + output, + "\n{}", + serde_json::to_string_pretty(&json).unwrap() + ) + .map_err(|_| "Could not write to output".to_string())?; + } + } else { + writeln!(output, "\n{}", data) + .map_err(|_| "Could not write to output".to_string())?; + } + Ok(output) + } else { + Err("File not found".to_string()) + } +} + +pub fn file_list(path: PathBuf, versions: &bool) -> Result { + let mut output = String::new(); + + let files: Vec = WalkDir::new(path) + .min_depth(1) + .max_depth(1) + .into_iter() + .filter_entry(|e| e.file_type().is_dir()) + .filter_map(|v| v.ok()) + .filter_map(|e| match AtomicFile::new(e.path()) { + Ok(file) => Some(file), + Err(_) => None, + }) + .collect(); + + if *versions { + writeln!( + output, + "{}", + format_line("version", "name", "machine", "path"), + ); + + for file in files { + if let Some(file) = format_file(&file) { + writeln!(output, "{}", file); + } + } + } else { + for file in files { + write!( + output, + "{} ", + file.directory + .file_name() + .unwrap() + .to_str() + .unwrap() + ); + } + } + + Ok(output) +} + +fn append_json( + atomic_file: &AtomicFile, + data: Vec<(String, String)>, +) -> arklib::Result<()> { + modify_json(&atomic_file, |current: &mut Option| { + let current_data = match current { + Some(current) => { + if let Ok(value) = serde_json::to_value(current) { + match value { + serde_json::Value::Object(map) => Some(map), + _ => None, + } + } else { + None + } + } + + None => None, + }; + let mut new = serde_json::Map::new(); + + if let None = current_data { + for (key, value) in &data { + new.insert( + key.clone(), + serde_json::Value::String(value.clone()), + ); + } + *current = Some(serde_json::Value::Object(new)); + } else if let Some(values) = current_data { + for (key, value) in &values { + new.insert(key.clone(), value.clone()); + } + + for (key, value) in &data { + new.insert( + key.clone(), + serde_json::Value::String(value.clone()), + ); + } + *current = Some(serde_json::Value::Object(new)); + } + })?; + + Ok(()) +} + +fn format_line(version: A, name: B, machine: C, path: D) -> String +where + A: std::fmt::Display, + B: std::fmt::Display, + C: std::fmt::Display, + D: std::fmt::Display, +{ + format!("{: <8} {: <14} {: <36} {}", version, name, machine, path) +} + +fn format_file(file: &AtomicFile) -> Option { + let current = file.load().ok()?; + + if current.version == 0 { + return None; + } + + let mut split = current + .path + .file_name() + .expect("Not a file") + .to_str() + .unwrap() + .split("_"); + + let name = split.next().unwrap(); + + let machine = split.next().unwrap(); + let machine = &machine[..machine.len() - 2]; + + Some(format_line( + current.version, + name, + machine, + current.path.display(), + )) +} diff --git a/ark-cli/src/commands/link.rs b/ark-cli/src/commands/link.rs new file mode 100644 index 00000000..69c0247b --- /dev/null +++ b/ark-cli/src/commands/link.rs @@ -0,0 +1,51 @@ +use std::path::PathBuf; + +use arklib::{id::ResourceId, link::Link}; +use url::Url; + +use crate::provide_index; + +pub async fn create_link( + root: &PathBuf, + url: &str, + title: &str, + desc: Option, +) -> Result<(), String> { + let url = Url::parse(url).map_err(|_| "Invalid url")?; + let link: Link = Link::new(url, title.to_owned(), desc.to_owned()); + link.save(&root, true) + .await + .map_err(|e| e.to_string()) +} + +pub fn load_link( + root: &PathBuf, + file_path: &Option, + id: &Option, +) -> Result { + let path_from_index = id.map(|id| { + let index = provide_index(&root); + index.id2path[&id].as_path().to_path_buf() + }); + let path_from_user = file_path; + + let path = match (path_from_user, path_from_index) { + (Some(path), Some(path2)) => { + if path.canonicalize().unwrap() != path2 { + Err(format!( + "Path {:?} was requested. But id {} maps to path {:?}", + path, + id.unwrap(), + path2, + )) + } else { + Ok(path.to_path_buf()) + } + } + (Some(path), None) => Ok(path.to_path_buf()), + (None, Some(path)) => Ok(path), + (None, None) => Err("Provide a path or id for request.".to_owned())?, + }?; + + arklib::link::Link::load(root, &path).map_err(|e| e.to_string()) +} diff --git a/ark-cli/src/commands/mod.rs b/ark-cli/src/commands/mod.rs new file mode 100644 index 00000000..7ee11691 --- /dev/null +++ b/ark-cli/src/commands/mod.rs @@ -0,0 +1,2 @@ +pub mod file; +pub mod link; diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs index b926af7d..138b450c 100644 --- a/ark-cli/src/main.rs +++ b/ark-cli/src/main.rs @@ -2,7 +2,7 @@ use std::env::current_dir; use std::fs::{canonicalize, create_dir_all, metadata, File}; use std::io::prelude::*; use std::io::BufReader; -use std::path::{Display, Path, PathBuf}; +use std::path::{Path, PathBuf}; use std::str::FromStr; use std::thread; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; @@ -24,6 +24,9 @@ use std::io::{Result, Write}; use url::Url; use walkdir::WalkDir; +mod commands; +mod parsers; + #[derive(Parser, Debug)] #[clap(name = "ark-cli")] #[clap(about = "Manage ARK tag storages and indexes", long_about = None)] @@ -32,46 +35,6 @@ struct Cli { command: Command, } -#[derive(Debug)] -enum InsertContent { - Values(Vec<(String, String)>), - String(String), -} - -impl FromStr for InsertContent { - type Err = &'static str; - - fn from_str(s: &str) -> std::result::Result { - let pairs: Vec<&str> = s.split(',').collect(); - - if pairs.len() == 1 { - let key_value: Vec<&str> = pairs[0].split(':').collect(); - if key_value.len() == 2 { - let key = key_value[0].trim().to_string(); - let value = key_value[1].trim().to_string(); - return Ok(InsertContent::Values(vec![(key, value)])); - } else { - return Ok(InsertContent::String(s.to_string())); - } - } - - let mut values = Vec::new(); - - for pair in pairs { - let key_value: Vec<&str> = pair.split(':').collect(); - if key_value.len() == 2 { - let key = key_value[0].trim().to_string(); - let value = key_value[1].trim().to_string(); - values.push((key, value)); - } else { - return Err("Invalid key-value pair format"); - } - } - - Ok(InsertContent::Values(values)) - } -} - #[derive(Subcommand, Debug)] enum Command { Backup { @@ -106,30 +69,34 @@ enum Command { #[derive(Subcommand, Debug)] enum FileCommand { Append { - #[clap(parse(from_os_str))] - storage: Option, + storage: String, + + content: Option, - content: Option, + #[clap(short, long)] + format: Option, }, Insert { - #[clap(parse(from_os_str))] - storage: Option, + storage: String, + + content: Option, - content: Option, + #[clap(short, long)] + format: Option, }, Read { - #[clap(parse(from_os_str))] - storage: Option, + storage: String, + + key: Option, }, List { - #[clap(parse(from_os_str))] - storage: Option, + storage: String, #[clap(short, long)] - all: bool, + versions: bool, }, } @@ -283,27 +250,25 @@ async fn main() { desc, } => { let root = provide_root(root_dir); - - let url = Url::parse(url.as_deref().unwrap()); - let link: arklib::link::Link = arklib::link::Link::new( - url.unwrap(), - title.to_owned().unwrap(), - desc.to_owned(), - ); - - let future = link.save(&root, true); + let url = url.as_ref().expect("ERROR: Url was not provided"); + let title = title + .as_ref() + .expect("ERROR: Title was not provided"); println!("Saving link..."); - match future.await { + match commands::link::create_link( + &root, + url, + title, + desc.to_owned(), + ) + .await + { Ok(_) => { println!("Link saved successfully!"); - match provide_index(&root).store() { - Ok(_) => println!("Index stored successfully!"), - Err(e) => println!("Error: {}", e), - } } - Err(e) => println!("Error: {}", e), + Err(e) => println!("ERROR: {}", e), } } @@ -313,311 +278,165 @@ async fn main() { id, } => { let root = provide_root(root_dir); + let link = commands::link::load_link(&root, file_path, id); - let path_from_index = id.map(|id| { - let index = provide_index(&root); - index.id2path[&id].as_path().to_path_buf() - }); - let path_from_user = file_path; - - let path = match (path_from_user, path_from_index) { - (Some(path), Some(path2)) => { - if path.canonicalize().unwrap() != path2 { - println!("Path {:?} was requested.", path); - println!( - "But id {} maps to path {:?}", - id.unwrap(), - path2 - ); - panic!() - } else { - path.to_path_buf() - } + match link { + Ok(link) => { + println!("Link data:\n{:?}", link); } - (Some(path), None) => path.to_path_buf(), - (None, Some(path)) => path, - (None, None) => { - println!("Provide a path or id for request."); - panic!() - } - }; - - let link = arklib::link::Link::load(root, path); - println!("Link data:\n{:?}", link.unwrap()); + Err(e) => println!("ERROR: {}", e), + } } }, Command::File(file) => match &file { - FileCommand::Append { storage, content } => { - let root = provide_root(&None); - let storage = storage.as_ref().unwrap_or(&root); - let file_path = get_storage_from_path(storage) - .expect("Could not find storage folder"); - - let atomic_file = arklib::AtomicFile::new(file_path).unwrap(); - - if let Some(content) = content { - match content { - InsertContent::String(content) => { - modify(&atomic_file, |current| { - let mut combined_vec: Vec = - current.to_vec(); - combined_vec - .extend_from_slice(content.as_bytes()); - combined_vec - }) - .expect("Could not append string") - } - InsertContent::Values(values) => { - append_json(&atomic_file, values.to_vec()) - .expect("Could not append json"); - } - } - } else { - println!("Provide content to insert"); - } - } + FileCommand::Append { + storage, + content, + format, + } => { + let file_path = translate_storage(storage) + .expect("ERROR: Could not find storage folder"); - FileCommand::Insert { storage, content } => { - let root = provide_root(&None); - let storage = storage.as_ref().unwrap_or(&root); - let file_path = get_storage_from_path(storage) - .expect("Could not find storage folder"); - - let atomic_file = arklib::AtomicFile::new(file_path).unwrap(); - - if let Some(content) = content { - match content { - InsertContent::String(content) => { - modify(&atomic_file, |_| { - content.as_bytes().to_vec() - }) - .expect("Could not insert string"); - } - InsertContent::Values(values) => { - modify_json( - &atomic_file, - |current: &mut Option| { - let mut new = serde_json::Map::new(); - for (key, value) in values { - new.insert( - key.clone(), - serde_json::Value::String( - value.clone(), - ), - ); - } - *current = - Some(serde_json::Value::Object(new)); - }, - ) - .expect("Could not insert json"); - } - } - } else { - println!("Provide content to insert"); - } - } + let atomic_file = AtomicFile::new(&file_path) + .expect("ERROR: Could not create atomic file"); - FileCommand::Read { storage } => { - let root = provide_root(&None); - let storage = storage.as_ref().unwrap_or(&root); - let file_path = get_storage_from_path(storage) - .expect("Could not find storage folder"); + let format = parsers::get_format(&format) + .expect("ERROR: Format must be either 'json' or 'raw'"); - let atomic_file = arklib::AtomicFile::new(&file_path).unwrap(); + let content = content + .as_ref() + .expect("ERROR: Content was not provided"); - if let Some(file) = format_file(&atomic_file, true) { - println!("{}", file); - } else { - println!( - "FILE: {} is not a valid atomic file", - file_path.display() - ); - } + commands::file::file_append(&atomic_file, content, format) + .map_err(|e| println!("ERROR: {}", e)) + .unwrap(); } - FileCommand::List { storage, all } => { - let root = provide_root(&None); - let storage = storage.as_ref().unwrap_or(&root); - let file_path = get_storage_from_path(storage) - .expect("Could not find storage folder"); - - if !all { - let file = AtomicFile::new(&file_path).unwrap(); - if let Some(file) = format_file(&file, false) { - println!("{}", file); - } else { - println!( - "FILE: {} is not a valid atomic file", - file_path.display() + FileCommand::Insert { + storage, + content, + format, + } => { + let file_path = match translate_storage(storage) { + Some(path) => path, + None => { + let path = PathBuf::from_str(storage) + .expect("ERROR: Could not create storage path"); + create_dir_all(&path).expect( + "ERROR: Could not create storage directory", ); + path } - } else { - let files: Vec = WalkDir::new(file_path) - .into_iter() - .filter_entry(|e| e.file_type().is_dir()) - .filter_map(|v| v.ok()) - .filter_map(|e| match AtomicFile::new(e.path()) { - Ok(file) => Some(file), - Err(_) => None, - }) - .collect(); - - for file in files { - if let Some(file) = format_file(&file, false) { - println!("{}", file); - } + }; + + let atomic_file = AtomicFile::new(&file_path) + .expect("ERROR: Could not create atomic file"); + + let format = parsers::get_format(&format) + .expect("ERROR: Format must be either 'json' or 'raw'"); + + let content = content + .as_ref() + .expect("ERROR: Content was not provided"); + + match commands::file::file_insert(&atomic_file, content, format) + { + Ok(_) => { + println!("File inserted successfully!"); } + Err(e) => println!("ERROR: {}", e), } } - }, - } -} -pub fn append_json( - atomic_file: &AtomicFile, - data: Vec<(String, String)>, -) -> Result<()> { - modify_json(&atomic_file, |current: &mut Option| { - let current_data = match current { - Some(current) => { - if let Ok(value) = serde_json::to_value(current) { - match value { - serde_json::Value::Object(map) => Some(map), - _ => None, + FileCommand::Read { storage, key } => { + let file_path = translate_storage(storage) + .expect("ERROR: Could not find storage folder"); + + let atomic_file = AtomicFile::new(&file_path) + .expect("ERROR: Could not create atomic file"); + + match commands::file::file_read(&atomic_file, key) { + Ok(output) => { + println!("{}", output); } - } else { - None + Err(e) => println!("ERROR: {}", e), } } - None => None, - }; - let mut new = serde_json::Map::new(); - - if let None = current_data { - for (key, value) in &data { - new.insert( - key.clone(), - serde_json::Value::String(value.clone()), - ); - } - *current = Some(serde_json::Value::Object(new)); - } else if let Some(values) = current_data { - for (key, value) in &values { - new.insert(key.clone(), value.clone()); - } + FileCommand::List { storage, versions } => { + let file_path = translate_storage(storage) + .expect("ERROR: Could not find storage folder"); - for (key, value) in &data { - new.insert( - key.clone(), - serde_json::Value::String(value.clone()), - ); + match commands::file::file_list(file_path, versions) { + Ok(output) => { + println!("{}", output); + } + Err(e) => println!("ERROR: {}", e), + } } - *current = Some(serde_json::Value::Object(new)); - } - }) + }, + } } -fn get_storage_from_path(storage: &PathBuf) -> Option { - if storage.exists() { - Some(storage.clone()) - } else { - match storage - .clone() - .into_os_string() - .into_string() - .unwrap() - .to_lowercase() - .as_str() - { - "favorites" => Some( - provide_root(&None) - .join(ARK_FOLDER) - .join(FAVORITES_FILE), - ), - "device" => Some( - provide_root(&None) - .join(ARK_FOLDER) - .join(DEVICE_ID), - ), - "tage" => Some( - provide_root(&None) - .join(ARK_FOLDER) - .join(TAG_STORAGE_FILE), - ), - "score" => Some( - provide_root(&None) - .join(ARK_FOLDER) - .join(SCORE_STORAGE_FILE), - ), - "stats" => Some( - provide_root(&None) - .join(ARK_FOLDER) - .join(STATS_FOLDER), - ), - "properties" => Some( - provide_root(&None) - .join(ARK_FOLDER) - .join(PROPERTIES_STORAGE_FOLDER), - ), - "metadata" => Some( - provide_root(&None) - .join(ARK_FOLDER) - .join(METADATA_STORAGE_FOLDER), - ), - "previews" => Some( - provide_root(&None) - .join(ARK_FOLDER) - .join(PREVIEWS_STORAGE_FOLDER), - ), - "thumbnails" => Some( - provide_root(&None) - .join(ARK_FOLDER) - .join(THUMBNAILS_STORAGE_FOLDER), - ), - - _ => None, +fn translate_storage(storage: &String) -> Option { + if let Ok(path) = PathBuf::from_str(&storage) { + if path.exists() && path.is_dir() { + return Some(path); } } -} - -fn format_file(file: &AtomicFile, show_content: bool) -> Option { - let current = file.load().ok()?; - if current.version == 0 { - return None; + let root = provide_root(&None); + if let Some(file) = WalkDir::new(root) + .into_iter() + .filter_entry(|e| e.file_type().is_dir()) + .filter_map(|v| v.ok()) + .find(|f| { + f.file_name().to_str().unwrap().to_lowercase() == storage.as_str() + }) + { + return Some(file.path().to_path_buf()); } - let mut split = current - .path - .file_name() - .expect("Not a file") - .to_str() - .unwrap() - .split("_"); - - let mut output = format!( - "{}: [{} - {}]", - current.version, - split.next().unwrap(), - split.next().unwrap() - ); - - if show_content { - let data = current.read_to_string().ok()?; - if let Ok(json) = serde_json::from_str::(&data) { - output.push_str(&format!( - "\n\n{}", - serde_json::to_string_pretty(&json).unwrap() - )); - } else { - output.push_str(&format!("\n\n{}", data)); - } + match storage.to_lowercase().as_str() { + "tags" => Some( + provide_root(&None) + .join(ARK_FOLDER) + .join(TAG_STORAGE_FILE), + ), + "scores" => Some( + provide_root(&None) + .join(ARK_FOLDER) + .join(SCORE_STORAGE_FILE), + ), + "stats" => Some( + provide_root(&None) + .join(ARK_FOLDER) + .join(STATS_FOLDER), + ), + "properties" => Some( + provide_root(&None) + .join(ARK_FOLDER) + .join(PROPERTIES_STORAGE_FOLDER), + ), + "metadata" => Some( + provide_root(&None) + .join(ARK_FOLDER) + .join(METADATA_STORAGE_FOLDER), + ), + "previews" => Some( + provide_root(&None) + .join(ARK_FOLDER) + .join(PREVIEWS_STORAGE_FOLDER), + ), + "thumbnails" => Some( + provide_root(&None) + .join(ARK_FOLDER) + .join(THUMBNAILS_STORAGE_FOLDER), + ), + _ => None, } - - Some(output) + .filter(|path| path.exists() && path.is_dir()) } fn discover_roots(roots_cfg: &Option) -> Vec { @@ -758,3 +577,40 @@ fn timestamp() -> Duration { .duration_since(UNIX_EPOCH) .expect("Time went backwards!"); } + +// createa test for the transalte_storage function +// Define the test module +#[cfg(test)] +mod tests { + // Import necessary items for testing + use super::*; + + // Define a test function + #[test] + fn test_translate_storage() { + let test_dir = + provide_root(&None).join(PathBuf::from_str("./test_dir").unwrap()); + let ark_dir = test_dir.join(ARK_FOLDER); + + // Creating a test atomic file + let hello_dir = ark_dir.join("hello"); + create_dir_all(&hello_dir).unwrap(); + + assert_eq!( + translate_storage(&"hello".to_string()) + .unwrap_or(PathBuf::from_str(".").unwrap()), + hello_dir + ); + + assert!( + translate_storage(&"./test_dir/.ark/hello".to_string()).is_some() + ); + + assert!(translate_storage(&"./test_dir/.ark/nonexist".to_string()) + .is_none()); + + assert!(translate_storage(&"metadata".to_string()).is_some()); + + assert!(translate_storage(&"properties".to_string()).is_some()); + } +} diff --git a/ark-cli/src/parsers/mod.rs b/ark-cli/src/parsers/mod.rs new file mode 100644 index 00000000..171672c6 --- /dev/null +++ b/ark-cli/src/parsers/mod.rs @@ -0,0 +1,36 @@ +pub enum Format { + Json, + Raw, +} + +pub fn key_value_to_str(s: &str) -> Result, String> { + let pairs: Vec<&str> = s.split(',').collect(); + + let mut values = Vec::new(); + + for pair in pairs { + let key_value: Vec<&str> = pair.split(':').collect(); + if key_value.len() == 2 { + let key = key_value[0].trim().to_string(); + let value = key_value[1].trim().to_string(); + values.push((key, value)); + } else { + return Err("Invalid key-value pair format".to_owned()); + } + } + + Ok(values) +} + +pub fn get_format(s: &Option) -> Option { + match s { + Some(value) => { + if value.to_lowercase() == "json" { + Some(Format::Json) + } else { + None + } + } + None => Some(Format::Raw), + } +} From e2ecaaedd0909c01ed1bd8f8f69d58a3115beb0e Mon Sep 17 00:00:00 2001 From: Alvinosh Date: Sat, 27 Jan 2024 16:42:57 +0100 Subject: [PATCH 18/23] Storage abstraction --- ark-cli/src/commands/file.rs | 112 +-------- ark-cli/src/commands/link.rs | 2 +- ark-cli/src/main.rs | 442 +++++++++++++---------------------- ark-cli/src/parsers/mod.rs | 4 +- ark-cli/src/storage.rs | 403 ++++++++++++++++++++++++++++++++ ark-cli/src/util.rs | 150 ++++++++++++ 6 files changed, 725 insertions(+), 388 deletions(-) create mode 100644 ark-cli/src/storage.rs create mode 100644 ark-cli/src/util.rs diff --git a/ark-cli/src/commands/file.rs b/ark-cli/src/commands/file.rs index afdc6051..fe1ab372 100644 --- a/ark-cli/src/commands/file.rs +++ b/ark-cli/src/commands/file.rs @@ -1,7 +1,6 @@ use crate::parsers::{self, Format}; use arklib::{modify, modify_json, AtomicFile}; -use std::{fmt::Write, path::PathBuf, process::Output}; -use walkdir::WalkDir; + pub fn file_append( atomic_file: &AtomicFile, @@ -15,7 +14,7 @@ pub fn file_append( combined_vec }) .map_err(|_| "ERROR: Could not append string".to_string()), - parsers::Format::Json => { + parsers::Format::KeyValue => { let values = parsers::key_value_to_str(&content) .map_err(|_| "ERROR: Could not parse json".to_string())?; @@ -35,7 +34,7 @@ pub fn file_insert( modify(&atomic_file, |_| content.as_bytes().to_vec()) .map_err(|_| "ERROR: Could not insert string".to_string()) } - parsers::Format::Json => { + parsers::Format::KeyValue => { let values = parsers::key_value_to_str(&content) .map_err(|_| "ERROR: Could not parse json".to_string())?; @@ -52,105 +51,11 @@ pub fn file_insert( *current = Some(serde_json::Value::Object(new)); }, ) - .map_err(|_| "ERROR:Could not insert json".to_string()) - } - } -} - -pub fn file_read( - atomic_file: &AtomicFile, - key: &Option, -) -> Result { - if let Some(file) = format_file(&atomic_file) { - let mut output = String::new(); - writeln!( - output, - "{}", - format_line("version", "name", "machine", "path"), - ) - .map_err(|_| "Could not write to output".to_string())?; - - writeln!(output, "{}", file) - .map_err(|_| "Could not write to output".to_string())?; - - let current = atomic_file - .load() - .map_err(|_| "Could not load atomic file.".to_string())?; - - let data = current - .read_to_string() - .map_err(|_| "Could not read atomic file content.".to_string())?; - - if let Ok(json) = serde_json::from_str::(&data) { - if let Some(key) = key { - if let Some(value) = json.get(key) { - writeln!(output, "\n{}", value) - .map_err(|_| "Could not write to output".to_string())?; - } else { - return Err(format!("Key {} not found", key)); - } - } else { - writeln!( - output, - "\n{}", - serde_json::to_string_pretty(&json).unwrap() - ) - .map_err(|_| "Could not write to output".to_string())?; - } - } else { - writeln!(output, "\n{}", data) - .map_err(|_| "Could not write to output".to_string())?; + .map_err(|e| e.to_string()) } - Ok(output) - } else { - Err("File not found".to_string()) } } -pub fn file_list(path: PathBuf, versions: &bool) -> Result { - let mut output = String::new(); - - let files: Vec = WalkDir::new(path) - .min_depth(1) - .max_depth(1) - .into_iter() - .filter_entry(|e| e.file_type().is_dir()) - .filter_map(|v| v.ok()) - .filter_map(|e| match AtomicFile::new(e.path()) { - Ok(file) => Some(file), - Err(_) => None, - }) - .collect(); - - if *versions { - writeln!( - output, - "{}", - format_line("version", "name", "machine", "path"), - ); - - for file in files { - if let Some(file) = format_file(&file) { - writeln!(output, "{}", file); - } - } - } else { - for file in files { - write!( - output, - "{} ", - file.directory - .file_name() - .unwrap() - .to_str() - .unwrap() - ); - } - } - - Ok(output) -} - fn append_json( atomic_file: &AtomicFile, data: Vec<(String, String)>, @@ -198,7 +103,12 @@ fn append_json( Ok(()) } -fn format_line(version: A, name: B, machine: C, path: D) -> String +pub fn format_line( + version: A, + name: B, + machine: C, + path: D, +) -> String where A: std::fmt::Display, B: std::fmt::Display, @@ -208,7 +118,7 @@ where format!("{: <8} {: <14} {: <36} {}", version, name, machine, path) } -fn format_file(file: &AtomicFile) -> Option { +pub fn format_file(file: &AtomicFile) -> Option { let current = file.load().ok()?; if current.version == 0 { diff --git a/ark-cli/src/commands/link.rs b/ark-cli/src/commands/link.rs index 69c0247b..182580fe 100644 --- a/ark-cli/src/commands/link.rs +++ b/ark-cli/src/commands/link.rs @@ -3,7 +3,7 @@ use std::path::PathBuf; use arklib::{id::ResourceId, link::Link}; use url::Url; -use crate::provide_index; +use crate::util::provide_index; pub async fn create_link( root: &PathBuf, diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs index 138b450c..ebe6b4bc 100644 --- a/ark-cli/src/main.rs +++ b/ark-cli/src/main.rs @@ -1,15 +1,5 @@ -use std::env::current_dir; -use std::fs::{canonicalize, create_dir_all, metadata, File}; -use std::io::prelude::*; -use std::io::BufReader; -use std::path::{Path, PathBuf}; -use std::str::FromStr; -use std::thread; -use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; - use arklib::app_id; use arklib::id::ResourceId; -use arklib::index::ResourceIndex; use arklib::pdf::PDFQuality; use arklib::{ modify, AtomicFile, APP_ID_FILE, ARK_FOLDER, FAVORITES_FILE, @@ -20,12 +10,22 @@ use arklib::{ use clap::{Parser, Subcommand}; use fs_extra::dir::{self, CopyOptions}; use home::home_dir; -use std::io::{Result, Write}; -use url::Url; -use walkdir::WalkDir; +use std::fs::{create_dir_all, File}; +use std::io::Write; +use std::path::PathBuf; +use std::str::FromStr; +use storage::StorageType; + +use crate::parsers::Format; +use crate::storage::Storage; +use util::{ + discover_roots, monitor_index, provide_root, storages_exists, timestamp, +}; mod commands; mod parsers; +mod storage; +mod util; #[derive(Parser, Debug)] #[clap(name = "ark-cli")] @@ -64,6 +64,22 @@ enum Command { #[clap(subcommand)] File(FileCommand), + + #[clap(subcommand)] + Storage(StorageCommand), +} + +#[derive(Subcommand, Debug)] +enum StorageCommand { + List { + storage: String, + + #[clap(short, long)] + versions: bool, + + #[clap(short, long)] + type_: Option, + }, } #[derive(Subcommand, Debug)] @@ -71,32 +87,38 @@ enum FileCommand { Append { storage: String, - content: Option, + id: String, + + content: String, #[clap(short, long)] format: Option, + + #[clap(short, long)] + type_: Option, }, Insert { storage: String, - content: Option, + id: String, + + content: String, #[clap(short, long)] format: Option, + + #[clap(short, long)] + type_: Option, }, Read { storage: String, - key: Option, - }, - - List { - storage: String, + id: String, #[clap(short, long)] - versions: bool, + type_: Option, }, } @@ -212,14 +234,11 @@ async fn main() { println!("Backup created:\n\t{}", backup_dir.display()); } - Command::Collisions { root_dir } => monitor_index(&root_dir, None), - Command::Monitor { root_dir, interval } => { let millis = interval.unwrap_or(1000); monitor_index(&root_dir, Some(millis)) } - Command::Render { path, quality } => { let filepath = path.to_owned().unwrap(); let quality = match quality.to_owned().unwrap().as_str() { @@ -241,7 +260,6 @@ async fn main() { let img = arklib::pdf::render_preview_page(buf, quality); img.save(PathBuf::from(dest_path)).unwrap(); } - Command::Link(link) => match &link { Link::Create { root_dir, @@ -288,329 +306,185 @@ async fn main() { } } }, - Command::File(file) => match &file { FileCommand::Append { storage, + id, content, format, + type_, } => { - let file_path = translate_storage(storage) + let (file_path, storage_type) = translate_storage(storage) .expect("ERROR: Could not find storage folder"); - let atomic_file = AtomicFile::new(&file_path) - .expect("ERROR: Could not create atomic file"); + let storage_type = storage_type.unwrap_or(match type_ { + Some(type_) => match type_.to_lowercase().as_str() { + "file" => StorageType::File, + "folder" => StorageType::Folder, + _ => panic!("unknown storage type"), + }, + None => StorageType::File, + }); + + let format = + parsers::get_format(&format).unwrap_or(Format::Raw); - let format = parsers::get_format(&format) - .expect("ERROR: Format must be either 'json' or 'raw'"); + let mut storage = Storage::new(file_path, storage_type) + .expect("ERROR: Could not create storage"); - let content = content - .as_ref() - .expect("ERROR: Content was not provided"); + let resource_id = ResourceId::from_str(id) + .expect("ERROR: Could not parse id"); - commands::file::file_append(&atomic_file, content, format) - .map_err(|e| println!("ERROR: {}", e)) + storage + .append(resource_id, content, format) .unwrap(); } FileCommand::Insert { storage, + id, content, format, + type_, } => { - let file_path = match translate_storage(storage) { - Some(path) => path, - None => { - let path = PathBuf::from_str(storage) - .expect("ERROR: Could not create storage path"); - create_dir_all(&path).expect( - "ERROR: Could not create storage directory", - ); - path - } - }; + let (file_path, storage_type) = translate_storage(storage) + .expect("ERROR: Could not find storage folder"); - let atomic_file = AtomicFile::new(&file_path) - .expect("ERROR: Could not create atomic file"); + let storage_type = storage_type.unwrap_or(match type_ { + Some(type_) => match type_.to_lowercase().as_str() { + "file" => StorageType::File, + "folder" => StorageType::Folder, + _ => panic!("unknown storage type"), + }, + None => StorageType::File, + }); - let format = parsers::get_format(&format) - .expect("ERROR: Format must be either 'json' or 'raw'"); + let format = + parsers::get_format(&format).unwrap_or(Format::Raw); - let content = content - .as_ref() - .expect("ERROR: Content was not provided"); + let mut storage = Storage::new(file_path, storage_type) + .expect("ERROR: Could not create storage"); - match commands::file::file_insert(&atomic_file, content, format) - { - Ok(_) => { - println!("File inserted successfully!"); - } - Err(e) => println!("ERROR: {}", e), - } + let resource_id = ResourceId::from_str(id) + .expect("ERROR: Could not parse id"); + + storage + .insert(resource_id, content, format) + .unwrap(); } - FileCommand::Read { storage, key } => { - let file_path = translate_storage(storage) + FileCommand::Read { storage, id, type_ } => { + let (file_path, storage_type) = translate_storage(storage) .expect("ERROR: Could not find storage folder"); - let atomic_file = AtomicFile::new(&file_path) - .expect("ERROR: Could not create atomic file"); + let storage_type = storage_type.unwrap_or(match type_ { + Some(type_) => match type_.to_lowercase().as_str() { + "file" => StorageType::File, + "folder" => StorageType::Folder, + _ => panic!("unknown storage type"), + }, + None => StorageType::File, + }); - match commands::file::file_read(&atomic_file, key) { - Ok(output) => { - println!("{}", output); - } + let mut storage = Storage::new(file_path, storage_type) + .expect("ERROR: Could not create storage"); + + let resource_id = ResourceId::from_str(id) + .expect("ERROR: Could not parse id"); + + let output = storage.read(resource_id); + + match output { + Ok(output) => println!("{}", output), Err(e) => println!("ERROR: {}", e), } } - - FileCommand::List { storage, versions } => { - let file_path = translate_storage(storage) + }, + Command::Storage(cmd) => match &cmd { + StorageCommand::List { + storage, + type_, + versions, + } => { + let (file_path, storage_type) = translate_storage(storage) .expect("ERROR: Could not find storage folder"); - match commands::file::file_list(file_path, versions) { - Ok(output) => { - println!("{}", output); - } - Err(e) => println!("ERROR: {}", e), - } + let storage_type = storage_type.unwrap_or(match type_ { + Some(type_) => match type_.to_lowercase().as_str() { + "file" => StorageType::File, + "folder" => StorageType::Folder, + _ => panic!("unknown storage type"), + }, + None => StorageType::File, + }); + + let mut storage = Storage::new(file_path, storage_type) + .expect("ERROR: Could not create storage"); + + storage + .load() + .expect("ERROR: Could not load storage"); + + let output = storage + .list(*versions) + .expect("ERROR: Could not list storage content"); + + println!("{}", output); } }, } } -fn translate_storage(storage: &String) -> Option { - if let Ok(path) = PathBuf::from_str(&storage) { +fn translate_storage(storage: &str) -> Option<(PathBuf, Option)> { + if let Ok(path) = PathBuf::from_str(storage) { if path.exists() && path.is_dir() { - return Some(path); + return Some((path, None)); } } - let root = provide_root(&None); - if let Some(file) = WalkDir::new(root) - .into_iter() - .filter_entry(|e| e.file_type().is_dir()) - .filter_map(|v| v.ok()) - .find(|f| { - f.file_name().to_str().unwrap().to_lowercase() == storage.as_str() - }) - { - return Some(file.path().to_path_buf()); - } - match storage.to_lowercase().as_str() { - "tags" => Some( + "tags" => Some(( provide_root(&None) .join(ARK_FOLDER) .join(TAG_STORAGE_FILE), - ), - "scores" => Some( + Some(StorageType::File), + )), + "scores" => Some(( provide_root(&None) .join(ARK_FOLDER) .join(SCORE_STORAGE_FILE), - ), - "stats" => Some( + Some(StorageType::File), + )), + "stats" => Some(( provide_root(&None) .join(ARK_FOLDER) .join(STATS_FOLDER), - ), - "properties" => Some( + Some(StorageType::Folder), + )), + "properties" => Some(( provide_root(&None) .join(ARK_FOLDER) .join(PROPERTIES_STORAGE_FOLDER), - ), - "metadata" => Some( + Some(StorageType::Folder), + )), + "metadata" => Some(( provide_root(&None) .join(ARK_FOLDER) .join(METADATA_STORAGE_FOLDER), - ), - "previews" => Some( + Some(StorageType::Folder), + )), + "previews" => Some(( provide_root(&None) .join(ARK_FOLDER) .join(PREVIEWS_STORAGE_FOLDER), - ), - "thumbnails" => Some( + Some(StorageType::Folder), + )), + "thumbnails" => Some(( provide_root(&None) .join(ARK_FOLDER) .join(THUMBNAILS_STORAGE_FOLDER), - ), + Some(StorageType::Folder), + )), _ => None, } - .filter(|path| path.exists() && path.is_dir()) -} - -fn discover_roots(roots_cfg: &Option) -> Vec { - if let Some(path) = roots_cfg { - println!( - "\tRoots config provided explicitly:\n\t\t{}", - path.display() - ); - let config = File::open(&path).expect("File doesn't exist!"); - - parse_roots(config) - } else { - if let Ok(config) = File::open(&ARK_CONFIG) { - println!( - "\tRoots config was found automatically:\n\t\t{}", - &ARK_CONFIG - ); - - parse_roots(config) - } else { - println!("\tRoots config wasn't found."); - - println!("Looking for a folder containing tag storage:"); - let path = canonicalize( - current_dir().expect("Can't open current directory!"), - ) - .expect("Couldn't canonicalize working directory!"); - - let result = path.ancestors().find(|path| { - println!("\t{}", path.display()); - storages_exists(path) - }); - - if let Some(root) = result { - println!("Root folder found:\n\t{}", root.display()); - vec![root.to_path_buf()] - } else { - println!("Root folder wasn't found."); - vec![] - } - } - } -} - -fn provide_root(root_dir: &Option) -> PathBuf { - if let Some(path) = root_dir { - path.clone() - } else { - current_dir() - .expect("Can't open current directory!") - .clone() - } -} - -// Read-only structure -fn provide_index(root_dir: &PathBuf) -> ResourceIndex { - let rwlock = - arklib::provide_index(root_dir).expect("Failed to retrieve index"); - let index = &*rwlock.read().unwrap(); - index.clone() -} - -fn monitor_index(root_dir: &Option, interval: Option) { - let dir_path = provide_root(root_dir); - - println!("Building index of folder {}", dir_path.display()); - let start = Instant::now(); - let dir_path = provide_root(root_dir); - let result = arklib::provide_index(dir_path); - let duration = start.elapsed(); - - match result { - Ok(rwlock) => { - println!("Build succeeded in {:?}\n", duration); - - if let Some(millis) = interval { - let mut index = rwlock.write().unwrap(); - loop { - let pause = Duration::from_millis(millis); - thread::sleep(pause); - - let start = Instant::now(); - match index.update_all() { - Err(msg) => println!("Oops! {}", msg), - Ok(diff) => { - index.store().expect("Could not store index"); - let duration = start.elapsed(); - println!("Updating succeeded in {:?}\n", duration); - - if !diff.deleted.is_empty() { - println!("Deleted: {:?}", diff.deleted); - } - if !diff.added.is_empty() { - println!("Added: {:?}", diff.added); - } - } - } - } - } else { - let index = rwlock.read().unwrap(); - - println!("Here are {} entries in the index", index.size()); - - for (key, count) in index.collisions.iter() { - println!("Id {:?} calculated {} times", key, count); - } - } - } - Err(err) => println!("Failure: {:?}", err), - } -} - -fn storages_exists(path: &Path) -> bool { - let meta = metadata(path.join(&arklib::ARK_FOLDER)); - if let Ok(meta) = meta { - return meta.is_dir(); - } - - false -} - -fn parse_roots(config: File) -> Vec { - return BufReader::new(config) - .lines() - .filter_map(|line| match line { - Ok(path) => Some(PathBuf::from(path)), - Err(msg) => { - println!("{:?}", msg); - None - } - }) - .collect(); -} - -fn timestamp() -> Duration { - let start = SystemTime::now(); - return start - .duration_since(UNIX_EPOCH) - .expect("Time went backwards!"); -} - -// createa test for the transalte_storage function -// Define the test module -#[cfg(test)] -mod tests { - // Import necessary items for testing - use super::*; - - // Define a test function - #[test] - fn test_translate_storage() { - let test_dir = - provide_root(&None).join(PathBuf::from_str("./test_dir").unwrap()); - let ark_dir = test_dir.join(ARK_FOLDER); - - // Creating a test atomic file - let hello_dir = ark_dir.join("hello"); - create_dir_all(&hello_dir).unwrap(); - - assert_eq!( - translate_storage(&"hello".to_string()) - .unwrap_or(PathBuf::from_str(".").unwrap()), - hello_dir - ); - - assert!( - translate_storage(&"./test_dir/.ark/hello".to_string()).is_some() - ); - - assert!(translate_storage(&"./test_dir/.ark/nonexist".to_string()) - .is_none()); - - assert!(translate_storage(&"metadata".to_string()).is_some()); - - assert!(translate_storage(&"properties".to_string()).is_some()); - } } diff --git a/ark-cli/src/parsers/mod.rs b/ark-cli/src/parsers/mod.rs index 171672c6..40727db9 100644 --- a/ark-cli/src/parsers/mod.rs +++ b/ark-cli/src/parsers/mod.rs @@ -1,5 +1,5 @@ pub enum Format { - Json, + KeyValue, Raw, } @@ -26,7 +26,7 @@ pub fn get_format(s: &Option) -> Option { match s { Some(value) => { if value.to_lowercase() == "json" { - Some(Format::Json) + Some(Format::KeyValue) } else { None } diff --git a/ark-cli/src/storage.rs b/ark-cli/src/storage.rs new file mode 100644 index 00000000..59c8755d --- /dev/null +++ b/ark-cli/src/storage.rs @@ -0,0 +1,403 @@ +use arklib::{id::ResourceId, AtomicFile}; +use std::fmt::Write; +use std::path::PathBuf; + +use crate::{ + commands::{ + self, + file::{format_file, format_line}, + }, + parsers::Format, +}; + +#[derive(Debug)] +pub enum StorageType { + File, + Folder, +} + +pub struct Storage { + path: PathBuf, + storage_type: StorageType, + files: Vec, +} + +impl Storage { + pub fn new>( + path: P, + storage_type: StorageType, + ) -> Result { + let path = path.into(); + + if !path.exists() { + std::fs::create_dir_all(&path).map_err(|e| { + format!( + "Failed to create storage folder at {:?} with error: {:?}", + path, e + ) + })?; + } + + Ok(Self { + path: path.into(), + storage_type, + files: Vec::new(), + }) + } + + #[allow(dead_code)] + pub fn load(&mut self) -> Result<(), String> { + match self.storage_type { + StorageType::File => { + let atomic_file = + AtomicFile::new(self.path.clone()).map_err(|e| { + format!( + "Failed to create atomic file at {:?} with error: {:?}", + self.path, e + ) + })?; + + let atomic_file_data = atomic_file.load().map_err(|e| { + format!( + "Failed to load atomic file at {:?} with error: {:?}", + self.path, e + ) + })?; + + let data = atomic_file_data.read_to_string().map_err(|_| { + "Could not read atomic file content.".to_string() + })?; + + for (i, line) in data.lines().enumerate() { + let mut line = line.split(':'); + let id = line.next().unwrap(); + let id = id.parse::().map_err(|_| { + format!("Failed to parse ResourceId from line: {i}",) + })?; + self.files.push(id); + } + } + StorageType::Folder => { + let folder_entries = + std::fs::read_dir(&self.path).map_err(|e| { + format!( + "Failed to read folder at {:?} with error: {:?}", + self.path, e + ) + })?; + + for entry in folder_entries { + let entry = entry.map_err(|e| { + format!("Error reading folder entry: {:?}", e) + })?; + + if let Some(file_name) = entry.file_name().to_str() { + let id = file_name.parse::().map_err(|_| { + format!("Failed to parse ResourceId from folder entry: {:?}", file_name) + })?; + self.files.push(id); + } + } + } + }; + + Ok(()) + } + + pub fn append( + &mut self, + id: ResourceId, + content: &str, + format: Format, + ) -> Result<(), String> { + match self.storage_type { + StorageType::File => { + let atomic_file = AtomicFile::new(&self.path) + // .expect("ERROR: Could not create atomic file"); + .map_err(|e| { + format!( + "Failed to create atomic file at {} with error: {:?}", + self.path.display(), e + ) + })?; + + let content = match format { + Format::KeyValue => return Err( + "Key value format is not supported for file storage" + .to_owned(), + ), + Format::Raw => format!("\n{}:{}", id, content), + }; + + match commands::file::file_append( + &atomic_file, + &content, + crate::parsers::Format::Raw, + ) { + Ok(_) => { + return Ok(()); + } + Err(e) => { + return Err(e); + } + } + } + StorageType::Folder => { + let folder_path = self.path.join(id.to_string()); + if !folder_path.exists() { + std::fs::create_dir_all(&folder_path).map_err(|e| { + format!( + "Failed to create folder at {:?} with error: {:?}", + folder_path, e + ) + })?; + } + + let atomic_file = AtomicFile::new(&folder_path) + .map_err(|e| { + format!( + "Failed to create atomic file at {} with error: {:?}", + self.path.display(), e + ) + })?; + + match commands::file::file_append( + &atomic_file, + &content, + format, + ) { + Ok(_) => { + return Ok(()); + } + Err(e) => { + return Err(e); + } + } + } + }; + } + + pub fn read(&mut self, id: ResourceId) -> Result { + match self.storage_type { + StorageType::File => { + let atomic_file = AtomicFile::new(&self.path).map_err(|e| { + format!( + "Failed to create atomic file at {} with error: {:?}", + self.path.display(), + e + ) + })?; + + let atomic_file_data = atomic_file.load().map_err(|e| { + format!( + "Failed to load atomic file at {:?} with error: {:?}", + self.path, e + ) + })?; + + let data = atomic_file_data.read_to_string().map_err(|_| { + "Could not read atomic file content.".to_string() + })?; + + for (i, line) in data.lines().enumerate() { + let mut line = line.split(':'); + let line_id: &str = line.next().unwrap(); + let line_id = line_id.parse::().map_err(|_| { + format!("Failed to parse ResourceId from line: {i}",) + })?; + + if id == line_id { + let data = line.next().unwrap(); + return Ok(format!("{}", data)); + } + } + + Err(format!("Resource with id {} not found", id)) + } + StorageType::Folder => { + let folder_path = self.path.join(id.to_string()); + if !folder_path.exists() { + return Err(format!("Resource with id {} not found", id)); + } + + let atomic_file = AtomicFile::new(&folder_path) + .map_err(|e| { + format!( + "Failed to create atomic file at {} with error: {:?}", + self.path.display(), e + ) + })?; + + let atomic_file_data = atomic_file.load().map_err(|e| { + format!( + "Failed to load atomic file at {:?} with error: {:?}", + self.path, e + ) + })?; + + let data = atomic_file_data.read_to_string().map_err(|_| { + "Could not read atomic file content.".to_string() + })?; + + Ok(data) + } + } + } + + pub fn insert( + &mut self, + id: ResourceId, + content: &str, + format: Format, + ) -> Result<(), String> { + match self.storage_type { + StorageType::File => { + let atomic_file = AtomicFile::new(&self.path).map_err(|e| { + format!( + "Failed to create atomic file at {} with error: {:?}", + self.path.display(), + e + ) + })?; + + let content = match format { + Format::KeyValue => return Err( + "Key value format is not supported for file storage" + .to_owned(), + ), + Format::Raw => format!("{}:{}", id, content), + }; + + match commands::file::file_insert( + &atomic_file, + &content, + crate::parsers::Format::Raw, + ) { + Ok(_) => { + return Ok(()); + } + Err(e) => { + return Err(e); + } + } + } + StorageType::Folder => { + let folder_path = self.path.join(id.to_string()); + if !folder_path.exists() { + std::fs::create_dir_all(&folder_path).map_err(|e| { + format!( + "Failed to create folder at {:?} with error: {:?}", + folder_path, e + ) + })?; + } + + let atomic_file = AtomicFile::new(&folder_path) + .map_err(|e| { + format!( + "Failed to create atomic file at {} with error: {:?}", + self.path.display(), e + ) + })?; + + match commands::file::file_insert( + &atomic_file, + &content, + format, + ) { + Ok(_) => { + return Ok(()); + } + Err(e) => { + return Err(e); + } + } + } + }; + } + + pub fn list(&self, versions: bool) -> Result { + let mut output = String::new(); + + if !versions { + for id in &self.files { + writeln!(output, "{}", id) + .map_err(|_| "Could not write to output".to_string())?; + } + } else { + match self.storage_type { + StorageType::File => { + let atomic_file = AtomicFile::new(&self.path) + .map_err(|e| { + format!( + "Failed to create atomic file at {} with error: {:?}", + self.path.display(), e + ) + })?; + + let atomic_file_data = atomic_file.load().map_err(|e| { + format!( + "Failed to load atomic file at {:?} with error: {:?}", + self.path, e + ) + })?; + + writeln!(output, "{: <16} {}", "id", "value") + .map_err(|_| "Could not write to output".to_string())?; + + let data = + atomic_file_data.read_to_string().map_err(|_| { + "Could not read atomic file content.".to_string() + })?; + + for line in data.lines() { + let mut line = line.split(':'); + let id = line.next().unwrap(); + let data = line.next().unwrap(); + writeln!(output, "{: <16} {}", id, data).map_err( + |_| "Could not write to output".to_string(), + )?; + } + } + StorageType::Folder => { + let folder_entries = std::fs::read_dir(&self.path) + .map_err(|e| { + format!( + "Failed to read folder at {:?} with error: {:?}", + self.path, e + ) + })? + .filter_map(|v| v.ok()) + .filter(|e| { + if let Ok(ftype) = e.file_type() { + ftype.is_dir() + } else { + false + } + }) + .filter_map(|e| match AtomicFile::new(e.path()) { + Ok(file) => Some(file), + Err(_) => None, + }); + + writeln!( + output, + "{}", + format_line("version", "name", "machine", "path"), + ) + .map_err(|_| "Could not write to output".to_string())?; + + for entry in folder_entries { + if let Some(file) = format_file(&entry) { + writeln!(output, "{}", file).map_err(|_| { + "Could not write to output".to_string() + })?; + } + } + } + }; + } + + Ok(output) + } +} diff --git a/ark-cli/src/util.rs b/ark-cli/src/util.rs new file mode 100644 index 00000000..d266aab6 --- /dev/null +++ b/ark-cli/src/util.rs @@ -0,0 +1,150 @@ +use arklib::index::ResourceIndex; +use std::env::current_dir; +use std::fs::{canonicalize, metadata}; +use std::io::BufRead; +use std::io::BufReader; +use std::path::Path; +use std::thread; +use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; +use std::{fs::File, path::PathBuf}; + +use crate::ARK_CONFIG; + +pub fn discover_roots(roots_cfg: &Option) -> Vec { + if let Some(path) = roots_cfg { + println!( + "\tRoots config provided explicitly:\n\t\t{}", + path.display() + ); + let config = File::open(&path).expect("File doesn't exist!"); + + parse_roots(config) + } else { + if let Ok(config) = File::open(&ARK_CONFIG) { + println!( + "\tRoots config was found automatically:\n\t\t{}", + &ARK_CONFIG + ); + + parse_roots(config) + } else { + println!("\tRoots config wasn't found."); + + println!("Looking for a folder containing tag storage:"); + let path = canonicalize( + current_dir().expect("Can't open current directory!"), + ) + .expect("Couldn't canonicalize working directory!"); + + let result = path.ancestors().find(|path| { + println!("\t{}", path.display()); + storages_exists(path) + }); + + if let Some(root) = result { + println!("Root folder found:\n\t{}", root.display()); + vec![root.to_path_buf()] + } else { + println!("Root folder wasn't found."); + vec![] + } + } + } +} + +pub fn provide_root(root_dir: &Option) -> PathBuf { + if let Some(path) = root_dir { + path.clone() + } else { + current_dir() + .expect("Can't open current directory!") + .clone() + } +} + +// Read-only structure +pub fn provide_index(root_dir: &PathBuf) -> ResourceIndex { + let rwlock = + arklib::provide_index(root_dir).expect("Failed to retrieve index"); + let index = &*rwlock.read().unwrap(); + index.clone() +} + +pub fn monitor_index(root_dir: &Option, interval: Option) { + let dir_path = provide_root(root_dir); + + println!("Building index of folder {}", dir_path.display()); + let start = Instant::now(); + let dir_path = provide_root(root_dir); + let result = arklib::provide_index(dir_path); + let duration = start.elapsed(); + + match result { + Ok(rwlock) => { + println!("Build succeeded in {:?}\n", duration); + + if let Some(millis) = interval { + let mut index = rwlock.write().unwrap(); + loop { + let pause = Duration::from_millis(millis); + thread::sleep(pause); + + let start = Instant::now(); + match index.update_all() { + Err(msg) => println!("Oops! {}", msg), + Ok(diff) => { + index.store().expect("Could not store index"); + let duration = start.elapsed(); + println!("Updating succeeded in {:?}\n", duration); + + if !diff.deleted.is_empty() { + println!("Deleted: {:?}", diff.deleted); + } + if !diff.added.is_empty() { + println!("Added: {:?}", diff.added); + } + } + } + } + } else { + let index = rwlock.read().unwrap(); + + println!("Here are {} entries in the index", index.size()); + + for (key, count) in index.collisions.iter() { + println!("Id {:?} calculated {} times", key, count); + } + } + } + Err(err) => println!("Failure: {:?}", err), + } +} + +pub fn storages_exists(path: &Path) -> bool { + let meta = metadata(path.join(&arklib::ARK_FOLDER)); + if let Ok(meta) = meta { + return meta.is_dir(); + } + + false +} + +pub fn parse_roots(config: File) -> Vec { + return BufReader::new(config) + .lines() + .filter_map(|line| match line { + Ok(path) => Some(PathBuf::from(path)), + Err(msg) => { + println!("{:?}", msg); + None + } + }) + .collect(); +} + +pub fn timestamp() -> Duration { + let start = SystemTime::now(); + return start + .duration_since(UNIX_EPOCH) + .expect("Time went backwards!"); +} From b3112c19314097e77ef3e7a6a8e572a77a333588 Mon Sep 17 00:00:00 2001 From: Alvinosh Date: Tue, 13 Feb 2024 16:23:49 +0100 Subject: [PATCH 19/23] Add `list` command --- ark-cli/Cargo.lock | 62 ++++++++++++ ark-cli/Cargo.toml | 3 +- ark-cli/src/main.rs | 225 ++++++++++++++++++++++++++++++-------------- ark-cli/src/util.rs | 93 ++++++++++++++++++ 4 files changed, 309 insertions(+), 74 deletions(-) diff --git a/ark-cli/Cargo.lock b/ark-cli/Cargo.lock index a0d34719..da7a2b3b 100644 --- a/ark-cli/Cargo.lock +++ b/ark-cli/Cargo.lock @@ -37,6 +37,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" version = "1.0.76" @@ -48,6 +63,7 @@ name = "ark-cli" version = "0.1.0" dependencies = [ "arklib", + "chrono", "clap", "env_logger", "fs_extra", @@ -265,6 +281,20 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.0", +] + [[package]] name = "cipher" version = "0.4.4" @@ -959,6 +989,29 @@ dependencies = [ "tokio-native-tls", ] +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "idna" version = "0.5.0" @@ -2723,6 +2776,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/ark-cli/Cargo.toml b/ark-cli/Cargo.toml index c7f30a7e..1a6315f9 100644 --- a/ark-cli/Cargo.toml +++ b/ark-cli/Cargo.toml @@ -16,4 +16,5 @@ walkdir = "2.3.2" home = "0.5.3" url = { version = "2.2.2", features = ["serde"] } serde_json = "1.0.82" -serde = { version = "1.0.138", features = ["derive"] } \ No newline at end of file +serde = { version = "1.0.138", features = ["derive"] } +chrono = "0.4.34" diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs index ebe6b4bc..7dff7edf 100644 --- a/ark-cli/src/main.rs +++ b/ark-cli/src/main.rs @@ -1,25 +1,33 @@ -use arklib::app_id; +use std::fs::{create_dir_all, File}; +use std::io::Write; +use std::path::PathBuf; +use std::str::FromStr; + use arklib::id::ResourceId; use arklib::pdf::PDFQuality; +use arklib::{app_id, provide_index, INDEX_PATH}; use arklib::{ modify, AtomicFile, APP_ID_FILE, ARK_FOLDER, FAVORITES_FILE, METADATA_STORAGE_FOLDER, PREVIEWS_STORAGE_FOLDER, PROPERTIES_STORAGE_FOLDER, SCORE_STORAGE_FILE, STATS_FOLDER, TAG_STORAGE_FILE, THUMBNAILS_STORAGE_FOLDER, }; + +use chrono::prelude::DateTime; +use chrono::Utc; + use clap::{Parser, Subcommand}; + use fs_extra::dir::{self, CopyOptions}; + use home::home_dir; -use std::fs::{create_dir_all, File}; -use std::io::Write; -use std::path::PathBuf; -use std::str::FromStr; -use storage::StorageType; use crate::parsers::Format; use crate::storage::Storage; +use storage::StorageType; use util::{ - discover_roots, monitor_index, provide_root, storages_exists, timestamp, + discover_roots, monitor_index, provide_root, read_storage_value, + storages_exists, timestamp, translate_storage, }; mod commands; @@ -59,6 +67,23 @@ enum Command { quality: Option, }, + List { + #[clap(parse(from_os_str))] + root_dir: Option, + + #[clap(long, short)] + entry: Option, + + #[clap(long, short)] + timestamp: Option, + + #[clap(long, short = 'g')] + tags: Option, + + #[clap(long, short)] + scores: Option, + }, + #[clap(subcommand)] Link(Link), @@ -72,10 +97,13 @@ enum Command { #[derive(Subcommand, Debug)] enum StorageCommand { List { - storage: String, + #[clap(parse(from_os_str))] + root_dir: Option, + + storage: Option, #[clap(short, long)] - versions: bool, + versions: Option, #[clap(short, long)] type_: Option, @@ -85,6 +113,9 @@ enum StorageCommand { #[derive(Subcommand, Debug)] enum FileCommand { Append { + #[clap(parse(from_os_str))] + root_dir: PathBuf, + storage: String, id: String, @@ -99,6 +130,9 @@ enum FileCommand { }, Insert { + #[clap(parse(from_os_str))] + root_dir: PathBuf, + storage: String, id: String, @@ -113,6 +147,9 @@ enum FileCommand { }, Read { + #[clap(parse(from_os_str))] + root_dir: PathBuf, + storage: String, id: String, @@ -144,6 +181,12 @@ enum Link { }, } +enum EntryOutput { + Id, + Path, + Both, +} + const ARK_CONFIG: &str = ".config/ark"; const ARK_BACKUPS_PATH: &str = ".ark-backups"; const ROOTS_CFG_FILENAME: &str = "roots"; @@ -166,6 +209,78 @@ async fn main() { }); match &args.command { + Command::List { + entry, + root_dir, + timestamp, + tags, + scores, + } => { + let root = provide_root(root_dir); + + let entry_output: EntryOutput = match entry { + Some(entry) => match entry.to_lowercase().as_str() { + "id" => EntryOutput::Id, + "path" => EntryOutput::Path, + "both" => EntryOutput::Both, + _ => panic!("unknown entry option"), + }, + None => EntryOutput::Id, + }; + + let index = provide_index(&root).expect("could not provide index"); + + let resource_index = index.read().unwrap(); + + for (path, resource) in resource_index.path2id.iter() { + let tags_list = read_storage_value( + &root, + "tags", + &resource.id.to_string(), + &None, + ) + .unwrap_or("".to_string()); + + let scores_list = read_storage_value( + &root, + "scores", + &resource.id.to_string(), + &None, + ) + .unwrap_or("0".to_string()); + + let mut output: String = match entry_output { + EntryOutput::Id => resource.id.to_string(), + EntryOutput::Path => path.display().to_string(), + EntryOutput::Both => { + format!("{}@{}", resource.id, path.display()) + } + }; + + let datetime = DateTime::::from(resource.modified); + + if timestamp.unwrap_or(false) { + let timestamp_str = datetime + .format("%Y-%m-%d %H:%M:%S.%f") + .to_string(); + output.push_str(&format!( + " last modified on {}", + timestamp_str + )); + } + + if tags.unwrap_or(false) { + output.push_str(&format!(" with tags {}", tags_list)); + } + + if scores.unwrap_or(false) { + output.push_str(&format!(" with score {}", scores_list)); + } + + println!("{}", output); + } + } + Command::Backup { roots_cfg } => { let timestamp = timestamp().as_secs(); let backup_dir = home_dir() @@ -308,14 +423,16 @@ async fn main() { }, Command::File(file) => match &file { FileCommand::Append { + root_dir, storage, id, content, format, type_, } => { - let (file_path, storage_type) = translate_storage(storage) - .expect("ERROR: Could not find storage folder"); + let (file_path, storage_type) = + translate_storage(&Some(root_dir.to_owned()), storage) + .expect("ERROR: Could not find storage folder"); let storage_type = storage_type.unwrap_or(match type_ { Some(type_) => match type_.to_lowercase().as_str() { @@ -341,14 +458,16 @@ async fn main() { } FileCommand::Insert { + root_dir, storage, id, content, format, type_, } => { - let (file_path, storage_type) = translate_storage(storage) - .expect("ERROR: Could not find storage folder"); + let (file_path, storage_type) = + translate_storage(&Some(root_dir.to_owned()), storage) + .expect("ERROR: Could not find storage folder"); let storage_type = storage_type.unwrap_or(match type_ { Some(type_) => match type_.to_lowercase().as_str() { @@ -373,9 +492,15 @@ async fn main() { .unwrap(); } - FileCommand::Read { storage, id, type_ } => { - let (file_path, storage_type) = translate_storage(storage) - .expect("ERROR: Could not find storage folder"); + FileCommand::Read { + root_dir, + storage, + id, + type_, + } => { + let (file_path, storage_type) = + translate_storage(&Some(root_dir.to_owned()), storage) + .expect("ERROR: Could not find storage folder"); let storage_type = storage_type.unwrap_or(match type_ { Some(type_) => match type_.to_lowercase().as_str() { @@ -402,12 +527,20 @@ async fn main() { }, Command::Storage(cmd) => match &cmd { StorageCommand::List { + root_dir, storage, type_, versions, } => { - let (file_path, storage_type) = translate_storage(storage) - .expect("ERROR: Could not find storage folder"); + let storage = storage + .as_ref() + .expect("ERROR: Storage was not provided"); + + let versions = versions.unwrap_or(false); + + let (file_path, storage_type) = + translate_storage(root_dir, storage) + .expect("ERROR: Could not find storage folder"); let storage_type = storage_type.unwrap_or(match type_ { Some(type_) => match type_.to_lowercase().as_str() { @@ -426,7 +559,7 @@ async fn main() { .expect("ERROR: Could not load storage"); let output = storage - .list(*versions) + .list(versions) .expect("ERROR: Could not list storage content"); println!("{}", output); @@ -434,57 +567,3 @@ async fn main() { }, } } - -fn translate_storage(storage: &str) -> Option<(PathBuf, Option)> { - if let Ok(path) = PathBuf::from_str(storage) { - if path.exists() && path.is_dir() { - return Some((path, None)); - } - } - - match storage.to_lowercase().as_str() { - "tags" => Some(( - provide_root(&None) - .join(ARK_FOLDER) - .join(TAG_STORAGE_FILE), - Some(StorageType::File), - )), - "scores" => Some(( - provide_root(&None) - .join(ARK_FOLDER) - .join(SCORE_STORAGE_FILE), - Some(StorageType::File), - )), - "stats" => Some(( - provide_root(&None) - .join(ARK_FOLDER) - .join(STATS_FOLDER), - Some(StorageType::Folder), - )), - "properties" => Some(( - provide_root(&None) - .join(ARK_FOLDER) - .join(PROPERTIES_STORAGE_FOLDER), - Some(StorageType::Folder), - )), - "metadata" => Some(( - provide_root(&None) - .join(ARK_FOLDER) - .join(METADATA_STORAGE_FOLDER), - Some(StorageType::Folder), - )), - "previews" => Some(( - provide_root(&None) - .join(ARK_FOLDER) - .join(PREVIEWS_STORAGE_FOLDER), - Some(StorageType::Folder), - )), - "thumbnails" => Some(( - provide_root(&None) - .join(ARK_FOLDER) - .join(THUMBNAILS_STORAGE_FOLDER), - Some(StorageType::Folder), - )), - _ => None, - } -} diff --git a/ark-cli/src/util.rs b/ark-cli/src/util.rs index d266aab6..88db2f1d 100644 --- a/ark-cli/src/util.rs +++ b/ark-cli/src/util.rs @@ -1,13 +1,21 @@ +use arklib::id::ResourceId; use arklib::index::ResourceIndex; +use arklib::{ + ARK_FOLDER, METADATA_STORAGE_FOLDER, PREVIEWS_STORAGE_FOLDER, + PROPERTIES_STORAGE_FOLDER, SCORE_STORAGE_FILE, STATS_FOLDER, + TAG_STORAGE_FILE, THUMBNAILS_STORAGE_FOLDER, +}; use std::env::current_dir; use std::fs::{canonicalize, metadata}; use std::io::BufRead; use std::io::BufReader; use std::path::Path; +use std::str::FromStr; use std::thread; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; use std::{fs::File, path::PathBuf}; +use crate::storage::{Storage, StorageType}; use crate::ARK_CONFIG; pub fn discover_roots(roots_cfg: &Option) -> Vec { @@ -148,3 +156,88 @@ pub fn timestamp() -> Duration { .duration_since(UNIX_EPOCH) .expect("Time went backwards!"); } + +pub fn translate_storage( + root: &Option, + storage: &str, +) -> Option<(PathBuf, Option)> { + if let Ok(path) = PathBuf::from_str(storage) { + if path.exists() && path.is_dir() { + return Some((path, None)); + } + } + + match storage.to_lowercase().as_str() { + "tags" => Some(( + provide_root(root) + .join(ARK_FOLDER) + .join(TAG_STORAGE_FILE), + Some(StorageType::File), + )), + "scores" => Some(( + provide_root(root) + .join(ARK_FOLDER) + .join(SCORE_STORAGE_FILE), + Some(StorageType::File), + )), + "stats" => Some(( + provide_root(root) + .join(ARK_FOLDER) + .join(STATS_FOLDER), + Some(StorageType::Folder), + )), + "properties" => Some(( + provide_root(root) + .join(ARK_FOLDER) + .join(PROPERTIES_STORAGE_FOLDER), + Some(StorageType::Folder), + )), + "metadata" => Some(( + provide_root(root) + .join(ARK_FOLDER) + .join(METADATA_STORAGE_FOLDER), + Some(StorageType::Folder), + )), + "previews" => Some(( + provide_root(root) + .join(ARK_FOLDER) + .join(PREVIEWS_STORAGE_FOLDER), + Some(StorageType::Folder), + )), + "thumbnails" => Some(( + provide_root(root) + .join(ARK_FOLDER) + .join(THUMBNAILS_STORAGE_FOLDER), + Some(StorageType::Folder), + )), + _ => None, + } +} + +pub fn read_storage_value( + root_dir: &PathBuf, + storage: &str, + id: &str, + type_: &Option, +) -> Result { + let (file_path, storage_type) = + translate_storage(&Some(root_dir.to_owned()), storage) + .expect("ERROR: Could not find storage folder"); + + let storage_type = storage_type.unwrap_or(match type_ { + Some(type_) => match type_.to_lowercase().as_str() { + "file" => StorageType::File, + "folder" => StorageType::Folder, + _ => panic!("unknown storage type"), + }, + None => StorageType::File, + }); + + let mut storage = Storage::new(file_path, storage_type) + .expect("ERROR: Could not create storage"); + + let resource_id = + ResourceId::from_str(id).expect("ERROR: Could not parse id"); + + storage.read(resource_id) +} From 5503217dd73e4da72f625b878e8d3295a4b0bd96 Mon Sep 17 00:00:00 2001 From: Alvinosh Date: Mon, 19 Feb 2024 14:18:59 +0100 Subject: [PATCH 20/23] Sorting by scores, filtering by tags. Add `Usage.md` --- ark-cli/USAGE.md | 74 +++++ ark-cli/ark-shelf/16-720383087 | 1 + ark-cli/ark-shelf/18-1909444406 | 1 + ark-cli/src/commands/file.rs | 19 +- ark-cli/src/main.rs | 301 +++++------------- ark-cli/src/models/cli.rs | 166 ++++++++++ ark-cli/src/models/entry.rs | 21 ++ .../src/{parsers/mod.rs => models/format.rs} | 26 +- ark-cli/src/models/mod.rs | 5 + ark-cli/src/models/sort.rs | 19 ++ ark-cli/src/{ => models}/storage.rs | 68 ++-- ark-cli/src/util.rs | 2 +- 12 files changed, 443 insertions(+), 260 deletions(-) create mode 100644 ark-cli/USAGE.md create mode 100644 ark-cli/ark-shelf/16-720383087 create mode 100644 ark-cli/ark-shelf/18-1909444406 create mode 100644 ark-cli/src/models/cli.rs create mode 100644 ark-cli/src/models/entry.rs rename ark-cli/src/{parsers/mod.rs => models/format.rs} (65%) create mode 100644 ark-cli/src/models/mod.rs create mode 100644 ark-cli/src/models/sort.rs rename ark-cli/src/{ => models}/storage.rs (87%) diff --git a/ark-cli/USAGE.md b/ark-cli/USAGE.md new file mode 100644 index 00000000..3802cb4c --- /dev/null +++ b/ark-cli/USAGE.md @@ -0,0 +1,74 @@ +## Usage + +Beginning with the following dir structure + +``` +├─── +│ └───.ark +│ ├───cache +│ │ ├───metadata +│ │ └───previews +│ └───user +│ ├───properties +│ ├───scores +│ └───tags +``` + +First create some sample links + +`ark-cli link create http://google.com google hi` + +`ark-cli link create http://bing.com bing hello` + +Then add some tags to the links + +`ark-cli file append tags search,engine` + +The same way we can append scores + +`ark-cli file append scores 15` + +We can also append json data + +`ark-cli file append properties favorites:false,ai:true --format=json` + +You can read these properties + +`ark-cli file read properties ` + +Or the scores + +`ark-cli file read scores ` + +You can list the entries for a storage like this + +`ark-cli storage list properties` + +For more info you can add the versions flag + +`ark-cli storage list properties --versions=true` + +Also works for file storages + +`ark-cli storage list scores --versions=true` + +List the files in the index using + +`ark-cli list ` + +`--entry=id|path|both` -> to show the path,the id or both of a resource + +`--timestamp=true` -> to show or not the last modified timestamp of a resource + +`--tags=true` -> to show or not the tags for every resource + +`--scores=true` -> to show or not the scores for every resource + +`--sort=asc|desc` -> to sort resources by asc or dsc order of scores + +`--filter=query` -> to filter resources by their tags + + + + + diff --git a/ark-cli/ark-shelf/16-720383087 b/ark-cli/ark-shelf/16-720383087 new file mode 100644 index 00000000..4b23f03e --- /dev/null +++ b/ark-cli/ark-shelf/16-720383087 @@ -0,0 +1 @@ +http://bing.com/ \ No newline at end of file diff --git a/ark-cli/ark-shelf/18-1909444406 b/ark-cli/ark-shelf/18-1909444406 new file mode 100644 index 00000000..d2a553a6 --- /dev/null +++ b/ark-cli/ark-shelf/18-1909444406 @@ -0,0 +1 @@ +http://google.com/ \ No newline at end of file diff --git a/ark-cli/src/commands/file.rs b/ark-cli/src/commands/file.rs index fe1ab372..6b8e6190 100644 --- a/ark-cli/src/commands/file.rs +++ b/ark-cli/src/commands/file.rs @@ -1,21 +1,20 @@ -use crate::parsers::{self, Format}; +use crate::models::{format, format::Format}; use arklib::{modify, modify_json, AtomicFile}; - pub fn file_append( atomic_file: &AtomicFile, content: &str, format: Format, ) -> Result<(), String> { match format { - parsers::Format::Raw => modify(&atomic_file, |current| { + Format::Raw => modify(&atomic_file, |current| { let mut combined_vec: Vec = current.to_vec(); combined_vec.extend_from_slice(content.as_bytes()); combined_vec }) .map_err(|_| "ERROR: Could not append string".to_string()), - parsers::Format::KeyValue => { - let values = parsers::key_value_to_str(&content) + Format::KeyValue => { + let values = format::key_value_to_str(&content) .map_err(|_| "ERROR: Could not parse json".to_string())?; append_json(&atomic_file, values.to_vec()) @@ -30,12 +29,10 @@ pub fn file_insert( format: Format, ) -> Result<(), String> { match format { - parsers::Format::Raw => { - modify(&atomic_file, |_| content.as_bytes().to_vec()) - .map_err(|_| "ERROR: Could not insert string".to_string()) - } - parsers::Format::KeyValue => { - let values = parsers::key_value_to_str(&content) + Format::Raw => modify(&atomic_file, |_| content.as_bytes().to_vec()) + .map_err(|_| "ERROR: Could not insert string".to_string()), + Format::KeyValue => { + let values = format::key_value_to_str(&content) .map_err(|_| "ERROR: Could not parse json".to_string())?; modify_json( diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs index 7dff7edf..39191fa4 100644 --- a/ark-cli/src/main.rs +++ b/ark-cli/src/main.rs @@ -16,177 +16,27 @@ use arklib::{ use chrono::prelude::DateTime; use chrono::Utc; -use clap::{Parser, Subcommand}; +use clap::Parser; use fs_extra::dir::{self, CopyOptions}; use home::home_dir; -use crate::parsers::Format; -use crate::storage::Storage; -use storage::StorageType; +use crate::models::cli::{Command, FileCommand, Link, StorageCommand}; +use crate::models::entry::EntryOutput; +use crate::models::format::Format; +use crate::models::sort::Sort; +use crate::models::storage::{Storage, StorageType}; + use util::{ discover_roots, monitor_index, provide_root, read_storage_value, storages_exists, timestamp, translate_storage, }; mod commands; -mod parsers; -mod storage; +mod models; mod util; -#[derive(Parser, Debug)] -#[clap(name = "ark-cli")] -#[clap(about = "Manage ARK tag storages and indexes", long_about = None)] -struct Cli { - #[clap(subcommand)] - command: Command, -} - -#[derive(Subcommand, Debug)] -enum Command { - Backup { - #[clap(parse(from_os_str))] - roots_cfg: Option, - }, - - Collisions { - #[clap(parse(from_os_str))] - root_dir: Option, - }, - - Monitor { - #[clap(parse(from_os_str))] - root_dir: Option, - interval: Option, - }, - - Render { - #[clap(parse(from_os_str))] - path: Option, - quality: Option, - }, - - List { - #[clap(parse(from_os_str))] - root_dir: Option, - - #[clap(long, short)] - entry: Option, - - #[clap(long, short)] - timestamp: Option, - - #[clap(long, short = 'g')] - tags: Option, - - #[clap(long, short)] - scores: Option, - }, - - #[clap(subcommand)] - Link(Link), - - #[clap(subcommand)] - File(FileCommand), - - #[clap(subcommand)] - Storage(StorageCommand), -} - -#[derive(Subcommand, Debug)] -enum StorageCommand { - List { - #[clap(parse(from_os_str))] - root_dir: Option, - - storage: Option, - - #[clap(short, long)] - versions: Option, - - #[clap(short, long)] - type_: Option, - }, -} - -#[derive(Subcommand, Debug)] -enum FileCommand { - Append { - #[clap(parse(from_os_str))] - root_dir: PathBuf, - - storage: String, - - id: String, - - content: String, - - #[clap(short, long)] - format: Option, - - #[clap(short, long)] - type_: Option, - }, - - Insert { - #[clap(parse(from_os_str))] - root_dir: PathBuf, - - storage: String, - - id: String, - - content: String, - - #[clap(short, long)] - format: Option, - - #[clap(short, long)] - type_: Option, - }, - - Read { - #[clap(parse(from_os_str))] - root_dir: PathBuf, - - storage: String, - - id: String, - - #[clap(short, long)] - type_: Option, - }, -} - -#[derive(Subcommand, Debug)] -enum Link { - Create { - #[clap(parse(from_os_str))] - root_dir: Option, - - url: Option, - title: Option, - desc: Option, - }, - - Load { - #[clap(parse(from_os_str))] - root_dir: Option, - - #[clap(parse(from_os_str))] - file_path: Option, - - id: Option, - }, -} - -enum EntryOutput { - Id, - Path, - Both, -} - const ARK_CONFIG: &str = ".config/ark"; const ARK_BACKUPS_PATH: &str = ".ark-backups"; const ROOTS_CFG_FILENAME: &str = "roots"; @@ -195,7 +45,7 @@ const ROOTS_CFG_FILENAME: &str = "roots"; async fn main() { env_logger::init(); - let args = Cli::parse(); + let args = models::cli::Cli::parse(); let app_id_dir = home_dir().expect("Couldn't retrieve home directory!"); let ark_dir = app_id_dir.join(".ark"); @@ -211,45 +61,84 @@ async fn main() { match &args.command { Command::List { entry, + entry_id, + entry_path, + root_dir, - timestamp, + modified, tags, scores, + sort, + filter, } => { let root = provide_root(root_dir); - let entry_output: EntryOutput = match entry { - Some(entry) => match entry.to_lowercase().as_str() { - "id" => EntryOutput::Id, - "path" => EntryOutput::Path, - "both" => EntryOutput::Both, - _ => panic!("unknown entry option"), - }, - None => EntryOutput::Id, + let entry_output = match (entry, entry_id, entry_path) { + (Some(e), false, false) => e, + (None, true, false) => &EntryOutput::Id, + (None, false, true) => &EntryOutput::Path, + (None, true, true) => &EntryOutput::Both, + (None, false, false) => &EntryOutput::Id, // default value + _ => panic!( + "incompatible entry output options, please choose only one" + ), }; let index = provide_index(&root).expect("could not provide index"); - let resource_index = index.read().unwrap(); + let resource_index = index.read().expect("could not read index"); + + let mut resources = resource_index + .path2id + .iter() + .map(|(path, resource)| { + let tags_list = read_storage_value( + &root, + "tags", + &resource.id.to_string(), + &None, + ) + .unwrap_or("NO_TAGS".to_string()); + + let scores_list = read_storage_value( + &root, + "scores", + &resource.id.to_string(), + &None, + ) + .unwrap_or("NO_SCORE".to_string()); + + let datetime = DateTime::::from(resource.modified); + + (path, resource, tags_list, scores_list, datetime) + }) + .collect::>(); + + match sort { + Some(Sort::Asc) => resources + .sort_by(|(_, _, _, _, a), (_, _, _, _, b)| a.cmp(b)), + + Some(Sort::Desc) => resources + .sort_by(|(_, _, _, _, a), (_, _, _, _, b)| b.cmp(a)), + None => (), + }; - for (path, resource) in resource_index.path2id.iter() { - let tags_list = read_storage_value( - &root, - "tags", - &resource.id.to_string(), - &None, - ) - .unwrap_or("".to_string()); + if let Some(filter) = filter { + resources = resources + .into_iter() + .filter(|(_, _, tags_list, _, _)| { + tags_list + .split(',') + .any(|tag| tag.trim() == filter) + }) + .collect(); + } - let scores_list = read_storage_value( - &root, - "scores", - &resource.id.to_string(), - &None, - ) - .unwrap_or("0".to_string()); + for (path, resource, tags_list, scores_list, datetime) in resources + { + let mut output = String::new(); - let mut output: String = match entry_output { + let entry_str = match entry_output { EntryOutput::Id => resource.id.to_string(), EntryOutput::Path => path.display().to_string(), EntryOutput::Both => { @@ -257,9 +146,9 @@ async fn main() { } }; - let datetime = DateTime::::from(resource.modified); + output.push_str(&entry_str); - if timestamp.unwrap_or(false) { + if *modified { let timestamp_str = datetime .format("%Y-%m-%d %H:%M:%S.%f") .to_string(); @@ -269,11 +158,11 @@ async fn main() { )); } - if tags.unwrap_or(false) { + if *tags { output.push_str(&format!(" with tags {}", tags_list)); } - if scores.unwrap_or(false) { + if *scores { output.push_str(&format!(" with score {}", scores_list)); } @@ -435,16 +324,11 @@ async fn main() { .expect("ERROR: Could not find storage folder"); let storage_type = storage_type.unwrap_or(match type_ { - Some(type_) => match type_.to_lowercase().as_str() { - "file" => StorageType::File, - "folder" => StorageType::Folder, - _ => panic!("unknown storage type"), - }, + Some(t) => *t, None => StorageType::File, }); - let format = - parsers::get_format(&format).unwrap_or(Format::Raw); + let format = format.unwrap_or(Format::Raw); let mut storage = Storage::new(file_path, storage_type) .expect("ERROR: Could not create storage"); @@ -454,7 +338,7 @@ async fn main() { storage .append(resource_id, content, format) - .unwrap(); + .expect("ERROR: Could not append content to storage"); } FileCommand::Insert { @@ -470,16 +354,11 @@ async fn main() { .expect("ERROR: Could not find storage folder"); let storage_type = storage_type.unwrap_or(match type_ { - Some(type_) => match type_.to_lowercase().as_str() { - "file" => StorageType::File, - "folder" => StorageType::Folder, - _ => panic!("unknown storage type"), - }, + Some(t) => *t, None => StorageType::File, }); - let format = - parsers::get_format(&format).unwrap_or(Format::Raw); + let format = format.unwrap_or(Format::Raw); let mut storage = Storage::new(file_path, storage_type) .expect("ERROR: Could not create storage"); @@ -489,7 +368,7 @@ async fn main() { storage .insert(resource_id, content, format) - .unwrap(); + .expect("ERROR: Could not insert content to storage"); } FileCommand::Read { @@ -503,11 +382,7 @@ async fn main() { .expect("ERROR: Could not find storage folder"); let storage_type = storage_type.unwrap_or(match type_ { - Some(type_) => match type_.to_lowercase().as_str() { - "file" => StorageType::File, - "folder" => StorageType::Folder, - _ => panic!("unknown storage type"), - }, + Some(t) => *t, None => StorageType::File, }); @@ -543,11 +418,7 @@ async fn main() { .expect("ERROR: Could not find storage folder"); let storage_type = storage_type.unwrap_or(match type_ { - Some(type_) => match type_.to_lowercase().as_str() { - "file" => StorageType::File, - "folder" => StorageType::Folder, - _ => panic!("unknown storage type"), - }, + Some(t) => *t, None => StorageType::File, }); diff --git a/ark-cli/src/models/cli.rs b/ark-cli/src/models/cli.rs new file mode 100644 index 00000000..322b39d8 --- /dev/null +++ b/ark-cli/src/models/cli.rs @@ -0,0 +1,166 @@ +use std::path::PathBuf; + +use arklib::id::ResourceId; +use clap::{Parser, Subcommand}; + +use super::{ + entry::EntryOutput, format::Format, sort::Sort, storage::StorageType, +}; + +#[derive(Parser, Debug)] +#[clap(name = "ark-cli")] +#[clap(about = "Manage ARK tag storages and indexes", long_about = None)] +pub struct Cli { + #[clap(subcommand)] + pub command: Command, +} + +#[derive(Subcommand, Debug)] +pub enum Command { + Backup { + #[clap(parse(from_os_str))] + roots_cfg: Option, + }, + + Collisions { + #[clap(parse(from_os_str))] + root_dir: Option, + }, + + Monitor { + #[clap(parse(from_os_str))] + root_dir: Option, + interval: Option, + }, + + Render { + #[clap(parse(from_os_str))] + path: Option, + quality: Option, + }, + + List { + #[clap(parse(from_os_str))] + root_dir: Option, + + #[clap(long)] + entry: Option, + + #[clap(long, short = 'i', action)] + entry_id: bool, + + #[clap(long, short = 'p', action)] + entry_path: bool, + + #[clap(long, short, action)] + modified: bool, + + #[clap(long, short, action)] + tags: bool, + + #[clap(long, short, action)] + scores: bool, + + #[clap(long)] + sort: Option, + + #[clap(long)] + filter: Option, + }, + + #[clap(subcommand)] + Link(Link), + + #[clap(subcommand)] + File(FileCommand), + + #[clap(subcommand)] + Storage(StorageCommand), +} + +#[derive(Subcommand, Debug)] +pub enum StorageCommand { + List { + #[clap(parse(from_os_str))] + root_dir: Option, + + storage: Option, + + #[clap(short, long)] + versions: Option, + + #[clap(short, long)] + type_: Option, + }, +} + +#[derive(Subcommand, Debug)] +pub enum FileCommand { + Append { + #[clap(parse(from_os_str))] + root_dir: PathBuf, + + storage: String, + + id: String, + + content: String, + + #[clap(short, long)] + format: Option, + + #[clap(short, long)] + type_: Option, + }, + + Insert { + #[clap(parse(from_os_str))] + root_dir: PathBuf, + + storage: String, + + id: String, + + content: String, + + #[clap(short, long)] + format: Option, + + #[clap(short, long)] + type_: Option, + }, + + Read { + #[clap(parse(from_os_str))] + root_dir: PathBuf, + + storage: String, + + id: String, + + #[clap(short, long)] + type_: Option, + }, +} + +#[derive(Subcommand, Debug)] +pub enum Link { + Create { + #[clap(parse(from_os_str))] + root_dir: Option, + + url: Option, + title: Option, + desc: Option, + }, + + Load { + #[clap(parse(from_os_str))] + root_dir: Option, + + #[clap(parse(from_os_str))] + file_path: Option, + + id: Option, + }, +} diff --git a/ark-cli/src/models/entry.rs b/ark-cli/src/models/entry.rs new file mode 100644 index 00000000..174d54a6 --- /dev/null +++ b/ark-cli/src/models/entry.rs @@ -0,0 +1,21 @@ +use clap::Parser; + +#[derive(Parser, Debug)] +pub enum EntryOutput { + Id, + Path, + Both, +} + +impl std::str::FromStr for EntryOutput { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "id" => Ok(EntryOutput::Id), + "path" => Ok(EntryOutput::Path), + "both" => Ok(EntryOutput::Both), + _ => Err("Entry output must be either 'id', 'path' or 'both'"), + } + } +} diff --git a/ark-cli/src/parsers/mod.rs b/ark-cli/src/models/format.rs similarity index 65% rename from ark-cli/src/parsers/mod.rs rename to ark-cli/src/models/format.rs index 40727db9..33f487eb 100644 --- a/ark-cli/src/parsers/mod.rs +++ b/ark-cli/src/models/format.rs @@ -1,8 +1,21 @@ +#[derive(Debug, Clone, Copy)] pub enum Format { KeyValue, Raw, } +impl std::str::FromStr for Format { + type Err = String; + + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "json" => Ok(Format::KeyValue), + "raw" => Ok(Format::Raw), + _ => Err("Invalid format".to_owned()), + } + } +} + pub fn key_value_to_str(s: &str) -> Result, String> { let pairs: Vec<&str> = s.split(',').collect(); @@ -21,16 +34,3 @@ pub fn key_value_to_str(s: &str) -> Result, String> { Ok(values) } - -pub fn get_format(s: &Option) -> Option { - match s { - Some(value) => { - if value.to_lowercase() == "json" { - Some(Format::KeyValue) - } else { - None - } - } - None => Some(Format::Raw), - } -} diff --git a/ark-cli/src/models/mod.rs b/ark-cli/src/models/mod.rs new file mode 100644 index 00000000..bc37c45a --- /dev/null +++ b/ark-cli/src/models/mod.rs @@ -0,0 +1,5 @@ +pub mod cli; +pub mod entry; +pub mod format; +pub mod sort; +pub mod storage; diff --git a/ark-cli/src/models/sort.rs b/ark-cli/src/models/sort.rs new file mode 100644 index 00000000..000da162 --- /dev/null +++ b/ark-cli/src/models/sort.rs @@ -0,0 +1,19 @@ +use clap::Parser; + +#[derive(Parser, Debug)] +pub enum Sort { + Asc, + Desc, +} + +impl std::str::FromStr for Sort { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "asc" => Ok(Sort::Asc), + "desc" => Ok(Sort::Desc), + _ => Err("Sort must be either 'asc' or 'desc'"), + } + } +} diff --git a/ark-cli/src/storage.rs b/ark-cli/src/models/storage.rs similarity index 87% rename from ark-cli/src/storage.rs rename to ark-cli/src/models/storage.rs index 59c8755d..8f5d3a9d 100644 --- a/ark-cli/src/storage.rs +++ b/ark-cli/src/models/storage.rs @@ -7,15 +7,27 @@ use crate::{ self, file::{format_file, format_line}, }, - parsers::Format, + models::format::Format, }; -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub enum StorageType { File, Folder, } +impl std::str::FromStr for StorageType { + type Err = String; + + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "file" => Ok(StorageType::File), + "folder" => Ok(StorageType::Folder), + _ => Err(format!("Invalid storage type: {}", s)), + } + } +} + pub struct Storage { path: PathBuf, storage_type: StorageType, @@ -71,10 +83,14 @@ impl Storage { for (i, line) in data.lines().enumerate() { let mut line = line.split(':'); let id = line.next().unwrap(); - let id = id.parse::().map_err(|_| { + match id.parse::().map_err(|_| { format!("Failed to parse ResourceId from line: {i}",) - })?; - self.files.push(id); + }) { + Ok(id) => self.files.push(id), + Err(e) => { + eprintln!("Error parsing line {}: {}", i, e); + } + } } } StorageType::Folder => { @@ -126,13 +142,13 @@ impl Storage { "Key value format is not supported for file storage" .to_owned(), ), - Format::Raw => format!("\n{}:{}", id, content), + Format::Raw => format!("{}:{}\n", id, content), }; match commands::file::file_append( &atomic_file, &content, - crate::parsers::Format::Raw, + Format::Raw, ) { Ok(_) => { return Ok(()); @@ -202,13 +218,18 @@ impl Storage { for (i, line) in data.lines().enumerate() { let mut line = line.split(':'); let line_id: &str = line.next().unwrap(); - let line_id = line_id.parse::().map_err(|_| { + match line_id.parse::().map_err(|_| { format!("Failed to parse ResourceId from line: {i}",) - })?; - - if id == line_id { - let data = line.next().unwrap(); - return Ok(format!("{}", data)); + }) { + Ok(line_id) => { + if id == line_id { + let data = line.next().unwrap(); + return Ok(format!("{}", data)); + } + } + Err(e) => { + eprintln!("Error parsing line {}: {}", i, e); + } } } @@ -265,13 +286,13 @@ impl Storage { "Key value format is not supported for file storage" .to_owned(), ), - Format::Raw => format!("{}:{}", id, content), + Format::Raw => format!("{}:{}\n", id, content), }; match commands::file::file_insert( &atomic_file, &content, - crate::parsers::Format::Raw, + Format::Raw, ) { Ok(_) => { return Ok(()); @@ -352,11 +373,18 @@ impl Storage { for line in data.lines() { let mut line = line.split(':'); - let id = line.next().unwrap(); - let data = line.next().unwrap(); - writeln!(output, "{: <16} {}", id, data).map_err( - |_| "Could not write to output".to_string(), - )?; + let id = line.next(); + let data = line.next(); + + match (id, data) { + (Some(id), Some(data)) => { + writeln!(output, "{: <16} {}", id, data) + .map_err(|_| { + "Could not write to output".to_string() + })?; + } + _ => {} + } } } StorageType::Folder => { diff --git a/ark-cli/src/util.rs b/ark-cli/src/util.rs index 88db2f1d..3d3ffa95 100644 --- a/ark-cli/src/util.rs +++ b/ark-cli/src/util.rs @@ -15,7 +15,7 @@ use std::thread; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; use std::{fs::File, path::PathBuf}; -use crate::storage::{Storage, StorageType}; +use crate::models::storage::{Storage, StorageType}; use crate::ARK_CONFIG; pub fn discover_roots(roots_cfg: &Option) -> Vec { From d19dc2ea50518e14cd52197c378c51b0f2a7d83e Mon Sep 17 00:00:00 2001 From: Kirill Taran Date: Thu, 29 Feb 2024 14:25:12 +0300 Subject: [PATCH 21/23] Minor changes. Update `Usage.md` --- ark-cli/USAGE.md | 182 +++++++++++++++++++++++++++------- ark-cli/src/main.rs | 10 +- ark-cli/src/models/storage.rs | 15 ++- 3 files changed, 153 insertions(+), 54 deletions(-) diff --git a/ark-cli/USAGE.md b/ark-cli/USAGE.md index 3802cb4c..1e8d4e5e 100644 --- a/ark-cli/USAGE.md +++ b/ark-cli/USAGE.md @@ -1,74 +1,180 @@ -## Usage +# Usage -Beginning with the following dir structure +## Get started +Create an empty dir: ``` -├─── -│ └───.ark -│ ├───cache -│ │ ├───metadata -│ │ └───previews -│ └───user -│ ├───properties -│ ├───scores -│ └───tags +mkdir /tmp/test +cd /tmp/test ``` -First create some sample links +Let's fill it with something. One of the simplest ways to create resources it is to save a link to web page using `ark-cli link` command: +``` +$ ark-cli link create . http://google.com goo +$ ark-cli link create . http://duckduckgo.com duck +``` -`ark-cli link create http://google.com google hi` +We can use `ark-cli list` to see just created resources: +``` +22-207093268 +18-1909444406 +``` -`ark-cli link create http://bing.com bing hello` +These are just ids, derived from the URLs themselves. -Then add some tags to the links +Now, the dir structure should resemble this: +``` +/tmp/test +└───.ark + ├───cache + │ ├───metadata + │ └───previews + │ + └───user + ├───properties + ├───scores + └───tags +``` -`ark-cli file append tags search,engine` +### Label your data -The same way we can append scores +You can attach various metadata to your data, e.g. tags: +``` +$ ark-cli file append . tags 22-207093268 search,engine +``` -`ark-cli file append scores 15` +The same way we can append scores: +``` +$ ark-cli file append . scores 22-207093268 15 +``` + +Generic metadata is possible using JSON-based properties: +``` +$ ark-cli file append . properties 22-207093268 favorites:false,ai:true --format=json +``` -We can also append json data +### Navigate your data -`ark-cli file append properties favorites:false,ai:true --format=json` +The simplest command to observe your resources is `list`: +``` +$ ark-cli list + +18-1909444406 +22-207093268 +``` -You can read these properties +You can also target this command to other folders: +``` +$ ark-cli list ~/Pictures/ -`ark-cli file read properties ` +58922-3276384608 +62591-2492670715 +723145-720506115 +125308-3041567246 +``` -Or the scores +But it's a bit boring and doesn't really tell anything, right? Various flags should be used to gain more knowledge about your collections of resources: +* `--entry=id|path|both` to show the path,the id or both of a resource +* `--timestamp=true` to show or not the last modified timestamp of a resource +* `--tags=true` to show or not the tags for every resource +* `--scores=true` to show or not the scores for every resource +* `--sort=asc|desc` to sort resources by asc or dsc order of scores +* `--filter=query` to filter resources by their tags -`ark-cli file read scores ` +For instance, you can list files with their paths and attached tags: +``` +$ ark-cli list -pt -You can list the entries for a storage like this +30-4257856154 with tags search +18-1909444406 with tags hello +22-207093268 with tags search,engine +38-103010298 with tags NO_TAGS +``` -`ark-cli storage list properties` +Or, sort by score: +``` +$ ark-cli list -s --sort=asc -For more info you can add the versions flag +30-4257856154 with score NO_SCORE +18-1909444406 with score 2 +38-103010298 with score 10 +22-207093268 with score 15 +``` -`ark-cli storage list properties --versions=true` +Finally, you can filter resources using their tags: +``` +$ /tmp/ark-cli list -t --filter=search -Also works for file storages +30-4257856154 with tags search +22-207093268 with tags search,engine +``` -`ark-cli storage list scores --versions=true` +## :zap: Low-level utilities :zap: -List the files in the index using +There are commands which could be useful with time, when you grasp the basic concepts. Some of these commands also can be useful for debugging [ArkLib](https://github.com/ARK-Builders/ark-rust). -`ark-cli list ` +### Retrieve the metadata -`--entry=id|path|both` -> to show the path,the id or both of a resource +You can read these properties: +``` +$ ark-cli file read . properties 22-207093268 +{"ai":"true","desc":null,"favorites":"false","title":"duck"} +``` -`--timestamp=true` -> to show or not the last modified timestamp of a resource +As well as scores or tags: +``` +$ ark-cli file read . scores 22-207093268 +15 +$ ark-cli file read . tags 22-207093268 +search,engine +``` -`--tags=true` -> to show or not the tags for every resource +### Inspect storages -`--scores=true` -> to show or not the scores for every resource +It's also possible to list resources having some metadata in a particular storage: +``` +$ ark-cli storage list . properties +22-207093268 +18-1909444406 -`--sort=asc|desc` -> to sort resources by asc or dsc order of scores +$ ark-cli storage list . tags +22-207093268 -`--filter=query` -> to filter resources by their tags +$ ark-cli storage list . scores +22-207093268 +``` +Note that, in this example, resource with id `18-1909444406` is listed only in `properties` storage since it lacks any metadata in `tags` and `scores` storages. The `ark-cli storage list` command only lists entries of a particular storage, not all resources. +### Inspect versions +For delving into history of storage mutations, we made `--versions` flag: +``` +$ ark-cli storage list . properties --versions=true +version name machine path +2 22-207093268 0592a937-a5d1-4843-8f03-ae0d6a9e77b5 ./.ark/user/properties/22-207093268/22-207093268_0592a937-a5d1-4843-8f03-ae0d6a9e77b5.2 +1 18-1909444406 0592a937-a5d1-4843-8f03-ae0d6a9e77b5 ./.ark/user/properties/18-1909444406/18-1909444406_0592a937-a5d1-4843-8f03-ae0d6a9e77b5.1 +``` +Each storage mutation made by `ark-cli file append` or `ark-cli file insert` commands increases the number in `version` column. Versions help to prevent dirty-writes caused by using same storages by separate apps, or devices. +The `properties` storage is _folder-based_, but same command can be used with _file-based_ storages like `tags`: +``` +$ ark-cli storage list . tags --versions=true +Loading app id at /home/kirill/.ark... +id value +22-207093268 search,engine + +$ ark-cli file append . tags 22-207093268 wow +$ ark-cli storage list . tags --versions=true +id value +22-207093268 search,engine +22-207093268 wow + +$ ark-cli file append . tags 22-207093268 one_more_time +$ ark-cli storage list . tags --versions=true +id value +22-207093268 search,engine +22-207093268 wow +22-207093268 one_more_time +``` diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs index 39191fa4..3375f309 100644 --- a/ark-cli/src/main.rs +++ b/ark-cli/src/main.rs @@ -5,13 +5,7 @@ use std::str::FromStr; use arklib::id::ResourceId; use arklib::pdf::PDFQuality; -use arklib::{app_id, provide_index, INDEX_PATH}; -use arklib::{ - modify, AtomicFile, APP_ID_FILE, ARK_FOLDER, FAVORITES_FILE, - METADATA_STORAGE_FOLDER, PREVIEWS_STORAGE_FOLDER, - PROPERTIES_STORAGE_FOLDER, SCORE_STORAGE_FILE, STATS_FOLDER, - TAG_STORAGE_FILE, THUMBNAILS_STORAGE_FOLDER, -}; +use arklib::{app_id, provide_index}; use chrono::prelude::DateTime; use chrono::Utc; @@ -78,7 +72,7 @@ async fn main() { (None, true, false) => &EntryOutput::Id, (None, false, true) => &EntryOutput::Path, (None, true, true) => &EntryOutput::Both, - (None, false, false) => &EntryOutput::Id, // default value + (None, false, false) => &EntryOutput::Id, // default mode _ => panic!( "incompatible entry output options, please choose only one" ), diff --git a/ark-cli/src/models/storage.rs b/ark-cli/src/models/storage.rs index 8f5d3a9d..f9ed932b 100644 --- a/ark-cli/src/models/storage.rs +++ b/ark-cli/src/models/storage.rs @@ -128,14 +128,13 @@ impl Storage { ) -> Result<(), String> { match self.storage_type { StorageType::File => { - let atomic_file = AtomicFile::new(&self.path) - // .expect("ERROR: Could not create atomic file"); - .map_err(|e| { - format!( - "Failed to create atomic file at {} with error: {:?}", - self.path.display(), e - ) - })?; + let atomic_file = AtomicFile::new(&self.path).map_err(|e| { + format!( + "Failed to create atomic file at {} with error: {:?}", + self.path.display(), + e + ) + })?; let content = match format { Format::KeyValue => return Err( From 413dff243f134385582b397cb44bc5f917561798 Mon Sep 17 00:00:00 2001 From: alvinosh <38663469+alvinosh@users.noreply.github.com> Date: Fri, 8 Mar 2024 22:10:12 +0100 Subject: [PATCH 22/23] #19: Print URLs (#27) --- ark-cli/.gitignore | 3 +- ark-cli/Cargo.lock | 44 +-- ark-cli/Cargo.toml | 2 + ark-cli/USAGE.md | 34 ++- ark-cli/src/commands/file.rs | 38 ++- ark-cli/src/commands/link.rs | 31 ++- ark-cli/src/error.rs | 57 ++++ ark-cli/src/main.rs | 497 +++++++++++++++++++++++----------- ark-cli/src/models/cli.rs | 3 + ark-cli/src/models/entry.rs | 4 +- ark-cli/src/models/format.rs | 8 +- ark-cli/src/models/storage.rs | 239 ++++++++-------- ark-cli/src/util.rs | 104 +++---- 13 files changed, 675 insertions(+), 389 deletions(-) create mode 100644 ark-cli/src/error.rs diff --git a/ark-cli/.gitignore b/ark-cli/.gitignore index 55f04984..9869c062 100644 --- a/ark-cli/.gitignore +++ b/ark-cli/.gitignore @@ -1,2 +1,3 @@ target -.ark \ No newline at end of file +.ark +.vscode \ No newline at end of file diff --git a/ark-cli/Cargo.lock b/ark-cli/Cargo.lock index da7a2b3b..c11ccdcd 100644 --- a/ark-cli/Cargo.lock +++ b/ark-cli/Cargo.lock @@ -54,14 +54,15 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.76" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59d2a3357dde987206219e78ecfbbb6e8dad06cbb65292758d3270e6254f7355" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" [[package]] name = "ark-cli" version = "0.1.0" dependencies = [ + "anyhow", "arklib", "chrono", "clap", @@ -70,6 +71,7 @@ dependencies = [ "home", "serde", "serde_json", + "thiserror", "tokio", "url", "walkdir", @@ -174,7 +176,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.42", + "syn 2.0.52", "which", ] @@ -499,7 +501,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.42", + "syn 2.0.52", ] [[package]] @@ -1387,7 +1389,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.52", ] [[package]] @@ -1656,7 +1658,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" dependencies = [ "proc-macro2", - "syn 2.0.42", + "syn 2.0.52", ] [[package]] @@ -1691,9 +1693,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.71" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -1709,9 +1711,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -2085,7 +2087,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.52", ] [[package]] @@ -2261,9 +2263,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.42" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b7d0a2c048d661a1a59fcd7355baa232f7ed34e0ee4df2eef3c1c1c0d3852d8" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", @@ -2355,22 +2357,22 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" [[package]] name = "thiserror" -version = "1.0.51" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.51" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.52", ] [[package]] @@ -2444,7 +2446,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.52", ] [[package]] @@ -2666,7 +2668,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.52", "wasm-bindgen-shared", ] @@ -2700,7 +2702,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.52", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/ark-cli/Cargo.toml b/ark-cli/Cargo.toml index 1a6315f9..1c257ce7 100644 --- a/ark-cli/Cargo.toml +++ b/ark-cli/Cargo.toml @@ -18,3 +18,5 @@ url = { version = "2.2.2", features = ["serde"] } serde_json = "1.0.82" serde = { version = "1.0.138", features = ["derive"] } chrono = "0.4.34" +anyhow = "1.0.80" +thiserror = "1.0.57" diff --git a/ark-cli/USAGE.md b/ark-cli/USAGE.md index 1e8d4e5e..19d79286 100644 --- a/ark-cli/USAGE.md +++ b/ark-cli/USAGE.md @@ -74,7 +74,7 @@ $ ark-cli list ~/Pictures/ ``` But it's a bit boring and doesn't really tell anything, right? Various flags should be used to gain more knowledge about your collections of resources: -* `--entry=id|path|both` to show the path,the id or both of a resource +* `--entry=id|path|both|link` to show the path,the id or both of a resource * `--timestamp=true` to show or not the last modified timestamp of a resource * `--tags=true` to show or not the tags for every resource * `--scores=true` to show or not the scores for every resource @@ -85,28 +85,40 @@ For instance, you can list files with their paths and attached tags: ``` $ ark-cli list -pt -30-4257856154 with tags search -18-1909444406 with tags hello -22-207093268 with tags search,engine -38-103010298 with tags NO_TAGS +30-4257856154 search +18-1909444406 hello +22-207093268 search,engine +38-103010298 NO_TAGS +``` + +You Can list the links of the files + +``` +$ark-cli list -l + +https://google.com +https://news.ycombinator.com +https://youtube.com +https://github.com + ``` Or, sort by score: ``` $ ark-cli list -s --sort=asc -30-4257856154 with score NO_SCORE -18-1909444406 with score 2 -38-103010298 with score 10 -22-207093268 with score 15 +30-4257856154 NO_SCORE +18-1909444406 2 +38-103010298 10 +22-207093268 15 ``` Finally, you can filter resources using their tags: ``` $ /tmp/ark-cli list -t --filter=search -30-4257856154 with tags search -22-207093268 with tags search,engine +30-4257856154 search +22-207093268 search,engine ``` ## :zap: Low-level utilities :zap: diff --git a/ark-cli/src/commands/file.rs b/ark-cli/src/commands/file.rs index 6b8e6190..a9149137 100644 --- a/ark-cli/src/commands/file.rs +++ b/ark-cli/src/commands/file.rs @@ -1,24 +1,22 @@ +use crate::error::AppError; use crate::models::{format, format::Format}; -use arklib::{modify, modify_json, AtomicFile}; +use arklib::{modify, modify_json, AtomicFile, Result as ArklibResult}; pub fn file_append( atomic_file: &AtomicFile, content: &str, format: Format, -) -> Result<(), String> { +) -> Result<(), AppError> { match format { - Format::Raw => modify(&atomic_file, |current| { + Format::Raw => Ok(modify(atomic_file, |current| { let mut combined_vec: Vec = current.to_vec(); combined_vec.extend_from_slice(content.as_bytes()); combined_vec - }) - .map_err(|_| "ERROR: Could not append string".to_string()), + })?), Format::KeyValue => { - let values = format::key_value_to_str(&content) - .map_err(|_| "ERROR: Could not parse json".to_string())?; + let values = format::key_value_to_str(content)?; - append_json(&atomic_file, values.to_vec()) - .map_err(|_| "ERROR: Could not append json".to_string()) + Ok(append_json(atomic_file, values.to_vec())?) } } } @@ -27,16 +25,16 @@ pub fn file_insert( atomic_file: &AtomicFile, content: &str, format: Format, -) -> Result<(), String> { +) -> Result<(), AppError> { match format { - Format::Raw => modify(&atomic_file, |_| content.as_bytes().to_vec()) - .map_err(|_| "ERROR: Could not insert string".to_string()), + Format::Raw => { + Ok(modify(atomic_file, |_| content.as_bytes().to_vec())?) + } Format::KeyValue => { - let values = format::key_value_to_str(&content) - .map_err(|_| "ERROR: Could not parse json".to_string())?; + let values = format::key_value_to_str(content)?; modify_json( - &atomic_file, + atomic_file, |current: &mut Option| { let mut new = serde_json::Map::new(); for (key, value) in &values { @@ -48,7 +46,7 @@ pub fn file_insert( *current = Some(serde_json::Value::Object(new)); }, ) - .map_err(|e| e.to_string()) + .map_err(|e| AppError::FileOperationError(e.to_string())) } } } @@ -56,8 +54,8 @@ pub fn file_insert( fn append_json( atomic_file: &AtomicFile, data: Vec<(String, String)>, -) -> arklib::Result<()> { - modify_json(&atomic_file, |current: &mut Option| { +) -> ArklibResult<()> { + modify_json(atomic_file, |current: &mut Option| { let current_data = match current { Some(current) => { if let Ok(value) = serde_json::to_value(current) { @@ -74,7 +72,7 @@ fn append_json( }; let mut new = serde_json::Map::new(); - if let None = current_data { + if current_data.is_none() { for (key, value) in &data { new.insert( key.clone(), @@ -128,7 +126,7 @@ pub fn format_file(file: &AtomicFile) -> Option { .expect("Not a file") .to_str() .unwrap() - .split("_"); + .split('_'); let name = split.next().unwrap(); diff --git a/ark-cli/src/commands/link.rs b/ark-cli/src/commands/link.rs index 182580fe..fee36cc5 100644 --- a/ark-cli/src/commands/link.rs +++ b/ark-cli/src/commands/link.rs @@ -1,51 +1,54 @@ -use std::path::PathBuf; - use arklib::{id::ResourceId, link::Link}; +use std::path::PathBuf; use url::Url; -use crate::util::provide_index; +use crate::error::AppError; +use crate::util::provide_index; // Import your custom AppError type pub async fn create_link( root: &PathBuf, url: &str, title: &str, desc: Option, -) -> Result<(), String> { - let url = Url::parse(url).map_err(|_| "Invalid url")?; +) -> Result<(), AppError> { + let url = Url::parse(url) + .map_err(|_| AppError::LinkCreationError("Invalid url".to_owned()))?; let link: Link = Link::new(url, title.to_owned(), desc.to_owned()); - link.save(&root, true) + link.save(root, true) .await - .map_err(|e| e.to_string()) + .map_err(|e| AppError::LinkCreationError(e.to_string())) } pub fn load_link( root: &PathBuf, file_path: &Option, id: &Option, -) -> Result { +) -> Result { let path_from_index = id.map(|id| { - let index = provide_index(&root); + let index = provide_index(root); index.id2path[&id].as_path().to_path_buf() }); let path_from_user = file_path; let path = match (path_from_user, path_from_index) { (Some(path), Some(path2)) => { - if path.canonicalize().unwrap() != path2 { - Err(format!( + if path.canonicalize()? != path2 { + Err(AppError::LinkLoadError(format!( "Path {:?} was requested. But id {} maps to path {:?}", path, id.unwrap(), path2, - )) + ))) } else { Ok(path.to_path_buf()) } } (Some(path), None) => Ok(path.to_path_buf()), (None, Some(path)) => Ok(path), - (None, None) => Err("Provide a path or id for request.".to_owned())?, + (None, None) => Err(AppError::LinkLoadError( + "Provide a path or id for request.".to_owned(), + ))?, }?; - arklib::link::Link::load(root, &path).map_err(|e| e.to_string()) + Ok(arklib::link::Link::load(root, &path)?) } diff --git a/ark-cli/src/error.rs b/ark-cli/src/error.rs new file mode 100644 index 00000000..59bd92d6 --- /dev/null +++ b/ark-cli/src/error.rs @@ -0,0 +1,57 @@ +use arklib::ArklibError; +use std::io; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum InlineJsonParseError { + #[error("Invalid JSON: entries must be key-value pairs seperated by ':'")] + InvalidKeyValPair, +} + +#[derive(Debug, Error)] +pub enum AppError { + #[error("Couldn't retrieve home directory!")] + HomeDirNotFound, + + #[error("Couldn't create .ark directory: {0}")] + ArkDirectoryCreationError(String), + + #[error("Couldn't load app id: {0}")] + AppIdLoadError(String), + + #[error("Could not provide/read index: {0}")] + IndexError(String), + + #[error("Could not create storage: {0}")] + StorageCreationError(String), + + #[error("Failed to create link: {0}")] + LinkCreationError(String), + + #[error("Could not load link: {0}")] + LinkLoadError(String), + + #[error("File operation error: {0}")] + FileOperationError(String), + + #[error("Failed to create backup: {0}")] + BackupCreationError(String), + + #[error("Unknown render option")] + InvalidRenderOption, + + #[error("Storage not found: {0}")] + StorageNotFound(String), + + #[error("Invalid entry option")] + InvalidEntryOption, + + #[error(transparent)] + IoError(#[from] io::Error), + + #[error(transparent)] + ArklibError(#[from] ArklibError), + + #[error(transparent)] + InlineJsonParseError(#[from] InlineJsonParseError), +} diff --git a/ark-cli/src/main.rs b/ark-cli/src/main.rs index 3375f309..51b441ea 100644 --- a/ark-cli/src/main.rs +++ b/ark-cli/src/main.rs @@ -1,5 +1,5 @@ use std::fs::{create_dir_all, File}; -use std::io::Write; +use std::io::{Read, Write}; use std::path::PathBuf; use std::str::FromStr; @@ -22,12 +22,15 @@ use crate::models::format::Format; use crate::models::sort::Sort; use crate::models::storage::{Storage, StorageType}; +use crate::error::AppError; + use util::{ discover_roots, monitor_index, provide_root, read_storage_value, storages_exists, timestamp, translate_storage, }; mod commands; +mod error; mod models; mod util; @@ -35,28 +38,41 @@ const ARK_CONFIG: &str = ".config/ark"; const ARK_BACKUPS_PATH: &str = ".ark-backups"; const ROOTS_CFG_FILENAME: &str = "roots"; +struct StorageEntry { + path: Option, + resource: Option, + content: Option, + tags: Option>, + scores: Option, + datetime: Option, +} + #[tokio::main] -async fn main() { +async fn main() -> anyhow::Result<()> { env_logger::init(); let args = models::cli::Cli::parse(); - let app_id_dir = home_dir().expect("Couldn't retrieve home directory!"); + let app_id_dir = home_dir().ok_or(AppError::HomeDirNotFound)?; + let ark_dir = app_id_dir.join(".ark"); + if !ark_dir.exists() { - std::fs::create_dir(&ark_dir).unwrap(); + std::fs::create_dir(&ark_dir) + .map_err(|e| AppError::ArkDirectoryCreationError(e.to_string()))?; } + println!("Loading app id at {}...", ark_dir.display()); - let _ = app_id::load(ark_dir).map_err(|e| { - println!("Couldn't load app id: {}", e); - std::process::exit(1); - }); + + let _ = app_id::load(ark_dir) + .map_err(|e| AppError::AppIdLoadError(e.to_string()))?; match &args.command { Command::List { entry, entry_id, entry_path, + entry_link, root_dir, modified, @@ -65,111 +81,293 @@ async fn main() { sort, filter, } => { - let root = provide_root(root_dir); - - let entry_output = match (entry, entry_id, entry_path) { - (Some(e), false, false) => e, - (None, true, false) => &EntryOutput::Id, - (None, false, true) => &EntryOutput::Path, - (None, true, true) => &EntryOutput::Both, - (None, false, false) => &EntryOutput::Id, // default mode - _ => panic!( - "incompatible entry output options, please choose only one" - ), - }; - - let index = provide_index(&root).expect("could not provide index"); - - let resource_index = index.read().expect("could not read index"); - - let mut resources = resource_index + let root = provide_root(root_dir)?; + + let entry_output = match (entry, entry_id, entry_path, entry_link) { + (Some(e), false, false, false) => Ok(*e), + (None, true, false, false) => Ok(EntryOutput::Id), + (None, false, true, false) => Ok(EntryOutput::Path), + (None, true, true, false) => Ok(EntryOutput::Both), + (None, false, false, false) => Ok(EntryOutput::Id), + (None, false, false, true) => Ok(EntryOutput::Link), + _ => Err(AppError::InvalidEntryOption), + }?; + + let mut storage_entries: Vec = provide_index(&root) + .map_err(|_| { + AppError::IndexError("Could not provide index".to_owned()) + })? + .read() + .map_err(|_| { + AppError::IndexError("Could not read index".to_owned()) + })? .path2id .iter() - .map(|(path, resource)| { - let tags_list = read_storage_value( - &root, - "tags", - &resource.id.to_string(), - &None, - ) - .unwrap_or("NO_TAGS".to_string()); - - let scores_list = read_storage_value( - &root, - "scores", - &resource.id.to_string(), - &None, - ) - .unwrap_or("NO_SCORE".to_string()); - - let datetime = DateTime::::from(resource.modified); - - (path, resource, tags_list, scores_list, datetime) + .filter_map(|(path, resource)| { + let tags = if *tags { + Some( + read_storage_value( + &root, + "tags", + &resource.id.to_string(), + &None, + ) + .map_or(vec![], |s| { + s.split(',') + .map(|s| s.trim().to_string()) + .collect::>() + }), + ) + } else { + None + }; + + let scores = if *scores { + Some( + read_storage_value( + &root, + "scores", + &resource.id.to_string(), + &None, + ) + .map_or(0, |s| s.parse::().unwrap_or(0)), + ) + } else { + None + }; + + let datetime = if *modified { + let format = "%b %e %H:%M %Y"; + Some( + DateTime::::from(resource.modified) + .format(format) + .to_string(), + ) + } else { + None + }; + + let (path, resource, content) = match entry_output { + EntryOutput::Both => ( + Some(path.to_owned().into_path_buf()), + Some(resource.id), + None, + ), + EntryOutput::Path => { + (Some(path.to_owned().into_path_buf()), None, None) + } + EntryOutput::Id => (None, Some(resource.id), None), + EntryOutput::Link => match File::open(&path) { + Ok(mut file) => { + let mut contents = String::new(); + match file.read_to_string(&mut contents) { + Ok(_) => (None, None, Some(contents)), + Err(_) => return None, + } + } + Err(_) => return None, + }, + }; + + Some(StorageEntry { + path, + resource, + content, + tags, + scores, + datetime, + }) }) .collect::>(); match sort { - Some(Sort::Asc) => resources - .sort_by(|(_, _, _, _, a), (_, _, _, _, b)| a.cmp(b)), + Some(Sort::Asc) => { + storage_entries.sort_by(|a, b| a.datetime.cmp(&b.datetime)) + } - Some(Sort::Desc) => resources - .sort_by(|(_, _, _, _, a), (_, _, _, _, b)| b.cmp(a)), + Some(Sort::Desc) => { + storage_entries.sort_by(|a, b| b.datetime.cmp(&a.datetime)) + } None => (), }; if let Some(filter) = filter { - resources = resources - .into_iter() - .filter(|(_, _, tags_list, _, _)| { - tags_list - .split(',') - .any(|tag| tag.trim() == filter) - }) - .collect(); + storage_entries.retain(|entry| { + entry + .tags + .as_ref() + .map(|tags| tags.contains(filter)) + .unwrap_or(false) + }); } - for (path, resource, tags_list, scores_list, datetime) in resources - { - let mut output = String::new(); + let no_tags = "NO_TAGS"; + let no_scores = "NO_SCORE"; + + let longest_path = storage_entries + .iter() + .map(|entry| { + if let Some(path) = entry.path.as_ref() { + path.display().to_string().len() + } else { + 0 + } + }) + .max_by(|a, b| a.cmp(b)) + .unwrap_or(0); + + let longest_id = storage_entries.iter().fold(0, |acc, entry| { + if let Some(resource) = &entry.resource { + let id_len = resource.to_string().len(); + if id_len > acc { + id_len + } else { + acc + } + } else { + acc + } + }); + + let longest_tags = storage_entries.iter().fold(0, |acc, entry| { + let tags_len = entry + .tags + .as_ref() + .map(|tags| { + if tags.is_empty() { + no_tags.len() + } else { + tags.join(", ").len() + } + }) + .unwrap_or(0); + if tags_len > acc { + tags_len + } else { + acc + } + }); + + let longest_scores = + storage_entries.iter().fold(0, |acc, entry| { + let scores_len = entry + .scores + .as_ref() + .map(|score| { + if *score == 0 { + no_scores.len() + } else { + score.to_string().len() + } + }) + .unwrap_or(0); + if scores_len > acc { + scores_len + } else { + acc + } + }); - let entry_str = match entry_output { - EntryOutput::Id => resource.id.to_string(), - EntryOutput::Path => path.display().to_string(), - EntryOutput::Both => { - format!("{}@{}", resource.id, path.display()) + let longest_datetime = + storage_entries.iter().fold(0, |acc, entry| { + let datetime_len = entry + .datetime + .as_ref() + .map(|datetime| datetime.len()) + .unwrap_or(0); + if datetime_len > acc { + datetime_len + } else { + acc } - }; + }); + + let longest_content = + storage_entries.iter().fold(0, |acc, entry| { + let content_len = entry + .content + .as_ref() + .map(|content| content.len()) + .unwrap_or(0); + if content_len > acc { + content_len + } else { + acc + } + }); + + for entry in &storage_entries { + let mut output = String::new(); - output.push_str(&entry_str); + if let Some(content) = &entry.content { + output.push_str(&format!( + "{:width$} ", + content, + width = longest_content + )); + } - if *modified { - let timestamp_str = datetime - .format("%Y-%m-%d %H:%M:%S.%f") - .to_string(); + if let Some(path) = &entry.path { output.push_str(&format!( - " last modified on {}", - timestamp_str + "{:width$} ", + path.display(), + width = longest_path )); } - if *tags { - output.push_str(&format!(" with tags {}", tags_list)); + if let Some(resource) = &entry.resource { + output.push_str(&format!( + "{:width$} ", + resource.to_string(), + width = longest_id + )); + } + + if let Some(tags) = &entry.tags { + let tags_out = if tags.is_empty() { + no_tags.to_owned() + } else { + tags.join(", ") + }; + + output.push_str(&format!( + "{:width$} ", + tags_out, + width = longest_tags + )); + } + + if let Some(scores) = &entry.scores { + let scores_out = if *scores == 0 { + no_scores.to_owned() + } else { + scores.to_string() + }; + + output.push_str(&format!( + "{:width$} ", + scores_out, + width = longest_scores + )); } - if *scores { - output.push_str(&format!(" with score {}", scores_list)); + if let Some(datetime) = &entry.datetime { + output.push_str(&format!( + "{:width$} ", + datetime, + width = longest_datetime + )); } println!("{}", output); } } - Command::Backup { roots_cfg } => { let timestamp = timestamp().as_secs(); let backup_dir = home_dir() - .expect("Couldn't retrieve home directory!") - .join(&ARK_BACKUPS_PATH) - .join(×tamp.to_string()); + .ok_or(AppError::HomeDirNotFound)? + .join(ARK_BACKUPS_PATH) + .join(timestamp.to_string()); if backup_dir.is_dir() { println!("Wait at least 1 second, please!"); @@ -177,11 +375,11 @@ async fn main() { } println!("Preparing backup:"); - let roots = discover_roots(roots_cfg); + let roots = discover_roots(roots_cfg)?; let (valid, invalid): (Vec, Vec) = roots .into_iter() - .partition(|root| storages_exists(&root)); + .partition(|root| storages_exists(root)); if !invalid.is_empty() { println!("These folders don't contain any storages:"); @@ -195,16 +393,20 @@ async fn main() { std::process::exit(0) } - create_dir_all(&backup_dir) - .expect("Couldn't create backup directory!"); + create_dir_all(&backup_dir).map_err(|_| { + AppError::BackupCreationError( + "Couldn't create backup directory!".to_owned(), + ) + })?; let mut roots_cfg_backup = - File::create(&backup_dir.join(&ROOTS_CFG_FILENAME)) - .expect("Couldn't backup roots config!"); + File::create(backup_dir.join(ROOTS_CFG_FILENAME))?; valid.iter().for_each(|root| { - writeln!(roots_cfg_backup, "{}", root.display()) - .expect("Couldn't write to roots config backup!") + let res = writeln!(roots_cfg_backup, "{}", root.display()); + if let Err(e) = res { + println!("Failed to write root to backup file: {}", e); + } }); println!("Performing backups:"); @@ -213,14 +415,14 @@ async fn main() { .enumerate() .for_each(|(i, root)| { println!("\tRoot {}", root.display()); - let storage_backup = backup_dir.join(&i.to_string()); + let storage_backup = backup_dir.join(i.to_string()); let mut options = CopyOptions::new(); options.overwrite = true; options.copy_inside = true; let result = dir::copy( - root.join(&arklib::ARK_FOLDER), + root.join(arklib::ARK_FOLDER), storage_backup, &options, ); @@ -232,19 +434,19 @@ async fn main() { println!("Backup created:\n\t{}", backup_dir.display()); } - Command::Collisions { root_dir } => monitor_index(&root_dir, None), + Command::Collisions { root_dir } => monitor_index(root_dir, None)?, Command::Monitor { root_dir, interval } => { let millis = interval.unwrap_or(1000); - monitor_index(&root_dir, Some(millis)) + monitor_index(root_dir, Some(millis))? } Command::Render { path, quality } => { let filepath = path.to_owned().unwrap(); let quality = match quality.to_owned().unwrap().as_str() { - "high" => PDFQuality::High, - "medium" => PDFQuality::Medium, - "low" => PDFQuality::Low, - _ => panic!("unknown render option"), - }; + "high" => Ok(PDFQuality::High), + "medium" => Ok(PDFQuality::Medium), + "low" => Ok(PDFQuality::Low), + _ => Err(AppError::InvalidRenderOption), + }?; let buf = File::open(&filepath).unwrap(); let dest_path = filepath.with_file_name( filepath @@ -256,7 +458,7 @@ async fn main() { + ".png", ); let img = arklib::pdf::render_preview_page(buf, quality); - img.save(PathBuf::from(dest_path)).unwrap(); + img.save(dest_path).unwrap(); } Command::Link(link) => match &link { Link::Create { @@ -265,11 +467,17 @@ async fn main() { title, desc, } => { - let root = provide_root(root_dir); - let url = url.as_ref().expect("ERROR: Url was not provided"); - let title = title - .as_ref() - .expect("ERROR: Title was not provided"); + let root = provide_root(root_dir)?; + let url = url.as_ref().ok_or_else(|| { + AppError::LinkCreationError( + "Url was not provided".to_owned(), + ) + })?; + let title = title.as_ref().ok_or_else(|| { + AppError::LinkCreationError( + "Title was not provided".to_owned(), + ) + })?; println!("Saving link..."); @@ -284,7 +492,7 @@ async fn main() { Ok(_) => { println!("Link saved successfully!"); } - Err(e) => println!("ERROR: {}", e), + Err(e) => println!("{}", e), } } @@ -293,15 +501,9 @@ async fn main() { file_path, id, } => { - let root = provide_root(root_dir); - let link = commands::link::load_link(&root, file_path, id); - - match link { - Ok(link) => { - println!("Link data:\n{:?}", link); - } - Err(e) => println!("ERROR: {}", e), - } + let root = provide_root(root_dir)?; + let link = commands::link::load_link(&root, file_path, id)?; + println!("Link data:\n{:?}", link); } }, Command::File(file) => match &file { @@ -315,7 +517,7 @@ async fn main() { } => { let (file_path, storage_type) = translate_storage(&Some(root_dir.to_owned()), storage) - .expect("ERROR: Could not find storage folder"); + .ok_or(AppError::StorageNotFound(storage.to_owned()))?; let storage_type = storage_type.unwrap_or(match type_ { Some(t) => *t, @@ -324,15 +526,11 @@ async fn main() { let format = format.unwrap_or(Format::Raw); - let mut storage = Storage::new(file_path, storage_type) - .expect("ERROR: Could not create storage"); + let mut storage = Storage::new(file_path, storage_type)?; - let resource_id = ResourceId::from_str(id) - .expect("ERROR: Could not parse id"); + let resource_id = ResourceId::from_str(id)?; - storage - .append(resource_id, content, format) - .expect("ERROR: Could not append content to storage"); + storage.append(resource_id, content, format)?; } FileCommand::Insert { @@ -345,7 +543,7 @@ async fn main() { } => { let (file_path, storage_type) = translate_storage(&Some(root_dir.to_owned()), storage) - .expect("ERROR: Could not find storage folder"); + .ok_or(AppError::StorageNotFound(storage.to_owned()))?; let storage_type = storage_type.unwrap_or(match type_ { Some(t) => *t, @@ -354,15 +552,11 @@ async fn main() { let format = format.unwrap_or(Format::Raw); - let mut storage = Storage::new(file_path, storage_type) - .expect("ERROR: Could not create storage"); + let mut storage = Storage::new(file_path, storage_type)?; - let resource_id = ResourceId::from_str(id) - .expect("ERROR: Could not parse id"); + let resource_id = ResourceId::from_str(id)?; - storage - .insert(resource_id, content, format) - .expect("ERROR: Could not insert content to storage"); + storage.insert(resource_id, content, format)?; } FileCommand::Read { @@ -373,25 +567,20 @@ async fn main() { } => { let (file_path, storage_type) = translate_storage(&Some(root_dir.to_owned()), storage) - .expect("ERROR: Could not find storage folder"); + .ok_or(AppError::StorageNotFound(storage.to_owned()))?; let storage_type = storage_type.unwrap_or(match type_ { Some(t) => *t, None => StorageType::File, }); - let mut storage = Storage::new(file_path, storage_type) - .expect("ERROR: Could not create storage"); + let mut storage = Storage::new(file_path, storage_type)?; - let resource_id = ResourceId::from_str(id) - .expect("ERROR: Could not parse id"); + let resource_id = ResourceId::from_str(id)?; - let output = storage.read(resource_id); + let output = storage.read(resource_id)?; - match output { - Ok(output) => println!("{}", output), - Err(e) => println!("ERROR: {}", e), - } + println!("{}", output); } }, Command::Storage(cmd) => match &cmd { @@ -401,34 +590,34 @@ async fn main() { type_, versions, } => { - let storage = storage - .as_ref() - .expect("ERROR: Storage was not provided"); + let storage = + storage + .as_ref() + .ok_or(AppError::StorageCreationError( + "Storage was not provided".to_owned(), + ))?; let versions = versions.unwrap_or(false); let (file_path, storage_type) = translate_storage(root_dir, storage) - .expect("ERROR: Could not find storage folder"); + .ok_or(AppError::StorageNotFound(storage.to_owned()))?; let storage_type = storage_type.unwrap_or(match type_ { Some(t) => *t, None => StorageType::File, }); - let mut storage = Storage::new(file_path, storage_type) - .expect("ERROR: Could not create storage"); + let mut storage = Storage::new(file_path, storage_type)?; - storage - .load() - .expect("ERROR: Could not load storage"); + storage.load()?; - let output = storage - .list(versions) - .expect("ERROR: Could not list storage content"); + let output = storage.list(versions)?; println!("{}", output); } }, - } + }; + + Ok(()) } diff --git a/ark-cli/src/models/cli.rs b/ark-cli/src/models/cli.rs index 322b39d8..24f3d485 100644 --- a/ark-cli/src/models/cli.rs +++ b/ark-cli/src/models/cli.rs @@ -52,6 +52,9 @@ pub enum Command { #[clap(long, short = 'p', action)] entry_path: bool, + #[clap(long, short = 'l', action)] + entry_link: bool, + #[clap(long, short, action)] modified: bool, diff --git a/ark-cli/src/models/entry.rs b/ark-cli/src/models/entry.rs index 174d54a6..475909bf 100644 --- a/ark-cli/src/models/entry.rs +++ b/ark-cli/src/models/entry.rs @@ -1,7 +1,8 @@ use clap::Parser; -#[derive(Parser, Debug)] +#[derive(Parser, Debug, Clone, Copy, PartialEq, Eq)] pub enum EntryOutput { + Link, Id, Path, Both, @@ -15,6 +16,7 @@ impl std::str::FromStr for EntryOutput { "id" => Ok(EntryOutput::Id), "path" => Ok(EntryOutput::Path), "both" => Ok(EntryOutput::Both), + "link" => Ok(EntryOutput::Link), _ => Err("Entry output must be either 'id', 'path' or 'both'"), } } diff --git a/ark-cli/src/models/format.rs b/ark-cli/src/models/format.rs index 33f487eb..c8d6fb55 100644 --- a/ark-cli/src/models/format.rs +++ b/ark-cli/src/models/format.rs @@ -1,3 +1,5 @@ +use crate::error::InlineJsonParseError; + #[derive(Debug, Clone, Copy)] pub enum Format { KeyValue, @@ -16,7 +18,9 @@ impl std::str::FromStr for Format { } } -pub fn key_value_to_str(s: &str) -> Result, String> { +pub fn key_value_to_str( + s: &str, +) -> Result, InlineJsonParseError> { let pairs: Vec<&str> = s.split(',').collect(); let mut values = Vec::new(); @@ -28,7 +32,7 @@ pub fn key_value_to_str(s: &str) -> Result, String> { let value = key_value[1].trim().to_string(); values.push((key, value)); } else { - return Err("Invalid key-value pair format".to_owned()); + return Err(InlineJsonParseError::InvalidKeyValPair); } } diff --git a/ark-cli/src/models/storage.rs b/ark-cli/src/models/storage.rs index f9ed932b..6e49d32b 100644 --- a/ark-cli/src/models/storage.rs +++ b/ark-cli/src/models/storage.rs @@ -7,6 +7,7 @@ use crate::{ self, file::{format_file, format_line}, }, + error::AppError, models::format::Format, }; @@ -38,53 +39,42 @@ impl Storage { pub fn new>( path: P, storage_type: StorageType, - ) -> Result { + ) -> Result { let path = path.into(); if !path.exists() { std::fs::create_dir_all(&path).map_err(|e| { - format!( + AppError::StorageCreationError(format!( "Failed to create storage folder at {:?} with error: {:?}", path, e - ) + )) })?; } Ok(Self { - path: path.into(), + path, storage_type, files: Vec::new(), }) } #[allow(dead_code)] - pub fn load(&mut self) -> Result<(), String> { + pub fn load(&mut self) -> Result<(), AppError> { match self.storage_type { StorageType::File => { - let atomic_file = - AtomicFile::new(self.path.clone()).map_err(|e| { - format!( - "Failed to create atomic file at {:?} with error: {:?}", - self.path, e - ) - })?; + let atomic_file = AtomicFile::new(self.path.clone())?; - let atomic_file_data = atomic_file.load().map_err(|e| { - format!( - "Failed to load atomic file at {:?} with error: {:?}", - self.path, e - ) - })?; + let atomic_file_data = atomic_file.load()?; - let data = atomic_file_data.read_to_string().map_err(|_| { - "Could not read atomic file content.".to_string() - })?; + let data = atomic_file_data.read_to_string()?; for (i, line) in data.lines().enumerate() { let mut line = line.split(':'); let id = line.next().unwrap(); match id.parse::().map_err(|_| { - format!("Failed to parse ResourceId from line: {i}",) + AppError::IndexError(format!( + "Failed to parse ResourceId from line: {i}", + )) }) { Ok(id) => self.files.push(id), Err(e) => { @@ -96,20 +86,26 @@ impl Storage { StorageType::Folder => { let folder_entries = std::fs::read_dir(&self.path).map_err(|e| { - format!( + AppError::FileOperationError(format!( "Failed to read folder at {:?} with error: {:?}", self.path, e - ) + )) })?; for entry in folder_entries { let entry = entry.map_err(|e| { - format!("Error reading folder entry: {:?}", e) + AppError::FileOperationError(format!( + "Error reading folder entry: {:?}", + e + )) })?; if let Some(file_name) = entry.file_name().to_str() { let id = file_name.parse::().map_err(|_| { - format!("Failed to parse ResourceId from folder entry: {:?}", file_name) + AppError::IndexError(format!( + "Failed to parse ResourceId from folder entry: {:?}", + file_name + )) })?; self.files.push(id); } @@ -125,21 +121,23 @@ impl Storage { id: ResourceId, content: &str, format: Format, - ) -> Result<(), String> { + ) -> Result<(), AppError> { match self.storage_type { StorageType::File => { let atomic_file = AtomicFile::new(&self.path).map_err(|e| { - format!( + AppError::FileOperationError(format!( "Failed to create atomic file at {} with error: {:?}", self.path.display(), e - ) + )) })?; let content = match format { Format::KeyValue => return Err( - "Key value format is not supported for file storage" - .to_owned(), + AppError::StorageCreationError( + "Key value format is not supported for file storage" + .to_owned(), + ), ), Format::Raw => format!("{}:{}\n", id, content), }; @@ -149,81 +147,74 @@ impl Storage { &content, Format::Raw, ) { - Ok(_) => { - return Ok(()); - } - Err(e) => { - return Err(e); - } + Ok(_) => Ok(()), + Err(e) => Err(e), } } StorageType::Folder => { let folder_path = self.path.join(id.to_string()); if !folder_path.exists() { std::fs::create_dir_all(&folder_path).map_err(|e| { - format!( + AppError::StorageCreationError(format!( "Failed to create folder at {:?} with error: {:?}", folder_path, e - ) + )) })?; } let atomic_file = AtomicFile::new(&folder_path) .map_err(|e| { - format!( + AppError::FileOperationError(format!( "Failed to create atomic file at {} with error: {:?}", self.path.display(), e - ) + )) })?; - match commands::file::file_append( - &atomic_file, - &content, - format, - ) { - Ok(_) => { - return Ok(()); - } - Err(e) => { - return Err(e); - } + match commands::file::file_append(&atomic_file, content, format) + { + Ok(_) => Ok(()), + Err(e) => Err(e), } } - }; + } } - pub fn read(&mut self, id: ResourceId) -> Result { + pub fn read(&mut self, id: ResourceId) -> Result { match self.storage_type { StorageType::File => { let atomic_file = AtomicFile::new(&self.path).map_err(|e| { - format!( + AppError::FileOperationError(format!( "Failed to create atomic file at {} with error: {:?}", self.path.display(), e - ) + )) })?; let atomic_file_data = atomic_file.load().map_err(|e| { - format!( + AppError::FileOperationError(format!( "Failed to load atomic file at {:?} with error: {:?}", self.path, e - ) + )) })?; let data = atomic_file_data.read_to_string().map_err(|_| { - "Could not read atomic file content.".to_string() + AppError::FileOperationError( + "Could not read atomic file content.".to_string(), + ) })?; for (i, line) in data.lines().enumerate() { let mut line = line.split(':'); let line_id: &str = line.next().unwrap(); match line_id.parse::().map_err(|_| { - format!("Failed to parse ResourceId from line: {i}",) + AppError::IndexError(format!( + "Failed to parse ResourceId from line: {i}", + )) }) { Ok(line_id) => { if id == line_id { let data = line.next().unwrap(); - return Ok(format!("{}", data)); + return Ok(data.to_string()); } } Err(e) => { @@ -232,31 +223,39 @@ impl Storage { } } - Err(format!("Resource with id {} not found", id)) + Err(AppError::StorageNotFound(format!( + "Resource with id {} not found", + id + ))) } StorageType::Folder => { let folder_path = self.path.join(id.to_string()); if !folder_path.exists() { - return Err(format!("Resource with id {} not found", id)); + return Err(AppError::StorageNotFound(format!( + "Resource with id {} not found", + id + ))); } let atomic_file = AtomicFile::new(&folder_path) .map_err(|e| { - format!( + AppError::FileOperationError(format!( "Failed to create atomic file at {} with error: {:?}", self.path.display(), e - ) + )) })?; let atomic_file_data = atomic_file.load().map_err(|e| { - format!( + AppError::FileOperationError(format!( "Failed to load atomic file at {:?} with error: {:?}", self.path, e - ) + )) })?; let data = atomic_file_data.read_to_string().map_err(|_| { - "Could not read atomic file content.".to_string() + AppError::FileOperationError( + "Could not read atomic file content.".to_string(), + ) })?; Ok(data) @@ -269,21 +268,23 @@ impl Storage { id: ResourceId, content: &str, format: Format, - ) -> Result<(), String> { + ) -> Result<(), AppError> { match self.storage_type { StorageType::File => { let atomic_file = AtomicFile::new(&self.path).map_err(|e| { - format!( + AppError::FileOperationError(format!( "Failed to create atomic file at {} with error: {:?}", self.path.display(), e - ) + )) })?; let content = match format { Format::KeyValue => return Err( - "Key value format is not supported for file storage" - .to_owned(), + AppError::StorageCreationError( + "Key value format is not supported for file storage" + .to_owned(), + ), ), Format::Raw => format!("{}:{}\n", id, content), }; @@ -293,81 +294,79 @@ impl Storage { &content, Format::Raw, ) { - Ok(_) => { - return Ok(()); - } - Err(e) => { - return Err(e); - } + Ok(_) => Ok(()), + Err(e) => Err(e), } } StorageType::Folder => { let folder_path = self.path.join(id.to_string()); if !folder_path.exists() { std::fs::create_dir_all(&folder_path).map_err(|e| { - format!( + AppError::StorageCreationError(format!( "Failed to create folder at {:?} with error: {:?}", folder_path, e - ) + )) })?; } let atomic_file = AtomicFile::new(&folder_path) .map_err(|e| { - format!( + AppError::FileOperationError(format!( "Failed to create atomic file at {} with error: {:?}", self.path.display(), e - ) + )) })?; - match commands::file::file_insert( - &atomic_file, - &content, - format, - ) { - Ok(_) => { - return Ok(()); - } - Err(e) => { - return Err(e); - } + match commands::file::file_insert(&atomic_file, content, format) + { + Ok(_) => Ok(()), + Err(e) => Err(e), } } - }; + } } - pub fn list(&self, versions: bool) -> Result { + pub fn list(&self, versions: bool) -> Result { let mut output = String::new(); if !versions { for id in &self.files { - writeln!(output, "{}", id) - .map_err(|_| "Could not write to output".to_string())?; + writeln!(output, "{}", id).map_err(|_| { + AppError::FileOperationError( + "Could not write to output".to_string(), + ) + })?; } } else { match self.storage_type { StorageType::File => { let atomic_file = AtomicFile::new(&self.path) .map_err(|e| { - format!( + AppError::FileOperationError(format!( "Failed to create atomic file at {} with error: {:?}", self.path.display(), e - ) + )) })?; let atomic_file_data = atomic_file.load().map_err(|e| { - format!( + AppError::FileOperationError(format!( "Failed to load atomic file at {:?} with error: {:?}", self.path, e - ) + )) })?; - writeln!(output, "{: <16} {}", "id", "value") - .map_err(|_| "Could not write to output".to_string())?; + writeln!(output, "{: <16} value", "id").map_err(|_| { + AppError::FileOperationError( + "Could not write to output".to_string(), + ) + })?; let data = atomic_file_data.read_to_string().map_err(|_| { - "Could not read atomic file content.".to_string() + AppError::FileOperationError( + "Could not read atomic file content." + .to_string(), + ) })?; for line in data.lines() { @@ -375,24 +374,24 @@ impl Storage { let id = line.next(); let data = line.next(); - match (id, data) { - (Some(id), Some(data)) => { - writeln!(output, "{: <16} {}", id, data) - .map_err(|_| { - "Could not write to output".to_string() - })?; - } - _ => {} + if let (Some(id), Some(data)) = (id, data) { + writeln!(output, "{: <16} {}", id, data).map_err( + |_| { + AppError::FileOperationError( + "Could not write to output".to_string(), + ) + }, + )?; } } } StorageType::Folder => { let folder_entries = std::fs::read_dir(&self.path) .map_err(|e| { - format!( + AppError::FileOperationError(format!( "Failed to read folder at {:?} with error: {:?}", self.path, e - ) + )) })? .filter_map(|v| v.ok()) .filter(|e| { @@ -412,12 +411,18 @@ impl Storage { "{}", format_line("version", "name", "machine", "path"), ) - .map_err(|_| "Could not write to output".to_string())?; + .map_err(|_| { + AppError::FileOperationError( + "Could not write to output".to_string(), + ) + })?; for entry in folder_entries { if let Some(file) = format_file(&entry) { writeln!(output, "{}", file).map_err(|_| { - "Could not write to output".to_string() + AppError::FileOperationError( + "Could not write to output".to_string(), + ) })?; } } diff --git a/ark-cli/src/util.rs b/ark-cli/src/util.rs index 3d3ffa95..65905e76 100644 --- a/ark-cli/src/util.rs +++ b/ark-cli/src/util.rs @@ -15,58 +15,56 @@ use std::thread; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; use std::{fs::File, path::PathBuf}; +use crate::error::AppError; use crate::models::storage::{Storage, StorageType}; use crate::ARK_CONFIG; -pub fn discover_roots(roots_cfg: &Option) -> Vec { +pub fn discover_roots( + roots_cfg: &Option, +) -> Result, AppError> { if let Some(path) = roots_cfg { println!( "\tRoots config provided explicitly:\n\t\t{}", path.display() ); - let config = File::open(&path).expect("File doesn't exist!"); + let config = File::open(path)?; - parse_roots(config) + Ok(parse_roots(config)) + } else if let Ok(config) = File::open(ARK_CONFIG) { + println!( + "\tRoots config was found automatically:\n\t\t{}", + &ARK_CONFIG + ); + + Ok(parse_roots(config)) } else { - if let Ok(config) = File::open(&ARK_CONFIG) { - println!( - "\tRoots config was found automatically:\n\t\t{}", - &ARK_CONFIG - ); + println!("\tRoots config wasn't found."); + + println!("Looking for a folder containing tag storage:"); + let path = + canonicalize(current_dir().expect("Can't open current directory!")) + .expect("Couldn't canonicalize working directory!"); + + let result = path.ancestors().find(|path| { + println!("\t{}", path.display()); + storages_exists(path) + }); - parse_roots(config) + if let Some(root) = result { + println!("Root folder found:\n\t{}", root.display()); + Ok(vec![root.to_path_buf()]) } else { - println!("\tRoots config wasn't found."); - - println!("Looking for a folder containing tag storage:"); - let path = canonicalize( - current_dir().expect("Can't open current directory!"), - ) - .expect("Couldn't canonicalize working directory!"); - - let result = path.ancestors().find(|path| { - println!("\t{}", path.display()); - storages_exists(path) - }); - - if let Some(root) = result { - println!("Root folder found:\n\t{}", root.display()); - vec![root.to_path_buf()] - } else { - println!("Root folder wasn't found."); - vec![] - } + println!("Root folder wasn't found."); + Ok(vec![]) } } } -pub fn provide_root(root_dir: &Option) -> PathBuf { +pub fn provide_root(root_dir: &Option) -> Result { if let Some(path) = root_dir { - path.clone() + Ok(path.clone()) } else { - current_dir() - .expect("Can't open current directory!") - .clone() + Ok(current_dir()?) } } @@ -78,12 +76,15 @@ pub fn provide_index(root_dir: &PathBuf) -> ResourceIndex { index.clone() } -pub fn monitor_index(root_dir: &Option, interval: Option) { - let dir_path = provide_root(root_dir); +pub fn monitor_index( + root_dir: &Option, + interval: Option, +) -> Result<(), AppError> { + let dir_path = provide_root(root_dir)?; println!("Building index of folder {}", dir_path.display()); let start = Instant::now(); - let dir_path = provide_root(root_dir); + let result = arklib::provide_index(dir_path); let duration = start.elapsed(); @@ -126,10 +127,12 @@ pub fn monitor_index(root_dir: &Option, interval: Option) { } Err(err) => println!("Failure: {:?}", err), } + + Ok(()) } pub fn storages_exists(path: &Path) -> bool { - let meta = metadata(path.join(&arklib::ARK_FOLDER)); + let meta = metadata(path.join(arklib::ARK_FOLDER)); if let Ok(meta) = meta { return meta.is_dir(); } @@ -138,7 +141,7 @@ pub fn storages_exists(path: &Path) -> bool { } pub fn parse_roots(config: File) -> Vec { - return BufReader::new(config) + BufReader::new(config) .lines() .filter_map(|line| match line { Ok(path) => Some(PathBuf::from(path)), @@ -147,14 +150,14 @@ pub fn parse_roots(config: File) -> Vec { None } }) - .collect(); + .collect() } pub fn timestamp() -> Duration { let start = SystemTime::now(); - return start + start .duration_since(UNIX_EPOCH) - .expect("Time went backwards!"); + .expect("Time went backwards!") } pub fn translate_storage( @@ -170,42 +173,49 @@ pub fn translate_storage( match storage.to_lowercase().as_str() { "tags" => Some(( provide_root(root) + .ok()? .join(ARK_FOLDER) .join(TAG_STORAGE_FILE), Some(StorageType::File), )), "scores" => Some(( provide_root(root) + .ok()? .join(ARK_FOLDER) .join(SCORE_STORAGE_FILE), Some(StorageType::File), )), "stats" => Some(( provide_root(root) + .ok()? .join(ARK_FOLDER) .join(STATS_FOLDER), Some(StorageType::Folder), )), "properties" => Some(( provide_root(root) + .ok()? .join(ARK_FOLDER) .join(PROPERTIES_STORAGE_FOLDER), Some(StorageType::Folder), )), "metadata" => Some(( provide_root(root) + .ok()? .join(ARK_FOLDER) .join(METADATA_STORAGE_FOLDER), Some(StorageType::Folder), )), "previews" => Some(( provide_root(root) + .ok()? .join(ARK_FOLDER) .join(PREVIEWS_STORAGE_FOLDER), Some(StorageType::Folder), )), "thumbnails" => Some(( provide_root(root) + .ok()? .join(ARK_FOLDER) .join(THUMBNAILS_STORAGE_FOLDER), Some(StorageType::Folder), @@ -219,10 +229,10 @@ pub fn read_storage_value( storage: &str, id: &str, type_: &Option, -) -> Result { +) -> Result { let (file_path, storage_type) = translate_storage(&Some(root_dir.to_owned()), storage) - .expect("ERROR: Could not find storage folder"); + .ok_or(AppError::StorageNotFound(storage.to_owned()))?; let storage_type = storage_type.unwrap_or(match type_ { Some(type_) => match type_.to_lowercase().as_str() { @@ -233,11 +243,9 @@ pub fn read_storage_value( None => StorageType::File, }); - let mut storage = Storage::new(file_path, storage_type) - .expect("ERROR: Could not create storage"); + let mut storage = Storage::new(file_path, storage_type)?; - let resource_id = - ResourceId::from_str(id).expect("ERROR: Could not parse id"); + let resource_id = ResourceId::from_str(id)?; storage.read(resource_id) } From 320380227a96cb3753875fcb936247bf1366ccab Mon Sep 17 00:00:00 2001 From: Tarek Elsayed <60650661+tareknaser@users.noreply.github.com> Date: Wed, 3 Apr 2024 05:43:50 +0200 Subject: [PATCH 23/23] docs: fix parameters in Usage of list subcommand (#26) Signed-off-by: Tarek --- ark-cli/USAGE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ark-cli/USAGE.md b/ark-cli/USAGE.md index 19d79286..fe48aac2 100644 --- a/ark-cli/USAGE.md +++ b/ark-cli/USAGE.md @@ -75,7 +75,7 @@ $ ark-cli list ~/Pictures/ But it's a bit boring and doesn't really tell anything, right? Various flags should be used to gain more knowledge about your collections of resources: * `--entry=id|path|both|link` to show the path,the id or both of a resource -* `--timestamp=true` to show or not the last modified timestamp of a resource +* `--modified` to show or not the last modified timestamp of a resource * `--tags=true` to show or not the tags for every resource * `--scores=true` to show or not the scores for every resource * `--sort=asc|desc` to sort resources by asc or dsc order of scores