use crate::task_shadowing::check_path_executable;
use crate::types::TaskRunner;
use std::path::Path;
pub fn detect_package_manager(dir: &Path) -> Option<TaskRunner> {
if dir.join("package-lock.json").exists() {
return Some(TaskRunner::NodeNpm);
}
if dir.join("yarn.lock").exists() {
return Some(TaskRunner::NodeYarn);
}
if dir.join("pnpm-lock.yaml").exists() {
return Some(TaskRunner::NodePnpm);
}
if dir.join("bun.lockb").exists() {
return Some(TaskRunner::NodeBun);
}
#[cfg(not(test))]
{
let has_bun = check_path_executable("bun").is_some();
let has_npm = check_path_executable("npm").is_some();
let has_yarn = check_path_executable("yarn").is_some();
let has_pnpm = check_path_executable("pnpm").is_some();
if has_bun {
return Some(TaskRunner::NodeBun);
} else if has_pnpm {
return Some(TaskRunner::NodePnpm);
} else if has_yarn {
return Some(TaskRunner::NodeYarn);
} else if has_npm {
return Some(TaskRunner::NodeNpm);
}
}
#[cfg(test)]
{
let has_bun = check_path_executable("bun").is_some();
let has_pnpm = check_path_executable("pnpm").is_some();
let has_yarn = check_path_executable("yarn").is_some();
let has_npm = check_path_executable("npm").is_some();
if has_bun {
return Some(TaskRunner::NodeBun);
} else if has_pnpm {
return Some(TaskRunner::NodePnpm);
} else if has_yarn {
return Some(TaskRunner::NodeYarn);
} else if has_npm {
return Some(TaskRunner::NodeNpm);
}
}
None
}
#[cfg(test)]
mod tests {
use super::*;
use crate::environment::{reset_to_real_environment, set_test_environment, TestEnvironment};
use crate::task_shadowing::{enable_mock, mock_executable, reset_mock};
use serial_test::serial;
use std::fs::File;
use tempfile::TempDir;
fn create_lock_file(dir: &Path, filename: &str) {
File::create(dir.join(filename)).unwrap();
}
#[test]
#[serial]
fn test_detect_package_manager_with_lock_files() {
let temp_dir = TempDir::new().unwrap();
fn remove_all_lock_files(dir: &std::path::Path) {
let _ = std::fs::remove_file(dir.join("package-lock.json"));
let _ = std::fs::remove_file(dir.join("yarn.lock"));
let _ = std::fs::remove_file(dir.join("pnpm-lock.yaml"));
let _ = std::fs::remove_file(dir.join("bun.lockb"));
}
reset_mock();
enable_mock();
remove_all_lock_files(temp_dir.path());
create_lock_file(temp_dir.path(), "package-lock.json");
mock_executable("npm");
assert_eq!(
detect_package_manager(temp_dir.path()),
Some(TaskRunner::NodeNpm)
);
remove_all_lock_files(temp_dir.path());
create_lock_file(temp_dir.path(), "yarn.lock");
mock_executable("yarn");
assert_eq!(
detect_package_manager(temp_dir.path()),
Some(TaskRunner::NodeYarn)
);
remove_all_lock_files(temp_dir.path());
create_lock_file(temp_dir.path(), "pnpm-lock.yaml");
mock_executable("pnpm");
assert_eq!(
detect_package_manager(temp_dir.path()),
Some(TaskRunner::NodePnpm)
);
remove_all_lock_files(temp_dir.path());
create_lock_file(temp_dir.path(), "bun.lockb");
mock_executable("bun");
assert_eq!(
detect_package_manager(temp_dir.path()),
Some(TaskRunner::NodeBun)
);
reset_mock();
}
#[test]
#[serial]
fn test_detect_package_manager_no_lock_files() {
let temp_dir = TempDir::new().unwrap();
let env = TestEnvironment::new().with_executable("bun");
set_test_environment(env);
assert_eq!(
detect_package_manager(temp_dir.path()),
Some(TaskRunner::NodeBun)
);
reset_to_real_environment();
let env = TestEnvironment::new().with_executable("npm");
set_test_environment(env);
assert_eq!(
detect_package_manager(temp_dir.path()),
Some(TaskRunner::NodeNpm)
);
reset_to_real_environment();
let env = TestEnvironment::new()
.with_executable("bun")
.with_executable("npm");
set_test_environment(env);
assert_eq!(
detect_package_manager(temp_dir.path()),
Some(TaskRunner::NodeBun)
);
reset_to_real_environment();
let env = TestEnvironment::new();
set_test_environment(env);
assert_eq!(detect_package_manager(temp_dir.path()), None);
reset_to_real_environment();
}
#[test]
#[serial]
fn test_detect_package_manager_multiple_available() {
let temp_dir = TempDir::new().unwrap();
reset_mock();
enable_mock();
let env = TestEnvironment::new()
.with_executable("npm")
.with_executable("bun")
.with_executable("pnpm")
.with_executable("yarn");
set_test_environment(env);
assert_eq!(
detect_package_manager(temp_dir.path()),
Some(TaskRunner::NodeBun)
);
create_lock_file(temp_dir.path(), "package-lock.json");
assert_eq!(
detect_package_manager(temp_dir.path()),
Some(TaskRunner::NodeNpm)
);
reset_mock();
reset_to_real_environment();
}
}