diff --git a/Cargo.lock b/Cargo.lock index 59398e3..b3eac59 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -101,11 +101,11 @@ dependencies = [ [[package]] name = "assert_cmd" -version = "2.2.0" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a686bbee5efb88a82df0621b236e74d925f470e5445d3220a5648b892ec99c9" +checksum = "2aa3a22042e45de04255c7bf3626e239f450200fd0493c1e382263544b20aea6" dependencies = [ - "anstream 0.6.13", + "anstream 1.0.0", "anstyle", "bstr", "libc", @@ -131,6 +131,17 @@ dependencies = [ "tempfile", ] +[[package]] +name = "auth-git2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aec364a6ee335b23a7e77703100f5103965810f91a9ef6319a004a7e7b8e2b66" +dependencies = [ + "dirs", + "git2", + "terminal-prompt", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -173,15 +184,6 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - [[package]] name = "bstr" version = "1.12.1" @@ -216,9 +218,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -251,9 +253,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.6.0" +version = "4.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19c9f1dde76b736e3681f28cec9d5a61299cbaae0fce80a68e43724ad56031eb" +checksum = "e0a7a9bfdb35811f9e59832f0f05975114d2251b415fb534108e6f34060fd772" dependencies = [ "clap", "clap_lex", @@ -263,9 +265,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck", "proc-macro2", @@ -281,9 +283,9 @@ checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" [[package]] name = "clap_mangen" -version = "0.2.33" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e30ffc187e2e3aeafcd1c6e2aa416e29739454c0ccaa419226d5ecd181f2d78" +checksum = "d82842b45bf9f6a3be090dd860095ac30728042c08e0d6261ca7259b5d850f07" dependencies = [ "clap", "roff", @@ -304,41 +306,19 @@ dependencies = [ "windows", ] -[[package]] -name = "console" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" -dependencies = [ - "encode_unicode 0.3.6", - "lazy_static", - "libc", - "unicode-width 0.1.11", - "windows-sys 0.45.0", -] - [[package]] name = "console" version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03e45a4a8926227e4197636ba97a9fc9b00477e9f4bd711395687c5f0734bec4" dependencies = [ - "encode_unicode 1.0.0", + "encode_unicode", "libc", "once_cell", "unicode-width 0.2.2", "windows-sys 0.61.2", ] -[[package]] -name = "cpufeatures" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" -dependencies = [ - "libc", -] - [[package]] name = "crossbeam-deque" version = "0.8.6" @@ -364,36 +344,13 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "dialoguer" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" -dependencies = [ - "console 0.15.7", - "shell-words", - "tempfile", - "thiserror 1.0.58", - "zeroize", -] - [[package]] name = "dialoguer" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25f104b501bf2364e78d0d3974cbc774f738f5865306ed128e1e0d7499c0ad96" dependencies = [ - "console 0.16.2", + "console", "fuzzy-matcher", "shell-words", "tempfile", @@ -406,35 +363,25 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - [[package]] name = "dirs" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] @@ -454,12 +401,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" -[[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - [[package]] name = "encode_unicode" version = "1.0.0" @@ -478,11 +419,11 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.9" +version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d" +checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" dependencies = [ - "anstream 0.6.13", + "anstream 1.0.0", "anstyle", "env_filter", "jiff", @@ -501,9 +442,9 @@ dependencies = [ [[package]] name = "expectrl" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0e0706d01b4f43adaf7e0fb460e07477c36b74ae60fdeb1d045001bd77b4bd1" +checksum = "9e0df3044b2257277f573d1e40912ebd4d5891f7588640e3125cbbbb24ff7be3" dependencies = [ "conpty", "nix", @@ -544,16 +485,6 @@ dependencies = [ "thread_local", ] -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "getrandom" version = "0.2.10" @@ -581,7 +512,7 @@ dependencies = [ "clap-verbosity-flag", "clap_complete", "clap_mangen", - "dialoguer 0.12.0", + "dialoguer", "env_logger", "expectrl", "git-workon-fixture", @@ -607,7 +538,6 @@ dependencies = [ "env_logger", "git-workon-lib", "git2", - "git2_credentials", "log", "predicates", "serde_json", @@ -618,11 +548,11 @@ name = "git-workon-lib" version = "0.4.0" dependencies = [ "assert_fs", - "dialoguer 0.12.0", + "auth-git2", + "dialoguer", "env_logger", "git-workon-fixture", "git2", - "git2_credentials", "glob", "ignore", "libc", @@ -630,14 +560,14 @@ dependencies = [ "miette", "predicates", "serde_json", - "thiserror 2.0.18", + "thiserror", ] [[package]] name = "git2" -version = "0.20.4" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b88256088d75a56f8ecfa070513a775dd9107f6530ef14919dac831af9cfe2b" +checksum = "ddddbf932745a6be37109b6112d3ee09696106f848449069d3a57bba937ab82e" dependencies = [ "bitflags 2.11.0", "libc", @@ -648,20 +578,6 @@ dependencies = [ "url", ] -[[package]] -name = "git2_credentials" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a5ef5b71f0b7c38b9fab78d33a071100a3a3d6f82d80bc8e53ba4b82b6487ed" -dependencies = [ - "dialoguer 0.11.0", - "dirs", - "git2", - "pest", - "pest_derive", - "regex", -] - [[package]] name = "glob" version = "0.3.3" @@ -827,7 +743,7 @@ version = "0.18.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25470f23803092da7d239834776d653104d551bc4d7eacaf31e6837854b8e9eb" dependencies = [ - "console 0.16.2", + "console", "portable-atomic", "unicode-width 0.2.2", "unit-prefix", @@ -904,23 +820,17 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - [[package]] name = "libc" -version = "0.2.183" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libgit2-sys" -version = "0.18.3+1.9.2" +version = "0.18.4+1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9b3acc4b91781bb0b3386669d325163746af5f6e4f73e6d2d630e09a35f3487" +checksum = "9b26f66f35e1871b22efcf7191564123d2a446ca0538cde63c23adfefa9b15b7" dependencies = [ "cc", "libc", @@ -930,6 +840,15 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libredox" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" +dependencies = [ + "libc", +] + [[package]] name = "libssh2-sys" version = "0.3.1" @@ -1135,50 +1054,6 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" -[[package]] -name = "pest" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73935e4d55e2abf7f130186537b19e7a4abc886a0252380b59248af473a3fc9" -dependencies = [ - "thiserror 1.0.58", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef623c9bbfa0eedf5a0efba11a5ee83209c326653ca31ff019bec3a95bfff2b" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e8cba4ec22bada7fc55ffe51e2deb6a0e0db2d0b7ab0b103acc80d2510c190" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pest_meta" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01f71cb40bd8bb94232df14b946909e14660e33fc05db3e50ae2a82d7ea0ca0" -dependencies = [ - "once_cell", - "pest", - "sha2", -] - [[package]] name = "pin-utils" version = "0.1.0" @@ -1272,15 +1147,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.3.5" @@ -1292,13 +1158,13 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.3" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom", - "redox_syscall 0.2.16", - "thiserror 1.0.58", + "libredox", + "thiserror", ] [[package]] @@ -1444,17 +1310,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "sha2" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - [[package]] name = "shell-words" version = "1.1.0" @@ -1536,11 +1391,21 @@ checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.3.5", + "redox_syscall", "rustix 0.38.4", "windows-sys 0.48.0", ] +[[package]] +name = "terminal-prompt" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "572818b3472910acbd5dff46a3413715c18e934b071ab2ba464a7b2c2af16376" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "terminal_size" version = "0.4.3" @@ -1567,33 +1432,13 @@ dependencies = [ "unicode-width 0.1.11", ] -[[package]] -name = "thiserror" -version = "1.0.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" -dependencies = [ - "thiserror-impl 1.0.58", -] - [[package]] name = "thiserror" version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.18", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "thiserror-impl", ] [[package]] @@ -1627,18 +1472,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "typenum" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - -[[package]] -name = "ucd-trie" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" - [[package]] name = "unicase" version = "2.9.0" @@ -1704,12 +1537,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - [[package]] name = "wait-timeout" version = "0.2.0" @@ -1836,15 +1663,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index 97a86b6..d75f11a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,9 +12,9 @@ repository = "https://github.com/lettertwo/git-workon" rust-version = "1.68.2" [workspace.dependencies] -assert_cmd = { version = "2.2.0", features = ["color", "color-auto"] } +assert_cmd = { version = "2.2.2", features = ["color", "color-auto"] } assert_fs = { version = "1.1.3", features = ["color", "color-auto"] } -clap = { version = "4.6.0", features = [ +clap = { version = "4.6.1", features = [ "derive", "color", "wrap_help", @@ -22,14 +22,14 @@ clap = { version = "4.6.0", features = [ "env", ] } clap-verbosity-flag = "3.0.4" -clap_complete = { version = "4.6.0", features = ["unstable-dynamic"] } -clap_mangen = "0.2.33" +clap_complete = { version = "4.6.5", features = ["unstable-dynamic"] } +clap_mangen = "0.3.0" dialoguer = { version = "0.12.0", features = ["fuzzy-select"] } -env_logger = "0.11.6" +env_logger = "0.11.10" git-workon-lib = { version = "0.4.0", path = "./git-workon-lib" } git-workon-fixture = { path = "./git-workon-fixture" } -git2_credentials = { version = "0.15.0", features = ["ui4dialoguer"] } -git2 = { version = "0.20.4", default-features = false, features = [ +auth-git2 = "0.6" +git2 = { version = "0.21.0", default-features = false, features = [ "ssh", "https", ] } @@ -42,7 +42,7 @@ miette = { version = "7.6.0", features = ["fancy"] } owo-colors = "4" predicates = { version = "3.1.4" } supports-color = "3" -expectrl = "0.8" +expectrl = "0.9" pathdiff = "0.2.3" serde_json = "1.0" thiserror = "2.0.18" diff --git a/git-workon-fixture/Cargo.toml b/git-workon-fixture/Cargo.toml index cb5c460..e534ee3 100644 --- a/git-workon-fixture/Cargo.toml +++ b/git-workon-fixture/Cargo.toml @@ -14,7 +14,6 @@ assert_fs.workspace = true env_logger.workspace = true git-workon-lib.workspace = true git2.workspace = true -git2_credentials.workspace = true log.workspace = true predicates.workspace = true serde_json.workspace = true diff --git a/git-workon-fixture/src/predicates/has_config_multivar.rs b/git-workon-fixture/src/predicates/has_config_multivar.rs index af61973..0720215 100644 --- a/git-workon-fixture/src/predicates/has_config_multivar.rs +++ b/git-workon-fixture/src/predicates/has_config_multivar.rs @@ -31,7 +31,7 @@ impl Predicate for HasConfigMultivarPredicate { if let Ok(mut entries) = config.multivar(&self.key, None) { while let Some(entry) = entries.next() { if let Ok(e) = entry { - if let Some(v) = e.value() { + if let Ok(v) = e.value() { actual_values.push(v.to_string()); } } diff --git a/git-workon-fixture/src/predicates/has_remote_url.rs b/git-workon-fixture/src/predicates/has_remote_url.rs index da1f860..e8455ea 100644 --- a/git-workon-fixture/src/predicates/has_remote_url.rs +++ b/git-workon-fixture/src/predicates/has_remote_url.rs @@ -25,7 +25,7 @@ impl Predicate for HasRemoteUrlPredicate { match repo.find_remote(&self.remote_name) { Ok(remote) => match &self.url { Some(expected_url) => remote.url().map(|u| u == expected_url).unwrap_or(false), - None => remote.url().is_some(), + None => remote.url().is_ok(), }, Err(_) => false, } diff --git a/git-workon-fixture/tests/fixture_builder.rs b/git-workon-fixture/tests/fixture_builder.rs index c14f738..4de1ebc 100644 --- a/git-workon-fixture/tests/fixture_builder.rs +++ b/git-workon-fixture/tests/fixture_builder.rs @@ -30,7 +30,7 @@ mod fixture_builder { // Check that the branch has the initial commit assert_eq!( commit.message(), - Some("Initial commit"), + Ok("Initial commit"), "Initial commit message should match" ); @@ -78,7 +78,7 @@ mod fixture_builder { // Check that the branch has the initial commit assert_eq!( commit.message(), - Some("Initial commit"), + Ok("Initial commit"), "Initial commit message should match" ); @@ -133,7 +133,7 @@ mod fixture_builder { // Check that the branch has the initial commit assert_eq!( commit.message(), - Some("Initial commit"), + Ok("Initial commit"), "Initial commit message should match" ); @@ -191,7 +191,7 @@ mod fixture_builder { // Check that the branch has the initial commit assert_eq!( commit.message(), - Some("Initial commit"), + Ok("Initial commit"), "Initial commit message should match" ); @@ -249,7 +249,7 @@ mod fixture_builder { // Check that the branch has the initial commit assert_eq!( commit.message(), - Some("Initial commit"), + Ok("Initial commit"), "Initial commit message should match" ); @@ -316,7 +316,7 @@ mod fixture_builder { // Check that the branch has the initial commit assert_eq!( commit.message(), - Some("Initial commit"), + Ok("Initial commit"), "Initial commit message should match" ); @@ -370,7 +370,7 @@ mod fixture_builder { // Check that the branch has the initial commit assert_eq!( commit.message(), - Some("Initial commit"), + Ok("Initial commit"), "Initial commit message should match" ); @@ -431,7 +431,7 @@ mod fixture_builder { // Check that the branch has the initial commit assert_eq!( commit.message(), - Some("Initial commit"), + Ok("Initial commit"), "Initial commit message should match" ); @@ -481,7 +481,7 @@ mod fixture_builder { // Check that the branch has the initial commit assert_eq!( commit.message(), - Some("Initial commit"), + Ok("Initial commit"), "Initial commit message should match" ); @@ -534,7 +534,7 @@ mod fixture_builder { // Check that the branch has the initial commit assert_eq!( commit.message(), - Some("Initial commit"), + Ok("Initial commit"), "Initial commit message should match" ); @@ -666,7 +666,7 @@ mod fixture_builder { // Verify commit was created let commit = repo.find_commit(commit_oid)?; - assert_eq!(commit.message(), Some("Add two files")); + assert_eq!(commit.message(), Ok("Add two files")); assert_eq!(commit.parent_count(), 1); // Verify files exist in the commit tree @@ -722,7 +722,7 @@ mod fixture_builder { assert_eq!(fixture.cwd()?.file_name(), Some(OsStr::new("docs"))); // Verify we can use the fixture to access the docs worktree - assert_eq!(fixture.head()?.name(), Some("refs/heads/docs")); + assert_eq!(fixture.head()?.name(), Ok("refs/heads/docs")); Ok(()) } diff --git a/git-workon-lib/Cargo.toml b/git-workon-lib/Cargo.toml index 48e7043..7bcd5d3 100644 --- a/git-workon-lib/Cargo.toml +++ b/git-workon-lib/Cargo.toml @@ -27,7 +27,7 @@ vendored = ["git2/vendored-libgit2", "git2/vendored-openssl"] dialoguer.workspace = true env_logger.workspace = true git2.workspace = true -git2_credentials.workspace = true +auth-git2.workspace = true glob.workspace = true ignore.workspace = true libc.workspace = true diff --git a/git-workon-lib/src/clone.rs b/git-workon-lib/src/clone.rs index 19e0743..9db767b 100644 --- a/git-workon-lib/src/clone.rs +++ b/git-workon-lib/src/clone.rs @@ -43,7 +43,8 @@ pub fn clone(path: PathBuf, url: &str, options: CloneOptions) -> Result WorkonConfig<'repo> { if let Ok(mut entries) = config.multivar(key, None) { while let Some(entry) = entries.next() { let entry = entry?; - if let Some(value) = entry.value() { + if let Ok(value) = entry.value() { values.push(value.to_string()); } } diff --git a/git-workon-lib/src/default_branch.rs b/git-workon-lib/src/default_branch.rs index e1beca3..f8dabf0 100644 --- a/git-workon-lib/src/default_branch.rs +++ b/git-workon-lib/src/default_branch.rs @@ -47,12 +47,12 @@ impl<'repo, 'cb> DefaultBranch<'repo, 'cb> { } match cxn.default_branch()?.as_str() { - Some(default_branch) => Ok(default_branch + Ok(default_branch) => Ok(default_branch .strip_prefix("refs/heads/") .unwrap_or(default_branch) .to_string()), - None => Err(DefaultBranchError::NoRemoteDefault { - remote: cxn.remote().name().map(|s| s.to_string()), + Err(_) => Err(DefaultBranchError::NoRemoteDefault { + remote: cxn.remote().name().ok().flatten().map(|s| s.to_string()), } .into()), } @@ -71,11 +71,13 @@ impl<'repo, 'cb> DefaultBranch<'repo, 'cb> { /// Queries the remote for its default branch if one is provided, otherwise /// falls back to `init.defaultbranch` config (defaulting to `"main"`). pub fn get_default_branch_name(repo: &Repository, remote: Option) -> Result { + let auth; let mut default_branch = DefaultBranch::new(repo); if let Some(remote) = remote { - let url = remote.url().map(str::to_string); + let url = remote.url().ok().map(str::to_string); default_branch.remote(remote); - default_branch.remote_callbacks(get_remote_callbacks(repo, url.as_deref())?); + auth = get_remote_callbacks(repo, url.as_deref())?; + default_branch.remote_callbacks(auth.callbacks()); } default_branch.get_name().or_else(|_| { debug!("Failed to read default branch from remote, trying git config"); diff --git a/git-workon-lib/src/get_remote_callbacks.rs b/git-workon-lib/src/get_remote_callbacks.rs index 42252b4..7bef2cc 100644 --- a/git-workon-lib/src/get_remote_callbacks.rs +++ b/git-workon-lib/src/get_remote_callbacks.rs @@ -1,36 +1,52 @@ +use auth_git2::GitAuthenticator; use git2::{Config, ConfigLevel, RemoteCallbacks, Repository}; -use git2_credentials::CredentialHandler; use crate::error::Result; use crate::ssh_config::apply_identity_agent; -/// Build [`git2::RemoteCallbacks`] using the given repo's config to drive -/// credential resolution. Mirrors `git fetch`/`git push` precedence: +/// Holds the credential authenticator and git config needed to build +/// [`git2::RemoteCallbacks`]. +/// +/// auth-git2's credential closure borrows both the authenticator and the config, +/// so this struct keeps them alive while the callbacks are in use. Call +/// [`RemoteAuth::callbacks`] to obtain borrowing callbacks tied to this holder's +/// lifetime. +pub struct RemoteAuth { + authenticator: GitAuthenticator, + config: Config, +} + +impl RemoteAuth { + /// Build credential callbacks that borrow this holder. + pub fn callbacks(&self) -> RemoteCallbacks<'_> { + let mut callbacks = RemoteCallbacks::new(); + callbacks.credentials(self.authenticator.credentials(&self.config)); + callbacks + } +} + +/// Build a [`RemoteAuth`] using the given repo's config to drive credential +/// resolution. Mirrors `git fetch`/`git push` precedence: /// local `.git/config` > worktree config > global > XDG > system. -pub fn get_remote_callbacks<'a>( - repo: &Repository, - url: Option<&str>, -) -> Result> { - build_callbacks(repo.config()?, url) +pub fn get_remote_callbacks(repo: &Repository, url: Option<&str>) -> Result { + build_auth(repo.config()?, url) } -/// Build [`git2::RemoteCallbacks`] for operations that run before a repo -/// exists (e.g. clone). Mirrors `git clone` precedence (global + XDG + system), -/// tolerating a missing `~/.gitconfig`. -pub fn get_remote_callbacks_default<'a>(url: Option<&str>) -> Result> { - build_callbacks(open_default_config_lenient()?, url) +/// Build a [`RemoteAuth`] for operations that run before a repo exists (e.g. +/// clone). Mirrors `git clone` precedence (global + XDG + system), tolerating +/// a missing `~/.gitconfig`. +pub fn get_remote_callbacks_default(url: Option<&str>) -> Result { + build_auth(open_default_config_lenient()?, url) } -fn build_callbacks<'a>(config: Config, url: Option<&str>) -> Result> { +fn build_auth(config: Config, url: Option<&str>) -> Result { if let Some(url) = url { apply_identity_agent(url); } - let mut callbacks = RemoteCallbacks::new(); - let mut credential_handler = CredentialHandler::new(config); - callbacks.credentials(move |url, username, allowed| { - credential_handler.try_next_credential(url, username, allowed) - }); - Ok(callbacks) + Ok(RemoteAuth { + authenticator: GitAuthenticator::default(), + config, + }) } /// Like `Config::open_default()`, but tolerates a missing `~/.gitconfig`. diff --git a/git-workon-lib/src/pr.rs b/git-workon-lib/src/pr.rs index c21d8ce..0fe2070 100644 --- a/git-workon-lib/src/pr.rs +++ b/git-workon-lib/src/pr.rs @@ -393,14 +393,14 @@ pub fn detect_pr_remote(repo: &Repository) -> Result { // Priority: upstream > origin for name in &["upstream", "origin"] { - if remotes.iter().flatten().any(|r| r == *name) { + if remotes.iter().flatten().flatten().any(|r| r == *name) { debug!("Using remote: {}", name); return Ok(name.to_string()); } } // Fall back to first remote - if let Some(first_remote) = remotes.get(0) { + if let Ok(Some(first_remote)) = remotes.get(0) { Ok(first_remote.to_string()) } else { Err(PrError::NoRemoteConfigured.into()) @@ -472,9 +472,10 @@ pub fn fetch_branch(repo: &Repository, remote_name: &str, branch: &str) -> Resul let remote_url = repo .find_remote(remote_name) .ok() - .and_then(|r| r.url().map(str::to_string)); + .and_then(|r| r.url().ok().map(str::to_string)); + let auth = get_remote_callbacks(repo, remote_url.as_deref())?; let mut fetch_options = FetchOptions::new(); - fetch_options.remote_callbacks(get_remote_callbacks(repo, remote_url.as_deref())?); + fetch_options.remote_callbacks(auth.callbacks()); repo.find_remote(remote_name)? .fetch( diff --git a/git-workon-lib/src/ssh_config.rs b/git-workon-lib/src/ssh_config.rs index c952235..c3d80cf 100644 --- a/git-workon-lib/src/ssh_config.rs +++ b/git-workon-lib/src/ssh_config.rs @@ -1,6 +1,6 @@ //! Minimal `~/.ssh/config` parser for extracting `IdentityAgent`. //! -//! libgit2 (and by extension `git2_credentials`) reads the SSH agent socket +//! libgit2 (and by extension `auth-git2`) reads the SSH agent socket //! from `SSH_AUTH_SOCK` only — it does not honour the `IdentityAgent` //! directive in `~/.ssh/config`. This module bridges that gap by parsing the //! config file and applying `IdentityAgent` to the process environment before diff --git a/git-workon-lib/src/stack/graphite.rs b/git-workon-lib/src/stack/graphite.rs index 254274d..261a41a 100644 --- a/git-workon-lib/src/stack/graphite.rs +++ b/git-workon-lib/src/stack/graphite.rs @@ -77,7 +77,7 @@ fn build_parent_map(repo: &Repository) -> Result, StackE let reference = reference.map_err(|e| StackError::GtParseFailed { message: format!("failed to read branch-metadata ref: {e}"), })?; - let Some(refname) = reference.name() else { + let Ok(refname) = reference.name() else { continue; }; let Some(branch) = refname.strip_prefix("refs/branch-metadata/") else { diff --git a/git-workon-lib/src/worktree.rs b/git-workon-lib/src/worktree.rs index ab5650e..aebcb18 100644 --- a/git-workon-lib/src/worktree.rs +++ b/git-workon-lib/src/worktree.rs @@ -77,7 +77,7 @@ impl WorktreeDescriptor { /// Returns the name of the worktree, or `None` if the name is invalid UTF-8. pub fn name(&self) -> Option<&str> { - self.worktree.name() + self.worktree.name().ok().flatten() } /// Returns the filesystem path to the worktree's working directory. @@ -518,7 +518,7 @@ impl WorktreeDescriptor { // Find the remote and extract the URL immediately let url = match repo.find_remote(&remote_name) { - Ok(remote) => remote.url().map(|s| s.to_string()), + Ok(remote) => remote.url().ok().map(|s| s.to_string()), Err(_) => return Ok(None), // Remote doesn't exist }; @@ -542,7 +542,7 @@ impl WorktreeDescriptor { // Find the remote and extract the fetch URL immediately let url = match repo.find_remote(&remote_name) { - Ok(remote) => remote.url().map(|s| s.to_string()), + Ok(remote) => remote.url().ok().map(|s| s.to_string()), Err(_) => return Ok(None), // Remote doesn't exist }; @@ -568,7 +568,9 @@ impl WorktreeDescriptor { let url = match repo.find_remote(&remote_name) { Ok(remote) => remote .pushurl() - .or_else(|| remote.url()) + .ok() + .flatten() + .or_else(|| remote.url().ok()) .map(|s| s.to_string()), Err(_) => return Ok(None), // Remote doesn't exist }; @@ -594,7 +596,7 @@ pub fn get_worktrees(repo: &Repository) -> Result> { repo.worktrees()? .into_iter() .map(|name| { - let name = name.ok_or(WorktreeError::InvalidName)?; + let name = name?.ok_or(WorktreeError::InvalidName)?; WorktreeDescriptor::new(repo, name) }) .collect() @@ -858,6 +860,7 @@ pub fn set_upstream_tracking( let head = repo.head()?; let branch_name = head .shorthand() + .ok() .ok_or(WorktreeError::NoCurrentBranchTarget)?; // Set branch.*.remote diff --git a/git-workon-lib/tests/stack.rs b/git-workon-lib/tests/stack.rs index 8436eb1..859d415 100644 --- a/git-workon-lib/tests/stack.rs +++ b/git-workon-lib/tests/stack.rs @@ -7,12 +7,12 @@ use workon::{current_stack, StackModel}; /// Build a fixture with Graphite metadata for a linear chain: /// main → step-1 → step-2 → step-3 fn linear_chain() -> Result> { - Ok(FixtureBuilder::new() + FixtureBuilder::new() .graphite_config(&["main"]) .branch_metadata("step-1", "main") .branch_metadata("step-2", "step-1") .branch_metadata("step-3", "step-2") - .build()?) + .build() } // ── read_trunks (tested indirectly via current_stack) ──────────────────────── diff --git a/git-workon-lib/tests/worktree.rs b/git-workon-lib/tests/worktree.rs index d5387a3..f72adec 100644 --- a/git-workon-lib/tests/worktree.rs +++ b/git-workon-lib/tests/worktree.rs @@ -75,7 +75,7 @@ mod tests { // Verify HEAD points to the docs branch let head = orphan_repo.head()?; - assert_eq!(head.name(), Some("refs/heads/docs")); + assert_eq!(head.name(), Ok("refs/heads/docs")); assert!(head.is_branch(), "HEAD should be a branch"); // Verify the branch has exactly one commit (the initial empty commit) @@ -85,7 +85,7 @@ mod tests { 0, "Orphan branch should have no parent commits" ); - assert_eq!(head_commit.message(), Some("Initial commit")); + assert_eq!(head_commit.message(), Ok("Initial commit")); // Verify the commit tree is empty let tree = head_commit.tree()?; diff --git a/git-workon/src/cmd/new.rs b/git-workon/src/cmd/new.rs index e11609d..fbc5737 100644 --- a/git-workon/src/cmd/new.rs +++ b/git-workon/src/cmd/new.rs @@ -391,8 +391,8 @@ fn copy_untracked_files( } else { match repo.head() { Ok(head) => match head.shorthand() { - Some(s) => s.to_string(), - None => return Ok(()), // detached HEAD, skip + Ok(s) => s.to_string(), + Err(_) => return Ok(()), // detached HEAD, skip }, Err(_) => return Ok(()), // can't determine HEAD, skip } diff --git a/git-workon/tests/new.rs b/git-workon/tests/new.rs index 93c9ed0..8593229 100644 --- a/git-workon/tests/new.rs +++ b/git-workon/tests/new.rs @@ -105,7 +105,7 @@ fn new_orphan_worktree() -> Result<(), Box> { // Verify HEAD points to the docs branch let head = fixture.head()?; - assert_eq!(head.name(), Some("refs/heads/docs")); + assert_eq!(head.name(), Ok("refs/heads/docs")); // Verify the branch has exactly one commit (the initial empty commit) let head_commit = head.peel_to_commit()?;