user_dependencies_graph/user-dependencies-graph.rs
1//! $ cargo run --release --example user-dependencies2
2//!
3//! Computes time series of the fraction of deps on crates.io which point to a
4//! given user's crates.
5
6use std::collections::{BTreeMap as Map, BTreeSet as Set};
7
8const USER: &str = "dtolnay";
9
10fn main() -> db_dump::Result<()> {
11 let mut user_id = None;
12 let mut crate_owners = Vec::new();
13 let mut dependencies = Map::new();
14 let mut versions = Vec::new();
15 db_dump::Loader::new()
16 .users(|row| {
17 if row.gh_login == USER {
18 user_id = Some(row.id);
19 }
20 })
21 .crate_owners(|row| crate_owners.push(row))
22 .dependencies(|row| {
23 dependencies
24 .entry(row.version_id)
25 .or_insert_with(Vec::new)
26 .push(row);
27 })
28 .versions(|row| {
29 if !row.yanked {
30 versions.push(row);
31 }
32 })
33 .load("./db-dump.tar.gz")?;
34
35 // User id of the crate author we care about.
36 let user_id = user_id.expect("no such user");
37
38 // Set of crate ids currently owned by that user.
39 let mut their_crates = Set::new();
40 for crate_owner in crate_owners {
41 if crate_owner.owner_id == user_id {
42 their_crates.insert(crate_owner.crate_id);
43 }
44 }
45
46 let mut total_deps = 0usize;
47 let mut their_deps = 0usize;
48 let mut last_printed_ratio = 0.0..=0.0;
49 let mut latest_version = Map::new();
50
51 versions.sort_by_key(|v| v.created_at);
52
53 for version in versions {
54 let no_deps = Vec::new();
55 if let Some(prev) = latest_version.insert(version.crate_id, version.id) {
56 for dep in dependencies.get(&prev).unwrap_or(&no_deps) {
57 total_deps -= 1;
58 their_deps -= their_crates.contains(&dep.crate_id) as usize;
59 }
60 }
61 for dep in dependencies.get(&version.id).unwrap_or(&no_deps) {
62 total_deps += 1;
63 their_deps += their_crates.contains(&dep.crate_id) as usize;
64 }
65 if total_deps != 0 {
66 let ratio = their_deps as f64 / total_deps as f64;
67 if !last_printed_ratio.contains(&ratio) {
68 println!("{},{:.3}", version.created_at.naive_utc(), ratio * 100.0);
69 last_printed_ratio = ratio * 0.99999..=ratio * 1.00001;
70 }
71 }
72 }
73
74 eprintln!(
75 "{} / {} ({:.02}%)",
76 their_deps,
77 total_deps,
78 (their_deps as f64 / total_deps as f64) * 100.0,
79 );
80 Ok(())
81}