dev_prune/adapters/
bun.rs1use super::{
7 BloatDir, EnforcePolicy, PackageManager, dir_size, lock_sync_or_verify_with_timeout,
8 run_command,
9};
10use anyhow::Result;
11use std::path::Path;
12
13pub struct Bun;
15
16impl PackageManager for Bun {
17 fn name(&self) -> &'static str {
19 "bun"
20 }
21
22 fn detect(&self, project_dir: &Path) -> bool {
24 project_dir.join("bun.lockb").exists() || project_dir.join("bun.lock").exists()
25 }
26
27 fn bloat_dirs(&self, project_dir: &Path) -> Vec<BloatDir> {
29 let node_modules = project_dir.join("node_modules");
30 if node_modules.exists() {
31 let size = dir_size(&node_modules);
32 vec![BloatDir {
33 name: "node_modules".to_string(),
34 path: node_modules,
35 size_bytes: size,
36 }]
37 } else {
38 vec![]
39 }
40 }
41
42 fn enforce_lockfile(&self, project_dir: &Path, policy: EnforcePolicy) -> Result<()> {
53 let lockfile = if project_dir.join("bun.lockb").exists() {
54 project_dir.join("bun.lockb")
55 } else {
56 project_dir.join("bun.lock")
57 };
58 lock_sync_or_verify_with_timeout(
59 &lockfile,
60 "bun",
61 &[
62 "install",
63 "--frozen-lockfile",
64 "--dry-run",
65 "--ignore-scripts",
66 ],
67 project_dir,
68 policy.timeout,
69 )
70 }
71
72 fn restore(&self, project_dir: &Path) -> Result<()> {
74 run_command("bun", &["install", "--frozen-lockfile"], project_dir)
75 }
76
77 fn lockfiles(&self) -> &'static [&'static str] {
78 &["bun.lockb", "bun.lock"]
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85 use std::fs;
86 use tempfile::tempdir;
87
88 #[test]
89 fn test_name() {
90 assert_eq!(Bun.name(), "bun");
91 }
92
93 #[test]
94 fn test_detect_positive_lockb() {
95 let dir = tempdir().unwrap();
96 fs::File::create(dir.path().join("bun.lockb")).unwrap();
97 assert!(Bun.detect(dir.path()));
98 }
99
100 #[test]
101 fn test_detect_positive_lock() {
102 let dir = tempdir().unwrap();
103 fs::File::create(dir.path().join("bun.lock")).unwrap();
104 assert!(Bun.detect(dir.path()));
105 }
106
107 #[test]
108 fn test_detect_negative() {
109 let dir = tempdir().unwrap();
110 assert!(!Bun.detect(dir.path()));
111 }
112
113 #[test]
114 fn test_bloat_dirs_present() {
115 let dir = tempdir().unwrap();
116 fs::create_dir(dir.path().join("node_modules")).unwrap();
117 let bloat = Bun.bloat_dirs(dir.path());
118 assert_eq!(bloat.len(), 1);
119 assert_eq!(bloat[0].path, dir.path().join("node_modules"));
120 }
121
122 #[test]
123 fn test_bloat_dirs_absent() {
124 let dir = tempdir().unwrap();
125 let bloat = Bun.bloat_dirs(dir.path());
126 assert!(bloat.is_empty());
127 }
128}