[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/diffusion/conduit/ -> DiffusionDiffQueryConduitAPIMethod.php (source)

   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  }


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