public function testURIGeneration()
 {
     $map = array('/diffusion/A/browse/branch/path.ext;abc$1' => array('action' => 'browse', 'callsign' => 'A', 'branch' => 'branch', 'path' => 'path.ext', 'commit' => 'abc', 'line' => '1'), '/diffusion/A/browse/a%252Fb/path.ext' => array('action' => 'browse', 'callsign' => 'A', 'branch' => 'a/b', 'path' => 'path.ext'), '/diffusion/A/browse/%2B/%20%21' => array('action' => 'browse', 'callsign' => 'A', 'path' => '+/ !'), '/diffusion/A/browse/money/%24%24100$2' => array('action' => 'browse', 'callsign' => 'A', 'path' => 'money/$100', 'line' => '2'), '/diffusion/A/browse/path/to/file.ext?view=things' => array('action' => 'browse', 'callsign' => 'A', 'path' => 'path/to/file.ext', 'params' => array('view' => 'things')), '/diffusion/A/repository/master/' => array('action' => 'branch', 'callsign' => 'A', 'branch' => 'master'), 'path/to/file.ext;abc' => array('action' => 'rendering-ref', 'path' => 'path/to/file.ext', 'commit' => 'abc'), '/diffusion/A/browse/branch/path.ext$3-5%2C7-12%2C14' => array('action' => 'browse', 'callsign' => 'A', 'branch' => 'branch', 'path' => 'path.ext', 'line' => '3-5,7-12,14'));
     foreach ($map as $expect => $input) {
         $actual = DiffusionRequest::generateDiffusionURI($input);
         $this->assertEqual($expect, (string) $actual);
     }
 }
 protected function renderResultList(array $repositories, PhabricatorSavedQuery $query, array $handles)
 {
     assert_instances_of($repositories, 'PhabricatorRepository');
     $viewer = $this->requireViewer();
     $list = new PHUIObjectItemListView();
     foreach ($repositories as $repository) {
         $id = $repository->getID();
         $item = id(new PHUIObjectItemView())->setUser($viewer)->setHeader($repository->getName())->setObjectName('r' . $repository->getCallsign())->setHref($this->getApplicationURI($repository->getCallsign() . '/'));
         $commit = $repository->getMostRecentCommit();
         if ($commit) {
             $commit_link = DiffusionView::linkCommit($repository, $commit->getCommitIdentifier(), $commit->getSummary());
             $item->setSubhead($commit_link);
             $item->setEpoch($commit->getEpoch());
         }
         $item->addIcon('none', PhabricatorRepositoryType::getNameForRepositoryType($repository->getVersionControlSystem()));
         $size = $repository->getCommitCount();
         if ($size) {
             $history_uri = DiffusionRequest::generateDiffusionURI(array('callsign' => $repository->getCallsign(), 'action' => 'history'));
             $item->addAttribute(phutil_tag('a', array('href' => $history_uri), pht('%s Commit(s)', new PhutilNumber($size))));
         } else {
             $item->addAttribute(pht('No Commits'));
         }
         $project_handles = array_select_keys($handles, $repository->getProjectPHIDs());
         if ($project_handles) {
             $item->addAttribute(id(new PHUIHandleTagListView())->setSlim(true)->setHandles($project_handles));
         }
         if (!$repository->isTracked()) {
             $item->setDisabled(true);
             $item->addIcon('disable-grey', pht('Inactive'));
         }
         $list->addItem($item);
     }
     return $list;
 }
 private function renderPathsTable(array $paths, array $repositories)
 {
     $viewer = $this->getViewer();
     $rows = array();
     foreach ($paths as $path) {
         $repo = idx($repositories, $path->getRepositoryPHID());
         if (!$repo) {
             continue;
         }
         $href = DiffusionRequest::generateDiffusionURI(array('callsign' => $repo->getCallsign(), 'branch' => $repo->getDefaultBranch(), 'path' => $path->getPath(), 'action' => 'browse'));
         $path_link = phutil_tag('a', array('href' => (string) $href), $path->getPath());
         $rows[] = array($path->getExcluded() ? '-' : '+', $repo->getName(), $path_link);
     }
     $info = null;
     if (!$paths) {
         $info = id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_WARNING)->setErrors(array(pht('This package does not contain any paths yet. Use ' . '"Edit Paths" to add some.')));
     }
     $table = id(new AphrontTableView($rows))->setHeaders(array(null, pht('Repository'), pht('Path')))->setColumnClasses(array(null, null, 'wide'));
     $box = id(new PHUIObjectBoxView())->setHeaderText(pht('Paths'))->setTable($table);
     if ($info) {
         $box->setInfoView($info);
     }
     return $box;
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $uri = $request->getStr('uri');
     $id = $request->getStr('id');
     $repositories = id(new PhabricatorRepository())->loadAll();
     if ($uri) {
         $uri_path = id(new PhutilURI($uri))->getPath();
         $matches = array();
         // Try to figure out which tracked repository this external lives in by
         // comparing repository metadata. We look for an exact match, but accept
         // a partial match.
         foreach ($repositories as $key => $repository) {
             $remote_uri = new PhutilURI($repository->getRemoteURI());
             if ($remote_uri->getPath() == $uri_path) {
                 $matches[$key] = 1;
             }
             if ($repository->getPublicRemoteURI() == $uri) {
                 $matches[$key] = 2;
             }
             if ($repository->getRemoteURI() == $uri) {
                 $matches[$key] = 3;
             }
         }
         arsort($matches);
         $best_match = head_key($matches);
         if ($best_match) {
             $repository = $repositories[$best_match];
             $redirect = DiffusionRequest::generateDiffusionURI(array('action' => 'browse', 'callsign' => $repository->getCallsign(), 'branch' => $repository->getDefaultBranch(), 'commit' => $id));
             return id(new AphrontRedirectResponse())->setURI($redirect);
         }
     }
     // TODO: This is a rare query but does a table scan, add a key?
     $commits = id(new PhabricatorRepositoryCommit())->loadAllWhere('commitIdentifier = %s', $id);
     if (empty($commits)) {
         $desc = null;
         if ($uri) {
             $desc = phutil_escape_html($uri) . ', at ';
         }
         $desc .= phutil_escape_html($id);
         $content = id(new AphrontErrorView())->setTitle('Unknown External')->setSeverity(AphrontErrorView::SEVERITY_WARNING)->appendChild("<p>This external ({$desc}) does not appear in any tracked " . "repository. It may exist in an untracked repository that " . "Diffusion does not know about.</p>");
     } else {
         if (count($commits) == 1) {
             $commit = head($commits);
             $repo = $repositories[$commit->getRepositoryID()];
             $redirect = DiffusionRequest::generateDiffusionURI(array('action' => 'browse', 'callsign' => $repo->getCallsign(), 'branch' => $repo->getDefaultBranch(), 'commit' => $commit->getCommitIdentifier()));
             return id(new AphrontRedirectResponse())->setURI($redirect);
         } else {
             $rows = array();
             foreach ($commits as $commit) {
                 $repo = $repositories[$commit->getRepositoryID()];
                 $href = DiffusionRequest::generateDiffusionURI(array('action' => 'browse', 'callsign' => $repo->getCallsign(), 'branch' => $repo->getDefaultBranch(), 'commit' => $commit->getCommitIdentifier()));
                 $rows[] = array(phutil_render_tag('a', array('href' => $href), phutil_escape_html('r' . $repo->getCallsign() . $commit->getCommitIdentifier())), phutil_escape_html($commit->loadCommitData()->getSummary()));
             }
             $table = new AphrontTableView($rows);
             $table->setHeaders(array('Commit', 'Description'));
             $table->setColumnClasses(array('pri', 'wide'));
             $content = new AphrontPanelView();
             $content->setHeader('Multiple Matching Commits');
             $content->setCaption('This external reference matches multiple known commits.');
             $content->appendChild($table);
         }
     }
     return $this->buildStandardPageResponse($content, array('title' => 'Unresolvable External'));
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $package = id(new PhabricatorOwnersPackage())->load($this->id);
     if (!$package) {
         return new Aphront404Response();
     }
     $this->package = $package;
     $paths = $package->loadPaths();
     $owners = $package->loadOwners();
     $repository_phids = array();
     foreach ($paths as $path) {
         $repository_phids[$path->getRepositoryPHID()] = true;
     }
     if ($repository_phids) {
         $repositories = id(new PhabricatorRepository())->loadAllWhere('phid in (%Ls)', array_keys($repository_phids));
         $repositories = mpull($repositories, null, 'getPHID');
     } else {
         $repositories = array();
     }
     $phids = array();
     foreach ($owners as $owner) {
         $phids[$owner->getUserPHID()] = true;
     }
     $phids = array_keys($phids);
     $handles = $this->loadViewerHandles($phids);
     $rows = array();
     $rows[] = array('Name', phutil_escape_html($package->getName()));
     $rows[] = array('Description', phutil_escape_html($package->getDescription()));
     $primary_owner = null;
     $primary_phid = $package->getPrimaryOwnerPHID();
     if ($primary_phid && isset($handles[$primary_phid])) {
         $primary_owner = '<strong>' . $handles[$primary_phid]->renderLink() . '</strong>';
     }
     $rows[] = array('Primary Owner', $primary_owner);
     $owner_links = array();
     foreach ($owners as $owner) {
         $owner_links[] = $handles[$owner->getUserPHID()]->renderLink();
     }
     $owner_links = implode('<br />', $owner_links);
     $rows[] = array('Owners', $owner_links);
     $rows[] = array('Auditing', $package->getAuditingEnabled() ? 'Enabled' : 'Disabled');
     $path_links = array();
     foreach ($paths as $path) {
         $repo = $repositories[$path->getRepositoryPHID()];
         $href = DiffusionRequest::generateDiffusionURI(array('callsign' => $repo->getCallsign(), 'branch' => $repo->getDefaultBranch(), 'path' => $path->getPath(), 'action' => 'browse'));
         $repo_name = '<strong>' . phutil_escape_html($repo->getName()) . '</strong>';
         $path_link = phutil_render_tag('a', array('href' => (string) $href), phutil_escape_html($path->getPath()));
         $path_links[] = $repo_name . ' ' . $path_link;
     }
     $path_links = implode('<br />', $path_links);
     $rows[] = array('Paths', $path_links);
     $table = new AphrontTableView($rows);
     $table->setColumnClasses(array('header', 'wide'));
     $panel = new AphrontPanelView();
     $panel->setHeader('Package Details for "' . phutil_escape_html($package->getName()) . '"');
     $panel->addButton(javelin_render_tag('a', array('href' => '/owners/delete/' . $package->getID() . '/', 'class' => 'button grey', 'sigil' => 'workflow'), 'Delete Package'));
     $panel->addButton(phutil_render_tag('a', array('href' => '/owners/edit/' . $package->getID() . '/', 'class' => 'button'), 'Edit Package'));
     $panel->appendChild($table);
     $key = 'package/' . $package->getID();
     $this->setSideNavFilter($key);
     $commit_views = array();
     $commit_uri = id(new PhutilURI('/audit/view/packagecommits/'))->setQueryParams(array('phid' => $package->getPHID()));
     $attention_query = id(new PhabricatorAuditCommitQuery())->withPackagePHIDs(array($package->getPHID()))->withStatus(PhabricatorAuditCommitQuery::STATUS_OPEN)->needCommitData(true)->needAudits(true)->setLimit(10);
     $attention_commits = $attention_query->execute();
     if ($attention_commits) {
         $view = new PhabricatorAuditCommitListView();
         $view->setUser($user);
         $view->setCommits($attention_commits);
         $commit_views[] = array('view' => $view, 'header' => 'Commits in this Package that Need Attention', 'button' => phutil_render_tag('a', array('href' => $commit_uri->alter('status', 'open'), 'class' => 'button grey'), 'View All Problem Commits'));
     }
     $all_query = id(new PhabricatorAuditCommitQuery())->withPackagePHIDs(array($package->getPHID()))->needCommitData(true)->needAudits(true)->setLimit(100);
     $all_commits = $all_query->execute();
     $view = new PhabricatorAuditCommitListView();
     $view->setUser($user);
     $view->setCommits($all_commits);
     $view->setNoDataString('No commits in this package.');
     $commit_views[] = array('view' => $view, 'header' => 'Recent Commits in Package', 'button' => phutil_render_tag('a', array('href' => $commit_uri, 'class' => 'button grey'), 'View All Package Commits'));
     $phids = array();
     foreach ($commit_views as $commit_view) {
         $phids[] = $commit_view['view']->getRequiredHandlePHIDs();
     }
     $phids = array_mergev($phids);
     $handles = $this->loadViewerHandles($phids);
     $commit_panels = array();
     foreach ($commit_views as $commit_view) {
         $commit_panel = new AphrontPanelView();
         $commit_panel->setHeader(phutil_escape_html($commit_view['header']));
         if (isset($commit_view['button'])) {
             $commit_panel->addButton($commit_view['button']);
         }
         $commit_view['view']->setHandles($handles);
         $commit_panel->appendChild($commit_view['view']);
         $commit_panels[] = $commit_panel;
     }
     return $this->buildStandardPageResponse(array($panel, $commit_panels), array('title' => "Package '" . $package->getName() . "'"));
 }
 protected function processDiffusionRequest(AphrontRequest $request)
 {
     $uri = $request->getStr('uri');
     $id = $request->getStr('id');
     $repositories = id(new PhabricatorRepositoryQuery())->setViewer($request->getUser())->execute();
     if ($uri) {
         $uri_path = id(new PhutilURI($uri))->getPath();
         $matches = array();
         // Try to figure out which tracked repository this external lives in by
         // comparing repository metadata. We look for an exact match, but accept
         // a partial match.
         foreach ($repositories as $key => $repository) {
             $remote_uri = new PhutilURI($repository->getRemoteURI());
             if ($remote_uri->getPath() == $uri_path) {
                 $matches[$key] = 1;
             }
             if ($repository->getPublicCloneURI() == $uri) {
                 $matches[$key] = 2;
             }
             if ($repository->getRemoteURI() == $uri) {
                 $matches[$key] = 3;
             }
         }
         arsort($matches);
         $best_match = head_key($matches);
         if ($best_match) {
             $repository = $repositories[$best_match];
             $redirect = DiffusionRequest::generateDiffusionURI(array('action' => 'browse', 'repository' => $repository, 'branch' => $repository->getDefaultBranch(), 'commit' => $id));
             return id(new AphrontRedirectResponse())->setURI($redirect);
         }
     }
     // TODO: This is a rare query but does a table scan, add a key?
     $commits = id(new PhabricatorRepositoryCommit())->loadAllWhere('commitIdentifier = %s', $id);
     if (empty($commits)) {
         $desc = null;
         if ($uri) {
             $desc = $uri . ', at ';
         }
         $desc .= $id;
         $content = id(new PHUIInfoView())->setTitle(pht('Unknown External'))->setSeverity(PHUIInfoView::SEVERITY_WARNING)->appendChild(phutil_tag('p', array(), pht('This external (%s) does not appear in any tracked ' . 'repository. It may exist in an untracked repository that ' . 'Diffusion does not know about.', $desc)));
     } else {
         if (count($commits) == 1) {
             $commit = head($commits);
             $repo = $repositories[$commit->getRepositoryID()];
             $redirect = DiffusionRequest::generateDiffusionURI(array('action' => 'browse', 'repository' => $repo, 'branch' => $repo->getDefaultBranch(), 'commit' => $commit->getCommitIdentifier()));
             return id(new AphrontRedirectResponse())->setURI($redirect);
         } else {
             $rows = array();
             foreach ($commits as $commit) {
                 $repo = $repositories[$commit->getRepositoryID()];
                 $href = DiffusionRequest::generateDiffusionURI(array('action' => 'browse', 'repository' => $repo, 'branch' => $repo->getDefaultBranch(), 'commit' => $commit->getCommitIdentifier()));
                 $rows[] = array(phutil_tag('a', array('href' => $href), $commit->getMonogram()), $commit->loadCommitData()->getSummary());
             }
             $table = new AphrontTableView($rows);
             $table->setHeaders(array(pht('Commit'), pht('Description')));
             $table->setColumnClasses(array('pri', 'wide'));
             $caption = id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_NOTICE)->appendChild(pht('This external reference matches multiple known commits.'));
             $content = new PHUIObjectBoxView();
             $content->setHeaderText(pht('Multiple Matching Commits'));
             $content->setInfoView($caption);
             $content->setTable($table);
         }
     }
     return $this->buildApplicationPage($content, array('title' => pht('Unresolvable External')));
 }
 private function renderPackageTable(array $packages, $header, $nodata)
 {
     assert_instances_of($packages, 'PhabricatorOwnersPackage');
     if ($packages) {
         $package_ids = mpull($packages, 'getID');
         $owners = id(new PhabricatorOwnersOwner())->loadAllWhere('packageID IN (%Ld)', $package_ids);
         $paths = id(new PhabricatorOwnersPath())->loadAllWhere('packageID in (%Ld)', $package_ids);
         $phids = array();
         foreach ($owners as $owner) {
             $phids[$owner->getUserPHID()] = true;
         }
         $phids = array_keys($phids);
         $handles = $this->loadViewerHandles($phids);
         $repository_phids = array();
         foreach ($paths as $path) {
             $repository_phids[$path->getRepositoryPHID()] = true;
         }
         if ($repository_phids) {
             $repositories = id(new PhabricatorRepositoryQuery())->setViewer($this->getRequest()->getUser())->withPHIDs(array_keys($repository_phids))->execute();
         } else {
             $repositories = array();
         }
         $repositories = mpull($repositories, null, 'getPHID');
         $owners = mgroup($owners, 'getPackageID');
         $paths = mgroup($paths, 'getPackageID');
     } else {
         $handles = array();
         $repositories = array();
         $owners = array();
         $paths = array();
     }
     $rows = array();
     foreach ($packages as $package) {
         $pkg_owners = idx($owners, $package->getID(), array());
         foreach ($pkg_owners as $key => $owner) {
             $pkg_owners[$key] = $handles[$owner->getUserPHID()]->renderLink();
             if ($owner->getUserPHID() == $package->getPrimaryOwnerPHID()) {
                 $pkg_owners[$key] = phutil_tag('strong', array(), $pkg_owners[$key]);
             }
         }
         $pkg_owners = phutil_implode_html(phutil_tag('br'), $pkg_owners);
         $pkg_paths = idx($paths, $package->getID(), array());
         foreach ($pkg_paths as $key => $path) {
             $repo = idx($repositories, $path->getRepositoryPHID());
             if ($repo) {
                 $href = DiffusionRequest::generateDiffusionURI(array('callsign' => $repo->getCallsign(), 'branch' => $repo->getDefaultBranch(), 'path' => $path->getPath(), 'action' => 'browse'));
                 $pkg_paths[$key] = hsprintf('%s %s%s', $path->getExcluded() ? "–" : '+', phutil_tag('strong', array(), $repo->getName()), phutil_tag('a', array('href' => (string) $href), $path->getPath()));
             } else {
                 $pkg_paths[$key] = $path->getPath();
             }
         }
         $pkg_paths = phutil_implode_html(phutil_tag('br'), $pkg_paths);
         $rows[] = array(phutil_tag('a', array('href' => '/owners/package/' . $package->getID() . '/'), $package->getName()), $pkg_owners, $pkg_paths, phutil_tag('a', array('href' => '/audit/view/packagecommits/?phid=' . $package->getPHID()), pht('Related Commits')));
     }
     $table = new AphrontTableView($rows);
     $table->setHeaders(array(pht('Name'), pht('Owners'), pht('Paths'), pht('Related Commits')));
     $table->setColumnClasses(array('pri', '', 'wide wrap', 'narrow'));
     $panel = new AphrontPanelView();
     $panel->setHeader($header);
     $panel->appendChild($table);
     $panel->setNoBackground();
     return $panel;
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $package = id(new PhabricatorOwnersPackage())->load($this->id);
     if (!$package) {
         return new Aphront404Response();
     }
     $this->package = $package;
     $paths = $package->loadPaths();
     $owners = $package->loadOwners();
     $repository_phids = array();
     foreach ($paths as $path) {
         $repository_phids[$path->getRepositoryPHID()] = true;
     }
     if ($repository_phids) {
         $repositories = id(new PhabricatorRepositoryQuery())->setViewer($user)->withPHIDs(array_keys($repository_phids))->execute();
         $repositories = mpull($repositories, null, 'getPHID');
     } else {
         $repositories = array();
     }
     $phids = array();
     foreach ($owners as $owner) {
         $phids[$owner->getUserPHID()] = true;
     }
     $phids = array_keys($phids);
     $handles = $this->loadViewerHandles($phids);
     $rows = array();
     $rows[] = array(pht('Name'), $package->getName());
     $rows[] = array(pht('Description'), $package->getDescription());
     $primary_owner = null;
     $primary_phid = $package->getPrimaryOwnerPHID();
     if ($primary_phid && isset($handles[$primary_phid])) {
         $primary_owner = phutil_tag('strong', array(), $handles[$primary_phid]->renderLink());
     }
     $rows[] = array(pht('Primary Owner'), $primary_owner);
     $owner_links = array();
     foreach ($owners as $owner) {
         $owner_links[] = $handles[$owner->getUserPHID()]->renderLink();
     }
     $owner_links = phutil_implode_html(phutil_tag('br'), $owner_links);
     $rows[] = array(pht('Owners'), $owner_links);
     $rows[] = array(pht('Auditing'), $package->getAuditingEnabled() ? pht('Enabled') : pht('Disabled'));
     $path_links = array();
     foreach ($paths as $path) {
         $repo = idx($repositories, $path->getRepositoryPHID());
         if (!$repo) {
             continue;
         }
         $href = DiffusionRequest::generateDiffusionURI(array('callsign' => $repo->getCallsign(), 'branch' => $repo->getDefaultBranch(), 'path' => $path->getPath(), 'action' => 'browse'));
         $repo_name = phutil_tag('strong', array(), $repo->getName());
         $path_link = phutil_tag('a', array('href' => (string) $href), $path->getPath());
         $path_links[] = hsprintf('%s %s %s', $path->getExcluded() ? "–" : '+', $repo_name, $path_link);
     }
     $path_links = phutil_implode_html(phutil_tag('br'), $path_links);
     $rows[] = array(pht('Paths'), $path_links);
     $table = new AphrontTableView($rows);
     $table->setColumnClasses(array('header', 'wide'));
     $panel = new AphrontPanelView();
     $panel->setNoBackground();
     $panel->setHeader(pht('Package Details for "%s"', $package->getName()));
     $panel->addButton(javelin_tag('a', array('href' => '/owners/delete/' . $package->getID() . '/', 'class' => 'button grey', 'sigil' => 'workflow'), pht('Delete Package')));
     $panel->addButton(phutil_tag('a', array('href' => '/owners/edit/' . $package->getID() . '/', 'class' => 'button'), pht('Edit Package')));
     $panel->appendChild($table);
     $key = 'package/' . $package->getID();
     $this->setSideNavFilter($key);
     $commit_views = array();
     $commit_uri = id(new PhutilURI('/audit/view/packagecommits/'))->setQueryParams(array('phid' => $package->getPHID()));
     $attention_commits = id(new DiffusionCommitQuery())->setViewer($request->getUser())->withAuditorPHIDs(array($package->getPHID()))->withAuditStatus(DiffusionCommitQuery::AUDIT_STATUS_CONCERN)->needCommitData(true)->setLimit(10)->execute();
     if ($attention_commits) {
         $view = id(new PhabricatorAuditListView())->setUser($user)->setCommits($attention_commits);
         $commit_views[] = array('view' => $view, 'header' => pht('Commits in this Package that Need Attention'), 'button' => phutil_tag('a', array('href' => $commit_uri->alter('status', 'open'), 'class' => 'button grey'), pht('View All Problem Commits')));
     }
     $all_commits = id(new DiffusionCommitQuery())->setViewer($request->getUser())->withAuditorPHIDs(array($package->getPHID()))->needCommitData(true)->setLimit(100)->execute();
     $view = id(new PhabricatorAuditListView())->setUser($user)->setCommits($all_commits)->setNoDataString(pht('No commits in this package.'));
     $commit_views[] = array('view' => $view, 'header' => pht('Recent Commits in Package'), 'button' => phutil_tag('a', array('href' => $commit_uri, 'class' => 'button grey'), pht('View All Package Commits')));
     $phids = array();
     foreach ($commit_views as $commit_view) {
         $phids[] = $commit_view['view']->getRequiredHandlePHIDs();
     }
     $phids = array_mergev($phids);
     $handles = $this->loadViewerHandles($phids);
     $commit_panels = array();
     foreach ($commit_views as $commit_view) {
         $commit_panel = new AphrontPanelView();
         $commit_panel->setNoBackground();
         $commit_panel->setHeader($commit_view['header']);
         if (isset($commit_view['button'])) {
             $commit_panel->addButton($commit_view['button']);
         }
         $commit_view['view']->setHandles($handles);
         $commit_panel->appendChild($commit_view['view']);
         $commit_panels[] = $commit_panel;
     }
     $nav = $this->buildSideNavView();
     $nav->appendChild($panel);
     $nav->appendChild($commit_panels);
     return $this->buildApplicationPage(array($nav), array('title' => pht('Package %s', $package->getName())));
 }