protected function execute(ConduitAPIRequest $request) { $diff = null; $revision_id = $request->getValue('revision_id'); $revision = id(new DifferentialRevision())->load($revision_id); if (!$revision) { throw new ConduitException('ERR_BAD_REVISION'); } $revision->loadRelationships(); $reviewer_phids = array_values($revision->getReviewers()); $diffs = $revision->loadDiffs(); $diff_dicts = array(); foreach ($diffs as $diff) { $diff->attachChangesets($diff->loadChangesets()); // TODO: We could batch this to improve performance. foreach ($diff->getChangesets() as $changeset) { $changeset->attachHunks($changeset->loadHunks()); } $diff_dicts[] = ConduitAPI_differential_getdiff_Method::createDiffDict($diff); } $commit_dicts = array(); $commit_phids = $revision->loadCommitPHIDs(); $handles = id(new PhabricatorObjectHandleData($commit_phids))->loadHandles(); foreach ($commit_phids as $commit_phid) { $commit_dicts[] = array('fullname' => $handles[$commit_phid]->getFullName(), 'dateCommitted' => $handles[$commit_phid]->getTimestamp()); } $auxiliary_fields = $this->loadAuxiliaryFields($revision); $dict = array('id' => $revision->getID(), 'phid' => $revision->getPHID(), 'authorPHID' => $revision->getAuthorPHID(), 'uri' => PhabricatorEnv::getURI('/D' . $revision->getID()), 'title' => $revision->getTitle(), 'status' => $revision->getStatus(), 'statusName' => DifferentialRevisionStatus::getNameForRevisionStatus($revision->getStatus()), 'summary' => $revision->getSummary(), 'testPlan' => $revision->getTestPlan(), 'lineCount' => $revision->getLineCount(), 'reviewerPHIDs' => $reviewer_phids, 'diffs' => $diff_dicts, 'commits' => $commit_dicts, 'auxiliary' => $auxiliary_fields); return $dict; }
public function render() { $user = $this->user; if (!$user) { throw new Exception("Call setUser() before render()!"); } $rows = array(); foreach ($this->revisions as $revision) { $status = $revision->getStatus(); $status = DifferentialRevisionStatus::getNameForRevisionStatus($status); $reviewer_phids = $revision->getReviewers(); if ($reviewer_phids) { $first = reset($reviewer_phids); if (count($reviewer_phids) > 1) { $suffix = ' (+' . (count($reviewer_phids) - 1) . ')'; } else { $suffix = null; } $reviewers = $this->handles[$first]->renderLink() . $suffix; } else { $reviewers = '<em>None</em>'; } $link = phutil_render_tag('a', array('href' => '/D' . $revision->getID()), phutil_escape_html($revision->getTitle())); $rows[] = array('D' . $revision->getID(), $link, phutil_escape_html($status), number_format($revision->getLineCount()), $this->handles[$revision->getAuthorPHID()]->renderLink(), $reviewers, phabricator_datetime($revision->getDateModified(), $user), phabricator_date($revision->getDateCreated(), $user)); } $table = new AphrontTableView($rows); $table->setHeaders(array('ID', 'Revision', 'Status', 'Lines', 'Author', 'Reviewers', 'Updated', 'Created')); $table->setColumnClasses(array(null, 'wide pri', null, 'n', null, null, 'right', 'right')); if ($this->noDataString) { $table->setNoDataString($this->noDataString); } return $table->render(); }
private function renderHeader(DifferentialRevision $revision) { $view = id(new PHUIHeaderView())->setHeader($revision->getTitle($revision))->setUser($this->getUser())->setPolicyObject($revision); $status = $revision->getStatus(); $status_name = DifferentialRevisionStatus::renderFullDescription($status); $view->addProperty(PHUIHeaderView::PROPERTY_STATUS, $status_name); return $view; }
protected function execute(ConduitAPIRequest $request) { $query = $request->getValue('query'); $guids = $request->getValue('guids'); $results = array(); if (!$guids) { return $results; } $revisions = id(new DifferentialRevisionListData($query, (array) $guids))->loadRevisions(); foreach ($revisions as $revision) { $diff = $revision->loadActiveDiff(); if (!$diff) { continue; } $id = $revision->getID(); $results[] = array('id' => $id, 'phid' => $revision->getPHID(), 'name' => $revision->getTitle(), 'uri' => PhabricatorEnv::getProductionURI('/D' . $id), 'dateCreated' => $revision->getDateCreated(), 'authorPHID' => $revision->getAuthorPHID(), 'statusName' => DifferentialRevisionStatus::getNameForRevisionStatus($revision->getStatus()), 'sourcePath' => $diff->getSourcePath()); } return $results; }
public function renderValueForRevisionView() { $revision = $this->getRevision(); $diff = $this->getDiff(); $status = $revision->getStatus(); $next_step = null; if ($status == DifferentialRevisionStatus::ACCEPTED) { switch ($diff->getSourceControlSystem()) { case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: $next_step = 'arc amend --revision ' . $revision->getID(); break; case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: $next_step = 'arc commit --revision ' . $revision->getID(); break; } if ($next_step) { $next_step = ' · ' . 'Next step: <tt>' . phutil_escape_html($next_step) . '</tt>'; } } $status = DifferentialRevisionStatus::getNameForRevisionStatus($status); return '<strong>' . $status . '</strong>' . $next_step; }
/** * @task internal */ private function buildWhereClause($conn_r) { $where = array(); if ($this->pathIDs) { $path_clauses = array(); $repo_info = igroup($this->pathIDs, 'repositoryID'); foreach ($repo_info as $repository_id => $paths) { $path_clauses[] = qsprintf($conn_r, '(p.repositoryID = %d AND p.pathID IN (%Ld))', $repository_id, ipull($paths, 'pathID')); } $path_clauses = '(' . implode(' OR ', $path_clauses) . ')'; $where[] = $path_clauses; } if ($this->authors) { $where[] = qsprintf($conn_r, 'r.authorPHID IN (%Ls)', $this->authors); } if ($this->revIDs) { $where[] = qsprintf($conn_r, 'r.id IN (%Ld)', $this->revIDs); } if ($this->repositoryPHIDs) { $where[] = qsprintf($conn_r, 'r.repositoryPHID IN (%Ls)', $this->repositoryPHIDs); } if ($this->commitHashes) { $hash_clauses = array(); foreach ($this->commitHashes as $info) { list($type, $hash) = $info; $hash_clauses[] = qsprintf($conn_r, '(hash_rel.type = %s AND hash_rel.hash = %s)', $type, $hash); } $hash_clauses = '(' . implode(' OR ', $hash_clauses) . ')'; $where[] = $hash_clauses; } if ($this->phids) { $where[] = qsprintf($conn_r, 'r.phid IN (%Ls)', $this->phids); } if ($this->branches) { $where[] = qsprintf($conn_r, 'r.branchName in (%Ls)', $this->branches); } if ($this->arcanistProjectPHIDs) { $where[] = qsprintf($conn_r, 'r.arcanistProjectPHID in (%Ls)', $this->arcanistProjectPHIDs); } switch ($this->status) { case self::STATUS_ANY: break; case self::STATUS_OPEN: $where[] = qsprintf($conn_r, 'r.status IN (%Ld)', DifferentialRevisionStatus::getOpenStatuses()); break; case self::STATUS_NEEDS_REVIEW: $where[] = qsprintf($conn_r, 'r.status IN (%Ld)', array(ArcanistDifferentialRevisionStatus::NEEDS_REVIEW)); break; case self::STATUS_NEEDS_REVISION: $where[] = qsprintf($conn_r, 'r.status IN (%Ld)', array(ArcanistDifferentialRevisionStatus::NEEDS_REVISION)); break; case self::STATUS_ACCEPTED: $where[] = qsprintf($conn_r, 'r.status IN (%Ld)', array(ArcanistDifferentialRevisionStatus::ACCEPTED)); break; case self::STATUS_CLOSED: $where[] = qsprintf($conn_r, 'r.status IN (%Ld)', DifferentialRevisionStatus::getClosedStatuses()); break; case self::STATUS_ABANDONED: $where[] = qsprintf($conn_r, 'r.status IN (%Ld)', array(ArcanistDifferentialRevisionStatus::ABANDONED)); break; default: throw new Exception("Unknown revision status filter constant '{$this->status}'!"); } $where[] = $this->buildPagingClause($conn_r); return $this->formatWhereClause($where); }
public function isClosed() { return DifferentialRevisionStatus::isClosedStatus($this->getStatus()); }
protected function execute(ConduitAPIRequest $request) { $authors = $request->getValue('authors'); $ccs = $request->getValue('ccs'); $reviewers = $request->getValue('reviewers'); $status = $request->getValue('status'); $order = $request->getValue('order'); $commit_hashes = $request->getValue('commitHashes'); $limit = $request->getValue('limit'); $offset = $request->getValue('offset'); $ids = $request->getValue('ids'); $phids = $request->getValue('phids'); $subscribers = $request->getValue('subscribers'); $responsible_users = $request->getValue('responsibleUsers'); $query = new DifferentialRevisionQuery(); if ($authors) { $query->withAuthors($authors); } if ($ccs) { $query->withCCs($ccs); } if ($reviewers) { $query->withReviewers($reviewers); } /* TODO: Implement. $paths = $request->getValue('paths'); if ($paths) { foreach ($paths as $path) { // (Lookup the repository IDs.) $query->withPath($repository_id, $path); } } */ if ($commit_hashes) { $hash_types = DifferentialRevisionHash::getTypes(); foreach ($commit_hashes as $info) { list($type, $hash) = $info; if (empty($type) || !in_array($type, $hash_types) || empty($hash)) { throw new ConduitException('ERR-INVALID-PARAMETER'); } } $query->withCommitHashes($commit_hashes); } if ($status) { $query->withStatus($status); } if ($order) { $query->setOrder($order); } if ($limit) { $query->setLimit($limit); } if ($offset) { $query->setOffset($offset); } if ($ids) { $query->withIDs($ids); } if ($phids) { $query->withPHIDs($phids); } if ($responsible_users) { $query->withResponsibleUsers($responsible_users); } if ($subscribers) { $query->withSubscribers($subscribers); } $query->needRelationships(true); $query->needCommitPHIDs(true); $query->needDiffIDs(true); $query->needActiveDiffs(true); $revisions = $query->execute(); $results = array(); foreach ($revisions as $revision) { $diff = $revision->getActiveDiff(); if (!$diff) { continue; } $id = $revision->getID(); $results[] = array('id' => $id, 'phid' => $revision->getPHID(), 'title' => $revision->getTitle(), 'uri' => PhabricatorEnv::getProductionURI('/D' . $id), 'dateCreated' => $revision->getDateCreated(), 'dateModified' => $revision->getDateModified(), 'authorPHID' => $revision->getAuthorPHID(), 'status' => $revision->getStatus(), 'statusName' => DifferentialRevisionStatus::getNameForRevisionStatus($revision->getStatus()), 'sourcePath' => $diff->getSourcePath(), 'summary' => $revision->getSummary(), 'testPlan' => $revision->getTestPlan(), 'lineCount' => $revision->getLineCount(), 'diffs' => $revision->getDiffIDs(), 'commits' => $revision->getCommitPHIDs(), 'reviewers' => array_values($revision->getReviewers()), 'ccs' => array_values($revision->getCCPHIDs())); } return $results; }
/** * @task internal */ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { $where = array(); if ($this->pathIDs) { $path_clauses = array(); $repo_info = igroup($this->pathIDs, 'repositoryID'); foreach ($repo_info as $repository_id => $paths) { $path_clauses[] = qsprintf($conn_r, '(p.repositoryID = %d AND p.pathID IN (%Ld))', $repository_id, ipull($paths, 'pathID')); } $path_clauses = '(' . implode(' OR ', $path_clauses) . ')'; $where[] = $path_clauses; } if ($this->authors) { $where[] = qsprintf($conn_r, 'r.authorPHID IN (%Ls)', $this->authors); } if ($this->revIDs) { $where[] = qsprintf($conn_r, 'r.id IN (%Ld)', $this->revIDs); } if ($this->repositoryPHIDs) { $where[] = qsprintf($conn_r, 'r.repositoryPHID IN (%Ls)', $this->repositoryPHIDs); } if ($this->commitHashes) { $hash_clauses = array(); foreach ($this->commitHashes as $info) { list($type, $hash) = $info; $hash_clauses[] = qsprintf($conn_r, '(hash_rel.type = %s AND hash_rel.hash = %s)', $type, $hash); } $hash_clauses = '(' . implode(' OR ', $hash_clauses) . ')'; $where[] = $hash_clauses; } if ($this->commitPHIDs) { $where[] = qsprintf($conn_r, 'commits.commitPHID IN (%Ls)', $this->commitPHIDs); } if ($this->phids) { $where[] = qsprintf($conn_r, 'r.phid IN (%Ls)', $this->phids); } if ($this->branches) { $where[] = qsprintf($conn_r, 'r.branchName in (%Ls)', $this->branches); } if ($this->updatedEpochMin !== null) { $where[] = qsprintf($conn_r, 'r.dateModified >= %d', $this->updatedEpochMin); } if ($this->updatedEpochMax !== null) { $where[] = qsprintf($conn_r, 'r.dateModified <= %d', $this->updatedEpochMax); } // NOTE: Although the status constants are integers in PHP, the column is a // string column in MySQL, and MySQL won't use keys on string columns if // you put integers in the query. switch ($this->status) { case self::STATUS_ANY: break; case self::STATUS_OPEN: $where[] = qsprintf($conn_r, 'r.status IN (%Ls)', DifferentialRevisionStatus::getOpenStatuses()); break; case self::STATUS_NEEDS_REVIEW: $where[] = qsprintf($conn_r, 'r.status IN (%Ls)', array(ArcanistDifferentialRevisionStatus::NEEDS_REVIEW)); break; case self::STATUS_NEEDS_REVISION: $where[] = qsprintf($conn_r, 'r.status IN (%Ls)', array(ArcanistDifferentialRevisionStatus::NEEDS_REVISION)); break; case self::STATUS_ACCEPTED: $where[] = qsprintf($conn_r, 'r.status IN (%Ls)', array(ArcanistDifferentialRevisionStatus::ACCEPTED)); break; case self::STATUS_CLOSED: $where[] = qsprintf($conn_r, 'r.status IN (%Ls)', DifferentialRevisionStatus::getClosedStatuses()); break; case self::STATUS_ABANDONED: $where[] = qsprintf($conn_r, 'r.status IN (%Ls)', array(ArcanistDifferentialRevisionStatus::ABANDONED)); break; default: throw new Exception(pht("Unknown revision status filter constant '%s'!", $this->status)); } $where[] = $this->buildWhereClauseParts($conn_r); return $this->formatWhereClause($where); }
private function renderRevisionTable(array $revisions, $header, $nodata, array $handles, array $reviewer_map) { $rows = array(); foreach ($revisions as $revision) { $status = DifferentialRevisionStatus::getNameForRevisionStatus($revision->getStatus()); $reviewers = idx($reviewer_map, $revision->getID(), array()); if ($reviewers) { $first = reset($reviewers); if (count($reviewers) > 1) { $suffix = ' (+' . (count($reviewers) - 1) . ')'; } else { $suffix = null; } $reviewers = $handles[$first]->renderLink() . $suffix; } else { $reviewers = '<em>None</em>'; } $rows[] = array('D' . $revision->getID(), '<strong>' . phutil_render_tag('a', array('href' => '/D' . $revision->getID()), phutil_escape_html($revision->getTitle())) . '</strong>', phutil_escape_html($status), number_format($revision->getLineCount()), $handles[$revision->getAuthorPHID()]->renderLink(), $reviewers, phabricator_format_timestamp($revision->getDateModified()), phabricator_format_timestamp($revision->getDateCreated())); } $table = new AphrontTableView($rows); $table->setHeaders(array('ID', 'Revision', 'Status', 'Lines', 'Author', 'Reviewers', 'Updated', 'Created')); $table->setColumnClasses(array(null, 'wide', null, null, null, null, null, null)); if ($nodata !== null) { $table->setNoDataString($nodata); } $panel = new AphrontPanelView(); $panel->setHeader($header); $panel->appendChild($table); return $panel; }
private function getRevisionProperties(DifferentialRevision $revision, DifferentialDiff $diff, array $handles, array $diff_properties) { $properties = array(); $status = $revision->getStatus(); $next_step = null; if ($status == DifferentialRevisionStatus::ACCEPTED) { switch ($diff->getSourceControlSystem()) { case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: $next_step = 'arc amend --revision ' . $revision->getID(); break; case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: $next_step = 'arc commit --revision ' . $revision->getID(); break; } if ($next_step) { $next_step = ' · ' . 'Next step: <tt>' . phutil_escape_html($next_step) . '</tt>'; } } $status = DifferentialRevisionStatus::getNameForRevisionStatus($status); $properties['Revision Status'] = '<strong>' . $status . '</strong>' . $next_step; $author = $handles[$revision->getAuthorPHID()]; $properties['Author'] = $author->renderLink(); $properties['Reviewers'] = $this->renderHandleLinkList(array_select_keys($handles, $revision->getReviewers())); $properties['CCs'] = $this->renderHandleLinkList(array_select_keys($handles, $revision->getCCPHIDs())); $host = $diff->getSourceMachine(); if ($host) { $properties['Host'] = phutil_escape_html($host); } $path = $diff->getSourcePath(); if ($path) { $branch = $diff->getBranch() ? ' (' . $diff->getBranch() . ')' : ''; $properties['Path'] = phutil_escape_html("{$path} {$branch}"); } $lstar = DifferentialRevisionUpdateHistoryView::renderDiffLintStar($diff); $lmsg = DifferentialRevisionUpdateHistoryView::getDiffLintMessage($diff); $ldata = idx($diff_properties, 'arc:lint'); $ltail = null; if ($ldata) { $ldata = igroup($ldata, 'path'); $lint_messages = array(); foreach ($ldata as $path => $messages) { $message_markup = array(); foreach ($messages as $message) { $path = idx($message, 'path'); $line = idx($message, 'line'); $code = idx($message, 'code'); $severity = idx($message, 'severity'); $name = idx($message, 'name'); $description = idx($message, 'description'); $message_markup[] = '<li>' . '<span class="lint-severity-' . phutil_escape_html($severity) . '">' . phutil_escape_html(ucwords($severity)) . '</span>' . ' ' . '(' . phutil_escape_html($code) . ') ' . phutil_escape_html($name) . ' at line ' . phutil_escape_html($line) . '<p>' . phutil_escape_html($description) . '</p>' . '</li>'; } $lint_messages[] = '<li class="lint-file-block">' . 'Lint for <strong>' . phutil_escape_html($path) . '</strong>' . '<ul>' . implode("\n", $message_markup) . '</ul>' . '</li>'; } $ltail = '<div class="differential-lint-block">' . '<ul>' . implode("\n", $lint_messages) . '</ul>' . '</div>'; } $properties['Lint'] = $lstar . ' ' . $lmsg . $ltail; $ustar = DifferentialRevisionUpdateHistoryView::renderDiffUnitStar($diff); $umsg = DifferentialRevisionUpdateHistoryView::getDiffUnitMessage($diff); $postponed_count = 0; $udata = idx($diff_properties, 'arc:unit'); $utail = null; if ($udata) { $unit_messages = array(); foreach ($udata as $test) { $name = phutil_escape_html(idx($test, 'name')); $result = phutil_escape_html(idx($test, 'result')); if ($result != DifferentialUnitTestResult::RESULT_POSTPONED && $result != DifferentialUnitTestResult::RESULT_PASS) { $userdata = phutil_escape_html(idx($test, 'userdata')); if (strlen($userdata) > 256) { $userdata = substr($userdata, 0, 256) . '...'; } $userdata = str_replace("\n", '<br />', $userdata); $unit_messages[] = '<tr>' . '<th>' . $name . '</th>' . '<th class="unit-test-result">' . '<div class="result-' . $result . '">' . strtoupper($result) . '</div>' . '</th>' . '<td>' . $userdata . '</td>' . '</tr>'; $utail = '<div class="differential-unit-block">' . '<table class="differential-unit-table">' . implode("\n", $unit_messages) . '</table>' . '</div>'; } else { if ($result == DifferentialUnitTestResult::RESULT_POSTPONED) { $postponed_count++; } } } } if ($postponed_count > 0 && $diff->getUnitStatus() == DifferentialUnitStatus::UNIT_POSTPONED) { $umsg = $postponed_count . ' ' . $umsg; } $properties['Unit'] = $ustar . ' ' . $umsg . $utail; if (PhabricatorEnv::getEnvConfig('maniphest.enabled')) { $tasks = $revision->getAttachedPHIDs(PhabricatorPHIDConstants::PHID_TYPE_TASK); if ($tasks) { $links = array(); foreach ($tasks as $task_phid) { $links[] = $handles[$task_phid]->renderLink(); } $properties['Maniphest Tasks'] = implode('<br />', $links); } } $commit_phids = $revision->getCommitPHIDs(); if ($commit_phids) { $links = array(); foreach ($commit_phids as $commit_phid) { $links[] = $handles[$commit_phid]->renderLink(); } $properties['Commits'] = implode('<br />', $links); } $properties['Lines'] = number_format($diff->getLineCount()); $arcanist_phid = $diff->getArcanistProjectPHID(); if ($arcanist_phid) { $properties['Arcanist Project'] = phutil_escape_html($handles[$arcanist_phid]->getName()); } $properties['Apply Patch'] = '<tt>arc patch D' . $revision->getID() . '</tt>'; $properties['Export Patch'] = '<tt>arc export --revision ' . $revision->getID() . '</tt>'; return $properties; }