diff --git a/src/events/constant/ArcanistEventType.php b/src/events/constant/ArcanistEventType.php index 26dfa260..8c988dbd 100644 --- a/src/events/constant/ArcanistEventType.php +++ b/src/events/constant/ArcanistEventType.php @@ -10,4 +10,6 @@ final class ArcanistEventType extends PhutilEventType { const TYPE_DIFF_WASCREATED = 'diff.wasCreated'; const TYPE_REVISION_WILLCREATEREVISION = 'revision.willCreateRevision'; + + const TYPE_LAND_WILLPUSHREVISION = 'land.willPushRevision'; } diff --git a/src/workflow/ArcanistLandWorkflow.php b/src/workflow/ArcanistLandWorkflow.php index 1a3f9a2e..0aa674b1 100644 --- a/src/workflow/ArcanistLandWorkflow.php +++ b/src/workflow/ArcanistLandWorkflow.php @@ -782,6 +782,18 @@ EOTEXT } } + // We dispatch this event so we can run checks on the merged revision, right + // before it gets pushed out. It's easier to do this in arc land than to + // try to hook into git/hg. + try { + $this->dispatchEvent( + ArcanistEventType::TYPE_LAND_WILLPUSHREVISION, + array()); + } catch (Exception $ex) { + $this->executeCleanupAfterFailedPush(); + throw $ex; + } + if ($this->getArgument('hold')) { echo phutil_console_format( "Holding change in **%s**: it has NOT been pushed yet.\n", @@ -818,9 +830,8 @@ EOTEXT if ($err) { echo phutil_console_format("** PUSH FAILED! **\n"); + $this->executeCleanupAfterFailedPush(); if ($this->isGit) { - $repository_api->execxLocal('reset --hard HEAD^'); - $this->restoreBranch(); throw new ArcanistUsageException( "'{$cmd}' failed! Fix the error and run 'arc land' again."); } @@ -841,6 +852,14 @@ EOTEXT } } + private function executeCleanupAfterFailedPush() { + if ($this->isGit) { + $repository_api = $this->getRepositoryAPI(); + $repository_api->execxLocal('reset --hard HEAD^'); + $this->restoreBranch(); + } + } + private function cleanupBranch() { $repository_api = $this->getRepositoryAPI();