dev_prune/adapters/
composer.rs1use super::{
11 BloatDir, EnforcePolicy, PackageManager, dir_size, enforce_two_tier, run_command_with_timeout,
12};
13use anyhow::Result;
14use std::path::Path;
15
16pub struct Composer;
18
19impl PackageManager for Composer {
20 fn name(&self) -> &'static str {
21 "composer"
22 }
23
24 fn detect(&self, path: &Path) -> bool {
28 path.join("composer.json").exists()
29 }
30
31 fn bloat_dirs(&self, path: &Path) -> Vec<BloatDir> {
39 let vendor = path.join("vendor");
40 if !vendor.is_dir() || vendor.join("bundle").is_dir() {
41 return Vec::new();
42 }
43 vec![BloatDir {
44 name: "vendor".to_string(),
45 path: vendor.clone(),
46 size_bytes: dir_size(&vendor),
47 shared_bytes: 0,
48 }]
49 }
50
51 fn enforce_lockfile(&self, path: &Path, policy: EnforcePolicy) -> Result<()> {
61 enforce_two_tier(
62 &path.join("composer.lock"),
63 "composer",
64 &[
65 "validate",
66 "--no-check-publish",
67 "--no-check-all",
68 "--no-interaction",
69 ],
70 &["update", "--no-install", "--no-interaction"],
71 path,
72 policy,
73 )
74 }
75
76 fn restore(&self, path: &Path, timeout: std::time::Duration) -> Result<()> {
77 run_command_with_timeout("composer", &["install", "--no-interaction"], path, timeout)
78 }
79
80 fn lockfiles(&self) -> &'static [&'static str] {
81 &["composer.lock"]
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88 use std::fs;
89 use tempfile::tempdir;
90
91 #[test]
92 fn detects_on_the_manifest() {
93 let dir = tempdir().unwrap();
94 assert!(!Composer.detect(dir.path()));
95 fs::write(dir.path().join("composer.json"), "{}").unwrap();
96 assert!(Composer.detect(dir.path()));
97 }
98
99 #[test]
100 fn claims_vendor_when_present() {
101 let dir = tempdir().unwrap();
102 assert!(Composer.bloat_dirs(dir.path()).is_empty());
103 fs::create_dir(dir.path().join("vendor")).unwrap();
104 let dirs = Composer.bloat_dirs(dir.path());
105 assert_eq!(dirs.len(), 1);
106 assert_eq!(dirs[0].name, "vendor");
107 }
108
109 #[test]
110 fn declines_a_vendor_directory_bundler_is_living_in() {
111 let dir = tempdir().unwrap();
112 fs::create_dir_all(dir.path().join("vendor").join("bundle")).unwrap();
113 assert!(Composer.bloat_dirs(dir.path()).is_empty());
114 }
115}