diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-05-10 20:31:00 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-05-10 20:31:00 +0900 |
| commit | 59bab6efee41a196b0d9d392167c536abbe068ba (patch) | |
| tree | f36ca1c8534cf703b357d3f9090ba85efd9a9b74 /crates/mozart-core/src/repository | |
| parent | 24bb31c109332ae982b7091ffcd5183442ce6f6f (diff) | |
| download | php-mozart-59bab6efee41a196b0d9d392167c536abbe068ba.tar.gz php-mozart-59bab6efee41a196b0d9d392167c536abbe068ba.tar.zst php-mozart-59bab6efee41a196b0d9d392167c536abbe068ba.zip | |
refactor(downloader): introduce top-level downloader module
Move VCS downloaders and DownloadManager out of vcs/repository into a
new top-level downloader module mirroring Composer\Downloader, and add
stub types for the remaining Composer downloader hierarchy (file,
archive variants, path, perforce, fossil, exceptions, interfaces) so
future ports have a home.
Diffstat (limited to 'crates/mozart-core/src/repository')
| -rw-r--r-- | crates/mozart-core/src/repository/download_manager.rs | 143 | ||||
| -rw-r--r-- | crates/mozart-core/src/repository/installer_executor/filesystem.rs | 18 |
2 files changed, 9 insertions, 152 deletions
diff --git a/crates/mozart-core/src/repository/download_manager.rs b/crates/mozart-core/src/repository/download_manager.rs deleted file mode 100644 index d422899..0000000 --- a/crates/mozart-core/src/repository/download_manager.rs +++ /dev/null @@ -1,143 +0,0 @@ -//! `DownloadManager` — pick the right [`VcsDownloader`] for a given -//! [`LocalPackage`]. Mirrors `Composer\Downloader\DownloadManager`. - -use std::path::PathBuf; - -use crate::composer::{InstallationSource, LocalPackage}; -use crate::vcs::downloader::VcsDownloader; -use crate::vcs::downloader::git::GitDownloader; -use crate::vcs::downloader::hg::HgDownloader; -use crate::vcs::downloader::svn::SvnDownloader; -use crate::vcs::process::ProcessExecutor; -use crate::vcs::util::git::GitUtil; -use crate::vcs::util::hg::HgUtil; -use crate::vcs::util::svn::SvnUtil; - -/// Selects a `VcsDownloader` for a package based on its installation source -/// and source type. Mirrors `DownloadManager::getDownloaderForPackage`: -/// -/// - `metapackage` → `None`. -/// - `installation-source: dist` → `None` (Composer would return a -/// `FileDownloader`-family object that does not implement -/// `ChangeReportInterface` / `DvcsDownloaderInterface`, so the status -/// command's `instanceof` checks all become no-ops; returning `None` -/// directly is the equivalent in our trait-object world). -/// - `installation-source: source` → the matching VCS downloader by -/// `source.type` (`git` / `hg` / `svn`). -pub struct DownloadManager { - git_cache_dir: PathBuf, -} - -impl DownloadManager { - /// `git_cache_dir`: where `GitUtil` should keep mirror clones (e.g. - /// `<vendor>/.cache/git`). - pub fn new(git_cache_dir: PathBuf) -> Self { - Self { git_cache_dir } - } - - pub fn get_downloader_for_package( - &self, - package: &LocalPackage, - ) -> Option<Box<dyn VcsDownloader>> { - if package.package_type() == Some("metapackage") { - return None; - } - match package.installation_source()? { - InstallationSource::Dist => None, - InstallationSource::Source => { - let kind = package.source()?.kind.as_str(); - match kind { - "git" => { - let git_util = - GitUtil::new(ProcessExecutor::new(), self.git_cache_dir.clone()); - Some(Box::new(GitDownloader::new(git_util))) - } - "hg" => { - let hg_util = HgUtil::new(ProcessExecutor::new()); - Some(Box::new(HgDownloader::new(hg_util))) - } - "svn" => { - let svn_util = SvnUtil::new(ProcessExecutor::new()); - Some(Box::new(SvnDownloader::new(svn_util))) - } - _ => None, - } - } - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::composer::PackageReference; - use serde_json::Value; - - fn pkg( - installation_source: Option<InstallationSource>, - source_kind: Option<&str>, - ) -> LocalPackage { - let source = source_kind.map(|kind| PackageReference { - kind: kind.to_string(), - url: "https://example/repo".into(), - reference: Some("abc123".into()), - shasum: None, - }); - LocalPackage::new( - "vendor/pkg".into(), - "1.0.0".into(), - None, - Some("library".into()), - installation_source, - source, - None, - Value::Null, - ) - } - - #[test] - fn metapackage_returns_none() { - let dm = DownloadManager::new(PathBuf::from("/tmp/mz-test-cache")); - let mut p = pkg(Some(InstallationSource::Source), Some("git")); - // override type - p = LocalPackage::new( - "vendor/pkg".into(), - "1.0.0".into(), - None, - Some("metapackage".into()), - p.installation_source(), - p.source().cloned(), - None, - Value::Null, - ); - assert!(dm.get_downloader_for_package(&p).is_none()); - } - - #[test] - fn dist_install_returns_none() { - let dm = DownloadManager::new(PathBuf::from("/tmp/mz-test-cache")); - let p = pkg(Some(InstallationSource::Dist), Some("git")); - assert!(dm.get_downloader_for_package(&p).is_none()); - } - - #[test] - fn source_install_with_git_returns_some() { - let dm = DownloadManager::new(PathBuf::from("/tmp/mz-test-cache")); - let p = pkg(Some(InstallationSource::Source), Some("git")); - assert!(dm.get_downloader_for_package(&p).is_some()); - } - - #[test] - fn unknown_source_kind_returns_none() { - let dm = DownloadManager::new(PathBuf::from("/tmp/mz-test-cache")); - let p = pkg(Some(InstallationSource::Source), Some("perforce")); - assert!(dm.get_downloader_for_package(&p).is_none()); - } - - #[test] - fn missing_installation_source_returns_none() { - let dm = DownloadManager::new(PathBuf::from("/tmp/mz-test-cache")); - let p = pkg(None, Some("git")); - assert!(dm.get_downloader_for_package(&p).is_none()); - } -} diff --git a/crates/mozart-core/src/repository/installer_executor/filesystem.rs b/crates/mozart-core/src/repository/installer_executor/filesystem.rs index 3f982e3..2b34e02 100644 --- a/crates/mozart-core/src/repository/installer_executor/filesystem.rs +++ b/crates/mozart-core/src/repository/installer_executor/filesystem.rs @@ -5,9 +5,10 @@ //! [`crate::vcs`], and removes vendor directories. Test code substitutes a //! recording-only executor instead (added in a later step). -use super::super::cache::Cache; -use super::super::downloader; -use super::{ExecuteContext, InstallerExecutor, PackageOperation}; +use crate::downloader::{GitDownloader, HgDownloader, SvnDownloader}; +use crate::repository::cache::Cache; +use crate::repository::downloader; +use crate::repository::installer_executor::{ExecuteContext, InstallerExecutor, PackageOperation}; use std::path::Path; pub struct FilesystemExecutor { @@ -135,6 +136,8 @@ fn install_from_source( vendor_dir: &Path, package_name: &str, ) -> anyhow::Result<()> { + use crate::downloader::VcsDownloader as _; + let target = vendor_dir.join(package_name); if target.exists() { std::fs::remove_dir_all(&target)?; @@ -145,23 +148,20 @@ fn install_from_source( let process = crate::vcs::process::ProcessExecutor::new(); let git_util = crate::vcs::util::git::GitUtil::new(process, vendor_dir.join(".cache").join("git")); - let downloader = crate::vcs::downloader::git::GitDownloader::new(git_util); - use crate::vcs::downloader::VcsDownloader as _; + let downloader = GitDownloader::new(git_util); downloader.download(url, reference, &target)?; downloader.install(url, reference, &target)?; } "svn" => { let process = crate::vcs::process::ProcessExecutor::new(); let svn_util = crate::vcs::util::svn::SvnUtil::new(process); - let downloader = crate::vcs::downloader::svn::SvnDownloader::new(svn_util); - use crate::vcs::downloader::VcsDownloader as _; + let downloader = SvnDownloader::new(svn_util); downloader.install(url, reference, &target)?; } "hg" => { let process = crate::vcs::process::ProcessExecutor::new(); let hg_util = crate::vcs::util::hg::HgUtil::new(process); - let downloader = crate::vcs::downloader::hg::HgDownloader::new(hg_util); - use crate::vcs::downloader::VcsDownloader as _; + let downloader = HgDownloader::new(hg_util); downloader.install(url, reference, &target)?; } _ => { |
