From 2edbe3fda4617c4e75a673bce55a53b6800c882e Mon Sep 17 00:00:00 2001 From: Martin Pfundmair Date: Fri, 6 Feb 2026 16:21:01 +0900 Subject: [PATCH 1/2] empty commit From c6a39777373b8d97ca18e680059c95cd56f85f20 Mon Sep 17 00:00:00 2001 From: Martin Pfundmair Date: Fri, 6 Feb 2026 16:21:09 +0900 Subject: [PATCH 2/2] fix: address code audit findings - Remove unused image dependency from Cargo.toml - Cache ANSI regex with LazyLock to avoid recompilation per call - Fix N+1 git calls in Split layout (2 calls -> 1) - Remove dead FIXME code in patch staging logic - Add status_message field for error display in TUI - Show commit errors in UI instead of stderr --- Cargo.lock | 560 +---------------------------------------------- Cargo.toml | 1 - src/tui/app.rs | 81 +++---- src/tui/event.rs | 6 +- src/tui/ui.rs | 6 + 5 files changed, 40 insertions(+), 614 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 11d77ad..dd5db80 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,24 +17,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "aligned" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" -dependencies = [ - "as-slice", -] - -[[package]] -name = "aligned-vec" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" -dependencies = [ - "equator", -] - [[package]] name = "allocator-api2" version = "0.2.21" @@ -103,12 +85,6 @@ version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" -[[package]] -name = "arbitrary" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" - [[package]] name = "arboard" version = "3.6.1" @@ -129,108 +105,18 @@ dependencies = [ "x11rb", ] -[[package]] -name = "arg_enum_proc_macro" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - -[[package]] -name = "as-slice" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" -dependencies = [ - "stable_deref_trait", -] - [[package]] name = "autocfg" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" -[[package]] -name = "av-scenechange" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" -dependencies = [ - "aligned", - "anyhow", - "arg_enum_proc_macro", - "arrayvec", - "log", - "num-rational", - "num-traits", - "pastey", - "rayon", - "thiserror", - "v_frame", - "y4m", -] - -[[package]] -name = "av1-grain" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" -dependencies = [ - "anyhow", - "arrayvec", - "log", - "nom", - "num-rational", - "v_frame", -] - -[[package]] -name = "avif-serialize" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47c8fbc0f831f4519fe8b810b6a7a91410ec83031b8233f730a0480029f6a23f" -dependencies = [ - "arrayvec", -] - -[[package]] -name = "bit_field" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" - [[package]] name = "bitflags" version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" -[[package]] -name = "bitstream-io" -version = "4.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60d4bd9d1db2c6bdf285e223a7fa369d5ce98ec767dec949c6ca62863ce61757" -dependencies = [ - "core2", -] - -[[package]] -name = "built" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64" - [[package]] name = "bumpalo" version = "3.19.1" @@ -270,18 +156,6 @@ dependencies = [ "rustversion", ] -[[package]] -name = "cc" -version = "1.2.52" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd4932aefd12402b36c60956a4fe0035421f544799057659ff86f923657aada3" -dependencies = [ - "find-msvc-tools", - "jobserver", - "libc", - "shlex", -] - [[package]] name = "cfg-if" version = "1.0.4" @@ -364,12 +238,6 @@ dependencies = [ "error-code", ] -[[package]] -name = "color_quant" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" - [[package]] name = "colorchoice" version = "1.0.4" @@ -399,15 +267,6 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "core2" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" -dependencies = [ - "memchr", -] - [[package]] name = "crc32fast" version = "1.5.0" @@ -525,26 +384,6 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" -[[package]] -name = "equator" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" -dependencies = [ - "equator-macro", -] - -[[package]] -name = "equator-macro" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "equivalent" version = "1.0.2" @@ -567,21 +406,6 @@ version = "3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" -[[package]] -name = "exr" -version = "1.74.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" -dependencies = [ - "bit_field", - "half", - "lebe", - "miniz_oxide", - "rayon-core", - "smallvec", - "zune-inflate", -] - [[package]] name = "fastrand" version = "2.3.0" @@ -617,12 +441,6 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "find-msvc-tools" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f449e6c6c08c865631d4890cfacf252b3d396c9bcc83adb6623cdb02a8336c41" - [[package]] name = "flate2" version = "1.1.8" @@ -661,16 +479,6 @@ dependencies = [ "wasip2", ] -[[package]] -name = "gif" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5df2ba84018d80c213569363bdcd0c64e6933c67fe4c1d60ecf822971a3c35e" -dependencies = [ - "color_quant", - "weezl", -] - [[package]] name = "git-twig" version = "1.2.6" @@ -681,7 +489,6 @@ dependencies = [ "colored", "criterion", "crossterm", - "image", "ratatui", "regex", "serde", @@ -739,38 +546,12 @@ checksum = "e6506c6c10786659413faa717ceebcb8f70731c0a60cbae39795fdf114519c1a" dependencies = [ "bytemuck", "byteorder-lite", - "color_quant", - "exr", - "gif", - "image-webp", "moxcms", "num-traits", "png", - "qoi", - "ravif", - "rayon", - "rgb", "tiff", - "zune-core 0.5.0", - "zune-jpeg 0.5.8", ] -[[package]] -name = "image-webp" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" -dependencies = [ - "byteorder-lite", - "quick-error", -] - -[[package]] -name = "imgref" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8" - [[package]] name = "indexmap" version = "2.13.0" @@ -781,17 +562,6 @@ dependencies = [ "hashbrown 0.16.1", ] -[[package]] -name = "interpolate_name" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "is-terminal" version = "0.4.17" @@ -836,31 +606,12 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" -[[package]] -name = "jobserver" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" -dependencies = [ - "getrandom", - "libc", -] - [[package]] name = "js-sys" version = "0.3.85" @@ -877,28 +628,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -[[package]] -name = "lebe" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" - [[package]] name = "libc" version = "0.2.180" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" -[[package]] -name = "libfuzzer-sys" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5037190e1f70cbeef565bd267599242926f724d3b8a9f510fd7e0b540cfa4404" -dependencies = [ - "arbitrary", - "cc", -] - [[package]] name = "linux-raw-sys" version = "0.11.0" @@ -920,15 +655,6 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" -[[package]] -name = "loop9" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" -dependencies = [ - "imgref", -] - [[package]] name = "lru" version = "0.12.5" @@ -938,16 +664,6 @@ dependencies = [ "hashbrown 0.15.5", ] -[[package]] -name = "maybe-rayon" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" -dependencies = [ - "cfg-if", - "rayon", -] - [[package]] name = "memchr" version = "2.7.6" @@ -986,68 +702,6 @@ dependencies = [ "pxfm", ] -[[package]] -name = "new_debug_unreachable" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" - -[[package]] -name = "nom" -version = "8.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" -dependencies = [ - "memchr", -] - -[[package]] -name = "noop_proc_macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -1177,12 +831,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "pastey" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" - [[package]] name = "percent-encoding" version = "2.3.2" @@ -1230,15 +878,6 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - [[package]] name = "proc-macro2" version = "1.0.105" @@ -1248,25 +887,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "profiling" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" -dependencies = [ - "profiling-procmacros", -] - -[[package]] -name = "profiling-procmacros" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" -dependencies = [ - "quote", - "syn", -] - [[package]] name = "pxfm" version = "0.1.27" @@ -1276,15 +896,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "qoi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" -dependencies = [ - "bytemuck", -] - [[package]] name = "quick-error" version = "2.0.1" @@ -1306,35 +917,6 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" -[[package]] -name = "rand" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" -dependencies = [ - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" -dependencies = [ - "getrandom", -] - [[package]] name = "ratatui" version = "0.26.3" @@ -1355,56 +937,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "rav1e" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" -dependencies = [ - "aligned-vec", - "arbitrary", - "arg_enum_proc_macro", - "arrayvec", - "av-scenechange", - "av1-grain", - "bitstream-io", - "built", - "cfg-if", - "interpolate_name", - "itertools 0.14.0", - "libc", - "libfuzzer-sys", - "log", - "maybe-rayon", - "new_debug_unreachable", - "noop_proc_macro", - "num-derive", - "num-traits", - "paste", - "profiling", - "rand", - "rand_chacha", - "simd_helpers", - "thiserror", - "v_frame", - "wasm-bindgen", -] - -[[package]] -name = "ravif" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef69c1990ceef18a116855938e74793a5f7496ee907562bd0857b6ac734ab285" -dependencies = [ - "avif-serialize", - "imgref", - "loop9", - "quick-error", - "rav1e", - "rayon", - "rgb", -] - [[package]] name = "rayon" version = "1.11.0" @@ -1463,12 +995,6 @@ version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" -[[package]] -name = "rgb" -version = "0.8.52" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" - [[package]] name = "rustix" version = "1.1.3" @@ -1565,12 +1091,6 @@ dependencies = [ "unsafe-libyaml", ] -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - [[package]] name = "signal-hook" version = "0.3.18" @@ -1608,15 +1128,6 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" -[[package]] -name = "simd_helpers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" -dependencies = [ - "quote", -] - [[package]] name = "smallvec" version = "1.15.1" @@ -1633,12 +1144,6 @@ dependencies = [ "syn", ] -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - [[package]] name = "static_assertions" version = "1.1.0" @@ -1697,26 +1202,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "thiserror" -version = "2.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "tiff" version = "0.10.3" @@ -1728,7 +1213,7 @@ dependencies = [ "half", "quick-error", "weezl", - "zune-jpeg 0.4.21", + "zune-jpeg", ] [[package]] @@ -1782,17 +1267,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" -[[package]] -name = "v_frame" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" -dependencies = [ - "aligned-vec", - "num-traits", - "wasm-bindgen", -] - [[package]] name = "walkdir" version = "2.5.0" @@ -2087,12 +1561,6 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" -[[package]] -name = "y4m" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" - [[package]] name = "zerocopy" version = "0.8.33" @@ -2125,35 +1593,11 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" -[[package]] -name = "zune-core" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "111f7d9820f05fd715df3144e254d6fc02ee4088b0644c0ffd0efc9e6d9d2773" - -[[package]] -name = "zune-inflate" -version = "0.2.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" -dependencies = [ - "simd-adler32", -] - [[package]] name = "zune-jpeg" version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" dependencies = [ - "zune-core 0.4.12", -] - -[[package]] -name = "zune-jpeg" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e35aee689668bf9bd6f6f3a6c60bb29ba1244b3b43adfd50edd554a371da37d5" -dependencies = [ - "zune-core 0.5.0", + "zune-core", ] diff --git a/Cargo.toml b/Cargo.toml index 618968d..d4e6f04 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,6 @@ homepage = "https://martinp7r.github.io/git-twig/" clap = { version = "4.5", features = ["derive"] } colored = "2.1" anyhow = "1.0" -image = "0.25.9" ratatui = "0.26" crossterm = "0.27" diff --git a/src/tui/app.rs b/src/tui/app.rs index eb086db..999ae45 100644 --- a/src/tui/app.rs +++ b/src/tui/app.rs @@ -1,6 +1,7 @@ use anyhow::{Context, Result}; use ratatui::widgets::ListState; use std::collections::HashSet; +use std::sync::LazyLock; use unicode_width::UnicodeWidthStr; use crate::cache::GitCache; @@ -123,6 +124,8 @@ pub struct App { pub selected_hunk_idx: Option, // Performance: centralized git data cache pub cache: GitCache, + // Status message (errors, confirmations) + pub status_message: Option, } impl App { @@ -173,6 +176,7 @@ impl App { diff_hunks: Vec::new(), selected_hunk_idx: None, cache: GitCache::new(), + status_message: None, }; app.refresh()?; Ok(app) @@ -194,7 +198,7 @@ impl App { pub fn refresh(&mut self) -> Result<()> { // Track the last collected stats to avoid redundant git calls - let mut last_stats; + let last_stats; match self.layout { AppLayout::Unified | AppLayout::EasterEgg => { @@ -227,25 +231,9 @@ impl App { Self::adjust_selection(&self.unified_nodes, &mut self.unified_state, true); } AppLayout::Split => { - let (staged_tree, staged_stats) = git::build_tree_from_git(true, false, false)?; - if let Some(root) = staged_tree { - self.staged_nodes = root.flatten( - self.indent_size, - self.collapse, - &self.theme, - &self.collapsed_paths, - ); - } else { - self.staged_nodes = Vec::new(); - } - + // Single git call - filter results for staged/unstaged let (all_tree, all_stats) = git::build_tree_from_git(false, false, false)?; - // Use the stats from the "all" tree which has both staged and unstaged last_stats = all_stats; - // Merge in any stats from staged that might be missing (shouldn't be, but safe) - for (k, v) in staged_stats { - last_stats.entry(k).or_insert(v); - } if let Some(root) = all_tree { let all = root.flatten( @@ -254,11 +242,18 @@ impl App { &self.theme, &self.collapsed_paths, ); + // Split into staged (ends with '+') and unstaged + self.staged_nodes = all + .iter() + .filter(|n| n.raw_status.ends_with('+')) + .cloned() + .collect(); self.unstaged_nodes = all .into_iter() .filter(|n| !n.raw_status.ends_with('+')) .collect(); } else { + self.staged_nodes = Vec::new(); self.unstaged_nodes = Vec::new(); } @@ -914,6 +909,14 @@ impl App { Ok(()) } + pub fn set_error(&mut self, message: String) { + self.status_message = Some(message); + } + + pub fn clear_status(&mut self) { + self.status_message = None; + } + pub fn toggle_patch_mode(&mut self) { if self.view_mode != ViewMode::Diff { return; @@ -967,43 +970,13 @@ impl App { pub fn stage_hunk(&mut self) -> Result<()> { if let Some(i) = self.selected_hunk_idx { if let Some(hunk) = self.diff_hunks.get(i) { - let _is_staged = if let Some(_idx) = self.unified_state.selected() { - // This is tricky: we need to know if the CURRENT file is staged or not - // But patch mode is generic. - // Generally, if we are in Diff view, we are diffing a specific file node. - // And we know the status of that node. - // We should pass 'stage' boolean direction. - // However, git apply --cached applies TO the index (staging it). - // git apply --reverse --cached would UNSTAGE it. - // We need to know if we are 'Adding' or 'Resetting'. - // Let's rely on the raw_status of the selected node. - false // FIXME: Logic needed below - } else { - false - }; - - // For now, let's assume this is mostly for STAGING (add -p). - // But unstage -p is also valid. - // We need to look up the node again. - // This is slightly inefficient but safe. - let node = self.get_selected_node(); if let Some(n) = node { let is_staged = n.raw_status.contains('+'); if is_staged { - // Unstage: git apply --cached --reverse - // Not implemented in helper yet, but we can just use `git restore --patch`? - // Or update apply_patch to support reverse. - // Let's update apply_patch first. - // For now, let's just support Staging (add -p equivalent). - // If user tries to stage checks on a staged file, it does nothing or errors. - - // Actually, apply_patch takes 'headers'. - // If we are unstaging, we might need --reverse. - // Let's start with just handling Staging for v1.3.0 scope if complex. - // roadmap says "Interactive Patch Staging". - - git::patch::apply_patch(&self.diff_headers, hunk, true)?; + // Unstage: would need `git apply --cached --reverse` + // Not implemented yet - skip for staged files + return Ok(()); } else { // Stage: git apply --cached git::patch::apply_patch(&self.diff_headers, hunk, true)?; @@ -1223,9 +1196,11 @@ impl App { } } +static ANSI_RE: LazyLock = + LazyLock::new(|| regex::Regex::new(r"\x1B\[[0-9;]*[mK]").unwrap()); + fn strip_ansi_codes(s: &str) -> String { - let re = regex::Regex::new(r"\x1B\[[0-9;]*[mK]").unwrap(); - re.replace_all(s, "").to_string() + ANSI_RE.replace_all(s, "").to_string() } #[cfg(test)] diff --git a/src/tui/event.rs b/src/tui/event.rs index 35c7026..eed5b6a 100644 --- a/src/tui/event.rs +++ b/src/tui/event.rs @@ -12,6 +12,9 @@ pub fn run_app(terminal: &mut Terminal>, app: &mut App) if event::poll(std::time::Duration::from_millis(100))? { if let Event::Key(key) = event::read()? { + // Clear any previous status/error message on new input + app.clear_status(); + if app.show_commit_dialog { match key.code { KeyCode::Char(c) => { @@ -25,8 +28,7 @@ pub fn run_app(terminal: &mut Terminal>, app: &mut App) } KeyCode::Enter => { if let Err(e) = app.confirm_commit() { - // TODO: Show error - eprintln!("Error committing: {}", e); + app.set_error(format!("Commit failed: {}", e)); } } _ => {} diff --git a/src/tui/ui.rs b/src/tui/ui.rs index 8fd1a8f..0655639 100644 --- a/src/tui/ui.rs +++ b/src/tui/ui.rs @@ -450,6 +450,12 @@ fn render_bottom_bar(f: &mut Frame, app: &App, area: Rect) { area.y + 1, ); } + } else if let Some(ref error) = app.status_message { + // Show error/status message + let p = Paragraph::new(error.as_str()) + .style(Style::default().fg(Color::Red)) + .block(Block::default().borders(Borders::ALL).title(" Error ")); + f.render_widget(p, area); } else { let (added, deleted) = app.global_stats.unwrap_or((0, 0)); let total = added + deleted;