[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 final class DiffusionDiffQueryConduitAPIMethod 4 extends DiffusionQueryConduitAPIMethod { 5 6 private $effectiveCommit; 7 8 public function getAPIMethodName() { 9 return 'diffusion.diffquery'; 10 } 11 12 public function getMethodDescription() { 13 return 14 'Get diff information from a repository for a specific path at an '. 15 '(optional) commit.'; 16 } 17 18 public function defineReturnType() { 19 return 'array'; 20 } 21 22 protected function defineCustomParamTypes() { 23 return array( 24 'path' => 'required string', 25 'commit' => 'optional string', 26 ); 27 } 28 29 protected function getResult(ConduitAPIRequest $request) { 30 $result = parent::getResult($request); 31 32 return array( 33 'changes' => mpull($result, 'toDictionary'), 34 'effectiveCommit' => $this->getEffectiveCommit($request), 35 ); 36 } 37 38 protected function getGitResult(ConduitAPIRequest $request) { 39 return $this->getGitOrMercurialResult($request); 40 } 41 42 protected function getMercurialResult(ConduitAPIRequest $request) { 43 return $this->getGitOrMercurialResult($request); 44 } 45 46 /** 47 * NOTE: We have to work particularly hard for SVN as compared to other VCS. 48 * That's okay but means this shares little code with the other VCS. 49 */ 50 protected function getSVNResult(ConduitAPIRequest $request) { 51 $drequest = $this->getDiffusionRequest(); 52 $repository = $drequest->getRepository(); 53 54 $effective_commit = $this->getEffectiveCommit($request); 55 if (!$effective_commit) { 56 return $this->getEmptyResult(); 57 } 58 59 $drequest = clone $drequest; 60 $drequest->updateSymbolicCommit($effective_commit); 61 62 $path_change_query = DiffusionPathChangeQuery::newFromDiffusionRequest( 63 $drequest); 64 $path_changes = $path_change_query->loadChanges(); 65 66 $path = null; 67 foreach ($path_changes as $change) { 68 if ($change->getPath() == $drequest->getPath()) { 69 $path = $change; 70 } 71 } 72 73 if (!$path) { 74 return $this->getEmptyResult(); 75 } 76 77 $change_type = $path->getChangeType(); 78 switch ($change_type) { 79 case DifferentialChangeType::TYPE_MULTICOPY: 80 case DifferentialChangeType::TYPE_DELETE: 81 if ($path->getTargetPath()) { 82 $old = array( 83 $path->getTargetPath(), 84 $path->getTargetCommitIdentifier(), 85 ); 86 } else { 87 $old = array($path->getPath(), $path->getCommitIdentifier() - 1); 88 } 89 $old_name = $path->getPath(); 90 $new_name = ''; 91 $new = null; 92 break; 93 case DifferentialChangeType::TYPE_ADD: 94 $old = null; 95 $new = array($path->getPath(), $path->getCommitIdentifier()); 96 $old_name = ''; 97 $new_name = $path->getPath(); 98 break; 99 case DifferentialChangeType::TYPE_MOVE_HERE: 100 case DifferentialChangeType::TYPE_COPY_HERE: 101 $old = array( 102 $path->getTargetPath(), 103 $path->getTargetCommitIdentifier(), 104 ); 105 $new = array($path->getPath(), $path->getCommitIdentifier()); 106 $old_name = $path->getTargetPath(); 107 $new_name = $path->getPath(); 108 break; 109 case DifferentialChangeType::TYPE_MOVE_AWAY: 110 $old = array( 111 $path->getPath(), 112 $path->getCommitIdentifier() - 1, 113 ); 114 $old_name = $path->getPath(); 115 $new_name = null; 116 $new = null; 117 break; 118 default: 119 $old = array($path->getPath(), $path->getCommitIdentifier() - 1); 120 $new = array($path->getPath(), $path->getCommitIdentifier()); 121 $old_name = $path->getPath(); 122 $new_name = $path->getPath(); 123 break; 124 } 125 126 $futures = array( 127 'old' => $this->buildSVNContentFuture($old), 128 'new' => $this->buildSVNContentFuture($new), 129 ); 130 $futures = array_filter($futures); 131 132 foreach (Futures($futures) as $key => $future) { 133 $stdout = ''; 134 try { 135 list($stdout) = $future->resolvex(); 136 } catch (CommandException $e) { 137 if ($path->getFileType() != DifferentialChangeType::FILE_DIRECTORY) { 138 throw $e; 139 } 140 } 141 $futures[$key] = $stdout; 142 } 143 144 $old_data = idx($futures, 'old', ''); 145 $new_data = idx($futures, 'new', ''); 146 147 $engine = new PhabricatorDifferenceEngine(); 148 $engine->setOldName($old_name); 149 $engine->setNewName($new_name); 150 $raw_diff = $engine->generateRawDiffFromFileContent($old_data, $new_data); 151 152 $arcanist_changes = DiffusionPathChange::convertToArcanistChanges( 153 $path_changes); 154 155 $parser = $this->getDefaultParser(); 156 $parser->setChanges($arcanist_changes); 157 $parser->forcePath($path->getPath()); 158 $changes = $parser->parseDiff($raw_diff); 159 160 $change = $changes[$path->getPath()]; 161 162 return array($change); 163 } 164 165 private function getEffectiveCommit(ConduitAPIRequest $request) { 166 if ($this->effectiveCommit === null) { 167 $drequest = $this->getDiffusionRequest(); 168 169 $path = $drequest->getPath(); 170 $result = DiffusionQuery::callConduitWithDiffusionRequest( 171 $request->getUser(), 172 $drequest, 173 'diffusion.lastmodifiedquery', 174 array( 175 'paths' => array($path => $drequest->getStableCommit()), 176 )); 177 178 $this->effectiveCommit = idx($result, $path); 179 } 180 181 return $this->effectiveCommit; 182 } 183 184 private function buildSVNContentFuture($spec) { 185 if (!$spec) { 186 return null; 187 } 188 189 $drequest = $this->getDiffusionRequest(); 190 $repository = $drequest->getRepository(); 191 192 list($ref, $rev) = $spec; 193 return $repository->getRemoteCommandFuture( 194 'cat %s', 195 $repository->getSubversionPathURI($ref, $rev)); 196 } 197 198 private function getGitOrMercurialResult(ConduitAPIRequest $request) { 199 $drequest = $this->getDiffusionRequest(); 200 $repository = $drequest->getRepository(); 201 202 $effective_commit = $this->getEffectiveCommit($request); 203 if (!$effective_commit) { 204 return $this->getEmptyResult(1); 205 } 206 207 $raw_query = DiffusionRawDiffQuery::newFromDiffusionRequest($drequest) 208 ->setAnchorCommit($effective_commit); 209 210 $raw_diff = $raw_query->loadRawDiff(); 211 if (!$raw_diff) { 212 return $this->getEmptyResult(2); 213 } 214 215 $parser = $this->getDefaultParser(); 216 $changes = $parser->parseDiff($raw_diff); 217 218 return $changes; 219 } 220 221 private function getDefaultParser() { 222 $drequest = $this->getDiffusionRequest(); 223 $repository = $drequest->getRepository(); 224 225 $parser = new ArcanistDiffParser(); 226 $try_encoding = $repository->getDetail('encoding'); 227 if ($try_encoding) { 228 $parser->setTryEncoding($try_encoding); 229 } 230 $parser->setDetectBinaryFiles(true); 231 232 return $parser; 233 } 234 235 private function getEmptyResult() { 236 return array(); 237 } 238 239 }
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 |