| Age | Commit message (Collapse) | Author |
|
Mirror Composer's structure where VCS drivers live under
Repository/Vcs/. Rename VcsDriver trait to VcsDriverInterface and
BitbucketDriver to GitBitbucketDriver to match Composer naming, and
add stubs for FossilDriver, PerforceDriver, and the VcsDriver base.
|
|
Mirror Composer's namespace layout: VersionGuesser/VersionParser move from
vcs/ to package/version/, and ArrayDumper is extracted out of the status
command into package/dumper/, matching Composer\Package\Version and
Composer\Package\Dumper.
|
|
|
|
Add an `IoInterface` trait in mozart-core::console that mirrors
`\Composer\IO\IOInterface`, implement it for `Console`, and switch
commands, the auditor, and the suggested-packages reporter to accept
the abstracted IO (typically `Arc<Mutex<Box<dyn IoInterface>>>` at the
command boundary, `&dyn IoInterface` deeper down) instead of
`&Console`. The console_writeln\!/write\! macros now go through
`IoInterface::verbosity()` via the lock so any implementor works.
|
|
Move AuditConfig, AuditFormat/AbandonedHandling enums, and stub types
(SecurityAdvisory, PartialSecurityAdvisory, IgnoredSecurityAdvisory)
into their own files under advisory/. Public API is preserved via
wildcard re-exports.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Mirrors Composer\Package\Loader\RootPackageLoader::load(): converts the
parsed RawPackageData into fully typed RootPackageData with Link objects,
defaulted fields, and trait-based accessors. Composer::package() now
returns RootPackageData instead of RawPackageData, eliminating the
pre-normalised JSON workaround noted in the previous comment.
|
|
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>
|
|
Composer needs DownloadManager (from mozart-registry), but mozart-core
sits below mozart-registry in the dependency graph — adding the field
would create a dependency cycle. Moving Composer and create_composer to
the mozart CLI crate breaks the cycle and lets the root state container
hold a DownloadManager.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
module
Removes the per-command duplicate implementations of
get_platform_requirement_filter from dump_autoload and reinstall,
and lifts a single canonical version into commands.rs.
|
|
Eliminate the nested &console_format!(...) boilerplate at every call site
by teaching console_writeln!, console_write!, console_writeln_error!, and
console_write_error! to accept a format literal + variadic args directly,
matching the println!/eprintln! ergonomics. Propagate the format string
span into generated code so rustc errors point to the right location.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Wire Composer::try_load_from_file so validate uses typed Config.lock
instead of a raw JSON read for the should-check-lock decision
- Surface LockFile::get_missing_requirement_info in check_lock_freshness,
mirroring Composer's locker->getMissingRequirementInfo call
- Replace inline per-dep error/warning printing with output_result calls
so each dependency gets the same header format as the root file
- Switch --with-dependencies to RepositoryManager + InstallationManager;
skip metapackages; fall back to vendor walk when Composer unavailable
- Move license wrong-type from warnings to errors (divergence #10),
matching ValidatingArrayLoader's classification
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Implement std::str::FromStr for AuditFormat and AbandonedHandling
instead of ad-hoc from_str methods (resolves should_implement_trait).
Group Auditor::audit() parameters into AuditOptions to resolve
too_many_arguments.
|
|
- Add mozart-core::advisory::{AuditFormat, AbandonedHandling, AuditConfig}
mirroring Composer\Advisory\AuditConfig; reads audit.ignore,
audit.ignore-severity, audit.ignore-abandoned, audit.abandoned,
audit.block-insecure, audit.block-abandoned, audit.ignore-unreachable
from composer.json config with full apply-scope support
- Add mozart-registry::advisory::Auditor mirroring Composer\Advisory\Auditor;
process_advisories() filters by package name, advisory ID, CVE, source
remote ID, and severity; filter_abandoned_packages() respects ignore-abandoned
- Add RepositorySet::get_matching_security_advisories() wrapping
fetch_security_advisories with version-matching and unreachable-repo tracking
- JSON output now includes ignored-advisories and unreachable-repositories keys
- --abandoned falls back to audit.abandoned config (was hardcoded to "fail")
- --ignore-severity merges with audit.ignore-severity config
- --ignore-unreachable ORs with audit.ignore-unreachable config
- Move normalize_or_separator into repository/mod.rs alongside version matching
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Introduce JsonConfigSource in mozart-core mirroring Composer's
JsonConfigSource fallback logic (add/insert/set-url/remove repository),
and BaseConfigContext mirroring BaseConfigCommand's initialize().
Key behaviour fixes:
- list: synthesise [packagist.org] <disabled> only when no composer-type
repo with a packagist.org host is present (was: always show enabled default)
- disable: idempotent via add_repository(false) matching Composer's branch;
now requires a name (no silent default to packagist.org)
- enable: calls remove_repository only, no extra empty-array cleanup
- set-url: preserves assoc-keyed format instead of converting to list
- get-url: assoc fast-path + unquoted error message matching Composer
- add: use regex pre-check (starts_with '{') instead of trial-parse
- error messages reworded to match Composer verbatim (mozart brand kept)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Extract script-event constants into mozart_core::script_events, fix
dev_mode to `--dev || \!--no-dev` (PHP wins-on---dev), route the --list
header to stderr with empty-list silent return, validate --timeout with
ctype_digit semantics, and reorder execute() so the cannot-be-run check
runs before requireComposer(). Drops the spurious --no-scripts
short-circuit (Composer honors that flag in the dispatcher, not the
command).
|
|
Mirror `CheckPlatformReqsCommand::execute` end-to-end: build an
`InstalledRepoLite` from lock/installed plus the root and the real
PlatformRepository, ksort the combined `$requires`, and run the
candidate matching loop with `findPackagesWithReplacersAndProviders`
so an installed package that `provide`s or `replace`s a platform name
(e.g. `symfony/polyfill-mbstring` providing `ext-mbstring`) is now
recognised as satisfying the requirement.
Fixes the JSON output schema to match Composer:
`failed_requirement` is the `{source, type, target, constraint}`
object (or null), `provider` is the bare "provided by …" string (or
null), and `status` is the unwrapped `success`/`failed`/`missing`.
Also switches `--format` to a clap `value_parser` and replaces the
"No installed packages found" hard error with Composer's warn-then-
proceed path so an empty lock yields `[]` and exit 0.
Adds `mozart_core::installer::InstalledCandidate` plus
`InstalledRepoLite::add_candidate` /
`find_with_replacers_and_providers` as the shared substrate for
future commands (`depends`, `prohibits`, `audit`) that need the same
provider/replacer index.
|
|
Port `Composer\Installer\SuggestedPackagesReporter` to
`mozart_core::installer` (modes, add_package, add_suggestions_from_package,
output, output_minimalistic, escape_output) and slim
`commands/suggests.rs` to mirror `SuggestsCommand::execute`. Defines
`HasSuggests`, `InstalledRepoLite`, `RootInfo` as the minimal stand-ins
for Composer's `PackageInterface` / `InstalledRepository` /
`onlyDependentsOf`.
Also fixes a latent bug where `provide`/`replace` virtuals were read
from `extra_fields` (always empty after a serde round-trip into
LockedPackage's typed fields) and moves the "additional suggestions
... --all" hint to fire after the rendered sections, matching
Composer's order.
|
|
Restructures diagnose to mirror Composer's 17-step DiagnoseCommand:
adds composer.json schema validation, custom composer-repo
connectivity, COMPOSER_IPRESOLVE warning, and the
checkConnectivityAndComposerNetworkHttpEnablement preflight; drops
Mozart-only extras (cache-dir, lock freshness, trailing summary).
Extracts the manifest validator into mozart-core::config_validator
so both ValidateCommand and DiagnoseCommand depend on the shared
module rather than each other -- the same shape Composer uses with
Util\\ConfigValidator. Adds a thin HttpDownloader wrapper in
mozart-core::http, shadowing Composer's Util\\HttpDownloader.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Drive the command from Composer::require() and route the
(installed | locked) branch through the ported PackageSorter,
RepositoryUtils::filterRequiredPackages, and PackageInfo helpers
in mozart-core. --no-dev for installed packages now filters via
root.require closure instead of dev_package_names membership;
text output annotates the name cell with an OSC 8 hyperlink to
the view-source/homepage URL; summary ties resolve in first-seen
order via IndexMap + stable sort_by_key(Reverse(count)) to mirror
PHP's arsort().
|
|
Switch to Composer::require() for the entrypoint, drop the Mozart-only
--dry-run / --no-dev flags, mirror selection inline using a port of
BasePackage::packageNameToRegexp, read autoloader options from
composer.config(), and route the autoload dump through
composer.autoload_generator(). Empty-result and unmatched-pattern
warnings now emit on stderr with <warning> markup, matching
$io->writeError. Plugin/script-event dispatch and Transaction-based
operation building remain TODO until the installer_executor lands.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Replace the dist-hash tree-diff implementation with Composer's VCS-level
status flow: three buckets (errors / unpushed_changes / vcs_version_changes)
populated via ChangeReportInterface / DvcsDownloaderInterface /
VcsCapableDownloaderInterface, and a bitfield exit code (1|2|4) instead
of always 1.
Supporting work:
- mozart-semver: add normalize_branch (VersionParser::normalizeBranch).
- mozart-vcs: extend VcsDownloader trait with unpushed_changes /
vcs_reference; port GitDownloader::getUnpushedChanges (HEAD-ref
discovery + git diff --name-status remote...branch + two-pass fetch);
fix git status invocation to use --untracked-files=no (Composer parity);
add hasMetadataRepository preconditions to git/hg/svn local_changes;
port VersionGuesser (git/hg/svn dispatch — Fossil omitted, feature
branch detection runs sequentially instead of via async promises).
- mozart-core: extend LocalPackage with pretty_version, package_type,
installation_source, source, dist, extra; add InstallationSource and
PackageReference. factory.rs reads them from installed.json.
- mozart-registry: new download_manager mirroring
DownloadManager::getDownloaderForPackage.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Replace the HTTP-only post-filtered implementation with a Repository::search
trait dispatch that mirrors ComposerRepository::search semantics for all
three modes (FULLTEXT/NAME/VENDOR). --only-name now does an OR-of-tokens
regex match against the full Packagist list.json index instead of a
substring match against a fulltext page, so e.g. \`mozart search --only-name
mono log\` matches \`monolog/monolog\` like Composer does. Other parity
fixes: regex::escape on non-fulltext queries, format check before mutex
check, 4-space JSON indent, OSC 8 terminal hyperlink emission when a
result has a url, <warning>\! Abandoned \!</warning> styling on abandoned
rows, and the Mozart-only "No packages found" warning is dropped to match
Composer's silent empty-result behavior.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Add the Composer state-container types (LocalRepository,
RepositoryManager, InstallationManager, AutoloadGenerator,
AutoloadDumpOptions, PlatformRequirementFilter, Locker) plus the
factory wiring that builds them from composer.json and
vendor/composer/installed.json.
AutoloadGenerator::dump lives in mozart-autoload as an extension
trait so the orchestrating algorithm sits next to the classmap
scanner while the state container stays in mozart-core. Rework
dump-autoload to drive both, mirroring
$composer->getAutoloadGenerator()->dump(...).
|
|
console_format!
The six tag-style color functions (info, comment, error, question,
highlight, warning) are pub only so that console_format! can call them
from generated code; they are not part of the public API. Rename them
to __format_*_message to make that intent visible, add a doc-comment
saying not to call them directly, and replace every remaining direct
call site with console_format!.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
|
|
--no-cache redirects COMPOSER_CACHE_DIR to /dev/null (mirrors Application::doRun).
cache_files_maxsize is now u64 with a "300MiB"-style string deserializer.
Cache::new() takes readonly instead of enabled; is_usable() detects null devices.
|
|
Adds crates/mozart-core/src/factory.rs with get_cache_dir(),
get_data_dir(), and create_config() — a Rust port of
Composer\Factory::createConfig() (auth loading and htaccess creation
are out of scope for now).
Also fixes a correctness bug on Linux: the previous Config::default()
resolved cache-dir to $XDG_CONFIG_HOME/composer/cache via the
{$home}/cache placeholder, whereas Composer uses the XDG cache base
($XDG_CACHE_HOME or ~/.cache), giving ~/.cache/composer.
Callers updated:
- Composer::load() uses create_config() as the global baseline before
merging project-level config.
- config command execute_read() builds the global baseline with
create_config() and overlays local config on top when not --global,
matching Composer's actual layering order.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Config uses serde with kebab-case field mapping; known properties are
strongly-typed fields and unknown keys flow into an extra BTreeMap.
resolve_references is moved to the new config module.
|
|
|
|
Introduce mozart_core::composer::Composer with require()/try_load()
constructors and a config() accessor, modelled on PHP Composer's
BaseCommand::requireComposer / tryComposer. ComposerConfig and
composer_home move into mozart-core so Composer::load can resolve
placeholders consistently.
Migrate dump-autoload, archive, exec and run-script away from ad-hoc
composer.json reads. exec and run-script now fail when composer.json
is missing instead of silently falling back to "vendor/bin",
matching the upstream requireComposer contract.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
|
|
|
|
Mirror Composer's Util\ConfigValidator::validate() license handling:
treat empty string and empty array as missing, accept array form, and
emit deprecation warnings (with GPL-specific -only/-or-later
suggestions) for identifiers flagged deprecated in the SPDX database.
|
|
Composer's config.cafile/config.capath were accepted by the config
command but ignored by every HTTP request. Centralize reqwest client
construction in mozart_core::http, pre-load the configured CA bundle
at startup, and route every callsite (registry, vcs drivers, diagnose,
self-update) through the shared builder so user-supplied roots are
actually used during HTTPS verification.
|
|
Three Composer-compat bugs surfaced by the github_issues_9290 fixture,
fixed together since they form one resolution path:
- RawPackageData.repositories now accepts a JSON object keyed by name,
matching RepositoryFactory::createRepos which iterates either int-
or string-keyed arrays via PHP foreach.
- Version::parse fills every unspecified position of a `.x-dev` branch
with 9999999, mirroring VersionParser::normalizeBranch. Previously
`2.x-dev` parsed to 2.0.9999999.9999999-dev and failed to satisfy
^2.8.
- is_platform_package limits the `php-` family to the closed set
{64bit,ipv6,zts,debug} per PLATFORM_PACKAGE_REGEX. Vendor packages
like `php-http/client-common` are no longer misclassified.
Unblocks github_issues_7051, _8903, _9012, _9290.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Mozart silently ignored the `security-advisories` block on inline
`type: package` repositories and the `config.audit.block-insecure`
audit flag, so a `composer update` succeeded with packages a Composer
run would have refused to load. Mirror Composer's
`SecurityAdvisoryPoolFilter` for the slice that feeds the pool:
- Plumb a `security-advisories` field through `RawRepository` and a
`block_insecure` flag through `ResolveRequest`, lifted off
`composer.json`'s `config.audit.block-insecure`.
- Collect every advisory's `affectedVersions` constraint at resolve
time. When `block_insecure` is set and an inline package's
normalized version satisfies the constraint, drop it from the pool
before solving — root requires with no unaffected candidate then
fail with the standard "could not be resolved" error.
|
|
Composer's FilterRepository wraps a repository with three knobs:
`only` / `exclude` to drop packages by name, and `canonical: false` to
relax the repo's authoritative claim on its package names so
lower-priority repos can still answer. Mozart was ignoring all three,
so first-listed inline / composer-repo entries always shadowed later
repos and `only` / `exclude` lists were silently no-ops.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Composer's RootPackageRepository puts a clone of the root package into
the pool as a fixed entry — its `require` / `require-dev` cleared, but
its name, version, provides, and replaces preserved. That way a
transitive `require` pointing back at the root resolves through the
pool the same way any other reference would, and legal circular
dependencies (root requires A, A requires root) work.
Mozart had no such seed: the rule generator only knew about the root
through the explicit root-require / root-provide / root-replace tables,
so a transitive consumer requiring the root by name failed with no
provider.
Plumb root_version through ResolveRequest (RawPackageData gains a
matching `Option<String>` field), build a fixed PoolPackageInput for
the root with provides/replaces lifted from request.root_provide /
root_replace, and skip the root by name when collecting the resolver's
output so it doesn't leak into the lock file. Falls back to
`1.0.0+no-version-set` (Composer's RootPackage::DEFAULT_PRETTY_VERSION)
when the root composer.json omits `version`.
Unblocks circular_dependency2, conflict_against_replaced_package_problem,
and provider_conflicts installer fixtures.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Adopt indexmap workspace-wide so iteration order is deterministic and
follows insertion order. The non-deterministic order of std HashMap
otherwise leaks into resolver decisions when multiple valid solutions
exist (e.g. cyclic require pairs under prefer-lowest), making behavior
flaky and divergent from Composer's PHP-array semantics.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Composer's PackageRepository lets composer.json embed full package
metadata under repositories[].package, mirroring the on-disk
Packagist response shape. The vast majority of installer fixtures
under composer/tests/Composer/Test/Fixtures/installer (179 of 189)
rely on this — they declare every package they need inline rather
than hitting the network.
Three pieces wire this into Mozart:
1. mozart-core::package::RawRepository: relax `url` to Option<String>
(Composer enforces presence per repo type, not at JSON parse) and
add `package: Option<Value>` to receive the inline definition,
which can be a single object or an array.
2. mozart-registry::inline_package: a new module that walks
`&[RawRepository]`, picks out type=package entries, and reshapes
each `package` payload into a PackagistVersion (auto-computing
version_normalized when omitted, matching Packagist's output).
3. resolver::resolve and lockfile::generate_lock_file: feed inline
packages into the SAT pool builder and short-circuit the Packagist
fetch when generating the lock entry for a resolved inline package.
The package-name set is shared with the existing VCS-skip logic so
the seed and transitive loops don't double-fetch.
One additional install-time change: in install_from_lock, packages
that have neither dist nor source are now skipped silently instead
of bailing with "no dist or source information". This mirrors
Composer's MetapackageInstaller (no installer for type=metapackage)
and is also what Composer's own AllFunctionalTest exercises via
InstallationManagerMock — most inline-package fixtures define
synthetic packages with no download metadata, expecting the install
operation to be recorded but not actually run.
Net effect: installer fixture scoreboard jumps from 7/187 to 103/187.
The 84 fixtures still ignored hit issues unrelated to inline-package
plumbing — aliases, replace/provide chains, dev-reference handling,
allow-list updates, etc. — and are tracked separately.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Mirrors Composer\Package\Loader\RootPackageLoader::load(): if the root
package's "name" appears as a key in its own "require" or "require-dev"
map, fail loudly before reaching the resolver. Without this, Mozart
would silently let the request hit Packagist (which has no entry for
the root's vendor/name) and report a misleading "could not be found"
error.
Wired into install::execute (when a lock file is present) and
update::execute (the no-lock fallback path). Carries the same wording
as Composer's RuntimeException so a future EXPECT-OUTPUT comparison
will match.
Also extends the installer test harness: when a fixture sets
EXPECT-EXCEPTION but no EXPECT-EXIT-CODE, assert that Mozart exits
non-zero. Full exception-class matching remains a follow-up (see
.ken/test_design.md §7.2).
Closes the gap exercised by the install-self-from-root installer
fixture.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Composer's RootPackageLoader assigns the root name "__root__" when
composer.json omits the "name" field. Mozart was failing deserialization
in that case, blocking any installer fixture with a nameless root
manifest. Apply the same serde default and unignore
update-to-empty-from-blank as the first green entry on the .test
scoreboard.
|
|
Composer
- Extract matches_wildcard to mozart-core for reuse across commands
- Support wildcard patterns in --package and --ignore arguments
- Use ^<installed_version> for semver-safe classification instead of root constraint
- Replace std::process::exit(1) with bail_silent for proper cleanup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
- Extend self.version replacement to conflict, provide, and replace
link types (previously only require and require-dev)
- Only rewrite self.version when VCS metadata is actually removed,
matching Composer's behavior
- Read optimize-autoloader, classmap-authoritative, and apcu-autoloader
from the project's composer.json config section instead of hardcoding
false
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Replace clap's built-in --version with custom handler that outputs
Composer-compatible version info: Mozart version line, PHP version
with binary path, and diagnose hint. Add detect_php_version_and_binary()
to mozart-core platform module.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Introduce a Symfony Console-style tag macro that replaces verbose
patterns like `console::info(&format!("text {name}"))` with
`console_format!("<info>text {name}</info>")`. Supports all 6 tag
types (info, comment, error, question, highlight, warning) with
format argument distribution across multiple tagged segments.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Extends the PHP inline script to query constants and functions for 14
library packages (lib-pcre, lib-openssl, lib-curl, lib-libxml, etc.)
and parses the new LIB:name:version output format. This fixes SAT
resolver failures for packages requiring lib-* constraints like
lib-pcre >=7.0.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
|
|
Split AND constraints (e.g. ">=1.0 <2.0" or ">=1.0,<2.0") into parts
and bump only the lower-bound operator (>=, ^, ~) while preserving
upper-bound operators (<, <=, \!=) unchanged.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
composer-runtime-api, composer-plugin-api, and composer are Composer
pseudo packages that don't exist on Packagist. The resolver was trying
to fetch them remotely (HTTP 404) because PackageName::is_platform()
didn't recognize them and detect_platform() didn't inject them.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|