From 71bb3d31508d4d6b4caa9d155a14dff383402c28 Mon Sep 17 00:00:00 2001 From: Stefan Seemayer Date: Sat, 25 Apr 2026 18:06:21 +0200 Subject: [PATCH] chore: bump keepass to 0.12.0 After a major refactor of the keepass crate, bring the tool up to the most recent, stable API version. --- Cargo.lock | 568 ++++++++++++++---- Cargo.toml | 4 +- src/diff/entry.rs | 42 +- src/diff/field.rs | 35 +- src/diff/group.rs | 75 ++- src/diff/mod.rs | 152 ++--- src/main.rs | 3 +- .../result_--passwords demopass | 6 +- ...sult_--passwords demopass --mask-passwords | 6 +- .../result_--passwords demopass --no-color | 6 +- ...words demopass --no-color --mask-passwords | 6 +- .../result_--passwords demopass --verbose | 8 +- ...swords demopass --verbose --mask-passwords | 8 +- ..._--passwords demopass --verbose --no-color | 8 +- ...pass --verbose --no-color --mask-passwords | 8 +- .../result_--passwords demopass | 6 +- ...sult_--passwords demopass --mask-passwords | 6 +- .../result_--passwords demopass --no-color | 6 +- ...words demopass --no-color --mask-passwords | 6 +- .../result_--passwords demopass --verbose | 8 +- ...swords demopass --verbose --mask-passwords | 8 +- ..._--passwords demopass --verbose --no-color | 8 +- ...pass --verbose --no-color --mask-passwords | 8 +- 23 files changed, 602 insertions(+), 389 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 12b49e6..e568281 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "adler" @@ -10,12 +10,12 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aes" -version = "0.8.3" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +checksum = "66bd29a732b644c0431c6140f370d097879203d79b80c94a6747ba0872adaef8" dependencies = [ - "cfg-if", "cipher", + "cpubits", "cpufeatures", ] @@ -82,6 +82,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + [[package]] name = "arrayref" version = "0.3.7" @@ -102,9 +108,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" -version = "0.21.5" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" @@ -120,16 +126,16 @@ checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" dependencies = [ "arrayref", "arrayvec", - "constant_time_eq", + "constant_time_eq 0.3.0", ] [[package]] name = "block-buffer" -version = "0.10.4" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" dependencies = [ - "generic-array", + "hybrid-array", ] [[package]] @@ -140,11 +146,11 @@ checksum = "9e2211b0817f061502a8dd9f11a37e879e79763e3c698d2418cf824d8cb2f21e" [[package]] name = "block-padding" -version = "0.3.3" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +checksum = "710f1dd022ef4e93f8a438b4ba958de7f64308434fa6a87104481645cc30068b" dependencies = [ - "generic-array", + "hybrid-array", ] [[package]] @@ -161,9 +167,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cbc" -version = "0.1.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +checksum = "98db6aeaef0eeef2c1e3ce9a27b739218825dae116076352ac3777076aa22225" dependencies = [ "cipher", ] @@ -185,9 +191,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chacha20" -version = "0.9.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" dependencies = [ "cfg-if", "cipher", @@ -209,10 +215,11 @@ dependencies = [ [[package]] name = "cipher" -version = "0.4.4" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +checksum = "e34d8227fe1ba289043aeb13792056ff80fd6de1a9f49137a5f499de8e8c78ea" dependencies = [ + "block-buffer", "crypto-common", "inout", ] @@ -246,7 +253,7 @@ version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "syn", @@ -258,29 +265,53 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +[[package]] +name = "cmov" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746" + [[package]] name = "colorchoice" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + [[package]] name = "constant_time_eq" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +[[package]] +name = "constant_time_eq" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" + [[package]] name = "core-foundation-sys" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +[[package]] +name = "cpubits" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef0c543070d296ea414df2dd7625d1b24866ce206709d8a4a424f28377f5861" + [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ "libc", ] @@ -294,27 +325,48 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" dependencies = [ - "generic-array", - "typenum", + "hybrid-array", +] + +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", ] [[package]] name = "digest" -version = "0.10.7" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" dependencies = [ "block-buffer", + "const-oid", "crypto-common", - "subtle", + "ctutils", ] +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "errno" version = "0.3.5" @@ -336,47 +388,83 @@ dependencies = [ ] [[package]] -name = "generic-array" -version = "0.14.7" +name = "foldhash" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "getrandom" -version = "0.2.10" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", + "js-sys", "libc", - "wasi", + "r-efi", + "wasip2", + "wasip3", + "wasm-bindgen", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", ] +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" + [[package]] name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "hex-literal" -version = "0.4.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" +checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1" [[package]] name = "hmac" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" dependencies = [ "digest", ] +[[package]] +name = "hybrid-array" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d46837a0ed51fe95bd3b05de33cd64a1ee88fc797477ca48446872504507c5" +dependencies = [ + "typenum", +] + [[package]] name = "iana-time-zone" version = "0.1.58" @@ -400,30 +488,55 @@ dependencies = [ "cc", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.0", + "serde", + "serde_core", +] + [[package]] name = "inout" -version = "0.1.3" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" dependencies = [ "block-padding", - "generic-array", + "hybrid-array", ] +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + [[package]] name = "js-sys" -version = "0.3.65" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" dependencies = [ + "once_cell", "wasm-bindgen", ] [[package]] name = "keepass" -version = "0.6.6" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69be91e6aeada33fca98962d6e801504dd013231721a29926677da2823e961b" +checksum = "adee434c69bae0f57eae9a53a5590357df8f00f90e52def5c8496f8169d535b6" dependencies = [ "aes", "base64", @@ -435,16 +548,20 @@ dependencies = [ "cipher", "flate2", "getrandom", + "hex", "hex-literal", "hmac", + "hybrid-array", + "js-sys", + "quick-xml", "rust-argon2", "salsa20", - "secstr", + "secrecy", + "serde", "sha2", "thiserror", "twofish", "uuid", - "xml-rs", "zeroize", ] @@ -452,18 +569,23 @@ dependencies = [ name = "keepass-diff" version = "1.2.0" dependencies = [ - "base64", "clap", "keepass", "rpassword", "termcolor", ] +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libc" -version = "0.2.150" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "linux-raw-sys" @@ -477,6 +599,12 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + [[package]] name = "miniz_oxide" version = "0.7.1" @@ -501,24 +629,50 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] +[[package]] +name = "quick-xml" +version = "0.39.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958f21e8e7ceb5a1aa7fa87fab28e7c75976e0bfe7e23ff069e0a260f894067d" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "quote" -version = "1.0.33" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "rpassword" version = "7.2.0" @@ -542,13 +696,14 @@ dependencies = [ [[package]] name = "rust-argon2" -version = "2.0.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e71971821b3ae0e769e4a4328dbcb517607b434db7697e9aba17203ec14e46a" +checksum = "8ae76b7506744d254fd0eb2c0ff5c5d108201ccbb083111ac04a44eeda105680" dependencies = [ "base64", "blake2b_simd", - "constant_time_eq", + "constant_time_eq 0.4.2", + "crossbeam-utils", ] [[package]] @@ -564,49 +719,85 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + [[package]] name = "salsa20" -version = "0.10.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +checksum = "2f874456e72520ff1375a06c588eaf074b0f01f9e9e1aada45bd9b7954a6e42c" dependencies = [ + "cfg-if", "cipher", ] [[package]] -name = "secstr" -version = "0.5.1" +name = "secrecy" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04f657244f605c4cf38f6de5993e8bd050c8a303f86aeabff142d5c7c113e12" +checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a" dependencies = [ - "libc", + "zeroize", ] +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + [[package]] name = "serde" -version = "1.0.190" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.190" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", "syn", ] +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + [[package]] name = "sha2" -version = "0.10.8" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" dependencies = [ "cfg-if", "cpufeatures", @@ -619,17 +810,11 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -[[package]] -name = "subtle" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" - [[package]] name = "syn" -version = "2.0.38" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -657,18 +842,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.50" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", @@ -677,18 +862,18 @@ dependencies = [ [[package]] name = "twofish" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a78e83a30223c757c3947cd144a31014ff04298d8719ae10d03c31c0448c8013" +checksum = "0218ef702a91e18ba84dd516edf8df33a9f9fb4431d6ada13e6f9502c3bcb6fc" dependencies = [ "cipher", ] [[package]] name = "typenum" -version = "1.17.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "unicode-ident" @@ -696,6 +881,12 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "utf8parse" version = "0.2.1" @@ -704,56 +895,52 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.5.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ "getrandom", - "serde", + "js-sys", + "serde_core", + "wasm-bindgen", ] [[package]] -name = "version_check" -version = "0.9.4" +name = "wasip2" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +dependencies = [ + "wit-bindgen 0.57.1", +] [[package]] -name = "wasm-bindgen" -version = "0.2.88" +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "cfg-if", - "wasm-bindgen-macro", + "wit-bindgen 0.51.0", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.88" +name = "wasm-bindgen" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" dependencies = [ - "bumpalo", - "log", + "cfg-if", "once_cell", - "proc-macro2", - "quote", - "syn", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.88" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -761,22 +948,59 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.88" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.88" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", +] [[package]] name = "winapi" @@ -885,10 +1109,98 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] -name = "xml-rs" -version = "0.8.19" +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] [[package]] name = "zeroize" @@ -909,3 +1221,9 @@ dependencies = [ "quote", "syn", ] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/Cargo.toml b/Cargo.toml index ae14b88..5fec1ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [package] name = "keepass-diff" +edition = "2015" description = "This CLI-tool reads two Keepass (.kdbx) files and prints their differences." keywords = ["cli", "diff", "keepass"] repository = "https://github.com/Narigo/keepass-diff" @@ -16,8 +17,7 @@ exclude = [ ] [dependencies] -base64 = "0.21.5" clap = { version = "4.4.7", features = ["cargo", "env", "derive", "wrap_help"] } -keepass = "0.6.6" +keepass = "0.12.0" rpassword = "7.2.0" termcolor = "1.3.0" diff --git a/src/diff/entry.rs b/src/diff/entry.rs index ea3c48c..2a5303b 100644 --- a/src/diff/entry.rs +++ b/src/diff/entry.rs @@ -1,8 +1,6 @@ -use base64::{engine::general_purpose, Engine as _}; -use keepass::db::Value; use std::collections::HashMap; -use crate::diff::field::{Field, ValueType}; +use crate::diff::field::Field; use crate::diff::{Diff, DiffResult, DiffResultFormat}; #[derive(Clone, Debug, PartialEq, Eq)] @@ -13,7 +11,11 @@ pub struct Entry { } impl Entry { - pub fn from_keepass(e: &keepass::db::Entry, use_verbose: bool, mask_passwords: bool) -> Self { + pub fn from_keepass( + e: keepass::db::EntryRef<'_>, + use_verbose: bool, + mask_passwords: bool, + ) -> Self { // username, password, etc. are just fields let fields = e .fields @@ -23,18 +25,8 @@ impl Entry { k.to_owned(), Field { name: k.to_owned(), - value: match v { - Value::Bytes(b) => general_purpose::STANDARD_NO_PAD.encode(b), - Value::Unprotected(v) => v.to_owned(), - Value::Protected(p) => String::from_utf8(p.unsecure().to_owned()) - .unwrap() - .to_owned(), - }, - kind: match v { - Value::Bytes(_) => ValueType::Binary, - Value::Unprotected(_) => ValueType::Unprotected, - Value::Protected(_) => ValueType::Protected, - }, + value: v.get().to_string(), + protected: v.is_protected(), use_verbose, mask_passwords, }, @@ -52,10 +44,15 @@ impl Entry { impl Diff for Entry { fn diff<'a>(&'a self, other: &'a Self) -> DiffResult<'a, Self> { - let (has_differences, field_differences) = - crate::diff::diff_entry(&self.fields, &other.fields); + let field_differences = + crate::diff::diff_hashmap(&self.fields, &other.fields, |(ka, _), (kb, _)| ka.cmp(&kb)); - if has_differences { + if field_differences.is_empty() { + DiffResult::Identical { + left: self, + right: other, + } + } else { let mut inner_differences: Vec> = Vec::new(); for dr in field_differences { @@ -67,11 +64,6 @@ impl Diff for Entry { right: other, inner_differences, } - } else { - DiffResult::Identical { - left: self, - right: other, - } } } } @@ -84,7 +76,7 @@ impl std::fmt::Display for Entry { .unwrap_or(&Field { name: "Title".to_string(), value: "".to_string(), - kind: ValueType::Unprotected, + protected: false, use_verbose: self.use_verbose, mask_passwords: self.mask_passwords, }) diff --git a/src/diff/field.rs b/src/diff/field.rs index 60225e5..ca8eaeb 100644 --- a/src/diff/field.rs +++ b/src/diff/field.rs @@ -1,17 +1,10 @@ use crate::diff::{Diff, DiffResult}; -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum ValueType { - Binary, - Unprotected, - Protected, -} - #[derive(Clone, Debug, PartialEq, Eq)] pub struct Field { pub name: String, pub value: String, - pub kind: ValueType, + pub protected: bool, pub use_verbose: bool, pub mask_passwords: bool, } @@ -34,26 +27,16 @@ impl Diff for Field { impl std::fmt::Display for Field { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let value = if self.mask_passwords && self.protected { + "***" + } else { + &self.value + }; + if self.use_verbose { - write!( - f, - "Field '{}' = '{}'", - self.name, - match (self.mask_passwords, self.kind) { - (true, ValueType::Protected) => "***".to_owned(), - _ => self.value.to_owned(), - } - ) + write!(f, "Field '{}' = '{}'", self.name, value) } else { - write!( - f, - "{} = {}", - self.name, - match (self.mask_passwords, self.kind) { - (true, ValueType::Protected) => "***".to_owned(), - _ => self.value.to_owned(), - } - ) + write!(f, "{} = {}", self.name, value) } } } diff --git a/src/diff/group.rs b/src/diff/group.rs index 9826eff..ea03024 100644 --- a/src/diff/group.rs +++ b/src/diff/group.rs @@ -6,41 +6,35 @@ use std::collections::HashMap; /// Corresponds to a sorted Vec of KdbxEntry objects that can be diffed #[derive(Debug)] pub struct Group { - name: String, - child_groups: HashMap>, - entries: HashMap>, - use_verbose: bool, + pub name: String, + pub child_groups: HashMap, + pub entries: HashMap, + pub use_verbose: bool, } impl Group { /// Create an entries list from a keepass::Group pub fn from_keepass( - group: &keepass::db::Group, + group: keepass::db::GroupRef<'_>, use_verbose: bool, mask_passwords: bool, ) -> Self { let name = group.name.to_owned(); - let mut child_groups: HashMap> = HashMap::new(); - for node in group.children.iter() { - match node { - keepass::db::Node::Group(g) => child_groups - .entry(g.name.clone()) - .or_insert(Vec::new()) - .push(Group::from_keepass(g, use_verbose, mask_passwords)), - _ => {} - } + let mut child_groups: HashMap = HashMap::new(); + for child_group in group.groups() { + child_groups.insert( + child_group.id(), + Group::from_keepass(child_group, use_verbose, mask_passwords), + ); } - let mut entries: HashMap> = HashMap::new(); - for node in group.children.iter() { - match node { - keepass::db::Node::Entry(e) => entries - .entry(e.get("Title").unwrap_or_default().to_owned()) - .or_insert(Vec::new()) - .push(Entry::from_keepass(e, use_verbose, mask_passwords)), - _ => {} - } + let mut entries: HashMap = HashMap::new(); + for entry in group.entries() { + entries.insert( + entry.id(), + Entry::from_keepass(entry, use_verbose, mask_passwords), + ); } Group { @@ -65,13 +59,33 @@ impl std::fmt::Display for Group { /// Groups can be diffed. impl Diff for Group { fn diff<'a>(&'a self, other: &'a Group) -> DiffResult<'a, Self> { - let (has_differences_groups, acc_groups) = - crate::diff::diff_hashmap(&self.child_groups, &other.child_groups); + let acc_groups = + crate::diff::diff_hashmap(&self.child_groups, &other.child_groups, |(_, a), (_, b)| { + a.name.cmp(&b.name) + }); + + let acc_entries = + crate::diff::diff_hashmap(&self.entries, &other.entries, |(_, a), (_, b)| { + let a_title = a + .fields + .get("Title") + .map(|f| f.value.as_str()) + .unwrap_or(""); + let b_title = b + .fields + .get("Title") + .map(|f| f.value.as_str()) + .unwrap_or(""); - let (has_differences_entries, acc_entries) = - crate::diff::diff_hashmap(&self.entries, &other.entries); + a_title.cmp(b_title) + }); - if has_differences_groups || has_differences_entries { + if acc_groups.is_empty() && acc_entries.is_empty() { + return DiffResult::Identical { + left: self, + right: other, + }; + } else { let mut inner_differences: Vec> = Vec::new(); for dr in acc_groups { @@ -87,11 +101,6 @@ impl Diff for Group { right: other, inner_differences, } - } else { - DiffResult::Identical { - left: self, - right: other, - } } } } diff --git a/src/diff/mod.rs b/src/diff/mod.rs index 3a6f88d..430ffa2 100644 --- a/src/diff/mod.rs +++ b/src/diff/mod.rs @@ -173,131 +173,59 @@ where } } -/// Compare to HashMaps of the same value type with each other, returning a bool indicating whether -/// there are any differences and a Vec> listing all differences -pub fn diff_entry<'a, A>( - a: &'a HashMap, - b: &'a HashMap, -) -> (bool, Vec>) +pub fn diff_hashmap<'a, K, A, F>( + a: &'a HashMap, + b: &'a HashMap, + order_fn: F, +) -> Vec> where + K: std::hash::Hash + Eq + Clone + std::fmt::Debug, A: Diff, + F: Fn((&K, &A), (&K, &A)) -> std::cmp::Ordering, { - let mut keys = HashSet::new(); - keys.extend(a.keys()); - keys.extend(b.keys()); + let mut keys: HashSet = HashSet::new(); + keys.extend(a.keys().cloned()); + keys.extend(b.keys().cloned()); + // sort keys by order_fn, i.e. groups by names and entries by titles let mut keys: Vec<_> = keys.iter().collect(); - keys.sort(); + keys.sort_by(|k1, k2| { + let v1 = a.get(*k1).or_else(|| b.get(*k1)).unwrap(); + let v2 = a.get(*k2).or_else(|| b.get(*k2)).unwrap(); - let mut acc: Vec> = Vec::new(); - - let mut has_differences = false; - - for key in keys { - let el_a: Option<&A> = a.get(*key); - let el_b: Option<&A> = b.get(*key); - - match (el_a, el_b) { - // both a and b have the key - (Some(v_a), Some(v_b)) => { - let dr: DiffResult = v_a.diff(v_b); - - if let DiffResult::Identical { .. } = dr { - } else { - has_differences = true; - } + let ord = order_fn((k1, v1), (k2, v2)); - acc.push(dr); - } - - // only a has the key - (Some(v_a), None) => { - has_differences = true; - acc.push(DiffResult::OnlyLeft { left: v_a }) - } - - // only b has the key - (None, Some(v_b)) => { - has_differences = true; - acc.push(DiffResult::OnlyRight { right: v_b }) - } - - // none have the key (this shouldn't happen) - (None, None) => {} + if ord == std::cmp::Ordering::Equal { + // if the order_fn returns Equal, we can use the keys to break ties + format!("{:?}", k1).cmp(&format!("{:?}", k2)) + } else { + ord } - } - - (has_differences, acc) -} - -pub fn diff_hashmap<'a, A>( - a: &'a HashMap>, - b: &'a HashMap>, -) -> (bool, Vec>) -where - A: Diff, -{ - let mut keys = HashSet::new(); - keys.extend(a.keys()); - keys.extend(b.keys()); - - let mut keys: Vec<_> = keys.iter().collect(); - keys.sort(); + }); let mut acc: Vec> = Vec::new(); - let mut has_differences = false; - for key in keys { - let el_a: Option<&Vec> = a.get(*key); - let el_b: Option<&Vec> = b.get(*key); - - match (el_a, el_b) { - // both a and b have the key - (Some(v_a), Some(v_b)) => { - v_a.into_iter() - .enumerate() - .for_each(|(index, value_a)| match v_b.get(index) { - Some(value_b) => { - let dr: DiffResult = value_a.diff(value_b); - if let DiffResult::Identical { .. } = dr { - } else { - has_differences = true; - } - acc.push(dr); - } - None => { - has_differences = true; - acc.push(DiffResult::OnlyLeft { left: value_a }) - } - }); - if v_a.len() < v_b.len() { - has_differences = true; - v_b[v_a.len()..] - .into_iter() - .for_each(|value_b| acc.push(DiffResult::OnlyRight { right: value_b })); - } - } + let Some(el_a): Option<&A> = a.get(&key) else { + acc.push(DiffResult::OnlyRight { + right: b.get(&key).unwrap(), + }); + continue; + }; - // only a has the key - (Some(v_a), None) => { - has_differences = true; - v_a.into_iter() - .for_each(|e| acc.push(DiffResult::OnlyLeft { left: e })); - } - // only b has the key - (None, Some(v_b)) => { - has_differences = true; - v_b.into_iter() - .for_each(|e| acc.push(DiffResult::OnlyRight { right: e })); - } + let Some(el_b): Option<&A> = b.get(&key) else { + acc.push(DiffResult::OnlyLeft { left: el_a }); + continue; + }; - // none have the key (this shouldn't happen) - (None, None) => {} + let dr = el_a.diff(el_b); + if let DiffResult::Identical { .. } = dr { + } else { + acc.push(dr); } } - (has_differences, acc) + acc } #[cfg(test)] @@ -308,10 +236,10 @@ mod test { #[test] fn diff_empty_groups() { - let a = HashMap::>::new(); - let b = HashMap::>::new(); - let (has_differences, _) = diff_hashmap(&a, &b); + let a = HashMap::::new(); + let b = HashMap::::new(); + let acc = diff_hashmap(&a, &b, |(_, a), (_, b)| a.name.cmp(&b.name)); - assert_eq!(false, has_differences); + assert!(acc.is_empty()); } } diff --git a/src/main.rs b/src/main.rs index 44f243b..e6dd441 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,3 @@ -extern crate base64; extern crate clap; extern crate keepass; extern crate rpassword; @@ -156,7 +155,7 @@ pub fn kdbx_to_group( ) -> Result { let db_key = get_database_key(password, keyfile_path)?; let db = Database::open(&mut File::open(file)?, db_key)?; - Ok(Group::from_keepass(&db.root, use_verbose, mask_passwords)) + Ok(Group::from_keepass(db.root(), use_verbose, mask_passwords)) } fn get_database_key( diff --git a/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass b/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass index 2d07b0e..a2f58b2 100644 --- a/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass +++ b/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass @@ -1,5 +1,3 @@ -- [Root, ] -- [Root, ] -+ [Root, another] -+ [Root, single] ++ [Root, , Title = single] ++ [Root, , Title = another]  diff --git a/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --mask-passwords b/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --mask-passwords index 2d07b0e..a2f58b2 100644 --- a/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --mask-passwords +++ b/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --mask-passwords @@ -1,5 +1,3 @@ -- [Root, ] -- [Root, ] -+ [Root, another] -+ [Root, single] ++ [Root, , Title = single] ++ [Root, , Title = another]  diff --git a/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --no-color b/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --no-color index ca665dd..1510050 100644 --- a/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --no-color +++ b/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --no-color @@ -1,5 +1,3 @@ -- [Root, ] -- [Root, ] -+ [Root, another] -+ [Root, single] ++ [Root, , Title = single] ++ [Root, , Title = another] diff --git a/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --no-color --mask-passwords b/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --no-color --mask-passwords index ca665dd..1510050 100644 --- a/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --no-color --mask-passwords +++ b/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --no-color --mask-passwords @@ -1,5 +1,3 @@ -- [Root, ] -- [Root, ] -+ [Root, another] -+ [Root, single] ++ [Root, , Title = single] ++ [Root, , Title = another] diff --git a/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --verbose b/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --verbose index 6422bad..ec0986b 100644 --- a/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --verbose +++ b/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --verbose @@ -1,6 +1,6 @@ ~ Group 'Root' -- Entry '' -- Entry '' -+ Entry 'another' -+ Entry 'single' +~ Entry '' ++ Field 'Title' = 'single' +~ Entry '' ++ Field 'Title' = 'another'  diff --git a/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --verbose --mask-passwords b/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --verbose --mask-passwords index 6422bad..ec0986b 100644 --- a/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --verbose --mask-passwords +++ b/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --verbose --mask-passwords @@ -1,6 +1,6 @@ ~ Group 'Root' -- Entry '' -- Entry '' -+ Entry 'another' -+ Entry 'single' +~ Entry '' ++ Field 'Title' = 'single' +~ Entry '' ++ Field 'Title' = 'another'  diff --git a/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --verbose --no-color b/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --verbose --no-color index 88acc17..d097cf8 100644 --- a/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --verbose --no-color +++ b/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --verbose --no-color @@ -1,6 +1,6 @@ ~ Group 'Root' -- Entry '' -- Entry '' -+ Entry 'another' -+ Entry 'single' +~ Entry '' ++ Field 'Title' = 'single' +~ Entry '' ++ Field 'Title' = 'another' diff --git a/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --verbose --no-color --mask-passwords b/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --verbose --no-color --mask-passwords index 88acc17..d097cf8 100644 --- a/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --verbose --no-color --mask-passwords +++ b/test/test-two-root-entries-without-title_two-root-entries/result_--passwords demopass --verbose --no-color --mask-passwords @@ -1,6 +1,6 @@ ~ Group 'Root' -- Entry '' -- Entry '' -+ Entry 'another' -+ Entry 'single' +~ Entry '' ++ Field 'Title' = 'single' +~ Entry '' ++ Field 'Title' = 'another' diff --git a/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass b/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass index db40c69..176b4a7 100644 --- a/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass +++ b/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass @@ -1,5 +1,3 @@ -+ [Root, ] -+ [Root, ] -- [Root, another] -- [Root, single] +- [Root, another, Title = another] +- [Root, single, Title = single]  diff --git a/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --mask-passwords b/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --mask-passwords index db40c69..176b4a7 100644 --- a/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --mask-passwords +++ b/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --mask-passwords @@ -1,5 +1,3 @@ -+ [Root, ] -+ [Root, ] -- [Root, another] -- [Root, single] +- [Root, another, Title = another] +- [Root, single, Title = single]  diff --git a/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --no-color b/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --no-color index 07c20a8..5628e8c 100644 --- a/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --no-color +++ b/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --no-color @@ -1,5 +1,3 @@ -+ [Root, ] -+ [Root, ] -- [Root, another] -- [Root, single] +- [Root, another, Title = another] +- [Root, single, Title = single] diff --git a/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --no-color --mask-passwords b/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --no-color --mask-passwords index 07c20a8..5628e8c 100644 --- a/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --no-color --mask-passwords +++ b/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --no-color --mask-passwords @@ -1,5 +1,3 @@ -+ [Root, ] -+ [Root, ] -- [Root, another] -- [Root, single] +- [Root, another, Title = another] +- [Root, single, Title = single] diff --git a/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --verbose b/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --verbose index 17baa98..ee5c7eb 100644 --- a/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --verbose +++ b/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --verbose @@ -1,6 +1,6 @@ ~ Group 'Root' -+ Entry '' -+ Entry '' -- Entry 'another' -- Entry 'single' +~ Entry 'another' +- Field 'Title' = 'another' +~ Entry 'single' +- Field 'Title' = 'single'  diff --git a/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --verbose --mask-passwords b/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --verbose --mask-passwords index 17baa98..ee5c7eb 100644 --- a/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --verbose --mask-passwords +++ b/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --verbose --mask-passwords @@ -1,6 +1,6 @@ ~ Group 'Root' -+ Entry '' -+ Entry '' -- Entry 'another' -- Entry 'single' +~ Entry 'another' +- Field 'Title' = 'another' +~ Entry 'single' +- Field 'Title' = 'single'  diff --git a/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --verbose --no-color b/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --verbose --no-color index 900f5d8..36cc00f 100644 --- a/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --verbose --no-color +++ b/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --verbose --no-color @@ -1,6 +1,6 @@ ~ Group 'Root' -+ Entry '' -+ Entry '' -- Entry 'another' -- Entry 'single' +~ Entry 'another' +- Field 'Title' = 'another' +~ Entry 'single' +- Field 'Title' = 'single' diff --git a/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --verbose --no-color --mask-passwords b/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --verbose --no-color --mask-passwords index 900f5d8..36cc00f 100644 --- a/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --verbose --no-color --mask-passwords +++ b/test/test-two-root-entries_two-root-entries-without-title/result_--passwords demopass --verbose --no-color --mask-passwords @@ -1,6 +1,6 @@ ~ Group 'Root' -+ Entry '' -+ Entry '' -- Entry 'another' -- Entry 'single' +~ Entry 'another' +- Field 'Title' = 'another' +~ Entry 'single' +- Field 'Title' = 'single'