forked from rust-lang/log
-
Notifications
You must be signed in to change notification settings - Fork 0
/
visitor.rs
89 lines (73 loc) · 2.55 KB
/
visitor.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
use std::{
io::{self, Read},
path::{Path, PathBuf},
};
use cargo_toml::Manifest;
use normalize_path::NormalizePath;
use tracing::debug;
use super::vfs::Vfs;
use crate::{
errors::BinstallError,
helpers::download::{DownloadError, Entries, TarEntriesVisitor},
manifests::cargo_toml_binstall::Meta,
};
#[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(),
}
}
}
impl TarEntriesVisitor for ManifestVisitor {
type Target = Manifest<Meta>;
fn visit<R: Read>(&mut self, entries: Entries<'_, R>) -> Result<(), DownloadError> {
for res in entries {
let mut entry = res?;
let path = entry.path()?;
let path = path.normalize();
let Ok(path) = path.strip_prefix(&self.manifest_dir_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(())
}
/// Load binstall metadata using the extracted information stored in memory.
fn finish(self) -> Result<Self::Target, DownloadError> {
Ok(load_manifest(&self.cargo_toml_content, &self.vfs).map_err(io::Error::from)?)
}
}
fn load_manifest(slice: &[u8], vfs: &Vfs) -> Result<Manifest<Meta>, BinstallError> {
debug!("Loading manifest directly from extracted file");
// Load and parse manifest
let mut manifest = Manifest::from_slice_with_metadata(slice)?;
// Checks vfs for binary output names
manifest.complete_from_abstract_filesystem(vfs)?;
// Return metadata
Ok(manifest)
}