diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -453,13 +453,10 @@ 'DifferentialGetRevisionCommentsConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetRevisionCommentsConduitAPIMethod.php', 'DifferentialGetRevisionConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetRevisionConduitAPIMethod.php', 'DifferentialGetWorkingCopy' => 'applications/differential/DifferentialGetWorkingCopy.php', - 'DifferentialGitHubLandingStrategy' => 'applications/differential/landing/DifferentialGitHubLandingStrategy.php', 'DifferentialGitSVNIDCommitMessageField' => 'applications/differential/field/DifferentialGitSVNIDCommitMessageField.php', 'DifferentialHarbormasterField' => 'applications/differential/customfield/DifferentialHarbormasterField.php', 'DifferentialHiddenComment' => 'applications/differential/storage/DifferentialHiddenComment.php', 'DifferentialHostField' => 'applications/differential/customfield/DifferentialHostField.php', - 'DifferentialHostedGitLandingStrategy' => 'applications/differential/landing/DifferentialHostedGitLandingStrategy.php', - 'DifferentialHostedMercurialLandingStrategy' => 'applications/differential/landing/DifferentialHostedMercurialLandingStrategy.php', 'DifferentialHovercardEngineExtension' => 'applications/differential/engineextension/DifferentialHovercardEngineExtension.php', 'DifferentialHunk' => 'applications/differential/storage/DifferentialHunk.php', 'DifferentialHunkParser' => 'applications/differential/parser/DifferentialHunkParser.php', @@ -472,8 +469,6 @@ 'DifferentialInlineCommentQuery' => 'applications/differential/query/DifferentialInlineCommentQuery.php', 'DifferentialJIRAIssuesCommitMessageField' => 'applications/differential/field/DifferentialJIRAIssuesCommitMessageField.php', 'DifferentialJIRAIssuesField' => 'applications/differential/customfield/DifferentialJIRAIssuesField.php', - 'DifferentialLandingActionMenuEventListener' => 'applications/differential/landing/DifferentialLandingActionMenuEventListener.php', - 'DifferentialLandingStrategy' => 'applications/differential/landing/DifferentialLandingStrategy.php', 'DifferentialLegacyHunk' => 'applications/differential/storage/DifferentialLegacyHunk.php', 'DifferentialLineAdjustmentMap' => 'applications/differential/parser/DifferentialLineAdjustmentMap.php', 'DifferentialLintField' => 'applications/differential/customfield/DifferentialLintField.php', @@ -548,7 +543,6 @@ 'DifferentialRevisionHeraldFieldGroup' => 'applications/differential/herald/DifferentialRevisionHeraldFieldGroup.php', 'DifferentialRevisionIDCommitMessageField' => 'applications/differential/field/DifferentialRevisionIDCommitMessageField.php', 'DifferentialRevisionInlinesController' => 'applications/differential/controller/DifferentialRevisionInlinesController.php', - 'DifferentialRevisionLandController' => 'applications/differential/controller/DifferentialRevisionLandController.php', 'DifferentialRevisionListController' => 'applications/differential/controller/DifferentialRevisionListController.php', 'DifferentialRevisionListView' => 'applications/differential/view/DifferentialRevisionListView.php', 'DifferentialRevisionMailReceiver' => 'applications/differential/mail/DifferentialRevisionMailReceiver.php', @@ -5411,13 +5405,10 @@ 'DifferentialGetRevisionCommentsConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetRevisionConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetWorkingCopy' => 'Phobject', - 'DifferentialGitHubLandingStrategy' => 'DifferentialLandingStrategy', 'DifferentialGitSVNIDCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialHarbormasterField' => 'DifferentialCustomField', 'DifferentialHiddenComment' => 'DifferentialDAO', 'DifferentialHostField' => 'DifferentialCustomField', - 'DifferentialHostedGitLandingStrategy' => 'DifferentialLandingStrategy', - 'DifferentialHostedMercurialLandingStrategy' => 'DifferentialLandingStrategy', 'DifferentialHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 'DifferentialHunk' => array( 'DifferentialDAO', @@ -5436,8 +5427,6 @@ 'DifferentialInlineCommentQuery' => 'PhabricatorOffsetPagedQuery', 'DifferentialJIRAIssuesCommitMessageField' => 'DifferentialCommitMessageCustomField', 'DifferentialJIRAIssuesField' => 'DifferentialStoredCustomField', - 'DifferentialLandingActionMenuEventListener' => 'PhabricatorEventListener', - 'DifferentialLandingStrategy' => 'Phobject', 'DifferentialLegacyHunk' => 'DifferentialHunk', 'DifferentialLineAdjustmentMap' => 'Phobject', 'DifferentialLintField' => 'DifferentialHarbormasterField', @@ -5529,7 +5518,6 @@ 'DifferentialRevisionHeraldFieldGroup' => 'HeraldFieldGroup', 'DifferentialRevisionIDCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialRevisionInlinesController' => 'DifferentialController', - 'DifferentialRevisionLandController' => 'DifferentialController', 'DifferentialRevisionListController' => 'DifferentialController', 'DifferentialRevisionListView' => 'AphrontView', 'DifferentialRevisionMailReceiver' => 'PhabricatorObjectMailReceiver', diff --git a/src/applications/differential/application/PhabricatorDifferentialApplication.php b/src/applications/differential/application/PhabricatorDifferentialApplication.php --- a/src/applications/differential/application/PhabricatorDifferentialApplication.php +++ b/src/applications/differential/application/PhabricatorDifferentialApplication.php @@ -41,12 +41,6 @@ return "\xE2\x9A\x99"; } - public function getEventListeners() { - return array( - new DifferentialLandingActionMenuEventListener(), - ); - } - public function getOverview() { return pht( 'Differential is a **code review application** which allows '. @@ -69,8 +63,6 @@ => 'DifferentialRevisionEditController', $this->getEditRoutePattern('attach/(?P[^/]+)/to/') => 'DifferentialRevisionEditController', - 'land/(?:(?P[1-9]\d*))/(?P[^/]+)/' - => 'DifferentialRevisionLandController', 'closedetails/(?P[^/]+)/' => 'DifferentialRevisionCloseDetailsController', 'update/(?P[1-9]\d*)/' diff --git a/src/applications/differential/controller/DifferentialRevisionLandController.php b/src/applications/differential/controller/DifferentialRevisionLandController.php deleted file mode 100644 --- a/src/applications/differential/controller/DifferentialRevisionLandController.php +++ /dev/null @@ -1,157 +0,0 @@ -getViewer(); - $revision_id = $request->getURIData('id'); - $strategy_class = $request->getURIData('strategy'); - - $revision = id(new DifferentialRevisionQuery()) - ->withIDs(array($revision_id)) - ->setViewer($viewer) - ->executeOne(); - if (!$revision) { - return new Aphront404Response(); - } - - if (is_subclass_of($strategy_class, 'DifferentialLandingStrategy')) { - $this->pushStrategy = newv($strategy_class, array()); - } else { - throw new Exception( - pht( - "Strategy type must be a valid class name and must subclass ". - "%s. '%s' is not a subclass of %s", - 'DifferentialLandingStrategy', - $strategy_class, - 'DifferentialLandingStrategy')); - } - - if ($request->isDialogFormPost()) { - $response = null; - $text = ''; - try { - $response = $this->attemptLand($revision, $request); - $title = pht('Success!'); - $text = pht('Revision was successfully landed.'); - } catch (Exception $ex) { - $title = pht('Failed to land revision'); - if ($ex instanceof PhutilProxyException) { - $text = hsprintf( - '%s:
%s
', - $ex->getMessage(), - $ex->getPreviousException()->getMessage()); - } else { - $text = phutil_tag('pre', array(), $ex->getMessage()); - } - $text = id(new PHUIInfoView()) - ->appendChild($text); - } - - if ($response instanceof AphrontDialogView) { - $dialog = $response; - } else { - $dialog = id(new AphrontDialogView()) - ->setUser($viewer) - ->setTitle($title) - ->appendChild(phutil_tag('p', array(), $text)) - ->addCancelButton('/D'.$revision_id, pht('Done')); - } - return id(new AphrontDialogResponse())->setDialog($dialog); - } - - $is_disabled = $this->pushStrategy->isActionDisabled( - $viewer, - $revision, - $revision->getRepository()); - if ($is_disabled) { - if (is_string($is_disabled)) { - $explain = $is_disabled; - } else { - $explain = pht('This action is not currently enabled.'); - } - $dialog = id(new AphrontDialogView()) - ->setUser($viewer) - ->setTitle(pht("Can't land revision")) - ->appendChild($explain) - ->addCancelButton('/D'.$revision_id); - - return id(new AphrontDialogResponse())->setDialog($dialog); - } - - - $prompt = hsprintf('%s

%s', - pht( - 'This will squash and rebase revision %s, and push it to '. - 'the default / master branch.', - $revision_id), - pht('It is an experimental feature and may not work.')); - - $dialog = id(new AphrontDialogView()) - ->setUser($viewer) - ->setTitle(pht('Land Revision %s?', $revision_id)) - ->appendChild($prompt) - ->setSubmitURI($request->getRequestURI()) - ->addSubmitButton(pht('Land it!')) - ->addCancelButton('/D'.$revision_id); - - return id(new AphrontDialogResponse())->setDialog($dialog); - } - - private function attemptLand($revision, $request) { - $status = $revision->getStatus(); - if ($status != ArcanistDifferentialRevisionStatus::ACCEPTED) { - throw new Exception(pht('Only Accepted revisions can be landed.')); - } - - $repository = $revision->getRepository(); - - if ($repository === null) { - throw new Exception(pht('Revision is not attached to a repository.')); - } - - $can_push = PhabricatorPolicyFilter::hasCapability( - $request->getUser(), - $repository, - DiffusionPushCapability::CAPABILITY); - - if (!$can_push) { - throw new Exception( - pht('You do not have permission to push to this repository.')); - } - - $lock = $this->lockRepository($repository); - - try { - $response = $this->pushStrategy->processLandRequest( - $request, - $revision, - $repository); - } catch (Exception $e) { - $lock->unlock(); - throw $e; - } - - $lock->unlock(); - - $looksoon = new ConduitCall( - 'diffusion.looksoon', - array( - 'repositories' => array($repository->getPHID()), - )); - $looksoon->setUser($request->getUser()); - $looksoon->execute(); - - return $response; - } - - private function lockRepository($repository) { - $lock_name = __CLASS__.':'.($repository->getPHID()); - $lock = PhabricatorGlobalLock::newLock($lock_name); - $lock->lock(); - return $lock; - } - -} diff --git a/src/applications/differential/landing/DifferentialGitHubLandingStrategy.php b/src/applications/differential/landing/DifferentialGitHubLandingStrategy.php deleted file mode 100644 --- a/src/applications/differential/landing/DifferentialGitHubLandingStrategy.php +++ /dev/null @@ -1,186 +0,0 @@ -getUser(); - $this->init($viewer, $repository); - - $workspace = $this->getGitWorkspace($repository); - - try { - id(new DifferentialHostedGitLandingStrategy()) - ->commitRevisionToWorkspace($revision, $workspace, $viewer); - } catch (Exception $e) { - throw new PhutilProxyException(pht('Failed to commit patch.'), $e); - } - - try { - $this->pushWorkspaceRepository($repository, $workspace); - } catch (Exception $e) { - // If it's a permission problem, we know more than git. - $dialog = $this->verifyRemotePermissions($viewer, $revision, $repository); - if ($dialog) { - return $dialog; - } - - // Else, throw what git said. - throw new PhutilProxyException( - pht('Failed to push changes upstream.'), - $e); - } - } - - /** - * Returns PhabricatorActionView or an array of PhabricatorActionView or null. - */ - public function createMenuItem( - PhabricatorUser $viewer, - DifferentialRevision $revision, - PhabricatorRepository $repository) { - - // TODO: This temporarily disables this action, because it doesn't work - // and is confusing to users. If you want to use it, comment out this line - // for now and we'll provide real support eventually. - return; - - $vcs = $repository->getVersionControlSystem(); - if ($vcs !== PhabricatorRepositoryType::REPOSITORY_TYPE_GIT) { - return; - } - - if ($repository->isHosted()) { - return; - } - - try { - // These throw when failing. - $this->init($viewer, $repository); - $this->findGitHubRepo($repository); - } catch (Exception $e) { - return; - } - - return $this->createActionView($revision, pht('Land to GitHub')) - ->setIcon('fa-cloud-upload'); - } - - public function pushWorkspaceRepository( - PhabricatorRepository $repository, - ArcanistRepositoryAPI $workspace) { - - $token = $this->getAccessToken(); - - $github_repo = $this->findGitHubRepo($repository); - - $remote = urisprintf( - 'https://%s:x-oauth-basic@%s/%s.git', - $token, - $this->provider->getProviderDomain(), - $github_repo); - - $workspace->execxLocal( - 'push %P HEAD:master', - new PhutilOpaqueEnvelope($remote)); - } - - private function init($viewer, $repository) { - $repo_uri = $repository->getRemoteURIObject(); - $repo_domain = $repo_uri->getDomain(); - - $this->account = id(new PhabricatorExternalAccountQuery()) - ->setViewer($viewer) - ->withUserPHIDs(array($viewer->getPHID())) - ->withAccountTypes(array('github')) - ->withAccountDomains(array($repo_domain)) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->executeOne(); - - if (!$this->account) { - throw new Exception( - pht('No matching GitHub account found for %s.', $repo_domain)); - } - - $this->provider = PhabricatorAuthProvider::getEnabledProviderByKey( - $this->account->getProviderKey()); - if (!$this->provider) { - throw new Exception( - pht('GitHub provider for %s is not enabled.', $repo_domain)); - } - } - - private function findGitHubRepo(PhabricatorRepository $repository) { - $repo_uri = $repository->getRemoteURIObject(); - - $repo_path = $repo_uri->getPath(); - - if (substr($repo_path, -4) == '.git') { - $repo_path = substr($repo_path, 0, -4); - } - $repo_path = ltrim($repo_path, '/'); - - return $repo_path; - } - - private function getAccessToken() { - return $this->provider->getOAuthAccessToken($this->account); - } - - private function verifyRemotePermissions($viewer, $revision, $repository) { - $github_user = $this->account->getUsername(); - $github_repo = $this->findGitHubRepo($repository); - - $uri = urisprintf( - 'https://api.github.com/repos/%s/collaborators/%s', - $github_repo, - $github_user); - - $uri = new PhutilURI($uri); - $uri->setQueryParam('access_token', $this->getAccessToken()); - list($status, $body, $headers) = id(new HTTPSFuture($uri))->resolve(); - - // Likely status codes: - // 204 No Content: Has permissions. Token might be too weak. - // 404 Not Found: Not a collaborator. - // 401 Unauthorized: Token is bad/revoked. - - $no_permission = ($status->getStatusCode() == 404); - - if ($no_permission) { - throw new Exception( - pht( - "You don't have permission to push to this repository. ". - "Push permissions for this repository are managed on GitHub.")); - } - - $scopes = BaseHTTPFuture::getHeader($headers, 'X-OAuth-Scopes'); - if (strpos($scopes, 'public_repo') === false) { - $provider_key = $this->provider->getProviderKey(); - $refresh_token_uri = new PhutilURI("/auth/refresh/{$provider_key}/"); - $refresh_token_uri->setQueryParam('scope', 'public_repo'); - - return id(new AphrontDialogView()) - ->setUser($viewer) - ->setTitle(pht('Stronger token needed')) - ->appendChild(pht( - 'In order to complete this action, you need a '. - 'stronger GitHub token.')) - ->setSubmitURI($refresh_token_uri) - ->addCancelButton('/D'.$revision->getId()) - ->setDisableWorkflowOnSubmit(true) - ->addSubmitButton(pht('Refresh Account Link')); - } - } -} diff --git a/src/applications/differential/landing/DifferentialHostedGitLandingStrategy.php b/src/applications/differential/landing/DifferentialHostedGitLandingStrategy.php deleted file mode 100644 --- a/src/applications/differential/landing/DifferentialHostedGitLandingStrategy.php +++ /dev/null @@ -1,127 +0,0 @@ -getUser(); - $workspace = $this->getGitWorkspace($repository); - - try { - $this->commitRevisionToWorkspace($revision, $workspace, $viewer); - } catch (Exception $e) { - throw new PhutilProxyException( - pht('Failed to commit patch.'), - $e); - } - - try { - $this->pushWorkspaceRepository($repository, $workspace, $viewer); - } catch (Exception $e) { - throw new PhutilProxyException( - pht('Failed to push changes upstream.'), - $e); - } - } - - public function commitRevisionToWorkspace( - DifferentialRevision $revision, - ArcanistRepositoryAPI $workspace, - PhabricatorUser $user) { - - $diff_id = $revision->loadActiveDiff()->getID(); - - $call = new ConduitCall( - 'differential.getrawdiff', - array( - 'diffID' => $diff_id, - )); - - $call->setUser($user); - $raw_diff = $call->execute(); - - $missing_binary = - "\nindex " - ."0000000000000000000000000000000000000000.." - ."0000000000000000000000000000000000000000\n"; - if (strpos($raw_diff, $missing_binary) !== false) { - throw new Exception(pht('Patch is missing content for a binary file')); - } - - $future = $workspace->execFutureLocal('apply --index -'); - $future->write($raw_diff); - $future->resolvex(); - - $workspace->reloadWorkingCopy(); - - $call = new ConduitCall( - 'differential.getcommitmessage', - array( - 'revision_id' => $revision->getID(), - )); - - $call->setUser($user); - $message = $call->execute(); - - $author = id(new PhabricatorUser())->loadOneWhere( - 'phid = %s', - $revision->getAuthorPHID()); - - $author_string = sprintf( - '%s <%s>', - $author->getRealName(), - $author->loadPrimaryEmailAddress()); - $author_date = $revision->getDateCreated(); - - $workspace->execxLocal( - '-c user.name=%s -c user.email=%s '. - 'commit --date=%s --author=%s '. - '--message=%s', - // -c will set the 'committer' - $user->getRealName(), - $user->loadPrimaryEmailAddress(), - $author_date, - $author_string, - $message); - } - - public function pushWorkspaceRepository( - PhabricatorRepository $repository, - ArcanistRepositoryAPI $workspace, - PhabricatorUser $user) { - - $workspace->execxLocal('push origin HEAD:master'); - } - - public function createMenuItem( - PhabricatorUser $viewer, - DifferentialRevision $revision, - PhabricatorRepository $repository) { - - $vcs = $repository->getVersionControlSystem(); - if ($vcs !== PhabricatorRepositoryType::REPOSITORY_TYPE_GIT) { - return; - } - - if (!$repository->isHosted()) { - return; - } - - if (!$repository->isWorkingCopyBare()) { - return; - } - - // TODO: This temporarily disables this action, because it doesn't work - // and is confusing to users. If you want to use it, comment out this line - // for now and we'll provide real support eventually. - return; - - return $this->createActionView( - $revision, - pht('Land to Hosted Repository')); - } -} diff --git a/src/applications/differential/landing/DifferentialHostedMercurialLandingStrategy.php b/src/applications/differential/landing/DifferentialHostedMercurialLandingStrategy.php deleted file mode 100644 --- a/src/applications/differential/landing/DifferentialHostedMercurialLandingStrategy.php +++ /dev/null @@ -1,106 +0,0 @@ -getUser(); - - $workspace = $this->getMercurialWorkspace($repository); - - try { - $this->commitRevisionToWorkspace($revision, $workspace, $viewer); - } catch (Exception $e) { - throw new PhutilProxyException(pht('Failed to commit patch.'), $e); - } - - try { - $this->pushWorkspaceRepository($repository, $workspace, $viewer); - } catch (Exception $e) { - throw new PhutilProxyException( - pht('Failed to push changes upstream.'), - $e); - } - } - - public function commitRevisionToWorkspace( - DifferentialRevision $revision, - ArcanistRepositoryAPI $workspace, - PhabricatorUser $user) { - - $diff_id = $revision->loadActiveDiff()->getID(); - - $call = new ConduitCall( - 'differential.getrawdiff', - array( - 'diffID' => $diff_id, - )); - - $call->setUser($user); - $raw_diff = $call->execute(); - - $future = $workspace->execFutureLocal('patch --no-commit -'); - $future->write($raw_diff); - $future->resolvex(); - - $workspace->reloadWorkingCopy(); - - $call = new ConduitCall( - 'differential.getcommitmessage', - array( - 'revision_id' => $revision->getID(), - )); - - $call->setUser($user); - $message = $call->execute(); - - $author = id(new PhabricatorUser())->loadOneWhere( - 'phid = %s', - $revision->getAuthorPHID()); - - $author_string = sprintf( - '%s <%s>', - $author->getRealName(), - $author->loadPrimaryEmailAddress()); - $author_date = $revision->getDateCreated(); - - $workspace->execxLocal( - 'commit --date=%s --user=%s '. - '--message=%s', - $author_date.' 0', - $author_string, - $message); - } - - - public function pushWorkspaceRepository( - PhabricatorRepository $repository, - ArcanistRepositoryAPI $workspace, - PhabricatorUser $user) { - - $workspace->execxLocal('push -b default'); - } - - public function createMenuItem( - PhabricatorUser $viewer, - DifferentialRevision $revision, - PhabricatorRepository $repository) { - - $vcs = $repository->getVersionControlSystem(); - if ($vcs !== PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL) { - return; - } - - if (!$repository->isHosted()) { - return; - } - - return $this->createActionView( - $revision, - pht('Land to Hosted Repository')); - } -} diff --git a/src/applications/differential/landing/DifferentialLandingActionMenuEventListener.php b/src/applications/differential/landing/DifferentialLandingActionMenuEventListener.php deleted file mode 100644 --- a/src/applications/differential/landing/DifferentialLandingActionMenuEventListener.php +++ /dev/null @@ -1,81 +0,0 @@ -listen(PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS); - } - - public function handleEvent(PhutilEvent $event) { - switch ($event->getType()) { - case PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS: - $this->handleActionsEvent($event); - break; - } - } - - private function handleActionsEvent(PhutilEvent $event) { - $object = $event->getValue('object'); - if ($object instanceof DifferentialRevision) { - $this->renderRevisionAction($event); - } - } - - private function renderRevisionAction(PhutilEvent $event) { - $viewer = $event->getUser(); - - if (!$this->canUseApplication($viewer)) { - return null; - } - - $revision = $event->getValue('object'); - - $repository = $revision->getRepository(); - if ($repository === null) { - return null; - } - - if ($repository->canPerformAutomation()) { - $revision_id = $revision->getID(); - - $op = new DrydockLandRepositoryOperation(); - $barrier = $op->getBarrierToLanding($viewer, $revision); - - if ($barrier) { - $can_land = false; - } else { - $can_land = true; - } - - $action = id(new PhabricatorActionView()) - ->setName(pht('Land Revision')) - ->setIcon('fa-fighter-jet') - ->setHref("/differential/revision/operation/{$revision_id}/") - ->setWorkflow(true) - ->setDisabled(!$can_land); - - - $this->addActionMenuItems($event, $action); - } - - $strategies = id(new PhutilClassMapQuery()) - ->setAncestorClass('DifferentialLandingStrategy') - ->execute(); - - foreach ($strategies as $strategy) { - $action = $strategy->createMenuItem($viewer, $revision, $repository); - if ($action == null) { - continue; - } - if ($strategy->isActionDisabled($viewer, $revision, $repository)) { - $action->setDisabled(true); - } - $this->addActionMenuItems($event, $action); - } - } - -} diff --git a/src/applications/differential/landing/DifferentialLandingStrategy.php b/src/applications/differential/landing/DifferentialLandingStrategy.php deleted file mode 100644 --- a/src/applications/differential/landing/DifferentialLandingStrategy.php +++ /dev/null @@ -1,87 +0,0 @@ -getId(); - return id(new PhabricatorActionView()) - ->setRenderAsForm(true) - ->setWorkflow(true) - ->setName($name) - ->setHref("/differential/revision/land/{$revision_id}/{$strategy}/"); - } - - /** - * Check if this action should be disabled, and explain why. - * - * By default, this method checks for push permissions, and for the - * revision being Accepted. - * - * @return False for "not disabled"; human-readable text explaining why, if - * it is disabled. - */ - public function isActionDisabled( - PhabricatorUser $viewer, - DifferentialRevision $revision, - PhabricatorRepository $repository) { - - $status = $revision->getStatus(); - if ($status != ArcanistDifferentialRevisionStatus::ACCEPTED) { - return pht('Only Accepted revisions can be landed.'); - } - - if (!PhabricatorPolicyFilter::hasCapability( - $viewer, - $repository, - DiffusionPushCapability::CAPABILITY)) { - return pht('You do not have permissions to push to this repository.'); - } - - return false; - } - - /** - * Might break if repository is not Git. - */ - protected function getGitWorkspace(PhabricatorRepository $repository) { - try { - return DifferentialGetWorkingCopy::getCleanGitWorkspace($repository); - } catch (Exception $e) { - throw new PhutilProxyException( - pht('Failed to allocate a workspace.'), - $e); - } - } - - /** - * Might break if repository is not Mercurial. - */ - protected function getMercurialWorkspace(PhabricatorRepository $repository) { - try { - return DifferentialGetWorkingCopy::getCleanMercurialWorkspace( - $repository); - } catch (Exception $e) { - throw new PhutilProxyException( - pht('Failed to allocate a workspace.'), - $e); - } - } - -}