Merge "MaintenanceRunner: keep track of script class explicitly."
This commit is contained in:
commit
20604e64fb
2 changed files with 47 additions and 20 deletions
|
|
@ -23,12 +23,20 @@ use Throwable;
|
|||
class MaintenanceRunner {
|
||||
|
||||
/**
|
||||
* Identifies the script to execute in a way that setup() understands.
|
||||
* Identifies the script to execute. This may be a class name, the relative or absolute
|
||||
* path of a script file, a plain name with or without an extension prefix, etc.
|
||||
*
|
||||
* @var ?string
|
||||
*/
|
||||
private $script = null;
|
||||
|
||||
/**
|
||||
* The class name of the script to execute.
|
||||
*
|
||||
* @var ?string
|
||||
*/
|
||||
private $scriptClass = null;
|
||||
|
||||
/** @var string[]|null */
|
||||
private $scriptArgv = null;
|
||||
|
||||
|
|
@ -170,6 +178,7 @@ class MaintenanceRunner {
|
|||
public function initForClass( string $scriptClass, $argv ) {
|
||||
$this->runFromWrapper = false;
|
||||
$this->script = $scriptClass;
|
||||
$this->scriptClass = $scriptClass;
|
||||
$this->parameters->setName( $argv[0] );
|
||||
$this->parameters->loadWithArgv( $argv );
|
||||
$this->initInternal( $scriptClass, array_slice( $argv, 1 ) );
|
||||
|
|
@ -323,15 +332,18 @@ class MaintenanceRunner {
|
|||
*
|
||||
* @internal
|
||||
* @param string $script
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function preloadScriptFile( string $script ): string {
|
||||
protected function preloadScriptFile( string $script ): void {
|
||||
if ( $this->scriptClass !== null && class_exists( $this->scriptClass ) ) {
|
||||
// We know the script class, and file-level code was executed because class_exists triggers auto-loading.
|
||||
return;
|
||||
}
|
||||
|
||||
[ $extName, $scriptName ] = $this->splitScript( $script );
|
||||
|
||||
if ( $extName !== null ) {
|
||||
// Preloading is not supported. findScriptClass() will try to find the script later.
|
||||
return $script;
|
||||
return;
|
||||
}
|
||||
|
||||
$scriptFile = $this->expandScriptFile( $scriptName, null );
|
||||
|
|
@ -347,12 +359,27 @@ class MaintenanceRunner {
|
|||
|
||||
// NOTE: class_exists will trigger auto-loading, so file-level code in the script file will run.
|
||||
if ( class_exists( $scriptClass ) ) {
|
||||
// Return the script class name we found, so we don't try to load the file again!
|
||||
return $scriptClass;
|
||||
// Set the script class name we found, so we don't try to load the file again!
|
||||
$this->scriptClass = $scriptClass;
|
||||
}
|
||||
|
||||
// Preloading failed. Let findScriptClass() try to find the script later.
|
||||
return $script;
|
||||
}
|
||||
|
||||
protected function getScriptClass(): string {
|
||||
if ( $this->scriptClass === null ) {
|
||||
if ( $this->runFromWrapper ) {
|
||||
$this->scriptClass = $this->findScriptClass( $this->script );
|
||||
} else {
|
||||
$this->scriptClass = $this->script;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !class_exists( $this->scriptClass ) ) {
|
||||
$this->fatalError( "Script class {$this->scriptClass} not found.\n" );
|
||||
}
|
||||
|
||||
return $this->scriptClass;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -399,14 +426,7 @@ class MaintenanceRunner {
|
|||
*/
|
||||
public function setup( SettingsBuilder $settings ) {
|
||||
// NOTE: this has to happen after the autoloader has been initialized.
|
||||
if ( $this->runFromWrapper ) {
|
||||
$scriptClass = $this->findScriptClass( $this->script );
|
||||
} else {
|
||||
$scriptClass = $this->script;
|
||||
if ( !class_exists( $scriptClass ) ) {
|
||||
$this->fatalError( "Class {$this->script} does not exist.\n" );
|
||||
}
|
||||
}
|
||||
$scriptClass = $this->getScriptClass();
|
||||
|
||||
$cls = new ReflectionClass( $scriptClass );
|
||||
if ( !$cls->isSubclassOf( Maintenance::class ) ) {
|
||||
|
|
@ -536,7 +556,9 @@ class MaintenanceRunner {
|
|||
// This allows the script file to define constants that change the behavior
|
||||
// of Setup.php.
|
||||
// Note that this will only work reliably for core scripts.
|
||||
$this->script = $this->preloadScriptFile( $this->script );
|
||||
if ( $this->runFromWrapper ) {
|
||||
$this->preloadScriptFile( $this->script );
|
||||
}
|
||||
|
||||
if ( !is_readable( $settingsFile ) ) {
|
||||
// NOTE: Some maintenance scripts can (and need to) run without LocalSettings.
|
||||
|
|
|
|||
|
|
@ -72,12 +72,16 @@ class MaintenanceRunnerTest extends TestCase {
|
|||
|
||||
private function newRunner(): MaintenanceRunner {
|
||||
return new class () extends MaintenanceRunner {
|
||||
public function getScriptClass(): string {
|
||||
return parent::getScriptClass();
|
||||
}
|
||||
|
||||
public function findScriptClass( string $script ): string {
|
||||
return parent::findScriptClass( $script );
|
||||
}
|
||||
|
||||
public function preloadScriptFile( string $script ): string {
|
||||
return parent::preloadScriptFile( $script );
|
||||
public function preloadScriptFile( string $script ): void {
|
||||
parent::preloadScriptFile( $script );
|
||||
}
|
||||
|
||||
protected function fatalError( $msg, $exitCode = 1 ) {
|
||||
|
|
@ -132,7 +136,8 @@ class MaintenanceRunnerTest extends TestCase {
|
|||
public function testPreloadScriptFile( $script, $expected ) {
|
||||
$runner = $this->newRunner();
|
||||
|
||||
$class = $runner->preloadScriptFile( $script );
|
||||
$runner->preloadScriptFile( $script );
|
||||
$class = $runner->getScriptClass();
|
||||
|
||||
if ( str_starts_with( $class, '\\' ) ) {
|
||||
$class = substr( $class, 1 );
|
||||
|
|
|
|||
Loading…
Reference in a new issue