diff --git a/Cargo.lock b/Cargo.lock index bbe839ee..b229b76b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3718,9 +3718,9 @@ dependencies = [ [[package]] name = "simple-git" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48955a621e2b4a92fdb9fcbf8a5bf0e56b15a56bfe09e6defc01cb25ca59f31c" +checksum = "ceb5955ab3b66f8c0f0557873ca472c196d30a6c19696074ce3aca4c226b5c3a" dependencies = [ "compact_str", "derive_destructure2", diff --git a/crates/binstalk-manifests/src/cargo_crates_v1.rs b/crates/binstalk-manifests/src/cargo_crates_v1.rs index 6e8100be..a4821285 100644 --- a/crates/binstalk-manifests/src/cargo_crates_v1.rs +++ b/crates/binstalk-manifests/src/cargo_crates_v1.rs @@ -66,12 +66,6 @@ impl CratesToml<'_> { Self::load_from_reader(file) } - /// Only use it when you know that the crate is not in the manifest. - /// Otherwise, you need to call [`CratesToml::remove`] first. - fn insert(&mut self, cvs: &CrateVersionSource, bins: Vec) { - self.v1.push((cvs.to_string(), Cow::owned(bins))); - } - pub fn remove(&mut self, name: &str) { self.v1.retain(|(s, _bin)| { s.split_once(' ') diff --git a/crates/binstalk-manifests/src/cargo_crates_v1/crate_version_source.rs b/crates/binstalk-manifests/src/cargo_crates_v1/crate_version_source.rs index 389bed2a..a705bba2 100644 --- a/crates/binstalk-manifests/src/cargo_crates_v1/crate_version_source.rs +++ b/crates/binstalk-manifests/src/cargo_crates_v1/crate_version_source.rs @@ -1,6 +1,6 @@ use std::{borrow::Cow, fmt, str::FromStr}; -use binstalk_types::{crate_info::cratesio_url, maybe_owned::MaybeOwned}; +use binstalk_types::maybe_owned::MaybeOwned; use compact_str::CompactString; use miette::Diagnostic; use semver::Version; @@ -42,12 +42,6 @@ pub enum Source<'a> { Registry(MaybeOwned<'a, Url>), } -impl Source<'static> { - pub fn cratesio_registry() -> Self { - Self::Registry(MaybeOwned::Borrowed(cratesio_url())) - } -} - impl<'a> From<&'a CrateSource> for Source<'a> { fn from(source: &'a CrateSource) -> Self { use SourceType::*; diff --git a/crates/binstalk-registry/src/git_registry.rs b/crates/binstalk-registry/src/git_registry.rs index 518a48b0..b707b602 100644 --- a/crates/binstalk-registry/src/git_registry.rs +++ b/crates/binstalk-registry/src/git_registry.rs @@ -1,4 +1,4 @@ -use std::{io, path::PathBuf, sync::Arc}; +use std::{fmt::Display, io, path::PathBuf, sync::Arc}; use binstalk_downloader::remote::Client; use binstalk_types::cargo_toml_binstall::Meta; @@ -73,6 +73,10 @@ impl GitRegistry { })) } + pub fn url(&self) -> impl Display + '_ { + &self.0.url + } + /// WARNING: This is a blocking operation. fn find_crate_matched_ver( repo: &Repository, diff --git a/crates/binstalk-registry/src/lib.rs b/crates/binstalk-registry/src/lib.rs index 59c40c7e..6dd19ecc 100644 --- a/crates/binstalk-registry/src/lib.rs +++ b/crates/binstalk-registry/src/lib.rs @@ -1,6 +1,6 @@ #![cfg_attr(docsrs, feature(doc_auto_cfg))] -use std::{io, str::FromStr, sync::Arc}; +use std::{fmt, io, str::FromStr, sync::Arc}; use base16::DecodeError as Base16DecodeError; use binstalk_downloader::{ @@ -197,6 +197,16 @@ impl Registry { } } +impl fmt::Display for Registry { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + #[cfg(feature = "git")] + Registry::Git(registry) => fmt::Display::fmt(®istry.url(), f), + Registry::Sparse(registry) => fmt::Display::fmt(®istry.url(), f), + } + } +} + impl FromStr for Registry { type Err = InvalidRegistryError; diff --git a/crates/binstalk-registry/src/sparse_registry.rs b/crates/binstalk-registry/src/sparse_registry.rs index 7dca1b32..48a4f5b2 100644 --- a/crates/binstalk-registry/src/sparse_registry.rs +++ b/crates/binstalk-registry/src/sparse_registry.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + use binstalk_downloader::remote::{Client, Error as RemoteError}; use binstalk_types::cargo_toml_binstall::Meta; use cargo_toml_workspace::cargo_toml::Manifest; @@ -28,6 +30,10 @@ impl SparseRegistry { } } + pub fn url(&self) -> impl Display + '_ { + &self.url + } + async fn get_dl_template(&self, client: &Client) -> Result<&str, RegistryError> { self.dl_template .get_or_try_init(|| { diff --git a/crates/binstalk/Cargo.toml b/crates/binstalk/Cargo.toml index f067de70..d5e6f75a 100644 --- a/crates/binstalk/Cargo.toml +++ b/crates/binstalk/Cargo.toml @@ -31,7 +31,7 @@ leon = "3.0.0" maybe-owned = "0.3.4" miette = "7.0.0" semver = { version = "1.0.17", features = ["serde"] } -simple-git = { version = "0.2.4", optional = true } +simple-git = { version = "0.2.10", optional = true } strum = "0.26.1" target-lexicon = { version = "0.12.11", features = ["std"] } tempfile = "3.5.0" diff --git a/crates/binstalk/src/ops/resolve.rs b/crates/binstalk/src/ops/resolve.rs index b8e02374..5c6379d9 100644 --- a/crates/binstalk/src/ops/resolve.rs +++ b/crates/binstalk/src/ops/resolve.rs @@ -8,6 +8,7 @@ use std::{ }; use binstalk_fetchers::FETCHER_GH_CRATE_META; +use binstalk_types::crate_info::{CrateSource, SourceType}; use compact_str::{CompactString, ToCompactString}; use itertools::Itertools; use leon::Template; @@ -15,6 +16,7 @@ use maybe_owned::MaybeOwned; use semver::{Version, VersionReq}; use tokio::task::spawn_blocking; use tracing::{debug, error, info, instrument, warn}; +use url::Url; use crate::{ bins, @@ -195,6 +197,7 @@ async fn resolve_inner( new_version: package_info.version, name: package_info.name, version_req: version_req_str, + source: package_info.source, bin_files, }))); } else { @@ -365,6 +368,7 @@ struct PackageInfo { binaries: Vec, name: CompactString, version_str: CompactString, + source: CrateSource, version: Version, repo: Option, overrides: BTreeMap, @@ -387,43 +391,80 @@ impl PackageInfo { use CargoTomlFetchOverride::*; // Fetch crate via crates.io, git, or use a local manifest path - let manifest = match opts.cargo_toml_fetch_override.as_ref() { - Some(Path(manifest_path)) => { - let manifest_path = manifest_path.clone(); - let name = name.clone(); + let (manifest, source) = match opts.cargo_toml_fetch_override.as_ref() { + Some(Path(manifest_path)) => ( + spawn_blocking({ + let manifest_path = manifest_path.clone(); + let name = name.clone(); - spawn_blocking(move || load_manifest_path(manifest_path, &name)).await?? - } + move || load_manifest_path(manifest_path, &name) + }) + .await??, + CrateSource { + source_type: SourceType::Path, + url: MaybeOwned::Owned(Url::parse(&format!( + "file://{}", + manifest_path.display() + ))?), + }, + ), #[cfg(feature = "git")] Some(Git(git_url)) => { use crate::helpers::git::{GitCancellationToken, Repository as GitRepository}; - let git_url = git_url.clone(); - let name = name.clone(); let cancellation_token = GitCancellationToken::default(); // Cancel git operation if the future is cancelled (dropped). let cancel_on_drop = cancellation_token.clone().cancel_on_drop(); - let ret = spawn_blocking(move || { - let dir = tempfile::TempDir::new()?; - GitRepository::shallow_clone(git_url, dir.as_ref(), Some(cancellation_token))?; + let (ret, commit_hash) = spawn_blocking({ + let git_url = git_url.clone(); + let name = name.clone(); + move || { + let dir = tempfile::TempDir::new()?; + let repo = GitRepository::shallow_clone( + git_url, + dir.as_ref(), + Some(cancellation_token), + )?; - load_manifest_from_workspace(dir.as_ref(), &name).map_err(BinstallError::from) + Ok::<_, BinstallError>(( + load_manifest_from_workspace(dir.as_ref(), &name) + .map_err(BinstallError::from)?, + repo.get_head_commit_hash()?, + )) + } }) .await??; // Git operation done, disarm it cancel_on_drop.disarm(); - ret + ( + ret, + CrateSource { + source_type: SourceType::Git, + url: MaybeOwned::Owned(Url::parse(&format!("{git_url}#{commit_hash}"))?), + }, + ) } - None => { + None => ( Box::pin( opts.registry .fetch_crate_matched(client, &name, version_req), ) - .await? - } + .await?, + { + let registry = format!("{}", opts.registry); + if registry == "https://index.crates.io/" { + CrateSource::cratesio_registry() + } else { + CrateSource { + source_type: SourceType::Registry, + url: MaybeOwned::Owned(Url::parse(®istry)?), + } + } + }, + ), }; let Some(mut package) = manifest.package else { @@ -479,6 +520,7 @@ impl PackageInfo { meta, binaries, name, + source, version_str: new_version_str, version: new_version, repo: package.repository().map(ToString::to_string), diff --git a/crates/binstalk/src/ops/resolve/resolution.rs b/crates/binstalk/src/ops/resolve/resolution.rs index 9c149dea..75d4f398 100644 --- a/crates/binstalk/src/ops/resolve/resolution.rs +++ b/crates/binstalk/src/ops/resolve/resolution.rs @@ -22,6 +22,7 @@ pub struct ResolutionFetch { pub name: CompactString, pub version_req: CompactString, pub bin_files: Vec, + pub source: CrateSource, } pub struct ResolutionSource { @@ -84,7 +85,7 @@ impl ResolutionFetch { name: self.name, version_req: self.version_req, current_version: self.new_version, - source: CrateSource::cratesio_registry(), + source: self.source, target: self.fetcher.target().to_compact_string(), bins: self .bin_files diff --git a/e2e-tests/git.sh b/e2e-tests/git.sh index 8058d49c..0811f88b 100644 --- a/e2e-tests/git.sh +++ b/e2e-tests/git.sh @@ -46,16 +46,29 @@ cp -r manifests/workspace/* "$GIT" git add . git commit -m 'Update to workspace' ) +COMMIT_HASH="$(cd "$GIT" && git rev-parse HEAD)" -# Install binaries using `--git` +if [ "$OSTYPE" = "cygwin" ] || [ "$OSTYPE" = "msys" ]; then + source="(git+file:///$(cygpath -m "$GIT")#$COMMIT_HASH)" +else + source="(git+file://$GIT#$COMMIT_HASH)" +fi + +# Install cargo-binstall using `--git` "./$1" binstall --force --git "file://$GIT" --no-confirm cargo-binstall test_cargo_binstall_install -# Install binaries using `--git` +cat "$CARGO_HOME/.crates.toml" +grep -F "cargo-binstall 0.12.0 $source" <"$CARGO_HOME/.crates.toml" + +# Install cargo-watch 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" ] + +cat "$CARGO_HOME/.crates.toml" +grep -F "cargo-watch 8.4.0 $source" <"$CARGO_HOME/.crates.toml" diff --git a/e2e-tests/manifest-path.sh b/e2e-tests/manifest-path.sh index 88cefad6..35f2a1b7 100755 --- a/e2e-tests/manifest-path.sh +++ b/e2e-tests/manifest-path.sh @@ -19,3 +19,6 @@ cargo_binstall_version="$(cargo binstall -V)" echo "$cargo_binstall_version" [ "$cargo_binstall_version" = "cargo-binstall 0.12.0" ] + +cat "$CARGO_HOME/.crates.toml" +grep -F "cargo-binstall 0.12.0 (path+file://manifests/github-test-Cargo.toml)" <"$CARGO_HOME/.crates.toml" diff --git a/e2e-tests/registries.sh b/e2e-tests/registries.sh index 7eb3f041..7be7ffaf 100644 --- a/e2e-tests/registries.sh +++ b/e2e-tests/registries.sh @@ -43,20 +43,27 @@ EOF # Install binaries using default registry in config "./$1" binstall --force -y cargo-binstall@0.12.0 +grep -F "cargo-binstall 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" <"$CARGO_HOME/.crates.toml" + test_cargo_binstall_install # Install binaries using registry t2 in config "./$1" binstall --force --registry t2 -y cargo-binstall@0.12.0 +grep -F "cargo-binstall 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" <"$CARGO_HOME/.crates.toml" + test_cargo_binstall_install # Install binaries using registry t3 in env CARGO_REGISTRIES_t3_INDEX='sparse+https://index.crates.io/' "./$1" binstall --force --registry t3 -y cargo-binstall@0.12.0 -test_cargo_binstall_install +grep -F "cargo-binstall 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" <"$CARGO_HOME/.crates.toml" +test_cargo_binstall_install # Install binaries using index directly "./$1" binstall --force --index 'sparse+https://index.crates.io/' -y cargo-binstall@0.12.0 +grep -F "cargo-binstall 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" <"$CARGO_HOME/.crates.toml" + test_cargo_binstall_install