mirror of
https://github.com/gitui-org/gitui
synced 2026-05-23 08:58:21 +00:00
Merge 30f2df31c4 into 8619c07f3f
This commit is contained in:
commit
ad40a6044f
4 changed files with 239 additions and 731 deletions
|
|
@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Fixes
|
||||
* crash when opening submodule ([#2895](https://github.com/gitui-org/gitui/issues/2895))
|
||||
* when staging the last file in a directory, the first item after the directory is no longer skipped [[@Tillerino](https://github.com/Tillerino)] ([#2748](https://github.com/gitui-org/gitui/issues/2748))
|
||||
* support SSH commit signing through ssh-agent and external signer programs ([#2188](https://github.com/gitui-org/gitui/issues/2188))
|
||||
|
||||
## [0.28.1] - 2026-03-21
|
||||
|
||||
|
|
|
|||
635
Cargo.lock
generated
635
Cargo.lock
generated
|
|
@ -17,41 +17,6 @@ version = "2.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||
|
||||
[[package]]
|
||||
name = "aead"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aes"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cipher",
|
||||
"cpufeatures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aes-gcm"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1"
|
||||
dependencies = [
|
||||
"aead",
|
||||
"aes",
|
||||
"cipher",
|
||||
"ctr",
|
||||
"ghash",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
|
|
@ -152,7 +117,6 @@ version = "0.28.1"
|
|||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"crossbeam-channel",
|
||||
"dirs",
|
||||
"easy-cast",
|
||||
"env_logger",
|
||||
"fuzzy-matcher",
|
||||
|
|
@ -168,7 +132,6 @@ dependencies = [
|
|||
"scopetime",
|
||||
"serde",
|
||||
"serial_test",
|
||||
"ssh-key",
|
||||
"tempfile",
|
||||
"thiserror 2.0.18",
|
||||
"unicode-truncate",
|
||||
|
|
@ -205,35 +168,12 @@ dependencies = [
|
|||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base16ct"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
||||
|
||||
[[package]]
|
||||
name = "bcrypt-pbkdf"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6aeac2e1fe888769f34f05ac343bbef98b14d1ffb292ab69d4608b3abc86f2a2"
|
||||
dependencies = [
|
||||
"blowfish",
|
||||
"pbkdf2",
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.3"
|
||||
|
|
@ -297,25 +237,6 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-padding"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blowfish"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.12.0"
|
||||
|
|
@ -380,15 +301,6 @@ dependencies = [
|
|||
"rustversion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cbc"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6"
|
||||
dependencies = [
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.7"
|
||||
|
|
@ -412,17 +324,6 @@ version = "0.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "chacha20"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cipher",
|
||||
"cpufeatures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.44"
|
||||
|
|
@ -434,16 +335,6 @@ dependencies = [
|
|||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"inout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.57"
|
||||
|
|
@ -510,12 +401,6 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.10.0"
|
||||
|
|
@ -628,18 +513,6 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-bigint"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"rand_core",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
|
|
@ -660,41 +533,6 @@ dependencies = [
|
|||
"phf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctr"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
|
||||
dependencies = [
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curve25519-dalek"
|
||||
version = "4.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"curve25519-dalek-derive",
|
||||
"digest",
|
||||
"fiat-crypto",
|
||||
"rustc_version",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curve25519-dalek-derive"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.10"
|
||||
|
|
@ -750,16 +588,6 @@ version = "0.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5729f5117e208430e437df2f4843f5e5952997175992d1414f94c57d61e270b4"
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.7.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.5.8"
|
||||
|
|
@ -804,9 +632,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"const-oid",
|
||||
"crypto-common",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -862,66 +688,12 @@ version = "0.5.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23f40539c229fc2e4674bdecdf24bfcc2cb83631ca911c78a035fa9f2381c32b"
|
||||
|
||||
[[package]]
|
||||
name = "ecdsa"
|
||||
version = "0.16.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"
|
||||
dependencies = [
|
||||
"der",
|
||||
"digest",
|
||||
"elliptic-curve",
|
||||
"rfc6979",
|
||||
"signature",
|
||||
"spki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ed25519"
|
||||
version = "2.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
|
||||
dependencies = [
|
||||
"signature",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ed25519-dalek"
|
||||
version = "2.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871"
|
||||
dependencies = [
|
||||
"curve25519-dalek",
|
||||
"ed25519",
|
||||
"sha2",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||
|
||||
[[package]]
|
||||
name = "elliptic-curve"
|
||||
version = "0.13.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
|
||||
dependencies = [
|
||||
"base16ct",
|
||||
"crypto-bigint",
|
||||
"digest",
|
||||
"ff",
|
||||
"generic-array",
|
||||
"group",
|
||||
"pkcs8",
|
||||
"rand_core",
|
||||
"sec1",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "1.0.0"
|
||||
|
|
@ -1028,22 +800,6 @@ version = "2.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||
|
||||
[[package]]
|
||||
name = "ff"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fiat-crypto"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
|
||||
|
||||
[[package]]
|
||||
name = "filedescriptor"
|
||||
version = "0.8.3"
|
||||
|
|
@ -1186,7 +942,6 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
|||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1235,16 +990,6 @@ dependencies = [
|
|||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ghash"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1"
|
||||
dependencies = [
|
||||
"opaque-debug",
|
||||
"polyval",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.32.3"
|
||||
|
|
@ -2120,17 +1865,6 @@ dependencies = [
|
|||
"gix-validate",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "group"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
|
||||
dependencies = [
|
||||
"ff",
|
||||
"rand_core",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hash32"
|
||||
version = "0.3.1"
|
||||
|
|
@ -2188,15 +1922,6 @@ version = "0.4.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "hmac"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
||||
dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.61"
|
||||
|
|
@ -2418,16 +2143,6 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
|
||||
dependencies = [
|
||||
"block-padding",
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "insta"
|
||||
version = "1.44.3"
|
||||
|
|
@ -2588,9 +2303,6 @@ name = "lazy_static"
|
|||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
dependencies = [
|
||||
"spin",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "leb128fmt"
|
||||
|
|
@ -2618,12 +2330,6 @@ dependencies = [
|
|||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.3"
|
||||
|
|
@ -2864,23 +2570,6 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint-dig"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"lazy_static",
|
||||
"libm",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-traits",
|
||||
"rand",
|
||||
"smallvec",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.2.0"
|
||||
|
|
@ -2898,26 +2587,6 @@ dependencies = [
|
|||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
|
|
@ -2925,7 +2594,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2980,12 +2648,6 @@ dependencies = [
|
|||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-probe"
|
||||
version = "0.1.5"
|
||||
|
|
@ -3029,44 +2691,6 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "p256"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
|
||||
dependencies = [
|
||||
"ecdsa",
|
||||
"elliptic-curve",
|
||||
"primeorder",
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "p384"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209"
|
||||
dependencies = [
|
||||
"ecdsa",
|
||||
"elliptic-curve",
|
||||
"primeorder",
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "p521"
|
||||
version = "0.13.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2"
|
||||
dependencies = [
|
||||
"base16ct",
|
||||
"ecdsa",
|
||||
"elliptic-curve",
|
||||
"primeorder",
|
||||
"rand_core",
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.5"
|
||||
|
|
@ -3090,24 +2714,6 @@ dependencies = [
|
|||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pbkdf2"
|
||||
version = "0.12.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
|
||||
dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pem-rfc7468"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.1"
|
||||
|
|
@ -3221,27 +2827,6 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pkcs1"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f"
|
||||
dependencies = [
|
||||
"der",
|
||||
"pkcs8",
|
||||
"spki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkcs8"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
|
||||
dependencies = [
|
||||
"der",
|
||||
"spki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.31"
|
||||
|
|
@ -3261,29 +2846,6 @@ dependencies = [
|
|||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "poly1305"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
|
||||
dependencies = [
|
||||
"cpufeatures",
|
||||
"opaque-debug",
|
||||
"universal-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "polyval"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"opaque-debug",
|
||||
"universal-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.10.0"
|
||||
|
|
@ -3305,15 +2867,6 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pretty_assertions"
|
||||
version = "1.4.1"
|
||||
|
|
@ -3334,15 +2887,6 @@ dependencies = [
|
|||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "primeorder"
|
||||
version = "0.13.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
|
||||
dependencies = [
|
||||
"elliptic-curve",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.94"
|
||||
|
|
@ -3397,17 +2941,6 @@ version = "0.8.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
|
|
@ -3416,9 +2949,6 @@ name = "rand_core"
|
|||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom 0.2.15",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ratatui"
|
||||
|
|
@ -3591,16 +3121,6 @@ version = "0.8.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
[[package]]
|
||||
name = "rfc6979"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
|
||||
dependencies = [
|
||||
"hmac",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ron"
|
||||
version = "0.12.0"
|
||||
|
|
@ -3615,27 +3135,6 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rsa"
|
||||
version = "0.9.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
"digest",
|
||||
"num-bigint-dig",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"pkcs1",
|
||||
"pkcs8",
|
||||
"rand_core",
|
||||
"sha2",
|
||||
"signature",
|
||||
"spki",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.24"
|
||||
|
|
@ -3726,20 +3225,6 @@ version = "3.0.8"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "584e070911c7017da6cb2eb0788d09f43d789029b5877d3e5ecc8acf86ceee21"
|
||||
|
||||
[[package]]
|
||||
name = "sec1"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
|
||||
dependencies = [
|
||||
"base16ct",
|
||||
"der",
|
||||
"generic-array",
|
||||
"pkcs8",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.24"
|
||||
|
|
@ -3903,16 +3388,6 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signature"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
|
||||
dependencies = [
|
||||
"digest",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "similar"
|
||||
version = "2.7.0"
|
||||
|
|
@ -3950,73 +3425,6 @@ version = "1.15.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||
|
||||
[[package]]
|
||||
name = "spki"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"der",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ssh-cipher"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "caac132742f0d33c3af65bfcde7f6aa8f62f0e991d80db99149eb9d44708784f"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"aes-gcm",
|
||||
"cbc",
|
||||
"chacha20",
|
||||
"cipher",
|
||||
"ctr",
|
||||
"poly1305",
|
||||
"ssh-encoding",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ssh-encoding"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb9242b9ef4108a78e8cd1a2c98e193ef372437f8c22be363075233321dd4a15"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"pem-rfc7468",
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ssh-key"
|
||||
version = "0.6.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b86f5297f0f04d08cabaa0f6bff7cb6aec4d9c3b49d87990d63da9d9156a8c3"
|
||||
dependencies = [
|
||||
"bcrypt-pbkdf",
|
||||
"ed25519-dalek",
|
||||
"num-bigint-dig",
|
||||
"p256",
|
||||
"p384",
|
||||
"p521",
|
||||
"rand_core",
|
||||
"rsa",
|
||||
"sec1",
|
||||
"sha2",
|
||||
"signature",
|
||||
"ssh-cipher",
|
||||
"ssh-encoding",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
|
|
@ -4076,12 +3484,6 @@ dependencies = [
|
|||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
|
|
@ -4440,16 +3842,6 @@ version = "0.2.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||
|
||||
[[package]]
|
||||
name = "universal-hash"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.4"
|
||||
|
|
@ -5126,27 +4518,6 @@ dependencies = [
|
|||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.7.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerofrom"
|
||||
version = "0.1.5"
|
||||
|
|
@ -5168,12 +4539,6 @@ dependencies = [
|
|||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
|
||||
|
||||
[[package]]
|
||||
name = "zerovec"
|
||||
version = "0.10.4"
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ keywords = ["git"]
|
|||
[dependencies]
|
||||
bitflags = "2"
|
||||
crossbeam-channel = "0.5"
|
||||
dirs = "6.0"
|
||||
easy-cast = "0.5"
|
||||
fuzzy-matcher = "0.3"
|
||||
git2 = "0.20"
|
||||
|
|
@ -34,7 +33,7 @@ rayon = "1.11"
|
|||
rayon-core = "1.13"
|
||||
scopetime = { path = "../scopetime", version = "0.1" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
ssh-key = { version = "0.6.7", features = ["crypto", "encryption"] }
|
||||
tempfile = "3"
|
||||
thiserror = "2.0"
|
||||
unicode-truncate = "2.0"
|
||||
url = "2.5"
|
||||
|
|
@ -44,7 +43,6 @@ env_logger = "0.11"
|
|||
invalidstring = { path = "../invalidstring", version = "0.1" }
|
||||
pretty_assertions = "1.4"
|
||||
serial_test = "3.3"
|
||||
tempfile = "3"
|
||||
|
||||
[features]
|
||||
default = ["trace-libgit"]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
//! Sign commit data.
|
||||
|
||||
use ssh_key::{HashAlg, LineEnding, PrivateKey};
|
||||
use std::path::PathBuf;
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
/// Error type for [`SignBuilder`], used to create [`Sign`]'s
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
|
|
@ -72,11 +71,11 @@ pub trait Sign {
|
|||
|
||||
/// only available in `#[cfg(test)]` helping to diagnose issues
|
||||
#[cfg(test)]
|
||||
fn program(&self) -> &String;
|
||||
fn program(&self) -> String;
|
||||
|
||||
/// only available in `#[cfg(test)]` helping to diagnose issues
|
||||
#[cfg(test)]
|
||||
fn signing_key(&self) -> &String;
|
||||
fn signing_key(&self) -> String;
|
||||
}
|
||||
|
||||
/// A builder to facilitate the creation of a signing method ([`Sign`]) by examining the git configuration.
|
||||
|
|
@ -156,35 +155,91 @@ impl SignBuilder {
|
|||
String::from("x509"),
|
||||
)),
|
||||
"ssh" => {
|
||||
let ssh_signer = config
|
||||
let program = config
|
||||
.get_string("gpg.ssh.program")
|
||||
.unwrap_or_else(|_| "ssh-keygen".to_string());
|
||||
|
||||
let signing_key = config
|
||||
.get_string("user.signingKey")
|
||||
.ok()
|
||||
.and_then(|key_path| {
|
||||
key_path.strip_prefix('~').map_or_else(
|
||||
|| Some(PathBuf::from(&key_path)),
|
||||
|ssh_key_path| {
|
||||
dirs::home_dir().map(|home| {
|
||||
home.join(
|
||||
ssh_key_path
|
||||
.strip_prefix('/')
|
||||
.unwrap_or(ssh_key_path),
|
||||
)
|
||||
})
|
||||
},
|
||||
.map_err(|err| {
|
||||
SignBuilderError::SSHSigningKey(
|
||||
err.to_string(),
|
||||
)
|
||||
})
|
||||
.ok_or_else(|| {
|
||||
SignBuilderError::SSHSigningKey(String::from(
|
||||
"ssh key setting absent",
|
||||
))
|
||||
})
|
||||
.and_then(SSHSign::new)?;
|
||||
let signer: Box<dyn Sign> = Box::new(ssh_signer);
|
||||
Ok(signer)
|
||||
})?;
|
||||
|
||||
let (
|
||||
signing_key_path,
|
||||
use_agent,
|
||||
public_key_temp_file,
|
||||
) = {
|
||||
let signing_key = signing_key
|
||||
.strip_prefix("key::")
|
||||
.unwrap_or(&signing_key);
|
||||
if Self::looks_like_ssh_public_key(signing_key) {
|
||||
let temp_file =
|
||||
Self::write_signing_key_to_temp_file(
|
||||
signing_key,
|
||||
)?;
|
||||
(
|
||||
temp_file.path().display().to_string(),
|
||||
true,
|
||||
Some(temp_file),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
signing_key.to_string(),
|
||||
Self::path_contains_ssh_public_key(
|
||||
signing_key,
|
||||
),
|
||||
None,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Box::new(SSHSign {
|
||||
program,
|
||||
signing_key_path,
|
||||
use_agent,
|
||||
public_key_temp_file,
|
||||
}))
|
||||
}
|
||||
_ => Err(SignBuilderError::InvalidFormat(format)),
|
||||
}
|
||||
}
|
||||
|
||||
fn write_signing_key_to_temp_file(
|
||||
signing_key: &str,
|
||||
) -> Result<NamedTempFile, SignBuilderError> {
|
||||
use std::io::Write;
|
||||
|
||||
let mut temp_file = NamedTempFile::new().map_err(|err| {
|
||||
SignBuilderError::SSHSigningKey(err.to_string())
|
||||
})?;
|
||||
writeln!(temp_file, "{signing_key}").map_err(|err| {
|
||||
SignBuilderError::SSHSigningKey(err.to_string())
|
||||
})?;
|
||||
Ok(temp_file)
|
||||
}
|
||||
|
||||
fn looks_like_ssh_public_key(signing_key: &str) -> bool {
|
||||
let key_type = signing_key
|
||||
.split_ascii_whitespace()
|
||||
.next()
|
||||
.unwrap_or_default();
|
||||
|
||||
key_type.starts_with("ssh-")
|
||||
|| key_type.starts_with("ecdsa-sha2-")
|
||||
|| key_type.starts_with("sk-ssh-")
|
||||
|| key_type.starts_with("sk-ecdsa-")
|
||||
}
|
||||
|
||||
fn path_contains_ssh_public_key(signing_key_path: &str) -> bool {
|
||||
std::fs::read_to_string(signing_key_path).ok().is_some_and(
|
||||
|contents| {
|
||||
Self::looks_like_ssh_public_key(contents.trim())
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Sign commit data using `OpenPGP`
|
||||
|
|
@ -193,16 +248,6 @@ pub struct GPGSign {
|
|||
signing_key: String,
|
||||
}
|
||||
|
||||
impl GPGSign {
|
||||
/// Create new [`GPGSign`] using given program and signing key.
|
||||
pub fn new(program: &str, signing_key: &str) -> Self {
|
||||
Self {
|
||||
program: program.to_string(),
|
||||
signing_key: signing_key.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sign for GPGSign {
|
||||
fn sign(
|
||||
&self,
|
||||
|
|
@ -261,55 +306,23 @@ impl Sign for GPGSign {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn program(&self) -> &String {
|
||||
&self.program
|
||||
fn program(&self) -> String {
|
||||
self.program.clone()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn signing_key(&self) -> &String {
|
||||
&self.signing_key
|
||||
fn signing_key(&self) -> String {
|
||||
self.signing_key.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Sign commit data using `SSHDiskKeySign`
|
||||
/// Sign commit data using `ssh-keygen` or a git-compatible SSH signer.
|
||||
pub struct SSHSign {
|
||||
#[cfg(test)]
|
||||
program: String,
|
||||
#[cfg(test)]
|
||||
key_path: String,
|
||||
secret_key: PrivateKey,
|
||||
}
|
||||
|
||||
impl SSHSign {
|
||||
/// Create new `SSHDiskKeySign` for sign.
|
||||
pub fn new(mut key: PathBuf) -> Result<Self, SignBuilderError> {
|
||||
key.set_extension("");
|
||||
if key.is_file() {
|
||||
#[cfg(test)]
|
||||
let key_path = format!("{}", &key.display());
|
||||
std::fs::read(key)
|
||||
.ok()
|
||||
.and_then(|bytes| {
|
||||
PrivateKey::from_openssh(bytes).ok()
|
||||
})
|
||||
.map(|secret_key| Self {
|
||||
#[cfg(test)]
|
||||
program: "ssh".to_string(),
|
||||
#[cfg(test)]
|
||||
key_path,
|
||||
secret_key,
|
||||
})
|
||||
.ok_or_else(|| {
|
||||
SignBuilderError::SSHSigningKey(String::from(
|
||||
"Fail to read the private key for sign.",
|
||||
))
|
||||
})
|
||||
} else {
|
||||
Err(SignBuilderError::SSHSigningKey(
|
||||
String::from("Currently, we only support a pair of ssh key in disk."),
|
||||
))
|
||||
}
|
||||
}
|
||||
signing_key_path: String,
|
||||
use_agent: bool,
|
||||
// Keep inline public-key temp files alive until the signer process reads them.
|
||||
public_key_temp_file: Option<NamedTempFile>,
|
||||
}
|
||||
|
||||
impl Sign for SSHSign {
|
||||
|
|
@ -317,23 +330,72 @@ impl Sign for SSHSign {
|
|||
&self,
|
||||
commit: &[u8],
|
||||
) -> Result<(String, Option<String>), SignError> {
|
||||
let sig = self
|
||||
.secret_key
|
||||
.sign("git", HashAlg::Sha256, commit)
|
||||
.map_err(|err| SignError::Spawn(err.to_string()))?
|
||||
.to_pem(LineEnding::LF)
|
||||
.map_err(|err| SignError::Spawn(err.to_string()))?;
|
||||
Ok((sig, None))
|
||||
use std::io::Write;
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
let _keep_public_key_file_alive =
|
||||
self.public_key_temp_file.as_ref();
|
||||
|
||||
let mut cmd = Command::new(&self.program);
|
||||
cmd.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.arg("-Y")
|
||||
.arg("sign")
|
||||
.arg("-n")
|
||||
.arg("git")
|
||||
.arg("-f")
|
||||
.arg(&self.signing_key_path);
|
||||
|
||||
if self.use_agent {
|
||||
cmd.arg("-U");
|
||||
}
|
||||
|
||||
log::trace!("signing command: {cmd:?}");
|
||||
|
||||
let mut child = cmd
|
||||
.spawn()
|
||||
.map_err(|e| SignError::Spawn(e.to_string()))?;
|
||||
|
||||
let mut stdin = child.stdin.take().ok_or(SignError::Stdin)?;
|
||||
|
||||
stdin
|
||||
.write_all(commit)
|
||||
.map_err(|e| SignError::WriteBuffer(e.to_string()))?;
|
||||
drop(stdin);
|
||||
|
||||
let output = child
|
||||
.wait_with_output()
|
||||
.map_err(|e| SignError::Output(e.to_string()))?;
|
||||
|
||||
if !output.status.success() {
|
||||
let error_msg = std::str::from_utf8(&output.stderr)
|
||||
.unwrap_or("[error could not be read from stderr]");
|
||||
if error_msg.contains("passphrase") {
|
||||
return Err(SignError::Shellout(String::from(
|
||||
"Currently, we only support unencrypted pairs of ssh keys in disk or ssh-agents",
|
||||
)));
|
||||
}
|
||||
return Err(SignError::Shellout(format!(
|
||||
"failed to sign data, program '{}' exited non-zero: {}",
|
||||
&self.program, error_msg
|
||||
)));
|
||||
}
|
||||
|
||||
let signed_commit = std::str::from_utf8(&output.stdout)
|
||||
.map_err(|e| SignError::Shellout(e.to_string()))?;
|
||||
|
||||
Ok((signed_commit.to_string(), None))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn program(&self) -> &String {
|
||||
&self.program
|
||||
fn program(&self) -> String {
|
||||
self.program.clone()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn signing_key(&self) -> &String {
|
||||
&self.key_path
|
||||
fn signing_key(&self) -> String {
|
||||
self.signing_key_path.clone()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -424,18 +486,100 @@ mod tests {
|
|||
#[test]
|
||||
fn test_ssh_program_configs() -> Result<()> {
|
||||
let (_tmp_dir, repo) = repo_init_empty()?;
|
||||
let temp_file = tempfile::NamedTempFile::new()
|
||||
.expect("failed to create temp file");
|
||||
|
||||
{
|
||||
let mut config = repo.config()?;
|
||||
config.set_str("gpg.program", "ssh")?;
|
||||
config.set_str("user.signingKey", "/tmp/key.pub")?;
|
||||
config.set_str("gpg.format", "ssh")?;
|
||||
config.set_str(
|
||||
"user.signingKey",
|
||||
temp_file.path().to_str().unwrap(),
|
||||
)?;
|
||||
}
|
||||
|
||||
let sign =
|
||||
SignBuilder::from_gitconfig(&repo, &repo.config()?)?;
|
||||
|
||||
assert_eq!("ssh", sign.program());
|
||||
assert_eq!("/tmp/key.pub", sign.signing_key());
|
||||
assert_eq!("ssh-keygen", sign.program());
|
||||
assert_eq!(
|
||||
temp_file.path().to_str().unwrap(),
|
||||
sign.signing_key()
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ssh_keyliteral_config() -> Result<()> {
|
||||
use std::path::PathBuf;
|
||||
|
||||
let (_tmp_dir, repo) = repo_init_empty()?;
|
||||
|
||||
{
|
||||
let mut config = repo.config()?;
|
||||
config.set_str("gpg.format", "ssh")?;
|
||||
config
|
||||
.set_str("user.signingKey", "ssh-ed25519 test-key")?;
|
||||
}
|
||||
|
||||
let sign =
|
||||
SignBuilder::from_gitconfig(&repo, &repo.config()?)?;
|
||||
|
||||
assert_eq!("ssh-keygen", sign.program());
|
||||
assert!(PathBuf::from(sign.signing_key()).is_file());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ssh_keyliteral_with_key_prefix_config() -> Result<()> {
|
||||
use std::path::PathBuf;
|
||||
|
||||
let (_tmp_dir, repo) = repo_init_empty()?;
|
||||
|
||||
{
|
||||
let mut config = repo.config()?;
|
||||
config.set_str("gpg.format", "ssh")?;
|
||||
config.set_str(
|
||||
"user.signingKey",
|
||||
"key::ssh-ed25519 test-key",
|
||||
)?;
|
||||
}
|
||||
|
||||
let sign =
|
||||
SignBuilder::from_gitconfig(&repo, &repo.config()?)?;
|
||||
|
||||
assert_eq!("ssh-keygen", sign.program());
|
||||
assert!(PathBuf::from(sign.signing_key()).is_file());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ssh_external_bin_config() -> Result<()> {
|
||||
let (_tmp_dir, repo) = repo_init_empty()?;
|
||||
let temp_file = tempfile::NamedTempFile::new()
|
||||
.expect("failed to create temp file");
|
||||
|
||||
{
|
||||
let mut config = repo.config()?;
|
||||
config.set_str("gpg.format", "ssh")?;
|
||||
config.set_str("gpg.ssh.program", "/opt/ssh/signer")?;
|
||||
config.set_str(
|
||||
"user.signingKey",
|
||||
temp_file.path().to_str().unwrap(),
|
||||
)?;
|
||||
}
|
||||
|
||||
let sign =
|
||||
SignBuilder::from_gitconfig(&repo, &repo.config()?)?;
|
||||
|
||||
assert_eq!("/opt/ssh/signer", sign.program());
|
||||
assert_eq!(
|
||||
temp_file.path().to_str().unwrap(),
|
||||
sign.signing_key()
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue