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
90
91
92
93
94
95
96
use std::path::{Path, PathBuf};
use rustsec::{
advisory::Informational,
fs,
osv::OsvAdvisory,
repository::git::{GitModificationTimes, GitPath, Repository},
Advisory, Collection,
};
use crate::{
error::{Error, ErrorKind},
prelude::*,
};
pub struct OsvExporter {
repository: Repository,
mod_times: GitModificationTimes,
}
impl OsvExporter {
pub fn new(repo_path: Option<&Path>) -> Result<Self, Error> {
let repository = match repo_path {
Some(path) => Repository::open(path)?,
None => Repository::fetch_default_repo()?,
};
let mod_times = GitModificationTimes::new(&repository)?;
Ok(Self {
repository,
mod_times,
})
}
pub fn export_all(&self, destination_folder: &Path) -> Result<(), Error> {
let repo_path = self.repository.path();
let collection_path = repo_path.join(Collection::Crates.as_str());
let mut found_at_least_one_advisory = false;
if let Ok(collection_entry) = fs::read_dir(&collection_path) {
for dir_entry in collection_entry {
for advisory_entry in fs::read_dir(dir_entry?.path())? {
found_at_least_one_advisory = true;
let advisory_path = advisory_entry?.path();
let advisory = Advisory::load_file(&advisory_path)?;
let id = advisory.id().clone();
if let Some(kind) = &advisory.metadata.informational {
match kind {
Informational::Unmaintained => (),
Informational::Unsound => (),
Informational::Notice => (),
_ => continue,
}
}
let relative_path = advisory_path.strip_prefix(repo_path).unwrap();
let gitpath = GitPath::new(&self.repository, relative_path)?;
let osv = OsvAdvisory::from_rustsec(advisory, &self.mod_times, gitpath);
let mut output_path: PathBuf = destination_folder.join(id.as_str());
output_path.set_extension("json");
let output_file = fs::File::create(output_path)?;
let writer = std::io::BufWriter::new(output_file);
serde_json::to_writer_pretty(writer, &osv)
.map_err(|err| format_err!(ErrorKind::Io, "{}", err))?
}
}
}
if found_at_least_one_advisory {
Ok(())
} else {
Err(format_err!(
ErrorKind::Io,
format!("Could not find any advisories in {:?}", repo_path)
)
.into())
}
}
}