rustsec_admin/
osv_export.rs1use std::path::{Path, PathBuf};
4
5use rustsec::{
6 advisory::Informational,
7 fs,
8 osv::OsvAdvisory,
9 repository::git::{GitModificationTimes, GitPath, Repository},
10 Advisory, Collection,
11};
12
13use crate::{
14 error::{Error, ErrorKind},
15 prelude::*,
16};
17
18pub struct OsvExporter {
20 repository: Repository,
22
23 mod_times: GitModificationTimes,
25}
26
27impl OsvExporter {
28 pub fn new(repo_path: Option<&Path>) -> Result<Self, Error> {
30 let repository = match repo_path {
31 Some(path) => Repository::open(path)?,
32 None => Repository::fetch_default_repo()?,
33 };
34 let mod_times = GitModificationTimes::new(&repository)?;
35 Ok(Self {
36 repository,
37 mod_times,
38 })
39 }
40
41 pub fn export_all(&self, destination_folder: &Path) -> Result<(), Error> {
43 let repo_path = self.repository.path();
44 let collection_path = repo_path.join(Collection::Crates.as_str());
45 let mut found_at_least_one_advisory = false;
46
47 if let Ok(collection_entry) = fs::read_dir(collection_path) {
48 for dir_entry in collection_entry {
49 for advisory_entry in fs::read_dir(dir_entry?.path())? {
50 found_at_least_one_advisory = true;
51
52 let advisory_path = advisory_entry?.path();
54 let advisory = Advisory::load_file(&advisory_path)?;
55 let id = advisory.id().clone();
56
57 if let Some(kind) = &advisory.metadata.informational {
58 match kind {
59 Informational::Unmaintained => (),
63 Informational::Unsound => (),
64 Informational::Notice => (),
65 _ => continue,
66 }
67 }
68
69 let relative_path = advisory_path.strip_prefix(repo_path).unwrap();
73 let gitpath = GitPath::new(&self.repository, relative_path)?;
74 let osv = OsvAdvisory::from_rustsec(advisory, &self.mod_times, gitpath);
75
76 let mut output_path: PathBuf = destination_folder.join(id.as_str());
78 output_path.set_extension("json");
79 let output_file = fs::File::create(output_path)?;
80 let writer = std::io::BufWriter::new(output_file);
81 serde_json::to_writer_pretty(writer, &osv)
82 .map_err(|err| format_err!(ErrorKind::Io, "{}", err))?
83 }
84 }
85 }
86 if found_at_least_one_advisory {
87 Ok(())
88 } else {
89 Err(format_err!(
90 ErrorKind::Io,
91 format!("Could not find any advisories in {:?}", repo_path)
92 )
93 .into())
94 }
95 }
96}