diff --git a/Cargo.lock b/Cargo.lock index 45b33e0a0e..8d3994305d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,6 +46,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", + "getrandom 0.2.15", "once_cell", "version_check", "zerocopy", @@ -927,6 +928,15 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbd0f76e066e64fdc5631e3bb46381254deab9ef1158292f27c8c57e3bf3fe59" +[[package]] +name = "cmake" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" +dependencies = [ + "cc", +] + [[package]] name = "cocoa" version = "0.24.1" @@ -1270,6 +1280,20 @@ dependencies = [ "syn 2.0.68", ] +[[package]] +name = "dashmap" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804c8821570c3f8b70230c2ba75ffa5c0f9a4189b9a432b6656c536712acae28" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core 0.9.10", +] + [[package]] name = "deranged" version = "0.3.11" @@ -1643,6 +1667,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", + "libz-ng-sys", "miniz_oxide", ] @@ -2141,11 +2166,15 @@ dependencies = [ "dirs-next", "gitbutler-branch", "gitbutler-branch-actions", + "gitbutler-command-context", "gitbutler-diff", "gitbutler-oplog", "gitbutler-project", "gitbutler-reference", "gix", + "tracing", + "tracing-forest", + "tracing-subscriber", ] [[package]] @@ -2155,6 +2184,7 @@ dependencies = [ "anyhow", "git2", "gitbutler-project", + "gix", "itertools 0.13.0", "tracing", ] @@ -2579,49 +2609,48 @@ dependencies = [ [[package]] name = "gix" version = "0.64.0" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ - "gix-actor 0.31.5 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-attributes 0.22.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-actor 0.31.5 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-attributes 0.22.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-command", - "gix-commitgraph 0.24.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-commitgraph 0.24.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-config", "gix-credentials", "gix-date 0.9.0", "gix-diff", "gix-dir", "gix-discover 0.33.0", - "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-filter", - "gix-fs 0.11.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-glob 0.16.4 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-hashtable 0.5.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-ignore 0.11.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-index 0.33.1 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-lock 14.0.0 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-macros", + "gix-fs 0.11.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-glob 0.16.4 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-hashtable 0.5.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-ignore 0.11.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-index 0.33.1 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-lock 14.0.0 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-negotiate", - "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-odb", "gix-pack", - "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-pathspec", "gix-prompt", "gix-protocol", "gix-ref 0.45.0", "gix-refspec", "gix-revision", - "gix-revwalk 0.13.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-sec 0.10.7 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-revwalk 0.13.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-sec 0.10.7 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-submodule", - "gix-tempfile 14.0.1 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-traverse 0.39.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-tempfile 14.0.1 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-traverse 0.39.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-url", - "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-validate 0.8.5 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-worktree 0.34.1 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-validate 0.8.5 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-worktree 0.34.1 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-worktree-state", "once_cell", "smallvec", @@ -2645,11 +2674,11 @@ dependencies = [ [[package]] name = "gix-actor" version = "0.31.5" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", "gix-date 0.9.0", - "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "itoa 1.0.11", "thiserror", "winnow 0.6.16", @@ -2675,13 +2704,13 @@ dependencies = [ [[package]] name = "gix-attributes" version = "0.22.3" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", - "gix-glob 0.16.4 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-quote 0.4.12 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-glob 0.16.4 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-quote 0.4.12 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "kstring", "smallvec", "thiserror", @@ -2700,7 +2729,7 @@ dependencies = [ [[package]] name = "gix-bitmap" version = "0.2.11" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "thiserror", ] @@ -2717,7 +2746,7 @@ dependencies = [ [[package]] name = "gix-chunk" version = "0.4.8" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "thiserror", ] @@ -2725,11 +2754,11 @@ dependencies = [ [[package]] name = "gix-command" version = "0.3.8" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", - "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "shell-words", ] @@ -2750,12 +2779,12 @@ dependencies = [ [[package]] name = "gix-commitgraph" version = "0.24.3" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", - "gix-chunk 0.4.8 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-chunk 0.4.8 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "memmap2", "thiserror", ] @@ -2763,15 +2792,15 @@ dependencies = [ [[package]] name = "gix-config" version = "0.38.0" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", "gix-config-value", - "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-glob 0.16.4 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-glob 0.16.4 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-ref 0.45.0", - "gix-sec 0.10.7 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-sec 0.10.7 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "memchr", "once_cell", "smallvec", @@ -2783,11 +2812,11 @@ dependencies = [ [[package]] name = "gix-config-value" version = "0.14.7" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bitflags 2.6.0", "bstr", - "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "libc", "thiserror", ] @@ -2795,15 +2824,15 @@ dependencies = [ [[package]] name = "gix-credentials" version = "0.24.4" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", "gix-command", "gix-config-value", - "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-prompt", - "gix-sec 0.10.7 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-sec 0.10.7 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-url", "thiserror", ] @@ -2823,7 +2852,7 @@ dependencies = [ [[package]] name = "gix-date" version = "0.9.0" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", "itoa 1.0.11", @@ -2834,30 +2863,38 @@ dependencies = [ [[package]] name = "gix-diff" version = "0.44.1" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-command", + "gix-filter", + "gix-fs 0.11.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-tempfile 14.0.1 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-worktree 0.34.1 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "imara-diff", "thiserror", ] [[package]] name = "gix-dir" version = "0.6.0" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", "gix-discover 0.33.0", - "gix-fs 0.11.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-ignore 0.11.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-index 0.33.1 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-fs 0.11.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-ignore 0.11.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-index 0.33.1 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-pathspec", - "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-worktree 0.34.1 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-worktree 0.34.1 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "thiserror", ] @@ -2880,15 +2917,15 @@ dependencies = [ [[package]] name = "gix-discover" version = "0.33.0" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", "dunce", - "gix-fs 0.11.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-fs 0.11.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-ref 0.45.0", - "gix-sec 0.10.7 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-sec 0.10.7 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "thiserror", ] @@ -2910,18 +2947,19 @@ dependencies = [ [[package]] name = "gix-features" version = "0.38.2" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "crc32fast", "crossbeam-channel", "flate2", - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "libc", "once_cell", "parking_lot 0.12.3", "prodash 29.0.0", + "sha1", "sha1_smol", "thiserror", "walkdir", @@ -2930,19 +2968,19 @@ dependencies = [ [[package]] name = "gix-filter" version = "0.11.3" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", "encoding_rs", - "gix-attributes 0.22.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-attributes 0.22.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-command", - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-packetline-blocking", - "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-quote 0.4.12 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-quote 0.4.12 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "smallvec", "thiserror", ] @@ -2961,11 +2999,11 @@ dependencies = [ [[package]] name = "gix-fs" version = "0.11.2" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "fastrand 2.1.0", - "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", ] [[package]] @@ -2983,12 +3021,12 @@ dependencies = [ [[package]] name = "gix-glob" version = "0.16.4" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bitflags 2.6.0", "bstr", - "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", ] [[package]] @@ -3004,7 +3042,7 @@ dependencies = [ [[package]] name = "gix-hash" version = "0.14.2" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "faster-hex", "thiserror", @@ -3024,9 +3062,9 @@ dependencies = [ [[package]] name = "gix-hashtable" version = "0.5.2" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "hashbrown 0.14.5", "parking_lot 0.12.3", ] @@ -3047,12 +3085,12 @@ dependencies = [ [[package]] name = "gix-ignore" version = "0.11.3" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", - "gix-glob 0.16.4 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-glob 0.16.4 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "unicode-bom", ] @@ -3087,21 +3125,21 @@ dependencies = [ [[package]] name = "gix-index" version = "0.33.1" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bitflags 2.6.0", "bstr", "filetime", "fnv", - "gix-bitmap 0.2.11 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-fs 0.11.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-lock 14.0.0 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-traverse 0.39.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-validate 0.8.5 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-bitmap 0.2.11 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-fs 0.11.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-lock 14.0.0 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-traverse 0.39.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-validate 0.8.5 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "hashbrown 0.14.5", "itoa 1.0.11", "libc", @@ -3125,34 +3163,24 @@ dependencies = [ [[package]] name = "gix-lock" version = "14.0.0" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ - "gix-tempfile 14.0.1 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-tempfile 14.0.1 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "thiserror", ] -[[package]] -name = "gix-macros" -version = "0.1.5" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.68", -] - [[package]] name = "gix-negotiate" version = "0.13.2" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bitflags 2.6.0", - "gix-commitgraph 0.24.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-commitgraph 0.24.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-date 0.9.0", - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-revwalk 0.13.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-revwalk 0.13.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "smallvec", "thiserror", ] @@ -3179,15 +3207,15 @@ dependencies = [ [[package]] name = "gix-object" version = "0.42.3" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", - "gix-actor 0.31.5 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-actor 0.31.5 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-date 0.9.0", - "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-validate 0.8.5 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-validate 0.8.5 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "itoa 1.0.11", "smallvec", "thiserror", @@ -3197,17 +3225,17 @@ dependencies = [ [[package]] name = "gix-odb" version = "0.61.1" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "arc-swap", "gix-date 0.9.0", - "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-fs 0.11.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-fs 0.11.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-pack", - "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-quote 0.4.12 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-quote 0.4.12 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "parking_lot 0.12.3", "tempfile", "thiserror", @@ -3216,16 +3244,16 @@ dependencies = [ [[package]] name = "gix-pack" version = "0.51.1" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "clru", - "gix-chunk 0.4.8 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-hashtable 0.5.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-tempfile 14.0.1 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-chunk 0.4.8 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-hashtable 0.5.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-tempfile 14.0.1 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "memmap2", "parking_lot 0.12.3", "smallvec", @@ -3236,22 +3264,22 @@ dependencies = [ [[package]] name = "gix-packetline" version = "0.17.5" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", "faster-hex", - "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "thiserror", ] [[package]] name = "gix-packetline-blocking" version = "0.17.4" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", "faster-hex", - "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "thiserror", ] @@ -3271,10 +3299,10 @@ dependencies = [ [[package]] name = "gix-path" version = "0.10.9" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", - "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "home", "once_cell", "thiserror", @@ -3283,21 +3311,21 @@ dependencies = [ [[package]] name = "gix-pathspec" version = "0.7.6" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bitflags 2.6.0", "bstr", - "gix-attributes 0.22.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-attributes 0.22.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-config-value", - "gix-glob 0.16.4 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-glob 0.16.4 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "thiserror", ] [[package]] name = "gix-prompt" version = "0.8.6" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "gix-command", "gix-config-value", @@ -3309,15 +3337,15 @@ dependencies = [ [[package]] name = "gix-protocol" version = "0.45.2" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", "gix-credentials", "gix-date 0.9.0", - "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-transport", - "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "maybe-async", "thiserror", "winnow 0.6.16", @@ -3337,10 +3365,10 @@ dependencies = [ [[package]] name = "gix-quote" version = "0.4.12" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", - "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "thiserror", ] @@ -3369,18 +3397,18 @@ dependencies = [ [[package]] name = "gix-ref" version = "0.45.0" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" -dependencies = [ - "gix-actor 0.31.5 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-fs 0.11.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-lock 14.0.0 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-tempfile 14.0.1 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-validate 0.8.5 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" +dependencies = [ + "gix-actor 0.31.5 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-fs 0.11.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-lock 14.0.0 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-tempfile 14.0.1 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-validate 0.8.5 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "memmap2", "thiserror", "winnow 0.6.16", @@ -3389,12 +3417,12 @@ dependencies = [ [[package]] name = "gix-refspec" version = "0.23.1" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-revision", - "gix-validate 0.8.5 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-validate 0.8.5 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "smallvec", "thiserror", ] @@ -3402,13 +3430,13 @@ dependencies = [ [[package]] name = "gix-revision" version = "0.27.2" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", "gix-date 0.9.0", - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-revwalk 0.13.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-revwalk 0.13.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "thiserror", ] @@ -3430,13 +3458,13 @@ dependencies = [ [[package]] name = "gix-revwalk" version = "0.13.2" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ - "gix-commitgraph 0.24.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-commitgraph 0.24.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-date 0.9.0", - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-hashtable 0.5.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-hashtable 0.5.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "smallvec", "thiserror", ] @@ -3456,10 +3484,10 @@ dependencies = [ [[package]] name = "gix-sec" version = "0.10.7" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bitflags 2.6.0", - "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "libc", "windows-sys 0.52.0", ] @@ -3467,11 +3495,11 @@ dependencies = [ [[package]] name = "gix-submodule" version = "0.12.0" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", "gix-config", - "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-pathspec", "gix-refspec", "gix-url", @@ -3496,9 +3524,10 @@ dependencies = [ [[package]] name = "gix-tempfile" version = "14.0.1" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ - "gix-fs 0.11.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "dashmap", + "gix-fs 0.11.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "libc", "once_cell", "parking_lot 0.12.3", @@ -3540,19 +3569,22 @@ checksum = "f924267408915fddcd558e3f37295cc7d6a3e50f8bd8b606cee0808c3915157e" [[package]] name = "gix-trace" version = "0.1.9" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" +dependencies = [ + "tracing-core", +] [[package]] name = "gix-transport" version = "0.42.2" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", "gix-command", - "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-packetline", - "gix-quote 0.4.12 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-sec 0.10.7 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-quote 0.4.12 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-sec 0.10.7 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-url", "thiserror", ] @@ -3577,15 +3609,15 @@ dependencies = [ [[package]] name = "gix-traverse" version = "0.39.2" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bitflags 2.6.0", - "gix-commitgraph 0.24.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-commitgraph 0.24.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-date 0.9.0", - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-hashtable 0.5.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-revwalk 0.13.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-hashtable 0.5.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-revwalk 0.13.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "smallvec", "thiserror", ] @@ -3593,11 +3625,11 @@ dependencies = [ [[package]] name = "gix-url" version = "0.27.4" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", - "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "home", "thiserror", "url", @@ -3616,7 +3648,7 @@ dependencies = [ [[package]] name = "gix-utils" version = "0.1.12" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", "fastrand 2.1.0", @@ -3636,7 +3668,7 @@ dependencies = [ [[package]] name = "gix-validate" version = "0.8.5" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", "thiserror", @@ -3664,36 +3696,36 @@ dependencies = [ [[package]] name = "gix-worktree" version = "0.34.1" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", - "gix-attributes 0.22.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-fs 0.11.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-glob 0.16.4 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-ignore 0.11.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-index 0.33.1 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-validate 0.8.5 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-attributes 0.22.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-fs 0.11.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-glob 0.16.4 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-ignore 0.11.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-index 0.33.1 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-validate 0.8.5 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", ] [[package]] name = "gix-worktree-state" version = "0.11.1" -source = "git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af#d51f330e9d364c6f7b068116b59bf5c0160e47af" +source = "git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547#242fedc973c56b6c1b6f150af99dda972a67f547" dependencies = [ "bstr", - "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "gix-filter", - "gix-fs 0.11.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-glob 0.16.4 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-index 0.33.1 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", - "gix-worktree 0.34.1 (git+https://github.com/Byron/gitoxide?rev=d51f330e9d364c6f7b068116b59bf5c0160e47af)", + "gix-fs 0.11.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-glob 0.16.4 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-index 0.33.1 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", + "gix-worktree 0.34.1 (git+https://github.com/Byron/gitoxide?rev=242fedc973c56b6c1b6f150af99dda972a67f547)", "io-close", "thiserror", ] @@ -4275,6 +4307,16 @@ dependencies = [ "tiff", ] +[[package]] +name = "imara-diff" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc9da1a252bd44cd341657203722352efc9bc0c847d06ea6d2dc1cd1135e0a01" +dependencies = [ + "ahash 0.8.11", + "hashbrown 0.14.5", +] + [[package]] name = "indexmap" version = "1.9.3" @@ -4662,6 +4704,16 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "libz-ng-sys" +version = "1.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6409efc61b12687963e602df8ecf70e8ddacf95bc6576bcf16e3ac6328083c5" +dependencies = [ + "cmake", + "libc", +] + [[package]] name = "libz-sys" version = "1.1.18" @@ -6688,6 +6740,16 @@ dependencies = [ "cfg-if", "cpufeatures", "digest", + "sha1-asm", +] + +[[package]] +name = "sha1-asm" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "286acebaf8b67c1130aedffad26f594eff0c1292389158135327d2e23aed582b" +dependencies = [ + "cc", ] [[package]] @@ -7798,6 +7860,18 @@ dependencies = [ "valuable", ] +[[package]] +name = "tracing-forest" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee40835db14ddd1e3ba414292272eddde9dad04d3d4b65509656414d1c42592f" +dependencies = [ + "smallvec", + "thiserror", + "tracing", + "tracing-subscriber", +] + [[package]] name = "tracing-log" version = "0.2.0" diff --git a/Cargo.toml b/Cargo.toml index e90091d7d3..30b4c4fd5f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,8 +36,7 @@ resolver = "2" [workspace.dependencies] bstr = "1.10.0" # Add the `tracing` or `tracing-detail` features to see more of gitoxide in the logs. Useful to see which programs it invokes. -gix = { git = "https://github.com/Byron/gitoxide", rev = "d51f330e9d364c6f7b068116b59bf5c0160e47af", default-features = false, features = [ -] } +gix = { git = "https://github.com/Byron/gitoxide", rev = "242fedc973c56b6c1b6f150af99dda972a67f547", default-features = false, features = [] } git2 = { version = "0.18.3", features = [ "vendored-openssl", "vendored-libgit2", @@ -52,6 +51,8 @@ fslock = "0.2.1" parking_lot = "0.12.3" futures = "0.3.30" toml = "0.8.13" +tracing = "0.1.40" +tracing-subscriber = "0.3.17" gitbutler-id = { path = "crates/gitbutler-id" } gitbutler-git = { path = "crates/gitbutler-git" } diff --git a/crates/gitbutler-branch-actions/Cargo.toml b/crates/gitbutler-branch-actions/Cargo.toml index 193ba84416..be70d0b046 100644 --- a/crates/gitbutler-branch-actions/Cargo.toml +++ b/crates/gitbutler-branch-actions/Cargo.toml @@ -6,10 +6,10 @@ authors = ["GitButler "] publish = false [dependencies] -tracing = "0.1.40" +tracing.workspace = true anyhow = "1.0.86" git2.workspace = true -gix.workspace = true +gix = { workspace = true, features = ["blob-diff"] } tokio.workspace = true gitbutler-oplog.workspace = true gitbutler-repo.workspace = true @@ -43,7 +43,7 @@ reqwest = { version = "0.12.4", features = ["json"] } once_cell = "1.19" pretty_assertions = "1.4" gitbutler-testsupport.workspace = true -gix = { workspace = true, features = ["max-performance-safe"] } +gix = { workspace = true, features = ["max-performance"] } gitbutler-git = { workspace = true, features = ["test-askpass-path"] } glob = "0.3.1" serial_test = "3.1.1" diff --git a/crates/gitbutler-branch-actions/benches/branches.rs b/crates/gitbutler-branch-actions/benches/branches.rs index e5932a1c21..d60d023296 100644 --- a/crates/gitbutler-branch-actions/benches/branches.rs +++ b/crates/gitbutler-branch-actions/benches/branches.rs @@ -1,5 +1,5 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput}; -use gitbutler_branch_actions::list_branches; +use gitbutler_branch_actions::{get_branch_listing_details, list_branches}; use gitbutler_command_context::CommandContext; use gitbutler_project::Project; @@ -50,5 +50,74 @@ pub fn benchmark_list_branches(c: &mut Criterion) { } } -criterion_group!(benches, benchmark_list_branches); +pub fn benchmark_branch_details(c: &mut Criterion) { + for (bench_name, (repo_name, branch_name, files_to_diff, script_name)) in [ + ( + "branch-details [many branches no change]", + ("many-local", "virtual", 0, "branch-benches.sh"), + ), + ( + "branch-details [tiny no change]", + ( + "one-vbranch-on-integration-two-remotes", + "main", + 0, + "for-listing.sh", + ), + ), + ( + "branch-details [big repo no change]", + ( + "big-repo-clone", + "no-change", + 0, + "branch-details-benches.sh", + ), + ), + ( + "branch-details [every-file-changed]", + ( + "big-repo-clone-one-commit-ahead", + "change-with-new-content", + 10_000, + "branch-details-benches.sh", + ), + ), + ] { + let mut group = c.benchmark_group(bench_name); + let project = fixture_project(repo_name, script_name); + if files_to_diff != 0 { + group.throughput(Throughput::Elements(files_to_diff)); + } + group.bench_function("list details of known branch", |b| { + b.iter(|| { + let ctx = CommandContext::open(&project).unwrap(); + let details = + get_branch_listing_details(black_box(&ctx), Some(branch_name)).unwrap(); + assert_eq!(details.len(), 1, "{script_name}:{repo_name}:{branch_name}"); + assert_eq!( + details[0].number_of_files, files_to_diff as usize, + "currently it creates a new vbranch for changes in local-commits, something we leverage here" + ); + }) + }); + } + + let mut group = c.benchmark_group("branch-details [revwalk]"); + let project = fixture_project("revwalk-repo", "branch-details-benches.sh"); + group.throughput(Throughput::Elements(100 + 15 + 50)); + group.bench_function("count commits/collect authors", |b| { + b.iter(|| { + let ctx = CommandContext::open(&project).unwrap(); + let details = get_branch_listing_details( + black_box(&ctx), + ["feature", "main", "non-virtual-feature"], + ) + .unwrap(); + assert_eq!(details.len(), 3); + }) + }); +} + +criterion_group!(benches, benchmark_list_branches, benchmark_branch_details); criterion_main!(benches); diff --git a/crates/gitbutler-branch-actions/src/base.rs b/crates/gitbutler-branch-actions/src/base.rs index 7b3656fd37..f824aa97ed 100644 --- a/crates/gitbutler-branch-actions/src/base.rs +++ b/crates/gitbutler-branch-actions/src/base.rs @@ -314,11 +314,12 @@ fn _print_tree(repo: &git2::Repository, tree: &git2::Tree) -> Result<()> { Ok(()) } -// try to update the target branch -// this means that we need to: -// determine if what the target branch is now pointing to is mergeable with our current working directory -// merge the target branch into our current working directory -// update the target sha +/// try to update the target branch +/// this means that we need to: +/// - determine if what the target branch is now pointing to is mergeable with our current working directory, +/// - merge the target branch into our current working directory +/// - update the target sha +/// - return all conflicting references that were unapplied to avoid the conflict pub(crate) fn update_base_branch( ctx: &CommandContext, perm: &mut WorktreeWritePermission, diff --git a/crates/gitbutler-branch-actions/src/branch.rs b/crates/gitbutler-branch-actions/src/branch.rs index ea42bfb65e..b03ec318f3 100644 --- a/crates/gitbutler-branch-actions/src/branch.rs +++ b/crates/gitbutler-branch-actions/src/branch.rs @@ -1,13 +1,14 @@ use crate::VirtualBranchesExt; -use anyhow::{Context, Result}; +use anyhow::{bail, Context, Result}; use bstr::{BStr, ByteSlice}; use core::fmt; use gitbutler_branch::{ Branch as GitButlerBranch, BranchId, BranchIdentity, ReferenceExtGix, Target, }; -use gitbutler_command_context::CommandContext; +use gitbutler_command_context::{CommandContext, GixRepositoryExt}; use gitbutler_reference::normalize_branch_name; use gitbutler_serde::BStringForFrontend; +use gix::object::tree::diff::Action; use gix::prelude::ObjectIdExt; use gix::reference::Category; use serde::{Deserialize, Serialize}; @@ -26,7 +27,7 @@ pub fn list_branches( filter: Option, filter_branch_names: Option>, ) -> Result> { - let mut repo = gix::open(ctx.repository().path())?; + let mut repo = ctx.gix_repository()?; repo.object_cache_size_if_unset(1024 * 1024); let has_filter = filter.is_some(); let filter = filter.unwrap_or_default(); @@ -60,11 +61,12 @@ pub fn list_branches( }); } - let virtual_branches = vb_handle.list_all_branches()?; - - for branch in virtual_branches { - branches.push(GroupBranch::Virtual(branch)); - } + branches.extend( + vb_handle + .list_all_branches()? + .into_iter() + .map(GroupBranch::Virtual), + ); let mut branches = combine_branches(branches, &repo, vb_handle.get_default_target()?)?; // Apply the filter @@ -256,8 +258,8 @@ fn branch_group_to_branch( })) } -fn gix_to_git2_oid(id: gix::ObjectId) -> git2::Oid { - git2::Oid::from_bytes(id.as_bytes()).expect("always valid") +fn gix_to_git2_oid(id: impl Into) -> git2::Oid { + git2::Oid::from_bytes(id.into().as_bytes()).expect("always valid") } fn git2_to_gix_object_id(id: git2::Oid) -> gix::ObjectId { @@ -413,8 +415,8 @@ pub struct VirtualBranchReference { pub in_workspace: bool, } -/// Takes a list of branch names (the given name, as returned by `BranchListing`) and returns -/// a list of enriched branch data in the form of `BranchData`. +/// Takes a list of `branch_names` (the given name, as returned by `BranchListing`) and returns +/// a list of enriched branch data. pub fn get_branch_listing_details( ctx: &CommandContext, branch_names: impl IntoIterator>, @@ -424,60 +426,167 @@ pub fn get_branch_listing_details( .map(TryInto::try_into) .filter_map(Result::ok) .collect(); - let repo = ctx.repository(); - let branches = list_branches(ctx, None, Some(branch_names.clone()))?; - let default_target = ctx - .project() - .virtual_branches() - .get_default_target() - .context("failed to get default target")?; + let repo = ctx.gix_repository_minimal()?.for_tree_diffing()?; + let branches = list_branches(ctx, None, Some(branch_names))?; + + let (default_target_current_upstream_commit_id, default_target_seen_at_last_update) = { + let target = ctx + .project() + .virtual_branches() + .get_default_target() + .context("failed to get default target")?; + let local_branch = repo.find_reference(target.branch.branch())?; + let local_tracking_ref_name = local_branch + .remote_tracking_ref_name(gix::remote::Direction::Fetch) + .with_context(|| { + format!( + "Branch {} did not have a remote tracking branch", + local_branch.name().as_bstr() + ) + })??; + let mut local_tracking_ref = repo.find_reference(local_tracking_ref_name.as_ref())?; + ( + gix_to_git2_oid(local_tracking_ref.peel_to_commit()?.id), + target.sha, + ) + }; + let mut enriched_branches = Vec::new(); + let (diffstats, merge_bases) = { + let (start, start_rx) = std::sync::mpsc::channel::<( + std::sync::mpsc::Receiver, + std::sync::mpsc::Sender<(usize, usize, usize)>, + )>(); + let diffstats = std::thread::Builder::new() + .name("gitbutler-diff-stats".into()) + .spawn({ + let repo = repo.clone(); + move || -> Result<()> { + let mut resource_cache = repo.diff_resource_cache_for_tree_diff()?; + for (change_rx, res_tx) in start_rx { + let (mut number_of_files, mut lines_added, mut lines_removed) = (0, 0, 0); + for change in change_rx { + if let Some(counts) = change + .attach(&repo, &repo) + .diff(&mut resource_cache) + .ok() + .and_then(|mut platform| platform.line_counts().ok()) + .flatten() + { + number_of_files += 1; + lines_added += counts.insertions as usize; + lines_removed += counts.removals as usize; + } + // Let's not attempt to reuse the cache as it's only useful if we know the diff repeats + // over different objects, like when doing rename tracking. + resource_cache.clear_resource_cache_keep_allocation(); + } + if res_tx + .send((number_of_files, lines_added, lines_removed)) + .is_err() + { + break; + } + } + Ok(()) + } + })?; + + let all_other_branch_commit_ids: Vec<_> = branches + .iter() + .map(|branch| { + ( + branch + .virtual_branch + .as_ref() + .and_then(|vb| { + vb.in_workspace + .then_some(default_target_seen_at_last_update) + }) + .unwrap_or(default_target_current_upstream_commit_id), + branch.head, + ) + }) + .collect(); + let (merge_tx, merge_rx) = std::sync::mpsc::channel(); + let merge_bases = std::thread::Builder::new() + .name("gitbutler-mergebases".into()) + .spawn({ + let git_dir = ctx.repository().path().to_owned(); + move || -> anyhow::Result<()> { + let git2_repo = git2::Repository::open(git_dir)?; + for (other_branch_commit_id, branch_head) in all_other_branch_commit_ids { + // TODO(ST): use `gix` for two-way mergebases. + let base = git2_repo + .merge_base(other_branch_commit_id, branch_head) + .ok(); + if merge_tx.send(base).is_err() { + break; + } + } + Ok(()) + } + })?; - let default_local_branch = - repo.find_branch(default_target.branch.branch(), git2::BranchType::Local)?; - let default_branch = default_local_branch.upstream()?; - let head_commit = default_branch.get().peel_to_commit()?; - - for branch in branches { - let merge_base_comparison = if let Some(virtual_branch) = branch.virtual_branch { - if virtual_branch.in_workspace { - default_target.sha - } else { - head_commit.id() - } - } else { - head_commit.id() - }; - if let Ok(base) = repo.merge_base(merge_base_comparison, branch.head) { - let base_tree = repo.find_commit(base)?.tree()?; - let head_tree = repo.find_commit(branch.head)?.tree()?; - let diff_stats = repo - .diff_tree_to_tree(Some(&base_tree), Some(&head_tree), None)? - .stats()?; - - let head = branch.head; - - let mut revwalk = repo.revwalk()?; - revwalk.push(head)?; - revwalk.hide(base)?; - let mut commits = Vec::new(); + for branch in branches { + let Some(base) = merge_rx.recv()? else { + continue; + }; + + let branch_head = git2_to_gix_object_id(branch.head); + let gix_base = git2_to_gix_object_id(base); + let base_commit = repo.find_object(gix_base)?.try_into_commit()?; + let base_tree = base_commit.tree()?; + let head_tree = repo.find_object(branch_head)?.peel_to_tree()?; + + let ((change_tx, change_rx), (res_tx, rex_rx)) = + (std::sync::mpsc::channel(), std::sync::mpsc::channel()); + if start.send((change_rx, res_tx)).is_err() { + bail!("diffing-thread crashed"); + }; + base_tree + .changes()? + .track_rewrites(None) + // NOTE: `stats(head_tree)` is also possible, but we have a separate thread for that. + .for_each_to_obtain_tree(&head_tree, move |change| -> anyhow::Result { + change_tx.send(change.detach()).ok(); + Ok(Action::Continue) + })?; + let (number_of_files, lines_added, lines_removed) = rex_rx.recv()?; + // TODO(ST): make this API nicer, maybe have one that is not based on `ancestors()` but + // similar to revwalk because it's so common? + let revwalk = branch_head + .attach(&repo) + .ancestors() + // When allowing to skip branches without a filter, make sure it automatically skips by date! + .sorting( + gix::traverse::commit::simple::Sorting::ByCommitTimeNewestFirstCutoffOlderThan { + seconds: base_commit.time()?.seconds, + }, + ) + .selected(|id| id != gix_base)?; + let mut num_commits = 0; let mut authors = HashSet::new(); - for oid in revwalk { - let commit = repo.find_commit(oid?)?; - authors.insert(commit.author().into()); - commits.push(commit); + for commit_info in revwalk { + let commit_info = commit_info?; + let commit = repo.find_commit(commit_info.id)?; + authors.insert(commit.author()?.into()); + num_commits += 1; } let branch_data = BranchListingDetails { name: branch.name, - lines_added: diff_stats.insertions(), - lines_removed: diff_stats.deletions(), - number_of_files: diff_stats.files_changed(), + lines_added, + lines_removed, + number_of_files, authors: authors.into_iter().collect(), - number_of_commits: commits.len(), + number_of_commits: num_commits, }; enriched_branches.push(branch_data); } - } + (diffstats, merge_bases) + }; + diffstats.join().expect("no panic")?; + merge_bases.join().expect("no panic")?; Ok(enriched_branches) } diff --git a/crates/gitbutler-branch-actions/tests/fixtures/branch-details-benches.sh b/crates/gitbutler-branch-actions/tests/fixtures/branch-details-benches.sh new file mode 100644 index 0000000000..acc8052307 --- /dev/null +++ b/crates/gitbutler-branch-actions/tests/fixtures/branch-details-benches.sh @@ -0,0 +1,10079 @@ +#!/usr/bin/env bash +set -eu -o pipefail +CLI=${1:?The first argument is the GitButler CLI} + +export GITBUTLER_CLI_DATA_DIR=../user/gitbutler/app-data + +git init big-repo +(cd big-repo + empty_oid=$(git hash-object -w --stdin file + git add . && git commit -m "init" +) + +git clone remote revwalk-repo +(cd revwalk-repo + for round in $(seq 5); do + echo main >> file + git commit -am "main-$round" + done + + local_tracking_ref="$(git rev-parse --symbolic-full-name @{u})"; + + git checkout -b feature main + for round in $(seq 100); do + echo feature >> file + git commit -am "feat-$round" + done + + git checkout main + $CLI project add --switch-to-integration "$local_tracking_ref" + for round in $(seq 10); do + echo virtual-main >> file + $CLI branch commit --message "virt-$round" main + done + + git checkout -b non-virtual-feature main + for round in $(seq 50); do + echo non-virtual-feature >> file + git commit -am "non-virtual-feat-$round" + done + + # pretend the remote is at the same state as our local `main` + git update-ref refs/remotes/origin/main main + git gc --aggressive +) diff --git a/crates/gitbutler-branch-actions/tests/fixtures/for-details.sh b/crates/gitbutler-branch-actions/tests/fixtures/for-details.sh new file mode 100644 index 0000000000..fb137be3da --- /dev/null +++ b/crates/gitbutler-branch-actions/tests/fixtures/for-details.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +set -eu -o pipefail +CLI=${1:?The first argument is the GitButler CLI} + +function tick () { + if test -z "${tick+set}"; then + tick=1675176957 + else + tick=$(($tick + 60)) + fi + GIT_COMMITTER_DATE="$tick +0100" + GIT_AUTHOR_DATE="$tick +0100" + export GIT_COMMITTER_DATE GIT_AUTHOR_DATE +} +tick + + +git init remote +(cd remote + echo first > file + git add . && git commit -m "init" +) + +export GITBUTLER_CLI_DATA_DIR=../user/gitbutler/app-data +git clone remote complex-repo +(cd complex-repo + for round in $(seq 5); do + echo main >> file + git commit -am "main-$round" + done + + local_tracking_ref="$(git rev-parse --symbolic-full-name @{u})"; + + git checkout -b feature main + for round in $(seq 100); do + echo feature >> file + git commit -am "feat-$round" + done + + git checkout main + $CLI project add --switch-to-integration "$local_tracking_ref" + for round in $(seq 10); do + echo virtual-main >> file + $CLI branch commit --message "virt-$round" main + done + + git checkout -b non-virtual-feature main + for round in $(seq 50); do + echo non-virtual-feature >> file + git commit -am "non-virtual-feat-$round" + done + + # pretend the remote is at the same state as our local `main` + git update-ref refs/remotes/origin/main main +) diff --git a/crates/gitbutler-branch-actions/tests/virtual_branches/list.rs b/crates/gitbutler-branch-actions/tests/virtual_branches/list.rs index 8090329598..93e348d448 100644 --- a/crates/gitbutler-branch-actions/tests/virtual_branches/list.rs +++ b/crates/gitbutler-branch-actions/tests/virtual_branches/list.rs @@ -229,4 +229,4 @@ mod util { Ok(branches) } } -use util::{assert_equal, init_env, list_branches, project_ctx, ExpectedBranchListing}; +pub use util::{assert_equal, init_env, list_branches, project_ctx, ExpectedBranchListing}; diff --git a/crates/gitbutler-branch-actions/tests/virtual_branches/list_details.rs b/crates/gitbutler-branch-actions/tests/virtual_branches/list_details.rs new file mode 100644 index 0000000000..35b7cbf189 --- /dev/null +++ b/crates/gitbutler-branch-actions/tests/virtual_branches/list_details.rs @@ -0,0 +1,117 @@ +use crate::virtual_branches::list; +use gitbutler_branch_actions::BranchListingDetails; + +#[test] +fn one_vbranch_on_integration_empty_details() -> anyhow::Result<()> { + let list = branch_details( + &list::project_ctx("one-vbranch-on-integration")?, + Some("virtual"), + )?; + assert_eq!(list.len(), 1); + assert_eq!( + list[0], + BranchListingDetails { + name: "virtual".into(), + lines_added: 0, + lines_removed: 0, + number_of_files: 0, + number_of_commits: 0, + authors: vec![], + } + ); + Ok(()) +} + +#[test] +fn one_vbranch_on_integration_single_commit() -> anyhow::Result<()> { + let list = branch_details( + &list::project_ctx("one-vbranch-on-integration-one-commit")?, + Some("virtual"), + )?; + assert_eq!(list.len(), 1); + assert_eq!( + list[0], + BranchListingDetails { + name: "virtual".into(), + lines_added: 2, + lines_removed: 0, + number_of_files: 2, + number_of_commits: 1, + authors: vec![default_author()], + } + ); + Ok(()) +} + +#[test] +fn many_commits_in_all_branch_types() -> anyhow::Result<()> { + let ctx = project_ctx("complex-repo")?; + let list = branch_details(&ctx, ["feature", "main", "non-virtual-feature"])?; + assert_eq!(list.len(), 3); + assert_eq!( + list[0], + BranchListingDetails { + name: "feature".into(), + lines_added: 100, + lines_removed: 0, + number_of_files: 1, + number_of_commits: 100, + authors: vec![default_author()], + }, + "local branches use the *current* local tracking branch…" + ); + assert_eq!( + list[1], + BranchListingDetails { + name: "main".into(), + lines_added: 15, + lines_removed: 0, + number_of_files: 1, + number_of_commits: 10 + 5, + authors: vec![default_author()], + }, + "…while virtual branches use the 'target' stored when the workspace was last updated.\ + That way the 'update' of the workspace performs the calculation to put it back on top of \ + the local tracking branch." + ); + assert_eq!( + list[2], + BranchListingDetails { + name: "non-virtual-feature".into(), + lines_added: 50, + lines_removed: 0, + number_of_files: 1, + number_of_commits: 50, + authors: vec![default_author()], + }, + "This is a non-virtual brnach, so it sees the local tracking branch as well" + ); + Ok(()) +} + +mod util { + use gitbutler_branch::BranchIdentity; + use gitbutler_branch_actions::{Author, BranchListingDetails}; + use gitbutler_command_context::CommandContext; + + pub fn branch_details( + ctx: &CommandContext, + branch_names: impl IntoIterator>, + ) -> anyhow::Result> { + let mut details = gitbutler_branch_actions::get_branch_listing_details(ctx, branch_names)?; + details.sort_by(|a, b| a.name.cmp(&b.name)); + Ok(details) + } + + pub fn default_author() -> Author { + Author { + name: Some("author".into()), + email: Some("author@example.com".into()), + } + } + + pub fn project_ctx(name: &str) -> anyhow::Result { + gitbutler_testsupport::read_only::fixture("for-details.sh", name) + } +} +use util::{branch_details, default_author, project_ctx}; diff --git a/crates/gitbutler-branch-actions/tests/virtual_branches/mod.rs b/crates/gitbutler-branch-actions/tests/virtual_branches/mod.rs index 0664fff338..b1b36b6b64 100644 --- a/crates/gitbutler-branch-actions/tests/virtual_branches/mod.rs +++ b/crates/gitbutler-branch-actions/tests/virtual_branches/mod.rs @@ -65,6 +65,7 @@ mod delete_virtual_branch; mod init; mod insert_blank_commit; mod list; +mod list_details; mod move_commit_file; mod move_commit_to_vbranch; mod oplog; diff --git a/crates/gitbutler-branch/Cargo.toml b/crates/gitbutler-branch/Cargo.toml index 8765246d3e..81e462787a 100644 --- a/crates/gitbutler-branch/Cargo.toml +++ b/crates/gitbutler-branch/Cargo.toml @@ -21,7 +21,7 @@ serde = { workspace = true, features = ["std"] } bstr.workspace = true md5 = "0.7.0" hex = "0.4.3" -tracing = "0.1.40" +tracing.workspace = true lazy_static = "1.4.0" [[test]] diff --git a/crates/gitbutler-branch/src/target.rs b/crates/gitbutler-branch/src/target.rs index 2c605bdee4..a005df585b 100644 --- a/crates/gitbutler-branch/src/target.rs +++ b/crates/gitbutler-branch/src/target.rs @@ -3,9 +3,23 @@ use serde::{ser::SerializeStruct, Deserialize, Deserializer, Serialize, Serializ #[derive(Debug, PartialEq, Clone)] pub struct Target { + /// The combination of remote name and branch name, i.e. `origin` and `main`. + /// The remote name is the one used to fetch from. + /// It's equivalent to e.g. `refs/remotes/origin/main` , and the type `RemoteRefName` + /// stores it as `` and `` so that finding references named `/` + /// will typically find the local tracking branch unambiguously. pub branch: RemoteRefname, + /// The URL of the remote behind the symbolic name. pub remote_url: String, + /// The merge-base between `branch` and the current worktree `HEAD` upon first creation, + /// but then it's the set to the new destination of e.g. `refs/remotes/origin/main` after + /// the remote was fetched. This value is used to determine if there was a change, + /// and if the *workspace* needs to be recalculated/rebased against the new commit. + // TODO(ST): is it safe/correct to rename this to `branch_target_id`? Should be! + // It's just a bit strange it starts life as merge-base, but maybe it ends + // up the same anyway? Definitely could use a test then. pub sha: git2::Oid, + /// The name of the remote to push to. pub push_remote_name: Option, } diff --git a/crates/gitbutler-cli/Cargo.toml b/crates/gitbutler-cli/Cargo.toml index eefae0adcc..4b87307f07 100644 --- a/crates/gitbutler-cli/Cargo.toml +++ b/crates/gitbutler-cli/Cargo.toml @@ -15,10 +15,14 @@ gitbutler-oplog.workspace = true gitbutler-project.workspace = true gitbutler-reference.workspace = true gitbutler-branch-actions.workspace = true +gitbutler-command-context.workspace = true gitbutler-branch.workspace = true gitbutler-diff.workspace = true -gix = { workspace = true, features = ["max-performance-safe"] } +gix = { workspace = true, features = ["max-performance", "tracing"] } dirs-next = "2.0.0" clap = { version = "4.5.13", features = ["derive", "env"] } anyhow = "1.0.86" chrono = "0.4.10" +tracing-forest = { version = "0.1.6" } +tracing-subscriber.workspace = true +tracing.workspace = true diff --git a/crates/gitbutler-cli/src/args.rs b/crates/gitbutler-cli/src/args.rs index 234feff2a2..4c3d2a6834 100644 --- a/crates/gitbutler-cli/src/args.rs +++ b/crates/gitbutler-cli/src/args.rs @@ -3,6 +3,9 @@ use std::path::PathBuf; #[derive(Debug, clap::Parser)] #[clap(name = "gitbutler-cli", about = "A CLI for GitButler", version = option_env!("GIX_VERSION"))] pub struct Args { + /// Enable tracing for debug and performance information printed to stderr. + #[clap(short = 'd', long)] + pub trace: bool, /// Run as if gitbutler-cli was started in PATH instead of the current working directory. #[clap(short = 'C', long, default_value = ".", value_name = "PATH")] pub current_dir: PathBuf, @@ -25,6 +28,8 @@ pub enum Subcommands { } pub mod vbranch { + use gitbutler_branch::BranchIdentity; + #[derive(Debug, clap::Parser)] pub struct Platform { #[clap(subcommand)] @@ -59,6 +64,15 @@ pub mod vbranch { /// The name of the virtual branch to create name: String, }, + /// Provide details about given branches. + Details { + /// The short-name/identity of branches to list. + names: Vec, + }, + /// List all branches that can be relevant. + ListAll, + /// After fetching the target (i.e. local tracking branch), recompute our workspace against it. + UpdateTarget, } } diff --git a/crates/gitbutler-cli/src/command.rs b/crates/gitbutler-cli/src/command.rs deleted file mode 100644 index 7ab172329f..0000000000 --- a/crates/gitbutler-cli/src/command.rs +++ /dev/null @@ -1,251 +0,0 @@ -pub mod vbranch { - use anyhow::{bail, Result}; - use gitbutler_branch::{ - Branch, BranchCreateRequest, BranchUpdateRequest, VirtualBranchesHandle, - }; - use gitbutler_branch_actions::VirtualBranchActions; - use gitbutler_project::Project; - - use crate::command::debug_print; - - pub fn list(project: Project) -> Result<()> { - let branches = VirtualBranchesHandle::new(project.gb_dir()).list_all_branches()?; - for vbranch in branches { - println!( - "{active} {id} {name} {upstream} {default}", - active = if vbranch.applied { "✔️" } else { "⛌" }, - id = vbranch.id, - name = vbranch.name, - upstream = vbranch - .upstream - .map_or_else(Default::default, |b| b.to_string()), - default = if vbranch.in_workspace { "🌟" } else { "" } - ); - } - Ok(()) - } - - pub fn unapply(project: Project, branch_name: String) -> Result<()> { - let branch = branch_by_name(&project, &branch_name)?; - debug_print(VirtualBranchActions.convert_to_real_branch(&project, branch.id)?) - } - - pub fn create(project: Project, branch_name: String, set_default: bool) -> Result<()> { - let new = VirtualBranchActions.create_virtual_branch( - &project, - &BranchCreateRequest { - name: Some(branch_name), - ..Default::default() - }, - )?; - if set_default { - let new = VirtualBranchesHandle::new(project.gb_dir()).get_branch(new)?; - set_default_branch(&project, &new)?; - } - debug_print(new) - } - - pub fn set_default(project: Project, branch_name: String) -> Result<()> { - let branch = branch_by_name(&project, &branch_name)?; - set_default_branch(&project, &branch) - } - - fn set_default_branch(project: &Project, branch: &Branch) -> Result<()> { - VirtualBranchActions.update_virtual_branch( - project, - BranchUpdateRequest { - id: branch.id, - name: None, - notes: None, - ownership: None, - order: None, - upstream: None, - selected_for_changes: Some(true), - allow_rebasing: None, - }, - ) - } - - pub fn commit(project: Project, branch_name: String, message: String) -> Result<()> { - let branch = branch_by_name(&project, &branch_name)?; - let (info, skipped) = VirtualBranchActions.list_virtual_branches(&project)?; - - if !skipped.is_empty() { - eprintln!( - "{} files could not be processed (binary or large size)", - skipped.len() - ) - } - - let populated_branch = info - .iter() - .find(|b| b.id == branch.id) - .expect("A populated branch exists for a branch we can list"); - if populated_branch.ownership.claims.is_empty() { - bail!( - "Branch '{branch_name}' has no change to commit{hint}", - hint = { - let candidate_names = info - .iter() - .filter_map(|b| (!b.ownership.claims.is_empty()).then_some(b.name.as_str())) - .collect::>(); - let mut candidates = candidate_names.join(", "); - if !candidate_names.is_empty() { - candidates = format!( - ". {candidates} {have} changes.", - have = if candidate_names.len() == 1 { - "has" - } else { - "have" - } - ) - }; - candidates - } - ) - } - - let run_hooks = false; - debug_print(VirtualBranchActions.create_commit( - &project, - branch.id, - &message, - Some(&populated_branch.ownership), - run_hooks, - )?) - } - - pub fn branch_by_name(project: &Project, name: &str) -> Result { - let mut found: Vec<_> = VirtualBranchesHandle::new(project.gb_dir()) - .list_all_branches()? - .into_iter() - .filter(|b| b.name == name) - .collect(); - if found.is_empty() { - bail!("No virtual branch named '{name}'"); - } else if found.len() > 1 { - bail!("Found more than one virtual branch named '{name}'"); - } - Ok(found.pop().expect("present")) - } -} - -pub mod project { - use std::path::PathBuf; - - use anyhow::{Context, Result}; - use gitbutler_branch_actions::VirtualBranchActions; - use gitbutler_project::Project; - use gitbutler_reference::RemoteRefname; - - use crate::command::debug_print; - - pub fn list(ctrl: gitbutler_project::Controller) -> Result<()> { - for project in ctrl.list()? { - println!( - "{id} {name} {path}", - id = project.id, - name = project.title, - path = project.path.display() - ); - } - Ok(()) - } - - pub fn add( - ctrl: gitbutler_project::Controller, - path: PathBuf, - refname: Option, - ) -> Result<()> { - let path = gix::discover(path)? - .work_dir() - .context("Only non-bare repositories can be added")? - .to_owned() - .canonicalize()?; - let project = ctrl.add(path)?; - if let Some(refname) = refname { - VirtualBranchActions.set_base_branch(&project, &refname)?; - }; - debug_print(project) - } - - pub fn switch_to_integration(project: Project, refname: RemoteRefname) -> Result<()> { - debug_print(VirtualBranchActions.set_base_branch(&project, &refname)?) - } -} -pub mod snapshot { - use anyhow::Result; - use gitbutler_oplog::OplogExt; - use gitbutler_project::Project; - - pub fn list(project: Project) -> Result<()> { - let snapshots = project.list_snapshots(100, None)?; - for snapshot in snapshots { - let ts = chrono::DateTime::from_timestamp(snapshot.created_at.seconds(), 0); - let details = snapshot.details; - if let (Some(ts), Some(details)) = (ts, details) { - println!("{} {} {}", ts, snapshot.commit_id, details.operation); - } - } - Ok(()) - } - - pub fn restore(project: Project, snapshot_id: String) -> Result<()> { - let _guard = project.try_exclusive_access()?; - project.restore_snapshot(snapshot_id.parse()?)?; - Ok(()) - } -} - -pub mod prepare { - use std::path::PathBuf; - - use anyhow::{bail, Context}; - use gitbutler_project::Project; - - pub fn project_from_path(path: PathBuf) -> anyhow::Result { - let worktree_dir = gix::discover(path)? - .work_dir() - .context("Bare repositories aren't supported")? - .to_owned(); - Ok(Project { - path: worktree_dir, - ..Default::default() - }) - } - - pub fn project_controller( - app_suffix: Option, - app_data_dir: Option, - ) -> anyhow::Result { - let path = if let Some(dir) = app_data_dir { - std::fs::create_dir_all(&dir) - .context("Failed to assure the designated data-dir exists")?; - dir - } else { - dirs_next::data_dir() - .map(|dir| { - dir.join(format!( - "com.gitbutler.app{}", - app_suffix - .map(|mut suffix| { - suffix.insert(0, '.'); - suffix - }) - .unwrap_or_default() - )) - }) - .context("no data-directory available on this platform")? - }; - if !path.is_dir() { - bail!("Path '{}' must be a valid directory", path.display()); - } - eprintln!("Using projects from '{}'", path.display()); - Ok(gitbutler_project::Controller::from_path(path)) - } -} - -fn debug_print(this: impl std::fmt::Debug) -> anyhow::Result<()> { - eprintln!("{:#?}", this); - Ok(()) -} diff --git a/crates/gitbutler-cli/src/command/mod.rs b/crates/gitbutler-cli/src/command/mod.rs new file mode 100644 index 0000000000..dcbb03d961 --- /dev/null +++ b/crates/gitbutler-cli/src/command/mod.rs @@ -0,0 +1,32 @@ +pub mod prepare; +pub mod project; +pub mod vbranch; + +pub mod snapshot { + use anyhow::Result; + use gitbutler_oplog::OplogExt; + use gitbutler_project::Project; + + pub fn list(project: Project) -> Result<()> { + let snapshots = project.list_snapshots(100, None)?; + for snapshot in snapshots { + let ts = chrono::DateTime::from_timestamp(snapshot.created_at.seconds(), 0); + let details = snapshot.details; + if let (Some(ts), Some(details)) = (ts, details) { + println!("{} {} {}", ts, snapshot.commit_id, details.operation); + } + } + Ok(()) + } + + pub fn restore(project: Project, snapshot_id: String) -> Result<()> { + let _guard = project.try_exclusive_access()?; + project.restore_snapshot(snapshot_id.parse()?)?; + Ok(()) + } +} + +fn debug_print(this: impl std::fmt::Debug) -> anyhow::Result<()> { + println!("{:#?}", this); + Ok(()) +} diff --git a/crates/gitbutler-cli/src/command/prepare.rs b/crates/gitbutler-cli/src/command/prepare.rs new file mode 100644 index 0000000000..705973c5cc --- /dev/null +++ b/crates/gitbutler-cli/src/command/prepare.rs @@ -0,0 +1,44 @@ +use std::path::PathBuf; + +use anyhow::{bail, Context}; +use gitbutler_project::Project; + +pub fn project_from_path(path: PathBuf) -> anyhow::Result { + let worktree_dir = gix::discover(path)? + .work_dir() + .context("Bare repositories aren't supported")? + .to_owned(); + Ok(Project { + path: worktree_dir, + ..Default::default() + }) +} + +pub fn project_controller( + app_suffix: Option, + app_data_dir: Option, +) -> anyhow::Result { + let path = if let Some(dir) = app_data_dir { + std::fs::create_dir_all(&dir).context("Failed to assure the designated data-dir exists")?; + dir + } else { + dirs_next::data_dir() + .map(|dir| { + dir.join(format!( + "com.gitbutler.app{}", + app_suffix + .map(|mut suffix| { + suffix.insert(0, '.'); + suffix + }) + .unwrap_or_default() + )) + }) + .context("no data-directory available on this platform")? + }; + if !path.is_dir() { + bail!("Path '{}' must be a valid directory", path.display()); + } + eprintln!("Using projects from '{}'", path.display()); + Ok(gitbutler_project::Controller::from_path(path)) +} diff --git a/crates/gitbutler-cli/src/command/project.rs b/crates/gitbutler-cli/src/command/project.rs new file mode 100644 index 0000000000..8626ab4705 --- /dev/null +++ b/crates/gitbutler-cli/src/command/project.rs @@ -0,0 +1,41 @@ +use std::path::PathBuf; + +use anyhow::{Context, Result}; +use gitbutler_branch_actions::VirtualBranchActions; +use gitbutler_project::Project; +use gitbutler_reference::RemoteRefname; + +use crate::command::debug_print; + +pub fn list(ctrl: gitbutler_project::Controller) -> Result<()> { + for project in ctrl.list()? { + println!( + "{id} {name} {path}", + id = project.id, + name = project.title, + path = project.path.display() + ); + } + Ok(()) +} + +pub fn add( + ctrl: gitbutler_project::Controller, + path: PathBuf, + refname: Option, +) -> Result<()> { + let path = gix::discover(path)? + .work_dir() + .context("Only non-bare repositories can be added")? + .to_owned() + .canonicalize()?; + let project = ctrl.add(path)?; + if let Some(refname) = refname { + VirtualBranchActions.set_base_branch(&project, &refname)?; + }; + debug_print(project) +} + +pub fn switch_to_integration(project: Project, refname: RemoteRefname) -> Result<()> { + debug_print(VirtualBranchActions.set_base_branch(&project, &refname)?) +} diff --git a/crates/gitbutler-cli/src/command/vbranch.rs b/crates/gitbutler-cli/src/command/vbranch.rs new file mode 100644 index 0000000000..685ab7886c --- /dev/null +++ b/crates/gitbutler-cli/src/command/vbranch.rs @@ -0,0 +1,145 @@ +use anyhow::{bail, Result}; +use gitbutler_branch::{ + Branch, BranchCreateRequest, BranchIdentity, BranchUpdateRequest, VirtualBranchesHandle, +}; +use gitbutler_branch_actions::{get_branch_listing_details, list_branches, VirtualBranchActions}; +use gitbutler_command_context::CommandContext; +use gitbutler_project::Project; + +use crate::command::debug_print; + +pub fn update_target(project: Project) -> Result<()> { + let unapplied = VirtualBranchActions.update_base_branch(&project)?; + debug_print(unapplied) +} + +pub fn list_all(project: Project) -> Result<()> { + let ctx = CommandContext::open(&project)?; + debug_print(list_branches(&ctx, None, None)?) +} + +pub fn details(project: Project, branch_names: Vec) -> Result<()> { + let ctx = CommandContext::open(&project)?; + debug_print(get_branch_listing_details(&ctx, branch_names)?) +} + +pub fn list(project: Project) -> Result<()> { + let branches = VirtualBranchesHandle::new(project.gb_dir()).list_all_branches()?; + for vbranch in branches { + println!( + "{active} {id} {name} {upstream} {default}", + active = if vbranch.applied { "✔️" } else { "⛌" }, + id = vbranch.id, + name = vbranch.name, + upstream = vbranch + .upstream + .map_or_else(Default::default, |b| b.to_string()), + default = if vbranch.in_workspace { "🌟" } else { "" } + ); + } + Ok(()) +} + +pub fn unapply(project: Project, branch_name: String) -> Result<()> { + let branch = branch_by_name(&project, &branch_name)?; + debug_print(VirtualBranchActions.convert_to_real_branch(&project, branch.id)?) +} + +pub fn create(project: Project, branch_name: String, set_default: bool) -> Result<()> { + let new = VirtualBranchActions.create_virtual_branch( + &project, + &BranchCreateRequest { + name: Some(branch_name), + ..Default::default() + }, + )?; + if set_default { + let new = VirtualBranchesHandle::new(project.gb_dir()).get_branch(new)?; + set_default_branch(&project, &new)?; + } + debug_print(new) +} + +pub fn set_default(project: Project, branch_name: String) -> Result<()> { + let branch = branch_by_name(&project, &branch_name)?; + set_default_branch(&project, &branch) +} + +fn set_default_branch(project: &Project, branch: &Branch) -> Result<()> { + VirtualBranchActions.update_virtual_branch( + project, + BranchUpdateRequest { + id: branch.id, + name: None, + notes: None, + ownership: None, + order: None, + upstream: None, + selected_for_changes: Some(true), + allow_rebasing: None, + }, + ) +} + +pub fn commit(project: Project, branch_name: String, message: String) -> Result<()> { + let branch = branch_by_name(&project, &branch_name)?; + let (info, skipped) = VirtualBranchActions.list_virtual_branches(&project)?; + + if !skipped.is_empty() { + eprintln!( + "{} files could not be processed (binary or large size)", + skipped.len() + ) + } + + let populated_branch = info + .iter() + .find(|b| b.id == branch.id) + .expect("A populated branch exists for a branch we can list"); + if populated_branch.ownership.claims.is_empty() { + bail!( + "Branch '{branch_name}' has no change to commit{hint}", + hint = { + let candidate_names = info + .iter() + .filter_map(|b| (!b.ownership.claims.is_empty()).then_some(b.name.as_str())) + .collect::>(); + let mut candidates = candidate_names.join(", "); + if !candidate_names.is_empty() { + candidates = format!( + ". {candidates} {have} changes.", + have = if candidate_names.len() == 1 { + "has" + } else { + "have" + } + ) + }; + candidates + } + ) + } + + let run_hooks = false; + debug_print(VirtualBranchActions.create_commit( + &project, + branch.id, + &message, + Some(&populated_branch.ownership), + run_hooks, + )?) +} + +pub fn branch_by_name(project: &Project, name: &str) -> Result { + let mut found: Vec<_> = VirtualBranchesHandle::new(project.gb_dir()) + .list_all_branches()? + .into_iter() + .filter(|b| b.name == name) + .collect(); + if found.is_empty() { + bail!("No virtual branch named '{name}'"); + } else if found.len() > 1 { + bail!("Found more than one virtual branch named '{name}'"); + } + Ok(found.pop().expect("present")) +} diff --git a/crates/gitbutler-cli/src/main.rs b/crates/gitbutler-cli/src/main.rs index db2aa590bb..a7585db56d 100644 --- a/crates/gitbutler-cli/src/main.rs +++ b/crates/gitbutler-cli/src/main.rs @@ -9,6 +9,12 @@ mod command; fn main() -> Result<()> { let args: Args = clap::Parser::parse(); + gitbutler_project::configure_git2(); + + if args.trace { + trace::init()?; + } + let _op_span = tracing::info_span!("cli-op").entered(); match args.cmd { args::Subcommands::Branch(vbranch::Platform { cmd }) => { @@ -26,6 +32,13 @@ fn main() -> Result<()> { Some(vbranch::SubCommands::Create { set_default, name }) => { command::vbranch::create(project, name, set_default) } + Some(vbranch::SubCommands::Details { names }) => { + command::vbranch::details(project, names) + } + Some(vbranch::SubCommands::ListAll) => command::vbranch::list_all(project), + Some(vbranch::SubCommands::UpdateTarget) => { + command::vbranch::update_target(project) + } None => command::vbranch::list(project), } } @@ -61,3 +74,17 @@ fn main() -> Result<()> { } } } + +mod trace { + use tracing_subscriber::layer::SubscriberExt; + use tracing_subscriber::util::SubscriberInitExt; + + pub fn init() -> anyhow::Result<()> { + tracing_subscriber::registry() + .with(tracing_forest::ForestLayer::from( + tracing_forest::printer::PrettyPrinter::new().writer(std::io::stderr), + )) + .init(); + Ok(()) + } +} diff --git a/crates/gitbutler-command-context/Cargo.toml b/crates/gitbutler-command-context/Cargo.toml index 17ce12d5bd..df826abf78 100644 --- a/crates/gitbutler-command-context/Cargo.toml +++ b/crates/gitbutler-command-context/Cargo.toml @@ -8,6 +8,7 @@ publish = false [dependencies] anyhow = "1.0.86" git2.workspace = true -tracing = "0.1.40" +gix.workspace = true +tracing.workspace = true gitbutler-project.workspace = true itertools = "0.13" diff --git a/crates/gitbutler-command-context/src/lib.rs b/crates/gitbutler-command-context/src/lib.rs index 445f170115..76d7ad812c 100644 --- a/crates/gitbutler-command-context/src/lib.rs +++ b/crates/gitbutler-command-context/src/lib.rs @@ -70,4 +70,46 @@ impl CommandContext { pub fn repository(&self) -> &git2::Repository { &self.git_repository } + + /// Return a newly opened `gitoxide` repository, with all configuration available + /// to correctly figure out author and committer names (i.e. with most global configuration loaded). + /// + /// ### Note + /// + /// The plan is to eventually phase out the `git2` version of the repository, and open + /// the `gitoxide` repository right away. Meanwhile, we open `gitoxide` repositories on the fly + /// on top-level functions, and pass them down as needed. + /// + /// Also note that there are plenty of other places where repositories are opened ad-hoc, and + /// there is no need to use this type there at all - opening a repo is very cheap still. + pub fn gix_repository(&self) -> Result { + Ok(gix::open(self.repository().path())?) + } + + /// Return a newly opened `gitoxide` repository with only the repository-local configuration + /// available. This is a little faster as it has to open less files upon startup. + /// + /// Such repositories are only useful for reference and object-access, but *can't be used* to create + /// commits, fetch or push. + pub fn gix_repository_minimal(&self) -> Result { + Ok(gix::open_opts( + self.repository().path(), + gix::open::Options::isolated(), + )?) + } +} + +// TODO(ST): put this into `gix`, the logic seems good, add unit-test for number generation. +pub trait GixRepositoryExt: Sized { + /// Configure the repository for diff operations between trees. + /// This means it needs an object cache relative to the amount of files in the repository. + fn for_tree_diffing(self) -> Result; +} + +impl GixRepositoryExt for gix::Repository { + fn for_tree_diffing(mut self) -> anyhow::Result { + let bytes = self.compute_object_cache_size_for_tree_diffs(&***self.index_or_empty()?); + self.object_cache_size_if_unset(bytes); + Ok(self) + } } diff --git a/crates/gitbutler-diff/Cargo.toml b/crates/gitbutler-diff/Cargo.toml index 3536333412..d284da64aa 100644 --- a/crates/gitbutler-diff/Cargo.toml +++ b/crates/gitbutler-diff/Cargo.toml @@ -11,7 +11,7 @@ bstr.workspace = true md5 = "0.7.0" anyhow = "1.0.86" hex = "0.4.3" -tracing = "0.1.40" +tracing.workspace = true gitbutler-serde.workspace = true gitbutler-command-context.workspace = true diffy = "0.4.0" diff --git a/crates/gitbutler-oplog/Cargo.toml b/crates/gitbutler-oplog/Cargo.toml index c613f42a45..1b8ac60aab 100644 --- a/crates/gitbutler-oplog/Cargo.toml +++ b/crates/gitbutler-oplog/Cargo.toml @@ -12,7 +12,7 @@ gitbutler-repo.workspace = true serde = { workspace = true, features = ["std"] } itertools = "0.13" strum = { version = "0.26", features = ["derive"] } -tracing = "0.1.40" +tracing.workspace = true gix = { workspace = true, features = ["dirwalk", "credentials", "parallel"] } toml.workspace = true gitbutler-project.workspace = true diff --git a/crates/gitbutler-project/Cargo.toml b/crates/gitbutler-project/Cargo.toml index a27d2a9926..f0e5f8afb4 100644 --- a/crates/gitbutler-project/Cargo.toml +++ b/crates/gitbutler-project/Cargo.toml @@ -17,7 +17,7 @@ gitbutler-storage.workspace = true git2.workspace = true gix = { workspace = true, features = ["dirwalk", "credentials", "parallel"] } uuid.workspace = true -tracing = "0.1.40" +tracing.workspace = true resolve-path = "0.1.0" # for locking diff --git a/crates/gitbutler-project/src/lib.rs b/crates/gitbutler-project/src/lib.rs index 200f90172d..49185ae5c0 100644 --- a/crates/gitbutler-project/src/lib.rs +++ b/crates/gitbutler-project/src/lib.rs @@ -7,3 +7,14 @@ mod storage; pub use controller::Controller; pub use project::{ApiProject, AuthKey, CodePushState, FetchResult, Project, ProjectId}; pub use storage::UpdateRequest; + +/// A utility to be used from applications to optimize `git2` configuration. +/// See comments for details. +pub fn configure_git2() { + // Do not re-hash each decoded objects for quite a significant performance gain. + // This delegates object validation to `git fsck`, which seems fair. + git2::opts::strict_hash_verification(false); + // Thus far, no broken object was created, and if that would be the case, tests should catch it. + // These settings are only changed from `main` of applications. + git2::opts::strict_object_creation(false); +} diff --git a/crates/gitbutler-repo/Cargo.toml b/crates/gitbutler-repo/Cargo.toml index 73397bb0a7..02f3bd2abd 100644 --- a/crates/gitbutler-repo/Cargo.toml +++ b/crates/gitbutler-repo/Cargo.toml @@ -12,7 +12,7 @@ anyhow = "1.0.86" bstr.workspace = true tokio = { workspace = true, features = [ "rt-multi-thread", "rt", "macros", "sync" ] } gitbutler-git.workspace = true -tracing = "0.1.40" +tracing.workspace = true tempfile = "3.10" serde = { workspace = true, features = ["std"]} log = "^0.4" diff --git a/crates/gitbutler-secret/Cargo.toml b/crates/gitbutler-secret/Cargo.toml index f89fb40831..a1bd07b517 100644 --- a/crates/gitbutler-secret/Cargo.toml +++ b/crates/gitbutler-secret/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] anyhow = "1.0.86" -tracing = "0.1.40" +tracing.workspace = true serde = { workspace = true, features = ["std"]} gix = { workspace = true, features = ["dirwalk", "credentials", "parallel"] } keyring.workspace = true diff --git a/crates/gitbutler-serde/src/bstring.rs b/crates/gitbutler-serde/src/bstring.rs index 86b982ab56..9d166f5100 100644 --- a/crates/gitbutler-serde/src/bstring.rs +++ b/crates/gitbutler-serde/src/bstring.rs @@ -65,6 +65,13 @@ impl From<&BStr> for BStringForFrontend { } } +/// Primarily for tests +impl From<&str> for BStringForFrontend { + fn from(value: &str) -> Self { + BStringForFrontend(value.into()) + } +} + impl PartialEq<&str> for BStringForFrontend { fn eq(&self, other: &&str) -> bool { self.0.eq(other) diff --git a/crates/gitbutler-sync/Cargo.toml b/crates/gitbutler-sync/Cargo.toml index 54f3d57bba..4371a0f41d 100644 --- a/crates/gitbutler-sync/Cargo.toml +++ b/crates/gitbutler-sync/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] anyhow = "1.0.86" -tracing = "0.1.40" +tracing.workspace = true itertools = "0.13" git2.workspace = true gitbutler-oplog.workspace = true diff --git a/crates/gitbutler-tauri/Cargo.toml b/crates/gitbutler-tauri/Cargo.toml index 0b9168d00c..45e1e2bb4c 100644 --- a/crates/gitbutler-tauri/Cargo.toml +++ b/crates/gitbutler-tauri/Cargo.toml @@ -29,7 +29,7 @@ dirs = "5.0.1" fslock.workspace = true futures.workspace = true git2.workspace = true -gix = { workspace = true, features = ["max-performance-safe"] } +gix = { workspace = true, features = ["max-performance"] } once_cell = "1.19" reqwest = { version = "0.12.4", features = ["json"] } serde.workspace = true @@ -44,9 +44,9 @@ log = "^0.4" thiserror.workspace = true # The features here optimize for performance. tokio = { workspace = true, features = ["rt-multi-thread", "parking_lot"] } -tracing = "0.1.40" +tracing.workspace = true tracing-appender = "0.2.3" -tracing-subscriber = "0.3.17" +tracing-subscriber.workspace = true gitbutler-watcher.workspace = true gitbutler-branch-actions.workspace = true gitbutler-oplog.workspace = true diff --git a/crates/gitbutler-tauri/src/main.rs b/crates/gitbutler-tauri/src/main.rs index 07af10ec3b..bbc070b89f 100644 --- a/crates/gitbutler-tauri/src/main.rs +++ b/crates/gitbutler-tauri/src/main.rs @@ -20,6 +20,7 @@ use tauri::{generate_context, Manager}; use tauri_plugin_log::LogTarget; fn main() { + gitbutler_project::configure_git2(); let tauri_context = generate_context!(); gitbutler_secret::secret::set_application_namespace( &tauri_context.config().tauri.bundle.identifier, diff --git a/crates/gitbutler-watcher/Cargo.toml b/crates/gitbutler-watcher/Cargo.toml index fe4802f11a..b2ebed9dfc 100644 --- a/crates/gitbutler-watcher/Cargo.toml +++ b/crates/gitbutler-watcher/Cargo.toml @@ -16,7 +16,7 @@ thiserror.workspace = true anyhow = "1.0.86" tokio = { workspace = true, features = ["macros"] } tokio-util = "0.7.11" -tracing = "0.1.40" +tracing.workspace = true gix = { workspace = true, features = [ "excludes", "blocking-network-client", diff --git a/crates/gitbutler-watcher/vendor/debouncer/Cargo.toml b/crates/gitbutler-watcher/vendor/debouncer/Cargo.toml index 4dbc674cab..61f6cf252c 100644 --- a/crates/gitbutler-watcher/vendor/debouncer/Cargo.toml +++ b/crates/gitbutler-watcher/vendor/debouncer/Cargo.toml @@ -11,7 +11,7 @@ doctest = false mock_instant = ["dep:mock_instant"] [dependencies] -tracing = "0.1.40" +tracing.workspace = true notify = { version = "6.0.1" } parking_lot.workspace = true