aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/mozart-core/src/repository
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-10 20:31:00 +0900
committernsfisis <nsfisis@gmail.com>2026-05-10 20:31:00 +0900
commit59bab6efee41a196b0d9d392167c536abbe068ba (patch)
treef36ca1c8534cf703b357d3f9090ba85efd9a9b74 /crates/mozart-core/src/repository
parent24bb31c109332ae982b7091ffcd5183442ce6f6f (diff)
downloadphp-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.rs143
-rw-r--r--crates/mozart-core/src/repository/installer_executor/filesystem.rs18
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)?;
}
_ => {