diff --git a/src/applications/differential/xaction/DifferentialRevisionHoldDraftTransaction.php b/src/applications/differential/xaction/DifferentialRevisionHoldDraftTransaction.php index 4d31f39f02..cf13e8e5b2 100644 --- a/src/applications/differential/xaction/DifferentialRevisionHoldDraftTransaction.php +++ b/src/applications/differential/xaction/DifferentialRevisionHoldDraftTransaction.php @@ -1,58 +1,69 @@ getHoldAsDraft(); } public function generateNewValue($object, $value) { return (bool)$value; } public function applyInternalEffects($object, $value) { $object->setHoldAsDraft($value); // If draft isn't the default state but we're creating a new revision // and holding it as a draft, put it in draft mode. See PHI206. // TODO: This can probably be removed once Draft is the universal default. if ($this->isNewObject()) { if ($object->isNeedsReview()) { $object ->setModernRevisionStatus(DifferentialRevisionStatus::DRAFT) ->setShouldBroadcast(false); } } } public function getTitle() { if ($this->getNewValue()) { return pht( '%s held this revision as a draft.', $this->renderAuthor()); } else { return pht( '%s set this revision to automatically submit once builds complete.', $this->renderAuthor()); } } public function getTitleForFeed() { if ($this->getNewValue()) { return pht( '%s held %s as a draft.', $this->renderAuthor(), $this->renderObject()); } else { return pht( '%s set %s to automatically submit once builds complete.', $this->renderAuthor(), $this->renderObject()); } } + public function getTransactionTypeForConduit($xaction) { + return 'draft'; + } + + public function getFieldValuesForConduit($xaction, $data) { + return array( + 'old' => $xaction->getOldValue(), + 'new' => $xaction->getNewValue(), + ); + } + } diff --git a/src/applications/differential/xaction/DifferentialRevisionSummaryTransaction.php b/src/applications/differential/xaction/DifferentialRevisionSummaryTransaction.php index 238eb53903..66b412ee9c 100644 --- a/src/applications/differential/xaction/DifferentialRevisionSummaryTransaction.php +++ b/src/applications/differential/xaction/DifferentialRevisionSummaryTransaction.php @@ -1,64 +1,75 @@ getSummary(); } public function applyInternalEffects($object, $value) { $object->setSummary($value); } public function getTitle() { return pht( '%s edited the summary of this revision.', $this->renderAuthor()); } public function getTitleForFeed() { return pht( '%s updated the summary of %s.', $this->renderAuthor(), $this->renderObject()); } public function hasChangeDetailView() { return true; } public function getMailDiffSectionHeader() { return pht('CHANGES TO REVISION SUMMARY'); } public function newChangeDetailView() { $viewer = $this->getViewer(); return id(new PhabricatorApplicationTransactionTextDiffDetailView()) ->setViewer($viewer) ->setOldText($this->getOldValue()) ->setNewText($this->getNewValue()); } public function newRemarkupChanges() { $changes = array(); $changes[] = $this->newRemarkupChange() ->setOldValue($this->getOldValue()) ->setNewValue($this->getNewValue()); return $changes; } public function validateTransactions($object, array $xactions) { return $this->validateCommitMessageCorpusTransactions( $object, $xactions, pht('Summary')); } + public function getTransactionTypeForConduit($xaction) { + return 'summary'; + } + + public function getFieldValuesForConduit($xaction, $data) { + return array( + 'old' => $xaction->getOldValue(), + 'new' => $xaction->getNewValue(), + ); + } + } diff --git a/src/applications/differential/xaction/DifferentialRevisionTestPlanTransaction.php b/src/applications/differential/xaction/DifferentialRevisionTestPlanTransaction.php index c7c77fbcff..99837a09fa 100644 --- a/src/applications/differential/xaction/DifferentialRevisionTestPlanTransaction.php +++ b/src/applications/differential/xaction/DifferentialRevisionTestPlanTransaction.php @@ -1,78 +1,89 @@ getTestPlan(); } public function applyInternalEffects($object, $value) { $object->setTestPlan($value); } public function getTitle() { return pht( '%s edited the test plan for this revision.', $this->renderAuthor()); } public function getTitleForFeed() { return pht( '%s updated the test plan for %s.', $this->renderAuthor(), $this->renderObject()); } public function hasChangeDetailView() { return true; } public function getMailDiffSectionHeader() { return pht('CHANGES TO TEST PLAN'); } public function newChangeDetailView() { $viewer = $this->getViewer(); return id(new PhabricatorApplicationTransactionTextDiffDetailView()) ->setViewer($viewer) ->setOldText($this->getOldValue()) ->setNewText($this->getNewValue()); } public function newRemarkupChanges() { $changes = array(); $changes[] = $this->newRemarkupChange() ->setOldValue($this->getOldValue()) ->setNewValue($this->getNewValue()); return $changes; } public function validateTransactions($object, array $xactions) { $errors = $this->validateCommitMessageCorpusTransactions( $object, $xactions, pht('Test Plan')); $is_required = PhabricatorEnv::getEnvConfig( 'differential.require-test-plan-field'); if ($is_required) { if ($this->isEmptyTextTransaction($object->getTestPlan(), $xactions)) { $errors[] = $this->newRequiredError( pht( 'You must provide a test plan. Describe the actions you '. 'performed to verify the behavior of this change.')); } } return $errors; } + public function getTransactionTypeForConduit($xaction) { + return 'testPlan'; + } + + public function getFieldValuesForConduit($xaction, $data) { + return array( + 'old' => $xaction->getOldValue(), + 'new' => $xaction->getNewValue(), + ); + } + } diff --git a/src/applications/differential/xaction/DifferentialRevisionTitleTransaction.php b/src/applications/differential/xaction/DifferentialRevisionTitleTransaction.php index 812464b26d..50d00e1892 100644 --- a/src/applications/differential/xaction/DifferentialRevisionTitleTransaction.php +++ b/src/applications/differential/xaction/DifferentialRevisionTitleTransaction.php @@ -1,69 +1,69 @@ getTitle(); } public function applyInternalEffects($object, $value) { $object->setTitle($value); } public function getTitle() { return pht( '%s retitled this revision from %s to %s.', $this->renderAuthor(), $this->renderOldValue(), $this->renderNewValue()); } public function getTitleForFeed() { return pht( '%s retitled %s from %s to %s.', $this->renderAuthor(), $this->renderObject(), $this->renderOldValue(), $this->renderNewValue()); } public function validateTransactions($object, array $xactions) { $errors = array(); if ($this->isEmptyTextTransaction($object->getTitle(), $xactions)) { $errors[] = $this->newRequiredError( pht('Revisions must have a title.')); } $max_length = $object->getColumnMaximumByteLength('title'); foreach ($xactions as $xaction) { $new_value = $xaction->getNewValue(); $new_length = strlen($new_value); if ($new_length > $max_length) { $errors[] = $this->newInvalidError( pht( 'Revision title is too long: the maximum length of a '. 'revision title is 255 bytes.'), $xaction); } } return $errors; } public function getTransactionTypeForConduit($xaction) { return 'title'; } - public function getFieldValuesForConduit($object, $data) { + public function getFieldValuesForConduit($xaction, $data) { return array( - 'old' => $object->getOldValue(), - 'new' => $object->getNewValue(), + 'old' => $xaction->getOldValue(), + 'new' => $xaction->getNewValue(), ); } } diff --git a/src/applications/differential/xaction/DifferentialRevisionUpdateTransaction.php b/src/applications/differential/xaction/DifferentialRevisionUpdateTransaction.php index 33bbaceb7e..ab544b1c68 100644 --- a/src/applications/differential/xaction/DifferentialRevisionUpdateTransaction.php +++ b/src/applications/differential/xaction/DifferentialRevisionUpdateTransaction.php @@ -1,238 +1,238 @@ getActiveDiffPHID(); } public function applyInternalEffects($object, $value) { $should_review = $this->shouldRequestReviewAfterUpdate($object); if ($should_review) { // If we're updating a non-broadcasting revision, put it back in draft // rather than moving it directly to "Needs Review". if ($object->getShouldBroadcast()) { $new_status = DifferentialRevisionStatus::NEEDS_REVIEW; } else { $new_status = DifferentialRevisionStatus::DRAFT; } $object->setModernRevisionStatus($new_status); } $editor = $this->getEditor(); $diff = $editor->requireDiff($value); $this->updateRevisionLineCounts($object, $diff); $object->setRepositoryPHID($diff->getRepositoryPHID()); $object->setActiveDiffPHID($diff->getPHID()); $object->attachActiveDiff($diff); } private function shouldRequestReviewAfterUpdate($object) { if ($this->isCommitUpdate()) { return false; } $should_update = $object->isNeedsRevision() || $object->isChangePlanned() || $object->isAbandoned(); if ($should_update) { return true; } return false; } public function applyExternalEffects($object, $value) { $editor = $this->getEditor(); $diff = $editor->requireDiff($value); // TODO: This can race with diff updates, particularly those from // Harbormaster. See discussion in T8650. $diff->setRevisionID($object->getID()); $diff->save(); } public function didCommitTransaction($object, $value) { $editor = $this->getEditor(); $diff = $editor->requireDiff($value); $omnipotent = PhabricatorUser::getOmnipotentUser(); // If there are any outstanding buildables for this diff, tell // Harbormaster that their containers need to be updated. This is // common, because `arc` creates buildables so it can upload lint // and unit results. $buildables = id(new HarbormasterBuildableQuery()) ->setViewer($omnipotent) ->withManualBuildables(false) ->withBuildablePHIDs(array($diff->getPHID())) ->execute(); foreach ($buildables as $buildable) { $buildable->sendMessage( $this->getActor(), HarbormasterMessageType::BUILDABLE_CONTAINER, true); } } public function getColor() { return 'sky'; } public function getIcon() { return 'fa-refresh'; } public function getActionName() { if ($this->isCreateTransaction()) { return pht('Request'); } else { return pht('Updated'); } } public function getActionStrength() { return 2; } public function getTitle() { $old = $this->getOldValue(); $new = $this->getNewValue(); if ($this->isCommitUpdate()) { return pht( 'This revision was automatically updated to reflect the '. 'committed changes.'); } // NOTE: Very, very old update transactions did not have a new value or // did not use a diff PHID as a new value. This was changed years ago, // but wasn't migrated. We might consider migrating if this causes issues. return pht( '%s updated this revision to %s.', $this->renderAuthor(), $this->renderNewHandle()); } public function getTitleForFeed() { return pht( '%s updated the diff for %s.', $this->renderAuthor(), $this->renderObject()); } public function validateTransactions($object, array $xactions) { $errors = array(); $diff_phid = null; foreach ($xactions as $xaction) { $diff_phid = $xaction->getNewValue(); $diff = id(new DifferentialDiffQuery()) ->withPHIDs(array($diff_phid)) ->setViewer($this->getActor()) ->executeOne(); if (!$diff) { $errors[] = $this->newInvalidError( pht( 'Specified diff ("%s") does not exist.', $diff_phid), $xaction); continue; } $is_attached = ($diff->getRevisionID()) && ($diff->getRevisionID() == $object->getID()); if ($is_attached) { $is_active = ($diff_phid == $object->getActiveDiffPHID()); } else { $is_active = false; } if ($is_attached) { if ($is_active) { // This is a no-op: we're reattaching the current active diff to the // revision it is already attached to. This is valid and will just // be dropped later on in the process. } else { // At least for now, there's no support for "undoing" a diff and // reverting to an older proposed change without just creating a // new diff from whole cloth. $errors[] = $this->newInvalidError( pht( 'You can not update this revision with the specified diff '. '("%s") because this diff is already attached to the revision '. 'as an older version of the change.', $diff_phid), $xaction); continue; } } else if ($diff->getRevisionID()) { $errors[] = $this->newInvalidError( pht( 'You can not update this revision with the specified diff ("%s") '. 'because the diff is already attached to another revision.', $diff_phid), $xaction); continue; } } if (!$diff_phid && !$object->getActiveDiffPHID()) { $errors[] = $this->newInvalidError( pht( 'You must specify an initial diff when creating a revision.')); } return $errors; } public function isCommitUpdate() { return (bool)$this->getMetadataValue('isCommitUpdate'); } private function updateRevisionLineCounts( DifferentialRevision $revision, DifferentialDiff $diff) { $revision->setLineCount($diff->getLineCount()); $conn = $revision->establishConnection('r'); $row = queryfx_one( $conn, 'SELECT SUM(addLines) A, SUM(delLines) D FROM %T WHERE diffID = %d', id(new DifferentialChangeset())->getTableName(), $diff->getID()); if ($row) { $revision->setAddedLineCount((int)$row['A']); $revision->setRemovedLineCount((int)$row['D']); } } public function getTransactionTypeForConduit($xaction) { return 'update'; } - public function getFieldValuesForConduit($object, $data) { - $commit_phids = $object->getMetadataValue('commitPHIDs', array()); + public function getFieldValuesForConduit($xaction, $data) { + $commit_phids = $xaction->getMetadataValue('commitPHIDs', array()); return array( - 'old' => $object->getOldValue(), - 'new' => $object->getNewValue(), + 'old' => $xaction->getOldValue(), + 'new' => $xaction->getNewValue(), 'commitPHIDs' => $commit_phids, ); } }