From ca00cbaccc0fd5f6b07babce2af5507b18390c2a Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Sat, 24 Jun 2023 11:01:31 +1000 Subject: [PATCH] feat: Support install directly from git repo (#1162) Fixed #3 Signed-off-by: Jiahao XU --- Cargo.lock | 1204 ++++++++++++++++- crates/bin/Cargo.toml | 7 +- crates/bin/src/args.rs | 39 +- crates/bin/src/entry.rs | 17 +- crates/bin/src/lib.rs | 2 + crates/binstalk/Cargo.toml | 9 +- crates/binstalk/src/errors.rs | 22 + crates/binstalk/src/helpers.rs | 3 + .../src/helpers/cargo_toml_workspace.rs | 263 ++++ crates/binstalk/src/helpers/git.rs | 89 ++ .../src/helpers/git/progress_tracing.rs | 144 ++ crates/binstalk/src/lib.rs | 2 + crates/binstalk/src/ops.rs | 13 +- crates/binstalk/src/ops/resolve.rs | 26 +- crates/normalize-path/src/lib.rs | 26 + e2e-tests/git.sh | 61 + e2e-tests/manifests/workspace/Cargo.toml | 3 + .../manifests/workspace/b/c/d/e/f/Cargo.toml | 13 + .../a/b/c/d/e/cargo-binstall/Cargo.toml | 8 + .../crates/a/b/c/d/e/cargo-watch/Cargo.toml | 7 + .../crates/a/b/c/d/e/cargo-watch/src/main.rs | 0 justfile | 8 +- 22 files changed, 1874 insertions(+), 92 deletions(-) create mode 100644 crates/binstalk/src/helpers/cargo_toml_workspace.rs create mode 100644 crates/binstalk/src/helpers/git.rs create mode 100644 crates/binstalk/src/helpers/git/progress_tracing.rs create mode 100644 e2e-tests/git.sh create mode 100644 e2e-tests/manifests/workspace/Cargo.toml create mode 100644 e2e-tests/manifests/workspace/b/c/d/e/f/Cargo.toml create mode 100644 e2e-tests/manifests/workspace/crates/a/b/c/d/e/cargo-binstall/Cargo.toml create mode 100644 e2e-tests/manifests/workspace/crates/a/b/c/d/e/cargo-watch/Cargo.toml create mode 100644 e2e-tests/manifests/workspace/crates/a/b/c/d/e/cargo-watch/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 94e48135f..d9a561040 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,6 +28,18 @@ dependencies = [ "version_check", ] +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "1.0.2" @@ -101,6 +113,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "arc-swap" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + [[package]] name = "async-compression" version = "0.3.15" @@ -226,6 +250,8 @@ dependencies = [ "compact_str", "detect-targets", "either", + "gix", + "glob", "home", "itertools", "jobslot", @@ -336,6 +362,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbe3c979c178231552ecba20214a8272df4e09f232a87aef4320cf06539aded" + [[package]] name = "block-buffer" version = "0.10.4" @@ -366,6 +398,27 @@ dependencies = [ "alloc-stdlib", ] +[[package]] +name = "bstr" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a246e68bb43f6cd9db24bea052a53e40405417c5fb372e3d1a8a7f770a564ef5" +dependencies = [ + "memchr", + "once_cell", + "regex-automata", + "serde", +] + +[[package]] +name = "btoi" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd6407f73a9b8b6162d8a2ef999fe6afd7cc15902ebf42c5cd296addf17e0ad" +dependencies = [ + "num-traits", +] + [[package]] name = "bumpalo" version = "3.13.0" @@ -384,6 +437,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +[[package]] +name = "bytesize" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38fcc2979eff34a4b84e1cf9a1e3da42a7d44b3b690a40cdcb23e3d556cfb2e5" + [[package]] name = "bzip2" version = "0.4.4" @@ -487,7 +546,7 @@ checksum = "2e53afce1efce6ed1f633cf0e57612fe51db54a1ee4fd8f8503d078fe02d69ae" dependencies = [ "anstream", "anstyle", - "bitflags", + "bitflags 1.3.2", "clap_lex", "strsim", ] @@ -510,6 +569,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +[[package]] +name = "clru" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8191fa7302e03607ff0e237d4246cc043ff5b3cb9409d995172ba3bea16b807" + [[package]] name = "cmake" version = "0.1.50" @@ -576,6 +641,73 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c" +dependencies = [ + "cfg-if", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -641,6 +773,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "dunce" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" + [[package]] name = "either" version = "1.8.1" @@ -799,123 +937,795 @@ dependencies = [ ] [[package]] -name = "futures-channel" -version = "0.3.28" +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gh-token" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1ff8db6b58b68c39ec14a0922cad141fee0e350324eb01ee45e3898f780d46" +dependencies = [ + "home", + "serde", + "serde_derive", + "serde_yaml", +] + +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" + +[[package]] +name = "gix" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f5281c55e0a7415877d91a15fae4a10ec7444615d64d78e48c07f20bcfcd9b" +dependencies = [ + "gix-actor", + "gix-attributes", + "gix-commitgraph", + "gix-config", + "gix-credentials", + "gix-date", + "gix-diff", + "gix-discover", + "gix-features", + "gix-fs", + "gix-glob", + "gix-hash", + "gix-hashtable", + "gix-ignore", + "gix-index", + "gix-lock", + "gix-mailmap", + "gix-negotiate", + "gix-object", + "gix-odb", + "gix-pack", + "gix-path", + "gix-prompt", + "gix-protocol", + "gix-ref", + "gix-refspec", + "gix-revision", + "gix-sec", + "gix-tempfile", + "gix-trace", + "gix-transport", + "gix-traverse", + "gix-url", + "gix-utils", + "gix-validate", + "gix-worktree", + "log", + "once_cell", + "reqwest", + "signal-hook", + "smallvec", + "thiserror", + "unicode-normalization", +] + +[[package]] +name = "gix-actor" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b70d0d809ee387113df810ab4ebe585a076e35ae6ed59b5b280072146955a3ff" +dependencies = [ + "bstr", + "btoi", + "gix-date", + "itoa", + "nom", + "thiserror", +] + +[[package]] +name = "gix-attributes" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d7006cc5a508514207154046e18c3c39d98ba98f865ada83b6f3f3886543bb" +dependencies = [ + "bstr", + "gix-glob", + "gix-path", + "gix-quote", + "kstring", + "log", + "smallvec", + "thiserror", + "unicode-bom", +] + +[[package]] +name = "gix-bitmap" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "311e2fa997be6560c564b070c5da2d56d038b645a94e1e5796d5d85a350da33c" +dependencies = [ + "thiserror", +] + +[[package]] +name = "gix-chunk" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39db5ed0fc0a2e9b1b8265993f7efdbc30379dec268f3b91b7af0c2de4672fdd" +dependencies = [ + "thiserror", +] + +[[package]] +name = "gix-command" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb49ab557a37b0abb2415bca2b10e541277dff0565deb5bd5e99fd95f93f51eb" +dependencies = [ + "bstr", +] + +[[package]] +name = "gix-commitgraph" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e498e98d0b477d6a1c1608bee39db201e7a38873460a130a97ce88b4d95b6e1" +dependencies = [ + "bstr", + "gix-chunk", + "gix-features", + "gix-hash", + "memmap2", + "thiserror", +] + +[[package]] +name = "gix-config" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b32541232a2c626849df7843e05b50cb43ac38a4f675abbe2f661874fc1e9d" +dependencies = [ + "bstr", + "gix-config-value", + "gix-features", + "gix-glob", + "gix-path", + "gix-ref", + "gix-sec", + "log", + "memchr", + "nom", + "once_cell", + "smallvec", + "thiserror", + "unicode-bom", +] + +[[package]] +name = "gix-config-value" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4783caa23062f86acfd1bc9e72c62250923d1673171ce1a524d9486f8a4556a8" +dependencies = [ + "bitflags 2.3.2", + "bstr", + "gix-path", + "libc", + "thiserror", +] + +[[package]] +name = "gix-credentials" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcec518a8db5b2e342ea7a2e785f46fd176b1b689ddd3f43052701bf3fa8ee3" +dependencies = [ + "bstr", + "gix-command", + "gix-config-value", + "gix-path", + "gix-prompt", + "gix-sec", + "gix-url", + "thiserror", +] + +[[package]] +name = "gix-date" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0213f923d63c2c7d10799c1977f42df38ec586ebbf1d14fd00dfa363ac994c2b" +dependencies = [ + "bstr", + "itoa", + "thiserror", + "time", +] + +[[package]] +name = "gix-diff" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5049dd5a60d5608912da0ab184f35064901f192f4adf737716789715faffa080" +dependencies = [ + "gix-hash", + "gix-object", + "imara-diff", + "thiserror", +] + +[[package]] +name = "gix-discover" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c14865cb9c6eb817d6a8d53595f1051239d2d31feae7a5e5b2f00910c94a8eb4" +dependencies = [ + "bstr", + "dunce", + "gix-hash", + "gix-path", + "gix-ref", + "gix-sec", + "thiserror", +] + +[[package]] +name = "gix-features" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae82dfceec06c034728c530399ee449f97b1e542e191247c52c169ca6af1fd89" +dependencies = [ + "bytes", + "bytesize", + "crc32fast", + "crossbeam-channel", + "flate2", + "gix-hash", + "gix-trace", + "jwalk", + "libc", + "once_cell", + "parking_lot", + "prodash", + "sha1_smol", + "thiserror", + "walkdir", +] + +[[package]] +name = "gix-fs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb15956bc0256594c62a2399fcf6958a02a11724217eddfdc2b49b21b6292496" +dependencies = [ + "gix-features", +] + +[[package]] +name = "gix-glob" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f45cd7ab22faf154db0a9f5a8011ba9cda8b298b61b7299f43a21bbaf0b3f208" +dependencies = [ + "bitflags 2.3.2", + "bstr", + "gix-features", + "gix-path", +] + +[[package]] +name = "gix-hash" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0dd58cdbe7ffa4032fc111864c80d5f8cecd9a2c9736c97ae7e5be834188272" +dependencies = [ + "hex", + "thiserror", +] + +[[package]] +name = "gix-hashtable" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cfd7f4ea905c13579565e3c264ca2c4103d192bd5fce2300c5a884cf1977d61" +dependencies = [ + "gix-hash", + "hashbrown 0.13.2", + "parking_lot", +] + +[[package]] +name = "gix-ignore" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27e82dec6975012b710837c6cd56353c3111d2308e016118bfc59275fcc8b5d0" +dependencies = [ + "bstr", + "gix-glob", + "gix-path", + "unicode-bom", +] + +[[package]] +name = "gix-index" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ef2fa392d351e62ac3a6309146f61880abfbe0c07474e075d3b2ac78a6834a5" +dependencies = [ + "bitflags 2.3.2", + "bstr", + "btoi", + "filetime", + "gix-bitmap", + "gix-features", + "gix-hash", + "gix-lock", + "gix-object", + "gix-traverse", + "itoa", + "memmap2", + "smallvec", + "thiserror", +] + +[[package]] +name = "gix-lock" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "328f50aad713ab606caeaf834459ef915ccdfbb9133ac6cd54616d601aa9249f" +dependencies = [ + "gix-tempfile", + "gix-utils", + "thiserror", +] + +[[package]] +name = "gix-mailmap" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0bef8d360a6a9fc5a6d872471588d8ca7db77b940e48ff20c3b4706ad5f481d" +dependencies = [ + "bstr", + "gix-actor", + "gix-date", + "thiserror", +] + +[[package]] +name = "gix-negotiate" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b626aafb9f4088058f1baa5d2029b2191820c84f6c81e43535ba70bfdc7b7d56" +dependencies = [ + "bitflags 2.3.2", + "gix-commitgraph", + "gix-date", + "gix-hash", + "gix-object", + "gix-revwalk", + "smallvec", + "thiserror", +] + +[[package]] +name = "gix-object" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "255e477ae4cc8d10778238f011e6125b01cc0e7067dc8df87acd67a428a81f20" +dependencies = [ + "bstr", + "btoi", + "gix-actor", + "gix-date", + "gix-features", + "gix-hash", + "gix-validate", + "hex", + "itoa", + "nom", + "smallvec", + "thiserror", +] + +[[package]] +name = "gix-odb" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b73469f145d1e6afbcfd0ab6499a366fbbcb958c2999d41d283d6c7b94024b9" +dependencies = [ + "arc-swap", + "gix-date", + "gix-features", + "gix-hash", + "gix-object", + "gix-pack", + "gix-path", + "gix-quote", + "parking_lot", + "tempfile", + "thiserror", +] + +[[package]] +name = "gix-pack" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f3bcd1aaa72aea7163b147d2bde2480a01eadefc774a479d38f29920f7f1c8" +dependencies = [ + "clru", + "gix-chunk", + "gix-diff", + "gix-features", + "gix-hash", + "gix-hashtable", + "gix-object", + "gix-path", + "gix-tempfile", + "gix-traverse", + "memmap2", + "parking_lot", + "smallvec", + "thiserror", + "uluru", +] + +[[package]] +name = "gix-packetline" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0158e98f4afb8f2da69a325c3e8b6674093a0eab2c91cc59f1522a3bc062a012" +dependencies = [ + "bstr", + "hex", + "thiserror", +] + +[[package]] +name = "gix-path" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea2a19d82dd55e5fad1d606b8a1ad2f7a804e10caa2efbb169cd37e0a07ede0" +dependencies = [ + "bstr", + "gix-trace", + "home", + "once_cell", + "thiserror", +] + +[[package]] +name = "gix-prompt" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dfd363fd89a40c1e7bff9c9c1b136cd2002480f724b0c627c1bc771cd5480ec" +dependencies = [ + "gix-command", + "gix-config-value", + "parking_lot", + "rustix", + "thiserror", +] + +[[package]] +name = "gix-protocol" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27e93c9343860c45c025e09bc26772d15cec690250d04b36822bd528dd3c44f8" +dependencies = [ + "bstr", + "btoi", + "gix-credentials", + "gix-date", + "gix-features", + "gix-hash", + "gix-transport", + "maybe-async", + "nom", + "thiserror", +] + +[[package]] +name = "gix-quote" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3874de636c2526de26a3405b8024b23ef1a327bebf4845d770d00d48700b6a40" +dependencies = [ + "bstr", + "btoi", + "thiserror", +] + +[[package]] +name = "gix-ref" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6c74873a9d8ff5d1310f2325f09164c15a91402ab5cde4d479ae12ff55ed69" +dependencies = [ + "gix-actor", + "gix-date", + "gix-features", + "gix-fs", + "gix-hash", + "gix-lock", + "gix-object", + "gix-path", + "gix-tempfile", + "gix-validate", + "memmap2", + "nom", + "thiserror", +] + +[[package]] +name = "gix-refspec" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "ca1bc6c40bad62570683d642fcb04e977433ac8f76b674860ef7b1483c1f8990" dependencies = [ - "futures-core", + "bstr", + "gix-hash", + "gix-revision", + "gix-validate", + "smallvec", + "thiserror", ] [[package]] -name = "futures-core" -version = "0.3.28" +name = "gix-revision" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "f3751d6643d731fc5829d2f43ca049f4333c968f30908220ba0783c9dfe5010c" +dependencies = [ + "bstr", + "gix-date", + "gix-hash", + "gix-hashtable", + "gix-object", + "gix-revwalk", + "thiserror", +] [[package]] -name = "futures-io" -version = "0.3.28" +name = "gix-revwalk" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "144995229c6e5788b1c7386f8a3f7146ace3745c9a6b56cef9123a7d83b110c5" +dependencies = [ + "gix-commitgraph", + "gix-date", + "gix-hash", + "gix-hashtable", + "gix-object", + "smallvec", + "thiserror", +] [[package]] -name = "futures-lite" -version = "1.13.0" +name = "gix-sec" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +checksum = "47f09860e2ddc7b13119e410c46d8e9f870acc7933fb53ae65817af83a8c9f80" dependencies = [ - "futures-core", - "pin-project-lite", + "bitflags 2.3.2", + "gix-path", + "libc", + "windows 0.48.0", ] [[package]] -name = "futures-macro" -version = "0.3.28" +name = "gix-tempfile" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "4fac8310c17406ea619af72f42ee46dac795110f68f41b4f4fa231b69889c6a2" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.18", + "gix-fs", + "libc", + "once_cell", + "parking_lot", + "signal-hook", + "signal-hook-registry", + "tempfile", ] [[package]] -name = "futures-sink" -version = "0.3.28" +name = "gix-trace" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "6ff8a60073500f4d6edd181432ee11394d843db7dcf05756aa137a1233b1cbf6" [[package]] -name = "futures-task" -version = "0.3.28" +name = "gix-transport" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "435013c7ce6983fd2cfa9a740873c31c048c042e47d92714e43d75d861f0eedf" +dependencies = [ + "base64 0.21.2", + "bstr", + "gix-command", + "gix-credentials", + "gix-features", + "gix-packetline", + "gix-quote", + "gix-sec", + "gix-url", + "reqwest", + "thiserror", +] [[package]] -name = "futures-util" -version = "0.3.28" +name = "gix-traverse" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "c3f6bba1686bfbc7e0e93d4932bc6e14d479c9c9524f7c8d65b25d2a9446a99e" dependencies = [ - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", + "gix-commitgraph", + "gix-date", + "gix-hash", + "gix-hashtable", + "gix-object", + "gix-revwalk", + "smallvec", + "thiserror", ] [[package]] -name = "fxhash" -version = "0.2.1" +name = "gix-url" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +checksum = "ff1f984816338039b151a9f5dae6100e1e51e438cf61242ea8136fedc574d825" dependencies = [ - "byteorder", + "bstr", + "gix-features", + "gix-path", + "home", + "thiserror", + "url", ] [[package]] -name = "generic-array" -version = "0.14.7" +name = "gix-utils" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "1ca284c260845bc0724050aec59c7a596407678342614cdf5a1d69e044f29a36" dependencies = [ - "typenum", - "version_check", + "fastrand", ] [[package]] -name = "getrandom" -version = "0.2.10" +name = "gix-validate" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "8d092b594c8af00a3a31fe526d363ee8a51a6f29d8496cdb991ed2f01ec0ec13" dependencies = [ - "cfg-if", - "libc", - "wasi", + "bstr", + "thiserror", ] [[package]] -name = "gh-token" -version = "0.1.2" +name = "gix-worktree" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1ff8db6b58b68c39ec14a0922cad141fee0e350324eb01ee45e3898f780d46" +checksum = "4ee22549d6723189366235e1c6959ccdac73b58197cdbb437684eaa2169edcb9" dependencies = [ - "home", - "serde", - "serde_derive", - "serde_yaml", + "bstr", + "filetime", + "gix-attributes", + "gix-features", + "gix-fs", + "gix-glob", + "gix-hash", + "gix-ignore", + "gix-index", + "gix-object", + "gix-path", + "io-close", + "thiserror", ] [[package]] -name = "gimli" -version = "0.27.3" +name = "glob" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "guess_host_triple" @@ -954,9 +1764,15 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash", + "ahash 0.7.6", ] +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" + [[package]] name = "heck" version = "0.4.1" @@ -978,6 +1794,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "home" version = "0.5.5" @@ -1032,6 +1854,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +[[package]] +name = "human_format" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86cce260d758a9aa3d7c4b99d55c815a540f8a37514ba6046ab6be402a157cb0" + [[package]] name = "hyper" version = "0.14.26" @@ -1103,6 +1931,16 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "imara-diff" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e98c1d0ad70fc91b8b9654b1f33db55e59579d3b3de2bffdced0fdb810570cb8" +dependencies = [ + "ahash 0.8.3", + "hashbrown 0.12.3", +] + [[package]] name = "indexmap" version = "1.9.3" @@ -1110,7 +1948,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", ] [[package]] @@ -1122,6 +1960,16 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "io-close" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cadcf447f06744f8ce713d2d6239bb5bde2c357a452397a9ed90c625da390bc" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "io-lifetimes" version = "1.0.11" @@ -1216,6 +2064,25 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jwalk" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2735847566356cd2179a2a38264839308f7079fa96e6bd5a42d740460e003c56" +dependencies = [ + "crossbeam", + "rayon", +] + +[[package]] +name = "kstring" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3066350882a1cd6d950d055997f379ac37fd39f81cd4d8ed186032eb3c5747" +dependencies = [ + "static_assertions", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1327,6 +2194,17 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" +[[package]] +name = "maybe-async" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f1b8c13cb1f814b634a96b2c725449fe7ed464a7b8781de8688be5ffbd3f305" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "maybe-owned" version = "0.3.4" @@ -1342,6 +2220,24 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + [[package]] name = "miette" version = "5.9.0" @@ -1389,6 +2285,12 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.6.2" @@ -1442,12 +2344,22 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "libc", "static_assertions", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "normalize-path" version = "0.2.0" @@ -1462,6 +2374,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + [[package]] name = "num_cpus" version = "1.15.0" @@ -1472,6 +2393,15 @@ dependencies = [ "libc", ] +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + [[package]] name = "object" version = "0.30.4" @@ -1493,7 +2423,7 @@ version = "0.10.55" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "foreign-types", "libc", @@ -1641,6 +2571,16 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prodash" +version = "25.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3236ce1618b6da4c7b618e0143c4d5b5dc190f75f81c49f248221382f7e9e9ae" +dependencies = [ + "bytesize", + "human_format", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -1739,13 +2679,35 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rayon" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + [[package]] name = "redox_syscall" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1754,7 +2716,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1779,6 +2741,12 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" + [[package]] name = "regex-syntax" version = "0.7.2" @@ -1877,7 +2845,7 @@ version = "0.37.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno 0.3.1", "io-lifetimes", "libc", @@ -1961,6 +2929,15 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.21" @@ -1992,7 +2969,7 @@ version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -2092,6 +3069,12 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + [[package]] name = "sharded-slab" version = "0.1.4" @@ -2101,6 +3084,16 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "signal-hook" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" +dependencies = [ + "libc", + "signal-hook-registry", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -2309,6 +3302,35 @@ dependencies = [ "once_cell", ] +[[package]] +name = "time" +version = "0.3.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" +dependencies = [ + "itoa", + "libc", + "num_threads", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" + +[[package]] +name = "time-macros" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +dependencies = [ + "time-core", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -2632,12 +3654,27 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +[[package]] +name = "uluru" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "794a32261a1f5eb6a4462c81b59cec87b5c27d5deea7dd1ac8fc781c41d226db" +dependencies = [ + "arrayvec", +] + [[package]] name = "unicode-bidi" version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +[[package]] +name = "unicode-bom" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98e90c70c9f0d4d1ee6d0a7d04aa06cb9bbd53d8cfbdd62a0269a7c2eb640552" + [[package]] name = "unicode-ident" version = "1.0.9" @@ -2650,7 +3687,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5faade31a542b8b35855fff6e8def199853b2da8da256da52f52f1316ee3137" dependencies = [ - "hashbrown", + "hashbrown 0.12.3", "regex", ] @@ -2737,6 +3774,16 @@ dependencies = [ "libc", ] +[[package]] +name = "walkdir" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -2882,6 +3929,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/crates/bin/Cargo.toml b/crates/bin/Cargo.toml index b4bf65315..aae1f939c 100644 --- a/crates/bin/Cargo.toml +++ b/crates/bin/Cargo.toml @@ -49,7 +49,9 @@ tracing-subscriber = { version = "0.3.17", features = ["fmt", "json", "ansi"], d embed-resource = "2.1.1" [features] -default = ["static", "rustls", "trust-dns", "fancy-no-backtrace", "zstd-thin"] +default = ["static", "rustls", "trust-dns", "fancy-no-backtrace", "zstd-thin", "git"] + +git = ["binstalk/git"] mimalloc = ["dep:mimalloc"] @@ -74,3 +76,6 @@ log_max_level_debug = ["log/max_level_debug", "tracing/max_level_debug", "log_re log_release_max_level_info = ["log/release_max_level_info", "tracing/release_max_level_info"] log_release_max_level_debug = ["log/release_max_level_debug", "tracing/release_max_level_debug"] + +[package.metadata.docs.rs] +rustdoc-args = ["--cfg", "docsrs"] diff --git a/crates/bin/src/args.rs b/crates/bin/src/args.rs index 814d2705e..fa3a19588 100644 --- a/crates/bin/src/args.rs +++ b/crates/bin/src/args.rs @@ -38,7 +38,7 @@ pub struct Args { /// install. The version syntax is as with the --version option. /// /// When multiple names are provided, the --version option and override option - /// `manifest_path` is unavailable due to ambiguity. + /// `--manifest-path` and `--git` are unavailable due to ambiguity. /// /// If duplicate names are provided, the last one (and their version requirement) /// is kept. @@ -88,9 +88,21 @@ pub struct Args { /// This skips searching crates.io for a manifest and uses the specified path directly, useful /// for debugging and when adding Binstall support. This may be either the path to the folder /// containing a Cargo.toml file, or the Cargo.toml file itself. + /// + /// This option cannot be used with `--git`. #[clap(help_heading = "Overrides", long)] pub manifest_path: Option, + #[cfg(feature = "git")] + /// Override how to fetch Cargo.toml package manifest. + /// + /// This skip searching crates.io and instead clone the repository specified and + /// runs as if `--manifest-path $cloned_repo` is passed to binstall. + /// + /// This option cannot be used with `--manifest-path`. + #[clap(help_heading = "Overrides", long)] + pub git: Option, + /// Override Cargo.toml package manifest bin-dir. #[clap(help_heading = "Overrides", long)] pub bin_dir: Option, @@ -391,13 +403,36 @@ pub fn parse() -> Args { // Ensure no conflict let mut command = Args::command(); + #[cfg(feature = "git")] + if opts.manifest_path.is_some() && opts.git.is_some() { + command + .error( + ErrorKind::ArgumentConflict, + format_args!( + r#"Multiple override options for Cargo.toml fetching. +You cannot use --manifest-path and --git. Do one or the other."# + ), + ) + .exit(); + } + if opts.crate_names.len() > 1 { let option = if opts.version_req.is_some() { "version" } else if opts.manifest_path.is_some() { "manifest-path" } else { - "" + #[cfg(not(feature = "git"))] + { + "" + } + + #[cfg(feature = "git")] + if opts.git.is_some() { + "git" + } else { + "" + } }; if !option.is_empty() { diff --git a/crates/bin/src/entry.rs b/crates/bin/src/entry.rs index 5818ae3cb..3b7b27369 100644 --- a/crates/bin/src/entry.rs +++ b/crates/bin/src/entry.rs @@ -19,7 +19,7 @@ use binstalk::{ ops::{ self, resolve::{CrateName, Resolution, ResolutionFetch, VersionReqExt}, - Resolver, + CargoTomlFetchOverride, Options, Resolver, }, }; use binstalk_manifests::cargo_toml_binstall::PkgOverride; @@ -95,7 +95,7 @@ pub fn install_crates( let gh_api_client = GhApiClient::new(client.clone(), args.github_token); // Create binstall_opts - let binstall_opts = Arc::new(ops::Options { + let binstall_opts = Arc::new(Options { no_symlinks: args.no_symlinks, dry_run: args.dry_run, force: args.force, @@ -104,7 +104,16 @@ pub fn install_crates( no_track: args.no_track, version_req: args.version_req, - manifest_path: args.manifest_path, + #[cfg(feature = "git")] + cargo_toml_fetch_override: match (args.manifest_path, args.git) { + (Some(manifest_path), None) => Some(CargoTomlFetchOverride::Path(manifest_path)), + (None, Some(git_url)) => Some(CargoTomlFetchOverride::Git(git_url)), + (None, None) => None, + _ => unreachable!("manifest_path and git cannot be specified at the same time"), + }, + + #[cfg(not(feature = "git"))] + cargo_toml_fetch_override: args.manifest_path.map(CargoTomlFetchOverride::Path), cli_overrides, desired_targets, @@ -326,7 +335,7 @@ fn do_install_fetches( resolution_fetchs: Vec>, // Take manifests by value to drop the `FileLock`. manifests: Option, - binstall_opts: &ops::Options, + binstall_opts: &Options, dry_run: bool, temp_dir: tempfile::TempDir, no_cleanup: bool, diff --git a/crates/bin/src/lib.rs b/crates/bin/src/lib.rs index 57299fe95..5e19e4d67 100644 --- a/crates/bin/src/lib.rs +++ b/crates/bin/src/lib.rs @@ -1,3 +1,5 @@ +#![cfg_attr(docsrs, feature(doc_auto_cfg))] + pub mod args; pub mod bin_util; pub mod entry; diff --git a/crates/binstalk/Cargo.toml b/crates/binstalk/Cargo.toml index 0750456ec..494a65981 100644 --- a/crates/binstalk/Cargo.toml +++ b/crates/binstalk/Cargo.toml @@ -18,6 +18,8 @@ command-group = { version = "2.1.0", features = ["with-tokio"] } compact_str = { version = "0.7.0", features = ["serde"] } detect-targets = { version = "0.1.7", path = "../detect-targets" } either = "1.8.1" +gix = { version = "0.47.0", features = ["blocking-http-transport-reqwest-rust-tls"], optional = true } +glob = "0.3.1" home = "0.5.5" itertools = "0.11.0" jobslot = { version = "0.2.11", features = ["tokio"] } @@ -43,7 +45,9 @@ xz2 = "0.1.7" windows = { version = "0.48.0", features = ["Win32_Storage_FileSystem", "Win32_Foundation"] } [features] -default = ["static", "rustls"] +default = ["static", "rustls", "git"] + +git = ["dep:gix"] static = ["binstalk-downloader/static"] pkg-config = ["binstalk-downloader/pkg-config"] @@ -57,3 +61,6 @@ trust-dns = ["binstalk-downloader/trust-dns"] zstd-thin = ["binstalk-downloader/zstd-thin"] cross-lang-fat-lto = ["binstalk-downloader/cross-lang-fat-lto"] + +[package.metadata.docs.rs] +rustdoc-args = ["--cfg", "docsrs"] diff --git a/crates/binstalk/src/errors.rs b/crates/binstalk/src/errors.rs index bc637947b..aa14d953c 100644 --- a/crates/binstalk/src/errors.rs +++ b/crates/binstalk/src/errors.rs @@ -15,6 +15,8 @@ use thiserror::Error; use tokio::task; use tracing::{error, warn}; +use crate::helpers::cargo_toml_workspace::LoadManifestFromWSError; + #[derive(Debug, Error)] #[error("crates.io API error for {crate_name}: {err}")] pub struct CratesIoApiError { @@ -323,6 +325,23 @@ pub enum BinstallError { #[diagnostic(severity(error), code(binstall::target_triple_parse_error))] TargetTripleParseError(#[source] Box), + /// Failed to shallow clone git repository + /// + /// - Code: `binstall::git` + /// - Exit: 98 + #[cfg(feature = "git")] + #[error("Failed to shallow clone git repository: {0}")] + #[diagnostic(severity(error), code(binstall::git))] + GitError(#[from] crate::helpers::git::GitError), + + /// Failed to load manifest from workspace + /// + /// - Code: `binstall::load_manifest_from_workspace` + /// - Exit: 99 + #[error(transparent)] + #[diagnostic(severity(error), code(binstall::load_manifest_from_workspace))] + LoadManifestFromWSError(#[from] Box), + /// A wrapped error providing the context of which crate the error is about. #[error(transparent)] #[diagnostic(transparent)] @@ -358,6 +377,9 @@ impl BinstallError { InvalidPkgFmt(..) => 95, GhApiErr(..) => 96, TargetTripleParseError(..) => 97, + #[cfg(feature = "git")] + GitError(_) => 98, + LoadManifestFromWSError(_) => 99, CrateContext(context) => context.err.exit_number(), }; diff --git a/crates/binstalk/src/helpers.rs b/crates/binstalk/src/helpers.rs index 23ed00ef2..34da60e0d 100644 --- a/crates/binstalk/src/helpers.rs +++ b/crates/binstalk/src/helpers.rs @@ -1,4 +1,7 @@ +pub mod cargo_toml_workspace; pub mod futures_resolver; +#[cfg(feature = "git")] +pub mod git; pub mod jobserver_client; pub mod remote; pub mod signal; diff --git a/crates/binstalk/src/helpers/cargo_toml_workspace.rs b/crates/binstalk/src/helpers/cargo_toml_workspace.rs new file mode 100644 index 000000000..3360e55e9 --- /dev/null +++ b/crates/binstalk/src/helpers/cargo_toml_workspace.rs @@ -0,0 +1,263 @@ +use std::{ + io, mem, + path::{Path, PathBuf}, +}; + +use cargo_toml::{Error as CargoTomlError, Manifest}; +use compact_str::CompactString; +use glob::PatternError; +use normalize_path::NormalizePath; +use thiserror::Error as ThisError; +use tracing::{debug, instrument, warn}; + +use crate::{errors::BinstallError, manifests::cargo_toml_binstall::Meta}; + +/// Load binstall metadata `Cargo.toml` from workspace at the provided path +/// +/// WARNING: This is a blocking operation. +/// +/// * `workspace_path` - should be a directory +pub fn load_manifest_from_workspace( + workspace_path: impl AsRef, + crate_name: impl AsRef, +) -> Result, BinstallError> { + fn inner(workspace_path: &Path, crate_name: &str) -> Result, BinstallError> { + load_manifest_from_workspace_inner(workspace_path, crate_name).map_err(|inner| { + Box::new(LoadManifestFromWSError { + workspace_path: workspace_path.into(), + crate_name: crate_name.into(), + inner, + }) + .into() + }) + } + + inner(workspace_path.as_ref(), crate_name.as_ref()) +} + +#[derive(Debug, ThisError)] +#[error("Failed to load {crate_name} from {}: {inner}", workspace_path.display())] +pub struct LoadManifestFromWSError { + workspace_path: Box, + crate_name: CompactString, + #[source] + inner: LoadManifestFromWSErrorInner, +} + +#[derive(Debug, ThisError)] +enum LoadManifestFromWSErrorInner { + #[error("Invalid pattern in workspace.members or workspace.exclude: {0}")] + PatternError(#[from] PatternError), + + #[error("Invalid pattern `{0}`: It must be relative and point within current dir")] + InvalidPatternError(CompactString), + + #[error("Failed to parse cargo manifest: {0}")] + CargoManifest(#[from] CargoTomlError), + + #[error("I/O error: {0}")] + Io(#[from] io::Error), + + #[error("Not found")] + NotFound, +} + +#[instrument] +fn load_manifest_from_workspace_inner( + workspace_path: &Path, + crate_name: &str, +) -> Result, LoadManifestFromWSErrorInner> { + debug!( + "Loading manifest of crate {crate_name} from workspace: {}", + workspace_path.display() + ); + + let mut workspace_paths = vec![workspace_path.to_owned()]; + + while let Some(workspace_path) = workspace_paths.pop() { + let p = workspace_path.join("Cargo.toml"); + let manifest = Manifest::::from_path_with_metadata(&p)?; + + let name = manifest.package.as_ref().map(|p| &*p.name); + debug!( + "Loading from {}, manifest.package.name = {:#?}", + p.display(), + name + ); + + if name == Some(crate_name) { + return Ok(manifest); + } + + if let Some(ws) = manifest.workspace { + let excludes = ws.exclude; + let members = ws.members; + + if members.is_empty() { + continue; + } + + let exclude_patterns = excludes + .into_iter() + .map(|pat| Pattern::new(&pat)) + .collect::, _>>()?; + + for member in members { + for path in Pattern::new(&member)?.glob_dirs(&workspace_path)? { + if !exclude_patterns + .iter() + .any(|exclude| exclude.matches_with_trailing(&path)) + { + workspace_paths.push(workspace_path.join(path)); + } + } + } + } + } + + Err(LoadManifestFromWSErrorInner::NotFound) +} + +struct Pattern(Vec); + +impl Pattern { + fn new(pat: &str) -> Result { + Path::new(pat) + .try_normalize() + .ok_or_else(|| LoadManifestFromWSErrorInner::InvalidPatternError(pat.into()))? + .iter() + .map(|c| glob::Pattern::new(c.to_str().unwrap())) + .collect::, _>>() + .map_err(Into::into) + .map(Self) + } + + /// * `glob_path` - path to dir to glob for + /// return paths relative to `glob_path`. + fn glob_dirs(&self, glob_path: &Path) -> Result, LoadManifestFromWSErrorInner> { + let mut paths = vec![PathBuf::new()]; + + for pattern in &self.0 { + if paths.is_empty() { + break; + } + + for path in mem::take(&mut paths) { + let p = glob_path.join(&path); + let res = p.read_dir(); + if res.is_err() && !p.is_dir() { + continue; + } + drop(p); + + for res in res? { + let entry = res?; + + let is_dir = entry + .file_type() + .map(|file_type| file_type.is_dir() || file_type.is_symlink()) + .unwrap_or(false); + if !is_dir { + continue; + } + + let filename = entry.file_name(); + if filename != "." // Ignore current dir + && filename != ".." // Ignore parent dir + && pattern.matches(&filename.to_string_lossy()) + { + paths.push(path.join(filename)); + } + } + } + } + + Ok(paths) + } + + /// Return `true` if `path` matches the pattern. + /// It will still return `true` even if there are some trailing components. + fn matches_with_trailing(&self, path: &Path) -> bool { + let mut iter = path.iter().map(|os_str| os_str.to_string_lossy()); + for pattern in &self.0 { + match iter.next() { + Some(s) if pattern.matches(&s) => (), + _ => return false, + } + } + true + } +} + +#[cfg(test)] +mod test { + use std::fs::create_dir_all as mkdir; + + use tempfile::TempDir; + + use super::*; + + #[test] + fn test_glob_dirs() { + let pattern = Pattern::new("*/*/q/*").unwrap(); + let tempdir = TempDir::new().unwrap(); + + mkdir(tempdir.as_ref().join("a/b/c/efe")).unwrap(); + mkdir(tempdir.as_ref().join("a/b/q/ww")).unwrap(); + mkdir(tempdir.as_ref().join("d/233/q/d")).unwrap(); + + let mut paths = pattern.glob_dirs(tempdir.as_ref()).unwrap(); + paths.sort_unstable(); + assert_eq!( + paths, + vec![PathBuf::from("a/b/q/ww"), PathBuf::from("d/233/q/d")] + ); + } + + #[test] + fn test_matches_with_trailing() { + let pattern = Pattern::new("*/*/q/*").unwrap(); + + assert!(pattern.matches_with_trailing(Path::new("a/b/q/d/"))); + assert!(pattern.matches_with_trailing(Path::new("a/b/q/d"))); + assert!(pattern.matches_with_trailing(Path::new("a/b/q/d/234"))); + assert!(pattern.matches_with_trailing(Path::new("a/234/q/d/234"))); + + assert!(!pattern.matches_with_trailing(Path::new(""))); + assert!(!pattern.matches_with_trailing(Path::new("a/"))); + assert!(!pattern.matches_with_trailing(Path::new("a/234"))); + assert!(!pattern.matches_with_trailing(Path::new("a/234/q"))); + } + + #[test] + fn test_load() { + let p = Path::new(env!("CARGO_MANIFEST_DIR")) + .parent() + .unwrap() + .parent() + .unwrap() + .join("e2e-tests/manifests/workspace"); + + let manifest = load_manifest_from_workspace(&p, "cargo-binstall").unwrap(); + let package = manifest.package.unwrap(); + assert_eq!(package.name, "cargo-binstall"); + assert_eq!(package.version.as_ref().unwrap(), "0.12.0"); + assert_eq!(manifest.bin.len(), 1); + assert_eq!(manifest.bin[0].name.as_deref().unwrap(), "cargo-binstall"); + assert_eq!(manifest.bin[0].path.as_deref().unwrap(), "src/main.rs"); + + let err = load_manifest_from_workspace_inner(&p, "cargo-binstall2").unwrap_err(); + assert!( + matches!(err, LoadManifestFromWSErrorInner::NotFound), + "{:#?}", + err + ); + + let manifest = load_manifest_from_workspace(&p, "cargo-watch").unwrap(); + let package = manifest.package.unwrap(); + assert_eq!(package.name, "cargo-watch"); + assert_eq!(package.version.as_ref().unwrap(), "8.4.0"); + assert_eq!(manifest.bin.len(), 1); + assert_eq!(manifest.bin[0].name.as_deref().unwrap(), "cargo-watch"); + } +} diff --git a/crates/binstalk/src/helpers/git.rs b/crates/binstalk/src/helpers/git.rs new file mode 100644 index 000000000..1509182fc --- /dev/null +++ b/crates/binstalk/src/helpers/git.rs @@ -0,0 +1,89 @@ +use std::{num::NonZeroU32, path::Path, str::FromStr, sync::atomic::AtomicBool}; + +use compact_str::CompactString; +use gix::{clone, create, open, remote, Url}; +use thiserror::Error as ThisError; +use tracing::debug; + +mod progress_tracing; +use progress_tracing::TracingProgress; + +#[derive(Debug, ThisError)] +#[non_exhaustive] +pub enum GitError { + #[error("Failed to prepare for fetch: {0}")] + PrepareFetchError(#[source] Box), + + #[error("Failed to fetch: {0}")] + FetchError(#[source] Box), + + #[error("Failed to checkout: {0}")] + CheckOutError(#[source] Box), +} + +impl From for GitError { + fn from(e: clone::Error) -> Self { + Self::PrepareFetchError(Box::new(e)) + } +} + +impl From for GitError { + fn from(e: clone::fetch::Error) -> Self { + Self::FetchError(Box::new(e)) + } +} + +impl From for GitError { + fn from(e: clone::checkout::main_worktree::Error) -> Self { + Self::CheckOutError(Box::new(e)) + } +} + +#[derive(Clone, Debug)] +pub struct GitUrl(Url); + +impl FromStr for GitUrl { + type Err = gix::url::parse::Error; + + fn from_str(s: &str) -> Result { + Url::try_from(s).map(Self) + } +} + +#[derive(Debug)] +pub struct Repository(gix::Repository); + +impl Repository { + /// WARNING: This is a blocking operation, if you want to use it in + /// async context then you must wrap the call in [`tokio::task::spawn_blocking`]. + /// + /// WARNING: This function must be called after tokio runtime is initialized. + pub fn shallow_clone(url: GitUrl, path: &Path) -> Result { + let url_bstr = url.0.to_bstring(); + let url_str = String::from_utf8_lossy(&url_bstr); + + debug!("Shallow cloning {url_str} to {}", path.display()); + + let mut progress = TracingProgress::new(CompactString::new("Cloning")); + + Ok(Self( + clone::PrepareFetch::new( + url.0, + path, + create::Kind::WithWorktree, + create::Options { + destination_must_be_empty: true, + ..Default::default() + }, + open::Options::isolated(), + )? + .with_shallow(remote::fetch::Shallow::DepthAtRemote( + NonZeroU32::new(1).unwrap(), + )) + .fetch_then_checkout(&mut progress, &AtomicBool::new(false))? + .0 + .main_worktree(&mut progress, &AtomicBool::new(false))? + .0, + )) + } +} diff --git a/crates/binstalk/src/helpers/git/progress_tracing.rs b/crates/binstalk/src/helpers/git/progress_tracing.rs new file mode 100644 index 000000000..67ebe562f --- /dev/null +++ b/crates/binstalk/src/helpers/git/progress_tracing.rs @@ -0,0 +1,144 @@ +use std::{ + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, + time::Duration, +}; + +use compact_str::{format_compact, CompactString}; +use gix::progress::{ + prodash::messages::MessageLevel, Id, Progress, Step, StepShared, Unit, UNKNOWN, +}; +use tokio::time; +use tracing::{error, info}; + +pub(super) struct TracingProgress { + name: CompactString, + id: Id, + max: Option, + unit: Option, + step: usize, + trigger: Arc, +} + +const EMIT_LOG_EVERY_S: f32 = 0.5; +const SEP: &str = "::"; + +impl TracingProgress { + /// Create a new instanCompactce from `name`. + pub fn new(name: CompactString) -> Self { + let trigger = Arc::new(AtomicBool::new(true)); + tokio::spawn({ + let mut interval = time::interval(Duration::from_secs_f32(EMIT_LOG_EVERY_S)); + interval.set_missed_tick_behavior(time::MissedTickBehavior::Skip); + + let trigger = Arc::clone(&trigger); + async move { + while Arc::strong_count(&trigger) > 1 { + trigger.store(true, Ordering::Relaxed); + + interval.tick().await; + } + } + }); + Self { + name, + id: UNKNOWN, + max: None, + step: 0, + unit: None, + trigger, + } + } +} + +impl Progress for TracingProgress { + type SubProgress = TracingProgress; + + fn add_child(&mut self, name: impl Into) -> Self::SubProgress { + self.add_child_with_id(name, UNKNOWN) + } + + fn add_child_with_id(&mut self, name: impl Into, id: Id) -> Self::SubProgress { + Self { + name: format_compact!("{}{}{}", self.name, SEP, Into::::into(name)), + id, + step: 0, + max: None, + unit: None, + trigger: Arc::clone(&self.trigger), + } + } + + fn init(&mut self, max: Option, unit: Option) { + self.max = max; + self.unit = unit; + } + + fn set(&mut self, step: usize) { + self.step = step; + if self.trigger.swap(false, Ordering::Relaxed) { + match (self.max, &self.unit) { + (max, Some(unit)) => { + info!("{} → {}", self.name, unit.display(step, max, None)) + } + (Some(max), None) => info!("{} → {} / {}", self.name, step, max), + (None, None) => info!("{} → {}", self.name, step), + } + } + } + + fn unit(&self) -> Option { + self.unit.clone() + } + + fn max(&self) -> Option { + self.max + } + + fn set_max(&mut self, max: Option) -> Option { + let prev = self.max; + self.max = max; + prev + } + + fn step(&self) -> usize { + self.step + } + + fn inc_by(&mut self, step: usize) { + self.set(self.step + step) + } + + fn set_name(&mut self, name: impl Into) { + let name = name.into(); + self.name = self + .name + .split("::") + .next() + .map(|parent| format_compact!("{}{}{}", parent.to_owned(), SEP, name)) + .unwrap_or_else(|| name.into()); + } + + fn name(&self) -> Option { + self.name.split(SEP).nth(1).map(ToOwned::to_owned) + } + + fn id(&self) -> Id { + self.id + } + + fn message(&self, level: MessageLevel, message: impl Into) { + let message: String = message.into(); + match level { + MessageLevel::Info => info!("ℹ{} → {}", self.name, message), + MessageLevel::Failure => error!("𐄂{} → {}", self.name, message), + MessageLevel::Success => info!("✓{} → {}", self.name, message), + } + } + + fn counter(&self) -> Option { + None + } +} diff --git a/crates/binstalk/src/lib.rs b/crates/binstalk/src/lib.rs index b4c67f0b2..a32de76f1 100644 --- a/crates/binstalk/src/lib.rs +++ b/crates/binstalk/src/lib.rs @@ -1,3 +1,5 @@ +#![cfg_attr(docsrs, feature(doc_auto_cfg))] + pub mod bins; pub mod drivers; pub mod errors; diff --git a/crates/binstalk/src/ops.rs b/crates/binstalk/src/ops.rs index 58affa677..382d3fc50 100644 --- a/crates/binstalk/src/ops.rs +++ b/crates/binstalk/src/ops.rs @@ -10,7 +10,9 @@ use tokio::{ use crate::{ fetchers::{Data, Fetcher, TargetData}, - helpers::{gh_api_client::GhApiClient, jobserver_client::LazyJobserverClient, remote::Client}, + helpers::{ + self, gh_api_client::GhApiClient, jobserver_client::LazyJobserverClient, remote::Client, + }, manifests::cargo_toml_binstall::PkgOverride, DesiredTargets, }; @@ -19,6 +21,13 @@ pub mod resolve; pub type Resolver = fn(Client, GhApiClient, Arc, Arc) -> Arc; +#[non_exhaustive] +pub enum CargoTomlFetchOverride { + #[cfg(feature = "git")] + Git(helpers::git::GitUrl), + Path(PathBuf), +} + pub struct Options { pub no_symlinks: bool, pub dry_run: bool, @@ -28,7 +37,7 @@ pub struct Options { pub no_track: bool, pub version_req: Option, - pub manifest_path: Option, + pub cargo_toml_fetch_override: Option, pub cli_overrides: PkgOverride, pub desired_targets: DesiredTargets, diff --git a/crates/binstalk/src/ops/resolve.rs b/crates/binstalk/src/ops/resolve.rs index f38246bfa..6bc87ad2b 100644 --- a/crates/binstalk/src/ops/resolve.rs +++ b/crates/binstalk/src/ops/resolve.rs @@ -13,17 +13,18 @@ use itertools::Itertools; use leon::Template; use maybe_owned::MaybeOwned; use semver::{Version, VersionReq}; -use tokio::task::block_in_place; +use tempfile::TempDir; +use tokio::task::{block_in_place, spawn_blocking}; use tracing::{debug, info, instrument, warn}; -use super::Options; use crate::{ bins, drivers::fetch_crate_cratesio, errors::{BinstallError, VersionParseError}, fetchers::{Data, Fetcher, TargetData}, - helpers::{download::ExtractedFiles, remote::Client, target_triple::TargetTriple}, + helpers::{self, download::ExtractedFiles, remote::Client, target_triple::TargetTriple}, manifests::cargo_toml_binstall::{Meta, PkgMeta, PkgOverride}, + ops::{CargoTomlFetchOverride, Options}, }; mod crate_name; @@ -359,9 +360,24 @@ impl PackageInfo { version_req: &VersionReq, client: Client, ) -> Result, BinstallError> { + use CargoTomlFetchOverride::*; + // Fetch crate via crates.io, git, or use a local manifest path - let manifest = match opts.manifest_path.as_ref() { - Some(manifest_path) => load_manifest_path(manifest_path)?, + let manifest = match opts.cargo_toml_fetch_override.as_ref() { + Some(Path(manifest_path)) => load_manifest_path(manifest_path)?, + #[cfg(feature = "git")] + Some(Git(git_url)) => { + let git_url = git_url.clone(); + let name = name.clone(); + + spawn_blocking(move || { + let dir = TempDir::new()?; + helpers::git::Repository::shallow_clone(git_url, dir.as_ref())?; + + helpers::cargo_toml_workspace::load_manifest_from_workspace(dir.as_ref(), &name) + }) + .await?? + } None => { Box::pin(fetch_crate_cratesio( client, diff --git a/crates/normalize-path/src/lib.rs b/crates/normalize-path/src/lib.rs index 42e2b8ece..cf65d0254 100644 --- a/crates/normalize-path/src/lib.rs +++ b/crates/normalize-path/src/lib.rs @@ -29,6 +29,11 @@ pub trait NormalizePath { /// However, this does not resolve links. fn normalize(&self) -> PathBuf; + /// Same as [`NormalizePath::normalize`] except that if + /// `Component::Prefix`/`Component::RootDir` is encountered, + /// or if the path points outside of current dir, returns `None`. + fn try_normalize(&self) -> Option; + /// Return `true` if the path is normalized. /// /// # Quirk @@ -68,6 +73,27 @@ impl NormalizePath for Path { ret } + fn try_normalize(&self) -> Option { + let mut ret = PathBuf::new(); + + for component in self.components() { + match component { + Component::Prefix(..) | Component::RootDir => return None, + Component::CurDir => {} + Component::ParentDir => { + if !ret.pop() { + return None; + } + } + Component::Normal(c) => { + ret.push(c); + } + } + } + + Some(ret) + } + fn is_normalized(&self) -> bool { for component in self.components() { match component { diff --git a/e2e-tests/git.sh b/e2e-tests/git.sh new file mode 100644 index 000000000..8058d49c3 --- /dev/null +++ b/e2e-tests/git.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +set -euxo pipefail + +test_cargo_binstall_install() { + # Test that the installed binaries can be run + cargo binstall --help >/dev/null + + cargo_binstall_version="$(cargo binstall -V)" + echo "$cargo_binstall_version" + + [ "$cargo_binstall_version" = "cargo-binstall 0.12.0" ] +} + +unset CARGO_INSTALL_ROOT + +CARGO_HOME="$(mktemp -d 2>/dev/null || mktemp -d -t 'cargo-home')" +export CARGO_HOME +export PATH="$CARGO_HOME/bin:$PATH" + +GIT="$(mktemp -d 2>/dev/null || mktemp -d -t 'git')" +if [ "$OSTYPE" = "cygwin" ] || [ "$OSTYPE" = "msys" ]; then + # Convert it to windows path so `--git "file://$GIT"` would work + # on windows. + GIT="$(cygpath -w "$GIT")" +fi + +git init "$GIT" +cp manifests/github-test-Cargo.toml "$GIT/Cargo.toml" +( + cd "$GIT" + git config user.email 'test@example.com' + git config user.name 'test' + git add Cargo.toml + git commit -m "Add Cargo.toml" +) + +# Install binaries using `--git` +"./$1" binstall --force --git "file://$GIT" --no-confirm cargo-binstall + +test_cargo_binstall_install + +cp -r manifests/workspace/* "$GIT" +( + cd "$GIT" + git add . + git commit -m 'Update to workspace' +) + +# Install binaries using `--git` +"./$1" binstall --force --git "file://$GIT" --no-confirm cargo-binstall + +test_cargo_binstall_install + +# Install binaries using `--git` +"./$1" binstall --force --git "file://$GIT" --no-confirm cargo-watch + +cargo_watch_version="$(cargo watch -V)" +echo "$cargo_watch_version" + +[ "$cargo_watch_version" = "cargo-watch 8.4.0" ] diff --git a/e2e-tests/manifests/workspace/Cargo.toml b/e2e-tests/manifests/workspace/Cargo.toml new file mode 100644 index 000000000..6e98755f7 --- /dev/null +++ b/e2e-tests/manifests/workspace/Cargo.toml @@ -0,0 +1,3 @@ +[workspace] +members = ["crates/*/*/*/*/*/*", "b/*/*/*/*"] +exclude = ["b/c/d/e/*"] diff --git a/e2e-tests/manifests/workspace/b/c/d/e/f/Cargo.toml b/e2e-tests/manifests/workspace/b/c/d/e/f/Cargo.toml new file mode 100644 index 000000000..176f70447 --- /dev/null +++ b/e2e-tests/manifests/workspace/b/c/d/e/f/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "cargo-binstall2" +description = "Rust binary package installer for CI integration" +repository = "https://bitbucket.org/nobodyxusdcdc/hello-world" +version = "0.0.0" +rust-version = "1.61.0" +authors = ["ryan "] +edition = "2021" +license = "GPL-3.0" + +[[bin]] +name = "cargo-binstall" +path = "src/main.rs" diff --git a/e2e-tests/manifests/workspace/crates/a/b/c/d/e/cargo-binstall/Cargo.toml b/e2e-tests/manifests/workspace/crates/a/b/c/d/e/cargo-binstall/Cargo.toml new file mode 100644 index 000000000..d54358560 --- /dev/null +++ b/e2e-tests/manifests/workspace/crates/a/b/c/d/e/cargo-binstall/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "cargo-binstall" +version = "0.12.0" +repository = "https://github.com/cargo-bins/cargo-binstall" + +[[bin]] +name = "cargo-binstall" +path = "src/main.rs" diff --git a/e2e-tests/manifests/workspace/crates/a/b/c/d/e/cargo-watch/Cargo.toml b/e2e-tests/manifests/workspace/crates/a/b/c/d/e/cargo-watch/Cargo.toml new file mode 100644 index 000000000..71d359714 --- /dev/null +++ b/e2e-tests/manifests/workspace/crates/a/b/c/d/e/cargo-watch/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "cargo-watch" +version = "8.4.0" +repository = "https://github.com/watchexec/cargo-watch" + +[[bin]] +name = "cargo-watch" diff --git a/e2e-tests/manifests/workspace/crates/a/b/c/d/e/cargo-watch/src/main.rs b/e2e-tests/manifests/workspace/crates/a/b/c/d/e/cargo-watch/src/main.rs new file mode 100644 index 000000000..e69de29bb diff --git a/justfile b/justfile index 58a05e6ee..4afb56871 100644 --- a/justfile +++ b/justfile @@ -74,8 +74,8 @@ support-pkg-config := if target == target-host { } else { "" } cargo-features := trim_end_match(if override-features != "" { override-features - } else if (cargo-profile / ci-or-no) == "dev/ci" { "rustls,fancy-with-backtrace,zstd-thin,log_max_level_debug" + (if support-pkg-config != "" { ",pkg-config" } else { "" }) + extra-features - } else if (cargo-profile / ci-or-no) == "release/ci" { "static,rustls,trust-dns,fancy-no-backtrace,zstd-thin,log_release_max_level_debug,cross-lang-fat-lto" + extra-features + } else if (cargo-profile / ci-or-no) == "dev/ci" { "git,rustls,fancy-with-backtrace,zstd-thin,log_max_level_debug" + (if support-pkg-config != "" { ",pkg-config" } else { "" }) + extra-features + } else if (cargo-profile / ci-or-no) == "release/ci" { "git,static,rustls,trust-dns,fancy-no-backtrace,zstd-thin,log_release_max_level_debug,cross-lang-fat-lto" + extra-features } else { extra-features }, ",") @@ -184,6 +184,7 @@ check: print-env {{cargo-bin}} check {{cargo-build-args}} cargo-hack hack check --feature-powerset -p leon {{cargo-check-args}} {{cargo-bin}} check -p binstalk-downloader --no-default-features + {{cargo-bin}} check -p cargo-binstall --no-default-features --features rustls {{cargo-check-args}} cargo-hack hack check -p binstalk-downloader \ --feature-powerset \ --include-features default,json,gh-api-client \ @@ -210,6 +211,7 @@ e2e-test-upgrade: (e2e-test "upgrade") e2e-test-self-upgrade-no-symlink: (e2e-test "self-upgrade-no-symlink") e2e-test-uninstall: (e2e-test "uninstall") e2e-test-no-track: (e2e-test "no-track") +e2e-test-git: (e2e-test "git") # WinTLS (Windows in CI) does not have TLS 1.3 support [windows] @@ -218,7 +220,7 @@ e2e-test-tls: (e2e-test "tls" "1.2") [macos] e2e-test-tls: (e2e-test "tls" "1.2") (e2e-test "tls" "1.3") -e2e-tests: e2e-test-live e2e-test-manifest-path e2e-test-other-repos e2e-test-strategies e2e-test-version-syntax e2e-test-upgrade e2e-test-tls e2e-test-self-upgrade-no-symlink e2e-test-uninstall e2e-test-subcrate e2e-test-no-track +e2e-tests: e2e-test-live e2e-test-manifest-path e2e-test-git e2e-test-other-repos e2e-test-strategies e2e-test-version-syntax e2e-test-upgrade e2e-test-tls e2e-test-self-upgrade-no-symlink e2e-test-uninstall e2e-test-subcrate e2e-test-no-track unit-tests: print-env {{cargo-bin}} test {{cargo-build-args}}