diff options
Diffstat (limited to 'crates/mozart/src/factory.rs')
| -rw-r--r-- | crates/mozart/src/factory.rs | 119 |
1 files changed, 83 insertions, 36 deletions
diff --git a/crates/mozart/src/factory.rs b/crates/mozart/src/factory.rs index b88e088..41f157a 100644 --- a/crates/mozart/src/factory.rs +++ b/crates/mozart/src/factory.rs @@ -14,39 +14,21 @@ use mozart_core::composer::{ AutoloadGenerator, InstallationManager, InstallationSource, LocalPackage, LocalRepository, Locker, PackageReference, RepositoryManager, }; -use mozart_core::config::resolve_references; -use mozart_core::downloader::DownloadManager; +use mozart_core::config::{Config, resolve_references}; +use mozart_core::console::IoInterface; +use mozart_core::downloader::{DownloadManager, GitDownloader, HgDownloader, SvnDownloader}; use mozart_core::factory::create_config; +use mozart_core::package::archiver::ArchiveManager; use mozart_core::package::{RootPackageData, read_from_file}; +use mozart_core::repository::cache::Cache; +use mozart_core::util::Filesystem; +use mozart_core::vcs::process::ProcessExecutor; -/// Rust port of `Factory::createComposer()`. +/// Creates a Composer instance. /// -/// Builds the project-level [`Composer`]: -/// 1. Read `composer.json` from `composer_json` and load it into both -/// the merged [`Config`] (overlaying [`create_config`]) and the -/// untyped [`crate::package::RawPackageData`]. -/// 2. Resolve all `{$home}` / `{$vendor-dir}` placeholders via -/// [`resolve_references`]. -/// 3. Resolve `vendor-dir` against `project_dir` if it is relative, so -/// the installation manager hands back absolute paths -/// (`Factory::createComposer` does the same via -/// `Filesystem::isAbsolutePath`). -/// 4. Wire up the [`InstallationManager`] and a [`RepositoryManager`] -/// whose local repository is populated from -/// `vendor/composer/installed.json` — the same role -/// `Factory::addLocalRepository` plays in PHP. -/// 5. Construct a fresh [`AutoloadGenerator`] with PHP defaults -/// (`new AutoloadGenerator($eventDispatcher, $io)` in PHP, minus the -/// not-yet-ported event dispatcher and IO dependencies). -/// 6. Construct a [`Locker`] pointed at `composer.lock` next to the -/// composer.json — same as `Factory::createComposer`'s -/// `new Locker($io, new JsonFile($lockFile, …), $im, $contents)`, -/// minus the IO/installation-manager/contents dependencies that -/// only matter once we port `setLockData`. -/// -/// The plugin manager, download manager, and event dispatcher that -/// `Factory::createComposer` also wires up are not yet ported. +/// ref: \Composer\Factory\createComposer() pub fn create_composer( + io: std::sync::Arc<std::sync::Mutex<Box<dyn IoInterface>>>, project_dir: std::path::PathBuf, composer_json: &std::path::Path, ) -> anyhow::Result<Composer> { @@ -78,7 +60,9 @@ pub fn create_composer( let repository_manager = RepositoryManager::new(LocalRepository::with_dev_mode(local_packages, dev_mode)); let installation_manager = InstallationManager::new(vendor_dir.clone()); - let download_manager = DownloadManager::new(vendor_dir.join(".cache").join("git")); + let dm = std::sync::Arc::new(tokio::sync::Mutex::new(create_download_manager( + io, &config, + ))); let autoload_generator = AutoloadGenerator::new(); // Mirrors `Factory::createComposer`'s lock-file path: the lockfile @@ -96,6 +80,7 @@ pub fn create_composer( .unwrap_or_else(|| "composer.lock".to_string()), ); let locker = Locker::new(lock_file_path); + let am = std::sync::Arc::new(tokio::sync::Mutex::new(create_archive_manager(dm.clone()))); Ok(Composer::new( project_dir, @@ -103,12 +88,66 @@ pub fn create_composer( package, repository_manager, installation_manager, - download_manager, + dm, autoload_generator, locker, + am, )) } +pub fn create_download_manager( + io: std::sync::Arc<std::sync::Mutex<Box<dyn IoInterface>>>, + config: &Config, +) -> DownloadManager { + let cache = if config.cache_files_ttl > 0 { + Some(Cache::new( + std::path::PathBuf::from(config.cache_files_dir.clone()), + config.cache_read_only, + )) + } else { + None + }; + let cache = cache.unwrap(); + + let mut dm = DownloadManager::new(io, false, Filesystem::new(), cache); + if let serde_json::Value::String(preferred) = &config.preferred_install { + match preferred.as_str() { + "dist" => dm.set_prefer_dist(true), + "source" => dm.set_prefer_source(true), + _ => (), + } + } + + if let serde_json::Value::Object(preferred) = &config.preferred_install { + _ = preferred; + unimplemented!() + } + + dm.set_downloader( + "git".to_owned(), + Box::new(GitDownloader::new( + ProcessExecutor::new(), + std::path::PathBuf::from(config.cache_files_dir.clone()), + )), + ); + dm.set_downloader( + "svn".to_owned(), + Box::new(SvnDownloader::new(ProcessExecutor::new())), + ); + dm.set_downloader( + "hg".to_owned(), + Box::new(HgDownloader::new(ProcessExecutor::new())), + ); + + dm +} + +pub fn create_archive_manager( + download_manager: std::sync::Arc<tokio::sync::Mutex<DownloadManager>>, +) -> ArchiveManager { + ArchiveManager::new(download_manager) +} + /// Read `vendor/composer/installed.json` into the minimal shape the /// installation manager needs. Mirrors the relevant slice of /// `Composer\Repository\FilesystemRepository::initialize`: accept both @@ -215,8 +254,10 @@ fn read_package_reference(value: Option<&serde_json::Value>) -> Option<PackageRe #[cfg(test)] mod tests { use super::*; + use mozart_core::console::Console; use std::fs; use std::path::Path; + use std::sync::{Arc, Mutex}; use tempfile::tempdir; fn write(path: &Path, content: &str) { @@ -224,6 +265,12 @@ mod tests { fs::write(path, content).unwrap(); } + fn io() -> Arc<Mutex<Box<dyn IoInterface>>> { + Arc::new(Mutex::new( + Box::new(Console::new(0, true, false, true, true)) as Box<dyn IoInterface>, + )) + } + #[test] fn install_path_is_vendor_dir_plus_pretty_name() { let dir = tempdir().unwrap(); @@ -233,7 +280,7 @@ mod tests { r#"{"packages": [{"name": "Vendor/Pkg", "version": "1.0.0"}]}"#, ); - let composer = Composer::require(dir.path()).unwrap(); + let composer = Composer::require(io(), dir.path()).unwrap(); let pkg = composer .repository_manager() .local_repository() @@ -261,7 +308,7 @@ mod tests { r#"{"packages": [{"name": "vendor/pkg", "target-dir": "src/lib"}]}"#, ); - let composer = Composer::require(dir.path()).unwrap(); + let composer = Composer::require(io(), dir.path()).unwrap(); let pkg = composer .repository_manager() .local_repository() @@ -282,7 +329,7 @@ mod tests { let dir = tempdir().unwrap(); write(&dir.path().join("composer.json"), r#"{"name": "acme/app"}"#); - let composer = Composer::require(dir.path()).unwrap(); + let composer = Composer::require(io(), dir.path()).unwrap(); let count = composer .repository_manager() .local_repository() @@ -303,7 +350,7 @@ mod tests { r#"[{"name": "a/a"}, {"name": "b/b"}]"#, ); - let composer = Composer::require(dir.path()).unwrap(); + let composer = Composer::require(io(), dir.path()).unwrap(); let names: Vec<&str> = composer .repository_manager() .local_repository() @@ -322,7 +369,7 @@ mod tests { ); use mozart_core::package::Package; - let composer = Composer::require(dir.path()).unwrap(); + let composer = Composer::require(io(), dir.path()).unwrap(); assert_eq!(composer.package().name(), "acme/app"); assert_eq!( composer @@ -346,7 +393,7 @@ mod tests { r#"{"packages": [{"name": "vendor/pkg"}]}"#, ); - let composer = Composer::require(dir.path()).unwrap(); + let composer = Composer::require(io(), dir.path()).unwrap(); let pkg = composer .repository_manager() .local_repository() |
