diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-05-10 00:32:08 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-05-10 00:32:08 +0900 |
| commit | 8cc1ba8a02c0318b65658f1634de378c780392b9 (patch) | |
| tree | fdd5cb61e488018891a486b25991b87c84220bb8 /crates/mozart-vcs/src/repository.rs | |
| parent | 72b2e877c01e67ba7edd37e34ac2eadb7a1c62c4 (diff) | |
| download | php-mozart-8cc1ba8a02c0318b65658f1634de378c780392b9.tar.gz php-mozart-8cc1ba8a02c0318b65658f1634de378c780392b9.tar.zst php-mozart-8cc1ba8a02c0318b65658f1634de378c780392b9.zip | |
refactor(workspace): consolidate crates into mozart-core
Merged mozart-archiver, mozart-autoload, mozart-registry,
mozart-sat-resolver, and mozart-vcs into mozart-core to align
the source layout with Composer's structure.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'crates/mozart-vcs/src/repository.rs')
| -rw-r--r-- | crates/mozart-vcs/src/repository.rs | 206 |
1 files changed, 0 insertions, 206 deletions
diff --git a/crates/mozart-vcs/src/repository.rs b/crates/mozart-vcs/src/repository.rs deleted file mode 100644 index b941eec..0000000 --- a/crates/mozart-vcs/src/repository.rs +++ /dev/null @@ -1,206 +0,0 @@ -use anyhow::{Result, bail}; - -use crate::driver::{ - DistReference, DriverConfig, DriverType, SourceReference, create_driver, detect_driver, -}; - -/// A single package version discovered from a VCS repository. -#[derive(Debug, Clone)] -pub struct VcsPackageVersion { - /// Package name (from composer.json). - pub name: String, - /// Version string (e.g., "1.2.3" for tags, "dev-main" for branches). - pub version: String, - /// Normalized version for comparison. - pub version_normalized: String, - /// Full composer.json data as JSON. - pub composer_json: serde_json::Value, - /// Source reference (VCS checkout info). - pub source: SourceReference, - /// Dist reference (archive download, if available). - pub dist: Option<DistReference>, - /// Whether this is the default branch version. - pub is_default_branch: bool, - /// Release date (ISO 8601). - pub time: Option<String>, -} - -/// Repository that scans a VCS URL for package versions. -/// -/// Corresponds to Composer's `Repository\VcsRepository`. -pub struct VcsRepository { - url: String, - driver_type: Option<DriverType>, - config: DriverConfig, -} - -impl VcsRepository { - pub fn new(url: String, repo_type: Option<&str>, config: DriverConfig) -> Self { - let driver_type = detect_driver(&url, repo_type, &config); - Self { - url, - driver_type, - config, - } - } - - /// Scan the VCS repository for all package versions. - /// - /// 1. Detects the driver type and initializes it - /// 2. Reads composer.json from the root to get the package name - /// 3. Scans tags → version releases - /// 4. Scans branches → dev versions - pub async fn scan(&self) -> Result<Vec<VcsPackageVersion>> { - let driver_type = self - .driver_type - .ok_or_else(|| anyhow::anyhow!("No suitable VCS driver found for URL: {}", self.url))?; - - let mut driver = create_driver(&self.url, driver_type, self.config.clone()); - driver.initialize().await?; - - // Get package name from root composer.json - let root_id = driver.root_identifier().to_string(); - let root_info = driver.composer_information(&root_id).await?; - let package_name = match &root_info { - Some(info) => info["name"] - .as_str() - .ok_or_else(|| { - anyhow::anyhow!( - "composer.json at root of {} does not contain a 'name' field", - self.url, - ) - })? - .to_string(), - None => bail!( - "No composer.json found at root of {} (ref: {})", - self.url, - root_id, - ), - }; - - let mut versions = Vec::new(); - - // Scan tags - let tags = driver.tags().await?.clone(); - for (tag_name, tag_hash) in &tags { - if let Some(version) = self.tag_to_version(tag_name) { - match driver.composer_information(tag_hash).await { - Ok(Some(info)) => { - let time = driver.change_date(tag_hash).await.unwrap_or(None); - let source = driver.source(tag_hash); - let dist = driver.dist(tag_hash).await.unwrap_or(None); - - // Ensure name matches root package - if info["name"].as_str() != Some(&package_name) { - continue; - } - - let normalized = self.normalize_version(&version); - - versions.push(VcsPackageVersion { - name: package_name.clone(), - version: version.clone(), - version_normalized: normalized, - composer_json: info, - source, - dist, - is_default_branch: false, - time, - }); - } - Ok(None) | Err(_) => continue, - } - } - } - - // Scan branches - let branches = driver.branches().await?.clone(); - let default_branch = driver.root_identifier().to_string(); - for (branch_name, branch_hash) in &branches { - match driver.composer_information(branch_hash).await { - Ok(Some(info)) => { - if info["name"].as_str() != Some(&package_name) { - continue; - } - - let time = driver.change_date(branch_hash).await.unwrap_or(None); - let source = driver.source(branch_hash); - let dist = driver.dist(branch_hash).await.unwrap_or(None); - let is_default = branch_name == &default_branch; - - let version = self.branch_to_version(branch_name); - let normalized = self.normalize_version(&version); - - // Check for branch-alias - let aliased_version = info - .get("extra") - .and_then(|e| e.get("branch-alias")) - .and_then(|ba| ba.get(format!("dev-{branch_name}"))) - .and_then(|v| v.as_str()) - .map(|s| s.to_string()); - - versions.push(VcsPackageVersion { - name: package_name.clone(), - version: aliased_version.unwrap_or(version), - version_normalized: normalized, - composer_json: info, - source, - dist, - is_default_branch: is_default, - time, - }); - } - Ok(None) | Err(_) => continue, - } - } - - driver.cleanup().await?; - Ok(versions) - } - - /// Convert a tag name to a version string. - /// Returns `None` if the tag doesn't look like a version. - fn tag_to_version(&self, tag: &str) -> Option<String> { - // Strip common prefixes - let version = tag - .strip_prefix('v') - .or_else(|| tag.strip_prefix("V")) - .or_else(|| tag.strip_prefix("release-")) - .or_else(|| tag.strip_prefix("release/")) - .unwrap_or(tag); - - // Basic semver-ish check - if version.is_empty() { - return None; - } - if version.chars().next()?.is_ascii_digit() { - Some(version.to_string()) - } else { - None - } - } - - /// Convert a branch name to a dev version string. - fn branch_to_version(&self, branch: &str) -> String { - // Numeric branches like "1.x", "2.0" become "1.x-dev", "2.0.x-dev" - if branch.chars().next().is_some_and(|c| c.is_ascii_digit()) { - let version = if branch.ends_with(".x") || branch.ends_with(".*") { - branch.to_string() - } else { - format!("{branch}.x") - }; - format!("{version}-dev") - } else { - format!("dev-{branch}") - } - } - - /// Normalize a version string. - fn normalize_version(&self, version: &str) -> String { - // Use mozart-semver for proper normalization if available, - // otherwise do a simple normalization - mozart_semver::Version::parse(version) - .map(|v| v.to_string()) - .unwrap_or_else(|_| version.to_string()) - } -} |
