diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-05-03 23:31:31 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-05-03 23:31:31 +0900 |
| commit | e37b12d6e2d95b4d3924859732513e125fc552e0 (patch) | |
| tree | 555b049cdca81814b4adc74d542ef39833cf5f5d /crates/mozart/src/commands/install.rs | |
| parent | 26af378d81da76c50593674fa86ed4911aa0e46f (diff) | |
| download | php-mozart-e37b12d6e2d95b4d3924859732513e125fc552e0.tar.gz php-mozart-e37b12d6e2d95b4d3924859732513e125fc552e0.tar.zst php-mozart-e37b12d6e2d95b4d3924859732513e125fc552e0.zip | |
feat(registry): support type: path repositories
Adds a `mozart-php-serialize` crate (a byte-compatible port of PHP's
`serialize()`) and a `mozart-registry::path_repository` module that
expands `type: path` entries into synthetic `type: package`
repositories. Each synthesized package carries the same SHA-1 dist
reference Composer computes (`sha1(\$json . serialize(\$options))`)
so the lockfile and trace lines match Composer byte-for-byte.
Two latent bugs surfaced once the path-repo flow exercised real
resolutions:
- `apply_partial_update` swapped path-repo packages back to their
locked version, defeating Composer's "path repos always reload"
rule (`PoolBuilder` treats them as canonical, not lock-bound).
Mirror the path-repo skip already used when constructing
`locked_packages`.
- `normalize_root_alias_atom` returned the raw input string for
stable numeric atoms (e.g. `1.1.1`), so the alias matcher's
`input.version \!= alias.version_normalized` check — comparing
against pool inputs that carry the 4-segment normalized form —
silently never matched. Run the parsed Version through Display so
both sides are in the same shape.
`install/update::run` gain a `path_repo_base_override: Option<&Path>`
parameter for the in-process test harness: Composer's PHPUnit
`InstallerTest::setUp` does `chdir(__DIR__)` so relative path-repo
URLs resolve against `composer/tests/Composer/Test/`, but the Rust
harness writes `composer.json` into a per-test tempdir and can't
chdir safely under parallel tests. Production callers pass `None`
and resolve against `working_dir`.
Greens 3 ignored installer fixtures:
partial_update_loads_root_aliases_for_path_repos
alias_in_lock
alias_in_lock2
Diffstat (limited to 'crates/mozart/src/commands/install.rs')
| -rw-r--r-- | crates/mozart/src/commands/install.rs | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/crates/mozart/src/commands/install.rs b/crates/mozart/src/commands/install.rs index ba9bd8a..a5698ff 100644 --- a/crates/mozart/src/commands/install.rs +++ b/crates/mozart/src/commands/install.rs @@ -1325,7 +1325,15 @@ pub async fn execute( )); let mut executor = FilesystemExecutor::new(mozart_registry::cache::Cache::files(&cache_config)); let working_dir = resolve_working_dir(cli); - run(&working_dir, args, console, repositories, &mut executor).await + run( + &working_dir, + None, + args, + console, + repositories, + &mut executor, + ) + .await } /// Library entry point — pure logic, no `Cli` access. @@ -1334,8 +1342,13 @@ pub async fn execute( /// `'packagist' => false` test config) and a tracing `InstallerExecutor`, /// then call this function directly to exercise the install flow without /// spawning the binary. +/// +/// `path_repo_base_override` is the in-process test escape hatch for relative +/// `type: path` repo URLs — see [`super::update::run`] for the full rationale. +/// Production callers pass `None` to anchor against `working_dir`. pub async fn run( working_dir: &Path, + path_repo_base_override: Option<&Path>, args: &InstallArgs, console: &mozart_core::console::Console, repositories: std::sync::Arc<mozart_registry::repository::RepositorySet>, @@ -1420,8 +1433,15 @@ pub async fn run( }; // Forward the caller's repositories + executor so in-process tests // see their mocks honored across the install→update fallback edge. - return super::update::run(working_dir, &update_args, console, repositories, executor) - .await; + return super::update::run( + working_dir, + path_repo_base_override, + &update_args, + console, + repositories, + executor, + ) + .await; } let lock = lockfile::LockFile::read_from_file(&lock_path)?; |
