Skip to content

Commit 2b99ab2

Browse files
authored
Merge pull request #64 from Gioyik/gio/read_file
feat: add read from filesystem
2 parents 2e8c594 + 34db00a commit 2b99ab2

File tree

5 files changed

+416
-1
lines changed

5 files changed

+416
-1
lines changed

Cargo.toml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,21 @@ thiserror = { version = "2.0", optional = true }
2424
url = { version = "2.3.1", optional = true }
2525
object_store = { version = "0.12.0", optional = true, features = ["gcp"] }
2626
futures = { version = "0.3.31", optional = true }
27-
27+
walkdir = { version = "2.5.0", optional = true }
2828

2929
[dev-dependencies]
3030
comfy-table = "7.1.1"
3131
cargo-release = "0.25.10"
3232
textwrap = { version = "0.16.1", features = ["default", "terminal_size"] }
3333
tokio-test = "0.4.3"
34+
tempfile = "3"
3435

3536
[features]
3637
default = ["schema"]
3738
schema = []
3839
client = ["dep:tokio", "dep:reqwest", "dep:url", "dep:thiserror", "schema"]
3940
data = ["dep:object_store", "dep:thiserror", "dep:futures", "dep:tokio"]
41+
local = ["dep:thiserror", "dep:walkdir", "schema"]
4042

4143
[[example]]
4244
name = "commit"
@@ -62,3 +64,13 @@ required-features = ["client"]
6264
name = "fetch"
6365
path = "examples/fetch.rs"
6466
required-features = ["data"]
67+
68+
[[example]]
69+
name = "load_file"
70+
path = "examples/load_file.rs"
71+
required-features = ["local"]
72+
73+
[[example]]
74+
name = "load_dir"
75+
path = "examples/load_dir.rs"
76+
required-features = ["local"]

examples/load_dir.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//! Example: Loading multiple OSV vulnerabilities from a local directory.
2+
//!
3+
//! Requires the `local` feature to be enabled.
4+
//!
5+
//! Usage:
6+
//! 1. Create a directory (e.g., `test_vuln_dir`).
7+
//! 2. Create multiple dummy OSV JSON files inside it (e.g., `vuln1.json`, `vuln2.json`).
8+
//! Use the format from the `load_file` example, changing the "id" for each.
9+
//! 3. Optionally create subdirectories with more `.json` files if testing recursion.
10+
//! 4. Run the example:
11+
//! - Non-recursive: `cargo run --example load_dir --features local -- test_vuln_dir`
12+
//! - Recursive: `cargo run --example load_dir --features local -- test_vuln_dir recursive`
13+
//! 5. Remember to delete `test_vuln_dir` afterwards.
14+
15+
#[cfg(feature = "local")]
16+
fn main() -> Result<(), Box<dyn std::error::Error>> {
17+
use osv::local::load_directory;
18+
use std::env;
19+
use std::path::Path;
20+
21+
let args: Vec<String> = env::args().collect();
22+
23+
if args.len() < 2 || args.len() > 3 {
24+
eprintln!("Usage: cargo run --example load_dir --features local -- <path_to_directory> [recursive]");
25+
std::process::exit(1);
26+
}
27+
28+
let dir_path_str = &args[1];
29+
let dir_path = Path::new(dir_path_str);
30+
let recursive = args.len() == 3 && args[2] == "recursive";
31+
32+
println!(
33+
"Attempting to load vulnerabilities from directory: {:?} (recursive: {})",
34+
dir_path, recursive
35+
);
36+
37+
match load_directory(dir_path, recursive) {
38+
Ok(vulnerabilities) => {
39+
println!(
40+
"Successfully loaded {} vulnerabilities:",
41+
vulnerabilities.len()
42+
);
43+
for (i, vulnerability) in vulnerabilities.iter().enumerate() {
44+
println!(
45+
" {}: ID = {}, Modified = {}",
46+
i + 1,
47+
vulnerability.id,
48+
vulnerability.modified
49+
// add more properties here to print
50+
);
51+
}
52+
}
53+
Err(e) => {
54+
eprintln!("Error loading directory: {}", e);
55+
std::process::exit(1);
56+
}
57+
}
58+
59+
Ok(())
60+
}
61+
62+
#[cfg(not(feature = "local"))]
63+
fn main() {
64+
println!("This example requires the 'local' feature to be enabled.");
65+
println!("Run with: cargo run --example load_dir --features local -- <path> [recursive]");
66+
}

examples/load_file.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//! Example: Loading a single OSV vulnerability from a local file.
2+
//!
3+
//! Requires the `local` feature to be enabled.
4+
//!
5+
//! Usage:
6+
//! 1. Create a dummy OSV JSON file (e.g., `test_vuln.json`):
7+
//! ```json
8+
//! {
9+
//! "schema_version": "1.0.0",
10+
//! "id": "TEST-VULN-001",
11+
//! "modified": "2023-01-01T00:00:00Z",
12+
//! "published": "2023-01-01T00:00:00Z",
13+
//! "summary": "A test vulnerability",
14+
//! "details": "Details about the test vulnerability.",
15+
//! "affected": [
16+
//! {
17+
//! "package": {
18+
//! "name": "test-package",
19+
//! "ecosystem": "PyPI"
20+
//! },
21+
//! "ranges": [
22+
//! {
23+
//! "type": "SEMVER",
24+
//! "events": [
25+
//! { "introduced": "1.0.0" },
26+
//! { "fixed": "1.0.1" }
27+
//! ]
28+
//! }
29+
//! ]
30+
//! }
31+
//! ]
32+
//! }
33+
//! ```
34+
//! 2. Run the example: `cargo run --example load_file --features local -- test_vuln.json`
35+
//! 3. Remember to delete `test_vuln.json` afterwards.
36+
37+
#[cfg(feature = "local")]
38+
fn main() -> Result<(), Box<dyn std::error::Error>> {
39+
use osv::local::load_vulnerability;
40+
use std::env;
41+
use std::path::Path;
42+
43+
let args: Vec<String> = env::args().collect();
44+
45+
if args.len() != 2 {
46+
eprintln!("Usage: cargo run --example load_file --features local -- <path_to_osv_json_file>");
47+
std::process::exit(1);
48+
}
49+
50+
let file_path_str = &args[1];
51+
let file_path = Path::new(file_path_str);
52+
53+
println!("Attempting to load vulnerability from: {:?}", file_path);
54+
55+
match load_vulnerability(file_path) {
56+
Ok(vulnerability) => {
57+
println!("Successfully loaded vulnerability:");
58+
println!("ID: {}", vulnerability.id);
59+
println!("Modified: {}", vulnerability.modified);
60+
if let Some(summary) = &vulnerability.summary {
61+
println!("Summary: {}", summary);
62+
}
63+
if let Some(details) = &vulnerability.details {
64+
println!("Details: {}", details);
65+
}
66+
}
67+
Err(e) => {
68+
eprintln!("Error loading vulnerability: {}", e);
69+
std::process::exit(1);
70+
}
71+
}
72+
73+
Ok(())
74+
}
75+
76+
#[cfg(not(feature = "local"))]
77+
fn main() {
78+
println!("This example requires the 'local' feature to be enabled.");
79+
println!("Run with: cargo run --example load_file --features local -- <path>");
80+
}

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@ pub mod client;
66

77
#[cfg(feature = "data")]
88
pub mod data;
9+
10+
#[cfg(feature = "local")]
11+
pub mod local;

0 commit comments

Comments
 (0)