Path: blob/master/src/applications/diffusion/conduit/DiffusionDiffQueryConduitAPIMethod.php
12242 views
<?php12final class DiffusionDiffQueryConduitAPIMethod3extends DiffusionQueryConduitAPIMethod {45private $effectiveCommit;67public function getAPIMethodName() {8return 'diffusion.diffquery';9}1011public function getMethodDescription() {12return pht(13'Get diff information from a repository for a specific path at an '.14'(optional) commit.');15}1617protected function defineReturnType() {18return 'array';19}2021protected function defineCustomParamTypes() {22return array(23'path' => 'required string',24'commit' => 'optional string',25);26}2728protected function getResult(ConduitAPIRequest $request) {29$result = parent::getResult($request);3031return array(32'changes' => mpull($result, 'toDictionary'),33'effectiveCommit' => $this->getEffectiveCommit($request),34);35}3637protected function getGitResult(ConduitAPIRequest $request) {38return $this->getGitOrMercurialResult($request);39}4041protected function getMercurialResult(ConduitAPIRequest $request) {42return $this->getGitOrMercurialResult($request);43}4445/**46* NOTE: We have to work particularly hard for SVN as compared to other VCS.47* That's okay but means this shares little code with the other VCS.48*/49protected function getSVNResult(ConduitAPIRequest $request) {50$drequest = $this->getDiffusionRequest();51$repository = $drequest->getRepository();5253$effective_commit = $this->getEffectiveCommit($request);54if (!$effective_commit) {55return $this->getEmptyResult();56}5758$drequest = clone $drequest;59$drequest->updateSymbolicCommit($effective_commit);6061$path_change_query = DiffusionPathChangeQuery::newFromDiffusionRequest(62$drequest);63$path_changes = $path_change_query->loadChanges();6465$path = null;66foreach ($path_changes as $change) {67if ($change->getPath() == $drequest->getPath()) {68$path = $change;69}70}7172if (!$path) {73return $this->getEmptyResult();74}7576$change_type = $path->getChangeType();77switch ($change_type) {78case DifferentialChangeType::TYPE_MULTICOPY:79case DifferentialChangeType::TYPE_DELETE:80if ($path->getTargetPath()) {81$old = array(82$path->getTargetPath(),83$path->getTargetCommitIdentifier(),84);85} else {86$old = array($path->getPath(), $path->getCommitIdentifier() - 1);87}88$old_name = $path->getPath();89$new_name = '';90$new = null;91break;92case DifferentialChangeType::TYPE_ADD:93$old = null;94$new = array($path->getPath(), $path->getCommitIdentifier());95$old_name = '';96$new_name = $path->getPath();97break;98case DifferentialChangeType::TYPE_MOVE_HERE:99case DifferentialChangeType::TYPE_COPY_HERE:100$old = array(101$path->getTargetPath(),102$path->getTargetCommitIdentifier(),103);104$new = array($path->getPath(), $path->getCommitIdentifier());105$old_name = $path->getTargetPath();106$new_name = $path->getPath();107break;108case DifferentialChangeType::TYPE_MOVE_AWAY:109$old = array(110$path->getPath(),111$path->getCommitIdentifier() - 1,112);113$old_name = $path->getPath();114$new_name = null;115$new = null;116break;117default:118$old = array($path->getPath(), $path->getCommitIdentifier() - 1);119$new = array($path->getPath(), $path->getCommitIdentifier());120$old_name = $path->getPath();121$new_name = $path->getPath();122break;123}124125$futures = array(126'old' => $this->buildSVNContentFuture($old),127'new' => $this->buildSVNContentFuture($new),128);129$futures = array_filter($futures);130131foreach (new FutureIterator($futures) as $key => $future) {132$stdout = '';133try {134list($stdout) = $future->resolvex();135} catch (CommandException $e) {136if ($path->getFileType() != DifferentialChangeType::FILE_DIRECTORY) {137throw $e;138}139}140$futures[$key] = $stdout;141}142143$old_data = idx($futures, 'old', '');144$new_data = idx($futures, 'new', '');145146$engine = new PhabricatorDifferenceEngine();147$engine->setOldName($old_name);148$engine->setNewName($new_name);149$raw_diff = $engine->generateRawDiffFromFileContent($old_data, $new_data);150151$arcanist_changes = DiffusionPathChange::convertToArcanistChanges(152$path_changes);153154$parser = $this->getDefaultParser();155$parser->setChanges($arcanist_changes);156$parser->forcePath($path->getPath());157$changes = $parser->parseDiff($raw_diff);158159$change = $changes[$path->getPath()];160161return array($change);162}163164private function getEffectiveCommit(ConduitAPIRequest $request) {165if ($this->effectiveCommit === null) {166$drequest = $this->getDiffusionRequest();167168$path = $drequest->getPath();169$result = DiffusionQuery::callConduitWithDiffusionRequest(170$request->getUser(),171$drequest,172'diffusion.lastmodifiedquery',173array(174'paths' => array($path => $drequest->getStableCommit()),175));176177$this->effectiveCommit = idx($result, $path);178}179180return $this->effectiveCommit;181}182183private function buildSVNContentFuture($spec) {184if (!$spec) {185return null;186}187188$drequest = $this->getDiffusionRequest();189$repository = $drequest->getRepository();190191list($ref, $rev) = $spec;192return $repository->getRemoteCommandFuture(193'cat %s',194$repository->getSubversionPathURI($ref, $rev));195}196197private function getGitOrMercurialResult(ConduitAPIRequest $request) {198$drequest = $this->getDiffusionRequest();199$repository = $drequest->getRepository();200201$effective_commit = $this->getEffectiveCommit($request);202if (!$effective_commit) {203return $this->getEmptyResult();204}205206$raw_query = DiffusionRawDiffQuery::newFromDiffusionRequest($drequest)207->setAnchorCommit($effective_commit);208209$raw_diff = $raw_query->executeInline();210if (!$raw_diff) {211return $this->getEmptyResult();212}213214$parser = $this->getDefaultParser();215$changes = $parser->parseDiff($raw_diff);216217return $changes;218}219220private function getDefaultParser() {221$drequest = $this->getDiffusionRequest();222$repository = $drequest->getRepository();223224$parser = new ArcanistDiffParser();225$try_encoding = $repository->getDetail('encoding');226if ($try_encoding) {227$parser->setTryEncoding($try_encoding);228}229$parser->setDetectBinaryFiles(true);230231return $parser;232}233234private function getEmptyResult() {235return array();236}237238}239240241