diff --git a/src/workflow/ArcanistDiffWorkflow.php b/src/workflow/ArcanistDiffWorkflow.php --- a/src/workflow/ArcanistDiffWorkflow.php +++ b/src/workflow/ArcanistDiffWorkflow.php @@ -2164,8 +2164,8 @@ // we always get this 100% right, we're just trying to do something // reasonable. - $local = $this->loadActiveLocalCommitInfo(); - $hashes = ipull($local, null, 'commit'); + $hashes = $this->loadActiveDiffLocalCommitHashes(); + $hashes = array_fuse($hashes); $usable = array(); foreach ($commit_messages as $message) { @@ -2212,8 +2212,8 @@ return null; } - $local = $this->loadActiveLocalCommitInfo(); - $hashes = ipull($local, null, 'commit'); + $hashes = $this->loadActiveDiffLocalCommitHashes(); + $hashes = array_fuse($hashes); $usable = array(); foreach ($messages as $rev => $message) { @@ -2261,7 +2261,63 @@ return implode('', $default); } - private function loadActiveLocalCommitInfo() { + private function loadActiveDiffLocalCommitHashes() { + // The older "differential.querydiffs" method includes the full diff text, + // which can be very slow for large diffs. If we can, try to use + // "differential.diff.search" instead. + + // We expect this to fail if the Phabricator version on the server is + // older than April 2018 (D19386), which introduced the "commits" + // attachment for "differential.revision.search". + + // TODO: This can be optimized if we're able to learn the "revisionPHID" + // before we get here. See PHI1104. + + try { + $revisions_raw = $this->getConduit()->callMethodSynchronous( + 'differential.revision.search', + array( + 'constraints' => array( + 'ids' => array( + $this->revisionID, + ), + ), + )); + + $revisions = $revisions_raw['data']; + $revision = head($revisions); + if ($revision) { + $revision_phid = $revision['phid']; + + $diffs_raw = $this->getConduit()->callMethodSynchronous( + 'differential.diff.search', + array( + 'constraints' => array( + 'revisionPHIDs' => array( + $revision_phid, + ), + ), + 'attachments' => array( + 'commits' => true, + ), + 'limit' => 1, + )); + + $diffs = $diffs_raw['data']; + $diff = head($diffs); + + if ($diff) { + $commits = idxv($diff, array('attachments', 'commits', 'commits')); + if ($commits !== null) { + $hashes = ipull($commits, 'identifier'); + return array_values($hashes); + } + } + } + } catch (Exception $ex) { + // If any of this fails, fall back to the older method below. + } + $current_diff = $this->getConduit()->callMethodSynchronous( 'differential.querydiffs', array( @@ -2270,7 +2326,10 @@ $current_diff = head($current_diff); $properties = idx($current_diff, 'properties', array()); - return idx($properties, 'local:commits', array()); + $local = idx($properties, 'local:commits', array()); + $hashes = ipull($local, 'commit'); + + return array_values($hashes); }