dev_prune/adapters/
bun.rs1use super::{
7 BloatDir, EnforcePolicy, PackageManager, dir_size_with_hardlinks,
8 lock_sync_or_verify_with_timeout, run_command_with_timeout,
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> {
35 let node_modules = project_dir.join("node_modules");
36 if node_modules.exists() {
37 let size = dir_size_with_hardlinks(&node_modules);
38 vec![BloatDir {
39 name: "node_modules".to_string(),
40 path: node_modules,
41 size_bytes: size.freed_bytes,
42 shared_bytes: size.shared_bytes,
43 }]
44 } else {
45 vec![]
46 }
47 }
48
49 fn enforce_lockfile(&self, project_dir: &Path, policy: EnforcePolicy) -> Result<()> {
60 let lockfile = if project_dir.join("bun.lockb").exists() {
61 project_dir.join("bun.lockb")
62 } else {
63 project_dir.join("bun.lock")
64 };
65 lock_sync_or_verify_with_timeout(
66 &lockfile,
67 "bun",
68 &[
69 "install",
70 "--frozen-lockfile",
71 "--dry-run",
72 "--ignore-scripts",
73 ],
74 project_dir,
75 policy.timeout,
76 )
77 }
78
79 fn restore(&self, project_dir: &Path, timeout: std::time::Duration) -> Result<()> {
81 run_command_with_timeout(
82 "bun",
83 &["install", "--frozen-lockfile"],
84 project_dir,
85 timeout,
86 )
87 }
88
89 fn lockfiles(&self) -> &'static [&'static str] {
90 &["bun.lockb", "bun.lock"]
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97 use std::fs;
98 use tempfile::tempdir;
99
100 #[test]
101 fn test_name() {
102 assert_eq!(Bun.name(), "bun");
103 }
104
105 #[test]
106 fn test_detect_positive_lockb() {
107 let dir = tempdir().unwrap();
108 fs::File::create(dir.path().join("bun.lockb")).unwrap();
109 assert!(Bun.detect(dir.path()));
110 }
111
112 #[test]
113 fn test_detect_positive_lock() {
114 let dir = tempdir().unwrap();
115 fs::File::create(dir.path().join("bun.lock")).unwrap();
116 assert!(Bun.detect(dir.path()));
117 }
118
119 #[test]
120 fn test_detect_negative() {
121 let dir = tempdir().unwrap();
122 assert!(!Bun.detect(dir.path()));
123 }
124
125 #[test]
126 fn test_bloat_dirs_present() {
127 let dir = tempdir().unwrap();
128 fs::create_dir(dir.path().join("node_modules")).unwrap();
129 let bloat = Bun.bloat_dirs(dir.path());
130 assert_eq!(bloat.len(), 1);
131 assert_eq!(bloat[0].path, dir.path().join("node_modules"));
132 }
133
134 #[test]
135 fn test_bloat_dirs_absent() {
136 let dir = tempdir().unwrap();
137 let bloat = Bun.bloat_dirs(dir.path());
138 assert!(bloat.is_empty());
139 }
140}