2011-03-31 02:36:16 +02:00
|
|
|
<?php
|
|
|
|
|
Rename Conduit classes
Summary: Ref T5655. Rename Conduit classes and provide a `getAPIMethodName` method to declare the API method.
Test Plan:
```
> echo '{}' | arc --conduit-uri='http://phabricator.joshuaspence.com' call-conduit user.whoami
Waiting for JSON parameters on stdin...
{"error":null,"errorMessage":null,"response":{"phid":"PHID-USER-lioqffnwn6y475mu5ndb","userName":"josh","realName":"Joshua Spence","image":"http:\/\/phabricator.joshuaspence.com\/res\/1404425321T\/phabricator\/3eb28cd9\/rsrc\/image\/avatar.png","uri":"http:\/\/phabricator.joshuaspence.com\/p\/josh\/","roles":["admin","verified","approved","activated"]}}
```
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: epriestley, Korvin, hach-que
Maniphest Tasks: T5655
Differential Revision: https://secure.phabricator.com/D9991
2014-07-25 02:54:15 +02:00
|
|
|
final class DiffusionDiffQueryConduitAPIMethod
|
|
|
|
extends DiffusionQueryConduitAPIMethod {
|
2013-05-14 22:53:32 +02:00
|
|
|
|
|
|
|
private $effectiveCommit;
|
|
|
|
|
Rename Conduit classes
Summary: Ref T5655. Rename Conduit classes and provide a `getAPIMethodName` method to declare the API method.
Test Plan:
```
> echo '{}' | arc --conduit-uri='http://phabricator.joshuaspence.com' call-conduit user.whoami
Waiting for JSON parameters on stdin...
{"error":null,"errorMessage":null,"response":{"phid":"PHID-USER-lioqffnwn6y475mu5ndb","userName":"josh","realName":"Joshua Spence","image":"http:\/\/phabricator.joshuaspence.com\/res\/1404425321T\/phabricator\/3eb28cd9\/rsrc\/image\/avatar.png","uri":"http:\/\/phabricator.joshuaspence.com\/p\/josh\/","roles":["admin","verified","approved","activated"]}}
```
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: epriestley, Korvin, hach-que
Maniphest Tasks: T5655
Differential Revision: https://secure.phabricator.com/D9991
2014-07-25 02:54:15 +02:00
|
|
|
public function getAPIMethodName() {
|
|
|
|
return 'diffusion.diffquery';
|
|
|
|
}
|
|
|
|
|
2013-05-14 22:53:32 +02:00
|
|
|
public function getMethodDescription() {
|
|
|
|
return
|
|
|
|
'Get diff information from a repository for a specific path at an '.
|
|
|
|
'(optional) commit.';
|
|
|
|
}
|
|
|
|
|
|
|
|
public function defineReturnType() {
|
|
|
|
return 'array';
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function defineCustomParamTypes() {
|
|
|
|
return array(
|
|
|
|
'path' => 'required string',
|
|
|
|
'commit' => 'optional string',
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getResult(ConduitAPIRequest $request) {
|
|
|
|
$result = parent::getResult($request);
|
2011-03-31 02:36:16 +02:00
|
|
|
|
2013-05-14 22:53:32 +02:00
|
|
|
return array(
|
|
|
|
'changes' => mpull($result, 'toDictionary'),
|
2014-05-11 01:46:32 +02:00
|
|
|
'effectiveCommit' => $this->getEffectiveCommit($request),
|
|
|
|
);
|
2013-05-14 22:53:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
protected function getGitResult(ConduitAPIRequest $request) {
|
|
|
|
return $this->getGitOrMercurialResult($request);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getMercurialResult(ConduitAPIRequest $request) {
|
|
|
|
return $this->getGitOrMercurialResult($request);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* NOTE: We have to work particularly hard for SVN as compared to other VCS.
|
|
|
|
* That's okay but means this shares little code with the other VCS.
|
|
|
|
*/
|
|
|
|
protected function getSVNResult(ConduitAPIRequest $request) {
|
|
|
|
$drequest = $this->getDiffusionRequest();
|
2011-10-28 17:04:57 +02:00
|
|
|
$repository = $drequest->getRepository();
|
2011-03-31 02:36:16 +02:00
|
|
|
|
2013-05-14 22:53:32 +02:00
|
|
|
$effective_commit = $this->getEffectiveCommit($request);
|
2012-03-27 06:58:02 +02:00
|
|
|
if (!$effective_commit) {
|
2013-05-14 22:53:32 +02:00
|
|
|
return $this->getEmptyResult();
|
2011-04-03 02:11:51 +02:00
|
|
|
}
|
|
|
|
|
2012-03-27 06:58:02 +02:00
|
|
|
$drequest = clone $drequest;
|
2014-05-15 13:45:13 +02:00
|
|
|
$drequest->updateSymbolicCommit($effective_commit);
|
2012-03-27 06:58:02 +02:00
|
|
|
|
2011-03-31 02:36:16 +02:00
|
|
|
$path_change_query = DiffusionPathChangeQuery::newFromDiffusionRequest(
|
|
|
|
$drequest);
|
|
|
|
$path_changes = $path_change_query->loadChanges();
|
|
|
|
|
|
|
|
$path = null;
|
|
|
|
foreach ($path_changes as $change) {
|
|
|
|
if ($change->getPath() == $drequest->getPath()) {
|
|
|
|
$path = $change;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$path) {
|
2013-05-14 22:53:32 +02:00
|
|
|
return $this->getEmptyResult();
|
2011-03-31 02:36:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$change_type = $path->getChangeType();
|
|
|
|
switch ($change_type) {
|
|
|
|
case DifferentialChangeType::TYPE_MULTICOPY:
|
|
|
|
case DifferentialChangeType::TYPE_DELETE:
|
|
|
|
if ($path->getTargetPath()) {
|
|
|
|
$old = array(
|
|
|
|
$path->getTargetPath(),
|
|
|
|
$path->getTargetCommitIdentifier());
|
|
|
|
} else {
|
|
|
|
$old = array($path->getPath(), $path->getCommitIdentifier() - 1);
|
|
|
|
}
|
|
|
|
$old_name = $path->getPath();
|
|
|
|
$new_name = '';
|
|
|
|
$new = null;
|
|
|
|
break;
|
|
|
|
case DifferentialChangeType::TYPE_ADD:
|
|
|
|
$old = null;
|
|
|
|
$new = array($path->getPath(), $path->getCommitIdentifier());
|
|
|
|
$old_name = '';
|
|
|
|
$new_name = $path->getPath();
|
|
|
|
break;
|
|
|
|
case DifferentialChangeType::TYPE_MOVE_HERE:
|
|
|
|
case DifferentialChangeType::TYPE_COPY_HERE:
|
|
|
|
$old = array(
|
|
|
|
$path->getTargetPath(),
|
|
|
|
$path->getTargetCommitIdentifier());
|
|
|
|
$new = array($path->getPath(), $path->getCommitIdentifier());
|
|
|
|
$old_name = $path->getTargetPath();
|
|
|
|
$new_name = $path->getPath();
|
|
|
|
break;
|
2011-07-20 21:07:26 +02:00
|
|
|
case DifferentialChangeType::TYPE_MOVE_AWAY:
|
|
|
|
$old = array(
|
|
|
|
$path->getPath(),
|
|
|
|
$path->getCommitIdentifier() - 1);
|
|
|
|
$old_name = $path->getPath();
|
|
|
|
$new_name = null;
|
|
|
|
$new = null;
|
|
|
|
break;
|
2011-03-31 02:36:16 +02:00
|
|
|
default:
|
|
|
|
$old = array($path->getPath(), $path->getCommitIdentifier() - 1);
|
|
|
|
$new = array($path->getPath(), $path->getCommitIdentifier());
|
|
|
|
$old_name = $path->getPath();
|
|
|
|
$new_name = $path->getPath();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
$futures = array(
|
2013-05-14 22:53:32 +02:00
|
|
|
'old' => $this->buildSVNContentFuture($old),
|
|
|
|
'new' => $this->buildSVNContentFuture($new),
|
2011-03-31 02:36:16 +02:00
|
|
|
);
|
|
|
|
$futures = array_filter($futures);
|
|
|
|
|
|
|
|
foreach (Futures($futures) as $key => $future) {
|
2012-03-24 00:28:42 +01:00
|
|
|
$stdout = '';
|
2012-03-13 21:32:17 +01:00
|
|
|
try {
|
|
|
|
list($stdout) = $future->resolvex();
|
|
|
|
} catch (CommandException $e) {
|
|
|
|
if ($path->getFileType() != DifferentialChangeType::FILE_DIRECTORY) {
|
|
|
|
throw $e;
|
|
|
|
}
|
|
|
|
}
|
2011-07-20 20:43:44 +02:00
|
|
|
$futures[$key] = $stdout;
|
2011-03-31 02:36:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$old_data = idx($futures, 'old', '');
|
|
|
|
$new_data = idx($futures, 'new', '');
|
|
|
|
|
2011-07-20 20:43:44 +02:00
|
|
|
$engine = new PhabricatorDifferenceEngine();
|
|
|
|
$engine->setOldName($old_name);
|
|
|
|
$engine->setNewName($new_name);
|
|
|
|
$raw_diff = $engine->generateRawDiffFromFileContent($old_data, $new_data);
|
2011-03-31 02:36:16 +02:00
|
|
|
|
2011-03-31 04:32:51 +02:00
|
|
|
$arcanist_changes = DiffusionPathChange::convertToArcanistChanges(
|
|
|
|
$path_changes);
|
|
|
|
|
2013-05-14 22:53:32 +02:00
|
|
|
$parser = $this->getDefaultParser();
|
2011-03-31 04:32:51 +02:00
|
|
|
$parser->setChanges($arcanist_changes);
|
|
|
|
$parser->forcePath($path->getPath());
|
|
|
|
$changes = $parser->parseDiff($raw_diff);
|
|
|
|
|
|
|
|
$change = $changes[$path->getPath()];
|
2011-03-31 02:36:16 +02:00
|
|
|
|
2013-05-14 22:53:32 +02:00
|
|
|
return array($change);
|
|
|
|
}
|
2011-03-31 02:36:16 +02:00
|
|
|
|
2013-05-14 22:53:32 +02:00
|
|
|
private function getEffectiveCommit(ConduitAPIRequest $request) {
|
|
|
|
if ($this->effectiveCommit === null) {
|
|
|
|
$drequest = $this->getDiffusionRequest();
|
|
|
|
|
2014-05-11 01:46:32 +02:00
|
|
|
$path = $drequest->getPath();
|
|
|
|
$result = DiffusionQuery::callConduitWithDiffusionRequest(
|
|
|
|
$request->getUser(),
|
2013-05-14 22:53:32 +02:00
|
|
|
$drequest,
|
|
|
|
'diffusion.lastmodifiedquery',
|
|
|
|
array(
|
2014-05-13 22:53:06 +02:00
|
|
|
'paths' => array($path => $drequest->getStableCommit()),
|
2014-05-11 01:46:32 +02:00
|
|
|
));
|
|
|
|
|
|
|
|
$this->effectiveCommit = idx($result, $path);
|
2013-05-14 22:53:32 +02:00
|
|
|
}
|
2014-05-11 01:46:32 +02:00
|
|
|
|
2013-05-14 22:53:32 +02:00
|
|
|
return $this->effectiveCommit;
|
2011-03-31 02:36:16 +02:00
|
|
|
}
|
|
|
|
|
2013-05-14 22:53:32 +02:00
|
|
|
private function buildSVNContentFuture($spec) {
|
2011-03-31 02:36:16 +02:00
|
|
|
if (!$spec) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2013-05-14 22:53:32 +02:00
|
|
|
$drequest = $this->getDiffusionRequest();
|
2011-03-31 02:36:16 +02:00
|
|
|
$repository = $drequest->getRepository();
|
|
|
|
|
|
|
|
list($ref, $rev) = $spec;
|
2011-09-08 21:46:48 +02:00
|
|
|
return $repository->getRemoteCommandFuture(
|
2013-12-19 17:32:26 +01:00
|
|
|
'cat %s',
|
|
|
|
$repository->getSubversionPathURI($ref, $rev));
|
2011-03-31 02:36:16 +02:00
|
|
|
}
|
|
|
|
|
2013-05-14 22:53:32 +02:00
|
|
|
private function getGitOrMercurialResult(ConduitAPIRequest $request) {
|
|
|
|
$drequest = $this->getDiffusionRequest();
|
|
|
|
$repository = $drequest->getRepository();
|
|
|
|
|
|
|
|
$effective_commit = $this->getEffectiveCommit($request);
|
|
|
|
if (!$effective_commit) {
|
|
|
|
return $this->getEmptyResult(1);
|
|
|
|
}
|
|
|
|
|
2014-05-13 22:53:06 +02:00
|
|
|
$raw_query = DiffusionRawDiffQuery::newFromDiffusionRequest($drequest)
|
|
|
|
->setAnchorCommit($effective_commit);
|
|
|
|
|
2013-05-14 22:53:32 +02:00
|
|
|
$raw_diff = $raw_query->loadRawDiff();
|
|
|
|
if (!$raw_diff) {
|
|
|
|
return $this->getEmptyResult(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
$parser = $this->getDefaultParser();
|
|
|
|
$changes = $parser->parseDiff($raw_diff);
|
|
|
|
|
|
|
|
return $changes;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function getDefaultParser() {
|
|
|
|
$drequest = $this->getDiffusionRequest();
|
|
|
|
$repository = $drequest->getRepository();
|
|
|
|
|
|
|
|
$parser = new ArcanistDiffParser();
|
|
|
|
$try_encoding = $repository->getDetail('encoding');
|
|
|
|
if ($try_encoding) {
|
|
|
|
$parser->setTryEncoding($try_encoding);
|
|
|
|
}
|
|
|
|
$parser->setDetectBinaryFiles(true);
|
|
|
|
|
|
|
|
return $parser;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function getEmptyResult() {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
|
2011-03-31 02:36:16 +02:00
|
|
|
}
|