[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |