Merge "composer: Remove localization from unlocalizable LockFileChecker"

This commit is contained in:
jenkins-bot 2024-05-31 23:33:19 +00:00 committed by Gerrit Code Review
commit 9f8c62a20e
5 changed files with 33 additions and 61 deletions

View file

@ -21,38 +21,29 @@
namespace MediaWiki\Composer; namespace MediaWiki\Composer;
use Composer\Semver\Semver; use Composer\Semver\Semver;
use Status;
use Wikimedia\Composer\ComposerJson; use Wikimedia\Composer\ComposerJson;
use Wikimedia\Composer\ComposerLock; use Wikimedia\Composer\ComposerLock;
/** /**
* Used to check whether composer-installed dependencies (no-dev) are up-to-date * Used to check whether composer-installed dependencies (no-dev) are up-to-date
*
* @internal For use by CheckComposerLockUpToDate and Installer
* @since 1.42 * @since 1.42
*/ */
class LockFileChecker { class LockFileChecker {
/** @var ComposerJson */ private ComposerJson $composerJson;
private $composerJson; private ComposerLock $composerLock;
/** @var ComposerJson */
private $composerLock;
/**
* @param ComposerJson $composerJson
* @param ComposerLock $composerLock
*/
public function __construct( ComposerJson $composerJson, ComposerLock $composerLock ) { public function __construct( ComposerJson $composerJson, ComposerLock $composerLock ) {
$this->composerJson = $composerJson; $this->composerJson = $composerJson;
$this->composerLock = $composerLock; $this->composerLock = $composerLock;
} }
/** /**
* This method will return a {@link Status} instance, * @return string[]|null Array of error messages, or null when Composer-installed dependencies are up-to-date.
* you can use {@link Status::isGood()} to simply determine that
* the composer-installed dependencies are up-to-date.
* @return Status
*/ */
public function check(): Status { public function check(): ?array {
$status = Status::newGood(); $errors = [];
$requiredButOld = []; $requiredButOld = [];
$requiredButMissing = []; $requiredButMissing = [];
@ -79,26 +70,21 @@ class LockFileChecker {
// We're happy; loop to the next dependency. // We're happy; loop to the next dependency.
} }
if ( count( $requiredButOld ) === 0 && count( $requiredButMissing ) === 0 ) {
// We couldn't find any out-of-date or missing dependencies, so assume everything is ok!
return $status;
}
foreach ( $requiredButOld as [ foreach ( $requiredButOld as [
"name" => $name, "name" => $name,
"suppliedVersion" => $suppliedVersion, "suppliedVersion" => $suppliedVersion,
"wantedVersion" => $wantedVersion "wantedVersion" => $wantedVersion
] ) { ] ) {
$status->error( 'composer-deps-outdated', $name, $suppliedVersion, $wantedVersion ); $errors[] = "$name: $suppliedVersion installed, $wantedVersion required.";
} }
foreach ( $requiredButMissing as [ foreach ( $requiredButMissing as [
"name" => $name, "name" => $name,
"wantedVersion" => $wantedVersion "wantedVersion" => $wantedVersion
] ) { ] ) {
$status->error( 'composer-deps-notinstalled', $name, $wantedVersion ); $errors[] = "$name: not installed, $wantedVersion required.";
} }
return $status; return $errors ?: null;
} }
} }

View file

@ -4475,7 +4475,5 @@
"benefit-1-description": "Watchlists that allow you to keep track of pages that youre interested in.", "benefit-1-description": "Watchlists that allow you to keep track of pages that youre interested in.",
"benefit-2-description": "Permanent list of contributions youve made to the project.", "benefit-2-description": "Permanent list of contributions youve made to the project.",
"benefit-3-description": "Preferences that allow you to customize your experience.", "benefit-3-description": "Preferences that allow you to customize your experience.",
"temp-user-unable-to-acquire": "Unable to acquire a temporary account username. Please try again.", "temp-user-unable-to-acquire": "Unable to acquire a temporary account username. Please try again."
"composer-deps-outdated": "$1: $2 installed, $3 required.",
"composer-deps-notinstalled": "$1: not installed, $2 required."
} }

View file

@ -4734,7 +4734,5 @@
"benefit-1-description": "The text for the first benefit shown on signup for temporary users.", "benefit-1-description": "The text for the first benefit shown on signup for temporary users.",
"benefit-2-description": "The text for the second benefit shown on signup for temporary users.", "benefit-2-description": "The text for the second benefit shown on signup for temporary users.",
"benefit-3-description": "The text for the third benefit shown on signup for temporary users.", "benefit-3-description": "The text for the third benefit shown on signup for temporary users.",
"temp-user-unable-to-acquire": "The error message shown when the server was unable to acquire a temporary account username for the user.", "temp-user-unable-to-acquire": "The error message shown when the server was unable to acquire a temporary account username for the user."
"composer-deps-outdated": "Error in check composer-installed dependencies. Parameters:\n* $1 - Dependency name.\n* $2 - Installed version\n* $3 - Required version.",
"composer-deps-notinstalled": "Error message if a composer dependency is not install. Parameters:\n* $1 - Dependency name.\n* $2 - Required version."
} }

View file

@ -43,30 +43,24 @@ class CheckComposerLockUpToDate extends Maintenance {
// Check all the dependencies to see if any are old // Check all the dependencies to see if any are old
$checker = new LockFileChecker( $json, $lock ); $checker = new LockFileChecker( $json, $lock );
$result = $checker->check(); $errors = $checker->check();
if ( $result->isGood() ) {
// We couldn't find any out-of-date dependencies, so assume everything is ok! // NOTE: This is used by TestSetup before MediaWikiServices is initialized and thus
$this->output( "Your composer.lock file is up to date with current dependencies!\n" ); // may not rely on global singletons.
} else { // NOTE: This is used by maintenance/update.php and thus may not rely on
// NOTE: wfMessage will fail if MediaWikiServices is not yet initialized. // database connections, including e.g. interface messages without useDatabase=false,
// This can happen when this class is called directly from bootstrap code, // which would call MessageCache.
// e.g. by TestSetup. We get around this by having testSetup use quiet mode. if ( $errors ) {
if ( !$this->isQuiet() ) { foreach ( $errors as $error ) {
foreach ( $result->getMessages() as $msg ) { $this->error( $error . "\n" );
$this->error(
wfMessage( $msg )
// Avoid fatal error from a cache miss in MessageCache when called
// from maintenance/update.php
->useDatabase( false )
->inLanguage( 'en' )
->plain() . "\n"
);
}
} }
$this->fatalError( $this->fatalError(
'Error: your composer.lock file is not up to date. ' . 'Error: your composer.lock file is not up to date. ' .
'Run "composer update --no-dev" to install newer dependencies' 'Run "composer update --no-dev" to install newer dependencies'
); );
} else {
// We couldn't find any out-of-date dependencies, so assume everything is ok!
$this->output( "Your composer.lock file is up to date with current dependencies!\n" );
} }
} }
} }

View file

@ -30,32 +30,28 @@ class LockFileCheckerTest extends MediaWikiIntegrationTestCase {
$json = new ComposerJson( __DIR__ . '/composer-testcase1.json' ); $json = new ComposerJson( __DIR__ . '/composer-testcase1.json' );
$lock = new ComposerLock( __DIR__ . '/composer-testcase1.lock' ); $lock = new ComposerLock( __DIR__ . '/composer-testcase1.lock' );
$checker = new LockFileChecker( $json, $lock ); $checker = new LockFileChecker( $json, $lock );
$status = $checker->check(); $errors = $checker->check();
$this->assertTrue( $status->isGood() ); $this->assertNull( $errors );
} }
public function testOutdated() { public function testOutdated() {
$json = new ComposerJson( __DIR__ . '/composer-testcase2.json' ); $json = new ComposerJson( __DIR__ . '/composer-testcase2.json' );
$lock = new ComposerLock( __DIR__ . '/composer-testcase2.lock' ); $lock = new ComposerLock( __DIR__ . '/composer-testcase2.lock' );
$checker = new LockFileChecker( $json, $lock ); $checker = new LockFileChecker( $json, $lock );
$status = $checker->check(); $errors = $checker->check();
$this->assertFalse( $status->isGood() ); $this->assertArrayEquals( [
$this->assertSame( 'wikimedia/relpath: 2.9.9 installed, 3.0.0 required.', $status->getMessage()->plain() ); 'wikimedia/relpath: 2.9.9 installed, 3.0.0 required.',
], $errors );
} }
public function testNotInstalled() { public function testNotInstalled() {
$json = new ComposerJson( __DIR__ . '/composer-testcase3.json' ); $json = new ComposerJson( __DIR__ . '/composer-testcase3.json' );
$lock = new ComposerLock( __DIR__ . '/composer-testcase3.lock' ); $lock = new ComposerLock( __DIR__ . '/composer-testcase3.lock' );
$checker = new LockFileChecker( $json, $lock ); $checker = new LockFileChecker( $json, $lock );
$status = $checker->check(); $errors = $checker->check();
$this->assertFalse( $status->isGood() );
$msgs = [];
foreach ( $status->getMessages() as $msg ) {
$msgs[] = wfMessage( $msg )->plain();
}
$this->assertArrayEquals( [ $this->assertArrayEquals( [
'wikimedia/relpath: 2.9.9 installed, 3.0.0 required.', 'wikimedia/relpath: 2.9.9 installed, 3.0.0 required.',
'wikimedia/at-ease: not installed, 2.1.0 required.', 'wikimedia/at-ease: not installed, 2.1.0 required.',
], $msgs ); ], $errors );
} }
} }