nitai/projects
noxstrap / src / crates / nox-roblox / examples / livecheck.rs
89 lines · 3.3 KB Raw
1//! Exercises the real deploy chain end to end: resolve, manifest, download,
2//! checksum, extract. Run manually; it talks to Roblox's servers.
3
4use nox_roblox::deploy::{install_package, latest, manifest, Binary, Event};
5use std::time::Instant;
6
7fn main() {
8 let channel = std::env::args().nth(1).unwrap_or_else(|| "LIVE".into());
9 println!("http backend: {}", nox_net::backend_name());
10
11 let t = Instant::now();
12 let v = match latest(Binary::Player, &channel) {
13 Ok(v) => v,
14 Err(e) => {
15 eprintln!("resolve failed: {e}");
16 std::process::exit(1);
17 }
18 };
19 println!("resolved in {:?}", t.elapsed());
20 println!(" version {}", v.version);
21 println!(" upload {}", v.upload);
22
23 let t = Instant::now();
24 let m = match manifest(&v.upload, &channel) {
25 Ok(m) => m,
26 Err(e) => {
27 eprintln!("manifest failed: {e}");
28 std::process::exit(1);
29 }
30 };
31 let list = m.installable();
32 println!(
33 "manifest in {:?}: {} packages, {} installable, {:.1} MB packed, {:.1} MB unpacked",
34 t.elapsed(),
35 m.packages.len(),
36 list.len(),
37 m.total_packed() as f64 / 1e6,
38 m.total_unpacked() as f64 / 1e6
39 );
40 for p in m.packages.iter() {
41 let dest = nox_roblox::package_dir(&p.name).unwrap_or("<skipped>");
42 println!(" {:<40} {:>10} -> {}", p.name, p.packed, dest);
43 }
44
45 let smallest = list.iter().min_by_key(|p| p.packed).expect("packages");
46 println!("\ndownloading smallest package: {} ({} bytes)", smallest.name, smallest.packed);
47 let dir = std::env::temp_dir().join("nox-livecheck");
48 let _ = std::fs::remove_dir_all(&dir);
49 std::fs::create_dir_all(&dir).unwrap();
50
51 let t = Instant::now();
52 let mut last = 0u64;
53 let mut sink = |e: Event| {
54 if let Event::PackageBytes { done, total } = e {
55 if done - last > 200_000 {
56 last = done;
57 println!(" {done} / {total}");
58 }
59 }
60 true
61 };
62 match install_package(&v.upload, &channel, smallest, &dir, &mut sink) {
63 Ok(files) => {
64 println!("verified md5 and extracted {files} files in {:?}", t.elapsed());
65 let sub = nox_roblox::package_dir(&smallest.name).unwrap();
66 let target = if sub.is_empty() { dir.clone() } else { dir.join(sub.trim_end_matches('/')) };
67 println!("into {}", target.display());
68 let mut shown = 0;
69 let mut stack = vec![target.clone()];
70 while let Some(d) = stack.pop() {
71 let Ok(rd) = std::fs::read_dir(&d) else { continue };
72 for e in rd.flatten() {
73 if e.path().is_dir() {
74 stack.push(e.path());
75 } else if shown < 8 {
76 shown += 1;
77 let rel = e.path().strip_prefix(&target).unwrap().to_path_buf();
78 println!(" {} ({} bytes)", rel.display(), e.metadata().map(|m| m.len()).unwrap_or(0));
79 }
80 }
81 }
82 println!("total on disk: {} bytes", nox_roblox::deploy::directory_size(&dir));
83 }
84 Err(e) => {
85 eprintln!("install failed: {e}");
86 std::process::exit(1);
87 }
88 }
89}