From f3d3c488e31ff92957e2a3d814b105ee4a226920 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Sun, 12 Jun 2022 16:31:47 +1000 Subject: [PATCH] Impl new type `ManifestVisitor Signed-off-by: Jiahao XU --- src/drivers.rs | 3 ++ src/drivers/visitor.rs | 80 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 src/drivers/visitor.rs diff --git a/src/drivers.rs b/src/drivers.rs index 5b053f25..8c5a9724 100644 --- a/src/drivers.rs +++ b/src/drivers.rs @@ -10,6 +10,9 @@ use version::find_version; mod vfs; +mod visitor; +pub use visitor::*; + /// Fetch a crate by name and version from github /// TODO: implement this pub async fn fetch_crate_gh_releases( diff --git a/src/drivers/visitor.rs b/src/drivers/visitor.rs new file mode 100644 index 00000000..005dbace --- /dev/null +++ b/src/drivers/visitor.rs @@ -0,0 +1,80 @@ +use std::io::Read; +use std::path::{Path, PathBuf}; + +use cargo_toml::Manifest; +use log::debug; +use tar::Entries; + +use super::vfs::Vfs; +use crate::{ + helpers::{PathExt, TarEntriesVisitor}, + BinstallError, Meta, +}; + +#[derive(Debug)] +pub struct ManifestVisitor { + cargo_toml_content: Vec, + /// 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::new(), + } + } + + /// Load binstall metadata using the extracted information stored in memory. + pub fn load_manifest(&self) -> Result, BinstallError> { + debug!("Loading manifest directly from extracted file"); + + // Load and parse manifest + let mut manifest = Manifest::::from_slice_with_metadata(&self.cargo_toml_content)?; + + // Checks vfs for binary output names + manifest.complete_from_abstract_filesystem(&self.vfs)?; + + // Return metadata + Ok(manifest) + } +} + +impl TarEntriesVisitor for ManifestVisitor { + fn visit(&mut self, entries: Entries<'_, R>) -> Result<(), BinstallError> { + for res in entries { + let mut entry = res?; + let path = entry.path()?.normalize_path(); + + 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. + continue; + }; + + 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(); + entry.read_to_end(&mut self.cargo_toml_content)?; + } + } + + Ok(()) + } +}