mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-08 16:02:39 +01:00
[Wilds] Allow class loading to continue on failure
Ref T13098. I think I didn't turn this into an actual revision, but let `ClassMapQuery` optionally continue if it encounters a class load failure. If we don't allow this, it can become very difficult to modify or remove some Arcanist classes since when you, say, remove a Workflow you can no longer make it to "arc liberate" to update the map for the change. This is currently used in roughly one place (in an upcoming diff) to let us get through startup in Runtime and into the "liberate" workflow.
This commit is contained in:
parent
412484022b
commit
23aaf85eaf
2 changed files with 51 additions and 2 deletions
|
@ -45,6 +45,7 @@ final class PhutilClassMapQuery extends Phobject {
|
|||
private $filterNull = false;
|
||||
private $uniqueMethod;
|
||||
private $sortMethod;
|
||||
private $continueOnFailure;
|
||||
|
||||
// NOTE: If you add more configurable properties here, make sure that
|
||||
// cache key construction in getCacheKey() is updated properly.
|
||||
|
@ -162,6 +163,10 @@ final class PhutilClassMapQuery extends Phobject {
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function setContinueOnFailure($continue) {
|
||||
$this->continueOnFailure = $continue;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/* -( Executing the Query )------------------------------------------------ */
|
||||
|
||||
|
@ -236,6 +241,7 @@ final class PhutilClassMapQuery extends Phobject {
|
|||
|
||||
$objects = id(new PhutilSymbolLoader())
|
||||
->setAncestorClass($ancestor)
|
||||
->setContinueOnFailure($this->continueOnFailure)
|
||||
->loadObjects();
|
||||
|
||||
// Apply the "expand" mechanism, if it is configured.
|
||||
|
|
|
@ -49,6 +49,7 @@ final class PhutilSymbolLoader {
|
|||
private $pathPrefix;
|
||||
|
||||
private $suppressLoad;
|
||||
private $continueOnFailure;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -148,6 +149,11 @@ final class PhutilSymbolLoader {
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function setContinueOnFailure($continue) {
|
||||
$this->continueOnFailure = $continue;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/* -( Load )--------------------------------------------------------------- */
|
||||
|
||||
|
@ -250,19 +256,56 @@ final class PhutilSymbolLoader {
|
|||
}
|
||||
|
||||
if (!$this->suppressLoad) {
|
||||
|
||||
// Loading a class may trigger the autoloader to load more classes
|
||||
// (usually, the parent class), so we need to keep track of whether we
|
||||
// are currently loading in "continue on failure" mode. Otherwise, we'll
|
||||
// fail anyway if we fail to load a parent class.
|
||||
|
||||
// The driving use case for the "continue on failure" mode is to let
|
||||
// "arc liberate" run so it can rebuild the library map, even if you have
|
||||
// made changes to Workflow or Config classes which it must load before
|
||||
// it can operate. If we don't let it continue on failure, it is very
|
||||
// difficult to remove or move Workflows.
|
||||
|
||||
static $continue_depth = 0;
|
||||
if ($this->continueOnFailure) {
|
||||
$continue_depth++;
|
||||
}
|
||||
|
||||
$caught = null;
|
||||
foreach ($symbols as $symbol) {
|
||||
foreach ($symbols as $key => $symbol) {
|
||||
try {
|
||||
$this->loadSymbol($symbol);
|
||||
} catch (Exception $ex) {
|
||||
// If we failed to load this symbol, remove it from the results.
|
||||
// Otherwise, we may fatal below when trying to reflect it.
|
||||
unset($symbols[$key]);
|
||||
|
||||
$caught = $ex;
|
||||
}
|
||||
}
|
||||
|
||||
$should_continue = ($continue_depth > 0);
|
||||
|
||||
if ($this->continueOnFailure) {
|
||||
$continue_depth--;
|
||||
}
|
||||
|
||||
if ($caught) {
|
||||
// NOTE: We try to load everything even if we fail to load something,
|
||||
// primarily to make it possible to remove functions from a libphutil
|
||||
// library without breaking library startup.
|
||||
throw $caught;
|
||||
if ($should_continue) {
|
||||
// We may not have `pht()` yet.
|
||||
fprintf(
|
||||
STDERR,
|
||||
"%s: %s\n",
|
||||
'IGNORING CLASS LOAD FAILURE',
|
||||
$caught->getMessage());
|
||||
} else {
|
||||
throw $caught;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue