diff --git a/resources/sql/autopatches/20170109.diff.01.commit.sql b/resources/sql/autopatches/20170109.diff.01.commit.sql new file mode 100644 --- /dev/null +++ b/resources/sql/autopatches/20170109.diff.01.commit.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_differential.differential_diff + ADD commitPHID VARBINARY(64); diff --git a/src/applications/differential/engine/DifferentialDiffExtractionEngine.php b/src/applications/differential/engine/DifferentialDiffExtractionEngine.php --- a/src/applications/differential/engine/DifferentialDiffExtractionEngine.php +++ b/src/applications/differential/engine/DifferentialDiffExtractionEngine.php @@ -26,6 +26,19 @@ public function newDiffFromCommit(PhabricatorRepositoryCommit $commit) { $viewer = $this->getViewer(); + // If we already have an unattached diff for this commit, just reuse it. + // This stops us from repeatedly generating diffs if something goes wrong + // later in the process. See T10968 for context. + $existing_diffs = id(new DifferentialDiffQuery()) + ->setViewer($viewer) + ->withCommitPHIDs(array($commit->getPHID())) + ->withHasRevision(false) + ->needChangesets(true) + ->execute(); + if ($existing_diffs) { + return head($existing_diffs); + } + $repository = $commit->getRepository(); $identifier = $commit->getCommitIdentifier(); $monogram = $commit->getMonogram(); @@ -73,6 +86,7 @@ $diff = DifferentialDiff::newFromRawChanges($viewer, $changes) ->setRepositoryPHID($repository->getPHID()) + ->setCommitPHID($commit->getPHID()) ->setCreationMethod('commit') ->setSourceControlSystem($repository->getVersionControlSystem()) ->setLintStatus(DifferentialLintStatus::LINT_AUTO_SKIP) diff --git a/src/applications/differential/query/DifferentialDiffQuery.php b/src/applications/differential/query/DifferentialDiffQuery.php --- a/src/applications/differential/query/DifferentialDiffQuery.php +++ b/src/applications/differential/query/DifferentialDiffQuery.php @@ -6,6 +6,8 @@ private $ids; private $phids; private $revisionIDs; + private $commitPHIDs; + private $hasRevision; private $needChangesets = false; private $needProperties; @@ -25,6 +27,16 @@ return $this; } + public function withCommitPHIDs(array $phids) { + $this->commitPHIDs = $phids; + return $this; + } + + public function withHasRevision($has_revision) { + $this->hasRevision = $has_revision; + return $this; + } + public function needChangesets($bool) { $this->needChangesets = $bool; return $this; @@ -108,27 +120,46 @@ protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { $where = parent::buildWhereClauseParts($conn); - if ($this->ids) { + if ($this->ids !== null) { $where[] = qsprintf( $conn, 'id IN (%Ld)', $this->ids); } - if ($this->phids) { + if ($this->phids !== null) { $where[] = qsprintf( $conn, 'phid IN (%Ls)', $this->phids); } - if ($this->revisionIDs) { + if ($this->revisionIDs !== null) { $where[] = qsprintf( $conn, 'revisionID IN (%Ld)', $this->revisionIDs); } + if ($this->commitPHIDs !== null) { + $where[] = qsprintf( + $conn, + 'commitPHID IN (%Ls)', + $this->commitPHIDs); + } + + if ($this->hasRevision !== null) { + if ($this->hasRevision) { + $where[] = qsprintf( + $conn, + 'revisionID IS NOT NULL'); + } else { + $where[] = qsprintf( + $conn, + 'revisionID IS NULL'); + } + } + return $where; } diff --git a/src/applications/differential/storage/DifferentialDiff.php b/src/applications/differential/storage/DifferentialDiff.php --- a/src/applications/differential/storage/DifferentialDiff.php +++ b/src/applications/differential/storage/DifferentialDiff.php @@ -13,6 +13,7 @@ protected $revisionID; protected $authorPHID; protected $repositoryPHID; + protected $commitPHID; protected $sourceMachine; protected $sourcePath; @@ -62,6 +63,7 @@ 'branch' => 'text255?', 'bookmark' => 'text255?', 'repositoryUUID' => 'text64?', + 'commitPHID' => 'phid?', // T6203/NULLABILITY // These should be non-null; all diffs should have a creation method @@ -73,6 +75,9 @@ 'revisionID' => array( 'columns' => array('revisionID'), ), + 'key_commit' => array( + 'columns' => array('commitPHID'), + ), ), ) + parent::getConfiguration(); }