返回 CodeWhale
prune.rs
根目录 / crates / tui / src / snapshot / prune.rs
1 //! Boot-time snapshot pruning.
2 //!
3 //! Called from `session_manager` once per session start. Failure is
4 //! never fatal — old snapshots taking disk space is annoying but not
5 //! correctness-breaking, so we log and move on.
6
7 use std::io;
8 use std::path::Path;
9 use std::time::Duration;
10
11 use super::paths::snapshot_git_dir;
12 use super::repo::SnapshotRepo;
13
14 /// Default snapshot retention window: 7 days.
15 pub const DEFAULT_MAX_AGE: Duration = Duration::from_secs(7 * 24 * 60 * 60);
16
17 /// Prune snapshots older than `max_age` for the given workspace.
18 ///
19 /// If no snapshot repo exists yet (first run) this is a cheap no-op.
20 /// Returns the number of snapshots removed.
21 pub fn prune_older_than(workspace: &Path, max_age: Duration) -> io::Result<usize> {
22 let git_dir = snapshot_git_dir(workspace)?;
23 if !git_dir.exists() {
24 return Ok(0);
25 }
26 let repo = SnapshotRepo::open_or_init(workspace)?;
27 let removed = repo.prune_older_than(max_age)?;
28 // `git prune --expire=now` walks the whole object store — seconds on a
29 // large snapshot repo. Nothing removed means nothing newly unreachable,
30 // so skip the walk entirely on the common boot path (#3757).
31 if removed > 0 {
32 repo.prune_unreachable_objects()?;
33 }
34 Ok(removed)
35 }
36
37 #[cfg(test)]
38 mod tests {
39 use super::*;
40 use crate::test_support::{EnvVarGuard, lock_test_env};
41 use tempfile::tempdir;
42
43 #[test]
44 fn prune_no_repo_returns_zero() {
45 let tmp = tempdir().unwrap();
46 let _lock = lock_test_env();
47 let _profile = EnvVarGuard::set("CODEWHALE_HOME", tmp.path().join("profile"));
48 let removed = prune_older_than(tmp.path(), DEFAULT_MAX_AGE).unwrap();
49 assert_eq!(removed, 0);
50 }
51
52 #[test]
53 fn prune_with_existing_repo_zero_age_clears_all() {
54 let tmp = tempdir().unwrap();
55 let _lock = lock_test_env();
56 let _profile = EnvVarGuard::set("CODEWHALE_HOME", tmp.path().join("profile"));
57 let workspace = tmp.path().join("ws");
58 std::fs::create_dir_all(&workspace).unwrap();
59 let repo = SnapshotRepo::open_or_init(&workspace).unwrap();
60 std::fs::write(workspace.join("f.txt"), "x").unwrap();
61 repo.snapshot("turn:0").unwrap();
62
63 // Same-second flake guard: see `repo::tests`.
64 std::thread::sleep(Duration::from_millis(1100));
65
66 let removed = prune_older_than(&workspace, Duration::from_secs(0)).unwrap();
67 assert!(removed >= 1);
68 }
69 }
70
70 lines RUST