Loading automatic_updates.services.yml +2 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ services: - '@tempstore.shared' - '@datetime.time' - '@PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface' - '@package_manager.failure_marker' automatic_updates.cron_updater: class: Drupal\automatic_updates\CronUpdater arguments: Loading @@ -45,6 +46,7 @@ services: - '@tempstore.shared' - '@datetime.time' - '@PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface' - '@package_manager.failure_marker' automatic_updates.staged_projects_validator: class: Drupal\automatic_updates\Validator\StagedProjectsValidator arguments: Loading automatic_updates_extensions/automatic_updates_extensions.services.yml +1 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ services: - '@tempstore.shared' - '@datetime.time' - '@PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface' - '@package_manager.failure_marker' automatic_updates_extensions.validator.packages_installed_with_composer: class: Drupal\automatic_updates_extensions\Validator\PackagesInstalledWithComposerValidator arguments: Loading automatic_updates_extensions/tests/src/Kernel/AutomaticUpdatesExtensionsKernelTestBase.php +2 −1 Original line number Diff line number Diff line Loading @@ -114,7 +114,8 @@ abstract class AutomaticUpdatesExtensionsKernelTestBase extends AutomaticUpdates $this->container->get('event_dispatcher'), $this->container->get('tempstore.shared'), $this->container->get('datetime.time'), new TestPathFactory() new TestPathFactory(), $this->container->get('package_manager.failure_marker') ); } Loading package_manager/package_manager.services.yml +4 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,10 @@ services: - '%app.root%' - '@config.factory' - '@file_system' package_manager.failure_marker: class: Drupal\package_manager\FailureMarker arguments: - '@package_manager.path_locator' # Validators. package_manager.validator.composer_executable: Loading package_manager/src/FailureMarker.php 0 → 100644 +87 −0 Original line number Diff line number Diff line <?php namespace Drupal\package_manager; use Drupal\Component\Serialization\Json; use Drupal\package_manager\Exception\ApplyFailedException; /** * Handles failure marker file operation. * * The failure marker is a file placed in the active directory while staged * code is copied back into it, and then removed afterwards. This allows us to * know if a commit operation failed midway through, which could leave the site * code base in an indeterminate state -- which, in the worst case scenario, * might render Drupal unbootable. */ final class FailureMarker { /** * The path locator service. * * @var \Drupal\package_manager\PathLocator */ protected $pathLocator; /** * Constructs a FailureMarker object. * * @param \Drupal\package_manager\PathLocator $pathLocator * The path locator service. */ public function __construct(PathLocator $pathLocator) { $this->pathLocator = $pathLocator; } /** * Gets the marker file path. * * @return string * The absolute path of the marker file. */ public function getPath(): string { return $this->pathLocator->getProjectRoot() . '/PACKAGE_MANAGER_FAILURE.json'; } /** * Deletes the marker file. */ public function clear(): void { unlink($this->getPath()); } /** * Writes data to marker file. * * @param \Drupal\package_manager\Stage $stage * The stage. * @param string $message * Failure message to be added. */ public function write(Stage $stage, string $message): void { $data = [ 'stage_class' => get_class($stage), 'stage_file' => (new \ReflectionObject($stage))->getFileName(), 'message' => $message, ]; file_put_contents($this->getPath(), Json::encode($data)); } /** * Asserts the failure file doesn't exist. * * @throws \Drupal\package_manager\Exception\ApplyFailedException * Thrown if the marker file exists. */ public function assertNotExists(): void { $path = $this->getPath(); if (file_exists($path)) { $data = file_get_contents($path); $data = Json::decode($data); throw new ApplyFailedException($data['message']); } } } Loading
automatic_updates.services.yml +2 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ services: - '@tempstore.shared' - '@datetime.time' - '@PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface' - '@package_manager.failure_marker' automatic_updates.cron_updater: class: Drupal\automatic_updates\CronUpdater arguments: Loading @@ -45,6 +46,7 @@ services: - '@tempstore.shared' - '@datetime.time' - '@PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface' - '@package_manager.failure_marker' automatic_updates.staged_projects_validator: class: Drupal\automatic_updates\Validator\StagedProjectsValidator arguments: Loading
automatic_updates_extensions/automatic_updates_extensions.services.yml +1 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ services: - '@tempstore.shared' - '@datetime.time' - '@PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface' - '@package_manager.failure_marker' automatic_updates_extensions.validator.packages_installed_with_composer: class: Drupal\automatic_updates_extensions\Validator\PackagesInstalledWithComposerValidator arguments: Loading
automatic_updates_extensions/tests/src/Kernel/AutomaticUpdatesExtensionsKernelTestBase.php +2 −1 Original line number Diff line number Diff line Loading @@ -114,7 +114,8 @@ abstract class AutomaticUpdatesExtensionsKernelTestBase extends AutomaticUpdates $this->container->get('event_dispatcher'), $this->container->get('tempstore.shared'), $this->container->get('datetime.time'), new TestPathFactory() new TestPathFactory(), $this->container->get('package_manager.failure_marker') ); } Loading
package_manager/package_manager.services.yml +4 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,10 @@ services: - '%app.root%' - '@config.factory' - '@file_system' package_manager.failure_marker: class: Drupal\package_manager\FailureMarker arguments: - '@package_manager.path_locator' # Validators. package_manager.validator.composer_executable: Loading
package_manager/src/FailureMarker.php 0 → 100644 +87 −0 Original line number Diff line number Diff line <?php namespace Drupal\package_manager; use Drupal\Component\Serialization\Json; use Drupal\package_manager\Exception\ApplyFailedException; /** * Handles failure marker file operation. * * The failure marker is a file placed in the active directory while staged * code is copied back into it, and then removed afterwards. This allows us to * know if a commit operation failed midway through, which could leave the site * code base in an indeterminate state -- which, in the worst case scenario, * might render Drupal unbootable. */ final class FailureMarker { /** * The path locator service. * * @var \Drupal\package_manager\PathLocator */ protected $pathLocator; /** * Constructs a FailureMarker object. * * @param \Drupal\package_manager\PathLocator $pathLocator * The path locator service. */ public function __construct(PathLocator $pathLocator) { $this->pathLocator = $pathLocator; } /** * Gets the marker file path. * * @return string * The absolute path of the marker file. */ public function getPath(): string { return $this->pathLocator->getProjectRoot() . '/PACKAGE_MANAGER_FAILURE.json'; } /** * Deletes the marker file. */ public function clear(): void { unlink($this->getPath()); } /** * Writes data to marker file. * * @param \Drupal\package_manager\Stage $stage * The stage. * @param string $message * Failure message to be added. */ public function write(Stage $stage, string $message): void { $data = [ 'stage_class' => get_class($stage), 'stage_file' => (new \ReflectionObject($stage))->getFileName(), 'message' => $message, ]; file_put_contents($this->getPath(), Json::encode($data)); } /** * Asserts the failure file doesn't exist. * * @throws \Drupal\package_manager\Exception\ApplyFailedException * Thrown if the marker file exists. */ public function assertNotExists(): void { $path = $this->getPath(); if (file_exists($path)) { $data = file_get_contents($path); $data = Json::decode($data); throw new ApplyFailedException($data['message']); } } }