Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package thin-provisioning-tools for 
openSUSE:Factory checked in at 2026-06-25 10:50:02
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/thin-provisioning-tools (Old)
 and      /work/SRC/openSUSE:Factory/.thin-provisioning-tools.new.2088 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "thin-provisioning-tools"

Thu Jun 25 10:50:02 2026 rev:35 rq:1361377 version:1.3.3

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/thin-provisioning-tools/thin-provisioning-tools.changes
  2026-05-24 19:35:45.703542382 +0200
+++ 
/work/SRC/openSUSE:Factory/.thin-provisioning-tools.new.2088/thin-provisioning-tools.changes
        2026-06-25 10:51:59.774554017 +0200
@@ -1,0 +2,12 @@
+Tue Jun 23 13:39:55 UTC 2026 - Martin Pluskal <[email protected]>
+
+- Update to version 1.3.3:
+  * thin_explore: fix a panic when navigating an empty top-level
+    tree, and panics when navigating empty btrees
+  * era_invalidate: fix missing era array traversal when no
+    writesets exist
+  * thin_metadata_pack/unpack: flush the output file before
+    returning
+  * update bundled dependencies to their latest patch releases
+
+-------------------------------------------------------------------

Old:
----
  thin-provisioning-tools-1.3.2.tar.zst

New:
----
  thin-provisioning-tools-1.3.3.tar.zst

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ thin-provisioning-tools.spec ++++++
--- /var/tmp/diff_new_pack.hqtihR/_old  2026-06-25 10:52:07.950837171 +0200
+++ /var/tmp/diff_new_pack.hqtihR/_new  2026-06-25 10:52:07.954837310 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           thin-provisioning-tools
-Version:        1.3.2
+Version:        1.3.3
 Release:        0
 Summary:        Thin Provisioning Tools
 License:        GPL-3.0-only
@@ -26,9 +26,9 @@
 Source1:        vendor.tar.zst
 BuildRequires:  cargo-packaging
 BuildRequires:  clang-devel
-BuildRequires:  device-mapper-devel
 BuildRequires:  pkgconfig
 BuildRequires:  suse-module-tools
+BuildRequires:  pkgconfig(devmapper)
 BuildRequires:  pkgconfig(libudev)
 Requires(post): coreutils
 Requires(postun): coreutils

++++++ _service ++++++
--- /var/tmp/diff_new_pack.hqtihR/_old  2026-06-25 10:52:08.006839111 +0200
+++ /var/tmp/diff_new_pack.hqtihR/_new  2026-06-25 10:52:08.014839388 +0200
@@ -6,7 +6,7 @@
     <param name="match-tag">*</param>
     <param name="versionrewrite-pattern">v(.*)</param>
     <param name="changesgenerate">enable</param>
-    <param name="revision">refs/tags/v1.3.2</param>
+    <param name="revision">refs/tags/v1.3.3</param>
   </service>
   <service mode="manual" name="tar" />
   <service mode="manual" name="recompress">

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.hqtihR/_old  2026-06-25 10:52:08.058840911 +0200
+++ /var/tmp/diff_new_pack.hqtihR/_new  2026-06-25 10:52:08.066841188 +0200
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param 
name="url">https://github.com/jthornber/thin-provisioning-tools.git</param>
-              <param 
name="changesrevision">c4deedacca13184f5bd5438c259fae581fbaf966</param></service></servicedata>
+              <param 
name="changesrevision">b61de422f87f06ca7526d0b378de4412ad2c760c</param></service></servicedata>
 (No newline at EOF)
 

++++++ thin-provisioning-tools-1.3.2.tar.zst -> 
thin-provisioning-tools-1.3.3.tar.zst ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thin-provisioning-tools-1.3.2/CHANGES 
new/thin-provisioning-tools-1.3.3/CHANGES
--- old/thin-provisioning-tools-1.3.2/CHANGES   2026-04-27 20:47:37.000000000 
+0200
+++ new/thin-provisioning-tools-1.3.3/CHANGES   2026-06-22 11:47:10.000000000 
+0200
@@ -1,3 +1,11 @@
+v1.3.3
+======
+
+- Fix missing era array traversal in era_invalidate when no writesets exist
+- Fix panics in thin_explore when navigating empty btrees
+- Ensure data consistency by flushing the output file when closing
+  thin_metadata_pack and thin_metadata_unpack.
+
 v1.3.2
 ======
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thin-provisioning-tools-1.3.2/Cargo.lock 
new/thin-provisioning-tools-1.3.3/Cargo.lock
--- old/thin-provisioning-tools-1.3.2/Cargo.lock        2026-04-27 
20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/Cargo.lock        2026-06-22 
11:47:10.000000000 +0200
@@ -75,9 +75,18 @@
 
 [[package]]
 name = "anyhow"
-version = "1.0.100"
+version = "1.0.102"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
+checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
+
+[[package]]
+name = "approx"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
+dependencies = [
+ "num-traits",
+]
 
 [[package]]
 name = "autocfg"
@@ -113,9 +122,9 @@
 
 [[package]]
 name = "bitflags"
-version = "2.10.0"
+version = "2.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
+checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
 
 [[package]]
 name = "bumpalo"
@@ -124,6 +133,12 @@
 checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
 
 [[package]]
+name = "by_address"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06"
+
+[[package]]
 name = "bytemuck"
 version = "1.24.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
@@ -166,6 +181,17 @@
 checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
 
 [[package]]
+name = "chacha20"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "rand_core 0.10.1",
+]
+
+[[package]]
 name = "clang-sys"
 version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
@@ -178,18 +204,18 @@
 
 [[package]]
 name = "clap"
-version = "4.5.52"
+version = "4.5.61"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "aa8120877db0e5c011242f96806ce3c94e0737ab8108532a76a3300a01db2ab8"
+checksum = "52fa72306bb30daf11bc97773431628e5b4916e97aaa74b7d3f625d4d495da02"
 dependencies = [
  "clap_builder",
 ]
 
 [[package]]
 name = "clap_builder"
-version = "4.5.52"
+version = "4.5.61"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "02576b399397b659c26064fbc92a75fede9d18ffd5f80ca1cd74ddab167016e1"
+checksum = "2071365c5c56eae7d77414029dde2f4f4ba151cf68d5a3261c9a40de428ace93"
 dependencies = [
  "anstyle",
  "clap_lex",
@@ -198,9 +224,9 @@
 
 [[package]]
 name = "clap_lex"
-version = "0.7.6"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
+checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
 
 [[package]]
 name = "colorchoice"
@@ -236,6 +262,15 @@
 ]
 
 [[package]]
+name = "cpufeatures"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
+dependencies = [
+ "libc",
+]
+
+[[package]]
 name = "crc32c"
 version = "0.6.8"
 source = "registry+https://github.com/rust-lang/crates.io-index";
@@ -305,18 +340,17 @@
 
 [[package]]
 name = "devicemapper"
-version = "0.34.5"
+version = "0.34.7"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "f8ca2baf05e507adafc3524fb687aa15f2f9953de808c6a4cbd57a7f2e5aa883"
+checksum = "607791a4633fca6e032a66614f4fe96a721dd8641ebe98438283e53d361503cd"
 dependencies = [
  "bitflags",
  "cfg-if",
  "devicemapper-sys",
- "env_logger 0.11.8",
+ "env_logger",
  "log",
  "nix",
- "once_cell",
- "rand 0.9.4",
+ "rand 0.10.1",
  "retry",
  "semver",
  "serde",
@@ -374,16 +408,6 @@
 
 [[package]]
 name = "env_logger"
-version = "0.8.4"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
-dependencies = [
- "log",
- "regex",
-]
-
-[[package]]
-name = "env_logger"
 version = "0.11.8"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f"
@@ -418,6 +442,12 @@
 checksum = "de853764b47027c2e862a995c34978ffa63c1501f2e15f987ba11bd4f9bba193"
 
 [[package]]
+name = "fast-srgb8"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1"
+
+[[package]]
 name = "fastrand"
 version = "2.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
@@ -431,9 +461,9 @@
 
 [[package]]
 name = "flate2"
-version = "1.1.5"
+version = "1.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb"
+checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
 dependencies = [
  "crc32fast",
  "miniz_oxide",
@@ -459,25 +489,26 @@
 
 [[package]]
 name = "getrandom"
-version = "0.2.16"
+version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
+checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
 dependencies = [
  "cfg-if",
  "libc",
- "wasi",
+ "r-efi 5.3.0",
+ "wasip2",
 ]
 
 [[package]]
 name = "getrandom"
-version = "0.3.4"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
+checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
 dependencies = [
  "cfg-if",
  "libc",
- "r-efi",
- "wasip2",
+ "r-efi 6.0.0",
+ "rand_core 0.10.1",
 ]
 
 [[package]]
@@ -498,6 +529,17 @@
 ]
 
 [[package]]
+name = "hashbrown"
+version = "0.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
+dependencies = [
+ "allocator-api2",
+ "equivalent",
+ "foldhash",
+]
+
+[[package]]
 name = "heck"
 version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
@@ -523,9 +565,9 @@
 
 [[package]]
 name = "indicatif"
-version = "0.18.3"
+version = "0.18.4"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "9375e112e4b463ec1b1c6c011953545c65a30164fbab5b581df32b3abf0dcb88"
+checksum = "25470f23803092da7d239834776d653104d551bc4d7eacaf31e6837854b8e9eb"
 dependencies = [
  "console",
  "portable-atomic",
@@ -569,9 +611,9 @@
 
 [[package]]
 name = "io-uring"
-version = "0.7.11"
+version = "0.7.12"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "fdd7bddefd0a8833b88a4b68f90dae22c7450d11b354198baee3874fd811b344"
+checksum = "4d09b98f7eace8982db770e4408e7470b028ce513ac28fecdc6bf4c30fe92b62"
 dependencies = [
  "bitflags",
  "cfg-if",
@@ -657,16 +699,16 @@
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "bde5057d6143cc94e861d90f591b9303d6716c6b9602309150bd068853c10899"
 dependencies = [
- "hashbrown",
+ "hashbrown 0.16.1",
  "portable-atomic",
  "thiserror",
 ]
 
 [[package]]
 name = "libc"
-version = "0.2.177"
+version = "0.2.186"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
+checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
 
 [[package]]
 name = "libloading"
@@ -679,15 +721,10 @@
 ]
 
 [[package]]
-name = "libredox"
-version = "0.1.10"
+name = "libm"
+version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"
-dependencies = [
- "bitflags",
- "libc",
- "redox_syscall",
-]
+checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
 
 [[package]]
 name = "libudev-sys"
@@ -710,9 +747,9 @@
 
 [[package]]
 name = "linux-raw-sys"
-version = "0.11.0"
+version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
+checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
 
 [[package]]
 name = "log"
@@ -722,11 +759,11 @@
 
 [[package]]
 name = "lru"
-version = "0.16.4"
+version = "0.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39"
+checksum = "8a860605968fce16869fd239cf4237a82f3ac470723415db603b0e8b6c8d4fb9"
 dependencies = [
- "hashbrown",
+ "hashbrown 0.17.1",
 ]
 
 [[package]]
@@ -779,9 +816,9 @@
 
 [[package]]
 name = "nix"
-version = "0.30.1"
+version = "0.31.3"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
+checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
 dependencies = [
  "bitflags",
  "cfg-if",
@@ -878,7 +915,31 @@
 checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
 dependencies = [
  "libc",
- "windows-sys 0.61.2",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "palette"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6"
+dependencies = [
+ "approx",
+ "fast-srgb8",
+ "libm",
+ "palette_derive",
+]
+
+[[package]]
+name = "palette_derive"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30"
+dependencies = [
+ "by_address",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -973,20 +1034,20 @@
 
 [[package]]
 name = "quickcheck"
-version = "1.0.3"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6"
+checksum = "95c589f335db0f6aaa168a7cd27b1fc6920f5e1470c804f814d9cd6e62a0f70b"
 dependencies = [
- "env_logger 0.8.4",
+ "env_logger",
  "log",
- "rand 0.8.6",
+ "rand 0.10.1",
 ]
 
 [[package]]
 name = "quickcheck_macros"
-version = "1.1.0"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "f71ee38b42f8459a88d3362be6f9b841ad2d5421844f61eb1c59c11bff3ac14a"
+checksum = "a9a28b8493dd664c8b171dd944da82d933f7d456b829bfb236738e1fe06c5ba4"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1009,13 +1070,10 @@
 checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
 
 [[package]]
-name = "rand"
-version = "0.8.6"
+name = "r-efi"
+version = "6.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
-dependencies = [
- "rand_core 0.6.4",
-]
+checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
 
 [[package]]
 name = "rand"
@@ -1028,6 +1086,17 @@
 ]
 
 [[package]]
+name = "rand"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
+dependencies = [
+ "chacha20",
+ "getrandom 0.4.3",
+ "rand_core 0.10.1",
+]
+
+[[package]]
 name = "rand_chacha"
 version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
@@ -1039,53 +1108,52 @@
 
 [[package]]
 name = "rand_core"
-version = "0.6.4"
+version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
 dependencies = [
- "getrandom 0.2.16",
+ "getrandom 0.3.4",
 ]
 
 [[package]]
 name = "rand_core"
-version = "0.9.3"
+version = "0.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
-dependencies = [
- "getrandom 0.3.4",
-]
+checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
 
 [[package]]
 name = "rangemap"
-version = "1.7.0"
+version = "1.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "acbbbbea733ec66275512d0b9694f34102e7d5406fdbe2ad8d21b28dce92887c"
+checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68"
 
 [[package]]
 name = "ratatui"
-version = "0.30.0"
+version = "0.30.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "d1ce67fb8ba4446454d1c8dbaeda0557ff5e94d39d5e5ed7f10a65eb4c8266bc"
+checksum = "3274ba0a2c5e1bcad2a2005d20f4dc59dad26b2eb0940fb094500dba4099d57d"
 dependencies = [
  "instability",
  "ratatui-core",
  "ratatui-termion",
  "ratatui-widgets",
+ "serde",
 ]
 
 [[package]]
 name = "ratatui-core"
-version = "0.1.0"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "5ef8dea09a92caaf73bff7adb70b76162e5937524058a7e5bff37869cbbec293"
+checksum = "cbb175c433c8e28a809d1f5773a2ae96e68c0ce40db865cbab1020bf33ae479c"
 dependencies = [
  "bitflags",
  "compact_str",
- "hashbrown",
- "indoc",
+ "hashbrown 0.17.1",
  "itertools 0.14.0",
  "kasuari",
  "lru",
+ "palette",
+ "serde",
  "strum",
  "thiserror",
  "unicode-segmentation",
@@ -1095,9 +1163,9 @@
 
 [[package]]
 name = "ratatui-termion"
-version = "0.1.0"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "4cade85a8591fbc911e147951422f0d6fd40f4948b271b6216c7dc01838996f8"
+checksum = "87c732202fa5a71a9da0991013f0853e53f87048f45198e3a1ca3ee722accc2f"
 dependencies = [
  "instability",
  "ratatui-core",
@@ -1106,17 +1174,18 @@
 
 [[package]]
 name = "ratatui-widgets"
-version = "0.3.0"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "d7dbfa023cd4e604c2553483820c5fe8aa9d71a42eea5aa77c6e7f35756612db"
+checksum = "66e3d19bcc9130ca376277d93b60767ff121ace3be06f5f95f81dd68956407d1"
 dependencies = [
  "bitflags",
- "hashbrown",
+ "hashbrown 0.17.1",
  "indoc",
  "instability",
  "itertools 0.14.0",
  "line-clipping",
  "ratatui-core",
+ "serde",
  "strum",
  "time",
  "unicode-segmentation",
@@ -1124,21 +1193,6 @@
 ]
 
 [[package]]
-name = "redox_syscall"
-version = "0.5.18"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "redox_termios"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "20145670ba436b55d91fc92d25e71160fbfbdd57831631c8d7d36377a476f1cb"
-
-[[package]]
 name = "regex"
 version = "1.12.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
@@ -1175,9 +1229,9 @@
 
 [[package]]
 name = "roaring"
-version = "0.11.2"
+version = "0.11.4"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "f08d6a905edb32d74a5d5737a0c9d7e950c312f3c46cb0ca0a2ca09ea11878a0"
+checksum = "1dedc5658c6ecb3bdb5ef5f3295bb9253f42dcf3fd1402c03f6b1f7659c3c4a9"
 dependencies = [
  "bytemuck",
  "byteorder",
@@ -1200,9 +1254,9 @@
 
 [[package]]
 name = "rustix"
-version = "1.1.2"
+version = "1.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
+checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
 dependencies = [
  "bitflags",
  "errno",
@@ -1236,6 +1290,7 @@
 checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
 dependencies = [
  "serde_core",
+ "serde_derive",
 ]
 
 [[package]]
@@ -1331,18 +1386,18 @@
 
 [[package]]
 name = "strum"
-version = "0.27.2"
+version = "0.28.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf"
+checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd"
 dependencies = [
  "strum_macros",
 ]
 
 [[package]]
 name = "strum_macros"
-version = "0.27.2"
+version = "0.28.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7"
+checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664"
 dependencies = [
  "heck",
  "proc-macro2",
@@ -1363,12 +1418,12 @@
 
 [[package]]
 name = "tempfile"
-version = "3.23.0"
+version = "3.27.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16"
+checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
 dependencies = [
  "fastrand",
- "getrandom 0.3.4",
+ "getrandom 0.4.3",
  "once_cell",
  "rustix",
  "windows-sys 0.61.2",
@@ -1376,14 +1431,12 @@
 
 [[package]]
 name = "termion"
-version = "4.0.5"
+version = "4.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "3669a69de26799d6321a5aa713f55f7e2cd37bd47be044b50f2acafc42c122bb"
+checksum = "f44138a9ae08f0f502f24104d82517ef4da7330c35acd638f1f29d3cd5475ecb"
 dependencies = [
  "libc",
- "libredox",
  "numtoa",
- "redox_termios",
 ]
 
 [[package]]
@@ -1394,7 +1447,7 @@
 
 [[package]]
 name = "thinp"
-version = "1.3.2"
+version = "1.3.3"
 dependencies = [
  "anyhow",
  "base64",
@@ -1432,18 +1485,18 @@
 
 [[package]]
 name = "thiserror"
-version = "2.0.17"
+version = "2.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
+checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "2.0.17"
+version = "2.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
+checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1525,12 +1578,6 @@
 checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
 
 [[package]]
-name = "wasi"
-version = "0.11.1+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
-
-[[package]]
 name = "wasip2"
 version = "1.0.1+wasi-0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index";
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thin-provisioning-tools-1.3.2/Cargo.toml 
new/thin-provisioning-tools-1.3.3/Cargo.toml
--- old/thin-provisioning-tools-1.3.2/Cargo.toml        2026-04-27 
20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/Cargo.toml        2026-06-22 
11:47:10.000000000 +0200
@@ -1,6 +1,6 @@
 [package]
 name = "thinp"
-version = "1.3.2"
+version = "1.3.3"
 authors = ["Joe Thornber <[email protected]>"]
 edition = "2021"
 license = "GPL-3.0-only"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thin-provisioning-tools-1.3.2/src/cache/check.rs 
new/thin-provisioning-tools-1.3.3/src/cache/check.rs
--- old/thin-provisioning-tools-1.3.2/src/cache/check.rs        2026-04-27 
20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/src/cache/check.rs        2026-06-22 
11:47:10.000000000 +0200
@@ -321,8 +321,8 @@
                     metadata_sm.clone(),
                     opts.ignore_non_fatal,
                 )?;
-                if err.is_some() {
-                    ctx.report.fatal(&format!("{}", err.unwrap()));
+                if let Some(e) = err {
+                    ctx.report.fatal(&format!("{}", e));
                 }
                 let c = format2::MappingChecker::new(nr_origin_blocks, 
dirty_bits);
                 if let Err(e) = w.walk(&c, sb.mapping_root) {
@@ -357,8 +357,8 @@
             metadata_sm.clone(),
             opts.ignore_non_fatal,
         )?;
-        if err.is_some() {
-            ctx.report.fatal(&format!("{}", err.unwrap()));
+        if let Some(e) = err {
+            ctx.report.fatal(&format!("{}", e));
         }
     }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thin-provisioning-tools-1.3.2/src/cache/dump.rs 
new/thin-provisioning-tools-1.3.3/src/cache/dump.rs
--- old/thin-provisioning-tools-1.3.2/src/cache/dump.rs 2026-04-27 
20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/src/cache/dump.rs 2026-06-22 
11:47:10.000000000 +0200
@@ -205,8 +205,10 @@
     let dirty_bits = if let Some(root) = dirty_root {
         let (bits, errs) =
             read_bitset_checked(engine.as_ref(), root, cache_blocks as usize, 
repair);
-        if errs.is_some() && !repair {
-            return Err(anyhow!("errors in bitset {}", errs.unwrap()));
+        if let Some(e) = errs {
+            if !repair {
+                return Err(anyhow!("errors in bitset {}", e));
+            }
         }
         bits
     } else {
@@ -368,8 +370,8 @@
     let ctx = mk_context(&opts)?;
     let sb = read_superblock(ctx.engine.as_ref(), SUPERBLOCK_LOCATION)?;
 
-    let writer: Box<dyn Write> = if opts.output.is_some() {
-        let f = File::create(opts.output.unwrap()).context(OutputError)?;
+    let writer: Box<dyn Write> = if let Some(output) = opts.output {
+        let f = File::create(output).context(OutputError)?;
         Box::new(BufWriter::new(f))
     } else {
         Box::new(BufWriter::new(std::io::stdout()))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/thin-provisioning-tools-1.3.2/src/cache/metadata_generator.rs 
new/thin-provisioning-tools-1.3.3/src/cache/metadata_generator.rs
--- old/thin-provisioning-tools-1.3.2/src/cache/metadata_generator.rs   
2026-04-27 20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/src/cache/metadata_generator.rs   
2026-06-22 11:47:10.000000000 +0200
@@ -105,7 +105,7 @@
         for (oblock, cblock) in oblocks.iter().zip(cblocks.iter()) {
             maps.push((oblock, *cblock));
         }
-        maps.sort_by(|lhs, rhs| lhs.1.cmp(&rhs.1));
+        maps.sort_by_key(|lhs| lhs.1);
 
         v.mappings_b()?;
         for (oblock, cblock) in maps {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/thin-provisioning-tools-1.3.2/src/cache/superblock.rs 
new/thin-provisioning-tools-1.3.3/src/cache/superblock.rs
--- old/thin-provisioning-tools-1.3.2/src/cache/superblock.rs   2026-04-27 
20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/src/cache/superblock.rs   2026-06-22 
11:47:10.000000000 +0200
@@ -196,8 +196,8 @@
     w.write_u32::<LittleEndian>(sb.policy_version[1])?;
     w.write_u32::<LittleEndian>(sb.policy_version[2])?;
 
-    if sb.dirty_root.is_some() {
-        w.write_u64::<LittleEndian>(sb.dirty_root.unwrap())?;
+    if let Some(root) = sb.dirty_root {
+        w.write_u64::<LittleEndian>(root)?;
     }
 
     Ok(())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/thin-provisioning-tools-1.3.2/src/commands/thin_explore.rs 
new/thin-provisioning-tools-1.3.3/src/commands/thin_explore.rs
--- old/thin-provisioning-tools-1.3.2/src/commands/thin_explore.rs      
2026-04-27 20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/src/commands/thin_explore.rs      
2026-06-22 11:47:10.000000000 +0200
@@ -121,31 +121,23 @@
 //------------------------------------
 
 fn ls_next(ls: &mut ListState, max: usize) {
+    if max == 0 {
+        return;
+    }
+
     let i = match ls.selected() {
-        Some(i) => {
-            if i >= max - 1 {
-                max - 1
-            } else {
-                i + 1
-            }
-        }
+        Some(i) => (i + 1).min(max - 1),
         None => 0,
     };
     ls.select(Some(i));
 }
 
 fn ls_previous(ls: &mut ListState) {
-    let i = match ls.selected() {
-        Some(i) => {
-            if i == 0 {
-                0
-            } else {
-                i - 1
-            }
+    if let Some(i) = ls.selected() {
+        if i > 0 {
+            ls.select(Some(i - 1));
         }
-        None => 0,
-    };
-    ls.select(Some(i));
+    }
 }
 
 //------------------------------------
@@ -444,24 +436,17 @@
         };
         hdr.render(chunks[0], buf);
 
-        let items: Vec<ListItem>;
-        let i: usize;
-        let selected = state.selected().unwrap();
+        let selected = state.selected().unwrap_or(0);
         let mut state = ListState::default();
 
-        match self.node {
-            btree::Node::Internal { keys, values, .. } => {
-                let (items_, i_) = mk_items(keys, values, selected);
-                items = items_;
-                i = i_;
-            }
-            btree::Node::Leaf { keys, values, .. } => {
-                let (items_, i_) = mk_items(keys, values, selected);
-                items = items_;
-                i = i_;
-            }
+        let (items, i) = match self.node {
+            btree::Node::Internal { keys, values, .. } => mk_items(keys, 
values, selected),
+            btree::Node::Leaf { keys, values, .. } => mk_items(keys, values, 
selected),
+        };
+
+        if !items.is_empty() {
+            state.select(Some(i));
         }
-        state.select(Some(i));
 
         let items = List::new(items)
             .block(Block::default().borders(Borders::ALL).title("Entries"))
@@ -559,7 +544,10 @@
     fn new(node: btree::Node<DeviceDetail>) -> DeviceDetailPanel {
         let nr_entries = node.get_header().nr_entries as usize;
         let mut state = ListState::default();
-        state.select(Some(0));
+
+        if nr_entries > 0 {
+            state.select(Some(0));
+        }
 
         DeviceDetailPanel {
             node,
@@ -629,7 +617,10 @@
     fn new(node: btree::Node<u64>) -> TopLevelPanel {
         let nr_entries = node.get_header().nr_entries as usize;
         let mut state = ListState::default();
-        state.select(Some(0));
+
+        if nr_entries > 0 {
+            state.select(Some(0));
+        }
 
         TopLevelPanel {
             node,
@@ -663,11 +654,10 @@
                 btree::Node::Internal { values, .. } => {
                     Some(PushTopLevel(values[self.state.selected().unwrap()]))
                 }
-                btree::Node::Leaf { values, keys, .. } => {
-                    let index = self.state.selected().unwrap();
-
-                    Some(PushBottomLevel(keys[index] as u32, values[index]))
-                }
+                btree::Node::Leaf { values, keys, .. } => self
+                    .state
+                    .selected()
+                    .map(|index| PushBottomLevel(keys[index] as u32, 
values[index])),
             },
             Key::Char('h') | Key::Left => Some(PopPanel),
             _ => None,
@@ -711,7 +701,10 @@
     fn new(thin_id: u32, node: btree::Node<BlockTime>) -> BottomLevelPanel {
         let nr_entries = node.get_header().nr_entries as usize;
         let mut state = ListState::default();
-        state.select(Some(0));
+
+        if nr_entries > 0 {
+            state.select(Some(0));
+        }
 
         BottomLevelPanel {
             thin_id,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thin-provisioning-tools-1.3.2/src/commands/utils.rs 
new/thin-provisioning-tools-1.3.3/src/commands/utils.rs
--- old/thin-provisioning-tools-1.3.2/src/commands/utils.rs     2026-04-27 
20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/src/commands/utils.rs     2026-06-22 
11:47:10.000000000 +0200
@@ -25,14 +25,14 @@
 
     fn from_str(s: &str) -> Result<Self, Self::Err> {
         let mut iter = s.split("..");
-        let start = iter.next().map_or_else(
-            || Err(anyhow!("badly formed region")),
-            |s| s.parse::<u64>().map_err(|e| e.into()),
-        )?;
-        let end = iter.next().map_or_else(
-            || Err(anyhow!("badly formed region")),
-            |s| s.parse::<u64>().map_err(|e| e.into()),
-        )?;
+        let start = iter
+            .next()
+            .ok_or_else(|| anyhow!("badly formed region"))?
+            .parse::<u64>()?;
+        let end = iter
+            .next()
+            .ok_or_else(|| anyhow!("badly formed region"))?
+            .parse::<u64>()?;
         if iter.next().is_some() {
             return Err(anyhow!("badly formed region"));
         }
@@ -134,13 +134,9 @@
 }
 
 pub fn yes_no_prompt(report: &Report, prompt: &str) -> Result<bool> {
-    report
-        .get_prompt_input(&format!("{} [y/n]: ", prompt))
-        .map(|input| {
-            let input = input.trim_end().to_lowercase();
-            input.eq("yes") || input.eq("y")
-        })
-        .map_err(|e| e.into())
+    let input = report.get_prompt_input(&format!("{} [y/n]: ", prompt))?;
+    let input = input.trim_end().to_lowercase();
+    Ok(input == "yes" || input == "y")
 }
 
 /// Reads the start of the file to see if it's a metadata.
@@ -164,10 +160,8 @@
         let root_cause = e.root_cause();
         let is_broken_pipe = root_cause
             .downcast_ref::<Arc<std::io::Error>>() // quick_xml::Error::Io 
wraps io::Error in Arc
-            .map_or_else(
-                || root_cause.downcast_ref::<std::io::Error>(),
-                |err| Some(err.as_ref()),
-            )
+            .map(|err| err.as_ref())
+            .or_else(|| root_cause.downcast_ref::<std::io::Error>())
             .is_some_and(|err| err.kind() == std::io::ErrorKind::BrokenPipe);
 
         if !is_broken_pipe {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thin-provisioning-tools-1.3.2/src/copier/batcher.rs 
new/thin-provisioning-tools-1.3.3/src/copier/batcher.rs
--- old/thin-provisioning-tools-1.3.2/src/copier/batcher.rs     2026-04-27 
20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/src/copier/batcher.rs     2026-06-22 
11:47:10.000000000 +0200
@@ -46,7 +46,7 @@
 
         // We sort by the destination since this is likely to be a spindle
         // and keeping the io in sequential order will help performance.
-        ops.sort_by(|lhs, rhs| lhs.dst.cmp(&rhs.dst));
+        ops.sort_by_key(|lhs| lhs.dst);
         self.tx
             .send(ops)
             .map_err(|_| anyhow!("unable to send copy op array"))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/thin-provisioning-tools-1.3.2/src/copier/sync_copier/tests.rs 
new/thin-provisioning-tools-1.3.3/src/copier/sync_copier/tests.rs
--- old/thin-provisioning-tools-1.3.2/src/copier/sync_copier/tests.rs   
2026-04-27 20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/src/copier/sync_copier/tests.rs   
2026-06-22 11:47:10.000000000 +0200
@@ -363,10 +363,8 @@
     assert_eq!(stats.read_errors.len(), ops.len());
     assert!(stats.write_errors.is_empty());
 
-    ops.sort_unstable_by(|lhs, rhs| lhs.src.cmp(&rhs.src));
-    stats
-        .read_errors
-        .sort_unstable_by(|lhs, rhs| lhs.src.cmp(&rhs.src));
+    ops.sort_unstable_by_key(|lhs| lhs.src);
+    stats.read_errors.sort_unstable_by_key(|lhs| lhs.src);
     assert_eq!(ops, stats.read_errors);
 
     t.verify(&ops)
@@ -388,10 +386,8 @@
     assert!(stats.read_errors.is_empty());
     assert_eq!(stats.write_errors.len(), ops.len());
 
-    ops.sort_unstable_by(|lhs, rhs| lhs.src.cmp(&rhs.src));
-    stats
-        .write_errors
-        .sort_unstable_by(|lhs, rhs| lhs.src.cmp(&rhs.src));
+    ops.sort_unstable_by_key(|lhs| lhs.src);
+    stats.write_errors.sort_unstable_by_key(|lhs| lhs.src);
     assert_eq!(ops, stats.write_errors);
 
     t.verify(&ops)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/thin-provisioning-tools-1.3.2/src/copier/sync_copier.rs 
new/thin-provisioning-tools-1.3.3/src/copier/sync_copier.rs
--- old/thin-provisioning-tools-1.3.2/src/copier/sync_copier.rs 2026-04-27 
20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/src/copier/sync_copier.rs 2026-06-22 
11:47:10.000000000 +0200
@@ -137,7 +137,7 @@
         }
 
         // sort by block_begin so the IO will be ordered.
-        reads.sort_by(|lhs, rhs| lhs.block_begin.cmp(&rhs.block_begin));
+        reads.sort_by_key(|lhs| lhs.block_begin);
 
         // Aggregate adjacent io
         let reads = aggregate_ops(&reads);
@@ -202,7 +202,7 @@
         }
 
         // sort by block_begin so the IO will be ordered.
-        writes.sort_by(|lhs, rhs| lhs.block_begin.cmp(&rhs.block_begin));
+        writes.sort_by_key(|lhs| lhs.block_begin);
 
         // Aggregate adjacent io
         let writes = aggregate_ops(&writes);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thin-provisioning-tools-1.3.2/src/era/check.rs 
new/thin-provisioning-tools-1.3.3/src/era/check.rs
--- old/thin-provisioning-tools-1.3.2/src/era/check.rs  2026-04-27 
20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/src/era/check.rs  2026-06-22 
11:47:10.000000000 +0200
@@ -123,8 +123,8 @@
             metadata_sm.clone(),
             opts.ignore_non_fatal,
         )?;
-        if err.is_some() {
-            ctx.report.fatal(&format!("{}", err.unwrap()));
+        if let Some(e) = err {
+            ctx.report.fatal(&format!("{}", e));
             fatal = true;
         }
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thin-provisioning-tools-1.3.2/src/era/dump.rs 
new/thin-provisioning-tools-1.3.3/src/era/dump.rs
--- old/thin-provisioning-tools-1.3.2/src/era/dump.rs   2026-04-27 
20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/src/era/dump.rs   2026-06-22 
11:47:10.000000000 +0200
@@ -458,8 +458,8 @@
     let ctx = mk_context(&opts)?;
     let sb = read_superblock(ctx.engine.as_ref(), SUPERBLOCK_LOCATION)?;
 
-    let writer: Box<dyn Write> = if opts.output.is_some() {
-        let f = File::create(opts.output.unwrap()).context(OutputError)?;
+    let writer: Box<dyn Write> = if let Some(output) = opts.output {
+        let f = File::create(output).context(OutputError)?;
         Box::new(BufWriter::new(f))
     } else {
         Box::new(BufWriter::new(std::io::stdout()))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thin-provisioning-tools-1.3.2/src/era/invalidate.rs 
new/thin-provisioning-tools-1.3.3/src/era/invalidate.rs
--- old/thin-provisioning-tools-1.3.2/src/era/invalidate.rs     2026-04-27 
20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/src/era/invalidate.rs     2026-06-22 
11:47:10.000000000 +0200
@@ -140,12 +140,13 @@
     }
 
     if let Some(archived_begin) = wsets.keys().next() {
-        if *archived_begin as u32 > threshold {
-            marked_bits =
-                collate_era_array(engine.clone(), sb.era_array_root, 
marked_bits, threshold)?;
+        if *archived_begin as u32 <= threshold {
+            return Ok(marked_bits);
         }
     }
 
+    marked_bits = collate_era_array(engine.clone(), sb.era_array_root, 
marked_bits, threshold)?;
+
     Ok(marked_bits)
 }
 
@@ -254,8 +255,8 @@
         read_superblock(ctx.engine.as_ref(), SUPERBLOCK_LOCATION)?
     };
 
-    let w: Box<dyn Write> = if opts.output.is_some() {
-        Box::new(BufWriter::new(File::create(opts.output.unwrap())?))
+    let w: Box<dyn Write> = if let Some(output) = opts.output {
+        Box::new(BufWriter::new(File::create(output)?))
     } else {
         Box::new(BufWriter::new(std::io::stdout()))
     };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thin-provisioning-tools-1.3.2/src/pack/toplevel.rs 
new/thin-provisioning-tools-1.3.3/src/pack/toplevel.rs
--- old/thin-provisioning-tools-1.3.2/src/pack/toplevel.rs      2026-04-27 
20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/src/pack/toplevel.rs      2026-06-22 
11:47:10.000000000 +0200
@@ -96,6 +96,9 @@
     for t in threads {
         t.join().unwrap()?;
     }
+
+    sync_output.lock().unwrap().sync_all()?;
+
     Ok(())
 }
 
@@ -309,5 +312,8 @@
     for t in threads {
         t.join().unwrap()?;
     }
+
+    output.lock().unwrap().sync_all()?;
+
     Ok(())
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/thin-provisioning-tools-1.3.2/src/pdata/space_map/aggregator_load.rs 
new/thin-provisioning-tools-1.3.3/src/pdata/space_map/aggregator_load.rs
--- old/thin-provisioning-tools-1.3.2/src/pdata/space_map/aggregator_load.rs    
2026-04-27 20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/src/pdata/space_map/aggregator_load.rs    
2026-06-22 11:47:10.000000000 +0200
@@ -159,8 +159,9 @@
                     }
                     let bitmap = bitmap.unwrap();
 
-                    let mut blocknr = block_index * ENTRIES_PER_BITMAP as u64;
-                    for e in bitmap.entries.iter() {
+                    for (blocknr, e) in
+                        (block_index * ENTRIES_PER_BITMAP as 
u64..).zip(bitmap.entries.iter())
+                    {
                         match e {
                             BitmapEntry::Small(count) => {
                                 if *count > 0 {
@@ -172,7 +173,6 @@
                                 // We'll handle this in the next step
                             }
                         }
-                        blocknr += 1;
                     }
                     self.flush_batch();
                 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/thin-provisioning-tools-1.3.2/src/pdata/space_map/repairer.rs 
new/thin-provisioning-tools-1.3.3/src/pdata/space_map/repairer.rs
--- old/thin-provisioning-tools-1.3.2/src/pdata/space_map/repairer.rs   
2026-04-27 20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/src/pdata/space_map/repairer.rs   
2026-06-22 11:47:10.000000000 +0200
@@ -31,9 +31,8 @@
     for (i, rb) in rblocks.into_iter().enumerate() {
         if let Ok(b) = rb {
             let be = &entries[i];
-            let mut blocknr = be.blocknr;
             let mut bitmap = unpack::<Bitmap>(b.get_data())?;
-            for e in bitmap.entries.iter_mut() {
+            for (blocknr, e) in (be.blocknr..).zip(bitmap.entries.iter_mut()) {
                 if blocknr >= sm.get_nr_blocks()? {
                     break;
                 }
@@ -44,8 +43,6 @@
                         *e = BitmapEntry::Small(0);
                     }
                 }
-
-                blocknr += 1;
             }
 
             let mut out = std::io::Cursor::new(b.get_data());
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thin-provisioning-tools-1.3.2/src/thin/dump.rs 
new/thin-provisioning-tools-1.3.3/src/thin/dump.rs
--- old/thin-provisioning-tools-1.3.2/src/thin/dump.rs  2026-04-27 
20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/src/thin/dump.rs  2026-06-22 
11:47:10.000000000 +0200
@@ -409,8 +409,8 @@
 }
 
 pub fn dump(opts: ThinDumpOptions) -> Result<()> {
-    let writer: Box<dyn Write> = if opts.output.is_some() {
-        let f = File::create(opts.output.unwrap()).context(OutputError)?;
+    let writer: Box<dyn Write> = if let Some(output) = opts.output {
+        let f = File::create(output).context(OutputError)?;
         Box::new(BufWriter::new(f))
     } else {
         Box::new(BufWriter::new(std::io::stdout()))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/thin-provisioning-tools-1.3.2/src/thin/metadata_repair.rs 
new/thin-provisioning-tools-1.3.3/src/thin/metadata_repair.rs
--- old/thin-provisioning-tools-1.3.2/src/thin/metadata_repair.rs       
2026-04-27 20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/src/thin/metadata_repair.rs       
2026-06-22 11:47:10.000000000 +0200
@@ -877,8 +877,7 @@
     let transaction_id = opts
         .transaction_id
         .or_else(|| ref_sb.as_ref().map(|sb| sb.transaction_id))
-        .filter(|tid| *tid > roots.transaction_id)
-        .unwrap_or(roots.transaction_id);
+        .map_or(roots.transaction_id, |tid| tid.max(roots.transaction_id));
 
     let nr_data_blocks = opts
         .nr_data_blocks
@@ -889,8 +888,7 @@
                     .map(|root| root.nr_blocks)
             })
         })
-        .filter(|n| *n > roots.nr_data_blocks)
-        .unwrap_or(roots.nr_data_blocks);
+        .map_or(roots.nr_data_blocks, |n| n.max(roots.nr_data_blocks));
 
     // The minimal timestamp for the rebuilt superblock is the age derived
     // from the data mapping tree or the details tree, which ensures the newly
@@ -900,7 +898,7 @@
     // whenever possible.
     let time = ref_sb
         .as_ref()
-        .map_or(roots.time, |sb| std::cmp::max(sb.time, roots.time));
+        .map_or(roots.time, |sb| sb.time.max(roots.time));
 
     let sm_root = SMRoot {
         nr_blocks: nr_data_blocks,
@@ -978,15 +976,13 @@
     read_superblock(engine.as_ref(), loc)
         .and_then(|sb| is_superblock_consistent_(sb, &found_roots))
         .and_then(|sb| sb.overrides(opts))
-        .map_or_else(
-            |e| {
-                let ref_sb = e
-                    .downcast_ref::<SuperblockError>()
-                    .and_then(|err| err.failed_sb.clone());
-                rebuild_superblock(&found_roots[0], ref_sb, opts)
-            },
-            |sb| Ok(ThinSuperblock::OnDisk(sb)),
-        )
+        .map(ThinSuperblock::OnDisk)
+        .or_else(|e| {
+            let ref_sb = e
+                .downcast_ref::<SuperblockError>()
+                .and_then(|err| err.failed_sb.clone());
+            rebuild_superblock(&found_roots[0], ref_sb, opts)
+        })
 }
 
 //------------------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thin-provisioning-tools-1.3.2/src/xml.rs 
new/thin-provisioning-tools-1.3.3/src/xml.rs
--- old/thin-provisioning-tools-1.3.2/src/xml.rs        2026-04-27 
20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/src/xml.rs        2026-06-22 
11:47:10.000000000 +0200
@@ -6,10 +6,8 @@
 
 //------------------------------------------
 
-// FIXME: nasty unwraps
 pub fn string_val(kv: &Attribute) -> anyhow::Result<String> {
-    kv.unescape_value()
-        .map_or_else(|e| Err(e.into()), |s| Ok(s.as_ref().to_string()))
+    Ok(kv.unescape_value()?.as_ref().to_string())
 }
 
 fn parse_val<T>(kv: &Attribute) -> anyhow::Result<T>
@@ -17,8 +15,7 @@
     T: std::str::FromStr,
     <T as std::str::FromStr>::Err: std::error::Error + Send + Sync + 'static,
 {
-    std::str::from_utf8(kv.value.as_ref())
-        .map_or_else(|e| Err(e.into()), |s| s.parse::<T>().map_err(|e| 
e.into()))
+    Ok(std::str::from_utf8(kv.value.as_ref())?.parse::<T>()?)
 }
 
 pub fn u64_val(kv: &Attribute) -> anyhow::Result<u64> {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/thin-provisioning-tools-1.3.2/tests/era_invalidate.rs 
new/thin-provisioning-tools-1.3.3/tests/era_invalidate.rs
--- old/thin-provisioning-tools-1.3.2/tests/era_invalidate.rs   2026-04-27 
20:47:37.000000000 +0200
+++ new/thin-provisioning-tools-1.3.3/tests/era_invalidate.rs   2026-06-22 
11:47:10.000000000 +0200
@@ -4,11 +4,14 @@
 
 use common::common_args::*;
 use common::era::*;
+use common::fixture::write_file;
 use common::input_arg::*;
 use common::program::*;
 use common::target::*;
 use common::test_dir::*;
 
+use thinp::file_utils;
+
 //------------------------------------------
 
 const USAGE: &str = "List blocks that may have changed since a given era
@@ -121,6 +124,206 @@
     Ok(())
 }
 
+fn mk_no_writeset_md(td: &mut TestDir) -> Result<std::path::PathBuf> {
+    let xml = td.mk_path("meta.xml");
+    let md = td.mk_path("meta.bin");
+
+    let content = b"\
+<superblock uuid=\"\" block_size=\"128\" nr_blocks=\"16\" current_era=\"5\">
+  <era_array>
+    <era block=\"0\" era=\"1\"/>
+    <era block=\"1\" era=\"2\"/>
+    <era block=\"2\" era=\"3\"/>
+    <era block=\"3\" era=\"4\"/>
+    <era block=\"4\" era=\"5\"/>
+    <era block=\"5\" era=\"0\"/>
+    <era block=\"6\" era=\"0\"/>
+    <era block=\"7\" era=\"0\"/>
+    <era block=\"8\" era=\"0\"/>
+    <era block=\"9\" era=\"0\"/>
+    <era block=\"10\" era=\"0\"/>
+    <era block=\"11\" era=\"0\"/>
+    <era block=\"12\" era=\"0\"/>
+    <era block=\"13\" era=\"0\"/>
+    <era block=\"14\" era=\"0\"/>
+    <era block=\"15\" era=\"0\"/>
+  </era_array>
+</superblock>";
+
+    write_file(&xml, content)?;
+    let _file = file_utils::create_sized_file(&md, 4096 * 4096);
+    run_ok(era_restore_cmd(args!["-i", &xml, "-o", &md]))?;
+
+    Ok(md)
+}
+
+#[test]
+fn no_writesets_threshold_zero() -> Result<()> {
+    let mut td = TestDir::new()?;
+    let md = mk_no_writeset_md(&mut td)?;
+
+    let stdout = run_ok(era_invalidate_cmd(args![&md, "--written-since", 
"0"]))?;
+    let expected = "\
+<blocks>
+  <range begin=\"0\" end=\"16\"/>
+</blocks>";
+    assert_eq!(stdout, expected);
+
+    Ok(())
+}
+
+#[test]
+fn no_writesets_threshold_within_era_range() -> Result<()> {
+    let mut td = TestDir::new()?;
+    let md = mk_no_writeset_md(&mut td)?;
+
+    let stdout = run_ok(era_invalidate_cmd(args![&md, "--written-since", 
"3"]))?;
+    let expected = "\
+<blocks>
+  <range begin=\"2\" end=\"5\"/>
+</blocks>";
+    assert_eq!(stdout, expected);
+
+    Ok(())
+}
+
+#[test]
+fn no_writesets_threshold_above_all_eras() -> Result<()> {
+    let mut td = TestDir::new()?;
+    let md = mk_no_writeset_md(&mut td)?;
+
+    let stdout = run_ok(era_invalidate_cmd(args![&md, "--written-since", 
"6"]))?;
+    let expected = "\
+<blocks>
+</blocks>";
+    assert_eq!(stdout, expected);
+
+    Ok(())
+}
+
+// Note: use the compact writeset format (<marked>) for conciseness
+// rather than the per-bit format (<bit>) that era_dump emits.
+fn mk_writeset_md(td: &mut TestDir) -> Result<std::path::PathBuf> {
+    let xml = td.mk_path("meta.xml");
+    let md = td.mk_path("meta.bin");
+
+    let content = b"\
+<superblock uuid=\"\" block_size=\"128\" nr_blocks=\"16\" current_era=\"5\">
+  <writeset era=\"3\" nr_bits=\"16\">
+    <marked block_begin=\"0\" len=\"2\"/>
+  </writeset>
+  <writeset era=\"4\" nr_bits=\"16\">
+    <marked block_begin=\"4\" len=\"2\"/>
+  </writeset>
+  <writeset era=\"5\" nr_bits=\"16\">
+    <marked block_begin=\"8\" len=\"2\"/>
+  </writeset>
+  <era_array>
+    <era block=\"0\" era=\"0\"/>
+    <era block=\"1\" era=\"1\"/>
+    <era block=\"2\" era=\"2\"/>
+    <era block=\"3\" era=\"1\"/>
+    <era block=\"4\" era=\"0\"/>
+    <era block=\"5\" era=\"1\"/>
+    <era block=\"6\" era=\"0\"/>
+    <era block=\"7\" era=\"0\"/>
+    <era block=\"8\" era=\"2\"/>
+    <era block=\"9\" era=\"0\"/>
+    <era block=\"10\" era=\"0\"/>
+    <era block=\"11\" era=\"0\"/>
+    <era block=\"12\" era=\"2\"/>
+    <era block=\"13\" era=\"2\"/>
+    <era block=\"14\" era=\"0\"/>
+    <era block=\"15\" era=\"0\"/>
+  </era_array>
+</superblock>";
+
+    write_file(&xml, content)?;
+    let _file = file_utils::create_sized_file(&md, 4096 * 4096);
+    run_ok(era_restore_cmd(args!["-i", &xml, "-o", &md]))?;
+
+    Ok(md)
+}
+
+#[test]
+fn threshold_at_oldest_writeset() -> Result<()> {
+    let mut td = TestDir::new()?;
+    let md = mk_writeset_md(&mut td)?;
+
+    let stdout = run_ok(era_invalidate_cmd(args![&md, "--written-since", 
"3"]))?;
+    let expected = "\
+<blocks>
+  <range begin=\"0\" end=\"2\"/>
+  <range begin=\"4\" end=\"6\"/>
+  <range begin=\"8\" end=\"10\"/>
+</blocks>";
+    assert_eq!(stdout, expected);
+
+    Ok(())
+}
+
+#[test]
+fn threshold_at_newest_writeset() -> Result<()> {
+    let mut td = TestDir::new()?;
+    let md = mk_writeset_md(&mut td)?;
+
+    let stdout = run_ok(era_invalidate_cmd(args![&md, "--written-since", 
"5"]))?;
+    let expected = "\
+<blocks>
+  <range begin=\"8\" end=\"10\"/>
+</blocks>";
+    assert_eq!(stdout, expected);
+
+    Ok(())
+}
+
+#[test]
+fn threshold_below_oldest_writeset() -> Result<()> {
+    let mut td = TestDir::new()?;
+    let md = mk_writeset_md(&mut td)?;
+
+    let stdout = run_ok(era_invalidate_cmd(args![&md, "--written-since", 
"2"]))?;
+    let expected = "\
+<blocks>
+  <range begin=\"0\" end=\"3\"/>
+  <range begin=\"4\" end=\"6\"/>
+  <range begin=\"8\" end=\"10\"/>
+  <range begin=\"12\" end=\"14\"/>
+</blocks>";
+    assert_eq!(stdout, expected);
+
+    Ok(())
+}
+
+#[test]
+fn threshold_above_newest_writeset() -> Result<()> {
+    let mut td = TestDir::new()?;
+    let md = mk_writeset_md(&mut td)?;
+
+    let stdout = run_ok(era_invalidate_cmd(args![&md, "--written-since", 
"6"]))?;
+    let expected = "\
+<blocks>
+</blocks>";
+    assert_eq!(stdout, expected);
+
+    Ok(())
+}
+
+#[test]
+fn threshold_zero() -> Result<()> {
+    let mut td = TestDir::new()?;
+    let md = mk_writeset_md(&mut td)?;
+
+    let stdout = run_ok(era_invalidate_cmd(args![&md, "--written-since", 
"0"]))?;
+    let expected = "\
+<blocks>
+  <range begin=\"0\" end=\"16\"/>
+</blocks>";
+    assert_eq!(stdout, expected);
+
+    Ok(())
+}
+
 #[test]
 fn list_changes_in_metadata_snapshot() -> Result<()> {
     let mut td = TestDir::new()?;

++++++ thin-provisioning-tools.obsinfo ++++++
--- /var/tmp/diff_new_pack.hqtihR/_old  2026-06-25 10:52:08.514856704 +0200
+++ /var/tmp/diff_new_pack.hqtihR/_new  2026-06-25 10:52:08.538857536 +0200
@@ -1,5 +1,5 @@
 name: thin-provisioning-tools
-version: 1.3.2
-mtime: 1777315657
-commit: c4deedacca13184f5bd5438c259fae581fbaf966
+version: 1.3.3
+mtime: 1782121630
+commit: b61de422f87f06ca7526d0b378de4412ad2c760c
 

++++++ vendor.tar.zst ++++++
/work/SRC/openSUSE:Factory/thin-provisioning-tools/vendor.tar.zst 
/work/SRC/openSUSE:Factory/.thin-provisioning-tools.new.2088/vendor.tar.zst 
differ: char 7, line 1

Reply via email to