- 1016
// GC only skips blobs younger than GC_GRACE; force the sweep to - 1017
// see everything as eligible rather than sleeping in a test. - 1018
let mut remaining = 0usize; - 1019
let mut referenced = std::collections::HashSet::new(); - 1020
for m in &list { - 1021
for f in &m.files { - 1022
referenced.insert(f.hash.clone()); - 1023
} - 1024
} - 1025
for prefix in std::fs::read_dir(blobs_dir(&home)).unwrap().flatten() { - 1026
for blob in std::fs::read_dir(prefix.path()).unwrap().flatten() { - 1027
remaining += 1; - 1028
let hash = format!( - 1029
"{}{}", - 1030
prefix.file_name().to_string_lossy(), - 1031
blob.file_name().to_string_lossy() - 1032
); - 1033
assert!( - 1034
referenced.contains(&hash) || !GC_GRACE.is_zero(), - 1035
"blob {hash} is unreferenced but within the GC grace period, which is fine" - 1036
); - 1037
} - 1038
} - 1039
assert!(remaining >= 20, "each surviving manifest's blob exists"); - 1040
} - 1041
- 1042
#[test] - 1043
fn incremental_capture_reads_only_changed_files() { - 1044
let dir = tempfile::tempdir().unwrap(); - 1045
// A sibling temp dir, never nested inside `dir` — sessions_home is - 1046
// never inside a real workspace either, and capturing the blob - 1047
// store's own files while walking the workspace would be wrong. - 1048
let home_dir = tempfile::tempdir().unwrap(); - 1049
let home = home_dir.path().to_path_buf(); - 1050
let cwd = dir.path().join("work"); - 1051
std::fs::create_dir_all(&cwd).unwrap(); - 1052
- 1053
const TOTAL: usize = 2_000; - 1054
const CHANGED: usize = 5; - 1055
for i in 0..TOTAL { - 1056
write(&cwd, &format!("file-{i:04}.txt"), "unchanged content"); - 1057
} - 1058
- 1059
let t0 = std::time::Instant::now(); - 1060
let (cp0, stats0) = capture(&cwd, &home, "perf", 0, "first").unwrap(); - 1061
let first_elapsed = t0.elapsed(); - 1062
store(&home, &cp0).unwrap(); - 1063
assert_eq!(cp0.files.len(), TOTAL); - 1064
assert_eq!(stats0.files_read, TOTAL, "first capture reads everything"); - 1065
assert_eq!(stats0.files_reused, 0); - 1066
- 1067
// mtime resolution can be as coarse as one second; sleep past it - 1068
// so the changed files are unambiguously newer. - 1069
std::thread::sleep(std::time::Duration::from_millis(1100)); - 1070
for i in 0..CHANGED { - 1071
write(&cwd, &format!("file-{i:04}.txt"), "this file was edited"); - 1072
} - 1073
- 1074
let t1 = std::time::Instant::now(); - 1075
let (cp1, stats1) = capture(&cwd, &home, "perf", 1, "second").unwrap(); - 1076
let second_elapsed = t1.elapsed(); - 1077
- 1078
assert_eq!(cp1.files.len(), TOTAL); - 1079
assert_eq!(stats1.files_observed, TOTAL); - 1080
assert_eq!( - 1081
stats1.files_read, CHANGED, - 1082
"only the edited files should be re-read" - 1083
); - 1084
assert_eq!(stats1.files_reused, TOTAL - CHANGED); - 1085
- 1086
eprintln!( - 1087
"checkpoint capture timings: first={first_elapsed:?} ({TOTAL} files, all read), \ - 1088
second={second_elapsed:?} ({CHANGED} changed of {TOTAL}, {} reused)", - 1089
stats1.files_reused - 1090
); - 1091
} - 1092
} - 1093
Indexing the workspace…
Vakyartha documentation is discovering safe artifacts, anchors, and source references.