use super::{BloatDir, EnforcePolicy, PackageManager, dir_size, enforce_two_tier, run_command};
use anyhow::Result;
use std::path::Path;
pub struct Yarn;
impl PackageManager for Yarn {
fn name(&self) -> &'static str {
"yarn"
}
fn detect(&self, project_dir: &Path) -> bool {
project_dir.join("yarn.lock").exists()
}
fn bloat_dirs(&self, project_dir: &Path) -> Vec<BloatDir> {
let node_modules = project_dir.join("node_modules");
if node_modules.exists() {
let size = dir_size(&node_modules);
vec![BloatDir {
name: "node_modules".to_string(),
path: node_modules,
size_bytes: size,
}]
} else {
vec![]
}
}
fn enforce_lockfile(&self, project_dir: &Path, policy: EnforcePolicy) -> Result<()> {
let lockfile = project_dir.join("yarn.lock");
let berry = enforce_two_tier(
&lockfile,
"yarn",
&["install", "--immutable", "--mode", "update-lockfile"],
&["install", "--mode", "update-lockfile"],
project_dir,
policy,
);
if berry.is_err() && !lockfile.exists() {
anyhow::bail!(
"`yarn install --mode update-lockfile` failed and there is no \
`yarn.lock` to fall back on. Cannot prove `node_modules` is \
rebuildable — run `yarn install` and commit the lockfile first."
);
}
Ok(())
}
fn restore(&self, project_dir: &Path) -> Result<()> {
run_command("yarn", &["install", "--immutable"], project_dir)
}
fn lockfiles(&self) -> &'static [&'static str] {
&["yarn.lock"]
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
use tempfile::tempdir;
#[test]
fn test_name() {
assert_eq!(Yarn.name(), "yarn");
}
#[test]
fn test_detect_positive() {
let dir = tempdir().unwrap();
fs::File::create(dir.path().join("yarn.lock")).unwrap();
assert!(Yarn.detect(dir.path()));
}
#[test]
fn test_detect_negative() {
let dir = tempdir().unwrap();
assert!(!Yarn.detect(dir.path()));
}
#[test]
fn test_bloat_dirs_present() {
let dir = tempdir().unwrap();
fs::create_dir(dir.path().join("node_modules")).unwrap();
let bloat = Yarn.bloat_dirs(dir.path());
assert_eq!(bloat.len(), 1);
assert_eq!(bloat[0].path, dir.path().join("node_modules"));
}
#[test]
fn test_bloat_dirs_absent() {
let dir = tempdir().unwrap();
let bloat = Yarn.bloat_dirs(dir.path());
assert!(bloat.is_empty());
}
}