Store paths as PathBuf rather than String

This commit is contained in:
Ajeet D'Souza 2020-03-27 17:11:26 +05:30
parent 857e15c65f
commit 890185176e
10 changed files with 223 additions and 131 deletions

135
Cargo.lock generated
View File

@ -10,7 +10,7 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.26"
version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -29,7 +29,7 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -49,7 +49,7 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -67,6 +67,16 @@ dependencies = [
"constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bstr"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-automata 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "byteorder"
version = "1.3.4"
@ -121,7 +131,7 @@ version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_users 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -131,7 +141,7 @@ name = "envy"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -140,7 +150,7 @@ version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
"wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -157,7 +167,28 @@ name = "hermit-abi"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "indoc"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"indoc-impl 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro-hack 0.5.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "indoc-impl"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro-hack 0.5.14 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
"unindent 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -167,33 +198,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.67"
version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro-error"
version = "0.4.11"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro-error-attr 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro-error-attr 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "proc-macro-error-attr"
version = "0.4.11"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
"syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "proc-macro-hack"
version = "0.5.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "1.0.9"
@ -225,6 +266,14 @@ dependencies = [
"rust-argon2 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-automata"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rust-argon2"
version = "0.7.0"
@ -238,20 +287,20 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.104"
version = "1.0.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_derive"
version = "1.0.104"
version = "1.0.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -261,29 +310,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "structopt"
version = "0.3.11"
version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"structopt-derive 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"structopt-derive 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "structopt-derive"
version = "0.4.4"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro-error 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro-error 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "1.0.16"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
@ -298,7 +347,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -324,6 +373,11 @@ name = "unicode-xid"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unindent"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "vec_map"
version = "0.8.1"
@ -362,18 +416,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "zoxide"
version = "0.2.2"
dependencies = [
"anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
"anyhow 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bstr 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"envy 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
"structopt 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
"indoc 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)",
"structopt 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
]
[metadata]
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c"
"checksum anyhow 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "013a6e0a2cbe3d20f9c60b65458f7a7f7a5e636c5d0f45a5a6aee5d4b1f01785"
"checksum arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
@ -382,6 +438,7 @@ dependencies = [
"checksum bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf"
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
"checksum blake2b_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a"
"checksum bstr 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "2889e6d50f394968c8bf4240dc3f2a7eb4680844d27308f798229ac9d4725f41"
"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
@ -393,26 +450,32 @@ dependencies = [
"checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
"checksum hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8"
"checksum indoc 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "79255cf29f5711995ddf9ec261b4057b1deb34e66c90656c201e41376872c544"
"checksum indoc-impl 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "54554010aa3d17754e484005ea0022f1c93839aabc627c2c55f3d7b47206134c"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018"
"checksum proc-macro-error 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e7959c6467d962050d639361f7703b2051c43036d03493c36f01d440fdd3138a"
"checksum proc-macro-error-attr 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e4002d9f55991d5e019fb940a90e1a95eb80c24e77cb2462dd4dc869604d543a"
"checksum libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0"
"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
"checksum proc-macro-error 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7"
"checksum proc-macro-error-attr 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de"
"checksum proc-macro-hack 0.5.14 (registry+https://github.com/rust-lang/crates.io-index)" = "fcfdefadc3d57ca21cf17990a28ef4c0f7c61383a28cb7604cf4a18e6ede1420"
"checksum proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435"
"checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
"checksum redox_users 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431"
"checksum regex-automata 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4"
"checksum rust-argon2 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017"
"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
"checksum serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)" = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff"
"checksum serde_derive 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)" = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum structopt 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe43617218c0805c6eb37160119dc3c548110a67786da7218d1c6555212f073"
"checksum structopt-derive 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c6e79c80e0f4efd86ca960218d4e056249be189ff1c42824dcd9a7f51a56f0bd"
"checksum syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859"
"checksum structopt 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "c8faa2719539bbe9d77869bfb15d4ee769f99525e707931452c97b693b3f159d"
"checksum structopt-derive 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f88b8e18c69496aad6f9ddf4630dd7d585bcaf765786cb415b9aec2fe5a0430"
"checksum syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03"
"checksum syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum unindent 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "63f18aa3b0e35fed5a0048f029558b1518095ffe2a0a31fb87c93dece93a4993"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce"
"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"

View File

@ -13,13 +13,17 @@ license = "MIT"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.26"
anyhow = "1.0.27"
bincode = "1.2.1"
clap = "2.33.0"
dirs = "2.0.2"
envy = "0.4.1"
serde = { version = "1.0.104", features = ["derive"] }
structopt = "0.3.11"
indoc = "0.3.5"
serde = { version = "1.0.105", features = ["derive"] }
structopt = "0.3.12"
[target.'cfg(unix)'.dependencies]
bstr = "0.2.12"
[profile.release]
codegen-units = 1

View File

@ -1,6 +1,8 @@
use crate::dir::Dir;
use crate::types::{Epoch, Rank};
use anyhow::{anyhow, bail, Context, Result};
use indoc::indoc;
use std::fs::{self, File};
use std::io::{self, BufRead, BufReader, BufWriter};
use std::path::{Path, PathBuf};
@ -18,12 +20,11 @@ impl DB {
let dirs = match File::open(&path) {
Ok(file) => {
let reader = BufReader::new(&file);
bincode::deserialize_from(reader)
.with_context(|| anyhow!("could not deserialize database"))?
bincode::deserialize_from(reader).context("could not deserialize database")?
}
Err(err) => match err.kind() {
io::ErrorKind::NotFound => Vec::<Dir>::new(),
_ => return Err(err).with_context(|| anyhow!("could not open database file")),
_ => return Err(err).context("could not open database file"),
},
};
@ -38,15 +39,13 @@ impl DB {
if self.modified {
let path_tmp = self.get_path_tmp();
let file_tmp = File::create(&path_tmp)
.with_context(|| anyhow!("could not open temporary database file"))?;
let file_tmp =
File::create(&path_tmp).context("could not open temporary database file")?;
let writer = BufWriter::new(&file_tmp);
bincode::serialize_into(writer, &self.dirs)
.with_context(|| anyhow!("could not serialize database"))?;
bincode::serialize_into(writer, &self.dirs).context("could not serialize database")?;
fs::rename(&path_tmp, &self.path)
.with_context(|| anyhow!("could not move temporary database file"))?;
fs::rename(&path_tmp, &self.path).context("could not move temporary database file")?;
}
Ok(())
@ -54,14 +53,13 @@ impl DB {
pub fn migrate<P: AsRef<Path>>(&mut self, path: P, merge: bool) -> Result<()> {
if !self.dirs.is_empty() && !merge {
bail!(
bail!(indoc!(
"To prevent conflicts, you can only migrate from z with an empty zoxide database!
If you wish to merge the two, specify the `--merge` flag."
);
If you wish to merge the two, specify the `--merge` flag."
));
}
let z_db_file =
File::open(path).with_context(|| anyhow!("could not open z database file"))?;
let z_db_file = File::open(path).context("could not open z database file")?;
let reader = BufReader::new(z_db_file);
for (idx, read_line) in reader.lines().enumerate() {
@ -104,22 +102,11 @@ If you wish to merge the two, specify the `--merge` flag."
continue;
}
};
let path_str = match path_abs.to_str() {
Some(path) => path,
None => {
eprintln!(
"invalid unicode in path '{}' at line {}",
path_abs.display(),
line_number
);
continue;
}
};
if merge {
// If the path exists in the database, add the ranks and set the epoch to
// the largest of the parsed epoch and the already present epoch.
if let Some(dir) = self.dirs.iter_mut().find(|dir| dir.path == path_str) {
if let Some(dir) = self.dirs.iter_mut().find(|dir| dir.path == path_abs) {
dir.rank += rank;
dir.last_accessed = Epoch::max(epoch, dir.last_accessed);
@ -130,7 +117,7 @@ If you wish to merge the two, specify the `--merge` flag."
// FIXME: When we switch to PathBuf for storing directories inside Dir, just
// pass `PathBuf::from(path_str)`
self.dirs.push(Dir {
path: path_str.to_string(),
path: path_abs,
rank,
last_accessed: epoch,
});
@ -154,13 +141,9 @@ If you wish to merge the two, specify the `--merge` flag."
.canonicalize()
.with_context(|| anyhow!("could not access directory: {}", path.as_ref().display()))?;
let path_str = path_abs
.to_str()
.ok_or_else(|| anyhow!("invalid unicode in path: {}", path_abs.display()))?;
match self.dirs.iter_mut().find(|dir| dir.path == path_str) {
match self.dirs.iter_mut().find(|dir| dir.path == path_abs) {
None => self.dirs.push(Dir {
path: path_str.to_string(),
path: path_abs,
last_accessed: now,
rank: 1.0,
}),
@ -186,20 +169,19 @@ If you wish to merge the two, specify the `--merge` flag."
}
pub fn query(&mut self, keywords: &[String], now: Epoch) -> Option<Dir> {
loop {
let (idx, dir) = self
.dirs
.iter()
.enumerate()
.filter(|(_, dir)| dir.is_match(keywords))
.max_by_key(|(_, dir)| dir.get_frecency(now) as i64)?;
let (idx, dir) = self
.dirs
.iter()
.enumerate()
.filter(|(_, dir)| dir.is_match(&keywords))
.max_by_key(|(_, dir)| dir.get_frecency(now) as i64)?;
if dir.is_dir() {
return Some(dir.to_owned());
} else {
self.dirs.remove(idx);
self.modified = true;
}
if dir.is_dir() {
Some(dir.to_owned())
} else {
self.dirs.swap_remove(idx);
self.modified = true;
self.query(keywords, now)
}
}
@ -219,12 +201,8 @@ If you wish to merge the two, specify the `--merge` flag."
Err(_) => path.as_ref().to_path_buf(),
};
let path_str = path_abs
.to_str()
.ok_or_else(|| anyhow!("invalid unicode in path"))?;
if let Some(idx) = self.dirs.iter().position(|dir| dir.path == path_str) {
self.dirs.remove(idx);
if let Some(idx) = self.dirs.iter().position(|dir| dir.path == path_abs) {
self.dirs.swap_remove(idx);
self.modified = true;
}

View File

@ -1,36 +1,49 @@
use crate::types::{Epoch, Rank};
use serde::{Deserialize, Serialize};
use std::path::Path;
use std::path::PathBuf;
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct Dir {
pub path: String,
pub path: PathBuf,
pub rank: Rank,
pub last_accessed: Epoch,
}
impl Dir {
pub fn is_dir(&self) -> bool {
Path::new(&self.path).is_dir()
self.path.is_dir()
}
#[cfg(unix)]
pub fn is_match(&self, query: &[String]) -> bool {
let path = self.path.to_ascii_lowercase();
use bstr::ByteSlice;
use std::os::unix::ffi::OsStrExt;
if let Some(query_name) = query.last().and_then(|word| Path::new(word).file_name()) {
if let Some(path_name) = Path::new(&path).file_name() {
// `unwrap()` here should be safe because the values are already encoded as UTF-8
let query_name = query_name.to_str().unwrap();
let path_name = path_name.to_str().unwrap();
let path_bytes = self.path.as_os_str().as_bytes().to_lowercase();
let mut subpath = path_bytes.as_slice();
if !path_name.contains(&query_name) {
return false;
}
for subquery in query.iter() {
let subquery_bytes = subquery.as_bytes();
match subpath.find(subquery_bytes) {
Some(idx) => subpath = &subpath[idx + subquery_bytes.len()..],
None => return false,
}
}
let mut subpath = path.as_str();
for subquery in query {
true
}
#[cfg(not(unix))]
pub fn is_match(&self, query: &[String]) -> bool {
let path_str = match self.path.to_str() {
Some(path_str) => path_str.to_lowercase(),
None => return false, // silently ignore invalid UTF-8
};
let mut subpath = path_str.as_str();
for subquery in query.iter() {
match subpath.find(subquery) {
Some(idx) => subpath = &subpath[idx + subquery.len()..],
None => return false,

View File

@ -6,6 +6,7 @@ mod types;
mod util;
use crate::env::Env;
use anyhow::{Context, Result};
use structopt::StructOpt;
@ -23,7 +24,7 @@ pub fn main() -> Result<()> {
let opt = Zoxide::from_args();
let env = envy::prefixed("_ZO_")
.from_env::<Env>()
.with_context(|| "could not parse environment variables")?;
.context("could not parse environment variables")?;
match opt {
Zoxide::Add(add) => add.run(&env)?,

View File

@ -1,7 +1,8 @@
use crate::env::Env;
use crate::types::Rank;
use crate::util;
use anyhow::{anyhow, Context, Result};
use anyhow::{Context, Result};
use std::env;
use structopt::StructOpt;
@ -20,8 +21,8 @@ impl Add {
match &self.path {
Some(path) => db.add(path, maxage, now),
None => {
let current_dir = env::current_dir()
.with_context(|| anyhow!("unable to fetch current directory"))?;
let current_dir =
env::current_dir().context("unable to fetch current directory")?;
db.add(current_dir, maxage, now)
}
}

View File

@ -1,5 +1,6 @@
use crate::env::Env;
use crate::util;
use anyhow::Result;
use structopt::StructOpt;

View File

@ -1,6 +1,8 @@
use crate::env::Env;
use crate::util;
use anyhow::{bail, Result};
use std::io::{self, Write};
use std::path::Path;
use structopt::StructOpt;
@ -21,38 +23,47 @@ impl Query {
};
match path_opt {
Some(path) => println!("query: {}", path.trim()),
Some(path) => {
let stdout = io::stdout();
let mut handle = stdout.lock();
handle.write_all(b"query: ").unwrap();
handle.write_all(&path).unwrap();
handle.write_all(b"\n").unwrap();
}
None => bail!("no match found"),
};
Ok(())
}
fn query(&mut self, env: &Env) -> Result<Option<String>> {
fn query(&mut self, env: &Env) -> Result<Option<Vec<u8>>> {
if let [path] = self.keywords.as_slice() {
if Path::new(path).is_dir() {
return Ok(Some(path.to_string()));
return Ok(Some(path.as_bytes().to_vec()));
}
}
for keyword in &mut self.keywords {
keyword.make_ascii_lowercase();
}
let now = util::get_current_time()?;
for keyword in &mut self.keywords {
*keyword = keyword.to_lowercase();
}
if let Some(dir) = util::get_db(env)?.query(&self.keywords, now) {
Ok(Some(dir.path))
// `path_to_bytes` is guaranteed to succeed here since
// the path has already been queried successfully
let path_bytes = util::path_to_bytes(&dir.path).unwrap();
Ok(Some(path_bytes.to_vec()))
} else {
Ok(None)
}
}
fn query_interactive(&mut self, env: &Env) -> Result<Option<String>> {
fn query_interactive(&mut self, env: &Env) -> Result<Option<Vec<u8>>> {
let now = util::get_current_time()?;
for keyword in &mut self.keywords {
keyword.make_ascii_lowercase();
*keyword = keyword.to_lowercase();
}
let dirs = util::get_db(env)?.query_all(&self.keywords);

View File

@ -1,5 +1,6 @@
use crate::env::Env;
use crate::util;
use anyhow::Result;
use structopt::StructOpt;

View File

@ -2,12 +2,25 @@ use crate::db::DB;
use crate::dir::Dir;
use crate::env::Env;
use crate::types::Epoch;
use anyhow::{anyhow, bail, Context, Result};
use std::cmp::{Ordering, PartialOrd};
use std::io::{Read, Write};
use std::path::Path;
use std::process::{Command, Stdio};
use std::time::SystemTime;
#[cfg(unix)]
pub fn path_to_bytes<P: AsRef<Path>>(path: &P) -> Option<&[u8]> {
use std::os::unix::ffi::OsStrExt;
Some(path.as_ref().as_os_str().as_bytes())
}
#[cfg(not(unix))]
pub fn path_to_bytes<P: AsRef<Path>>(path: &P) -> Option<&[u8]> {
Some(path.as_ref().to_str()?.as_bytes())
}
pub fn get_db(env: &Env) -> Result<DB> {
let path = env
.data
@ -19,19 +32,19 @@ pub fn get_db(env: &Env) -> Result<DB> {
pub fn get_current_time() -> Result<Epoch> {
let current_time = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.with_context(|| "system clock set to invalid time")?
.context("system clock set to invalid time")?
.as_secs();
Ok(current_time as Epoch)
}
pub fn fzf_helper(now: Epoch, mut dirs: Vec<Dir>) -> Result<Option<String>> {
pub fn fzf_helper(now: Epoch, mut dirs: Vec<Dir>) -> Result<Option<Vec<u8>>> {
let mut fzf = Command::new("fzf")
.arg("-n2..")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.with_context(|| anyhow!("could not launch fzf"))?;
.context("could not launch fzf")?;
let fzf_stdin = fzf
.stdin
@ -52,8 +65,15 @@ pub fn fzf_helper(now: Epoch, mut dirs: Vec<Dir>) -> Result<Option<String>> {
for dir in dirs.iter() {
// ensure that frecency fits in 4 characters
let frecency = clamp(dir.rank, 0.0, 9999.0);
writeln!(fzf_stdin, "{:>4.0} {}", frecency, dir.path)
.with_context(|| anyhow!("could not write into fzf stdin"))?;
if let Some(path_bytes) = path_to_bytes(&dir.path) {
(|| {
write!(fzf_stdin, "{:>4.0} ", frecency)?;
fzf_stdin.write_all(path_bytes)?;
fzf_stdin.write_all(b"\n")
})()
.context("could not write into fzf stdin")?;
}
}
let fzf_stdout = fzf
@ -61,17 +81,16 @@ pub fn fzf_helper(now: Epoch, mut dirs: Vec<Dir>) -> Result<Option<String>> {
.as_mut()
.ok_or_else(|| anyhow!("could not connect to fzf stdout"))?;
let mut output = String::new();
let mut buffer = Vec::new();
fzf_stdout
.read_to_string(&mut output)
.with_context(|| anyhow!("could not read from fzf stdout"))?;
let status = fzf.wait().with_context(|| "could not wait on fzf")?;
.read_to_end(&mut buffer)
.context("could not read from fzf stdout")?;
let status = fzf.wait().context("wait failed on fzf")?;
match status.code() {
// normal exit
Some(0) => match output.get(12..) {
Some(path) => Ok(Some(path.to_string())),
Some(0) => match buffer.get(12..buffer.len() - 1) {
Some(path) => Ok(Some(path.to_vec())),
None => bail!("fzf returned invalid output"),
},