summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1634
-rw-r--r--Cargo.toml62
-rw-r--r--NEWS.md52
-rwxr-xr-xcheck7
-rw-r--r--debian/changelog12
-rw-r--r--debian/control8
-rwxr-xr-xdebian/rules8
-rw-r--r--deny.toml2
-rw-r--r--obnam.md237
-rw-r--r--obnam.subplot23
-rw-r--r--src/accumulated_time.rs4
-rw-r--r--src/backup_progress.rs44
-rw-r--r--src/backup_run.rs29
-rw-r--r--src/bin/obnam-server.rs75
-rw-r--r--src/bin/obnam.rs14
-rw-r--r--src/chunk.rs2
-rw-r--r--src/chunker.rs3
-rw-r--r--src/chunkmeta.rs2
-rw-r--r--src/chunkstore.rs307
-rw-r--r--src/cipher.rs2
-rw-r--r--src/client.rs144
-rw-r--r--src/cmd/backup.rs16
-rw-r--r--src/cmd/chunk.rs12
-rw-r--r--src/cmd/chunkify.rs4
-rw-r--r--src/cmd/gen_info.rs5
-rw-r--r--src/cmd/get_chunk.rs5
-rw-r--r--src/cmd/init.rs8
-rw-r--r--src/cmd/inspect.rs5
-rw-r--r--src/cmd/list.rs4
-rw-r--r--src/cmd/list_backup_versions.rs6
-rw-r--r--src/cmd/list_files.rs6
-rw-r--r--src/cmd/resolve.rs4
-rw-r--r--src/cmd/restore.rs14
-rw-r--r--src/cmd/show_config.rs4
-rw-r--r--src/cmd/show_gen.rs6
-rw-r--r--src/config.rs4
-rw-r--r--src/db.rs10
-rw-r--r--src/engine.rs2
-rw-r--r--src/fsentry.rs2
-rw-r--r--src/index.rs4
-rw-r--r--src/indexedstore.rs77
-rw-r--r--src/lib.rs2
-rw-r--r--src/passwords.rs2
-rw-r--r--src/policy.rs11
-rw-r--r--src/server.rs2
-rw-r--r--src/store.rs12
-rw-r--r--subplot/server.py6
-rw-r--r--subplot/server.yaml10
48 files changed, 1718 insertions, 1196 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 7715bf3..c0e9e3c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,31 +3,46 @@
version = 3
[[package]]
+name = "addr2line"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
name = "aead"
-version = "0.4.3"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877"
+checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
dependencies = [
+ "crypto-common",
"generic-array",
]
[[package]]
name = "aes"
-version = "0.7.5"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
+checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures",
- "opaque-debug",
]
[[package]]
name = "aes-gcm"
-version = "0.9.4"
+version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6"
+checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1"
dependencies = [
"aead",
"aes",
@@ -39,73 +54,138 @@ dependencies = [
[[package]]
name = "ahash"
-version = "0.7.6"
+version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
+checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
- "getrandom",
+ "cfg-if",
"once_cell",
"version_check",
+ "zerocopy",
]
[[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 = "ansi_term"
-version = "0.12.1"
+name = "allocator-api2"
+version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
+checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
+
+[[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 = [
- "winapi",
+ "libc",
]
[[package]]
-name = "anyhow"
-version = "1.0.56"
+name = "anstream"
+version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27"
+checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "utf8parse",
+]
[[package]]
-name = "arc-swap"
-version = "0.4.8"
+name = "anstyle"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dabe5a181f83789739c194cbe5a897dde195078fac08568d09221fd6137a7ba8"
+checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
[[package]]
-name = "atty"
-version = "0.2.14"
+name = "anstyle-parse"
+version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
dependencies = [
- "hermit-abi",
- "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 0.52.0",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
+dependencies = [
+ "anstyle",
+ "windows-sys 0.52.0",
]
[[package]]
+name = "anyhow"
+version = "1.0.80"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
+
+[[package]]
+name = "arc-swap"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b3d0060af21e8d11a926981cc00c6c1541aa91dd64b9f881985c3da1094425f"
+
+[[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.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.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
+checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
[[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 = "bitflags"
@@ -114,71 +194,58 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
-name = "blake2"
-version = "0.10.4"
+name = "bitflags"
+version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9cf849ee05b2ee5fba5e36f97ff8ec2533916700fc0758d40d92136a42f3388"
-dependencies = [
- "digest 0.10.3",
-]
+checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
[[package]]
-name = "block-buffer"
-version = "0.9.0"
+name = "blake2"
+version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
+checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
dependencies = [
- "generic-array",
+ "digest",
]
[[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 = "buf_redux"
-version = "0.8.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f"
-dependencies = [
- "memchr",
- "safemem",
-]
-
-[[package]]
name = "bumpalo"
-version = "3.9.1"
+version = "3.15.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
+checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b"
[[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.1.0"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
+checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]]
name = "bytesize"
-version = "1.1.0"
+version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c58ec36aac5066d5ca17df51b3e70279f5670a72102f5752cb7e7c856adfc70"
+checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc"
[[package]]
name = "cc"
-version = "1.0.73"
+version = "1.0.88"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
+checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc"
[[package]]
name = "cfg-if"
@@ -188,59 +255,92 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
-version = "0.4.19"
+version = "0.4.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
+checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b"
dependencies = [
- "libc",
- "num-integer",
+ "android-tzdata",
+ "iana-time-zone",
+ "js-sys",
"num-traits",
- "time",
- "winapi",
+ "wasm-bindgen",
+ "windows-targets 0.52.4",
]
[[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 = "clap"
-version = "2.34.0"
+version = "4.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
+checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb"
dependencies = [
- "ansi_term",
- "atty",
- "bitflags",
+ "anstream",
+ "anstyle",
+ "clap_lex",
"strsim",
- "textwrap",
- "unicode-width",
- "vec_map",
]
[[package]]
+name = "clap_derive"
+version = "4.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.52",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+
+[[package]]
name = "console"
-version = "0.15.0"
+version = "0.15.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31"
+checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
dependencies = [
"encode_unicode",
+ "lazy_static",
"libc",
- "once_cell",
- "terminal_size",
- "winapi",
+ "unicode-width",
+ "windows-sys 0.52.0",
]
[[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",
@@ -248,39 +348,46 @@ 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.1"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469"
+checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
-version = "0.1.3"
+version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
+ "rand_core",
"typenum",
]
[[package]]
name = "ctr"
-version = "0.8.0"
+version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea"
+checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
dependencies = [
"cipher",
]
[[package]]
+name = "data-encoding"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5"
+
+[[package]]
name = "derivative"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -288,25 +395,22 @@ checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 1.0.109",
]
[[package]]
-name = "digest"
-version = "0.9.0"
+name = "destructure_traitobject"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
-dependencies = [
- "generic-array",
-]
+checksum = "3c877555693c14d2f84191cfd3ad8582790fc52b5e2274b40b59cf5f5cea25c7"
[[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 0.10.2",
+ "block-buffer",
"crypto-common",
"subtle",
]
@@ -340,31 +444,47 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]]
name = "encoding_rs"
-version = "0.8.30"
+version = "0.8.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df"
+checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"
dependencies = [
"cfg-if",
]
[[package]]
name = "env_logger"
-version = "0.7.1"
+version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
+checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
dependencies = [
- "atty",
- "humantime 1.3.0",
+ "humantime",
+ "is-terminal",
"log",
"regex",
"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 = "fallible-iterator"
-version = "0.2.0"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
+checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
[[package]]
name = "fallible-streaming-iterator"
@@ -374,12 +494,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
[[package]]
name = "fastrand"
-version = "1.7.0"
+version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
-dependencies = [
- "instant",
-]
+checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
[[package]]
name = "fnv"
@@ -404,19 +521,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 = "futures"
-version = "0.3.21"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e"
+checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
dependencies = [
"futures-channel",
"futures-core",
@@ -429,9 +545,9 @@ dependencies = [
[[package]]
name = "futures-channel"
-version = "0.3.21"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
+checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [
"futures-core",
"futures-sink",
@@ -439,15 +555,15 @@ dependencies = [
[[package]]
name = "futures-core"
-version = "0.3.21"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
+checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-executor"
-version = "0.3.21"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6"
+checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
dependencies = [
"futures-core",
"futures-task",
@@ -456,38 +572,38 @@ dependencies = [
[[package]]
name = "futures-io"
-version = "0.3.21"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
+checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
[[package]]
name = "futures-macro"
-version = "0.3.21"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
+checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.52",
]
[[package]]
name = "futures-sink"
-version = "0.3.21"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
+checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
[[package]]
name = "futures-task"
-version = "0.3.21"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
+checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
[[package]]
name = "futures-util"
-version = "0.3.21"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
+checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [
"futures-channel",
"futures-core",
@@ -503,9 +619,9 @@ dependencies = [
[[package]]
name = "generic-array"
-version = "0.14.5"
+version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
@@ -513,9 +629,9 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.2.5"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77"
+checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
dependencies = [
"cfg-if",
"libc",
@@ -524,19 +640,25 @@ dependencies = [
[[package]]
name = "ghash"
-version = "0.4.4"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99"
+checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40"
dependencies = [
"opaque-debug",
"polyval",
]
[[package]]
+name = "gimli"
+version = "0.28.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
+
+[[package]]
name = "h2"
-version = "0.3.12"
+version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62eeb471aa3e3c9197aa4bfeabfe02982f6dc96f750486c0bb0009ac58b26d2b"
+checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9"
dependencies = [
"bytes",
"fnv",
@@ -553,36 +675,36 @@ dependencies = [
[[package]]
name = "hashbrown"
-version = "0.11.2"
+version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
dependencies = [
"ahash",
+ "allocator-api2",
]
[[package]]
name = "hashlink"
-version = "0.7.0"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf"
+checksum = "692eaaf7f7607518dd3cef090f1474b61edc5301d8012f09579920df68b725ee"
dependencies = [
"hashbrown",
]
[[package]]
name = "headers"
-version = "0.3.7"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4cff78e5788be1e0ab65b04d306b2ed5092c815ec97ec70f4ebd5aee158aa55d"
+checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270"
dependencies = [
"base64",
- "bitflags",
"bytes",
"headers-core",
"http",
"httpdate",
"mime",
- "sha-1 0.10.0",
+ "sha1",
]
[[package]]
@@ -596,21 +718,15 @@ dependencies = [
[[package]]
name = "heck"
-version = "0.3.3"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
-dependencies = [
- "unicode-segmentation",
-]
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "hermit-abi"
-version = "0.1.19"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
-dependencies = [
- "libc",
-]
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "hmac"
@@ -618,14 +734,14 @@ version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
- "digest 0.10.3",
+ "digest",
]
[[package]]
name = "http"
-version = "0.2.6"
+version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03"
+checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb"
dependencies = [
"bytes",
"fnv",
@@ -634,9 +750,9 @@ dependencies = [
[[package]]
name = "http-body"
-version = "0.4.4"
+version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6"
+checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
dependencies = [
"bytes",
"http",
@@ -645,24 +761,15 @@ dependencies = [
[[package]]
name = "httparse"
-version = "1.6.0"
+version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4"
+checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
[[package]]
name = "httpdate"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
-
-[[package]]
-name = "humantime"
-version = "1.3.0"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
-dependencies = [
- "quick-error",
-]
+checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "humantime"
@@ -672,9 +779,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "hyper"
-version = "0.14.17"
+version = "0.14.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "043f0e083e9901b6cc658a77d1eb86f4fc650bbb977a4337dd63192826aa85dd"
+checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80"
dependencies = [
"bytes",
"futures-channel",
@@ -708,36 +815,68 @@ dependencies = [
]
[[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.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 = "indexmap"
-version = "1.8.0"
+version = "2.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
+checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4"
dependencies = [
- "autocfg",
+ "equivalent",
"hashbrown",
]
[[package]]
name = "indicatif"
-version = "0.16.2"
+version = "0.17.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d207dc617c7a380ab07ff572a6e52fa202a2a8f355860ac9c38e23f8196be1b"
+checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3"
dependencies = [
"console",
- "lazy_static",
+ "instant",
"number_prefix",
- "regex",
+ "portable-atomic",
+ "unicode-width",
+]
+
+[[package]]
+name = "inout"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
+dependencies = [
+ "generic-array",
]
[[package]]
@@ -751,21 +890,32 @@ dependencies = [
[[package]]
name = "ipnet"
-version = "2.4.0"
+version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35e70ee094dc02fd9c13fdad4940090f22dbd6ac7c9e7094a46cf0232a50bc7c"
+checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
+
+[[package]]
+name = "is-terminal"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "windows-sys 0.52.0",
+]
[[package]]
name = "itoa"
-version = "1.0.1"
+version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
+checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
name = "js-sys"
-version = "0.3.56"
+version = "0.3.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04"
+checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee"
dependencies = [
"wasm-bindgen",
]
@@ -778,42 +928,53 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.119"
+version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
+
+[[package]]
+name = "libredox"
+version = "0.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8"
+dependencies = [
+ "bitflags 2.4.2",
+ "libc",
+ "redox_syscall",
+]
[[package]]
name = "libsqlite3-sys"
-version = "0.24.1"
+version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb644c388dfaefa18035c12614156d285364769e818893da0dda9030c80ad2ba"
+checksum = "0c10584274047cb335c23d3e61bcef8e323adae7c5c8c760540f73610177fc3f"
dependencies = [
"pkg-config",
"vcpkg",
]
[[package]]
-name = "linked-hash-map"
-version = "0.5.4"
+name = "linux-raw-sys"
+version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
+checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
[[package]]
name = "lock_api"
-version = "0.4.6"
+version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b"
+checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
dependencies = [
+ "autocfg",
"scopeguard",
]
[[package]]
name = "log"
-version = "0.4.14"
+version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
+checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
dependencies = [
- "cfg-if",
"serde",
]
@@ -825,48 +986,43 @@ checksum = "a94d21414c1f4a51209ad204c1776a3d0765002c76c6abcb602a6f09f1e881c7"
[[package]]
name = "log4rs"
-version = "1.0.0"
+version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1572a880d1115ff867396eee7ae2bc924554225e67a0d3c85c745b3e60ca211"
+checksum = "0816135ae15bd0391cf284eab37e6e3ee0a6ee63d2ceeb659862bd8d0a984ca6"
dependencies = [
"anyhow",
"arc-swap",
"chrono",
"derivative",
"fnv",
- "humantime 2.1.0",
+ "humantime",
"libc",
"log",
"log-mdc",
- "parking_lot 0.11.2",
- "regex",
+ "once_cell",
+ "parking_lot",
+ "rand",
"serde",
"serde-value",
"serde_json",
"serde_yaml",
"thiserror",
"thread-id",
- "typemap",
+ "typemap-ors",
"winapi",
]
[[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"
+version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
[[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 = "mime_guess"
@@ -879,50 +1035,48 @@ dependencies = [
]
[[package]]
-name = "mio"
-version = "0.8.0"
+name = "miniz_oxide"
+version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2"
+checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
dependencies = [
- "libc",
- "log",
- "miow",
- "ntapi",
- "winapi",
+ "adler",
]
[[package]]
-name = "miow"
-version = "0.3.7"
+name = "mio"
+version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
+checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
dependencies = [
- "winapi",
+ "libc",
+ "wasi",
+ "windows-sys 0.48.0",
]
[[package]]
-name = "multipart"
-version = "0.18.0"
+name = "multer"
+version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00dec633863867f29cb39df64a397cdf4a6354708ddd7759f70c7fb51c5f9182"
+checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2"
dependencies = [
- "buf_redux",
+ "bytes",
+ "encoding_rs",
+ "futures-util",
+ "http",
"httparse",
"log",
+ "memchr",
"mime",
- "mime_guess",
- "quick-error",
- "rand",
- "safemem",
- "tempfile",
- "twoway",
+ "spin",
+ "version_check",
]
[[package]]
name = "native-tls"
-version = "0.2.8"
+version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d"
+checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
dependencies = [
"lazy_static",
"libc",
@@ -937,38 +1091,19 @@ dependencies = [
]
[[package]]
-name = "ntapi"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "num-integer"
-version = "0.1.44"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
-dependencies = [
- "autocfg",
- "num-traits",
-]
-
-[[package]]
name = "num-traits"
-version = "0.2.14"
+version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
+checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
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",
"libc",
@@ -981,14 +1116,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
[[package]]
+name = "object"
+version = "0.32.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
name = "obnam"
-version = "0.7.1"
+version = "0.8.1"
dependencies = [
"aes-gcm",
"anyhow",
"blake2",
"bytesize",
"chrono",
+ "clap",
"directories-next",
"futures",
"indicatif",
@@ -1006,7 +1151,6 @@ dependencies = [
"serde_yaml",
"sha2",
"spmc",
- "structopt",
"tempfile",
"thiserror",
"tokio",
@@ -1018,31 +1162,43 @@ dependencies = [
[[package]]
name = "once_cell"
-version = "1.10.0"
+version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "opaque-debug"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
+checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "openssl"
-version = "0.10.38"
+version = "0.10.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95"
+checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f"
dependencies = [
- "bitflags",
+ "bitflags 2.4.2",
"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.52",
+]
+
+[[package]]
name = "openssl-probe"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1050,11 +1206,10 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
-version = "0.9.72"
+version = "0.9.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb"
+checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff"
dependencies = [
- "autocfg",
"cc",
"libc",
"pkg-config",
@@ -1063,66 +1218,41 @@ dependencies = [
[[package]]
name = "ordered-float"
-version = "2.10.0"
+version = "2.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87"
+checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c"
dependencies = [
"num-traits",
]
[[package]]
name = "parking_lot"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
-dependencies = [
- "instant",
- "lock_api",
- "parking_lot_core 0.8.5",
-]
-
-[[package]]
-name = "parking_lot"
-version = "0.12.0"
+version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58"
+checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
- "parking_lot_core 0.9.1",
-]
-
-[[package]]
-name = "parking_lot_core"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
-dependencies = [
- "cfg-if",
- "instant",
- "libc",
- "redox_syscall 0.2.11",
- "smallvec",
- "winapi",
+ "parking_lot_core",
]
[[package]]
name = "parking_lot_core"
-version = "0.9.1"
+version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954"
+checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
dependencies = [
"cfg-if",
"libc",
- "redox_syscall 0.2.11",
+ "redox_syscall",
"smallvec",
- "windows-sys",
+ "windows-targets 0.48.5",
]
[[package]]
name = "password-hash"
-version = "0.3.2"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d791538a6dcc1e7cb7fe6f6b58aca40e7f79403c45b2bc274008b5e647af1d8"
+checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
dependencies = [
"base64ct",
"rand_core",
@@ -1131,11 +1261,11 @@ dependencies = [
[[package]]
name = "pbkdf2"
-version = "0.10.1"
+version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "271779f35b581956db91a3e55737327a03aa051e90b1c47aeb189508533adfd7"
+checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
dependencies = [
- "digest 0.10.3",
+ "digest",
"hmac",
"password-hash",
"sha2",
@@ -1143,35 +1273,35 @@ dependencies = [
[[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 = "pin-project"
-version = "1.0.10"
+version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e"
+checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
-version = "1.0.10"
+version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb"
+checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.52",
]
[[package]]
name = "pin-project-lite"
-version = "0.2.8"
+version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
+checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]]
name = "pin-utils"
@@ -1181,15 +1311,15 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
-version = "0.3.24"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
+checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
[[package]]
name = "polyval"
-version = "0.5.3"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1"
+checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -1198,65 +1328,41 @@ dependencies = [
]
[[package]]
+name = "portable-atomic"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
+
+[[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 = "pretty_env_logger"
-version = "0.4.0"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d"
+checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c"
dependencies = [
"env_logger",
"log",
]
[[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"
+version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
+checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
- "unicode-xid",
+ "unicode-ident",
]
[[package]]
-name = "quick-error"
-version = "1.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
-
-[[package]]
name = "quote"
-version = "1.0.15"
+version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
+checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
@@ -1284,69 +1390,67 @@ 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",
]
[[package]]
name = "redox_syscall"
-version = "0.1.57"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
-
-[[package]]
-name = "redox_syscall"
-version = "0.2.11"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c"
+checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
]
[[package]]
name = "redox_users"
-version = "0.4.0"
+version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
+checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4"
dependencies = [
"getrandom",
- "redox_syscall 0.2.11",
+ "libredox",
+ "thiserror",
]
[[package]]
name = "regex"
-version = "1.5.5"
+version = "1.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
+checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
dependencies = [
"aho-corasick",
"memchr",
+ "regex-automata",
"regex-syntax",
]
[[package]]
-name = "regex-syntax"
-version = "0.6.25"
+name = "regex-automata"
+version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
+checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
+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.9"
+version = "0.11.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87f242f1488a539a79bac6dbe7c8609ae43b7914b7736210f239a37cccb32525"
+checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251"
dependencies = [
"base64",
"bytes",
@@ -1360,17 +1464,21 @@ dependencies = [
"hyper-tls",
"ipnet",
"js-sys",
- "lazy_static",
"log",
"mime",
"native-tls",
+ "once_cell",
"percent-encoding",
"pin-project-lite",
+ "rustls-pemfile",
"serde",
"serde_json",
"serde_urlencoded",
+ "sync_wrapper",
+ "system-configuration",
"tokio",
"tokio-native-tls",
+ "tower-service",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
@@ -1380,68 +1488,109 @@ dependencies = [
[[package]]
name = "ring"
-version = "0.16.20"
+version = "0.17.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
+checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
dependencies = [
"cc",
+ "cfg-if",
+ "getrandom",
"libc",
- "once_cell",
"spin",
"untrusted",
- "web-sys",
- "winapi",
+ "windows-sys 0.52.0",
]
[[package]]
name = "rpassword"
-version = "5.0.1"
+version = "7.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffc936cf8a7ea60c58f030fd36a612a48f440610214dc54bc36431f9ea0c3efb"
+checksum = "80472be3c897911d0137b2d2b9055faf6eeac5b14e324073d83bc17b191d7e3f"
dependencies = [
"libc",
- "winapi",
+ "rtoolbox",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "rtoolbox"
+version = "0.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c247d24e63230cdb56463ae328478bd5eac8b8faa8c69461a77e8e323afac90e"
+dependencies = [
+ "libc",
+ "windows-sys 0.48.0",
]
[[package]]
name = "rusqlite"
-version = "0.27.0"
+version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85127183a999f7db96d1a976a309eebbfb6ea3b0b400ddd8340190129de6eb7a"
+checksum = "b838eba278d213a8beaf485bd313fd580ca4505a00d5871caeb1457c55322cae"
dependencies = [
- "bitflags",
+ "bitflags 2.4.2",
"fallible-iterator",
"fallible-streaming-iterator",
"hashlink",
"libsqlite3-sys",
- "memchr",
"smallvec",
]
[[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.38.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
+dependencies = [
+ "bitflags 2.4.2",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
name = "rustls"
-version = "0.19.1"
+version = "0.21.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7"
+checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba"
dependencies = [
- "base64",
"log",
"ring",
+ "rustls-webpki",
"sct",
- "webpki",
]
[[package]]
-name = "ryu"
-version = "1.0.9"
+name = "rustls-pemfile"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
+dependencies = [
+ "base64",
+]
+
+[[package]]
+name = "rustls-webpki"
+version = "0.101.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
+checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
+dependencies = [
+ "ring",
+ "untrusted",
+]
[[package]]
-name = "safemem"
-version = "0.3.3"
+name = "ryu"
+version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
+checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
[[package]]
name = "same-file"
@@ -1454,31 +1603,30 @@ dependencies = [
[[package]]
name = "schannel"
-version = "0.1.19"
+version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
+checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534"
dependencies = [
- "lazy_static",
- "winapi",
+ "windows-sys 0.52.0",
]
[[package]]
name = "scoped-tls"
-version = "1.0.0"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
+checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[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 = "sct"
-version = "0.6.1"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce"
+checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
dependencies = [
"ring",
"untrusted",
@@ -1486,11 +1634,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",
@@ -1499,9 +1647,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",
@@ -1509,9 +1657,9 @@ dependencies = [
[[package]]
name = "serde"
-version = "1.0.136"
+version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
+checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
dependencies = [
"serde_derive",
]
@@ -1528,20 +1676,20 @@ dependencies = [
[[package]]
name = "serde_derive"
-version = "1.0.136"
+version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
+checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.52",
]
[[package]]
name = "serde_json"
-version = "1.0.79"
+version = "1.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
+checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
dependencies = [
"itoa",
"ryu",
@@ -1562,87 +1710,78 @@ dependencies = [
[[package]]
name = "serde_yaml"
-version = "0.8.23"
+version = "0.9.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4a521f2940385c165a24ee286aa8599633d162077a54bdcae2a6fd5a7bfa7a0"
+checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f"
dependencies = [
"indexmap",
+ "itoa",
"ryu",
"serde",
- "yaml-rust",
-]
-
-[[package]]
-name = "sha-1"
-version = "0.9.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6"
-dependencies = [
- "block-buffer 0.9.0",
- "cfg-if",
- "cpufeatures",
- "digest 0.9.0",
- "opaque-debug",
+ "unsafe-libyaml",
]
[[package]]
-name = "sha-1"
-version = "0.10.0"
+name = "sha1"
+version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
+checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
dependencies = [
"cfg-if",
"cpufeatures",
- "digest 0.10.3",
+ "digest",
]
[[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",
- "digest 0.10.3",
+ "digest",
]
[[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 = "slab"
-version = "0.4.5"
+version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
+checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
+dependencies = [
+ "autocfg",
+]
[[package]]
name = "smallvec"
-version = "1.8.0"
+version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
+checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
[[package]]
name = "socket2"
-version = "0.4.4"
+version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
+checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871"
dependencies = [
"libc",
- "winapi",
+ "windows-sys 0.52.0",
]
[[package]]
name = "spin"
-version = "0.5.2"
+version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]]
name = "spmc"
@@ -1652,129 +1791,111 @@ checksum = "02a8428da277a8e3a15271d79943e80ccc2ef254e78813a166a08d65e4c3ece5"
[[package]]
name = "strsim"
-version = "0.8.0"
+version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
[[package]]
-name = "structopt"
-version = "0.3.26"
+name = "subtle"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10"
-dependencies = [
- "clap",
- "lazy_static",
- "structopt-derive",
-]
+checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
-name = "structopt-derive"
-version = "0.4.18"
+name = "syn"
+version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
- "heck",
- "proc-macro-error",
"proc-macro2",
"quote",
- "syn",
+ "unicode-ident",
]
[[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.86"
+version = "2.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
+checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
dependencies = [
"proc-macro2",
"quote",
- "unicode-xid",
+ "unicode-ident",
]
[[package]]
-name = "tempfile"
-version = "3.3.0"
+name = "sync_wrapper"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
+checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
+
+[[package]]
+name = "system-configuration"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
dependencies = [
- "cfg-if",
- "fastrand",
- "libc",
- "redox_syscall 0.2.11",
- "remove_dir_all",
- "winapi",
+ "bitflags 1.3.2",
+ "core-foundation",
+ "system-configuration-sys",
]
[[package]]
-name = "termcolor"
-version = "1.1.3"
+name = "system-configuration-sys"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
+checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
dependencies = [
- "winapi-util",
+ "core-foundation-sys",
+ "libc",
]
[[package]]
-name = "terminal_size"
-version = "0.1.17"
+name = "tempfile"
+version = "3.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
+checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
dependencies = [
- "libc",
- "winapi",
+ "cfg-if",
+ "fastrand",
+ "rustix",
+ "windows-sys 0.52.0",
]
[[package]]
-name = "textwrap"
-version = "0.11.0"
+name = "termcolor"
+version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
- "unicode-width",
+ "winapi-util",
]
[[package]]
name = "thiserror"
-version = "1.0.30"
+version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
+checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.30"
+version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
+checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.52",
]
[[package]]
name = "thread-id"
-version = "3.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7fbf4c9d56b320106cd64fd024dadfa0be7cb4706725fc44a7d7ce952d820c1"
-dependencies = [
- "libc",
- "redox_syscall 0.1.57",
- "winapi",
-]
-
-[[package]]
-name = "time"
-version = "0.1.43"
+version = "4.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
+checksum = "f0ec81c46e9eb50deaa257be2f148adf052d1fb7701cfd55ccfab2525280b70b"
dependencies = [
"libc",
"winapi",
@@ -1782,55 +1903,54 @@ dependencies = [
[[package]]
name = "tinyvec"
-version = "1.5.1"
+version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2"
+checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
"tinyvec_macros",
]
[[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.17.0"
+version = "1.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee"
+checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931"
dependencies = [
+ "backtrace",
"bytes",
"libc",
- "memchr",
"mio",
"num_cpus",
- "once_cell",
- "parking_lot 0.12.0",
+ "parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
- "winapi",
+ "windows-sys 0.48.0",
]
[[package]]
name = "tokio-macros"
-version = "1.7.0"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
+checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.52",
]
[[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",
@@ -1838,20 +1958,19 @@ dependencies = [
[[package]]
name = "tokio-rustls"
-version = "0.22.0"
+version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6"
+checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
dependencies = [
"rustls",
"tokio",
- "webpki",
]
[[package]]
name = "tokio-stream"
-version = "0.1.8"
+version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3"
+checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
dependencies = [
"futures-core",
"pin-project-lite",
@@ -1860,44 +1979,42 @@ dependencies = [
[[package]]
name = "tokio-tungstenite"
-version = "0.15.0"
+version = "0.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "511de3f85caf1c98983545490c3d09685fa8eb634e57eec22bb4db271f46cbd8"
+checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c"
dependencies = [
"futures-util",
"log",
- "pin-project",
"tokio",
"tungstenite",
]
[[package]]
name = "tokio-util"
-version = "0.6.9"
+version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0"
+checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
- "log",
"pin-project-lite",
"tokio",
+ "tracing",
]
[[package]]
name = "tower-service"
-version = "0.3.1"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
+checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
[[package]]
name = "tracing"
-version = "0.1.32"
+version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f"
+checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
- "cfg-if",
"log",
"pin-project-lite",
"tracing-core",
@@ -1905,144 +2022,128 @@ dependencies = [
[[package]]
name = "tracing-core"
-version = "0.1.23"
+version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa31669fa42c09c34d94d8165dd2012e8ff3c66aca50f3bb226b68f216f2706c"
+checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [
- "lazy_static",
+ "once_cell",
]
[[package]]
-name = "traitobject"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
-
-[[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 = "tungstenite"
-version = "0.14.0"
+version = "0.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0b2d8558abd2e276b0a8df5c05a2ec762609344191e5fd23e292c910e9165b5"
+checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9"
dependencies = [
- "base64",
"byteorder",
"bytes",
+ "data-encoding",
"http",
"httparse",
"log",
"rand",
- "sha-1 0.9.8",
+ "sha1",
"thiserror",
"url",
"utf-8",
]
[[package]]
-name = "twoway"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "typemap"
-version = "0.3.3"
+name = "typemap-ors"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "653be63c80a3296da5551e1bfd2cca35227e13cdd08c6668903ae2f4f77aa1f6"
+checksum = "a68c24b707f02dd18f1e4ccceb9d49f2058c2fb86384ef9972592904d7a28867"
dependencies = [
- "unsafe-any",
+ "unsafe-any-ors",
]
[[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 = "unicase"
-version = "2.6.0"
+version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
+checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
dependencies = [
"version_check",
]
[[package]]
name = "unicode-bidi"
-version = "0.3.7"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-normalization"
-version = "0.1.19"
+version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9"
+checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
dependencies = [
"tinyvec",
]
[[package]]
-name = "unicode-segmentation"
-version = "1.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
-
-[[package]]
name = "unicode-width"
-version = "0.1.9"
+version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
-
-[[package]]
-name = "unicode-xid"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
+checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
[[package]]
name = "universal-hash"
-version = "0.4.1"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05"
+checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
dependencies = [
- "generic-array",
+ "crypto-common",
"subtle",
]
[[package]]
-name = "unsafe-any"
-version = "0.4.2"
+name = "unsafe-any-ors"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f30360d7979f5e9c6e6cea48af192ea8fab4afb3cf72597154b8f08935bc9c7f"
+checksum = "e0a303d30665362d9680d7d91d78b23f5f899504d4f08b3c4cf08d055d87c0ad"
dependencies = [
- "traitobject",
+ "destructure_traitobject",
]
[[package]]
+name = "unsafe-libyaml"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b"
+
+[[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 = "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",
]
@@ -2063,10 +2164,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]]
+name = "utf8parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
+[[package]]
name = "uuid"
-version = "0.8.2"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
+checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a"
dependencies = [
"getrandom",
]
@@ -2078,12 +2185,6 @@ 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"
@@ -2091,30 +2192,28 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "walkdir"
-version = "2.3.2"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
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",
]
[[package]]
name = "warp"
-version = "0.3.2"
+version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3cef4e1e9114a4b7f1ac799f16ce71c14de5778500c5450ec6b7b920c55b587e"
+checksum = "c1e92e22e03ff1230c03a1a8ee37d2f89cd489e2e541b7550d6afad96faed169"
dependencies = [
"bytes",
"futures-channel",
@@ -2125,9 +2224,10 @@ dependencies = [
"log",
"mime",
"mime_guess",
- "multipart",
+ "multer",
"percent-encoding",
"pin-project",
+ "rustls-pemfile",
"scoped-tls",
"serde",
"serde_json",
@@ -2143,15 +2243,15 @@ dependencies = [
[[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.79"
+version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06"
+checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@@ -2159,24 +2259,24 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.79"
+version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca"
+checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b"
dependencies = [
"bumpalo",
- "lazy_static",
"log",
+ "once_cell",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.52",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
-version = "0.4.29"
+version = "0.4.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395"
+checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97"
dependencies = [
"cfg-if",
"js-sys",
@@ -2186,9 +2286,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.79"
+version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01"
+checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -2196,44 +2296,34 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.79"
+version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc"
+checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.52",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.79"
+version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2"
+checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838"
[[package]]
name = "web-sys"
-version = "0.3.56"
+version = "0.3.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb"
+checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
-name = "webpki"
-version = "0.21.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea"
-dependencies = [
- "ring",
- "untrusted",
-]
-
-[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2251,9 +2341,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",
]
@@ -2265,62 +2355,172 @@ 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.4",
+]
+
+[[package]]
name = "windows-sys"
-version = "0.32.0"
+version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6"
+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.4",
+]
+
+[[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.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.4",
+ "windows_aarch64_msvc 0.52.4",
+ "windows_i686_gnu 0.52.4",
+ "windows_i686_msvc 0.52.4",
+ "windows_x86_64_gnu 0.52.4",
+ "windows_x86_64_gnullvm 0.52.4",
+ "windows_x86_64_msvc 0.52.4",
+]
+
+[[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.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
+
+[[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.32.0"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5"
+checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
-version = "0.32.0"
+version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615"
+checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
[[package]]
name = "windows_i686_msvc"
-version = "0.32.0"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172"
+checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
-version = "0.32.0"
+version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc"
+checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
+
+[[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.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.32.0"
+version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316"
+checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
[[package]]
name = "winreg"
-version = "0.7.0"
+version = "0.50.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69"
+checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
dependencies = [
- "winapi",
+ "cfg-if",
+ "windows-sys 0.48.0",
]
[[package]]
-name = "yaml-rust"
-version = "0.4.5"
+name = "zerocopy"
+version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
+checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
dependencies = [
- "linked-hash-map",
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.52",
]
diff --git a/Cargo.toml b/Cargo.toml
index 36f1682..4666847 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,46 +1,46 @@
[package]
name = "obnam"
-version ="0.7.1"
+version ="0.8.1"
authors = ["Lars Wirzenius <liw@liw.fi>"]
edition = "2021"
description = "a backup program"
license = "AGPL-3.0-or-later"
homepage = "https://obnam.org/"
repository = "https://gitlab.com/obnam/obnam"
-rust-version = "1.56.0"
+rust-version = "1.75.0"
[dependencies]
-aes-gcm = "0.9"
-anyhow = "1"
-blake2 = "0.10.4"
-bytesize = "1"
-chrono = "0.4"
-directories-next = "2"
-futures = "0.3.15"
-indicatif = "0.16"
-libc = "0.2"
-log = "0.4"
-log4rs = "1"
-pbkdf2 = "0.10"
-pretty_env_logger = "0.4"
-rand = "0.8"
-reqwest = { version = "0.11", features = ["blocking", "json"]}
-rpassword = "5"
-rusqlite = "0.27"
-serde = { version = "1", features = ["derive"] }
-serde_json = "1"
-serde_yaml = "0.8"
-sha2 = "0.10"
+aes-gcm = "0.10.3"
+anyhow = "1.0.80"
+blake2 = "0.10.6"
+bytesize = "1.3.0"
+chrono = "0.4.34"
+clap = { version = "4.5.1", features = ["derive"] }
+directories-next = "2.0.0"
+futures = "0.3.30"
+indicatif = "0.17.8"
+libc = "0.2.153"
+log = "0.4.21"
+log4rs = "1.3.0"
+pbkdf2 = { version = "0.12.2", features = ["simple"] }
+pretty_env_logger = "0.5.0"
+rand = "0.8.5"
+reqwest = { version = "0.11.24", features = ["blocking", "json"]}
+rpassword = "7.3.1"
+rusqlite = "0.31.0"
+serde = { version = "1.0.197", features = ["derive"] }
+serde_json = "1.0.114"
+serde_yaml = "0.9.32"
+sha2 = "0.10.8"
spmc = "0.3.0"
-structopt = "0.3"
-tempfile = "3"
-thiserror = "1"
-tokio = { version = "1", features = ["full"] }
-users = "0.11"
-uuid = { version = "0.8", features = ["v4"] }
-walkdir = "2"
-warp = { version = "0.3", features = ["tls"] }
+tempfile = "3.10.1"
+thiserror = "1.0.57"
+tokio = { version = "1.36.0", features = ["full"] }
+users = "0.11.0"
+uuid = { version = "1.7.0", features = ["v4"] }
+walkdir = "2.5.0"
+warp = { version = "0.3.6", features = ["tls"] }
[profile.release]
debug = true
diff --git a/NEWS.md b/NEWS.md
index db53285..a2f1d23 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -6,6 +6,58 @@ of Obnam, the backup software. The software is technically called
ended in 2017 with version number 1.22.
+# Version 0.8.0, released 2022-07-24
+
+## Breaking changes
+
+Breaking changes are ones that mean existing backups can't be
+restored, or new backups can't be created.
+
+* The list of backups is stored in a special "root chunk". This means
+ backups are explicitly ordered. This also paves way for a future
+ feature to backups: only the root chunk will need to be updated.
+ Without a root chunk, the backups formed a linked list, and deleting
+ from the middle of the list would updating the whole list.
+
+* The server chunk metadata field `sha256` is now called `label`.
+ Labels include a type prefix, to allow for other chunk checksum
+ types in the future.
+
+* The server API is now explicitly versioned, to allow future changes
+ to cause less breakage.
+
+## New features
+
+* Users can now choose the backup schema version for new backups. A
+ repository can have backups with different schemas, and any existing
+ backup can be restored. The schema version only applies to new
+ backups.
+
+* New command `obnam inspect` shows metadata about a backup. Currently
+ only the schema version is shown.
+
+* New command `obnam list-backup-versions` shows all the backup schema
+ versions that this version of Obnam supports.
+
+* Obnam now logs some basic performance measurement for each run: how
+ many live files were found in total, backed up, chunks uploaded,
+ existing chunks reused, and how long various parts of the process
+ took.
+
+## Other changes
+
+* The `obnam show-generation` command now outputs data in the JSON
+ format. The output now includes data about the generation's SQLite
+ database size.
+
+## Thank you
+
+Several people have helped with this release, with changes or
+feedback.
+
+* Alexander Batischev
+* Lars Wirzenius
+
# Version 0.7.1, released 2022-03-08
## Bug fixes
diff --git a/check b/check
index 905bc5b..9e3e0a4 100755
--- a/check
+++ b/check
@@ -36,8 +36,6 @@ require_cmd python3
require_cmd subplot
require_cmd summain
require_cmd pkg-config
-require_cmd pandoc
-require_cmd pdflatex
# daemonize installation location changed from Debian 10 to 11.
require_cmd daemonize || require_cmd /usr/sbin/daemonize
@@ -50,11 +48,10 @@ $hideok cargo build --all-targets
got_cargo_cmd fmt && $hideok cargo fmt -- --check
$hideok cargo test
-subplot docgen obnam.md -o obnam.html
-subplot docgen obnam.md -o obnam.pdf
+subplot docgen obnam.subplot -o obnam.html
target="$(cargo metadata --format-version=1 | python3 -c 'import sys, json; o = json.load(sys.stdin); print(o["target_directory"])')"
-subplot codegen obnam.md -o test.py
+subplot codegen obnam.subplot -o test.py
rm -f test.log
if [ "$(id -un)" = root ]; then
echo Not running tests as root.
diff --git a/debian/changelog b/debian/changelog
index b5840b8..e73fed8 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,15 @@
+obnam (0.8.1-1) unstable; urgency=medium
+
+ * New Debian package
+
+ -- Lars Wirzenius <liw@liw.fi> Mon, 01 Jan 2024 16:22:35 +0200
+
+obnam (0.8.0-1) unstable; urgency=medium
+
+ * New release.
+
+ -- Lars Wirzenius <liw@liw.fi> Sun, 24 Jul 2022 11:13:59 +0300
+
obnam (0.7.1-1) unstable; urgency=medium
* New release.
diff --git a/debian/control b/debian/control
index 5d3167b..b13c20d 100644
--- a/debian/control
+++ b/debian/control
@@ -5,8 +5,6 @@ Priority: optional
Standards-Version: 4.2.0
Build-Depends:
debhelper (>= 10~),
- build-essential,
- dh-cargo,
daemonize,
git,
libsqlite3-dev,
@@ -16,12 +14,8 @@ Build-Depends:
python3,
python3-requests,
python3-yaml,
- strace,
subplot,
- summain,
- texlive-fonts-recommended,
- texlive-latex-base,
- texlive-latex-recommended
+ summain
Homepage: https://obnam.org
Package: obnam
diff --git a/debian/rules b/debian/rules
index ecfca56..7a3e4e9 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,15 +1,15 @@
#!/usr/bin/make -f
%:
- dh $@ --buildsystem cargo
+ dh $@
override_dh_auto_build:
true
override_dh_auto_install:
- cargo install --path=. --root=debian/obnam
- find debian/obnam -name '.crates*' -delete
+ cargo install --path=. --root=debian/obnam --offline
+ find debian -name '.crates*' -delete
find debian/obnam/bin -type f ! -name 'obnam*' -delete
override_dh_auto_test:
- ./check
+ echo disabled: ./check
diff --git a/deny.toml b/deny.toml
index 08ad9ef..f6e7bb8 100644
--- a/deny.toml
+++ b/deny.toml
@@ -14,7 +14,6 @@ notice = "deny"
ignore = [
"RUSTSEC-2020-0027",
"RUSTSEC-2020-0071",
- "RUSTSEC-2020-0159",
]
[licenses]
@@ -26,6 +25,7 @@ allow = [
"ISC",
"LicenseRef-ring",
"MIT",
+ "Unicode-DFS-2016",
]
deny = [
#"Nokia",
diff --git a/obnam.md b/obnam.md
index 396bc44..c4122c2 100644
--- a/obnam.md
+++ b/obnam.md
@@ -1,26 +1,3 @@
----
-title: "Obnam2&mdash;a backup system"
-author: Lars Wirzenius
-documentclass: report
-bindings:
- - subplot/server.yaml
- - subplot/client.yaml
- - subplot/data.yaml
- - lib/files.yaml
- - lib/runcmd.yaml
-impls:
- python:
- - subplot/server.py
- - subplot/client.py
- - subplot/data.py
- - lib/daemon.py
- - lib/files.py
- - lib/runcmd.py
-classes:
- - json
- - sql
-...
-
# Abstract
Obnam is a backup system, consisting of a not very smart server for
@@ -204,6 +181,23 @@ This is mitigated in two ways:
[CACHEDIR.TAG]: https://bford.info/cachedir/
+## Attacker can read backups via chunk server HTTP API
+
+This threat arises from the fact that the chunk server HTTP API
+currently has no authentication. This allows an attacker who can
+access the API to copy the backups and break their encryption at
+leisure.
+
+The mitigation is to add access control for the API.
+
+A simple approach is to have the chunk server admin to create an
+**access token** that the client must provide with each API request.
+The token can be stored in the client configuration by `obnam init`.
+
+This would be the simplest possible access control approach. More
+nuanced approaches will be added later.
+
+
# Software architecture
## Effects of requirements
@@ -587,6 +581,153 @@ using configuration management, and if necessary, backups can be
triggered on each host by having the server reach out and run the
Obnam client.
+## On splitting file data into chunks
+
+A backup program needs to split the data it backs up into chunks. This
+can be done in various ways.
+
+### A complete file as a single chunk
+
+This is a very simple approach, where the whole file is considered to
+be a chunk, regardless of its size.
+
+Using complete files is often impractical, since they need to be
+stored and transferred as a unit. If a file is enormous, transferring
+it completely can be a challenge: if there's a one-bit error in the
+transfer, the whole thing needs to be transferred again.
+
+There is no de-duplication except possibly of entire files.
+
+### Fixed size chunks
+
+Split a file into chunks of a fixed size. For example, if the chunk
+size is 1 MiB, a 1 GiB file is 1024 chunks. All chunks are of the same
+size, unless a file size is not a multiple of the chunk size.
+
+Fixed size chunks are very easy to implement and make de-duplication
+of partial files possible. However, that de-duplication tends to only
+work for the beginnings of file: inserting data in the file tends to
+result in chunks after the insertion not matching anymore.
+
+### Splitting based on a formula using content
+
+A rolling checksum function is computed on a sliding window of bytes
+from the input file. The window has a fixed size. The function is
+extremely efficient to compute when bytes are moved into or out of the
+window. When the value of the function, the checksum, matches a
+certain bit pattern, it is considered a chunk boundary. Such a pattern
+might for example be that the lowest N bits are zero. Any data that
+is pushed out of the sliding window also forms a chunk.
+
+The code to split into chunks may set minimum and maximum sizes of
+chunks, whether from checksum patterns or overflowed bytes. This
+prevents pathological input data, where the checksum has the boundary
+bit pattern after every byte, to not result in each input byte being
+its own chunk.
+
+This finds chunks efficiently even new data is inserted into the input
+data, with some caveats.
+
+Example: assume a sliding window of four bytes, and a 17-byte input
+file where there are four copies of the same 4-byte sequence with a
+random byte in between.
+
++------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+|data | a| b| c| d| a| b| c| d|ff| a| b| c| d| a| b| c| d|
++------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+|offset|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|
++------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+Bytes 1-4 are the same as bytes 5-8, 10-13, and 14-17. When we compute
+the checksum for each input byte, we get the results below, for a
+moving sum function.
+
++--------+------+----------+-----------------+
+| offset | byte | checksum | chunk boundary? |
++--------+------+----------+-----------------+
+| 0 | a | a | no |
++--------+------+----------+-----------------+
+| 1 | b | a+b | no |
++--------+------+----------+-----------------+
+| 2 | c | a+b+c | no |
++--------+------+----------+-----------------+
+| 3 | d | a+b+c+ | yes |
++--------+------+----------+-----------------+
+| 4 | a | a | no |
++--------+------+----------+-----------------+
+| 5 | b | a+b | no |
++--------+------+----------+-----------------+
+| 6 | c | a+b+c | no |
++--------+------+----------+-----------------+
+| 7 | d | a+b+c+ | yes |
++--------+------+----------+-----------------+
+| 9 | ff | ff | no |
++--------+------+----------+-----------------+
+| 10 | a | ff+a | no |
++--------+------+----------+-----------------+
+| 11 | b | ff+a+b | no |
++--------+------+----------+-----------------+
+| 12 | c | ff+a+b+c | no |
++--------+------+----------+-----------------+
+| 13 | d | a+b+c+d | yes |
++--------+------+----------+-----------------+
+| 14 | a | a | no |
++--------+------+----------+-----------------+
+| 15 | b | a+b | no |
++--------+------+----------+-----------------+
+| 16 | c | a+b+c | no |
++--------+------+----------+-----------------+
+| 17 | d | a+b+c+ | yes |
++--------+------+----------+-----------------+
+
+Note that in this example, the byte at offset 9 (0xff) slides out of
+the window then byte at offset 13 slides in, and in results in bytes
+at offsets 10-13 being recognized as a chunk by the checksum function.
+This example is carefully constructed for that happy co-incidence. In
+a more realistic scenario, the data after the inserted bytes might not
+notice a chunk boundary until after the sliding window has been filled
+once.
+
+By choosing a suitable window size and checksum value pattern for
+chunk boundaries, the chunk splitting can find smaller or large
+chunks, balancing the possibility for more detailed de-duplication
+versus the overhead of storing many chunks.
+
+### Varying splitting method based on file type
+
+The data may contain files of different types, and this can be used to
+vary the way data is split into chunks. For example, compressed video
+files may use one way of chunking, while software source code may use
+another.
+
+For example:
+
+* emails in mbox or Maildir formats could be split based on headers,
+ body, and attachment and each of those into chunks
+* SQL dumps of databases tend to contain very large numbers containing
+ the same structure
+* video files are often split into frames, possibly those can be used
+ for intelligent chunking?
+* uncompressed tar files have a definite structure (header, followed
+ by file data) that can probably be used for splitting into chunks
+* ZIP files compress each file separately, which could be used to
+ split them into chunks: this way, two ZIP files with the same file
+ inside them might share the compressed file as a chunk
+* disk images often contain long sequences of zeroes, which could be
+ used for splitting into chunks
+
+### Next actions
+
+Obnam currently splits data using fixed size chunks. This can and will
+be improved, and the changes will only affect the client. Help is
+welcome.
+
+### Thanks
+
+Thank you to Daniel Silverstone who explained some of the mathematics
+about this to me.
+
+
# File metadata
Files in a file system contain data and have metadata: data about the
@@ -1118,21 +1259,6 @@ and content-type is application/json
and the JSON body matches {"<ID>":{"label":"0abc"}}
~~~
-Finally, we must be able to delete it. After that, we must not be able
-to retrieve it, or find it using metadata.
-
-~~~scenario
-when I DELETE /v1/chunks/<ID>
-then HTTP status code is 200
-
-when I GET /v1/chunks/<ID>
-then HTTP status code is 404
-
-when I GET /v1/chunks?label=0abc
-then HTTP status code is 200
-and content-type is application/json
-and the JSON body matches {}
-~~~
## Retrieve a chunk that does not exist
@@ -1157,17 +1283,6 @@ and content-type is application/json
and the JSON body matches {}
~~~
-## Delete chunk that does not exist
-
-We must get the right error when deleting a chunk that doesn't exist.
-
-~~~scenario
-given a working Obnam system
-when I try to DELETE /v1/chunks/any.random.string
-then HTTP status code is 404
-~~~
-
-
## Persistent across restarts
Chunk storage, and the index of chunk metadata for searches, needs to
@@ -1333,7 +1448,7 @@ and a client config based on ca-required.yaml
and a file live/data.dat containing some random data
when I try to run obnam backup
then command fails
-then stderr contains "self signed certificate"
+then stderr matches regex self.signed certificate
~~~
~~~{#ca-required.yaml .file .yaml .numberLines}
@@ -1662,8 +1777,12 @@ given a manifest of the directory live restored in rest in rest.yaml
then manifests live.yaml and rest.yaml match
~~~
-## Unreadable file
+## FIXME: Unreadable file
+FIXME: This scenario has been disabled, temporarily, as my current CI
+system runs things as `root` and that means this scenario fails.
+
+~~~~~~~~
This scenario verifies that Obnam will back up all files of live data,
even if one of them is unreadable. By inference, we assume this means
other errors on individual files also won't end the backup
@@ -1682,9 +1801,14 @@ when I invoke obnam restore <GEN> rest
then file live/data.dat is restored to rest
then file live/bad.dat is not restored to rest
~~~
+~~~~~~~~
+
+## FIXME: Unreadable directory
-## Unreadable directory
+FIXME: This scenario has been disabled, temporarily, as my current CI
+system runs things as `root` and that means this scenario fails.
+~~~~~~~~
This scenario verifies that Obnam will skip a file in a directory it
can't read. Obnam should warn about that, but not give an error.
@@ -1700,9 +1824,14 @@ when I invoke obnam restore <GEN> rest
then file live/unreadable is restored to rest
then file live/unreadable/data.dat is not restored to rest
~~~
+~~~~~~~~
-## Unexecutable directory
+## FIXME: Unexecutable directory
+FIXME: This scenario has been disabled, temporarily, as my current CI
+system runs things as `root` and that means this scenario fails.
+
+~~~~~~~
This scenario verifies that Obnam will skip a file in a directory it
can't read. Obnam should warn about that, but not give an error.
@@ -1718,6 +1847,8 @@ when I invoke obnam restore <GEN> rest
then file live/dir is restored to rest
then file live/dir/data.dat is not restored to rest
~~~
+~~~~~~~
+
## Restore latest generation
diff --git a/obnam.subplot b/obnam.subplot
new file mode 100644
index 0000000..10a0ad7
--- /dev/null
+++ b/obnam.subplot
@@ -0,0 +1,23 @@
+title: "Obnam2&mdash;a backup system"
+authors:
+ - Lars Wirzenius
+documentclass: report
+markdowns:
+ - obnam.md
+bindings:
+ - subplot/server.yaml
+ - subplot/client.yaml
+ - subplot/data.yaml
+ - lib/files.yaml
+ - lib/runcmd.yaml
+impls:
+ python:
+ - subplot/server.py
+ - subplot/client.py
+ - subplot/data.py
+ - lib/daemon.py
+ - lib/files.py
+ - lib/runcmd.py
+classes:
+ - json
+ - sql
diff --git a/src/accumulated_time.rs b/src/accumulated_time.rs
index e633a10..cdf34b2 100644
--- a/src/accumulated_time.rs
+++ b/src/accumulated_time.rs
@@ -37,7 +37,7 @@ impl<T: Eq + PartialEq + Hash + Copy> AccumulatedTime<T> {
/// clock is stopped.
pub fn start(&mut self, clock: T) {
let mut map = self.accumulated.lock().unwrap();
- let ct = map.entry(clock).or_insert_with(ClockTime::default);
+ let ct = map.entry(clock).or_default();
assert!(ct.started.is_none());
ct.started = Some(Instant::now());
}
@@ -47,7 +47,7 @@ impl<T: Eq + PartialEq + Hash + Copy> AccumulatedTime<T> {
/// Its run time is added to the accumulated time for that kind of clock.
pub fn stop(&mut self, clock: T) {
let mut map = self.accumulated.lock().unwrap();
- if let Some(mut ct) = map.get_mut(&clock) {
+ if let Some(ct) = map.get_mut(&clock) {
assert!(ct.started.is_some());
if let Some(started) = ct.started.take() {
ct.nanos += started.elapsed().as_nanos();
diff --git a/src/backup_progress.rs b/src/backup_progress.rs
index f119210..e3995f0 100644
--- a/src/backup_progress.rs
+++ b/src/backup_progress.rs
@@ -2,7 +2,7 @@
use crate::generation::GenId;
use indicatif::{ProgressBar, ProgressStyle};
-use std::path::Path;
+use std::{path::Path, time::Duration};
const SHOW_PROGRESS: bool = true;
@@ -22,15 +22,19 @@ impl BackupProgress {
} else {
ProgressBar::hidden()
};
- let parts = vec![
+ let parts = [
"initial backup",
"elapsed: {elapsed}",
"files: {pos}",
"current: {wide_msg}",
"{spinner}",
];
- progress.set_style(ProgressStyle::default_bar().template(&parts.join("\n")));
- progress.enable_steady_tick(100);
+ progress.set_style(
+ ProgressStyle::default_bar()
+ .template(&parts.join("\n"))
+ .expect("create indicatif ProgressStyle value"),
+ );
+ progress.enable_steady_tick(Duration::from_millis(100));
Self { progress }
}
@@ -42,7 +46,7 @@ impl BackupProgress {
} else {
ProgressBar::hidden()
};
- let parts = vec![
+ let parts = [
"incremental backup",
"{wide_bar}",
"elapsed: {elapsed}",
@@ -50,8 +54,12 @@ impl BackupProgress {
"current: {wide_msg}",
"{spinner}",
];
- progress.set_style(ProgressStyle::default_bar().template(&parts.join("\n")));
- progress.enable_steady_tick(100);
+ progress.set_style(
+ ProgressStyle::default_bar()
+ .template(&parts.join("\n"))
+ .expect("create indicatif ProgressStyle value"),
+ );
+ progress.enable_steady_tick(Duration::from_millis(100));
Self { progress }
}
@@ -59,13 +67,17 @@ impl BackupProgress {
/// Create a progress bar for uploading a new generation's metadata.
pub fn upload_generation() -> Self {
let progress = ProgressBar::new(0);
- let parts = vec![
+ let parts = [
"uploading new generation metadata",
"elapsed: {elapsed}",
"{spinner}",
];
- progress.set_style(ProgressStyle::default_bar().template(&parts.join("\n")));
- progress.enable_steady_tick(100);
+ progress.set_style(
+ ProgressStyle::default_bar()
+ .template(&parts.join("\n"))
+ .expect("create indicatif ProgressStyle value"),
+ );
+ progress.enable_steady_tick(Duration::from_millis(100));
Self { progress }
}
@@ -74,9 +86,13 @@ impl BackupProgress {
/// metadata.
pub fn download_generation(gen_id: &GenId) -> Self {
let progress = ProgressBar::new(0);
- let parts = vec!["{msg}", "elapsed: {elapsed}", "{spinner}"];
- progress.set_style(ProgressStyle::default_bar().template(&parts.join("\n")));
- progress.enable_steady_tick(100);
+ let parts = ["{msg}", "elapsed: {elapsed}", "{spinner}"];
+ progress.set_style(
+ ProgressStyle::default_bar()
+ .template(&parts.join("\n"))
+ .expect("create indicatif ProgressStyle value"),
+ );
+ progress.enable_steady_tick(Duration::from_millis(100));
progress.set_message(format!(
"downloading previous generation metadata: {}",
gen_id
@@ -102,7 +118,7 @@ impl BackupProgress {
/// Update progress bar about number of actual files found.
pub fn found_live_file(&self, filename: &Path) {
self.progress.inc(1);
- if self.progress.length() < self.progress.position() {
+ if self.progress.length() < Some(self.progress.position()) {
self.progress.set_length(self.progress.position());
}
self.progress.set_message(format!("{}", filename.display()));
diff --git a/src/backup_run.rs b/src/backup_run.rs
index 2418871..372ef65 100644
--- a/src/backup_run.rs
+++ b/src/backup_run.rs
@@ -31,7 +31,7 @@ const SQLITE_CHUNK_SIZE: usize = MIB as usize;
/// A running backup.
pub struct BackupRun<'a> {
checksum_kind: Option<LabelChecksumKind>,
- client: &'a BackupClient,
+ client: &'a mut BackupClient,
policy: BackupPolicy,
buffer_size: usize,
progress: Option<BackupProgress>,
@@ -106,7 +106,10 @@ pub struct RootsBackupOutcome {
impl<'a> BackupRun<'a> {
/// Create a new run for an initial backup.
- pub fn initial(config: &ClientConfig, client: &'a BackupClient) -> Result<Self, BackupError> {
+ pub fn initial(
+ config: &ClientConfig,
+ client: &'a mut BackupClient,
+ ) -> Result<Self, BackupError> {
Ok(Self {
checksum_kind: Some(DEFAULT_CHECKSUM_KIND),
client,
@@ -119,7 +122,7 @@ impl<'a> BackupRun<'a> {
/// Create a new run for an incremental backup.
pub fn incremental(
config: &ClientConfig,
- client: &'a BackupClient,
+ client: &'a mut BackupClient,
) -> Result<Self, BackupError> {
Ok(Self {
checksum_kind: None,
@@ -166,9 +169,7 @@ impl<'a> BackupRun<'a> {
}
fn checksum_kind(&self) -> LabelChecksumKind {
- self.checksum_kind
- .or(Some(LabelChecksumKind::Sha256))
- .unwrap()
+ self.checksum_kind.unwrap_or(LabelChecksumKind::Sha256)
}
async fn fetch_previous_generation(
@@ -191,7 +192,7 @@ impl<'a> BackupRun<'a> {
/// Back up all the roots for this run.
pub async fn backup_roots(
- &self,
+ &mut self,
config: &ClientConfig,
old: &LocalGeneration,
newpath: &Path,
@@ -238,7 +239,7 @@ impl<'a> BackupRun<'a> {
}
async fn backup_one_root(
- &self,
+ &mut self,
config: &ClientConfig,
old: &LocalGeneration,
new: &mut NascentGeneration,
@@ -289,7 +290,7 @@ impl<'a> BackupRun<'a> {
}
async fn backup_if_needed(
- &self,
+ &mut self,
entry: AnnotatedFsEntry,
old: &LocalGeneration,
) -> Result<Option<FsEntryBackupOutcome>, BackupError> {
@@ -324,7 +325,7 @@ impl<'a> BackupRun<'a> {
}
async fn backup_one_entry(
- &self,
+ &mut self,
entry: &AnnotatedFsEntry,
path: &Path,
reason: Reason,
@@ -353,7 +354,7 @@ impl<'a> BackupRun<'a> {
/// Upload any file content for a file system entry.
pub async fn upload_filesystem_entry(
- &self,
+ &mut self,
e: &FilesystemEntry,
size: usize,
) -> Result<Vec<ChunkId>, BackupError> {
@@ -372,7 +373,7 @@ impl<'a> BackupRun<'a> {
/// Upload the metadata for the backup of this run.
pub async fn upload_generation(
- &self,
+ &mut self,
filename: &Path,
size: usize,
) -> Result<ChunkId, BackupError> {
@@ -386,7 +387,7 @@ impl<'a> BackupRun<'a> {
}
async fn upload_regular_file(
- &self,
+ &mut self,
filename: &Path,
size: usize,
) -> Result<Vec<ChunkId>, BackupError> {
@@ -409,7 +410,7 @@ impl<'a> BackupRun<'a> {
Ok(chunk_ids)
}
- async fn upload_nascent_generation(&self, filename: &Path) -> Result<ChunkId, ObnamError> {
+ async fn upload_nascent_generation(&mut self, filename: &Path) -> Result<ChunkId, ObnamError> {
let progress = BackupProgress::upload_generation();
let gen_id = self.upload_generation(filename, SQLITE_CHUNK_SIZE).await?;
progress.finish();
diff --git a/src/bin/obnam-server.rs b/src/bin/obnam-server.rs
index 6cf4122..9b5a557 100644
--- a/src/bin/obnam-server.rs
+++ b/src/bin/obnam-server.rs
@@ -1,9 +1,10 @@
use anyhow::Context;
+use clap::Parser;
use log::{debug, error, info};
-use obnam::chunk::DataChunk;
use obnam::chunkid::ChunkId;
use obnam::chunkmeta::ChunkMeta;
-use obnam::indexedstore::IndexedStore;
+use obnam::chunkstore::ChunkStore;
+use obnam::label::Label;
use obnam::server::{ServerConfig, ServerConfigError};
use serde::Serialize;
use std::collections::HashMap;
@@ -11,16 +12,14 @@ use std::default::Default;
use std::net::{SocketAddr, ToSocketAddrs};
use std::path::{Path, PathBuf};
use std::sync::Arc;
-use structopt::StructOpt;
use tokio::sync::Mutex;
use warp::http::StatusCode;
use warp::hyper::body::Bytes;
use warp::Filter;
-#[derive(Debug, StructOpt)]
-#[structopt(name = "obnam2-server", about = "Backup server")]
+#[derive(Debug, Parser)]
+#[clap(name = "obnam2-server", about = "Backup server")]
struct Opt {
- #[structopt(parse(from_os_str))]
config: PathBuf,
}
@@ -28,7 +27,7 @@ struct Opt {
async fn main() -> anyhow::Result<()> {
pretty_env_logger::init_custom_env("OBNAM_SERVER_LOG");
- let opt = Opt::from_args();
+ let opt = Opt::parse();
let config = load_config(&opt.config)?;
let addresses: Vec<SocketAddr> = config.address.to_socket_addrs()?.collect();
@@ -38,7 +37,7 @@ async fn main() -> anyhow::Result<()> {
return Err(ServerConfigError::BadServerAddress.into());
}
- let store = IndexedStore::new(&config.chunks)?;
+ let store = ChunkStore::local(&config.chunks)?;
let store = Arc::new(Mutex::new(store));
let store = warp::any().map(move || Arc::clone(&store));
@@ -71,16 +70,8 @@ async fn main() -> anyhow::Result<()> {
.and(store.clone())
.and_then(search_chunks);
- let delete = warp::delete()
- .and(warp::path("v1"))
- .and(warp::path("chunks"))
- .and(warp::path::param())
- .and(warp::path::end())
- .and(store.clone())
- .and_then(delete_chunk);
-
let log = warp::log("obnam");
- let webroot = create.or(fetch).or(search).or(delete).with(log);
+ let webroot = create.or(fetch).or(search).with(log);
debug!("starting warp");
warp::serve(webroot)
@@ -103,11 +94,11 @@ fn load_config(filename: &Path) -> Result<ServerConfig, anyhow::Error> {
}
pub async fn create_chunk(
- store: Arc<Mutex<IndexedStore>>,
+ store: Arc<Mutex<ChunkStore>>,
meta: String,
data: Bytes,
) -> Result<impl warp::Reply, warp::Rejection> {
- let mut store = store.lock().await;
+ let store = store.lock().await;
let meta: ChunkMeta = match meta.parse() {
Ok(s) => s,
@@ -117,9 +108,7 @@ pub async fn create_chunk(
}
};
- let chunk = DataChunk::new(data.to_vec(), meta);
-
- let id = match store.save(&chunk) {
+ let id = match store.put(data.to_vec(), &meta).await {
Ok(id) => id,
Err(e) => {
error!("couldn't save: {}", e);
@@ -133,11 +122,11 @@ pub async fn create_chunk(
pub async fn fetch_chunk(
id: String,
- store: Arc<Mutex<IndexedStore>>,
+ store: Arc<Mutex<ChunkStore>>,
) -> Result<impl warp::Reply, warp::Rejection> {
let store = store.lock().await;
let id: ChunkId = id.parse().unwrap();
- match store.load(&id) {
+ match store.get(&id).await {
Ok((data, meta)) => {
info!("found chunk {}: {:?}", id, meta);
Ok(ChunkResult::Fetched(meta, data))
@@ -151,18 +140,23 @@ pub async fn fetch_chunk(
pub async fn search_chunks(
query: HashMap<String, String>,
- store: Arc<Mutex<IndexedStore>>,
+ store: Arc<Mutex<ChunkStore>>,
) -> Result<impl warp::Reply, warp::Rejection> {
let store = store.lock().await;
let mut query = query.iter();
let found = if let Some((key, value)) = query.next() {
- if query.next() != None {
+ if query.next().is_some() {
error!("search has more than one key to search for");
return Ok(ChunkResult::BadRequest);
}
if key == "label" {
- store.find_by_label(value).expect("SQL lookup failed")
+ let label = Label::deserialize(value).unwrap();
+ let label = ChunkMeta::new(&label);
+ store
+ .find_by_label(&label)
+ .await
+ .expect("SQL lookup failed")
} else {
error!("unknown search key {:?}", key);
return Ok(ChunkResult::BadRequest);
@@ -174,7 +168,7 @@ pub async fn search_chunks(
let mut hits = SearchHits::default();
for chunk_id in found {
- let meta = match store.load_meta(&chunk_id) {
+ let (_, meta) = match store.get(&chunk_id).await {
Ok(meta) => {
info!("search found chunk {}", chunk_id);
meta
@@ -213,30 +207,10 @@ impl SearchHits {
}
}
-pub async fn delete_chunk(
- id: String,
- store: Arc<Mutex<IndexedStore>>,
-) -> Result<impl warp::Reply, warp::Rejection> {
- let mut store = store.lock().await;
- let id: ChunkId = id.parse().unwrap();
-
- match store.remove(&id) {
- Ok(_) => {
- info!("chunk deleted: {}", id);
- Ok(ChunkResult::Deleted)
- }
- Err(e) => {
- error!("could not delete chunk {}: {:?}", id, e);
- Ok(ChunkResult::NotFound)
- }
- }
-}
-
enum ChunkResult {
Created(ChunkId),
- Fetched(ChunkMeta, DataChunk),
+ Fetched(ChunkMeta, Vec<u8>),
Found(SearchHits),
- Deleted,
NotFound,
BadRequest,
InternalServerError,
@@ -265,13 +239,12 @@ impl warp::Reply for ChunkResult {
);
into_response(
StatusCode::OK,
- chunk.data(),
+ &chunk,
"application/octet-stream",
Some(headers),
)
}
ChunkResult::Found(hits) => json_response(StatusCode::OK, hits.to_json(), None),
- ChunkResult::Deleted => status_response(StatusCode::OK),
ChunkResult::BadRequest => status_response(StatusCode::BAD_REQUEST),
ChunkResult::NotFound => status_response(StatusCode::NOT_FOUND),
ChunkResult::InternalServerError => status_response(StatusCode::INTERNAL_SERVER_ERROR),
diff --git a/src/bin/obnam.rs b/src/bin/obnam.rs
index 089a7a1..240960b 100644
--- a/src/bin/obnam.rs
+++ b/src/bin/obnam.rs
@@ -1,3 +1,4 @@
+use clap::Parser;
use directories_next::ProjectDirs;
use log::{debug, error, info, LevelFilter};
use log4rs::append::file::FileAppender;
@@ -19,7 +20,6 @@ use obnam::cmd::show_gen::ShowGeneration;
use obnam::config::ClientConfig;
use obnam::performance::{Clock, Performance};
use std::path::{Path, PathBuf};
-use structopt::StructOpt;
const QUALIFIER: &str = "";
const ORG: &str = "";
@@ -38,7 +38,7 @@ fn main() {
}
fn main_program(perf: &mut Performance) -> anyhow::Result<()> {
- let opt = Opt::from_args();
+ let opt = Opt::parse();
let config = ClientConfig::read(&config_filename(&opt))?;
setup_logging(&config.log)?;
@@ -96,17 +96,17 @@ fn default_config() -> PathBuf {
}
}
-#[derive(Debug, StructOpt)]
-#[structopt(name = "obnam-backup", about = "Simplistic backup client")]
+#[derive(Debug, Parser)]
+#[clap(name = "obnam-backup", version, about = "Simplistic backup client")]
struct Opt {
- #[structopt(long, short, parse(from_os_str))]
+ #[clap(long, short)]
config: Option<PathBuf>,
- #[structopt(subcommand)]
+ #[clap(subcommand)]
cmd: Command,
}
-#[derive(Debug, StructOpt)]
+#[derive(Debug, Parser)]
enum Command {
Init(Init),
Backup(Backup),
diff --git a/src/chunk.rs b/src/chunk.rs
index 4f604b9..a6abad3 100644
--- a/src/chunk.rs
+++ b/src/chunk.rs
@@ -13,7 +13,7 @@ use std::default::Default;
/// together. The identifier is used to find the chunk, and it's
/// assigned by the server when the chunk is uploaded, so it's not
/// stored in the chunk itself.
-#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
+#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
pub struct DataChunk {
data: Vec<u8>,
meta: ChunkMeta,
diff --git a/src/chunker.rs b/src/chunker.rs
index 29f8a90..9883f89 100644
--- a/src/chunker.rs
+++ b/src/chunker.rs
@@ -31,8 +31,7 @@ impl FileChunks {
filename: &Path,
kind: LabelChecksumKind,
) -> Self {
- let mut buf = vec![];
- buf.resize(chunk_size, 0);
+ let buf = vec![0; chunk_size];
Self {
chunk_size,
kind,
diff --git a/src/chunkmeta.rs b/src/chunkmeta.rs
index fe7ef4c..e2fa9b3 100644
--- a/src/chunkmeta.rs
+++ b/src/chunkmeta.rs
@@ -28,7 +28,7 @@ use std::str::FromStr;
///
/// [ISO 8601]: https://en.wikipedia.org/wiki/ISO_8601
/// [SHA256]: https://en.wikipedia.org/wiki/SHA-2
-#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
+#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
pub struct ChunkMeta {
label: String,
}
diff --git a/src/chunkstore.rs b/src/chunkstore.rs
new file mode 100644
index 0000000..4c8125c
--- /dev/null
+++ b/src/chunkstore.rs
@@ -0,0 +1,307 @@
+//! Access local and remote chunk stores.
+//!
+//! A chunk store may be local and accessed via the file system, or
+//! remote and accessed over HTTP. This module implements both. This
+//! module only handles encrypted chunks.
+
+use crate::chunkid::ChunkId;
+use crate::chunkmeta::ChunkMeta;
+use crate::config::{ClientConfig, ClientConfigError};
+use crate::index::{Index, IndexError};
+
+use log::{debug, error, info};
+use reqwest::header::HeaderMap;
+use std::collections::HashMap;
+use std::path::{Path, PathBuf};
+use tokio::sync::Mutex;
+
+/// A chunk store.
+///
+/// The store may be local or remote.
+pub enum ChunkStore {
+ /// A local chunk store.
+ Local(LocalStore),
+
+ /// A remote chunk store.
+ Remote(RemoteStore),
+}
+
+impl ChunkStore {
+ /// Open a local chunk store.
+ pub fn local<P: AsRef<Path>>(path: P) -> Result<Self, StoreError> {
+ let store = LocalStore::new(path.as_ref())?;
+ Ok(Self::Local(store))
+ }
+
+ /// Open a remote chunk store.
+ pub fn remote(config: &ClientConfig) -> Result<Self, StoreError> {
+ let store = RemoteStore::new(config)?;
+ Ok(Self::Remote(store))
+ }
+
+ /// Does the store have a chunk with a given label?
+ pub async fn find_by_label(&self, meta: &ChunkMeta) -> Result<Vec<ChunkId>, StoreError> {
+ match self {
+ Self::Local(store) => store.find_by_label(meta).await,
+ Self::Remote(store) => store.find_by_label(meta).await,
+ }
+ }
+
+ /// Store a chunk in the store.
+ ///
+ /// The store chooses an id for the chunk.
+ pub async fn put(&self, chunk: Vec<u8>, meta: &ChunkMeta) -> Result<ChunkId, StoreError> {
+ match self {
+ Self::Local(store) => store.put(chunk, meta).await,
+ Self::Remote(store) => store.put(chunk, meta).await,
+ }
+ }
+
+ /// Get a chunk given its id.
+ pub async fn get(&self, id: &ChunkId) -> Result<(Vec<u8>, ChunkMeta), StoreError> {
+ match self {
+ Self::Local(store) => store.get(id).await,
+ Self::Remote(store) => store.get(id).await,
+ }
+ }
+}
+
+/// A local chunk store.
+pub struct LocalStore {
+ path: PathBuf,
+ index: Mutex<Index>,
+}
+
+impl LocalStore {
+ fn new(path: &Path) -> Result<Self, StoreError> {
+ Ok(Self {
+ path: path.to_path_buf(),
+ index: Mutex::new(Index::new(path)?),
+ })
+ }
+
+ async fn find_by_label(&self, meta: &ChunkMeta) -> Result<Vec<ChunkId>, StoreError> {
+ self.index
+ .lock()
+ .await
+ .find_by_label(meta.label())
+ .map_err(StoreError::Index)
+ }
+
+ async fn put(&self, chunk: Vec<u8>, meta: &ChunkMeta) -> Result<ChunkId, StoreError> {
+ let id = ChunkId::new();
+ let (dir, filename) = self.filename(&id);
+
+ if !dir.exists() {
+ std::fs::create_dir_all(&dir).map_err(|err| StoreError::ChunkMkdir(dir, err))?;
+ }
+
+ std::fs::write(&filename, &chunk)
+ .map_err(|err| StoreError::WriteChunk(filename.clone(), err))?;
+ self.index
+ .lock()
+ .await
+ .insert_meta(id.clone(), meta.clone())
+ .map_err(StoreError::Index)?;
+ Ok(id)
+ }
+
+ async fn get(&self, id: &ChunkId) -> Result<(Vec<u8>, ChunkMeta), StoreError> {
+ let meta = self.index.lock().await.get_meta(id)?;
+
+ let (_, filename) = &self.filename(id);
+
+ let raw =
+ std::fs::read(filename).map_err(|err| StoreError::ReadChunk(filename.clone(), err))?;
+
+ Ok((raw, meta))
+ }
+
+ fn filename(&self, id: &ChunkId) -> (PathBuf, PathBuf) {
+ let bytes = id.as_bytes();
+ assert!(bytes.len() > 3);
+ let a = bytes[0];
+ let b = bytes[1];
+ let c = bytes[2];
+ let dir = self.path.join(format!("{}/{}/{}", a, b, c));
+ let filename = dir.join(format!("{}.data", id));
+ (dir, filename)
+ }
+}
+
+/// A remote chunk store.
+pub struct RemoteStore {
+ client: reqwest::Client,
+ base_url: String,
+}
+
+impl RemoteStore {
+ fn new(config: &ClientConfig) -> Result<Self, StoreError> {
+ info!("creating remote store with config: {:#?}", config);
+
+ let client = reqwest::Client::builder()
+ .danger_accept_invalid_certs(!config.verify_tls_cert)
+ .build()
+ .map_err(StoreError::ReqwestError)?;
+ Ok(Self {
+ client,
+ base_url: config.server_url.to_string(),
+ })
+ }
+
+ async fn find_by_label(&self, meta: &ChunkMeta) -> Result<Vec<ChunkId>, StoreError> {
+ let body = match self.get_helper("", &[("label", meta.label())]).await {
+ Ok((_, body)) => body,
+ Err(err) => return Err(err),
+ };
+
+ let hits: HashMap<String, ChunkMeta> =
+ serde_json::from_slice(&body).map_err(StoreError::JsonParse)?;
+ let ids = hits.keys().map(|id| ChunkId::recreate(id)).collect();
+ Ok(ids)
+ }
+
+ async fn put(&self, chunk: Vec<u8>, meta: &ChunkMeta) -> Result<ChunkId, StoreError> {
+ let res = self
+ .client
+ .post(&self.chunks_url())
+ .header("chunk-meta", meta.to_json())
+ .body(chunk)
+ .send()
+ .await
+ .map_err(StoreError::ReqwestError)?;
+ let res: HashMap<String, String> = res.json().await.map_err(StoreError::ReqwestError)?;
+ debug!("upload_chunk: res={:?}", res);
+ let chunk_id = if let Some(chunk_id) = res.get("chunk_id") {
+ debug!("upload_chunk: id={}", chunk_id);
+ chunk_id.parse().unwrap()
+ } else {
+ return Err(StoreError::NoCreatedChunkId);
+ };
+ info!("uploaded_chunk {}", chunk_id);
+ Ok(chunk_id)
+ }
+
+ async fn get(&self, id: &ChunkId) -> Result<(Vec<u8>, ChunkMeta), StoreError> {
+ let (headers, body) = self.get_helper(&format!("/{}", id), &[]).await?;
+ let meta = self.get_chunk_meta_header(id, &headers)?;
+ Ok((body, meta))
+ }
+
+ fn base_url(&self) -> &str {
+ &self.base_url
+ }
+
+ fn chunks_url(&self) -> String {
+ format!("{}/v1/chunks", self.base_url())
+ }
+
+ async fn get_helper(
+ &self,
+ path: &str,
+ query: &[(&str, &str)],
+ ) -> Result<(HeaderMap, Vec<u8>), StoreError> {
+ let url = format!("{}{}", &self.chunks_url(), path);
+ info!("GET {}", url);
+
+ // Build HTTP request structure.
+ let req = self
+ .client
+ .get(&url)
+ .query(query)
+ .build()
+ .map_err(StoreError::ReqwestError)?;
+
+ // Make HTTP request.
+ let res = self
+ .client
+ .execute(req)
+ .await
+ .map_err(StoreError::ReqwestError)?;
+
+ // Did it work?
+ if res.status() != 200 {
+ return Err(StoreError::NotFound(path.to_string()));
+ }
+
+ // Return headers and body.
+ let headers = res.headers().clone();
+ let body = res.bytes().await.map_err(StoreError::ReqwestError)?;
+ let body = body.to_vec();
+ Ok((headers, body))
+ }
+
+ fn get_chunk_meta_header(
+ &self,
+ chunk_id: &ChunkId,
+ headers: &HeaderMap,
+ ) -> Result<ChunkMeta, StoreError> {
+ let meta = headers.get("chunk-meta");
+
+ if meta.is_none() {
+ let err = StoreError::NoChunkMeta(chunk_id.clone());
+ error!("fetching chunk {} failed: {}", chunk_id, err);
+ return Err(err);
+ }
+
+ let meta = meta
+ .unwrap()
+ .to_str()
+ .map_err(StoreError::MetaHeaderToString)?;
+ let meta: ChunkMeta = serde_json::from_str(meta).map_err(StoreError::JsonParse)?;
+
+ Ok(meta)
+ }
+}
+
+/// Possible errors from using a ChunkStore.
+#[derive(Debug, thiserror::Error)]
+pub enum StoreError {
+ /// FIXME
+ #[error("FIXME")]
+ FIXME,
+
+ /// Error from a chunk index.
+ #[error(transparent)]
+ Index(#[from] IndexError),
+
+ /// An error from the HTTP library.
+ #[error("error from reqwest library: {0}")]
+ ReqwestError(reqwest::Error),
+
+ /// Client configuration is wrong.
+ #[error(transparent)]
+ ClientConfigError(#[from] ClientConfigError),
+
+ /// Server claims to not have an entity.
+ #[error("Server does not have {0}")]
+ NotFound(String),
+
+ /// Server didn't give us a chunk's metadata.
+ #[error("Server response did not have a 'chunk-meta' header for chunk {0}")]
+ NoChunkMeta(ChunkId),
+
+ /// An error with the `chunk-meta` header.
+ #[error("couldn't convert response chunk-meta header to string: {0}")]
+ MetaHeaderToString(reqwest::header::ToStrError),
+
+ /// Error parsing JSON.
+ #[error("failed to parse JSON: {0}")]
+ JsonParse(serde_json::Error),
+
+ /// An error creating chunk directory.
+ #[error("Failed to create chunk directory {0}")]
+ ChunkMkdir(PathBuf, #[source] std::io::Error),
+
+ /// An error writing a chunk file.
+ #[error("Failed to write chunk {0}")]
+ WriteChunk(PathBuf, #[source] std::io::Error),
+
+ /// An error reading a chunk file.
+ #[error("Failed to read chunk {0}")]
+ ReadChunk(PathBuf, #[source] std::io::Error),
+
+ /// No chunk id for uploaded chunk.
+ #[error("Server response claimed it had created a chunk, but lacked chunk id")]
+ NoCreatedChunkId,
+}
diff --git a/src/cipher.rs b/src/cipher.rs
index 7bd2e84..21785b9 100644
--- a/src/cipher.rs
+++ b/src/cipher.rs
@@ -4,7 +4,7 @@ use crate::chunk::DataChunk;
use crate::chunkmeta::ChunkMeta;
use crate::passwords::Passwords;
-use aes_gcm::aead::{generic_array::GenericArray, Aead, NewAead, Payload};
+use aes_gcm::aead::{generic_array::GenericArray, Aead, KeyInit, Payload};
use aes_gcm::Aes256Gcm; // Or `Aes128Gcm`
use rand::Rng;
diff --git a/src/client.rs b/src/client.rs
index bed5f1e..a924052 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -5,15 +5,14 @@ use crate::chunk::{
};
use crate::chunkid::ChunkId;
use crate::chunkmeta::ChunkMeta;
+use crate::chunkstore::{ChunkStore, StoreError};
use crate::cipher::{CipherEngine, CipherError};
use crate::config::{ClientConfig, ClientConfigError};
use crate::generation::{FinishedGeneration, GenId, LocalGeneration, LocalGenerationError};
use crate::genlist::GenerationList;
use crate::label::Label;
-use log::{debug, error, info};
-use reqwest::header::HeaderMap;
-use std::collections::HashMap;
+use log::{error, info};
use std::fs::File;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
@@ -100,12 +99,15 @@ pub enum ClientError {
/// Failed to write a file.
#[error("failed to write to file {0}: {1}")]
FileWrite(PathBuf, std::io::Error),
+
+ /// Error from a chunk store.
+ #[error(transparent)]
+ ChunkStore(#[from] StoreError),
}
/// Client for the Obnam server HTTP API.
pub struct BackupClient {
- client: reqwest::Client,
- base_url: String,
+ store: ChunkStore,
cipher: CipherEngine,
}
@@ -113,68 +115,25 @@ impl BackupClient {
/// Create a new backup client.
pub fn new(config: &ClientConfig) -> Result<Self, ClientError> {
info!("creating backup client with config: {:#?}", config);
-
let pass = config.passwords()?;
-
- let client = reqwest::Client::builder()
- .danger_accept_invalid_certs(!config.verify_tls_cert)
- .build()
- .map_err(ClientError::ReqwestError)?;
Ok(Self {
- client,
- base_url: config.server_url.to_string(),
+ store: ChunkStore::remote(config)?,
cipher: CipherEngine::new(&pass),
})
}
- fn base_url(&self) -> &str {
- &self.base_url
- }
-
- fn chunks_url(&self) -> String {
- format!("{}/v1/chunks", self.base_url())
- }
-
/// Does the server have a chunk?
pub async fn has_chunk(&self, meta: &ChunkMeta) -> Result<Option<ChunkId>, ClientError> {
- let body = match self.get("", &[("label", meta.label())]).await {
- Ok((_, body)) => body,
- Err(err) => return Err(err),
- };
-
- let hits: HashMap<String, ChunkMeta> =
- serde_json::from_slice(&body).map_err(ClientError::JsonParse)?;
- let mut iter = hits.iter();
- let has = if let Some((chunk_id, _)) = iter.next() {
- Some(chunk_id.into())
- } else {
- None
- };
-
- Ok(has)
+ let mut ids = self.store.find_by_label(meta).await?;
+ Ok(ids.pop())
}
/// Upload a data chunk to the server.
- pub async fn upload_chunk(&self, chunk: DataChunk) -> Result<ChunkId, ClientError> {
+ pub async fn upload_chunk(&mut self, chunk: DataChunk) -> Result<ChunkId, ClientError> {
let enc = self.cipher.encrypt_chunk(&chunk)?;
- let res = self
- .client
- .post(&self.chunks_url())
- .header("chunk-meta", chunk.meta().to_json())
- .body(enc.ciphertext().to_vec())
- .send()
- .await
- .map_err(ClientError::ReqwestError)?;
- debug!("upload_chunk: res={:?}", res);
- let res: HashMap<String, String> = res.json().await.map_err(ClientError::ReqwestError)?;
- let chunk_id = if let Some(chunk_id) = res.get("chunk_id") {
- debug!("upload_chunk: id={}", chunk_id);
- chunk_id.parse().unwrap()
- } else {
- return Err(ClientError::NoCreatedChunkId);
- };
- info!("uploaded_chunk {}", chunk_id);
- Ok(chunk_id)
+ let data = enc.ciphertext().to_vec();
+ let id = self.store.put(data, chunk.meta()).await?;
+ Ok(id)
}
/// Get current client trust chunk from repository, if there is one.
@@ -196,15 +155,9 @@ impl BackupClient {
}
async fn find_client_trusts(&self) -> Result<Vec<ChunkId>, ClientError> {
- let label = Label::literal("client-trust").serialize();
- let body = match self.get("", &[("label", &label)]).await {
- Ok((_, body)) => body,
- Err(err) => return Err(err),
- };
-
- let hits: HashMap<String, ChunkMeta> =
- serde_json::from_slice(&body).map_err(ClientError::JsonParse)?;
- let ids = hits.iter().map(|(id, _)| id.into()).collect();
+ let label = Label::literal("client-trust");
+ let meta = ChunkMeta::new(&label);
+ let ids = self.store.find_by_label(&meta).await?;
Ok(ids)
}
@@ -220,9 +173,7 @@ impl BackupClient {
/// Fetch a data chunk from the server, given the chunk identifier.
pub async fn fetch_chunk(&self, chunk_id: &ChunkId) -> Result<DataChunk, ClientError> {
- let (headers, body) = self.get(&format!("/{}", chunk_id), &[]).await?;
- let meta = self.get_chunk_meta_header(chunk_id, &headers)?;
-
+ let (body, meta) = self.store.get(chunk_id).await?;
let meta_bytes = meta.to_json_vec();
let chunk = self.cipher.decrypt_chunk(&body, &meta_bytes)?;
@@ -244,7 +195,7 @@ impl BackupClient {
let gen = self.fetch_generation_chunk(gen_id).await?;
// Fetch the SQLite file, storing it in the named file.
- let mut dbfile = File::create(&dbname)
+ let mut dbfile = File::create(dbname)
.map_err(|err| ClientError::FileCreate(dbname.to_path_buf(), err))?;
for id in gen.chunk_ids() {
let chunk = self.fetch_chunk(id).await?;
@@ -257,61 +208,4 @@ impl BackupClient {
let gen = LocalGeneration::open(dbname)?;
Ok(gen)
}
-
- async fn get(
- &self,
- path: &str,
- query: &[(&str, &str)],
- ) -> Result<(HeaderMap, Vec<u8>), ClientError> {
- let url = format!("{}{}", &self.chunks_url(), path);
- info!("GET {}", url);
-
- // Build HTTP request structure.
- let req = self
- .client
- .get(&url)
- .query(query)
- .build()
- .map_err(ClientError::ReqwestError)?;
-
- // Make HTTP request.
- let res = self
- .client
- .execute(req)
- .await
- .map_err(ClientError::ReqwestError)?;
-
- // Did it work?
- if res.status() != 200 {
- return Err(ClientError::NotFound(path.to_string()));
- }
-
- // Return headers and body.
- let headers = res.headers().clone();
- let body = res.bytes().await.map_err(ClientError::ReqwestError)?;
- let body = body.to_vec();
- Ok((headers, body))
- }
-
- fn get_chunk_meta_header(
- &self,
- chunk_id: &ChunkId,
- headers: &HeaderMap,
- ) -> Result<ChunkMeta, ClientError> {
- let meta = headers.get("chunk-meta");
-
- if meta.is_none() {
- let err = ClientError::NoChunkMeta(chunk_id.clone());
- error!("fetching chunk {} failed: {}", chunk_id, err);
- return Err(err);
- }
-
- let meta = meta
- .unwrap()
- .to_str()
- .map_err(ClientError::MetaHeaderToString)?;
- let meta: ChunkMeta = serde_json::from_str(meta).map_err(ClientError::JsonParse)?;
-
- Ok(meta)
- }
}
diff --git a/src/cmd/backup.rs b/src/cmd/backup.rs
index 60045cc..70e9eac 100644
--- a/src/cmd/backup.rs
+++ b/src/cmd/backup.rs
@@ -10,21 +10,21 @@ use crate::generation::GenId;
use crate::performance::{Clock, Performance};
use crate::schema::VersionComponent;
+use clap::Parser;
use log::info;
use std::time::SystemTime;
-use structopt::StructOpt;
use tempfile::tempdir;
use tokio::runtime::Runtime;
/// Make a backup.
-#[derive(Debug, StructOpt)]
+#[derive(Debug, Parser)]
pub struct Backup {
/// Force a full backup, instead of an incremental one.
- #[structopt(long)]
+ #[clap(long)]
full: bool,
/// Backup schema major version to use.
- #[structopt(long)]
+ #[clap(long)]
backup_version: Option<VersionComponent>,
}
@@ -42,10 +42,10 @@ impl Backup {
) -> Result<(), ObnamError> {
let runtime = SystemTime::now();
- let major = self.backup_version.or(Some(DEFAULT_SCHEMA_MAJOR)).unwrap();
+ let major = self.backup_version.unwrap_or(DEFAULT_SCHEMA_MAJOR);
let schema = schema_version(major)?;
- let client = BackupClient::new(config)?;
+ let mut client = BackupClient::new(config)?;
let trust = client
.get_client_trust()
.await?
@@ -68,7 +68,7 @@ impl Backup {
let (is_incremental, outcome) = if let Some(old_id) = old_id {
info!("incremental backup based on {}", old_id);
- let mut run = BackupRun::incremental(config, &client)?;
+ let mut run = BackupRun::incremental(config, &mut client)?;
let old = run.start(Some(&old_id), &oldtemp, perf).await?;
(
true,
@@ -77,7 +77,7 @@ impl Backup {
)
} else {
info!("fresh backup without a previous generation");
- let mut run = BackupRun::initial(config, &client)?;
+ let mut run = BackupRun::initial(config, &mut client)?;
let old = run.start(None, &oldtemp, perf).await?;
(
false,
diff --git a/src/cmd/chunk.rs b/src/cmd/chunk.rs
index 445d23f..293de20 100644
--- a/src/cmd/chunk.rs
+++ b/src/cmd/chunk.rs
@@ -5,22 +5,19 @@ use crate::chunkmeta::ChunkMeta;
use crate::cipher::CipherEngine;
use crate::config::ClientConfig;
use crate::error::ObnamError;
+use clap::Parser;
use std::path::PathBuf;
-use structopt::StructOpt;
/// Encrypt a chunk.
-#[derive(Debug, StructOpt)]
+#[derive(Debug, Parser)]
pub struct EncryptChunk {
/// The name of the file containing the cleartext chunk.
- #[structopt(parse(from_os_str))]
filename: PathBuf,
/// Name of file where to write the encrypted chunk.
- #[structopt(parse(from_os_str))]
output: PathBuf,
/// Chunk metadata as JSON.
- #[structopt()]
json: String,
}
@@ -43,18 +40,15 @@ impl EncryptChunk {
}
/// Decrypt a chunk.
-#[derive(Debug, StructOpt)]
+#[derive(Debug, Parser)]
pub struct DecryptChunk {
/// Name of file containing encrypted chunk.
- #[structopt(parse(from_os_str))]
filename: PathBuf,
/// Name of file where to write the cleartext chunk.
- #[structopt(parse(from_os_str))]
output: PathBuf,
/// Chunk metadata as JSON.
- #[structopt()]
json: String,
}
diff --git a/src/cmd/chunkify.rs b/src/cmd/chunkify.rs
index e2ce05f..91cb0be 100644
--- a/src/cmd/chunkify.rs
+++ b/src/cmd/chunkify.rs
@@ -4,10 +4,10 @@ use crate::config::ClientConfig;
use crate::engine::Engine;
use crate::error::ObnamError;
use crate::workqueue::WorkQueue;
+use clap::Parser;
use serde::Serialize;
use sha2::{Digest, Sha256};
use std::path::PathBuf;
-use structopt::StructOpt;
use tokio::fs::File;
use tokio::io::{AsyncReadExt, BufReader};
use tokio::runtime::Runtime;
@@ -18,7 +18,7 @@ use tokio::sync::mpsc;
const Q: usize = 8;
/// Split files into chunks and show their metadata.
-#[derive(Debug, StructOpt)]
+#[derive(Debug, Parser)]
pub struct Chunkify {
/// Names of files to split into chunks.
filenames: Vec<PathBuf>,
diff --git a/src/cmd/gen_info.rs b/src/cmd/gen_info.rs
index 0aec103..901a0ae 100644
--- a/src/cmd/gen_info.rs
+++ b/src/cmd/gen_info.rs
@@ -4,16 +4,15 @@ use crate::chunk::ClientTrust;
use crate::client::BackupClient;
use crate::config::ClientConfig;
use crate::error::ObnamError;
+use clap::Parser;
use log::info;
-use structopt::StructOpt;
use tempfile::NamedTempFile;
use tokio::runtime::Runtime;
/// Show metadata for a generation.
-#[derive(Debug, StructOpt)]
+#[derive(Debug, Parser)]
pub struct GenInfo {
/// Reference of the generation.
- #[structopt()]
gen_ref: String,
}
diff --git a/src/cmd/get_chunk.rs b/src/cmd/get_chunk.rs
index 0b27084..1561492 100644
--- a/src/cmd/get_chunk.rs
+++ b/src/cmd/get_chunk.rs
@@ -4,15 +4,14 @@ use crate::chunkid::ChunkId;
use crate::client::BackupClient;
use crate::config::ClientConfig;
use crate::error::ObnamError;
+use clap::Parser;
use std::io::{stdout, Write};
-use structopt::StructOpt;
use tokio::runtime::Runtime;
/// Fetch a chunk from the server.
-#[derive(Debug, StructOpt)]
+#[derive(Debug, Parser)]
pub struct GetChunk {
/// Identifier of chunk to fetch.
- #[structopt()]
chunk_id: String,
}
diff --git a/src/cmd/init.rs b/src/cmd/init.rs
index 8e555ca..5950fbb 100644
--- a/src/cmd/init.rs
+++ b/src/cmd/init.rs
@@ -3,15 +3,15 @@
use crate::config::ClientConfig;
use crate::error::ObnamError;
use crate::passwords::{passwords_filename, Passwords};
-use structopt::StructOpt;
+use clap::Parser;
const PROMPT: &str = "Obnam passphrase: ";
/// Initialize client by setting passwords.
-#[derive(Debug, StructOpt)]
+#[derive(Debug, Parser)]
pub struct Init {
/// Only for testing.
- #[structopt(long)]
+ #[clap(long)]
insecure_passphrase: Option<String>,
}
@@ -20,7 +20,7 @@ impl Init {
pub fn run(&self, config: &ClientConfig) -> Result<(), ObnamError> {
let passphrase = match &self.insecure_passphrase {
Some(x) => x.to_string(),
- None => rpassword::read_password_from_tty(Some(PROMPT)).unwrap(),
+ None => rpassword::prompt_password(PROMPT).unwrap(),
};
let passwords = Passwords::new(&passphrase);
diff --git a/src/cmd/inspect.rs b/src/cmd/inspect.rs
index 02801ae..3b41075 100644
--- a/src/cmd/inspect.rs
+++ b/src/cmd/inspect.rs
@@ -6,16 +6,15 @@ use crate::client::BackupClient;
use crate::config::ClientConfig;
use crate::error::ObnamError;
+use clap::Parser;
use log::info;
-use structopt::StructOpt;
use tempfile::NamedTempFile;
use tokio::runtime::Runtime;
/// Make a backup.
-#[derive(Debug, StructOpt)]
+#[derive(Debug, Parser)]
pub struct Inspect {
/// Reference to generation to inspect.
- #[structopt()]
gen_id: String,
}
diff --git a/src/cmd/list.rs b/src/cmd/list.rs
index bbb9c91..8bc6978 100644
--- a/src/cmd/list.rs
+++ b/src/cmd/list.rs
@@ -4,11 +4,11 @@ use crate::chunk::ClientTrust;
use crate::client::BackupClient;
use crate::config::ClientConfig;
use crate::error::ObnamError;
-use structopt::StructOpt;
+use clap::Parser;
use tokio::runtime::Runtime;
/// List generations on the server.
-#[derive(Debug, StructOpt)]
+#[derive(Debug, Parser)]
pub struct List {}
impl List {
diff --git a/src/cmd/list_backup_versions.rs b/src/cmd/list_backup_versions.rs
index 859d91c..c78ccfc 100644
--- a/src/cmd/list_backup_versions.rs
+++ b/src/cmd/list_backup_versions.rs
@@ -4,13 +4,13 @@ use crate::config::ClientConfig;
use crate::dbgen::{schema_version, DEFAULT_SCHEMA_MAJOR, SCHEMA_MAJORS};
use crate::error::ObnamError;
-use structopt::StructOpt;
+use clap::Parser;
/// List supported backup schema versions.
-#[derive(Debug, StructOpt)]
+#[derive(Debug, Parser)]
pub struct ListSchemaVersions {
/// List only the default version.
- #[structopt(long)]
+ #[clap(long)]
default_only: bool,
}
diff --git a/src/cmd/list_files.rs b/src/cmd/list_files.rs
index fb4764d..e8276cd 100644
--- a/src/cmd/list_files.rs
+++ b/src/cmd/list_files.rs
@@ -6,15 +6,15 @@ use crate::client::BackupClient;
use crate::config::ClientConfig;
use crate::error::ObnamError;
use crate::fsentry::{FilesystemEntry, FilesystemKind};
-use structopt::StructOpt;
+use clap::Parser;
use tempfile::NamedTempFile;
use tokio::runtime::Runtime;
/// List files in a backup.
-#[derive(Debug, StructOpt)]
+#[derive(Debug, Parser)]
pub struct ListFiles {
/// Reference to backup to list files in.
- #[structopt(default_value = "latest")]
+ #[clap(default_value = "latest")]
gen_id: String,
}
diff --git a/src/cmd/resolve.rs b/src/cmd/resolve.rs
index 12432cc..a7774d7 100644
--- a/src/cmd/resolve.rs
+++ b/src/cmd/resolve.rs
@@ -4,11 +4,11 @@ use crate::chunk::ClientTrust;
use crate::client::BackupClient;
use crate::config::ClientConfig;
use crate::error::ObnamError;
-use structopt::StructOpt;
+use clap::Parser;
use tokio::runtime::Runtime;
/// Resolve a generation reference into a generation id.
-#[derive(Debug, StructOpt)]
+#[derive(Debug, Parser)]
pub struct Resolve {
/// The generation reference.
generation: String,
diff --git a/src/cmd/restore.rs b/src/cmd/restore.rs
index 223d481..58caf61 100644
--- a/src/cmd/restore.rs
+++ b/src/cmd/restore.rs
@@ -9,6 +9,7 @@ use crate::dbgen::FileId;
use crate::error::ObnamError;
use crate::fsentry::{FilesystemEntry, FilesystemKind};
use crate::generation::{LocalGeneration, LocalGenerationError};
+use clap::Parser;
use indicatif::{ProgressBar, ProgressStyle};
use libc::{chmod, mkfifo, timespec, utimensat, AT_FDCWD, AT_SYMLINK_NOFOLLOW};
use log::{debug, error, info};
@@ -20,19 +21,16 @@ use std::os::unix::fs::symlink;
use std::os::unix::net::UnixListener;
use std::path::StripPrefixError;
use std::path::{Path, PathBuf};
-use structopt::StructOpt;
use tempfile::NamedTempFile;
use tokio::runtime::Runtime;
/// Restore a backup.
-#[derive(Debug, StructOpt)]
+#[derive(Debug, Parser)]
pub struct Restore {
/// Reference to generation to restore.
- #[structopt()]
gen_id: String,
/// Path to directory where restored files are written.
- #[structopt(parse(from_os_str))]
to: PathBuf,
}
@@ -301,13 +299,17 @@ fn create_progress_bar(file_count: FileId, verbose: bool) -> ProgressBar {
} else {
ProgressBar::hidden()
};
- let parts = vec![
+ let parts = [
"{wide_bar}",
"elapsed: {elapsed}",
"files: {pos}/{len}",
"current: {wide_msg}",
"{spinner}",
];
- progress.set_style(ProgressStyle::default_bar().template(&parts.join("\n")));
+ progress.set_style(
+ ProgressStyle::default_bar()
+ .template(&parts.join("\n"))
+ .expect("create indicatif ProgressStyle value"),
+ );
progress
}
diff --git a/src/cmd/show_config.rs b/src/cmd/show_config.rs
index 7ac52ec..8e0ce30 100644
--- a/src/cmd/show_config.rs
+++ b/src/cmd/show_config.rs
@@ -2,10 +2,10 @@
use crate::config::ClientConfig;
use crate::error::ObnamError;
-use structopt::StructOpt;
+use clap::Parser;
/// Show actual client configuration.
-#[derive(Debug, StructOpt)]
+#[derive(Debug, Parser)]
pub struct ShowConfig {}
impl ShowConfig {
diff --git a/src/cmd/show_gen.rs b/src/cmd/show_gen.rs
index f47a07b..95d3fd3 100644
--- a/src/cmd/show_gen.rs
+++ b/src/cmd/show_gen.rs
@@ -7,17 +7,17 @@ use crate::db::DbInt;
use crate::error::ObnamError;
use crate::fsentry::FilesystemKind;
use crate::generation::GenId;
+use clap::Parser;
use indicatif::HumanBytes;
use serde::Serialize;
-use structopt::StructOpt;
use tempfile::NamedTempFile;
use tokio::runtime::Runtime;
/// Show information about a generation.
-#[derive(Debug, StructOpt)]
+#[derive(Debug, Parser)]
pub struct ShowGeneration {
/// Reference to the generation. Defaults to latest.
- #[structopt(default_value = "latest")]
+ #[clap(default_value = "latest")]
gen_id: String,
}
diff --git a/src/config.rs b/src/config.rs
index a9be716..5774aad 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -62,11 +62,11 @@ impl ClientConfig {
let exclude_cache_tag_directories = tentative.exclude_cache_tag_directories.unwrap_or(true);
let config = Self {
- chunk_size: tentative.chunk_size.or(Some(DEFAULT_CHUNK_SIZE)).unwrap(),
+ chunk_size: tentative.chunk_size.unwrap_or(DEFAULT_CHUNK_SIZE),
filename: filename.to_path_buf(),
roots,
server_url: tentative.server_url,
- verify_tls_cert: tentative.verify_tls_cert.or(Some(false)).unwrap(),
+ verify_tls_cert: tentative.verify_tls_cert.unwrap_or(false),
log,
exclude_cache_tag_directories,
};
diff --git a/src/db.rs b/src/db.rs
index da24e96..392134d 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -428,10 +428,7 @@ impl<'a> ToSql for Value<'a> {
i64::try_from(*v)
.map_err(|err| rusqlite::Error::ToSqlConversionFailure(Box::new(err)))?,
),
- Self::Bool(_, v) => ValueRef::Integer(
- i64::try_from(*v)
- .map_err(|err| rusqlite::Error::ToSqlConversionFailure(Box::new(err)))?,
- ),
+ Self::Bool(_, v) => ValueRef::Integer(i64::from(*v)),
Self::Text(_, v) => ValueRef::Text(v.as_ref()),
Self::Blob(_, v) => ValueRef::Blob(v),
};
@@ -478,10 +475,7 @@ impl ToSql for OwnedValue {
i64::try_from(*v)
.map_err(|err| rusqlite::Error::ToSqlConversionFailure(Box::new(err)))?,
),
- Self::Bool(_, v) => Value::Integer(
- i64::try_from(*v)
- .map_err(|err| rusqlite::Error::ToSqlConversionFailure(Box::new(err)))?,
- ),
+ Self::Bool(_, v) => Value::Integer(i64::from(*v)),
Self::Text(_, v) => Value::Text(v.to_string()),
Self::Blob(_, v) => Value::Blob(v.to_vec()),
};
diff --git a/src/engine.rs b/src/engine.rs
index 384f591..d35281b 100644
--- a/src/engine.rs
+++ b/src/engine.rs
@@ -76,7 +76,7 @@ async fn manage_workers<S, T, F>(
// We got a work item. Launch background task to
// work on it.
let tx = tx.clone();
- workers.push(do_work(work, tx, func));
+ workers.push_back(do_work(work, tx, func));
// If queue is full, wait for at least one
// background task to finish.
diff --git a/src/fsentry.rs b/src/fsentry.rs
index 276e3f9..f31d6b5 100644
--- a/src/fsentry.rs
+++ b/src/fsentry.rs
@@ -268,7 +268,7 @@ impl EntryBuilder {
}
/// Different types of file system entries.
-#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub enum FilesystemKind {
/// Regular file, including a hard link to one.
Regular,
diff --git a/src/index.rs b/src/index.rs
index 52da2f2..42f1a95 100644
--- a/src/index.rs
+++ b/src/index.rs
@@ -139,7 +139,7 @@ mod sql {
params![],
)?;
conn.execute("CREATE INDEX label_idx ON chunks (label)", params![])?;
- conn.pragma_update(None, "journal_mode", &"WAL")?;
+ conn.pragma_update(None, "journal_mode", "WAL")?;
Ok(conn)
}
@@ -147,7 +147,7 @@ mod sql {
pub fn open_db(filename: &Path) -> Result<Connection, IndexError> {
let flags = OpenFlags::SQLITE_OPEN_READ_WRITE;
let conn = Connection::open_with_flags(filename, flags)?;
- conn.pragma_update(None, "journal_mode", &"WAL")?;
+ conn.pragma_update(None, "journal_mode", "WAL")?;
Ok(conn)
}
diff --git a/src/indexedstore.rs b/src/indexedstore.rs
deleted file mode 100644
index 15b5a22..0000000
--- a/src/indexedstore.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-//! An indexed, on-disk store for chunks on the server.
-
-use crate::chunk::{DataChunk, GenerationChunkError};
-use crate::chunkid::ChunkId;
-use crate::chunkmeta::ChunkMeta;
-use crate::index::{Index, IndexError};
-use crate::store::{Store, StoreError};
-use std::path::Path;
-
-/// A store for chunks and their metadata.
-///
-/// This combines Store and Index into one interface to make it easier
-/// to handle the server side storage of chunks.
-pub struct IndexedStore {
- store: Store,
- index: Index,
-}
-
-/// All the errors that may be returned for `IndexStore`.
-#[derive(Debug, thiserror::Error)]
-pub enum IndexedError {
- /// An error from Index.
- #[error(transparent)]
- IndexError(#[from] IndexError),
-
- /// Error regarding generation chunks.
- #[error(transparent)]
- GenerationChunkError(#[from] GenerationChunkError),
-
- /// An error from Store.
- #[error(transparent)]
- SqlError(#[from] StoreError),
-}
-
-impl IndexedStore {
- /// Create a new indexed store.
- pub fn new(dirname: &Path) -> Result<Self, IndexedError> {
- let store = Store::new(dirname);
- let index = Index::new(dirname)?;
- Ok(Self { store, index })
- }
-
- /// Save a chunk in the store.
- pub fn save(&mut self, chunk: &DataChunk) -> Result<ChunkId, IndexedError> {
- let id = ChunkId::new();
- self.store.save(&id, chunk)?;
- self.insert_meta(&id, chunk.meta())?;
- Ok(id)
- }
-
- fn insert_meta(&mut self, id: &ChunkId, meta: &ChunkMeta) -> Result<(), IndexedError> {
- self.index.insert_meta(id.clone(), meta.clone())?;
- Ok(())
- }
-
- /// Get a chunk from the store, given its id.
- pub fn load(&self, id: &ChunkId) -> Result<(DataChunk, ChunkMeta), IndexedError> {
- Ok((self.store.load(id)?, self.load_meta(id)?))
- }
-
- /// Get a chunk's metadata form the store, given its id.
- pub fn load_meta(&self, id: &ChunkId) -> Result<ChunkMeta, IndexedError> {
- Ok(self.index.get_meta(id)?)
- }
-
- /// Find chunks with a client-assigned label.
- pub fn find_by_label(&self, label: &str) -> Result<Vec<ChunkId>, IndexedError> {
- Ok(self.index.find_by_label(label)?)
- }
-
- /// Remove a chunk from the store.
- pub fn remove(&mut self, id: &ChunkId) -> Result<(), IndexedError> {
- self.index.remove_meta(id)?;
- self.store.delete(id)?;
- Ok(())
- }
-}
diff --git a/src/lib.rs b/src/lib.rs
index fbbea15..8894966 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -13,6 +13,7 @@ pub mod chunk;
pub mod chunker;
pub mod chunkid;
pub mod chunkmeta;
+pub mod chunkstore;
pub mod cipher;
pub mod client;
pub mod cmd;
@@ -27,7 +28,6 @@ pub mod generation;
pub mod genlist;
pub mod genmeta;
pub mod index;
-pub mod indexedstore;
pub mod label;
pub mod passwords;
pub mod performance;
diff --git a/src/passwords.rs b/src/passwords.rs
index ea476bf..efc3f96 100644
--- a/src/passwords.rs
+++ b/src/passwords.rs
@@ -76,7 +76,7 @@ fn derive_password(passphrase: &str) -> String {
let salt = SaltString::generate(&mut OsRng);
Pbkdf2
- .hash_password(passphrase.as_bytes(), salt.as_ref())
+ .hash_password(passphrase.as_bytes(), salt.as_salt())
.unwrap()
.to_string()
}
diff --git a/src/policy.rs b/src/policy.rs
index bb98a48..8cdbd76 100644
--- a/src/policy.rs
+++ b/src/policy.rs
@@ -20,19 +20,21 @@ pub struct BackupPolicy {
old_if_changed: bool,
}
-impl BackupPolicy {
+impl Default for BackupPolicy {
/// Create a default policy.
- pub fn default() -> Self {
+ fn default() -> Self {
Self {
new: true,
old_if_changed: true,
}
}
+}
+impl BackupPolicy {
/// Does a given file need to be backed up?
pub fn needs_backup(&self, old: &LocalGeneration, new_entry: &FilesystemEntry) -> Reason {
let new_name = new_entry.pathbuf();
- let reason = match old.get_file(&new_name) {
+ match old.get_file(&new_name) {
Ok(None) => {
if self.new {
Reason::IsNew
@@ -58,8 +60,7 @@ impl BackupPolicy {
);
Reason::GenerationLookupError
}
- };
- reason
+ }
}
}
diff --git a/src/server.rs b/src/server.rs
index 6b688d6..ffd4009 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -115,7 +115,7 @@ impl Fetched {
}
/// Result of a search.
-#[derive(Debug, Default, PartialEq, Deserialize, Serialize)]
+#[derive(Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct SearchHits {
map: HashMap<String, ChunkMeta>,
}
diff --git a/src/store.rs b/src/store.rs
index 4e85ba1..185370e 100644
--- a/src/store.rs
+++ b/src/store.rs
@@ -48,18 +48,18 @@ impl Store {
std::fs::create_dir_all(dir)?;
}
- std::fs::write(&metaname, chunk.meta().to_json())?;
- std::fs::write(&dataname, chunk.data())?;
+ std::fs::write(metaname, chunk.meta().to_json())?;
+ std::fs::write(dataname, chunk.data())?;
Ok(())
}
/// Load a chunk from a store.
pub fn load(&self, id: &ChunkId) -> Result<DataChunk, StoreError> {
let (_, metaname, dataname) = &self.filenames(id);
- let meta = std::fs::read(&metaname)?;
+ let meta = std::fs::read(metaname)?;
let meta = serde_json::from_slice(&meta)?;
- let data = std::fs::read(&dataname)?;
+ let data = std::fs::read(dataname)?;
let data = DataChunk::new(data, meta);
Ok(data)
}
@@ -67,8 +67,8 @@ impl Store {
/// Delete a chunk from a store.
pub fn delete(&self, id: &ChunkId) -> Result<(), StoreError> {
let (_, metaname, dataname) = &self.filenames(id);
- std::fs::remove_file(&metaname)?;
- std::fs::remove_file(&dataname)?;
+ std::fs::remove_file(metaname)?;
+ std::fs::remove_file(dataname)?;
Ok(())
}
}
diff --git a/subplot/server.py b/subplot/server.py
index 1f4506f..a604733 100644
--- a/subplot/server.py
+++ b/subplot/server.py
@@ -87,7 +87,9 @@ def delete_chunk_by_id(ctx, chunk_id=None):
def make_chunk_file_be_empty(ctx, chunk_id=None):
chunk_id = ctx["vars"][chunk_id]
chunks = ctx["config"]["chunks"]
- for (dirname, _, _) in os.walk(chunks):
+ logging.debug(f"trying to empty chunk {chunk_id}")
+ for (dirname, _, filenames) in os.walk(chunks):
+ logging.debug(f"found directory {dirname}, with {filenames}")
filename = os.path.join(dirname, chunk_id + ".data")
if os.path.exists(filename):
logging.debug(f"emptying chunk file {filename}")
@@ -136,7 +138,7 @@ def server_has_n_chunks(ctx, n=None):
assert_eq = globals()["assert_eq"]
n = int(n)
files = find_files(ctx["config"]["chunks"])
- files = [json.load(open(x)) for x in files if x.endswith(".meta")]
+ files = [x for x in files if x.endswith(".data")]
logging.debug(f"server_has_n_file_chunks: n={n}")
logging.debug(f"server_has_n_file_chunks: len(files)={len(files)}")
logging.debug(f"server_has_n_file_chunks: files={files}")
diff --git a/subplot/server.yaml b/subplot/server.yaml
index ac45cac..cf57931 100644
--- a/subplot/server.yaml
+++ b/subplot/server.yaml
@@ -17,6 +17,11 @@
- when: "I POST (?P<filename>\\S+) to (?P<path>\\S+), with (?P<header>\\S+): (?P<json>.*)"
regex: true
+ types:
+ filename: word
+ path: word
+ header: word
+ json: text
impl:
python:
function: post_file
@@ -63,12 +68,17 @@
function: header_is
- then: "the JSON body has a field {field}, henceforth {var}"
+ types:
+ field: word
+ var: word
impl:
python:
function: remember_json_field
- then: "the JSON body matches (?P<wanted>.*)"
regex: true
+ types:
+ wanted: text
impl:
python:
function: json_body_matches