2014-08-20 23:26:29 +02:00
|
|
|
<?php
|
|
|
|
|
2014-11-19 00:32:23 +01:00
|
|
|
final class DifferentialDiffEditor
|
|
|
|
extends PhabricatorApplicationTransactionEditor {
|
2014-08-20 23:26:29 +02:00
|
|
|
|
2014-11-19 00:32:23 +01:00
|
|
|
private $diffDataDict;
|
2014-08-20 23:26:29 +02:00
|
|
|
|
2014-11-19 00:32:23 +01:00
|
|
|
public function getEditorApplicationClass() {
|
|
|
|
return 'PhabricatorDifferentialApplication';
|
2014-08-20 23:26:29 +02:00
|
|
|
}
|
|
|
|
|
2014-11-19 00:32:23 +01:00
|
|
|
public function getEditorObjectsDescription() {
|
|
|
|
return pht('Differential Diffs');
|
2014-08-20 23:26:29 +02:00
|
|
|
}
|
|
|
|
|
2014-11-19 00:32:23 +01:00
|
|
|
public function getTransactionTypes() {
|
|
|
|
$types = parent::getTransactionTypes();
|
2014-08-20 23:26:29 +02:00
|
|
|
|
2014-11-19 00:32:23 +01:00
|
|
|
$types[] = DifferentialDiffTransaction::TYPE_DIFF_CREATE;
|
2014-08-20 23:26:29 +02:00
|
|
|
|
2014-11-19 00:32:23 +01:00
|
|
|
return $types;
|
|
|
|
}
|
2014-08-20 23:26:29 +02:00
|
|
|
|
2014-11-19 00:32:23 +01:00
|
|
|
protected function getCustomTransactionOldValue(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
PhabricatorApplicationTransaction $xaction) {
|
2014-08-20 23:26:29 +02:00
|
|
|
|
2014-11-19 00:32:23 +01:00
|
|
|
switch ($xaction->getTransactionType()) {
|
|
|
|
case DifferentialDiffTransaction::TYPE_DIFF_CREATE:
|
|
|
|
return null;
|
|
|
|
}
|
2014-08-20 23:26:29 +02:00
|
|
|
|
2014-11-19 00:32:23 +01:00
|
|
|
return parent::getCustomTransactionOldValue($object, $xaction);
|
|
|
|
}
|
2014-08-20 23:26:29 +02:00
|
|
|
|
2014-11-19 00:32:23 +01:00
|
|
|
protected function getCustomTransactionNewValue(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
PhabricatorApplicationTransaction $xaction) {
|
2014-08-20 23:26:29 +02:00
|
|
|
|
2014-11-19 00:32:23 +01:00
|
|
|
switch ($xaction->getTransactionType()) {
|
|
|
|
case DifferentialDiffTransaction::TYPE_DIFF_CREATE:
|
|
|
|
$this->diffDataDict = $xaction->getNewValue();
|
|
|
|
return true;
|
2014-08-20 23:26:29 +02:00
|
|
|
}
|
|
|
|
|
2014-11-19 00:32:23 +01:00
|
|
|
return parent::getCustomTransactionNewValue($object, $xaction);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function applyCustomInternalTransaction(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
PhabricatorApplicationTransaction $xaction) {
|
|
|
|
|
|
|
|
switch ($xaction->getTransactionType()) {
|
|
|
|
case DifferentialDiffTransaction::TYPE_DIFF_CREATE:
|
|
|
|
$dict = $this->diffDataDict;
|
|
|
|
$this->updateDiffFromDict($object, $dict);
|
|
|
|
return;
|
|
|
|
}
|
2014-08-20 23:26:29 +02:00
|
|
|
|
2014-11-19 00:32:23 +01:00
|
|
|
return parent::applyCustomInternalTransaction($object, $xaction);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function applyCustomExternalTransaction(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
PhabricatorApplicationTransaction $xaction) {
|
|
|
|
|
|
|
|
switch ($xaction->getTransactionType()) {
|
|
|
|
case DifferentialDiffTransaction::TYPE_DIFF_CREATE:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
return parent::applyCustomExternalTransaction($object, $xaction);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function applyFinalEffects(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
array $xactions) {
|
|
|
|
|
|
|
|
// If we didn't get an explicit `repositoryPHID` (which means the client
|
|
|
|
// is old, or couldn't figure out which repository the working copy
|
|
|
|
// belongs to), apply heuristics to try to figure it out.
|
|
|
|
|
|
|
|
if (!$object->getRepositoryPHID()) {
|
|
|
|
$repository = id(new DifferentialRepositoryLookup())
|
|
|
|
->setDiff($object)
|
|
|
|
->setViewer($this->getActor())
|
|
|
|
->lookupRepository();
|
|
|
|
if ($repository) {
|
|
|
|
$object->setRepositoryPHID($repository->getPHID());
|
|
|
|
$object->setRepositoryUUID($repository->getUUID());
|
|
|
|
$object->save();
|
2014-08-20 23:26:29 +02:00
|
|
|
}
|
2014-11-19 00:32:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return $xactions;
|
|
|
|
}
|
2014-08-20 23:26:29 +02:00
|
|
|
|
2014-11-19 00:32:23 +01:00
|
|
|
/**
|
|
|
|
* We run Herald as part of transaction validation because Herald can
|
|
|
|
* block diff creation for Differential diffs. Its important to do this
|
|
|
|
* separately so no Herald logs are saved; these logs could expose
|
|
|
|
* information the Herald rules are inteneded to block.
|
|
|
|
*/
|
|
|
|
protected function validateTransaction(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
$type,
|
|
|
|
array $xactions) {
|
|
|
|
|
|
|
|
$errors = parent::validateTransaction($object, $type, $xactions);
|
|
|
|
|
|
|
|
foreach ($xactions as $xaction) {
|
|
|
|
switch ($type) {
|
|
|
|
case DifferentialDiffTransaction::TYPE_DIFF_CREATE:
|
|
|
|
$diff = clone $object;
|
|
|
|
$diff = $this->updateDiffFromDict($diff, $xaction->getNewValue());
|
|
|
|
|
|
|
|
$adapter = $this->buildHeraldAdapter($diff, $xactions);
|
|
|
|
$adapter->setContentSource($this->getContentSource());
|
|
|
|
$adapter->setIsNewObject($this->getIsNewObject());
|
|
|
|
|
|
|
|
$engine = new HeraldEngine();
|
|
|
|
|
|
|
|
$rules = $engine->loadRulesForAdapter($adapter);
|
|
|
|
$rules = mpull($rules, null, 'getID');
|
|
|
|
|
|
|
|
$effects = $engine->applyRules($rules, $adapter);
|
|
|
|
|
|
|
|
$blocking_effect = null;
|
|
|
|
foreach ($effects as $effect) {
|
|
|
|
if ($effect->getAction() == HeraldAdapter::ACTION_BLOCK) {
|
|
|
|
$blocking_effect = $effect;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($blocking_effect) {
|
|
|
|
$rule = idx($rules, $effect->getRuleID());
|
|
|
|
if ($rule && strlen($rule->getName())) {
|
|
|
|
$rule_name = $rule->getName();
|
|
|
|
} else {
|
|
|
|
$rule_name = pht('Unnamed Herald Rule');
|
|
|
|
}
|
|
|
|
|
|
|
|
$message = $effect->getTarget();
|
|
|
|
if (!strlen($message)) {
|
|
|
|
$message = pht('(None.)');
|
|
|
|
}
|
|
|
|
|
|
|
|
$errors[] = new PhabricatorApplicationTransactionValidationError(
|
|
|
|
$type,
|
|
|
|
pht('Rejected by Herald'),
|
|
|
|
pht(
|
|
|
|
"Creation of this diff was rejected by Herald rule %s.\n".
|
|
|
|
" Rule: %s\n".
|
|
|
|
"Reason: %s",
|
|
|
|
'H'.$effect->getRuleID(),
|
|
|
|
$rule_name,
|
|
|
|
$message));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2014-08-20 23:26:29 +02:00
|
|
|
}
|
|
|
|
|
2014-11-19 00:32:23 +01:00
|
|
|
return $errors;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected function shouldPublishFeedStory(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
array $xactions) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function shouldSendMail(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
array $xactions) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function supportsSearch() {
|
|
|
|
return false;
|
|
|
|
}
|
2014-08-20 23:26:29 +02:00
|
|
|
|
2014-11-19 00:32:23 +01:00
|
|
|
/* -( Herald Integration )------------------------------------------------- */
|
2014-08-20 23:26:29 +02:00
|
|
|
|
2014-11-19 00:32:23 +01:00
|
|
|
/**
|
|
|
|
* See @{method:validateTransaction}. The only Herald action is to block
|
|
|
|
* the creation of Diffs. We thus have to be careful not to save any
|
|
|
|
* data and do this validation very early.
|
|
|
|
*/
|
|
|
|
protected function shouldApplyHeraldRules(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
array $xactions) {
|
2014-08-20 23:26:29 +02:00
|
|
|
|
2014-11-19 00:32:23 +01:00
|
|
|
return false;
|
2014-08-20 23:26:29 +02:00
|
|
|
}
|
|
|
|
|
2014-11-19 00:32:23 +01:00
|
|
|
protected function buildHeraldAdapter(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
array $xactions) {
|
|
|
|
|
|
|
|
$adapter = id(new HeraldDifferentialDiffAdapter())
|
|
|
|
->setDiff($object);
|
|
|
|
|
|
|
|
return $adapter;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function didApplyHeraldRules(
|
|
|
|
PhabricatorLiskDAO $object,
|
|
|
|
HeraldAdapter $adapter,
|
|
|
|
HeraldTranscript $transcript) {
|
|
|
|
|
|
|
|
$xactions = array();
|
|
|
|
return $xactions;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function updateDiffFromDict(DifferentialDiff $diff, $dict) {
|
|
|
|
$diff
|
|
|
|
->setSourcePath(idx($dict, 'sourcePath'))
|
|
|
|
->setSourceMachine(idx($dict, 'sourceMachine'))
|
|
|
|
->setBranch(idx($dict, 'branch'))
|
|
|
|
->setCreationMethod(idx($dict, 'creationMethod'))
|
|
|
|
->setAuthorPHID(idx($dict, 'authorPHID', $this->getActor()))
|
|
|
|
->setBookmark(idx($dict, 'bookmark'))
|
|
|
|
->setRepositoryPHID(idx($dict, 'repositoryPHID'))
|
|
|
|
->setRepositoryUUID(idx($dict, 'repositoryUUID'))
|
|
|
|
->setSourceControlSystem(idx($dict, 'sourceControlSystem'))
|
|
|
|
->setSourceControlPath(idx($dict, 'sourceControlPath'))
|
|
|
|
->setSourceControlBaseRevision(idx($dict, 'sourceControlBaseRevision'))
|
|
|
|
->setLintStatus(idx($dict, 'lintStatus'))
|
|
|
|
->setUnitStatus(idx($dict, 'unitStatus'))
|
|
|
|
->setArcanistProjectPHID(idx($dict, 'arcanistProjectPHID'));
|
|
|
|
|
|
|
|
return $diff;
|
|
|
|
}
|
2014-08-20 23:26:29 +02:00
|
|
|
}
|