public function renderDiffPropertyViewValue(DifferentialDiff $diff)
 {
     // TODO: This load is slightly inefficient, but most of this is moving
     // to Harbormaster and this simplifies the transition. Eat 1-2 extra
     // queries for now.
     $keys = $this->getDiffPropertyKeys();
     $properties = id(new DifferentialDiffProperty())->loadAllWhere('diffID = %d AND name IN (%Ls)', $diff->getID(), $keys);
     $properties = mpull($properties, 'getData', 'getName');
     foreach ($keys as $key) {
         $diff->attachProperty($key, idx($properties, $key));
     }
     $target_phids = $diff->getBuildTargetPHIDs();
     if ($target_phids) {
         $messages = $this->loadHarbormasterTargetMessages($target_phids);
     } else {
         $messages = array();
     }
     if (!$messages) {
         // No Harbormaster messages, so look for legacy messages and make them
         // look like modern messages.
         $legacy_messages = $diff->getProperty($this->getLegacyProperty());
         if ($legacy_messages) {
             // Show the top 100 legacy lint messages. Previously, we showed some
             // by default and let the user toggle the rest. With modern messages,
             // we can send the user to the Harbormaster detail page. Just show
             // "a lot" of messages in legacy cases to try to strike a balance
             // between implementation simplicitly and compatibility.
             $legacy_messages = array_slice($legacy_messages, 0, 100);
             foreach ($legacy_messages as $message) {
                 try {
                     $modern = $this->newModernMessage($message);
                     $messages[] = $modern;
                 } catch (Exception $ex) {
                     // Ignore any poorly formatted messages.
                 }
             }
         }
     }
     $status = $this->renderHarbormasterStatus($diff, $messages);
     if ($messages) {
         $path_map = mpull($diff->loadChangesets(), 'getID', 'getFilename');
         foreach ($path_map as $path => $id) {
             $href = '#C' . $id . 'NL';
             // TODO: When the diff is not the right-hand-size diff, we should
             // ideally adjust this URI to be absolute.
             $path_map[$path] = $href;
         }
         $view = $this->newHarbormasterMessageView($messages);
         if ($view) {
             $view->setPathURIMap($path_map);
         }
     } else {
         $view = null;
     }
     if ($view) {
         $view = phutil_tag('div', array('class' => 'differential-harbormaster-table-view'), $view);
     }
     return array($status, $view);
 }
 public static function createDiffDict(DifferentialDiff $diff)
 {
     $dict = array('id' => $diff->getID(), 'parent' => $diff->getParentRevisionID(), 'revisionID' => $diff->getRevisionID(), 'sourceControlBaseRevision' => $diff->getSourceControlBaseRevision(), 'sourceControlPath' => $diff->getSourceControlPath(), 'changes' => array(), 'properties' => array());
     foreach ($diff->getChangesets() as $changeset) {
         $hunks = array();
         foreach ($changeset->getHunks() as $hunk) {
             $hunks[] = array('oldOffset' => $hunk->getOldOffset(), 'newOffset' => $hunk->getNewOffset(), 'oldLength' => $hunk->getOldLen(), 'newLength' => $hunk->getNewLen(), 'addLines' => null, 'delLines' => null, 'isMissingOldNewline' => null, 'isMissingNewNewline' => null, 'corpus' => $hunk->getChanges());
         }
         $change = array('metadata' => $changeset->getMetadata(), 'oldPath' => $changeset->getOldFile(), 'currentPath' => $changeset->getFileName(), 'awayPaths' => $changeset->getAwayPaths(), 'oldProperties' => $changeset->getOldProperties(), 'newProperties' => $changeset->getNewProperties(), 'type' => $changeset->getChangeType(), 'fileType' => $changeset->getFileType(), 'commitHash' => null, 'hunks' => $hunks);
         $dict['changes'][] = $change;
     }
     $properties = id(new DifferentialDiffProperty())->loadAllWhere('diffID = %d', $diff->getID());
     foreach ($properties as $property) {
         $dict['properties'][$property->getName()] = $property->getData();
     }
     return $dict;
 }
 private function buildTransactions(DifferentialRevision $revision, DifferentialDiff $left_diff, DifferentialDiff $right_diff, array $old_ids, array $new_ids)
 {
     $timeline = $this->buildTransactionTimeline($revision, new DifferentialTransactionQuery(), $engine = null, array('left' => $left_diff->getID(), 'right' => $right_diff->getID(), 'old' => implode(',', $old_ids), 'new' => implode(',', $new_ids)));
     return $timeline;
 }
 /**
  * Update the table connecting revisions to DVCS local hashes, so we can
  * identify revisions by commit/tree hashes.
  */
 private function updateRevisionHashTable(DifferentialRevision $revision, DifferentialDiff $diff)
 {
     $vcs = $diff->getSourceControlSystem();
     if ($vcs == DifferentialRevisionControlSystem::SVN) {
         // Subversion has no local commit or tree hash information, so we don't
         // have to do anything.
         return;
     }
     $property = id(new DifferentialDiffProperty())->loadOneWhere('diffID = %d AND name = %s', $diff->getID(), 'local:commits');
     if (!$property) {
         return;
     }
     $hashes = array();
     $data = $property->getData();
     switch ($vcs) {
         case DifferentialRevisionControlSystem::GIT:
             foreach ($data as $commit) {
                 $hashes[] = array(ArcanistDifferentialRevisionHash::HASH_GIT_COMMIT, $commit['commit']);
                 $hashes[] = array(ArcanistDifferentialRevisionHash::HASH_GIT_TREE, $commit['tree']);
             }
             break;
         case DifferentialRevisionControlSystem::MERCURIAL:
             foreach ($data as $commit) {
                 $hashes[] = array(ArcanistDifferentialRevisionHash::HASH_MERCURIAL_COMMIT, $commit['rev']);
             }
             break;
     }
     $conn_w = $revision->establishConnection('w');
     $sql = array();
     foreach ($hashes as $info) {
         list($type, $hash) = $info;
         $sql[] = qsprintf($conn_w, '(%d, %s, %s)', $revision->getID(), $type, $hash);
     }
     queryfx($conn_w, 'DELETE FROM %T WHERE revisionID = %d', ArcanistDifferentialRevisionHash::TABLE_NAME, $revision->getID());
     if ($sql) {
         queryfx($conn_w, 'INSERT INTO %T (revisionID, type, hash) VALUES %Q', ArcanistDifferentialRevisionHash::TABLE_NAME, implode(', ', $sql));
     }
 }
 protected function buildDiffInfoDictionary(DifferentialDiff $diff)
 {
     $uri = '/differential/diff/' . $diff->getID() . '/';
     $uri = PhabricatorEnv::getProductionURI($uri);
     return array('id' => $diff->getID(), 'uri' => $uri);
 }
 private function loadChangesetsAndVsMap(DifferentialDiff $target, DifferentialDiff $diff_vs = null, PhabricatorRepository $repository = null)
 {
     $load_diffs = array($target);
     if ($diff_vs) {
         $load_diffs[] = $diff_vs;
     }
     $raw_changesets = id(new DifferentialChangesetQuery())->setViewer($this->getRequest()->getUser())->withDiffs($load_diffs)->execute();
     $changeset_groups = mgroup($raw_changesets, 'getDiffID');
     $changesets = idx($changeset_groups, $target->getID(), array());
     $changesets = mpull($changesets, null, 'getID');
     $refs = array();
     $vs_map = array();
     $vs_changesets = array();
     if ($diff_vs) {
         $vs_id = $diff_vs->getID();
         $vs_changesets_path_map = array();
         foreach (idx($changeset_groups, $vs_id, array()) as $changeset) {
             $path = $changeset->getAbsoluteRepositoryPath($repository, $diff_vs);
             $vs_changesets_path_map[$path] = $changeset;
             $vs_changesets[$changeset->getID()] = $changeset;
         }
         foreach ($changesets as $key => $changeset) {
             $path = $changeset->getAbsoluteRepositoryPath($repository, $target);
             if (isset($vs_changesets_path_map[$path])) {
                 $vs_map[$changeset->getID()] = $vs_changesets_path_map[$path]->getID();
                 $refs[$changeset->getID()] = $changeset->getID() . '/' . $vs_changesets_path_map[$path]->getID();
                 unset($vs_changesets_path_map[$path]);
             } else {
                 $refs[$changeset->getID()] = $changeset->getID();
             }
         }
         foreach ($vs_changesets_path_map as $path => $changeset) {
             $changesets[$changeset->getID()] = $changeset;
             $vs_map[$changeset->getID()] = -1;
             $refs[$changeset->getID()] = $changeset->getID() . '/-1';
         }
     } else {
         foreach ($changesets as $changeset) {
             $refs[$changeset->getID()] = $changeset->getID();
         }
     }
     $changesets = msort($changesets, 'getSortKey');
     return array($changesets, $vs_map, $vs_changesets, $refs);
 }
 private function loadChangesetsAndVsMap(array $diffs, $diff_vs, DifferentialDiff $target)
 {
     assert_instances_of($diffs, 'DifferentialDiff');
     $load_ids = array();
     if ($diff_vs) {
         $load_ids[] = $diff_vs;
     }
     $load_ids[] = $target->getID();
     $raw_changesets = id(new DifferentialChangeset())->loadAllWhere('diffID IN (%Ld)', $load_ids);
     $changeset_groups = mgroup($raw_changesets, 'getDiffID');
     $changesets = idx($changeset_groups, $target->getID(), array());
     $changesets = mpull($changesets, null, 'getID');
     $refs = array();
     foreach ($changesets as $changeset) {
         $refs[$changeset->getID()] = $changeset->getID();
     }
     $vs_map = array();
     if ($diff_vs) {
         $vs_changesets = idx($changeset_groups, $diff_vs, array());
         $vs_changesets = mpull($vs_changesets, null, 'getFilename');
         foreach ($changesets as $key => $changeset) {
             $file = $changeset->getFilename();
             if (isset($vs_changesets[$file])) {
                 $vs_map[$changeset->getID()] = $vs_changesets[$file]->getID();
                 $refs[$changeset->getID()] = $changeset->getID() . '/' . $vs_changesets[$file]->getID();
                 unset($vs_changesets[$file]);
             } else {
                 $refs[$changeset->getID()] = $changeset->getID();
             }
         }
         foreach ($vs_changesets as $changeset) {
             $changesets[$changeset->getID()] = $changeset;
             $vs_map[$changeset->getID()] = -1;
             $refs[$changeset->getID()] = $changeset->getID() . '/-1';
         }
     }
     $changesets = msort($changesets, 'getSortKey');
     return array($changesets, $vs_map, $refs);
 }
 public function addDiff(DifferentialDiff $diff, $comments)
 {
     if ($diff->getRevisionID() && $diff->getRevisionID() != $this->getRevision()->getID()) {
         $diff_id = (int) $diff->getID();
         $targ_id = (int) $this->getRevision()->getID();
         $real_id = (int) $diff->getRevisionID();
         throw new Exception("Can not attach diff #{$diff_id} to Revision D{$targ_id}, it is " . "already attached to D{$real_id}.");
     }
     $this->diff = $diff;
     $this->comments = $comments;
     return $this;
 }