[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/differential/controller/ -> DifferentialRevisionLandController.php (source)

   1  <?php
   2  
   3  final class DifferentialRevisionLandController extends DifferentialController {
   4  
   5    private $revisionID;
   6    private $strategyClass;
   7    private $pushStrategy;
   8  
   9    public function willProcessRequest(array $data) {
  10      $this->revisionID = $data['id'];
  11      $this->strategyClass = $data['strategy'];
  12    }
  13  
  14    public function processRequest() {
  15      $request = $this->getRequest();
  16      $viewer = $request->getUser();
  17  
  18      $revision_id = $this->revisionID;
  19  
  20      $revision = id(new DifferentialRevisionQuery())
  21        ->withIDs(array($revision_id))
  22        ->setViewer($viewer)
  23        ->executeOne();
  24      if (!$revision) {
  25        return new Aphront404Response();
  26      }
  27  
  28      if (is_subclass_of($this->strategyClass, 'DifferentialLandingStrategy')) {
  29        $this->pushStrategy = newv($this->strategyClass, array());
  30      } else {
  31        throw new Exception(
  32          "Strategy type must be a valid class name and must subclass ".
  33          "DifferentialLandingStrategy. ".
  34          "'{$this->strategyClass}' is not a subclass of ".
  35          "DifferentialLandingStrategy.");
  36      }
  37  
  38      if ($request->isDialogFormPost()) {
  39        $response = null;
  40        $text = '';
  41        try {
  42          $response = $this->attemptLand($revision, $request);
  43          $title = pht('Success!');
  44          $text = pht('Revision was successfully landed.');
  45        } catch (Exception $ex) {
  46          $title = pht('Failed to land revision');
  47          if ($ex instanceof PhutilProxyException) {
  48            $text = hsprintf(
  49              '%s:<br><pre>%s</pre>',
  50              $ex->getMessage(),
  51              $ex->getPreviousException()->getMessage());
  52          } else {
  53            $text = phutil_tag('pre', array(), $ex->getMessage());
  54          }
  55          $text = id(new AphrontErrorView())
  56             ->appendChild($text);
  57        }
  58  
  59        if ($response instanceof AphrontDialogView) {
  60          $dialog = $response;
  61        } else {
  62          $dialog = id(new AphrontDialogView())
  63            ->setUser($viewer)
  64            ->setTitle($title)
  65            ->appendChild(phutil_tag('p', array(), $text))
  66            ->addCancelButton('/D'.$revision_id, pht('Done'));
  67        }
  68        return id(new AphrontDialogResponse())->setDialog($dialog);
  69      }
  70  
  71      $is_disabled = $this->pushStrategy->isActionDisabled(
  72        $viewer,
  73        $revision,
  74        $revision->getRepository());
  75      if ($is_disabled) {
  76        if (is_string($is_disabled)) {
  77          $explain = $is_disabled;
  78        } else {
  79          $explain = pht('This action is not currently enabled.');
  80        }
  81        $dialog = id(new AphrontDialogView())
  82          ->setUser($viewer)
  83          ->setTitle(pht("Can't land revision"))
  84          ->appendChild($explain)
  85          ->addCancelButton('/D'.$revision_id);
  86  
  87        return id(new AphrontDialogResponse())->setDialog($dialog);
  88      }
  89  
  90  
  91      $prompt = hsprintf('%s<br><br>%s',
  92        pht(
  93          'This will squash and rebase revision %s, and push it to '.
  94            'the default / master branch.',
  95          $revision_id),
  96        pht('It is an experimental feature and may not work.'));
  97  
  98      $dialog = id(new AphrontDialogView())
  99        ->setUser($viewer)
 100        ->setTitle(pht('Land Revision %s?', $revision_id))
 101        ->appendChild($prompt)
 102        ->setSubmitURI($request->getRequestURI())
 103        ->addSubmitButton(pht('Land it!'))
 104        ->addCancelButton('/D'.$revision_id);
 105  
 106      return id(new AphrontDialogResponse())->setDialog($dialog);
 107    }
 108  
 109    private function attemptLand($revision, $request) {
 110      $status = $revision->getStatus();
 111      if ($status != ArcanistDifferentialRevisionStatus::ACCEPTED) {
 112        throw new Exception('Only Accepted revisions can be landed.');
 113      }
 114  
 115      $repository = $revision->getRepository();
 116  
 117      if ($repository === null) {
 118        throw new Exception('revision is not attached to a repository.');
 119      }
 120  
 121      $can_push = PhabricatorPolicyFilter::hasCapability(
 122        $request->getUser(),
 123        $repository,
 124        DiffusionPushCapability::CAPABILITY);
 125  
 126      if (!$can_push) {
 127        throw new Exception(
 128          pht('You do not have permission to push to this repository.'));
 129      }
 130  
 131      $lock = $this->lockRepository($repository);
 132  
 133      try {
 134        $response = $this->pushStrategy->processLandRequest(
 135          $request,
 136          $revision,
 137          $repository);
 138      } catch (Exception $e) {
 139        $lock->unlock();
 140        throw $e;
 141      }
 142  
 143      $lock->unlock();
 144  
 145      $looksoon = new ConduitCall(
 146        'diffusion.looksoon',
 147        array(
 148          'callsigns' => array($repository->getCallsign()),
 149        ));
 150      $looksoon->setUser($request->getUser());
 151      $looksoon->execute();
 152  
 153      return $response;
 154    }
 155  
 156    private function lockRepository($repository) {
 157      $lock_name = __CLASS__.':'.($repository->getCallsign());
 158      $lock = PhabricatorGlobalLock::newLock($lock_name);
 159      $lock->lock();
 160      return $lock;
 161    }
 162  
 163  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1