diff --git a/Cargo.lock b/Cargo.lock index 22edbae..b164951 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,30 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "addr2line" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aho-corasick" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" -dependencies = [ - "memchr", -] - [[package]] name = "android-tzdata" version = "0.1.1" @@ -42,70 +18,65 @@ dependencies = [ ] [[package]] -name = "ansi_term" -version = "0.12.1" +name = "anstream" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" dependencies = [ - "winapi", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", ] [[package]] -name = "arrayref" -version = "0.3.7" +name = "anstyle" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220" [[package]] -name = "arrayvec" -version = "0.5.2" +name = "anstyle-parse" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", + "utf8parse", ] +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "anyhow" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "backtrace" -version = "0.3.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64" -version = "0.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" - [[package]] name = "bitflags" version = "1.3.2" @@ -113,39 +84,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "blake2b_simd" -version = "0.5.11" +name = "bitflags" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" -dependencies = [ - "arrayref", - "arrayvec", - "constant_time_eq", -] +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -155,108 +112,106 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", - "num-traits 0.2.15", - "time", + "num-traits", "wasm-bindgen", - "winapi", + "windows-targets", ] [[package]] name = "clap" -version = "2.34.0" +version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" dependencies = [ - "ansi_term", - "atty", - "bitflags", + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", "strsim", - "textwrap", - "unicode-width", - "vec_map", - "yaml-rust 0.3.5", ] [[package]] -name = "config" -version = "0.11.0" +name = "clap_derive" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1b9d958c2b1368a663f05538fc1b5975adce1e19f435acceae987aceeeb369" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ - "lazy_static", - "nom", - "rust-ini", - "serde 1.0.164", - "serde-hjson", - "serde_json", - "toml", - "yaml-rust 0.4.5", + "heck", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "constant_time_eq" -version = "0.1.5" +name = "clap_lex" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] -name = "core-foundation" -version = "0.9.3" +name = "colorchoice" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - -[[package]] -name = "crossbeam-utils" -version = "0.8.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "csv" -version = "1.2.2" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" dependencies = [ "csv-core", "itoa", "ryu", - "serde 1.0.164", + "serde", ] [[package]] name = "csv-core" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" dependencies = [ "memchr", ] [[package]] -name = "dirs" -version = "1.0.5" +name = "dirs-next" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", "redox_users", @@ -265,280 +220,55 @@ dependencies = [ [[package]] name = "encode_unicode" -version = "0.3.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - -[[package]] -name = "encoding_rs" -version = "0.8.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" -dependencies = [ - "cfg-if", -] +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "errno" -version = "0.3.1" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "errno-dragonfly", "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "failure" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" -dependencies = [ - "backtrace", - "failure_derive", -] - -[[package]] -name = "failure_derive" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "synstructure", -] - -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[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.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "futures-channel" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" -dependencies = [ - "futures-core", -] - -[[package]] -name = "futures-core" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" - -[[package]] -name = "futures-sink" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" - -[[package]] -name = "futures-task" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" - -[[package]] -name = "futures-util" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" -dependencies = [ - "futures-core", - "futures-task", - "pin-project-lite", - "pin-utils", + "windows-sys", ] [[package]] name = "getrandom" -version = "0.1.16" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", - "wasi 0.9.0+wasi-snapshot-preview1", + "wasi", ] [[package]] -name = "gimli" -version = "0.27.2" +name = "heck" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" - -[[package]] -name = "h2" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.1.19" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" - -[[package]] -name = "http" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" - -[[package]] -name = "hyper" -version = "0.14.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "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", -] +checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -551,62 +281,27 @@ dependencies = [ ] [[package]] -name = "idna" -version = "0.4.0" +name = "is-terminal" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "hermit-abi", + "rustix", + "windows-sys", ] -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.1", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "ipnet" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" - [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "js-sys" -version = "0.3.63" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" dependencies = [ "wasm-bindgen", ] @@ -618,41 +313,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] -name = "lexical-core" -version = "0.7.6" +name = "libc" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "arrayvec", - "bitflags", - "cfg-if", - "ryu", - "static_assertions", + "bitflags 2.4.2", + "libc", + "redox_syscall", ] -[[package]] -name = "libc" -version = "0.2.146" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" - -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - [[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "md5" @@ -662,185 +349,40 @@ checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "miniz_oxide" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" -dependencies = [ - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", -] - -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "nom" -version = "5.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08959a387a676302eebf4ddbcbc611da04285579f76f88ee0506c63b1a61dd4b" -dependencies = [ - "lexical-core", - "memchr", - "version_check", -] +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "num-traits" -version = "0.1.43" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" -dependencies = [ - "num-traits 0.2.15", -] - -[[package]] -name = "num-traits" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", ] -[[package]] -name = "object" -version = "0.30.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "openssl" -version = "0.10.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69b3f656a17a6cbc115b5c7a40c616947d213ba182135b014d6051b73ab6f019" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.18", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-src" -version = "111.26.0+1.1.1u" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efc62c9f12b22b8f5208c23a7200a442b2e5999f8bdf80233852122b5a4f6f37" -dependencies = [ - "cc", -] - -[[package]] -name = "openssl-sys" -version = "0.9.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2ce0f250f34a308dcfdbb351f511359857d4ed2134ba715a4eadd46e1ffd617" -dependencies = [ - "cc", - "libc", - "openssl-src", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "percent-encoding" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" - -[[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" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" [[package]] name = "prettytable-rs" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fd04b170004fa2daccf418a7f8253aaf033c27760b5f225889024cf66d7ac2e" +checksum = "eea25e07510aa6ab6547308ebe3c036016d162b8da920dbb079e3ba8acf3d95a" dependencies = [ - "atty", "csv", "encode_unicode", + "is-terminal", "lazy_static", "term", "unicode-width", @@ -848,264 +390,105 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.60" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.28" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] [[package]] name = "redox_syscall" -version = "0.1.57" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] name = "redox_users" -version = "0.3.5" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ "getrandom", - "redox_syscall 0.1.57", - "rust-argon2", -] - -[[package]] -name = "regex" -version = "1.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" - -[[package]] -name = "reqwest" -version = "0.11.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" -dependencies = [ - "base64 0.21.2", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-tls", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "serde 1.0.164", - "serde_json", - "serde_urlencoded", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg", + "libredox", + "thiserror", ] [[package]] name = "rusnapshot" -version = "0.1.0" +version = "0.2.0" dependencies = [ + "anyhow", "chrono", "clap", - "config", - "failure", "md5", - "openssl", "prettytable-rs", - "reqwest", + "serde", "sqlite", ] -[[package]] -name = "rust-argon2" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" -dependencies = [ - "base64 0.13.1", - "blake2b_simd", - "constant_time_eq", - "crossbeam-utils", -] - -[[package]] -name = "rust-ini" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2" - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - [[package]] name = "rustix" -version = "0.37.20" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags", + "bitflags 2.4.2", "errno", - "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys", ] +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" - -[[package]] -name = "schannel" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" -dependencies = [ - "windows-sys 0.42.0", -] - -[[package]] -name = "security-framework" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" -dependencies = [ - "core-foundation-sys", - "libc", -] +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "serde" -version = "0.8.23" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" - -[[package]] -name = "serde" -version = "1.0.164" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" - -[[package]] -name = "serde-hjson" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a3a4e0ea8a88553209f6cc6cfe8724ecad22e1acf372793c27d995290fe74f8" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ - "lazy_static", - "num-traits 0.1.43", - "regex", - "serde 0.8.23", + "serde_derive", ] [[package]] -name = "serde_json" -version = "1.0.96" +name = "serde_derive" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ - "itoa", - "ryu", - "serde 1.0.164", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde 1.0.164", -] - -[[package]] -name = "slab" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" -dependencies = [ - "autocfg", -] - -[[package]] -name = "socket2" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" -dependencies = [ - "libc", - "winapi", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "sqlite" -version = "0.26.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1a534c07ec276fbbe0e55a1c00814d8563da3a2f4d9d9d4c802bd1278db6a" +checksum = "78a97f6ee5b054b7cfddc3b6613fdea4c77af2ef8f8aac3048c7d0be31e605e3" dependencies = [ "libc", "sqlite3-sys", @@ -1113,9 +496,9 @@ dependencies = [ [[package]] name = "sqlite3-src" -version = "0.3.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a260b07ce75a0644c6f5891f34f46db9869e731838e95293469ab17999abcfa3" +checksum = "9448d45899495acd1a46b0b888ae9747c13551fb0d8f4a60ab485da52b040503" dependencies = [ "cc", "pkg-config", @@ -1123,283 +506,79 @@ dependencies = [ [[package]] name = "sqlite3-sys" -version = "0.13.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04d2f028faeb14352df7934b4771806f60d61ce61be1928ec92396d7492e2e54" +checksum = "aed0b61828382e1103930d2d5df1972d493173319730b481192e63d929097321" dependencies = [ "libc", "sqlite3-src", ] -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "strsim" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.109" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "syn" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "unicode-xid", -] - -[[package]] -name = "tempfile" -version = "3.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" -dependencies = [ - "autocfg", - "cfg-if", - "fastrand", - "redox_syscall 0.3.5", - "rustix", - "windows-sys 0.48.0", -] - [[package]] name = "term" -version = "0.5.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" dependencies = [ - "byteorder", - "dirs", + "dirs-next", + "rustversion", "winapi", ] [[package]] -name = "textwrap" -version = "0.11.0" +name = "thiserror" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ - "unicode-width", + "thiserror-impl", ] [[package]] -name = "time" -version = "0.1.45" +name = "thiserror-impl" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", + "proc-macro2", + "quote", + "syn", ] -[[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.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.28.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" -dependencies = [ - "autocfg", - "bytes", - "libc", - "mio", - "pin-project-lite", - "socket2", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", -] - -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde 1.0.164", -] - -[[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.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" -dependencies = [ - "cfg-if", - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" -dependencies = [ - "once_cell", -] - -[[package]] -name = "try-lock" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" - -[[package]] -name = "unicode-bidi" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" - [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" - -[[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] -name = "unicode-xid" -version = "0.2.4" +name = "utf8parse" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - -[[package]] -name = "url" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[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.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "wasi" @@ -1409,9 +588,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.86" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1419,36 +598,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.86" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.18", + "syn", "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-bindgen-macro" -version = "0.2.86" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1456,32 +623,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.86" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.86" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" - -[[package]] -name = "web-sys" -version = "0.3.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" -dependencies = [ - "js-sys", - "wasm-bindgen", -] +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" [[package]] name = "winapi" @@ -1506,157 +663,76 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ "windows-targets", ] [[package]] name = "windows-sys" -version = "0.42.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" [[package]] name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" - -[[package]] -name = "winreg" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" -dependencies = [ - "winapi", -] - -[[package]] -name = "yaml-rust" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" - -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" diff --git a/Cargo.toml b/Cargo.toml index a254765..f7c668c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,21 +1,20 @@ [package] name = "rusnapshot" -version = "0.1.0" +version = "0.2.0" authors = ["edu4rdshl"] edition = "2018" +description = "Simple and handy btrfs snapshoting tool." # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -clap = { version = "2.34.0", features = ["yaml"] } -reqwest = { version = "0.11.18", features = ["default-tls"] } -openssl = { version = "0.10.54", features = ["vendored"] } -config = { version = "0.11.0", features = ["yaml", "json", "toml", "hjson", "ini"] } -failure = "0.1.8" -sqlite = "0.26.0" +clap = { version = "4.4.18", features = ["derive", "env"] } +serde = { version = "1.0.188", features = ["derive"] } +sqlite = "0.33.0" md5 = "0.7.0" -chrono = "0.4.26" -prettytable-rs = "0.8.0" +chrono = "0.4.33" +prettytable-rs = "0.10.0" +anyhow = "1.0.79" [profile.release] diff --git a/src/args.rs b/src/args.rs index cfc6ad5..cf9b501 100644 --- a/src/args.rs +++ b/src/args.rs @@ -1,155 +1,97 @@ use { - crate::structs::Args, - clap::{load_yaml, value_t, App}, - std::{collections::HashMap, path::Path}, + crate::{database, operations, structs::ExtraArgs}, + anyhow::Result, + clap::Parser, + serde::{Deserialize, Serialize}, + sqlite::Connection, }; -pub fn get_args() -> Args { - let yaml = load_yaml!("cli.yml"); - let matches = App::from_yaml(yaml) - .version(clap::crate_version!()) - .get_matches(); - let settings: HashMap = - return_settings(&matches, &mut config::Config::default()); - Args { - create_snapshot: matches.is_present("create-snapshot"), - delete_snapshot: matches.is_present("delete-snapshot"), - list_snapshots: matches.is_present("list-snapshots"), - clean_snapshots: matches.is_present("clean-snapshots") || matches.is_present("keep-only"), - restore_snapshot: matches.is_present("restore-snapshot"), - rw_snapshots: matches.is_present("read-write"), - dest_dir: if matches.is_present("dest-dir") { - value_t!(matches, "dest-dir", String).unwrap_or_else(|_| String::new()) - } else { - return_value_or_default(&settings, "dest_dir", String::new()) - }, - source_dir: if matches.is_present("source-dir") { - value_t!(matches, "source-dir", String).unwrap_or_else(|_| String::new()) - } else { - return_value_or_default(&settings, "source_dir", String::new()) - }, - database_connection: { - let db_file_path = if matches.is_present("database-file") { - value_t!(matches, "database-file", String).unwrap_or_else(|_| String::new()) - } else { - return_value_or_default(&settings, "database_file", String::new()) - }; - if db_file_path.is_empty() { - eprintln!( - "Please specify a database file with -d/--dfile or the database_file option in the config file, it's required for all the operations, leaving." - ); - std::process::exit(1) - } else { - match sqlite::open(&db_file_path) { - Ok(mut connection) => { - let timeout = value_t!(matches, "timeout", usize).unwrap_or_else(|_| 5000); - connection - .set_busy_timeout(timeout) - .expect("Failed to set database timeout"); - connection - } - Err(e) => { - eprintln!( - "Error while trying to stablish the database connection. Error: {}", - e - ); - std::process::exit(1) - } - } - } - }, - snapshot_name: String::new(), - snapshot_id: value_t!(matches, "snapshot-id", String).unwrap_or_else(|_| String::new()), - snapshot_prefix: if matches.is_present("snapshot-prefix") { - value_t!(matches, "snapshot-prefix", String) - .unwrap_or_else(|_| String::from("snapshot")) - } else { - return_value_or_default(&settings, "snapshot_prefix", String::from("snapshot")) - }, - snapshot_kind: if matches.is_present("snapshot-kind") { - value_t!(matches, "snapshot-kind", String) - .unwrap_or_else(|_| String::from("rusnapshot")) - } else { - return_value_or_default(&settings, "snapshot_kind", String::from("rusnapshot")) - }, - snapshot_ro_rw: if matches.is_present("read-write") { - "read-write".to_string() - } else { - "read-only".to_string() - }, - keep_only: if matches.is_present("keep-only") { - value_t!(matches, "keep-only", usize).unwrap_or_else(|_| 0) - } else { - return_value_or_default(&settings, "keep_only", 0.to_string()) - .parse() - .unwrap_or_default() - }, - } +/// Simple and handy btrfs snapshoting tool. +#[derive(Parser, Debug, Default, Serialize, Deserialize, Clone)] +#[clap(author, version, about, long_about = None, arg_required_else_help = true)] +pub struct Args { + /// Path to configuration file. + #[clap(short = 'c', long = "config")] + pub config_file: Option, + /// Directory where snapshots should be saved. + #[clap(long = "to", requires_all = &["create_snapshot"], default_value = "/.rusnapshot")] + pub dest_dir: String, + /// Directory from where snapshots should be created. It can also be used to specify the directory where a snapshot will be restored. + #[clap(long = "from", requires_all = &["create_snapshot"], default_value = "")] + pub source_dir: String, + /// Snapshot id or name to work with. + #[clap(long = "id", default_value = "")] + pub snapshot_id: String, + /// Path to the SQLite database file. + #[clap( + short = 'd', + long = "dfile", + env = "RUSNAPSHOT_DB_FILE", + default_value = "/var/lib/rusnapshot/rusnapshot.db" + )] + pub database_file: String, + /// Prefix for the snapshot name. + #[clap(short = 'p', long = "prefix", default_value = "rusnapshot")] + pub snapshot_prefix: String, + /// Used to specify a differentiator between snapshots with the same prefix. + #[clap(long = "kind", default_value = "rusnapshot")] + pub snapshot_kind: String, + /// Keep only the last X items. + #[clap(short = 'k', long = "keep", default_value = "10")] + pub keep_only: usize, + /// Time in milliseconds until SQLite can return a timeout. Do not touch if you don't know what you are doing. + #[clap(long = "timeout", default_value = "5000")] + pub timeout: usize, + /// Create a read-only/ro snapshot. + #[clap(long = "create", conflicts_with_all = &["restore_snapshot", "delete_snapshot", "list_snapshots", "clean_snapshots"])] + pub create_snapshot: bool, + /// Enable snapshots cleaning, will keep only the last X snapshots specified with -k/--keep. + #[clap(long = "clean")] + pub clean_snapshots: bool, + /// Delete a snapshot. + #[clap(long = "del", requires_all = &["snapshot_id"])] + pub delete_snapshot: bool, + /// Restore a specific snapshot. + #[clap(short = 'r', long = "restore", requires_all = &["snapshot_id"])] + pub restore_snapshot: bool, + /// List the snapshots tracked in the database. + #[clap(short = 'l', long = "list")] + pub list_snapshots: bool, + /// Create read-write/rw snapshots. + #[clap(short = 'w', long = "rw")] + pub read_write: bool, + /// Init the Rusnapshot database and directory structure. + #[clap(long = "init")] + pub init: bool, } -fn return_settings( - matches: &clap::ArgMatches, - settings: &mut config::Config, -) -> HashMap { - if matches.is_present("config-file") { - match settings.merge(config::File::with_name( - &value_t!(matches, "config-file", String).unwrap(), - )) { - Ok(settings) => match settings.merge(config::Environment::with_prefix("RUSNAPSHOT")) { - Ok(settings) => settings - .clone() - .try_into::>() - .unwrap(), - Err(e) => { - eprintln!("Error merging environment variables into settings: {}", e); - std::process::exit(1) - } - }, - Err(e) => { - eprintln!("Error reading config file: {}", e); - std::process::exit(1) +impl Args { + /// Get the database connection string. + #[must_use] + pub fn database_connection(&self) -> Connection { + match sqlite::open(&self.database_file) { + Ok(mut connection) => { + connection + .set_busy_timeout(self.timeout) + .expect("Failed to set database timeout"); + + connection } - } - } else if Path::new("rusnapshot.toml").exists() - || Path::new("rusnapshot.json").exists() - || Path::new("rusnapshot.hjson").exists() - || Path::new("rusnapshot.ini").exists() - || Path::new("rusnapshot.yml").exists() - { - match settings.merge(config::File::with_name("rusnapshot")) { - Ok(settings) => match settings.merge(config::Environment::with_prefix("RUSNAPSHOT")) { - Ok(settings) => settings - .clone() - .try_into::>() - .unwrap(), - Err(e) => { - eprintln!("Error merging environment variables into settings: {}", e); - std::process::exit(1) - } - }, Err(e) => { - eprintln!("Error reading config file: {}", e); - std::process::exit(1) - } - } - } else { - match settings.merge(config::Environment::with_prefix("RUSNAPSHOT")) { - Ok(settings) => settings - .clone() - .try_into::>() - .unwrap(), - Err(e) => { - eprintln!("Error merging environment variables into settings: {}", e); + eprintln!("Error while trying to stablish the database connection. Error: {e}"); std::process::exit(1) } } } -} -fn return_value_or_default( - settings: &HashMap, - value: &str, - default_value: String, -) -> String { - settings.get(value).unwrap_or(&default_value).to_string() + /// Initialize the database and directory structure. + pub fn init(&self, extra_args: &ExtraArgs) -> Result<()> { + if !std::path::Path::new(&self.dest_dir).exists() { + println!("Setting up the directory structure."); + operations::setup_directory_structure(self)?; + } + database::setup_initial_database(&extra_args.database_connection)?; + + Ok(()) + } } diff --git a/src/cli.yml b/src/cli.yml deleted file mode 100644 index af5263a..0000000 --- a/src/cli.yml +++ /dev/null @@ -1,107 +0,0 @@ -name: Rusnapshot -author: Eduard Tolosa -settings: - - ArgRequiredElseHelp - - StrictUtf8 -about: Simple and handy btrfs snapshoting tool. -args: - - config-file: - help: Path to configuration file. - short: c - long: config - takes_value: true - multiple: false - - - dest-dir: - help: Directory where snapshots should be saved. - long: to - takes_value: true - multiple: false - - - source-dir: - help: Directory from where snapshots should be created. It can also be used to specify the directory where a snapshot will be restored. - long: from - takes_value: true - multiple: false - - - snapshot-id: - help: Snapshot id or name to work with. - long: id - takes_value: true - multiple: false - - - database-file: - help: Path to the SQLite database file. - short: d - long: dfile - takes_value: true - multiple: false - - - snapshot-prefix: - help: "Prefix for the snapshot name. Default: snapshot" - short: p - long: prefix - takes_value: true - multiple: false - - - snapshot-kind: - help: "Used to specify a differentiator between snapshots with the same prefix. Default: rusnapshot" - long: kind - takes_value: true - multiple: false - - - keep-only: - help: Keep only the last X items. - short: k - long: keep - takes_value: true - multiple: false - - - timeout: - help: "Time in milliseconds until SQLite can return a timeout (Do not touch if you don't know what you are doing). Default: 5000" - long: timeout - takes_value: true - multiple: false - - - create-snapshot: - help: Create an snapshot. - long: cr - takes_value: false - multiple: false - - - clean-snapshots: - help: "Enable snapshots cleaning, will keep only the last X snapshots specified with -k/--keep. WARNING: if -k/--keep is not specified, IT WILL DELETE ALL THE SNAPSHOTS." - long: clean - takes_value: false - multiple: false - - - delete-snapshot: - help: Delete an snapshot. - long: del - takes_value: false - multiple: false - requires: - - snapshot-id - - - restore-snapshot: - help: Restore an specific snapshot. - short: r - long: restore - takes_value: false - multiple: false - requires: - - snapshot-id - - - list-snapshots: - help: List the snapshots tracked in the database. - short: l - long: list - takes_value: false - multiple: false - - - read-write: - help: Create read-write/rw snapshots. - short: w - long: rw - takes_value: false - multiple: false diff --git a/src/controller.rs b/src/controller.rs index b9d216a..abb8cc5 100644 --- a/src/controller.rs +++ b/src/controller.rs @@ -1,66 +1,70 @@ use { - crate::{database, errors::*, operations, structs::Args}, - chrono::Utc, + crate::{args::Args, database, operations, structs::ExtraArgs}, + anyhow::Result, md5, - prettytable::{cell, row, Table}, + prettytable::{row, Table}, + sqlite::Connection, }; -pub fn manage_creation(args: &mut Args) -> Result<()> { - args.snapshot_name = format!( - "{}-{}", - args.snapshot_prefix, - Utc::now().format("%Y-%m-%d-%H-%M-%S-%6f") - ); - args.snapshot_id = format!("{:?}", md5::compute(&args.snapshot_name)); - if operations::take_snapshot(args) { - database::commit_to_database(&args.database_connection, args)? +pub fn manage_creation(args: &mut Args, extra_args: &ExtraArgs) -> Result<()> { + args.snapshot_id = format!("{:?}", md5::compute(&extra_args.snapshot_name)); + if operations::take_snapshot(args, &extra_args.snapshot_name) { + database::commit_to_database(args, extra_args)?; } Ok(()) } -pub fn manage_deletion(args: &mut Args) -> Result<()> { - let snapshot_data = database::return_snapshot_data(&args.database_connection, args)?; - if !snapshot_data.snap_id.is_empty() { - args.snapshot_name = snapshot_data.destination + &snapshot_data.name; - } else { +pub fn manage_deletion(args: &Args, extra_args: &mut ExtraArgs) -> Result<()> { + let snapshot_data = database::return_snapshot_data(&extra_args.database_connection, args)?; + if snapshot_data.snap_id.is_empty() { eprintln!( "Snapshot ID {} does not returned any data. Please double check the ID.", args.snapshot_id - ) + ); + std::process::exit(1); + } else { + extra_args.snapshot_name = snapshot_data.destination + &snapshot_data.name; } - if !args.snapshot_name.is_empty() && operations::del_snapshot(args) { - database::delete_from_database(&args.database_connection, args)? + if !extra_args.snapshot_name.is_empty() && operations::del_snapshot(&extra_args.snapshot_name) { + database::delete_from_database(&extra_args.database_connection, args)?; } Ok(()) } -pub fn manage_restoring(args: &mut Args) -> Result<()> { - let snapshot_data = database::return_snapshot_data(&args.database_connection, args)?; - if !snapshot_data.snap_id.is_empty() { - args.snapshot_name = snapshot_data.destination + &snapshot_data.name; +pub fn manage_restoring(args: &mut Args, extra_args: &mut ExtraArgs) -> Result<()> { + let snapshot_data = database::return_snapshot_data(&extra_args.database_connection, args)?; + if snapshot_data.snap_id.is_empty() { + eprintln!( + "Snapshot ID {} does not returned any data. Please double check the ID.", + args.snapshot_id + ); + std::process::exit(1); + } else { + extra_args.snapshot_name = snapshot_data.destination + &snapshot_data.name; if args.source_dir.is_empty() { args.source_dir = snapshot_data.source; } - } else { - eprintln!( - "Snapshot ID {} does not returned any data. Please double check the ID.", - args.snapshot_id - ) } - if !args.snapshot_name.is_empty() && operations::restore_snapshot(args) { + println!("Restoring the snapshot with ID {}", args.snapshot_id); + println!("Name of the snapshot: {}", extra_args.snapshot_name); + println!("Source directory: {}", args.source_dir); + + if !extra_args.snapshot_name.is_empty() + && operations::restore_snapshot(args, &extra_args.snapshot_name) + { println!( "The snapshot with ID {} was successfully restored to {}", args.snapshot_id, args.source_dir - ) + ); } Ok(()) } -pub fn manage_listing(args: &mut Args) -> Result<()> { - let snaps_data = database::return_all_data(&args.database_connection)?; +pub fn manage_listing(database_connection: &Connection) -> Result<()> { + let snaps_data = database::return_all_data(database_connection)?; let mut table = Table::new(); table.set_titles(row![ @@ -89,12 +93,12 @@ pub fn manage_listing(args: &mut Args) -> Result<()> { Ok(()) } -pub fn keep_only_x(args: &mut Args) -> Result<()> { - let snaps_data = database::return_only_x_items(&args.database_connection, args)?; +pub fn keep_only_x(args: &mut Args, extra_args: &mut ExtraArgs) -> Result<()> { + let snaps_data = database::return_only_x_items(&extra_args.database_connection, args)?; for data in &snaps_data { - args.snapshot_name = data.destination.clone() + &data.name; + extra_args.snapshot_name = data.destination.clone() + &data.name; args.snapshot_id = data.snap_id.clone(); - manage_deletion(args)? + manage_deletion(args, extra_args)?; } Ok(()) diff --git a/src/database.rs b/src/database.rs index c614be8..7eb7f5f 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,8 +1,9 @@ use { crate::{ - errors::*, - structs::{Args, Database}, + args::Args, + structs::{Database, ExtraArgs}, }, + anyhow::Result, sqlite::{Connection, State, Statement}, }; @@ -13,12 +14,12 @@ pub fn setup_initial_database(connection: &Connection) -> Result<()> { Ok(()) } -pub fn commit_to_database(connection: &Connection, args: &Args) -> Result<()> { +pub fn commit_to_database(args: &Args, extra_args: &ExtraArgs) -> Result<()> { let statement = format!( "INSERT INTO snapshots (name, snap_id, kind, source, destination, ro_rw) VALUES ('{}', '{}', '{}', '{}', '{}', '{}')", - args.snapshot_name, args.snapshot_id, args.snapshot_kind, args.source_dir, args.dest_dir, args.snapshot_ro_rw + &extra_args.snapshot_name, args.snapshot_id, args.snapshot_kind, args.source_dir, args.dest_dir, args.read_write ); - connection.execute(statement)?; + extra_args.database_connection.execute(statement)?; Ok(()) } @@ -40,7 +41,7 @@ pub fn return_snapshot_data(connection: &Connection, args: &Args) -> Result Result> { let mut statement = connection .prepare("SELECT name,snap_id,kind,source,destination,ro_rw,datetime(date, 'localtime') FROM snapshots ORDER BY date DESC")?; - while let State::Row = statement.next()? { + while statement.next()? == State::Row { let db_struct = Database::default(); snapshots_data.push(populate_db_struct(&statement, db_struct)?); } @@ -64,9 +65,9 @@ pub fn return_all_data(connection: &Connection) -> Result> { pub fn return_only_x_items(connection: &Connection, args: &Args) -> Result> { let mut snapshots_data: Vec = Vec::new(); - let mut statement = connection.prepare(&format!("SELECT name,snap_id,kind,source,destination,ro_rw,date FROM (SELECT row_number() over(ORDER BY date DESC) n,* from snapshots WHERE name like '{}%' AND kind = '{}' AND ro_rw = '{}') WHERE n > {}", args.snapshot_prefix, args.snapshot_kind, args.snapshot_ro_rw, args.keep_only))?; + let mut statement = connection.prepare(&format!("SELECT name,snap_id,kind,source,destination,ro_rw,date FROM (SELECT row_number() over(ORDER BY date DESC) n,* from snapshots WHERE name like '{}%' AND kind = '{}' AND ro_rw = '{}') WHERE n > {}", args.snapshot_prefix, args.snapshot_kind, args.read_write, args.keep_only))?; - while let State::Row = statement.next()? { + while statement.next()? == State::Row { let db_struct = Database::default(); snapshots_data.push(populate_db_struct(&statement, db_struct)?); } @@ -75,12 +76,15 @@ pub fn return_only_x_items(connection: &Connection, args: &Args) -> Result Result { - db_struct.name = row.read::(0)?; - db_struct.snap_id = row.read::(1)?; - db_struct.kind = row.read::(2)?; - db_struct.source = row.read::(3)?; - db_struct.destination = row.read::(4)?; - db_struct.ro_rw = row.read::(5)?; - db_struct.date = row.read::(6)?; + // I'll improve this later. + + db_struct.name = row.read(0)?; + db_struct.snap_id = row.read(1)?; + db_struct.kind = row.read(2)?; + db_struct.source = row.read(3)?; + db_struct.destination = row.read(4)?; + db_struct.ro_rw = row.read(5)?; + db_struct.date = row.read(6)?; + Ok(db_struct) } diff --git a/src/errors.rs b/src/errors.rs deleted file mode 100644 index 245cff2..0000000 --- a/src/errors.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub use failure::{Error, ResultExt}; -pub type Result = ::std::result::Result; diff --git a/src/lib.rs b/src/lib.rs index 45d64eb..4062b4c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ pub mod args; pub mod controller; pub mod database; -pub mod errors; -mod operations; -mod structs; +pub mod operations; +pub mod structs; +pub mod utils; diff --git a/src/main.rs b/src/main.rs index 12efa74..223fc65 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,41 +1,75 @@ -use rusnapshot::{args, controller, database, errors::*}; +use std::path::Path; -fn run() -> Result<()> { - let mut arguments = args::get_args(); +use anyhow::Result; +use chrono::Utc; +use clap::Parser; +use rusnapshot::{args, controller, structs::ExtraArgs}; +fn try_run() -> Result<()> { + let mut arguments = args::Args::parse(); + + let mut extra_args = ExtraArgs { + snapshot_name: format!( + "{}-{}", + arguments.snapshot_prefix, + Utc::now().format("%Y-%m-%d-%H-%M-%S-%6f") + ), + database_connection: arguments.database_connection(), + }; + + arguments.init(&extra_args)?; + + // It's required to have a trailing slash for the source and destination directories. + // Otherwise, when we retrieve the snapshot data from the database, we won't be able to + // restore/delete the snapshot because the source/destination paths won't match. if !arguments.source_dir.is_empty() && !arguments.source_dir.ends_with('/') { - arguments.source_dir += "/" + arguments.source_dir += "/"; } if !arguments.dest_dir.is_empty() && !arguments.dest_dir.ends_with('/') { - arguments.dest_dir += "/" + arguments.dest_dir += "/"; } - database::setup_initial_database(&arguments.database_connection)?; + // Now we need to make sure that the paths for source and destination are full paths. + // If they are not, we will use the current working directory to build the full path. + if arguments.create_snapshot { + if !Path::new(&arguments.source_dir).is_absolute() { + arguments.source_dir = std::env::current_dir()? + .join(&arguments.source_dir) + .to_str() + .expect("Failed to get the source directory") + .to_string(); + } + + if !Path::new(&arguments.dest_dir).is_absolute() { + arguments.dest_dir = std::env::current_dir()? + .join(&arguments.dest_dir) + .to_str() + .expect("Failed to get the destination directory") + .to_string(); + } + } if arguments.create_snapshot { - controller::manage_creation(&mut arguments)? + controller::manage_creation(&mut arguments, &extra_args)?; } if arguments.delete_snapshot { - controller::manage_deletion(&mut arguments)? + controller::manage_deletion(&arguments, &mut extra_args)?; } if arguments.list_snapshots { - controller::manage_listing(&mut arguments)? + controller::manage_listing(&extra_args.database_connection)?; } if arguments.clean_snapshots { - controller::keep_only_x(&mut arguments)? + controller::keep_only_x(&mut arguments, &mut extra_args)?; } if arguments.restore_snapshot { - controller::manage_restoring(&mut arguments)? + controller::manage_restoring(&mut arguments, &mut extra_args)?; } Ok(()) } fn main() { - if let Err(err) = run() { - eprintln!("\nError: {}", err); - for cause in err.iter_chain().skip(1) { - eprintln!("Error description: {}", cause); - } + if let Err(err) = try_run() { + eprintln!("\nError: {err}"); std::process::exit(1); } } diff --git a/src/operations.rs b/src/operations.rs index b9457cc..f4d03ee 100644 --- a/src/operations.rs +++ b/src/operations.rs @@ -1,13 +1,17 @@ +use crate::utils::is_same_character; +use std::path::PathBuf; + use { - crate::structs::Args, + crate::args::Args, + anyhow::Result, std::{path::Path, process::Command}, }; -pub fn take_snapshot(args: &Args) -> bool { - let snapshot_name = format!("{}/{}", args.dest_dir, args.snapshot_name); +pub fn take_snapshot(args: &Args, snapshot_name: &str) -> bool { + let snapshot_name = format!("{}/{}", args.dest_dir, snapshot_name); let mut btrfs_args = vec!["subvolume", "snapshot", &args.source_dir, &snapshot_name]; - if !args.rw_snapshots { - btrfs_args.push("-r") + if !args.read_write { + btrfs_args.push("-r"); } Command::new("btrfs") .args(&btrfs_args) @@ -16,15 +20,23 @@ pub fn take_snapshot(args: &Args) -> bool { .success() } -pub fn del_snapshot(args: &Args) -> bool { +pub fn del_snapshot(snapshot_name: &str) -> bool { + // Refuse to delete the root subvolume. + if snapshot_name == "/" || is_same_character(snapshot_name, '/') { + println!( + "Snapshot name to delete is: {}. Refusing to delete the root subvolume.", + snapshot_name + ); + std::process::exit(1); + } Command::new("btrfs") - .args(["subvolume", "delete", &args.snapshot_name]) + .args(["subvolume", "delete", snapshot_name]) .status() .expect("Error deleting the snapshot.") .success() } -pub fn restore_snapshot(args: &Args) -> bool { +pub fn restore_snapshot(args: &Args, snapshot_name: &str) -> bool { (!Path::new(&args.source_dir).exists() || Command::new("btrfs") .args(["subvolume", "delete", &args.source_dir]) @@ -32,13 +44,19 @@ pub fn restore_snapshot(args: &Args) -> bool { .expect("Error deleting the subvolume.") .success()) && Command::new("btrfs") - .args([ - "subvolume", - "snapshot", - &args.snapshot_name, - &args.source_dir, - ]) + .args(["subvolume", "snapshot", &snapshot_name, &args.source_dir]) .status() .expect("Error restoring the snapshot.") .success() } + +pub fn setup_directory_structure(args: &Args) -> Result<()> { + let dest_dir = PathBuf::from(&args.dest_dir); + if !dest_dir.exists() { + Command::new("btrfs") + .args(["subvolume", "create", &args.dest_dir]) + .spawn()?; + } + + Ok(()) +} diff --git a/src/structs.rs b/src/structs.rs index 6bccf66..9f3e655 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -1,23 +1,6 @@ use sqlite::Connection; -pub struct Args { - pub create_snapshot: bool, - pub delete_snapshot: bool, - pub list_snapshots: bool, - pub clean_snapshots: bool, - pub restore_snapshot: bool, - pub rw_snapshots: bool, - pub dest_dir: String, - pub source_dir: String, - pub database_connection: Connection, - pub snapshot_name: String, - pub snapshot_id: String, - pub snapshot_prefix: String, - pub snapshot_kind: String, - pub snapshot_ro_rw: String, - pub keep_only: usize, -} - +#[derive(Debug, Default, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct Database { pub name: String, pub snap_id: String, @@ -28,16 +11,7 @@ pub struct Database { pub date: String, } -impl Database { - pub fn default() -> Database { - Database { - name: String::new(), - snap_id: String::new(), - kind: String::new(), - source: String::new(), - destination: String::new(), - ro_rw: String::new(), - date: String::new(), - } - } +pub struct ExtraArgs { + pub snapshot_name: String, + pub database_connection: Connection, } diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..842361c --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,3 @@ +pub fn is_same_character(s: &str, specific_char: char) -> bool { + s.chars().all(|c| c == specific_char) +}