From f3549bb2d3e28ff2f206ef8333af158c73d9f25b Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 28 Feb 2012 21:10:39 -0800 Subject: [PATCH] Show commits in /audit/ Summary: The general idea here is to build a Differential-like dashboard which shows all the things you need to audit and all the things that other people have raised issues with, so you have a one-stop "what do I need to deal with?" interface. - Add problem commits to the "active" view of /audit/. - Add problem commits to homepage. - Add commit browsing interfaces to /audit/. - Add an "Audit" app button. Test Plan: Looked at homepage, commit filters. Audited commits, verified state changes reflected properly. Reviewers: btrahan, jungejason Reviewed By: btrahan CC: aran, epriestley Maniphest Tasks: T904 Differential Revision: https://secure.phabricator.com/D1712 --- src/__phutil_library_map__.php | 3 + .../list/PhabricatorAuditListController.php | 303 +++++++++++++----- .../audit/controller/list/__init__.php | 3 + .../commit/PhabricatorAuditCommitQuery.php | 177 ++++++++++ .../audit/query/commit/__init__.php | 19 ++ .../PhabricatorAuditCommitListView.php | 113 +++++++ .../audit/view/commitlist/__init__.php | 18 ++ .../view/list/PhabricatorAuditListView.php | 14 + .../PhabricatorDirectoryMainController.php | 61 +++- .../directory/controller/main/__init__.php | 2 + .../phid/handle/PhabricatorObjectHandle.php | 1 + .../data/PhabricatorObjectHandleData.php | 10 +- .../directory/phabricator-app-buttons.css | 4 + webroot/rsrc/image/apps.png | Bin 3436 -> 3972 bytes 14 files changed, 646 insertions(+), 82 deletions(-) create mode 100644 src/applications/audit/query/commit/PhabricatorAuditCommitQuery.php create mode 100644 src/applications/audit/query/commit/__init__.php create mode 100644 src/applications/audit/view/commitlist/PhabricatorAuditCommitListView.php create mode 100644 src/applications/audit/view/commitlist/__init__.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 39dae22d77..3b1408ebc8 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -445,6 +445,8 @@ phutil_register_library_map(array( 'PhabricatorAuditAddCommentController' => 'applications/audit/controller/addcomment', 'PhabricatorAuditComment' => 'applications/audit/storage/auditcomment', 'PhabricatorAuditCommentEditor' => 'applications/audit/editor/comment', + 'PhabricatorAuditCommitListView' => 'applications/audit/view/commitlist', + 'PhabricatorAuditCommitQuery' => 'applications/audit/query/commit', 'PhabricatorAuditCommitStatusConstants' => 'applications/audit/constants/commitstatus', 'PhabricatorAuditController' => 'applications/audit/controller/base', 'PhabricatorAuditDAO' => 'applications/audit/storage/base', @@ -1240,6 +1242,7 @@ phutil_register_library_map(array( 'Phabricator404Controller' => 'PhabricatorController', 'PhabricatorAuditAddCommentController' => 'PhabricatorAuditController', 'PhabricatorAuditComment' => 'PhabricatorAuditDAO', + 'PhabricatorAuditCommitListView' => 'AphrontView', 'PhabricatorAuditController' => 'PhabricatorController', 'PhabricatorAuditDAO' => 'PhabricatorLiskDAO', 'PhabricatorAuditEditController' => 'PhabricatorAuditController', diff --git a/src/applications/audit/controller/list/PhabricatorAuditListController.php b/src/applications/audit/controller/list/PhabricatorAuditListController.php index 834eb66e3b..c8884b5a1a 100644 --- a/src/applications/audit/controller/list/PhabricatorAuditListController.php +++ b/src/applications/audit/controller/list/PhabricatorAuditListController.php @@ -56,6 +56,7 @@ final class PhabricatorAuditListController extends PhabricatorAuditController { $message = 'Choose a project to view audits for.'; break; case 'package': + case 'packagecommits': $title = 'Choose a Package'; $message = 'Choose a package to view audits for.'; break; @@ -63,80 +64,15 @@ final class PhabricatorAuditListController extends PhabricatorAuditController { } if (!$message) { - $pager = new AphrontPagerView(); - $pager->setURI($request->getRequestURI(), 'offset'); - - $query = new PhabricatorAuditQuery(); - $query->setOffset($pager->getOffset()); - $query->setLimit($pager->getPageSize() + 1); - - $phids = null; - switch ($this->filter) { - case 'user': - case 'active': - $obj = id(new PhabricatorUser())->loadOneWhere( - 'phid = %s', - $handle->getPHID()); - if (!$obj) { - throw new Exception("Invalid user!"); - } - $phids = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($obj); - break; - case 'project': - case 'package': - $phids = array($handle->getPHID()); - break; - case 'all'; - break; - default: - throw new Exception("Unknown filter!"); - } - - if ($phids) { - $query->withAuditorPHIDs($phids); - } - - switch ($this->filter) { - case 'all': - case 'user': - case 'project': - case 'package': - switch ($this->filterStatus) { - case 'open': - $query->withStatus(PhabricatorAuditQuery::STATUS_OPEN); - break; - } - break; - case 'active': - $query->withStatus(PhabricatorAuditQuery::STATUS_OPEN); - break; - } - - $audits = $query->execute(); - $audits = $pager->sliceResults($audits); - - $view = new PhabricatorAuditListView(); - $view->setAudits($audits); - - $phids = $view->getRequiredHandlePHIDs(); - $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); - $view->setHandles($handles); - - $panel = new AphrontPanelView(); - $panel->appendChild($view); - $panel->setHeader('Audits'); - + $nav->appendChild($this->buildViews($handle)); } else { $panel = id(new AphrontErrorView()) ->setSeverity(AphrontErrorView::SEVERITY_NODATA) ->setTitle($title) ->appendChild($message); - $pager = null; + $nav->appendChild($panel); } - $nav->appendChild($panel); - $nav->appendChild($pager); - return $this->buildStandardPageResponse( $nav, array( @@ -149,11 +85,17 @@ final class PhabricatorAuditListController extends PhabricatorAuditController { $nav->setBaseURI(new PhutilURI('/audit/view/')); $nav->addLabel('Active'); $nav->addFilter('active', 'Need Attention'); + $nav->addLabel('Audits'); - $nav->addFilter('all', 'All'); - $nav->addFilter('user', 'By User'); - $nav->addFilter('project', 'By Project'); - $nav->addFilter('package', 'By Package'); + $nav->addFilter('audits', 'All'); + $nav->addFilter('user', 'By User'); + $nav->addFilter('project', 'By Project'); + $nav->addFilter('package', 'By Package'); + + $nav->addLabel('Commits'); + $nav->addFilter('commits', 'All'); + $nav->addFilter('author', 'By User'); + $nav->addFilter('packagecommits', 'By Package'); $this->filter = $nav->selectFilter($this->filter, 'active'); @@ -173,12 +115,14 @@ final class PhabricatorAuditListController extends PhabricatorAuditController { $show_package = false; switch ($this->filter) { - case 'all': + case 'audits': + case 'commits': $show_status = true; break; case 'active': $show_user = true; break; + case 'author': case 'user': $show_user = true; $show_status = true; @@ -188,6 +132,7 @@ final class PhabricatorAuditListController extends PhabricatorAuditController { $show_status = true; break; case 'package': + case 'packagecommits': $show_package = true; $show_status = true; break; @@ -251,6 +196,7 @@ final class PhabricatorAuditListController extends PhabricatorAuditController { switch ($this->filter) { case 'user': case 'active': + case 'author': $default = $request->getUser()->getPHID(); break; } @@ -272,11 +218,13 @@ final class PhabricatorAuditListController extends PhabricatorAuditController { switch ($this->filter) { case 'active': case 'user': + case 'author': if ($handle->getType() !== PhabricatorPHIDConstants::PHID_TYPE_USER) { throw new Exception("PHID must be a user PHID!"); } break; case 'package': + case 'packagecommits': if ($handle->getType() !== PhabricatorPHIDConstants::PHID_TYPE_OPKG) { throw new Exception("PHID must be a package PHID!"); } @@ -286,11 +234,220 @@ final class PhabricatorAuditListController extends PhabricatorAuditController { throw new Exception("PHID must be a project PHID!"); } break; - case 'all': + case 'audits': + case 'commits': break; default: throw new Exception("Unknown filter '{$this->filter}'!"); } } + private function buildViews(PhabricatorObjectHandle $handle = null) { + $views = array(); + switch ($this->filter) { + case 'active': + $views[] = $this->buildAuditView($handle); + $views[] = $this->buildCommitView($handle); + break; + case 'audits': + case 'user': + case 'package': + case 'project': + $views[] = $this->buildAuditView($handle); + break; + case 'commits': + case 'packagecommits': + case 'author': + $views[] = $this->buildCommitView($handle); + break; + } + return $views; + } + + private function buildAuditView(PhabricatorObjectHandle $handle = null) { + $request = $this->getRequest(); + + $pager = new AphrontPagerView(); + $pager->setURI($request->getRequestURI(), 'offset'); + + $query = new PhabricatorAuditQuery(); + + if ($this->filter != 'active') { + $query->setOffset($pager->getOffset()); + $query->setLimit($pager->getPageSize() + 1); + } + + $phids = null; + switch ($this->filter) { + case 'user': + case 'active': + $obj = id(new PhabricatorUser())->loadOneWhere( + 'phid = %s', + $handle->getPHID()); + if (!$obj) { + throw new Exception("Invalid user!"); + } + $phids = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($obj); + break; + case 'project': + case 'package': + $phids = array($handle->getPHID()); + break; + case 'audits'; + break; + default: + throw new Exception("Unknown filter!"); + } + + if ($phids) { + $query->withAuditorPHIDs($phids); + } + + switch ($this->filter) { + case 'audits': + case 'user': + case 'project': + case 'package': + switch ($this->filterStatus) { + case 'open': + $query->withStatus(PhabricatorAuditQuery::STATUS_OPEN); + break; + } + break; + case 'active': + $query->withStatus(PhabricatorAuditQuery::STATUS_OPEN); + break; + } + + if ($handle) { + $handle_name = phutil_escape_html($handle->getName()); + } else { + $handle_name = null; + } + + switch ($this->filter) { + case 'active': + $header = 'Required Audits'; + $nodata = 'No commits require your audit.'; + break; + case 'user': + $header = "Audits for {$handle_name}"; + $nodata = "No matching audits by {$handle_name}."; + break; + case 'audits': + $header = "Audits"; + $nodata = "No matching audits."; + break; + case 'project': + $header = "Audits in Project '{$handle_name}'"; + $nodata = "No matching audits in project '{$handle_name}'."; + break; + case 'package': + $header = "Audits for Package '{$handle_name}'"; + $nodata = "No matching audits in package '{$handle_name}'."; + break; + } + + $audits = $query->execute(); + $audits = $pager->sliceResults($audits); + + $view = new PhabricatorAuditListView(); + $view->setAudits($audits); + $view->setNoDataString($nodata); + + $phids = $view->getRequiredHandlePHIDs(); + $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); + $view->setHandles($handles); + + $panel = new AphrontPanelView(); + $panel->setHeader($header); + $panel->appendChild($view); + $panel->appendChild($pager); + + return $panel; + } + + private function buildCommitView(PhabricatorObjectHandle $handle = null) { + $request = $this->getRequest(); + + $pager = new AphrontPagerView(); + $pager->setURI($request->getRequestURI(), 'offset'); + + $query = new PhabricatorAuditCommitQuery(); + $query->needCommitData(true); + + if ($this->filter != 'active') { + $query->setOffset($pager->getOffset()); + $query->setLimit($pager->getPageSize() + 1); + } + + switch ($this->filter) { + case 'active': + case 'author': + $query->withAuthorPHIDs(array($handle->getPHID())); + break; + case 'packagecommits': + $query->withPackagePHIDs(array($handle->getPHID())); + break; + } + + switch ($this->filter) { + case 'active': + $query->withStatus(PhabricatorAuditQuery::STATUS_OPEN); + break; + case 'author': + case 'packagecommits': + switch ($this->filterStatus) { + case 'open': + $query->withStatus(PhabricatorAuditQuery::STATUS_OPEN); + break; + } + break; + } + + if ($handle) { + $handle_name = phutil_escape_html($handle->getName()); + } else { + $handle_name = null; + } + + switch ($this->filter) { + case 'active': + $header = 'Problem Commits'; + $nodata = 'None of your commits have open concerns.'; + break; + case 'author': + $header = "Commits by {$handle_name}"; + $nodata = "No matching commits by {$handle_name}."; + break; + case 'commits': + $header = "Commits"; + $nodata = "No matching commits."; + break; + case 'packagecommits': + $header = "Commits in Package '{$handle_name}'"; + $nodata = "No matching commits in package '{$handle_name}'."; + break; + } + + $commits = $query->execute(); + $commits = $pager->sliceResults($commits); + + $view = new PhabricatorAuditCommitListView(); + $view->setUser($request->getUser()); + $view->setCommits($commits); + $view->setNoDataString($nodata); + + $phids = $view->getRequiredHandlePHIDs(); + $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); + $view->setHandles($handles); + + $panel = new AphrontPanelView(); + $panel->setHeader($header); + $panel->appendChild($view); + $panel->appendChild($pager); + + return $panel; + } + } diff --git a/src/applications/audit/controller/list/__init__.php b/src/applications/audit/controller/list/__init__.php index bfad9b0a2e..a51c07782e 100644 --- a/src/applications/audit/controller/list/__init__.php +++ b/src/applications/audit/controller/list/__init__.php @@ -10,6 +10,8 @@ phutil_require_module('phabricator', 'aphront/response/redirect'); phutil_require_module('phabricator', 'applications/audit/controller/base'); phutil_require_module('phabricator', 'applications/audit/editor/comment'); phutil_require_module('phabricator', 'applications/audit/query/audit'); +phutil_require_module('phabricator', 'applications/audit/query/commit'); +phutil_require_module('phabricator', 'applications/audit/view/commitlist'); phutil_require_module('phabricator', 'applications/audit/view/list'); phutil_require_module('phabricator', 'applications/people/storage/user'); phutil_require_module('phabricator', 'applications/phid/constants'); @@ -24,6 +26,7 @@ phutil_require_module('phabricator', 'view/layout/listfilter'); phutil_require_module('phabricator', 'view/layout/panel'); phutil_require_module('phabricator', 'view/layout/sidenavfilter'); +phutil_require_module('phutil', 'markup'); phutil_require_module('phutil', 'parser/uri'); phutil_require_module('phutil', 'utils'); diff --git a/src/applications/audit/query/commit/PhabricatorAuditCommitQuery.php b/src/applications/audit/query/commit/PhabricatorAuditCommitQuery.php new file mode 100644 index 0000000000..131ffc833c --- /dev/null +++ b/src/applications/audit/query/commit/PhabricatorAuditCommitQuery.php @@ -0,0 +1,177 @@ +authorPHIDs = $author_phids; + return $this; + } + + public function withPackagePHIDs(array $phids) { + $this->packagePHIDs = $phids; + return $this; + } + + public function withStatus($status) { + $this->status = $status; + return $this; + } + + public function needCommitData($need) { + $this->needCommitData = $need; + return $this; + } + + public function setOffset($offset) { + $this->offset = $offset; + return $this; + } + + public function setLimit($limit) { + $this->limit = $limit; + return $this; + } + + public function execute() { + + if ($this->packagePHIDs) { + + // TODO: This is an odd, awkward query plan because these rows aren't + // on the same database as the commits. Once they're migrated we can + // resolve this via JOIN. + + $table = new PhabricatorOwnersPackageCommitRelationship(); + $conn_r = $table->establishConnection('r'); + $phids = queryfx_all( + $conn_r, + 'SELECT DISTINCT commitPHID FROM %T WHERE packagePHID IN (%Ls) + ORDER BY id DESC %Q', + $table->getTableName(), + $this->packagePHIDs, + $this->buildLimitClause($conn_r)); + $this->packageConstraint = ipull($phids, 'commitPHID'); + $this->limit = null; + $this->offset = null; + } + + $table = new PhabricatorRepositoryCommit(); + $conn_r = $table->establishConnection('r'); + + $where = $this->buildWhereClause($conn_r); + $order = $this->buildOrderClause($conn_r); + $limit = $this->buildLimitClause($conn_r); + + $data = queryfx_all( + $conn_r, + 'SELECT * FROM %T %Q %Q %Q', + $table->getTableName(), + $where, + $order, + $limit); + + $commits = $table->loadAllFromArray($data); + + if ($this->needCommitData && $commits) { + $data = id(new PhabricatorRepositoryCommitData())->loadAllWhere( + 'commitID in (%Ld)', + mpull($commits, 'getID')); + $data = mpull($data, null, 'getCommitID'); + foreach ($commits as $commit) { + if (idx($data, $commit->getID())) { + $commit->attachCommitData($data[$commit->getID()]); + } else { + $commit->attachCommitData(new PhabricatorRepositoryCommitData()); + } + } + } + + return $commits; + + } + + private function buildOrderClause($conn_r) { + return 'ORDER BY epoch DESC'; + } + + private function buildWhereClause($conn_r) { + $where = array(); + + if ($this->authorPHIDs) { + $where[] = qsprintf( + $conn_r, + 'authorPHID IN (%Ls)', + $this->authorPHIDs); + } + + if ($this->packageConstraint !== null) { + $where[] = qsprintf( + $conn_r, + 'phid IN (%Ls)', + $this->packageConstraint); + } + + $status = $this->status; + switch ($status) { + case self::STATUS_OPEN: + $where[] = qsprintf( + $conn_r, + 'auditStatus = %s', + PhabricatorAuditCommitStatusConstants::CONCERN_RAISED); + break; + case self::STATUS_ANY: + break; + default: + throw new Exception("Unknown status '{$status}'!"); + } + + if ($where) { + $where = 'WHERE ('.implode(') AND (', $where).')'; + } else { + $where = ''; + } + + return $where; + } + + private function buildLimitClause($conn_r) { + if ($this->limit && $this->offset) { + return qsprintf($conn_r, 'LIMIT %d, %d', $this->offset, $this->limit); + } else if ($this->limit) { + return qsprintf($conn_r, 'LIMIT %d', $this->limit); + } else if ($this->offset) { + return qsprintf($conn_r, 'LIMIT %d, %d', $this->offset, PHP_INT_MAX); + } else { + return ''; + } + } + +} diff --git a/src/applications/audit/query/commit/__init__.php b/src/applications/audit/query/commit/__init__.php new file mode 100644 index 0000000000..a3426b91b0 --- /dev/null +++ b/src/applications/audit/query/commit/__init__.php @@ -0,0 +1,19 @@ +user = $user; + return $this; + } + + public function setNoDataString($no_data_string) { + $this->noDataString = $no_data_string; + return $this; + } + + public function setCommits(array $commits) { + $this->commits = $commits; + return $this; + } + + public function setHandles(array $handles) { + $this->handles = $handles; + return $this; + } + + public function setAuthorityPHIDs(array $phids) { + $this->authorityPHIDs = $phids; + return $this; + } + + public function getRequiredHandlePHIDs() { + $phids = array(); + foreach ($this->commits as $commit) { + if ($commit->getAuthorPHID()) { + $phids[$commit->getAuthorPHID()] = true; + } + $phids[$commit->getPHID()] = true; + } + return array_keys($phids); + } + + private function getHandle($phid) { + $handle = idx($this->handles, $phid); + if (!$handle) { + throw new Exception("No handle for '{$phid}'!"); + } + return $handle; + } + + public function render() { + $rows = array(); + foreach ($this->commits as $commit) { + $commit_name = $this->getHandle($commit->getPHID())->renderLink(); + $author_name = null; + if ($commit->getAuthorPHID()) { + $author_name = $this->getHandle($commit->getAuthorPHID())->renderLink(); + } + $rows[] = array( + $commit_name, + $author_name, + phutil_escape_html($commit->getCommitData()->getSummary()), + PhabricatorAuditCommitStatusConstants::getStatusName( + $commit->getAuditStatus()), + phabricator_datetime($commit->getEpoch(), $this->user), + ); + } + + $table = new AphrontTableView($rows); + $table->setHeaders( + array( + 'Commit', + 'Author', + 'Summary', + 'Audit Status', + 'Date', + )); + $table->setColumnClasses( + array( + 'n', + '', + 'wide', + '', + '', + )); + + if ($this->noDataString) { + $table->setNoDataString($this->noDataString); + } + + return $table->render(); + } + +} diff --git a/src/applications/audit/view/commitlist/__init__.php b/src/applications/audit/view/commitlist/__init__.php new file mode 100644 index 0000000000..4f81e9041c --- /dev/null +++ b/src/applications/audit/view/commitlist/__init__.php @@ -0,0 +1,18 @@ +audits = $audits; @@ -37,6 +38,15 @@ final class PhabricatorAuditListView extends AphrontView { return $this; } + public function setNoDataString($no_data_string) { + $this->noDataString = $no_data_string; + return $this; + } + + public function getNoDataString() { + return $this->noDataString; + } + public function getRequiredHandlePHIDs() { $phids = array(); foreach ($this->audits as $audit) { @@ -112,6 +122,10 @@ final class PhabricatorAuditListView extends AphrontView { )); $table->setRowClasses($rowc); + if ($this->noDataString) { + $table->setNoDataString($this->noDataString); + } + return $table->render(); } diff --git a/src/applications/directory/controller/main/PhabricatorDirectoryMainController.php b/src/applications/directory/controller/main/PhabricatorDirectoryMainController.php index f14c1f0d12..e8a2cd9348 100644 --- a/src/applications/directory/controller/main/PhabricatorDirectoryMainController.php +++ b/src/applications/directory/controller/main/PhabricatorDirectoryMainController.php @@ -78,6 +78,7 @@ class PhabricatorDirectoryMainController $revision_panel = $this->buildRevisionPanel(); $app_panel = $this->buildAppPanel(); $audit_panel = $this->buildAuditPanel(); + $commit_panel = $this->buildCommitPanel(); $content = array( $app_panel, @@ -87,6 +88,7 @@ class PhabricatorDirectoryMainController $revision_panel, $tasks_panel, $audit_panel, + $commit_panel, ); $nav->appendChild($content); @@ -577,6 +579,11 @@ class PhabricatorDirectoryMainController '/diffusion/', 'diffusion'); + $nav_buttons[] = array( + 'Audit Code', + '/audit/', + 'audit'); + $view = new AphrontNullView(); $view->appendChild('
'); foreach ($nav_buttons as $info) { @@ -638,13 +645,9 @@ class PhabricatorDirectoryMainController $audits = $query->execute(); if (!$audits) { - $panel = new AphrontMiniPanelView(); - $panel->appendChild( - '

'. - 'No Audits: '. - 'No commits are waiting for you to audit them.'. - '

'); - return $panel; + return $this->renderMinipanel( + 'No Audits', + 'No commits are waiting for you to audit them.'); } $view = new PhabricatorAuditListView(); @@ -670,4 +673,48 @@ class PhabricatorDirectoryMainController return $panel; } + public function buildCommitPanel() { + $request = $this->getRequest(); + $user = $request->getUser(); + + $phids = array($user->getPHID()); + + $query = new PhabricatorAuditCommitQuery(); + $query->withAuthorPHIDs($phids); + $query->withStatus(PhabricatorAuditQuery::STATUS_OPEN); + $query->needCommitData(true); + $query->setLimit(10); + + $commits = $query->execute(); + + if (!$commits) { + return $this->renderMinipanel( + 'No Problem Commits', + 'No one has raised concerns with your commits.'); + } + + $view = new PhabricatorAuditCommitListView(); + $view->setCommits($commits); + $view->setUser($user); + + $phids = $view->getRequiredHandlePHIDs(); + $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); + $view->setHandles($handles); + + $panel = new AphrontPanelView(); + $panel->setHeader('Problem Commits'); + $panel->setCaption('Commits which auditors have raised concerns about.'); + $panel->appendChild($view); + $panel->addButton( + phutil_render_tag( + 'a', + array( + 'href' => '/audit/', + 'class' => 'button grey', + ), + "View Problem Commits \xC2\xBB")); + + return $panel; + } + } diff --git a/src/applications/directory/controller/main/__init__.php b/src/applications/directory/controller/main/__init__.php index 498c10dfa2..8b9c63a804 100644 --- a/src/applications/directory/controller/main/__init__.php +++ b/src/applications/directory/controller/main/__init__.php @@ -9,6 +9,8 @@ phutil_require_module('phabricator', 'aphront/response/redirect'); phutil_require_module('phabricator', 'applications/audit/editor/comment'); phutil_require_module('phabricator', 'applications/audit/query/audit'); +phutil_require_module('phabricator', 'applications/audit/query/commit'); +phutil_require_module('phabricator', 'applications/audit/view/commitlist'); phutil_require_module('phabricator', 'applications/audit/view/list'); phutil_require_module('phabricator', 'applications/differential/query/revision'); phutil_require_module('phabricator', 'applications/differential/view/revisionlist'); diff --git a/src/applications/phid/handle/PhabricatorObjectHandle.php b/src/applications/phid/handle/PhabricatorObjectHandle.php index 08dd34d347..1d3633c51c 100644 --- a/src/applications/phid/handle/PhabricatorObjectHandle.php +++ b/src/applications/phid/handle/PhabricatorObjectHandle.php @@ -218,6 +218,7 @@ class PhabricatorObjectHandle { public function getLinkName() { switch ($this->getType()) { case PhabricatorPHIDConstants::PHID_TYPE_USER: + case PhabricatorPHIDConstants::PHID_TYPE_CMIT: $name = $this->getName(); break; default: diff --git a/src/applications/phid/handle/data/PhabricatorObjectHandleData.php b/src/applications/phid/handle/data/PhabricatorObjectHandleData.php index 2e757ff4d5..1aca83d594 100644 --- a/src/applications/phid/handle/data/PhabricatorObjectHandleData.php +++ b/src/applications/phid/handle/data/PhabricatorObjectHandleData.php @@ -265,8 +265,14 @@ class PhabricatorObjectHandleData { // we don't have have info about the repository anymore. if ($repository) { $vcs = $repository->getVersionControlSystem(); - if ($vcs == PhabricatorRepositoryType::REPOSITORY_TYPE_GIT) { - $short_identifier = substr($commit_identifier, 0, 16); + + $type_git = PhabricatorRepositoryType::REPOSITORY_TYPE_GIT; + $type_hg = PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL; + + $is_git = ($vcs == $type_git); + $is_hg = ($vcs == $type_hg); + if ($is_git || $is_hg) { + $short_identifier = substr($commit_identifier, 0, 12); } else { $short_identifier = $commit_identifier; } diff --git a/webroot/rsrc/css/application/directory/phabricator-app-buttons.css b/webroot/rsrc/css/application/directory/phabricator-app-buttons.css index 3ef867fa95..a411c119a2 100644 --- a/webroot/rsrc/css/application/directory/phabricator-app-buttons.css +++ b/webroot/rsrc/css/application/directory/phabricator-app-buttons.css @@ -97,3 +97,7 @@ a.phabricator-button-caption:visited { .icon-diffusion { background-position: 0 -300px; } + +.icon-audit { + background-position: 0 -350px; +} diff --git a/webroot/rsrc/image/apps.png b/webroot/rsrc/image/apps.png index 69a54bd4baa913c6321d43db37f5366e631b1995..4e0aaa83389a42c1324d896869f6a2924de5cb95 100644 GIT binary patch delta 3815 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 delta 3286 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