cargo-binstall/crates/binstalk-registry/src/visitor.rs
Tomas Olvecky dfa230f039
Use binary name when searching for artifacts (#1747)
* Use binary name when searching for artifacts

When there is a single binary declared in the manifest and
it differs from the package name, add it to the list of handles
used for pre-built artifact fetching.

* Simplify `binary_name` assignment with a `match`

* Add e2e test

* Only attempt to use the binary name with `GhCrateMeta` fetcher

* Avoid too much over-allocating.

Technically it should also check if gh-crate-meta resolver is enabled, but it is unlikely for it to be disabled and overallocating for extra n-target should be fine, it is an improvement over doubling the space allocated if the binary_name is Some.

* Fix fmt in crates/binstalk/src/ops/resolve.rs

---------

Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>
2024-06-14 04:52:37 +00:00

81 lines
2.5 KiB
Rust

use std::path::{Path, PathBuf};
use binstalk_downloader::download::{DownloadError, TarEntriesVisitor, TarEntry};
use binstalk_types::cargo_toml_binstall::Meta;
use cargo_toml_workspace::cargo_toml::{Manifest, Value};
use normalize_path::NormalizePath;
use tokio::io::AsyncReadExt;
use tracing::debug;
use crate::{vfs::Vfs, RegistryError};
#[derive(Debug)]
pub(super) struct ManifestVisitor {
cargo_toml_content: Vec<u8>,
/// manifest_dir_path is treated as the current dir.
manifest_dir_path: PathBuf,
vfs: Vfs,
}
impl ManifestVisitor {
pub(super) fn new(manifest_dir_path: PathBuf) -> Self {
Self {
// Cargo.toml is quite large usually.
cargo_toml_content: Vec::with_capacity(2000),
manifest_dir_path,
vfs: Vfs::default(),
}
}
}
#[async_trait::async_trait]
impl TarEntriesVisitor for ManifestVisitor {
async fn visit(&mut self, entry: &mut dyn TarEntry) -> Result<(), DownloadError> {
let path = entry.path()?;
let path = path.normalize();
let path = if let Ok(path) = path.strip_prefix(&self.manifest_dir_path) {
path
} else {
// The path is outside of the curr dir (manifest dir),
// ignore it.
return Ok(());
};
if path == Path::new("Cargo.toml")
|| path == Path::new("src/main.rs")
|| path.starts_with("src/bin")
{
self.vfs.add_path(path);
}
if path == Path::new("Cargo.toml") {
// Since it is possible for the same Cargo.toml to appear
// multiple times using `tar --keep-old-files`, here we
// clear the buffer first before reading into it.
self.cargo_toml_content.clear();
self.cargo_toml_content
.reserve_exact(entry.size()?.try_into().unwrap_or(usize::MAX));
entry.read_to_end(&mut self.cargo_toml_content).await?;
}
Ok(())
}
}
impl ManifestVisitor {
/// Load binstall metadata using the extracted information stored in memory.
pub(super) fn load_manifest(self) -> Result<Manifest<Meta>, RegistryError> {
debug!("Loading manifest directly from extracted file");
// Load and parse manifest
let mut manifest = Manifest::from_slice_with_metadata(&self.cargo_toml_content)?;
debug!("Manifest: {manifest:?}");
// Checks vfs for binary output names
manifest.complete_from_abstract_filesystem::<Value, _>(&self.vfs, None)?;
// Return metadata
Ok(manifest)
}
}