diff --git a/Cargo.lock b/Cargo.lock index bcfc2bd..9991b33 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,7 +27,7 @@ name = "atty" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -53,7 +53,7 @@ dependencies = [ [[package]] name = "byteorder" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -63,16 +63,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "chrono" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "clap" -version = "2.31.1" +version = "2.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -100,7 +101,7 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -123,7 +124,7 @@ name = "fuse" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "thread-scoped 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -156,7 +157,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.39" +version = "0.2.40" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -164,7 +165,7 @@ name = "libsodium-sys" version = "0.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -180,7 +181,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -205,7 +206,7 @@ name = "memchr" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -214,7 +215,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -227,31 +228,12 @@ name = "nodrop" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "num" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "num-integer" version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-iter" -version = "0.1.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -259,12 +241,12 @@ name = "num-traits" version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -273,7 +255,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -294,7 +276,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -313,28 +295,30 @@ dependencies = [ [[package]] name = "regex" -version = "0.2.6" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.4.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "remove_dir_all" -version = "0.3.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -342,7 +326,7 @@ name = "rmp" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -351,9 +335,9 @@ name = "rmp-serde" version = "0.13.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rmp 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -363,15 +347,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.27" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_bytes" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -379,8 +363,8 @@ name = "serde_utils" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_bytes 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -390,7 +374,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -399,9 +383,9 @@ name = "sodiumoxide" version = "0.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "libsodium-sys 0.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -410,7 +394,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -425,18 +409,18 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tempdir" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -444,7 +428,7 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -476,11 +460,16 @@ name = "time" version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ucd-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-width" version = "0.1.4" @@ -496,10 +485,10 @@ dependencies = [ [[package]] name = "users" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -551,7 +540,7 @@ name = "xattr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -559,7 +548,7 @@ name = "xattr" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -576,14 +565,14 @@ version = "0.5.0" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.31.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "fuse 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "libsodium-sys 0.0.16 (registry+https://github.com/rust-lang/crates.io-index)", "locale_config 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -592,18 +581,18 @@ dependencies = [ "pbr 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "rmp-serde 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)", "runtime-fmt 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_bytes 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde_utils 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "sodiumoxide 0.0.16 (registry+https://github.com/rust-lang/crates.io-index)", "squash-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "users 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "users 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "xattr 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -615,10 +604,10 @@ dependencies = [ "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" -"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23" +"checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" -"checksum chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c20ebe0b2b08b0aeddba49c609fe7957ba2e33449882cb186a180bc60682fa9" -"checksum clap 2.31.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dc18f6f4005132120d9711636b32c46a233fad94df6217fa1d81c5e97a9f200" +"checksum chrono 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ba5f60682a4c264e7f8d77b82e7788938a76befdf949d4a98026d19099c9d873" +"checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" "checksum filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "714653f3e34871534de23771ac7b26e999651a0a228f47beb324dfdf1dd4b10f" @@ -629,7 +618,7 @@ dependencies = [ "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" "checksum libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122" -"checksum libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)" = "f54263ad99207254cf58b5f701ecb432c717445ea2ee8af387334bdd1a03fdff" +"checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" "checksum libsodium-sys 0.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fcbd1beeed8d44caa8a669ebaa697c313976e242c03cc9fb23d88bf1656f5542" "checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e" "checksum locale_config 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "14fbee0e39bc2dd6a2427c4fdea66e9826cc1fd09b0a0b7550359f5f6efe1dab" @@ -639,40 +628,39 @@ dependencies = [ "checksum mmap 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc85448a6006dd2ba26a385a564a8a0f1f2c7e78c70f1a70b2e0f4af286b823" "checksum murmurhash3 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a2983372caf4480544083767bf2d27defafe32af49ab4df3a0b7fc90793a3664" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" -"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" "checksum num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f8d26da319fb45674985c78f1d1caf99aa4941f785d384a2ae36d0740bc3e2fe" -"checksum num-iter 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "4b226df12c5a59b63569dd57fafb926d91b385dfce33d8074a412411b689d593" "checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" -"checksum num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3c2bd9b9d21e48e956b763c9f37134dc62d9e95da6edb3f672cacb6caf3cd3" +"checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364" "checksum pbr 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e048e3afebb6c454bb1c5d0fe73fda54698b4715d78ed8e7302447c37736d23a" "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5be5347bde0c48cfd8c3fdc0766cdfe9d8a755ef84d620d6794c778c91de8b2b" -"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e" -"checksum remove_dir_all 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5d2f806b0fcdabd98acd380dc8daef485e22bcb7cddc811d1337967f2528cf5" +"checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb" +"checksum regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b2550876c31dc914696a6c2e01cbce8afba79a93c8ae979d2fe051c0230b3756" +"checksum remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfc5b3ce5d5ea144bb04ebd093a9e14e9765bcfec866aecda9b6dec43b3d1e24" "checksum rmp 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a3d45d7afc9b132b34a2479648863aa95c5c88e98b32285326a6ebadc80ec5c9" "checksum rmp-serde 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)" = "011e1d58446e9fa3af7cdc1fb91295b10621d3ac4cb3a85cc86385ee9ca50cd3" "checksum runtime-fmt 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "647a821d66049faccc993fc3c379d1181b81a484097495cda79ffdb17b55b87f" -"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526" -"checksum serde_bytes 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "52b678af90a3aebc4484c22d639bf374eb7d598988edb33fa73c4febd6046a59" +"checksum serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "d3bcee660dcde8f52c3765dd9ca5ee36b4bf35470a738eb0bd5a8752b0389645" +"checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3" "checksum serde_utils 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f6e0edb364c93646633800df969086bc7c5c25fb3f1eb57349990d1cb4cae4bc" "checksum serde_yaml 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e0f868d400d9d13d00988da49f7f02aeac6ef00f11901a8c535bd59d777b9e19" "checksum sodiumoxide 0.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "eb5cb2f14f9a51352ad65e59257a0a9459d5a36a3615f3d53a974c82fdaaa00a" "checksum squash-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db1f9dde91d819b7746e153bc32489fa19e6a106c3d7f2b92187a4efbdc88b40" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "1605d3388ceb50252952ffebab4b5dc43017ead7e4481b175961c283bb951195" -"checksum tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f73eebdb68c14bcb24aef74ea96079830e7fa7b31a6106e42ea7ee887c1e134e" +"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" "checksum thread-scoped 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bcbb6aa301e5d3b0b5ef639c9a9c7e2f1c944f177b460c04dc24c69b1fa2bd99" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" "checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098" +"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum users 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "99ab1b53affc9f75f57da4a8b051a188e84d20d43bea0dd9bd8db71eebbca6da" +"checksum users 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a098d836637f965bbe0df8f744088318c43b685ffd46b676ed21036b7c94bae6" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" diff --git a/src/backups/mod.rs b/src/backups/mod.rs index 650544f..a203969 100644 --- a/src/backups/mod.rs +++ b/src/backups/mod.rs @@ -28,7 +28,7 @@ const DEFAULT_EXCLUDES: &[u8] = include_bytes!("../../docs/excludes.default"); pub struct BackupRepository { layout: Arc, crypto: Arc, - repo: Repository + repo: RepositoryInner } impl BackupRepository { @@ -44,7 +44,7 @@ impl BackupRepository { Ok(BackupRepository { crypto: crypto.clone(), layout: layout.clone(), - repo: try!(Repository::create(layout, config, crypto, remote)) + repo: try!(RepositoryInner::create(layout, config, crypto, remote)) }) } @@ -55,7 +55,7 @@ impl BackupRepository { Ok(BackupRepository { crypto: crypto.clone(), layout: layout.clone(), - repo: try!(Repository::open(layout, crypto, online)) + repo: try!(RepositoryInner::open(layout, crypto, online)) }) } diff --git a/src/prelude.rs b/src/prelude.rs index 142ee20..c68742e 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -2,10 +2,10 @@ pub use util::*; pub use repository::bundledb::{BundleReader, BundleMode, BundleWriter, BundleInfo, BundleId, BundleDbError, BundleDb, BundleWriterError, StoredBundle, BundleStatistics}; pub use repository::chunking::{ChunkerType, Chunker, ChunkerStatus, ChunkerError}; -pub use repository::{Repository, Config, RepositoryError, RepositoryInfo, - IntegrityError, BundleAnalysis, - RepositoryLayout, Location, +pub use repository::{RepositoryInner, Config, RepositoryError, RepositoryInfo, + IntegrityError, BundleAnalysis, RepositoryLayout, Location, RepositoryStatistics, ChunkRepositoryLayout}; +pub use repository::*; pub use repository::index::{Index, IndexError, IndexStatistics}; pub use backups::mount::FuseFilesystem; pub use backups::{BackupFile, BackupFileError, Inode, FileType, FileData, InodeError, BackupError, diff --git a/src/repository/bundledb/writer.rs b/src/repository/bundledb/writer.rs index 34b3958..a42da37 100644 --- a/src/repository/bundledb/writer.rs +++ b/src/repository/bundledb/writer.rs @@ -114,6 +114,7 @@ impl BundleWriter { let encoded_size = self.data.len(); let mut chunk_data = Vec::with_capacity(self.chunks.encoded_size()); self.chunks.write_to(&mut chunk_data).unwrap(); + //TODO: use random value as bundle id and store hash value in another field let id = BundleId(self.hash_method.hash(&chunk_data)); if let Some(ref encryption) = self.encryption { chunk_data = try!(self.crypto.encrypt(encryption, &chunk_data)); diff --git a/src/repository/inner/api.rs b/src/repository/inner/api.rs new file mode 100644 index 0000000..0e5db38 --- /dev/null +++ b/src/repository/inner/api.rs @@ -0,0 +1,178 @@ +use ::prelude::*; + +pub struct Repository(RepositoryInner); +pub struct LocalWriteMode<'a>(&'a mut RepositoryInner); +pub struct RestoreMode<'a>(&'a mut RepositoryInner); +pub struct BackupMode<'a>(&'a mut RepositoryInner); +pub struct VacuumMode<'a>(&'a mut RepositoryInner); + +macro_rules! in_readonly_mode { + ( $($f:tt)* ) => { + impl Repository { + $( $f )* + } + impl<'a> LocalWriteMode<'a> { + $( $f )* + } + impl<'a> RestoreMode<'a> { + $( $f )* + } + impl<'a> BackupMode<'a> { + $( $f )* + } + impl<'a> VacuumMode<'a> { + $( $f )* + } + }; +} + +macro_rules! in_local_write_mode { + ( $($f:tt)* ) => { + impl<'a> LocalWriteMode<'a> { + $( $f )* + } + impl<'a> RestoreMode<'a> { + $( $f )* + } + impl<'a> BackupMode<'a> { + $( $f )* + } + impl<'a> VacuumMode<'a> { + $( $f )* + } + }; +} + +macro_rules! in_restore_mode { + ( $($f:tt)* ) => { + impl<'a> RestoreMode<'a> { + $( $f )* + } + impl<'a> BackupMode<'a> { + $( $f )* + } + impl<'a> VacuumMode<'a> { + $( $f )* + } + }; +} + +macro_rules! in_backup_mode { + ( $($f:tt)* ) => { + impl<'a> BackupMode<'a> { + $( $f )* + } + impl<'a> VacuumMode<'a> { + $( $f )* + } + }; +} + +macro_rules! in_vacuum_mode { + ( $($f:tt)* ) => { + impl<'a> VacuumMode<'a> { + $( $f )* + } + }; +} + + +impl RepositoryInner { + fn local_write_mode Result>(&mut self, f: F) -> Result { + let ret = f(LocalWriteMode(self)); + ret + } + + fn restore_mode Result>(&mut self, f: F) -> Result { + let ret = f(RestoreMode(self)); + ret + } + + fn backup_mode Result>(&mut self, f: F) -> Result { + let ret = f(BackupMode(self)); + ret + } + + fn vacuum_mode Result>(&mut self, f: F) -> Result { + let ret = f(VacuumMode(self)); + ret + } +} + + +impl Repository { + pub fn local_write_mode Result>(&mut self, f: F) -> Result { + self.0.local_write_mode(f) + } + + pub fn restore_mode Result>(&mut self, f: F) -> Result { + self.0.restore_mode(f) + } + + pub fn backup_mode Result>(&mut self, f: F) -> Result { + self.0.backup_mode(f) + } + + pub fn vacuum_mode Result>(&mut self, f: F) -> Result { + self.0.vacuum_mode(f) + } +} + +impl<'a> LocalWriteMode<'a> { + pub fn restore_mode Result>(&mut self, f: F) -> Result { + self.0.restore_mode(f) + } + + pub fn backup_mode Result>(&mut self, f: F) -> Result { + self.0.backup_mode(f) + } + + pub fn vacuum_mode Result>(&mut self, f: F) -> Result { + self.0.vacuum_mode(f) + } +} + +impl<'a> RestoreMode<'a> { + pub fn backup_mode Result>(&mut self, f: F) -> Result { + self.0.backup_mode(f) + } + + pub fn vacuum_mode Result>(&mut self, f: F) -> Result { + self.0.vacuum_mode(f) + } +} + +impl<'a> BackupMode<'a> { + pub fn vacuum_mode Result>(&mut self, f: F) -> Result { + self.0.vacuum_mode(f) + } +} + + +impl Repository { + fn test(&mut self) { + self.local_write_mode(|s| { + s.dummy("aaa"); + Ok(()) + }); + } +} + +in_readonly_mode! { + pub fn get_config(&self) -> &Config { + self.0.get_config() + } + + pub fn set_config(&mut self, config: Config) { + self.0.set_config(config); + } +} + + +in_local_write_mode! { + fn dummy(&self, r: R) { + + } +} + + diff --git a/src/repository/basic_io.rs b/src/repository/inner/basic_io.rs similarity index 98% rename from src/repository/basic_io.rs rename to src/repository/inner/basic_io.rs index b5d4478..ba88874 100644 --- a/src/repository/basic_io.rs +++ b/src/repository/inner/basic_io.rs @@ -10,11 +10,11 @@ pub struct ChunkReader<'a> { chunks: VecDeque, data: Vec, pos: usize, - repo: &'a mut Repository + repo: &'a mut RepositoryInner } impl<'a> ChunkReader<'a> { - pub fn new(repo: &'a mut Repository, chunks: ChunkList) -> Self { + pub fn new(repo: &'a mut RepositoryInner, chunks: ChunkList) -> Self { ChunkReader { repo, chunks: chunks.into_inner().into(), @@ -58,7 +58,7 @@ impl<'a> Read for ChunkReader<'a> { } -impl Repository { +impl RepositoryInner { #[inline] pub fn get_bundle_id(&self, id: u32) -> Result { self.bundle_map.get(id).ok_or_else(|| { diff --git a/src/repository/info.rs b/src/repository/inner/info.rs similarity index 99% rename from src/repository/info.rs rename to src/repository/inner/info.rs index c247b23..8e12357 100644 --- a/src/repository/info.rs +++ b/src/repository/inner/info.rs @@ -46,7 +46,7 @@ pub struct RepositoryStatistics { } -impl Repository { +impl RepositoryInner { #[inline] pub fn list_bundles(&self) -> Vec<&BundleInfo> { self.bundles.list_bundles() diff --git a/src/repository/integrity.rs b/src/repository/inner/integrity.rs similarity index 99% rename from src/repository/integrity.rs rename to src/repository/inner/integrity.rs index 3632914..91f477c 100644 --- a/src/repository/integrity.rs +++ b/src/repository/inner/integrity.rs @@ -1,9 +1,9 @@ use prelude::*; use super::*; +use super::super::bundle_map::BundleMap; use std::time::Duration; - use pbr::ProgressBar; @@ -36,7 +36,7 @@ quick_error!{ } -impl Repository { +impl RepositoryInner { pub fn get_chunk_marker(&self) -> Bitmap { Bitmap::new(self.index.capacity()) } diff --git a/src/repository/inner/mod.rs b/src/repository/inner/mod.rs new file mode 100644 index 0000000..22aeb6a --- /dev/null +++ b/src/repository/inner/mod.rs @@ -0,0 +1,364 @@ +mod integrity; +mod basic_io; +mod info; +mod vacuum; +pub mod api; + + +use prelude::*; + +use std::mem; +use std::cmp::max; +use std::path::Path; +use std::fs::{self, File}; +use std::sync::Arc; +use std::os::unix::fs::symlink; +use std::io::Write; + +use super::{INDEX_MAGIC, INDEX_VERSION, REPOSITORY_README}; +use super::bundle_map::BundleMap; +use super::index; +pub use self::integrity::IntegrityError; +pub use self::info::{BundleAnalysis, RepositoryInfo, RepositoryStatistics}; + + +#[derive(Clone, Copy, PartialEq, Debug, Default)] +pub struct Location { + pub bundle: u32, + pub chunk: u32 +} +impl Location { + pub fn new(bundle: u32, chunk: u32) -> Self { + Location { + bundle, + chunk + } + } +} + +impl index::Value for Location {} + +impl index::Key for Hash { + fn hash(&self) -> u64 { + self.low + } + + fn is_used(&self) -> bool { + self.low != 0 || self.high != 0 + } + + fn clear(&mut self) { + self.low = 0; + self.high = 0; + } +} + + +pub struct RepositoryInner { + layout: Arc, + config: Config, + index: Index, + crypto: Arc, + bundle_map: BundleMap, + next_data_bundle: u32, + next_meta_bundle: u32, + bundles: BundleDb, + data_bundle: Option, + meta_bundle: Option, + chunker: Box, + remote_locks: LockFolder, + local_locks: LockFolder, + lock: LockHandle, + dirty: bool +} + + +impl RepositoryInner { + pub fn create>( + layout: Arc, + config: &Config, + crypto: Arc, + remote: R, + ) -> Result { + try!(fs::create_dir(layout.local_locks_path())); + try!(symlink(remote, layout.remote_path())); + try!(File::create(layout.remote_readme_path()).and_then( + |mut f| { + f.write_all(REPOSITORY_README) + } + )); + try!(fs::create_dir_all(layout.remote_locks_path())); + try!(config.save(layout.config_path())); + try!(BundleDb::create(layout.clone())); + try!(Index::::create( + layout.index_path(), + &INDEX_MAGIC, + INDEX_VERSION + )); + try!(BundleMap::create().save(layout.bundle_map_path())); + Self::open(layout, crypto, true) + } + + #[allow(unknown_lints, useless_let_if_seq)] + pub fn open(layout: Arc, crypto: Arc, online: bool) -> Result { + if !layout.remote_exists() { + return Err(RepositoryError::NoRemote); + } + let config = try!(Config::load(layout.config_path())); + let remote_locks = LockFolder::new(layout.remote_locks_path()); + try!(fs::create_dir_all(layout.local_locks_path())); // Added after v0.1.0 + let local_locks = LockFolder::new(layout.local_locks_path()); + let lock = try!(local_locks.lock(false)); + let (bundles, new, gone) = try!(BundleDb::open(layout.clone(), crypto.clone(), online)); + let (index, mut rebuild_index) = + match unsafe { Index::open(layout.index_path(), &INDEX_MAGIC, INDEX_VERSION) } { + Ok(index) => (index, false), + Err(err) => { + tr_error!("Failed to load local index:\n\tcaused by: {}", err); + ( + try!(Index::create( + layout.index_path(), + &INDEX_MAGIC, + INDEX_VERSION + )), + true + ) + } + }; + let (bundle_map, rebuild_bundle_map) = match BundleMap::load(layout.bundle_map_path()) { + Ok(bundle_map) => (bundle_map, false), + Err(err) => { + tr_error!("Failed to load local bundle map:\n\tcaused by: {}", err); + (BundleMap::create(), true) + } + }; + let dirty = layout.dirtyfile_path().exists(); + let mut repo = RepositoryInner { + layout, + dirty: true, + chunker: config.chunker.create(), + config, + index, + crypto, + bundle_map, + next_data_bundle: 0, + next_meta_bundle: 0, + bundles, + data_bundle: None, + meta_bundle: None, + lock, + remote_locks, + local_locks + }; + if !rebuild_bundle_map { + let mut save_bundle_map = false; + if !gone.is_empty() { + tr_info!("Removing {} old bundles from index", gone.len()); + try!(repo.write_mode()); + for bundle in gone { + try!(repo.remove_gone_remote_bundle(&bundle)) + } + save_bundle_map = true; + } + if !new.is_empty() { + tr_info!("Adding {} new bundles to index", new.len()); + try!(repo.write_mode()); + for bundle in ProgressIter::new( + tr!("adding bundles to index"), + new.len(), + new.into_iter() + ) + { + try!(repo.add_new_remote_bundle(&bundle)) + } + save_bundle_map = true; + } + if save_bundle_map { + try!(repo.write_mode()); + try!(repo.save_bundle_map()); + } + } + repo.next_meta_bundle = repo.next_free_bundle_id(); + repo.next_data_bundle = repo.next_free_bundle_id(); + if rebuild_bundle_map { + try!(repo.write_mode()); + try!(repo.rebuild_bundle_map()); + rebuild_index = true; + } + if rebuild_index { + try!(repo.write_mode()); + try!(repo.rebuild_index()); + } + repo.dirty = dirty; + Ok(repo) + } + + #[inline] + pub fn save_config(&mut self) -> Result<(), RepositoryError> { + try!(self.write_mode()); + try!(self.config.save(self.layout.config_path())); + Ok(()) + } + + #[inline] + pub fn set_encryption(&mut self, public: Option<&PublicKey>) { + if let Some(key) = public { + if !self.crypto.contains_secret_key(key) { + tr_warn!("The secret key for that public key is not stored in the repository.") + } + let mut key_bytes = Vec::new(); + key_bytes.extend_from_slice(&key[..]); + self.config.encryption = Some((EncryptionMethod::Sodium, key_bytes.into())) + } else { + self.config.encryption = None + } + } + + #[inline] + pub fn save_bundle_map(&self) -> Result<(), RepositoryError> { + try!(self.bundle_map.save(self.layout.bundle_map_path())); + Ok(()) + } + + #[inline] + pub fn next_free_bundle_id(&self) -> u32 { + let mut id = max(self.next_data_bundle, self.next_meta_bundle) + 1; + while self.bundle_map.get(id).is_some() { + id += 1; + } + id + } + + pub fn set_dirty(&mut self) -> Result<(), RepositoryError> { + self.dirty = true; + let dirtyfile = self.layout.dirtyfile_path(); + if !dirtyfile.exists() { + try!(File::create(&dirtyfile)); + } + Ok(()) + } + + pub fn flush(&mut self) -> Result<(), RepositoryError> { + let dirtyfile = self.layout.dirtyfile_path(); + if self.dirty && !dirtyfile.exists() { + try!(File::create(&dirtyfile)); + } + if self.data_bundle.is_some() { + let mut finished = None; + mem::swap(&mut self.data_bundle, &mut finished); + { + let bundle = try!(self.bundles.add_bundle(finished.unwrap())); + self.bundle_map.set( + self.next_data_bundle, + bundle.id.clone() + ); + } + self.next_data_bundle = self.next_free_bundle_id() + } + if self.meta_bundle.is_some() { + let mut finished = None; + mem::swap(&mut self.meta_bundle, &mut finished); + { + let bundle = try!(self.bundles.add_bundle(finished.unwrap())); + self.bundle_map.set( + self.next_meta_bundle, + bundle.id.clone() + ); + } + self.next_meta_bundle = self.next_free_bundle_id() + } + try!(self.bundles.flush()); + try!(self.save_bundle_map()); + if !self.dirty && dirtyfile.exists() { + try!(fs::remove_file(&dirtyfile)); + } + Ok(()) + } + + fn add_new_remote_bundle(&mut self, bundle: &BundleInfo) -> Result<(), RepositoryError> { + if self.bundle_map.find(&bundle.id).is_some() { + return Ok(()); + } + tr_debug!("Adding new bundle to index: {}", bundle.id); + let bundle_id = match bundle.mode { + BundleMode::Data => self.next_data_bundle, + BundleMode::Meta => self.next_meta_bundle, + }; + let chunks = try!(self.bundles.get_chunk_list(&bundle.id)); + self.bundle_map.set(bundle_id, bundle.id.clone()); + if self.next_meta_bundle == bundle_id { + self.next_meta_bundle = self.next_free_bundle_id() + } + if self.next_data_bundle == bundle_id { + self.next_data_bundle = self.next_free_bundle_id() + } + for (i, (hash, _len)) in chunks.into_inner().into_iter().enumerate() { + if let Some(old) = try!(self.index.set( + &hash, + &Location { + bundle: bundle_id as u32, + chunk: i as u32 + } + )) + { + // Duplicate chunk, forced ordering: higher bundle id wins + let old_bundle_id = try!(self.get_bundle_id(old.bundle)); + if old_bundle_id > bundle.id { + try!(self.index.set(&hash, &old)); + } + } + } + Ok(()) + } + + fn remove_gone_remote_bundle(&mut self, bundle: &BundleInfo) -> Result<(), RepositoryError> { + if let Some(id) = self.bundle_map.find(&bundle.id) { + tr_debug!("Removing bundle from index: {}", bundle.id); + try!(self.bundles.delete_local_bundle(&bundle.id)); + try!(self.index.filter(|_key, data| data.bundle != id)); + self.bundle_map.remove(id); + } + Ok(()) + } + + #[inline] + pub fn write_mode(&mut self) -> Result<(), RepositoryError> { + try!(self.local_locks.upgrade(&mut self.lock)); + Ok(()) + } + + #[inline] + pub fn lock(&self, exclusive: bool) -> Result { + Ok(try!(self.remote_locks.lock(exclusive))) + } + + pub fn is_dirty(&self) -> bool { + self.dirty + } + + pub fn get_chunk_location(&self, chunk: Hash) -> Option { + self.index.get(&chunk) + } + + #[inline] + pub fn set_clean(&mut self) { + self.dirty = false; + } + + pub fn get_config(&self) -> &Config { + &self.config + } + + pub fn set_config(&mut self, config: Config) { + self.config = config; + } +} + + +impl Drop for RepositoryInner { + fn drop(&mut self) { + if let Err(err) = self.flush() { + tr_error!("Failed to flush repository: {}", err); + } + } +} diff --git a/src/repository/vacuum.rs b/src/repository/inner/vacuum.rs similarity index 98% rename from src/repository/vacuum.rs rename to src/repository/inner/vacuum.rs index ad64042..3060cee 100644 --- a/src/repository/vacuum.rs +++ b/src/repository/inner/vacuum.rs @@ -3,7 +3,7 @@ use prelude::*; use std::collections::HashMap; -impl Repository { +impl RepositoryInner { pub fn delete_bundle(&mut self, id: u32) -> Result<(), RepositoryError> { if let Some(bundle) = self.bundle_map.remove(id) { try!(self.bundles.delete_bundle(&bundle)); diff --git a/src/repository/mod.rs b/src/repository/mod.rs index 38d6b07..f7bf068 100644 --- a/src/repository/mod.rs +++ b/src/repository/mod.rs @@ -1,375 +1,24 @@ mod config; mod bundle_map; -mod integrity; -mod basic_io; -mod info; -mod error; -mod vacuum; mod layout; +mod error; +mod inner; pub mod bundledb; pub mod index; pub mod chunking; -use prelude::*; - -use std::mem; -use std::cmp::max; -use std::path::Path; -use std::fs::{self, File}; -use std::sync::Arc; -use std::os::unix::fs::symlink; -use std::io::Write; pub use self::error::RepositoryError; pub use self::config::Config; -pub use self::integrity::IntegrityError; -pub use self::info::{RepositoryInfo, BundleAnalysis, RepositoryStatistics}; +pub use self::inner::IntegrityError; +pub use self::inner::{RepositoryInfo, BundleAnalysis, RepositoryStatistics}; pub use self::layout::{RepositoryLayout, ChunkRepositoryLayout}; -use self::bundle_map::BundleMap; +pub use self::inner::{Location, RepositoryInner}; + +pub use self::inner::api::*; const REPOSITORY_README: &[u8] = include_bytes!("../../docs/repository_readme.md"); const INDEX_MAGIC: [u8; 7] = *b"zvault\x02"; -const INDEX_VERSION: u8 = 1; - - -#[derive(Clone, Copy, PartialEq, Debug, Default)] -pub struct Location { - pub bundle: u32, - pub chunk: u32 -} -impl Location { - pub fn new(bundle: u32, chunk: u32) -> Self { - Location { - bundle, - chunk - } - } -} - -impl index::Value for Location {} - -impl index::Key for Hash { - fn hash(&self) -> u64 { - self.low - } - - fn is_used(&self) -> bool { - self.low != 0 || self.high != 0 - } - - fn clear(&mut self) { - self.low = 0; - self.high = 0; - } -} - -pub struct Repository { - layout: Arc, - config: Config, - index: Index, - crypto: Arc, - bundle_map: BundleMap, - next_data_bundle: u32, - next_meta_bundle: u32, - bundles: BundleDb, - data_bundle: Option, - meta_bundle: Option, - chunker: Box, - remote_locks: LockFolder, - local_locks: LockFolder, - lock: LockHandle, - dirty: bool -} - - -impl Repository { - pub fn create>( - layout: Arc, - config: &Config, - crypto: Arc, - remote: R, - ) -> Result { - try!(fs::create_dir(layout.local_locks_path())); - try!(symlink(remote, layout.remote_path())); - try!(File::create(layout.remote_readme_path()).and_then( - |mut f| { - f.write_all(REPOSITORY_README) - } - )); - try!(fs::create_dir_all(layout.remote_locks_path())); - try!(config.save(layout.config_path())); - try!(BundleDb::create(layout.clone())); - try!(Index::::create( - layout.index_path(), - &INDEX_MAGIC, - INDEX_VERSION - )); - try!(BundleMap::create().save(layout.bundle_map_path())); - Self::open(layout, crypto, true) - } - - #[allow(unknown_lints, useless_let_if_seq)] - pub fn open(layout: Arc, crypto: Arc, online: bool) -> Result { - if !layout.remote_exists() { - return Err(RepositoryError::NoRemote); - } - let config = try!(Config::load(layout.config_path())); - let remote_locks = LockFolder::new(layout.remote_locks_path()); - try!(fs::create_dir_all(layout.local_locks_path())); // Added after v0.1.0 - let local_locks = LockFolder::new(layout.local_locks_path()); - let lock = try!(local_locks.lock(false)); - let (bundles, new, gone) = try!(BundleDb::open(layout.clone(), crypto.clone(), online)); - let (index, mut rebuild_index) = - match unsafe { Index::open(layout.index_path(), &INDEX_MAGIC, INDEX_VERSION) } { - Ok(index) => (index, false), - Err(err) => { - tr_error!("Failed to load local index:\n\tcaused by: {}", err); - ( - try!(Index::create( - layout.index_path(), - &INDEX_MAGIC, - INDEX_VERSION - )), - true - ) - } - }; - let (bundle_map, rebuild_bundle_map) = match BundleMap::load(layout.bundle_map_path()) { - Ok(bundle_map) => (bundle_map, false), - Err(err) => { - tr_error!("Failed to load local bundle map:\n\tcaused by: {}", err); - (BundleMap::create(), true) - } - }; - let dirty = layout.dirtyfile_path().exists(); - let mut repo = Repository { - layout, - dirty: true, - chunker: config.chunker.create(), - config, - index, - crypto, - bundle_map, - next_data_bundle: 0, - next_meta_bundle: 0, - bundles, - data_bundle: None, - meta_bundle: None, - lock, - remote_locks, - local_locks - }; - if !rebuild_bundle_map { - let mut save_bundle_map = false; - if !gone.is_empty() { - tr_info!("Removing {} old bundles from index", gone.len()); - try!(repo.write_mode()); - for bundle in gone { - try!(repo.remove_gone_remote_bundle(&bundle)) - } - save_bundle_map = true; - } - if !new.is_empty() { - tr_info!("Adding {} new bundles to index", new.len()); - try!(repo.write_mode()); - for bundle in ProgressIter::new( - tr!("adding bundles to index"), - new.len(), - new.into_iter() - ) - { - try!(repo.add_new_remote_bundle(&bundle)) - } - save_bundle_map = true; - } - if save_bundle_map { - try!(repo.write_mode()); - try!(repo.save_bundle_map()); - } - } - repo.next_meta_bundle = repo.next_free_bundle_id(); - repo.next_data_bundle = repo.next_free_bundle_id(); - if rebuild_bundle_map { - try!(repo.write_mode()); - try!(repo.rebuild_bundle_map()); - rebuild_index = true; - } - if rebuild_index { - try!(repo.write_mode()); - try!(repo.rebuild_index()); - } - repo.dirty = dirty; - Ok(repo) - } - - #[inline] - pub fn save_config(&mut self) -> Result<(), RepositoryError> { - try!(self.write_mode()); - try!(self.config.save(self.layout.config_path())); - Ok(()) - } - - #[inline] - pub fn set_encryption(&mut self, public: Option<&PublicKey>) { - if let Some(key) = public { - if !self.crypto.contains_secret_key(key) { - tr_warn!("The secret key for that public key is not stored in the repository.") - } - let mut key_bytes = Vec::new(); - key_bytes.extend_from_slice(&key[..]); - self.config.encryption = Some((EncryptionMethod::Sodium, key_bytes.into())) - } else { - self.config.encryption = None - } - } - - #[inline] - pub fn save_bundle_map(&self) -> Result<(), RepositoryError> { - try!(self.bundle_map.save(self.layout.bundle_map_path())); - Ok(()) - } - - #[inline] - fn next_free_bundle_id(&self) -> u32 { - let mut id = max(self.next_data_bundle, self.next_meta_bundle) + 1; - while self.bundle_map.get(id).is_some() { - id += 1; - } - id - } - - pub fn set_dirty(&mut self) -> Result<(), RepositoryError> { - self.dirty = true; - let dirtyfile = self.layout.dirtyfile_path(); - if !dirtyfile.exists() { - try!(File::create(&dirtyfile)); - } - Ok(()) - } - - pub fn flush(&mut self) -> Result<(), RepositoryError> { - let dirtyfile = self.layout.dirtyfile_path(); - if self.dirty && !dirtyfile.exists() { - try!(File::create(&dirtyfile)); - } - if self.data_bundle.is_some() { - let mut finished = None; - mem::swap(&mut self.data_bundle, &mut finished); - { - let bundle = try!(self.bundles.add_bundle(finished.unwrap())); - self.bundle_map.set( - self.next_data_bundle, - bundle.id.clone() - ); - } - self.next_data_bundle = self.next_free_bundle_id() - } - if self.meta_bundle.is_some() { - let mut finished = None; - mem::swap(&mut self.meta_bundle, &mut finished); - { - let bundle = try!(self.bundles.add_bundle(finished.unwrap())); - self.bundle_map.set( - self.next_meta_bundle, - bundle.id.clone() - ); - } - self.next_meta_bundle = self.next_free_bundle_id() - } - try!(self.bundles.flush()); - try!(self.save_bundle_map()); - if !self.dirty && dirtyfile.exists() { - try!(fs::remove_file(&dirtyfile)); - } - Ok(()) - } - - fn add_new_remote_bundle(&mut self, bundle: &BundleInfo) -> Result<(), RepositoryError> { - if self.bundle_map.find(&bundle.id).is_some() { - return Ok(()); - } - tr_debug!("Adding new bundle to index: {}", bundle.id); - let bundle_id = match bundle.mode { - BundleMode::Data => self.next_data_bundle, - BundleMode::Meta => self.next_meta_bundle, - }; - let chunks = try!(self.bundles.get_chunk_list(&bundle.id)); - self.bundle_map.set(bundle_id, bundle.id.clone()); - if self.next_meta_bundle == bundle_id { - self.next_meta_bundle = self.next_free_bundle_id() - } - if self.next_data_bundle == bundle_id { - self.next_data_bundle = self.next_free_bundle_id() - } - for (i, (hash, _len)) in chunks.into_inner().into_iter().enumerate() { - if let Some(old) = try!(self.index.set( - &hash, - &Location { - bundle: bundle_id as u32, - chunk: i as u32 - } - )) - { - // Duplicate chunk, forced ordering: higher bundle id wins - let old_bundle_id = try!(self.get_bundle_id(old.bundle)); - if old_bundle_id > bundle.id { - try!(self.index.set(&hash, &old)); - } - } - } - Ok(()) - } - - fn remove_gone_remote_bundle(&mut self, bundle: &BundleInfo) -> Result<(), RepositoryError> { - if let Some(id) = self.bundle_map.find(&bundle.id) { - tr_debug!("Removing bundle from index: {}", bundle.id); - try!(self.bundles.delete_local_bundle(&bundle.id)); - try!(self.index.filter(|_key, data| data.bundle != id)); - self.bundle_map.remove(id); - } - Ok(()) - } - - #[inline] - pub fn write_mode(&mut self) -> Result<(), RepositoryError> { - try!(self.local_locks.upgrade(&mut self.lock)); - Ok(()) - } - - #[inline] - pub fn lock(&self, exclusive: bool) -> Result { - Ok(try!(self.remote_locks.lock(exclusive))) - } - - pub fn is_dirty(&self) -> bool { - self.dirty - } - - pub fn get_chunk_location(&self, chunk: Hash) -> Option { - self.index.get(&chunk) - } - - #[inline] - pub fn set_clean(&mut self) { - self.dirty = false; - } - - pub fn get_config(&self) -> &Config { - &self.config - } - - pub fn set_config(&mut self, config: Config) { - self.config = config; - } -} - - -impl Drop for Repository { - fn drop(&mut self) { - if let Err(err) = self.flush() { - tr_error!("Failed to flush repository: {}", err); - } - } -} +const INDEX_VERSION: u8 = 1; \ No newline at end of file diff --git a/src/util/mod.rs b/src/util/mod.rs index e651777..1ac1075 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -10,6 +10,7 @@ mod hostname; mod fs; mod lock; mod statistics; + pub mod msgpack; pub use self::fs::*; diff --git a/src/util/mode_test.rs b/src/util/mode_test.rs new file mode 100644 index 0000000..348aace --- /dev/null +++ b/src/util/mode_test.rs @@ -0,0 +1,224 @@ +/** + +ReadonlyMode +- Local: readonly, shared lock +- Remote: offline + +LocalWriteMode +- Local: writable, exclusive lock, dirty flag +- Remote: offline + +OnlineMode +- Local: writable, exclusive lock, dirty flag +- Remote: readonly, shared lock + +BackupMode +- Local: writable, exclusive lock, dirty flag +- Remote: append-only, shared lock + +VacuumMode +- Local: writable, exclusive lock, dirty flag +- Remote: writable, exclusive lock + +**/ + + +pub enum RepositoryError { + Error +} + +enum LockMode { + None, Shared, Exclusive +} + + + +struct RepositoryInner { +} + + +impl RepositoryInner { + fn set_local_lock(&mut self, mode: LockMode) -> Result<(), RepositoryError> { + Ok(()) + } + + fn set_remote_lock(&mut self, mode: LockMode) -> Result<(), RepositoryError> { + Ok(()) + } + + fn set_dirty(&mut self, dirty: bool) -> Result<(), RepositoryError> { + Ok(()) + } + +} + +pub trait ReadonlyMode { + fn func1(&self) -> Result<(), RepositoryError>; +} + +impl ReadonlyMode for RepositoryInner { + fn func1(&self) -> Result<(), RepositoryError> { + Ok(()) + } +} + + +pub trait LocalWriteMode: ReadonlyMode { + fn func2(&self) -> Result<(), RepositoryError>; +} + +impl LocalWriteMode for RepositoryInner { + fn func2(&self) -> Result<(), RepositoryError> { + Ok(()) + } +} + + +pub trait OnlineMode: LocalWriteMode { + +} + +impl OnlineMode for RepositoryInner { + +} + + +pub trait BackupMode: OnlineMode { + +} + +impl BackupMode for RepositoryInner { + +} + + +pub trait VacuumMode: BackupMode { + +} + +impl VacuumMode for RepositoryInner { + +} + + + +pub trait UpgradeToLocalWriteMode { + fn in_local_write_mode, F: FnOnce(&mut LocalWriteMode) -> Result>(&mut self, f: F) -> Result; +} + +impl UpgradeToLocalWriteMode for RepositoryInner { + fn in_local_write_mode, F: FnOnce(&mut LocalWriteMode) -> Result>(&mut self, f: F) -> Result { + try!(self.set_local_lock(LockMode::Exclusive)); + try!(self.set_dirty(true)); + let res = f(self); + if res.is_ok() { + try!(self.set_dirty(false)); + } + try!(self.set_local_lock(LockMode::Shared)); + res + } +} + + +pub trait UpgradeToOnlineMode { + fn in_online_mode, F: FnOnce(&mut OnlineMode) -> Result>(&mut self, f: F) -> Result; +} + +impl UpgradeToOnlineMode for RepositoryInner { + fn in_online_mode, F: FnOnce(&mut OnlineMode) -> Result>(&mut self, f: F) -> Result { + try!(self.set_local_lock(LockMode::Exclusive)); + try!(self.set_remote_lock(LockMode::Shared)); + try!(self.set_dirty(true)); + let res = f(self); + if res.is_ok() { + try!(self.set_dirty(false)); + } + try!(self.set_remote_lock(LockMode::None)); + try!(self.set_local_lock(LockMode::Shared)); + res + } +} + + +pub trait UpgradeToBackupMode { + fn in_backup_mode, F: FnOnce(&mut BackupMode) -> Result>(&mut self, f: F) -> Result; +} + +impl UpgradeToBackupMode for RepositoryInner { + fn in_backup_mode, F: FnOnce(&mut BackupMode) -> Result>(&mut self, f: F) -> Result { + try!(self.set_local_lock(LockMode::Exclusive)); + try!(self.set_remote_lock(LockMode::Shared)); + try!(self.set_dirty(true)); + let res = f(self); + if res.is_ok() { + try!(self.set_dirty(false)); + } + try!(self.set_remote_lock(LockMode::None)); + try!(self.set_local_lock(LockMode::Shared)); + res + } +} + + +pub trait UpgradeToVacuumMode { + fn in_vacuum_mode, F: FnOnce(&mut VacuumMode) -> Result>(&mut self, f: F) -> Result; +} + +impl UpgradeToVacuumMode for RepositoryInner { + fn in_vacuum_mode, F: FnOnce(&mut VacuumMode) -> Result>(&mut self, f: F) -> Result { + try!(self.set_local_lock(LockMode::Exclusive)); + try!(self.set_remote_lock(LockMode::Exclusive)); + try!(self.set_dirty(true)); + let res = f(self); + if res.is_ok() { + try!(self.set_dirty(false)); + } + try!(self.set_remote_lock(LockMode::None)); + try!(self.set_local_lock(LockMode::Shared)); + res + } +} + + +pub struct Repository(RepositoryInner); + +impl ReadonlyMode for Repository { + fn func1(&self) -> Result<(), RepositoryError> { + self.0.func1() + } +} + +impl UpgradeToLocalWriteMode for Repository { + fn in_local_write_mode, F: FnOnce(&mut LocalWriteMode) -> Result>(&mut self, f: F) -> Result { + self.0.in_local_write_mode(f) + } +} + +impl UpgradeToOnlineMode for Repository { + fn in_online_mode, F: FnOnce(&mut OnlineMode) -> Result>(&mut self, f: F) -> Result { + self.0.in_online_mode(f) + } +} + +impl UpgradeToBackupMode for Repository { + fn in_backup_mode, F: FnOnce(&mut BackupMode) -> Result>(&mut self, f: F) -> Result { + self.0.in_backup_mode(f) + } +} + +impl UpgradeToVacuumMode for Repository { + fn in_vacuum_mode, F: FnOnce(&mut VacuumMode) -> Result>(&mut self, f: F) -> Result { + self.0.in_vacuum_mode(f) + } +} + + +impl Repository { + +} + + +fn test_it(mut repo: Repository) { + repo.func1(); + repo.in_local_write_mode(|repo| repo.func2()); +} \ No newline at end of file