public static function renderLastModifiedColumns(PhabricatorRepository $repository, array $handles, PhabricatorRepositoryCommit $commit = null, PhabricatorRepositoryCommitData $data = null)
 {
     if ($commit) {
         $epoch = $commit->getEpoch();
         $modified = DiffusionView::linkCommit($repository, $commit->getCommitIdentifier());
         $date = date('M j, Y', $epoch);
         $time = date('g:i A', $epoch);
     } else {
         $modified = '';
         $date = '';
         $time = '';
     }
     if ($data) {
         $author_phid = $data->getCommitDetail('authorPHID');
         if ($author_phid && isset($handles[$author_phid])) {
             $author = $handles[$author_phid]->renderLink();
         } else {
             $author = phutil_escape_html($data->getAuthorName());
         }
         $details = AphrontTableView::renderSingleDisplayLine(phutil_escape_html($data->getSummary()));
     } else {
         $author = '';
         $details = '';
     }
     return array('commit' => $modified, 'date' => $date, 'time' => $time, 'author' => $author, 'details' => $details);
 }
 public function renderForDisplay(PhabricatorUser $viewer)
 {
     $suffix = parent::renderForDisplay($viewer);
     $commit = id(new DiffusionCommitQuery())->setViewer($viewer)->withIDs(array(idx($this->getTaskData(), 'commitID')))->executeOne();
     if (!$commit) {
         return $suffix;
     }
     $link = DiffusionView::linkCommit($commit->getRepository(), $commit->getCommitIdentifier());
     return array($link, $suffix);
 }
 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;
 }
 protected function processDiffusionRequest(AphrontRequest $request)
 {
     $user = $request->getUser();
     // This controller doesn't use blob/path stuff, just pass the dictionary
     // in directly instead of using the AphrontRequest parsing mechanism.
     $data = $request->getURIMap();
     $data['user'] = $user;
     $drequest = DiffusionRequest::newFromDictionary($data);
     $this->diffusionRequest = $drequest;
     if ($request->getStr('diff')) {
         return $this->buildRawDiffResponse($drequest);
     }
     $repository = $drequest->getRepository();
     $callsign = $repository->getCallsign();
     $content = array();
     $commit = id(new DiffusionCommitQuery())->setViewer($request->getUser())->withRepository($repository)->withIdentifiers(array($drequest->getCommit()))->needCommitData(true)->needAuditRequests(true)->executeOne();
     $crumbs = $this->buildCrumbs(array('commit' => true));
     if (!$commit) {
         $exists = $this->callConduitWithDiffusionRequest('diffusion.existsquery', array('commit' => $drequest->getCommit()));
         if (!$exists) {
             return new Aphront404Response();
         }
         $error = id(new PHUIInfoView())->setTitle(pht('Commit Still Parsing'))->appendChild(pht('Failed to load the commit because the commit has not been ' . 'parsed yet.'));
         return $this->buildApplicationPage(array($crumbs, $error), array('title' => pht('Commit Still Parsing')));
     }
     $audit_requests = $commit->getAudits();
     $this->auditAuthorityPHIDs = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($user);
     $commit_data = $commit->getCommitData();
     $is_foreign = $commit_data->getCommitDetail('foreign-svn-stub');
     if ($is_foreign) {
         $subpath = $commit_data->getCommitDetail('svn-subpath');
         $error_panel = new PHUIInfoView();
         $error_panel->setTitle(pht('Commit Not Tracked'));
         $error_panel->setSeverity(PHUIInfoView::SEVERITY_WARNING);
         $error_panel->appendChild(pht("This Diffusion repository is configured to track only one " . "subdirectory of the entire Subversion repository, and this commit " . "didn't affect the tracked subdirectory ('%s'), so no " . "information is available.", $subpath));
         $content[] = $error_panel;
     } else {
         $engine = PhabricatorMarkupEngine::newDifferentialMarkupEngine();
         $engine->setConfig('viewer', $user);
         require_celerity_resource('phabricator-remarkup-css');
         $parents = $this->callConduitWithDiffusionRequest('diffusion.commitparentsquery', array('commit' => $drequest->getCommit()));
         if ($parents) {
             $parents = id(new DiffusionCommitQuery())->setViewer($user)->withRepository($repository)->withIdentifiers($parents)->execute();
         }
         $headsup_view = id(new PHUIHeaderView())->setHeader(nonempty($commit->getSummary(), pht('Commit Detail')));
         $headsup_actions = $this->renderHeadsupActionList($commit, $repository);
         $commit_properties = $this->loadCommitProperties($commit, $commit_data, $parents, $audit_requests);
         $property_list = id(new PHUIPropertyListView())->setHasKeyboardShortcuts(true)->setUser($user)->setObject($commit);
         foreach ($commit_properties as $key => $value) {
             $property_list->addProperty($key, $value);
         }
         $message = $commit_data->getCommitMessage();
         $revision = $commit->getCommitIdentifier();
         $message = $this->linkBugtraq($message);
         $message = $engine->markupText($message);
         $property_list->invokeWillRenderEvent();
         $property_list->setActionList($headsup_actions);
         $detail_list = new PHUIPropertyListView();
         $detail_list->addSectionHeader(pht('Description'), PHUIPropertyListView::ICON_SUMMARY);
         $detail_list->addTextContent(phutil_tag('div', array('class' => 'diffusion-commit-message phabricator-remarkup'), $message));
         $headsup_view->setTall(true);
         $object_box = id(new PHUIObjectBoxView())->setHeader($headsup_view)->addPropertyList($property_list)->addPropertyList($detail_list);
         $content[] = $object_box;
     }
     $content[] = $this->buildComments($commit);
     $hard_limit = 1000;
     if ($commit->isImported()) {
         $change_query = DiffusionPathChangeQuery::newFromDiffusionRequest($drequest);
         $change_query->setLimit($hard_limit + 1);
         $changes = $change_query->loadChanges();
     } else {
         $changes = array();
     }
     $was_limited = count($changes) > $hard_limit;
     if ($was_limited) {
         $changes = array_slice($changes, 0, $hard_limit);
     }
     $content[] = $this->buildMergesTable($commit);
     $highlighted_audits = $commit->getAuthorityAudits($user, $this->auditAuthorityPHIDs);
     $count = count($changes);
     $bad_commit = null;
     if ($count == 0) {
         $bad_commit = queryfx_one(id(new PhabricatorRepository())->establishConnection('r'), 'SELECT * FROM %T WHERE fullCommitName = %s', PhabricatorRepository::TABLE_BADCOMMIT, 'r' . $callsign . $commit->getCommitIdentifier());
     }
     $show_changesets = false;
     if ($bad_commit) {
         $content[] = $this->renderStatusMessage(pht('Bad Commit'), $bad_commit['description']);
     } else {
         if ($is_foreign) {
             // Don't render anything else.
         } else {
             if (!$commit->isImported()) {
                 $content[] = $this->renderStatusMessage(pht('Still Importing...'), pht('This commit is still importing. Changes will be visible once ' . 'the import finishes.'));
             } else {
                 if (!count($changes)) {
                     $content[] = $this->renderStatusMessage(pht('Empty Commit'), pht('This commit is empty and does not affect any paths.'));
                 } else {
                     if ($was_limited) {
                         $content[] = $this->renderStatusMessage(pht('Enormous Commit'), pht('This commit is enormous, and affects more than %d files. ' . 'Changes are not shown.', $hard_limit));
                     } else {
                         $show_changesets = true;
                         // The user has clicked "Show All Changes", and we should show all the
                         // changes inline even if there are more than the soft limit.
                         $show_all_details = $request->getBool('show_all');
                         $change_panel = new PHUIObjectBoxView();
                         $header = new PHUIHeaderView();
                         $header->setHeader(pht('Changes (%s)', new PhutilNumber($count)));
                         $change_panel->setID('toc');
                         if ($count > self::CHANGES_LIMIT && !$show_all_details) {
                             $icon = id(new PHUIIconView())->setIconFont('fa-files-o');
                             $button = id(new PHUIButtonView())->setText(pht('Show All Changes'))->setHref('?show_all=true')->setTag('a')->setIcon($icon);
                             $warning_view = id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_WARNING)->setTitle(pht('Very Large Commit'))->appendChild(pht('This commit is very large. Load each file individually.'));
                             $change_panel->setInfoView($warning_view);
                             $header->addActionLink($button);
                         }
                         $changesets = DiffusionPathChange::convertToDifferentialChangesets($user, $changes);
                         // TODO: This table and panel shouldn't really be separate, but we need
                         // to clean up the "Load All Files" interaction first.
                         $change_table = $this->buildTableOfContents($changesets);
                         $change_panel->setTable($change_table);
                         $change_panel->setHeader($header);
                         $content[] = $change_panel;
                         $vcs = $repository->getVersionControlSystem();
                         switch ($vcs) {
                             case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
                                 $vcs_supports_directory_changes = true;
                                 break;
                             case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
                             case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
                                 $vcs_supports_directory_changes = false;
                                 break;
                             default:
                                 throw new Exception(pht('Unknown VCS.'));
                         }
                         $references = array();
                         foreach ($changesets as $key => $changeset) {
                             $file_type = $changeset->getFileType();
                             if ($file_type == DifferentialChangeType::FILE_DIRECTORY) {
                                 if (!$vcs_supports_directory_changes) {
                                     unset($changesets[$key]);
                                     continue;
                                 }
                             }
                             $references[$key] = $drequest->generateURI(array('action' => 'rendering-ref', 'path' => $changeset->getFilename()));
                         }
                         // TODO: Some parts of the views still rely on properties of the
                         // DifferentialChangeset. Make the objects ephemeral to make sure we don't
                         // accidentally save them, and then set their ID to the appropriate ID for
                         // this application (the path IDs).
                         $path_ids = array_flip(mpull($changes, 'getPath'));
                         foreach ($changesets as $changeset) {
                             $changeset->makeEphemeral();
                             $changeset->setID($path_ids[$changeset->getFilename()]);
                         }
                         if ($count <= self::CHANGES_LIMIT || $show_all_details) {
                             $visible_changesets = $changesets;
                         } else {
                             $visible_changesets = array();
                             $inlines = PhabricatorAuditInlineComment::loadDraftAndPublishedComments($user, $commit->getPHID());
                             $path_ids = mpull($inlines, null, 'getPathID');
                             foreach ($changesets as $key => $changeset) {
                                 if (array_key_exists($changeset->getID(), $path_ids)) {
                                     $visible_changesets[$key] = $changeset;
                                 }
                             }
                         }
                         $change_list_title = DiffusionView::nameCommit($repository, $commit->getCommitIdentifier());
                         $change_list = new DifferentialChangesetListView();
                         $change_list->setTitle($change_list_title);
                         $change_list->setChangesets($changesets);
                         $change_list->setVisibleChangesets($visible_changesets);
                         $change_list->setRenderingReferences($references);
                         $change_list->setRenderURI('/diffusion/' . $callsign . '/diff/');
                         $change_list->setRepository($repository);
                         $change_list->setUser($user);
                         // TODO: Try to setBranch() to something reasonable here?
                         $change_list->setStandaloneURI('/diffusion/' . $callsign . '/diff/');
                         $change_list->setRawFileURIs(null, '/diffusion/' . $callsign . '/diff/?view=r');
                         $change_list->setInlineCommentControllerURI('/diffusion/inline/edit/' . phutil_escape_uri($commit->getPHID()) . '/');
                         $content[] = $change_list->render();
                     }
                 }
             }
         }
     }
     $content[] = $this->renderAddCommentPanel($commit, $audit_requests);
     $commit_id = 'r' . $callsign . $commit->getCommitIdentifier();
     $short_name = DiffusionView::nameCommit($repository, $commit->getCommitIdentifier());
     $prefs = $user->loadPreferences();
     $pref_filetree = PhabricatorUserPreferences::PREFERENCE_DIFF_FILETREE;
     $pref_collapse = PhabricatorUserPreferences::PREFERENCE_NAV_COLLAPSED;
     $show_filetree = $prefs->getPreference($pref_filetree);
     $collapsed = $prefs->getPreference($pref_collapse);
     if ($show_changesets && $show_filetree) {
         $nav = id(new DifferentialChangesetFileTreeSideNavBuilder())->setTitle($short_name)->setBaseURI(new PhutilURI('/' . $commit_id))->build($changesets)->setCrumbs($crumbs)->setCollapsed((bool) $collapsed)->appendChild($content);
         $content = $nav;
     } else {
         $content = array($crumbs, $content);
     }
     return $this->buildApplicationPage($content, array('title' => $commit_id, 'pageObjects' => array($commit->getPHID())));
 }
Ejemplo n.º 5
0
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $shortcuts = id(new PhabricatorRepositoryShortcut())->loadAll();
     if ($shortcuts) {
         $shortcuts = msort($shortcuts, 'getSequence');
         $rows = array();
         foreach ($shortcuts as $shortcut) {
             $rows[] = array(phutil_render_tag('a', array('href' => $shortcut->getHref()), phutil_escape_html($shortcut->getName())), phutil_escape_html($shortcut->getDescription()));
         }
         $shortcut_table = new AphrontTableView($rows);
         $shortcut_table->setHeaders(array('Link', ''));
         $shortcut_table->setColumnClasses(array('pri', 'wide'));
         $shortcut_panel = new AphrontPanelView();
         $shortcut_panel->setHeader('Shortcuts');
         $shortcut_panel->appendChild($shortcut_table);
     } else {
         $shortcut_panel = null;
     }
     $repository = new PhabricatorRepository();
     $repositories = $repository->loadAll();
     foreach ($repositories as $key => $repo) {
         if (!$repo->isTracked()) {
             unset($repositories[$key]);
         }
     }
     $repository_ids = mpull($repositories, 'getID');
     $summaries = array();
     $commits = array();
     if ($repository_ids) {
         $summaries = queryfx_all($repository->establishConnection('r'), 'SELECT * FROM %T WHERE repositoryID IN (%Ld)', PhabricatorRepository::TABLE_SUMMARY, $repository_ids);
         $summaries = ipull($summaries, null, 'repositoryID');
         $commit_ids = array_filter(ipull($summaries, 'lastCommitID'));
         if ($commit_ids) {
             $commit = new PhabricatorRepositoryCommit();
             $commits = $commit->loadAllWhere('id IN (%Ld)', $commit_ids);
             $commits = mpull($commits, null, 'getRepositoryID');
         }
     }
     $rows = array();
     foreach ($repositories as $repository) {
         $id = $repository->getID();
         $commit = idx($commits, $id);
         $size = idx(idx($summaries, $id, array()), 'size', 0);
         $date = '-';
         $time = '-';
         if ($commit) {
             $date = phabricator_date($commit->getEpoch(), $user);
             $time = phabricator_time($commit->getEpoch(), $user);
         }
         $rows[] = array(phutil_render_tag('a', array('href' => '/diffusion/' . $repository->getCallsign() . '/'), phutil_escape_html($repository->getName())), phutil_escape_html($repository->getDetail('description')), PhabricatorRepositoryType::getNameForRepositoryType($repository->getVersionControlSystem()), $size ? number_format($size) : '-', $commit ? DiffusionView::linkCommit($repository, $commit->getCommitIdentifier()) : '-', $date, $time);
     }
     $repository_tool_uri = PhabricatorEnv::getProductionURI('/repository/');
     $repository_tool = phutil_render_tag('a', array('href' => $repository_tool_uri), 'repository tool');
     $no_repositories_txt = 'This instance of Phabricator does not have any ' . 'configured repositories. ';
     if ($user->getIsAdmin()) {
         $no_repositories_txt .= 'To setup one or more repositories, visit the ' . $repository_tool . '.';
     } else {
         $no_repositories_txt .= 'Ask an administrator to setup one or more ' . 'repositories via the ' . $repository_tool . '.';
     }
     $table = new AphrontTableView($rows);
     $table->setNoDataString($no_repositories_txt);
     $table->setHeaders(array('Repository', 'Description', 'VCS', 'Commits', 'Last', 'Date', 'Time'));
     $table->setColumnClasses(array('pri', 'wide', '', 'n', 'n', '', 'right'));
     $panel = new AphrontPanelView();
     $panel->setHeader('Browse Repositories');
     $panel->appendChild($table);
     $crumbs = $this->buildCrumbs();
     return $this->buildStandardPageResponse(array($crumbs, $shortcut_panel, $panel), array('title' => 'Diffusion'));
 }
 private function renderColumns(DiffusionRequest $drequest, array $handles, PhabricatorRepositoryCommit $commit = null, $lint = null)
 {
     assert_instances_of($handles, 'PhabricatorObjectHandle');
     $viewer = $this->getRequest()->getUser();
     if ($commit) {
         $epoch = $commit->getEpoch();
         $modified = DiffusionView::linkCommit($drequest->getRepository(), $commit->getCommitIdentifier());
         $date = phabricator_date($epoch, $viewer);
         $time = phabricator_time($epoch, $viewer);
     } else {
         $modified = '';
         $date = '';
         $time = '';
     }
     $data = $commit->getCommitData();
     if ($data) {
         $author_phid = $data->getCommitDetail('authorPHID');
         if ($author_phid && isset($handles[$author_phid])) {
             $author = $handles[$author_phid]->renderLink();
         } else {
             $author = DiffusionView::renderName($data->getAuthorName());
         }
         $committer = $data->getCommitDetail('committer');
         if ($committer) {
             $committer_phid = $data->getCommitDetail('committerPHID');
             if ($committer_phid && isset($handles[$committer_phid])) {
                 $committer = $handles[$committer_phid]->renderLink();
             } else {
                 $committer = DiffusionView::renderName($committer);
             }
             if ($author != $committer) {
                 $author = hsprintf('%s/%s', $author, $committer);
             }
         }
         $details = AphrontTableView::renderSingleDisplayLine($data->getSummary());
     } else {
         $author = '';
         $details = '';
     }
     $return = array('commit' => $modified, 'date' => $date, 'time' => $time, 'author' => $author, 'details' => $details);
     if ($lint !== null) {
         $return['lint'] = phutil_tag('a', array('href' => $drequest->generateURI(array('action' => 'lint', 'lint' => null))), number_format($lint));
     }
     // The client treats these results as markup, so make sure they have been
     // escaped correctly.
     foreach ($return as $key => $value) {
         $return[$key] = hsprintf('%s', $value);
     }
     return $return;
 }
Ejemplo n.º 7
0
 private function buildCrumbList(array $spec = array())
 {
     $spec = $spec + array('commit' => null, 'tags' => null, 'branches' => null, 'view' => null);
     $crumb_list = array();
     // On the home page, we don't have a DiffusionRequest.
     if ($this->diffusionRequest) {
         $drequest = $this->getDiffusionRequest();
         $repository = $drequest->getRepository();
     } else {
         $drequest = null;
         $repository = null;
     }
     if ($repository) {
         $crumb_list[] = phutil_render_tag('a', array('href' => '/diffusion/'), 'Diffusion');
     } else {
         $crumb_list[] = 'Diffusion';
         return $crumb_list;
     }
     $callsign = $repository->getCallsign();
     $repository_name = phutil_escape_html($repository->getName()) . ' Repository';
     if (!$spec['commit'] && !$spec['tags'] && !$spec['branches']) {
         $branch_name = $drequest->getBranch();
         if ($branch_name) {
             $repository_name .= ' (' . phutil_escape_html($branch_name) . ')';
         }
     }
     if (!$spec['view'] && !$spec['commit'] && !$spec['tags'] && !$spec['branches']) {
         $crumb_list[] = $repository_name;
         return $crumb_list;
     }
     $crumb_list[] = phutil_render_tag('a', array('href' => "/diffusion/{$callsign}/"), $repository_name);
     $raw_commit = $drequest->getRawCommit();
     if ($spec['tags']) {
         if ($spec['commit']) {
             $crumb_list[] = "Tags for " . phutil_render_tag('a', array('href' => $drequest->generateURI(array('action' => 'commit', 'commit' => $raw_commit))), phutil_escape_html("r{$callsign}{$raw_commit}"));
         } else {
             $crumb_list[] = 'Tags';
         }
         return $crumb_list;
     }
     if ($spec['branches']) {
         $crumb_list[] = 'Branches';
         return $crumb_list;
     }
     if ($spec['commit']) {
         $crumb_list[] = "r{$callsign}{$raw_commit}";
         return $crumb_list;
     }
     $view = $spec['view'];
     $path = null;
     if (isset($spec['path'])) {
         $path = $drequest->getPath();
     }
     if ($raw_commit) {
         $commit_link = DiffusionView::linkCommit($repository, $raw_commit);
     } else {
         $commit_link = '';
     }
     switch ($view) {
         case 'history':
             $view_name = 'History';
             break;
         case 'browse':
             $view_name = 'Browse';
             break;
         case 'change':
             $view_name = 'Change';
             $crumb_list[] = phutil_escape_html($path) . ' (' . $commit_link . ')';
             return $crumb_list;
     }
     $uri_params = array('action' => $view);
     if (!strlen($path)) {
         $crumb_list[] = $view_name;
     } else {
         $crumb_list[] = phutil_render_tag('a', array('href' => $drequest->generateURI(array('path' => '') + $uri_params)), $view_name);
         $path_parts = explode('/', $path);
         do {
             $last = array_pop($path_parts);
         } while ($last == '');
         $path_sections = array();
         $thus_far = '';
         foreach ($path_parts as $path_part) {
             $thus_far .= $path_part . '/';
             $path_sections[] = phutil_render_tag('a', array('href' => $drequest->generateURI(array('path' => $thus_far) + $uri_params)), phutil_escape_html($path_part));
         }
         $path_sections[] = phutil_escape_html($last);
         $path_sections = '/' . implode('/', $path_sections);
         $crumb_list[] = $path_sections;
     }
     $last_crumb = array_pop($crumb_list);
     if ($raw_commit) {
         $jump_link = phutil_render_tag('a', array('href' => $drequest->generateURI(array('commit' => '') + $uri_params)), 'Jump to HEAD');
         $last_crumb .= " @ {$commit_link} ({$jump_link})";
     } else {
         $last_crumb .= " @ HEAD";
     }
     $crumb_list[] = $last_crumb;
     return $crumb_list;
 }
Ejemplo n.º 8
0
 private function buildCrumbList(array $spec = array())
 {
     $drequest = $this->getDiffusionRequest();
     $crumb_list = array();
     $repository = $drequest->getRepository();
     if ($repository) {
         $crumb_list[] = phutil_render_tag('a', array('href' => '/diffusion/'), 'Diffusion');
     } else {
         $crumb_list[] = 'Diffusion';
         return $crumb_list;
     }
     $callsign = $repository->getCallsign();
     $repository_name = phutil_escape_html($repository->getName()) . ' Repository';
     $branch_name = $drequest->getBranch();
     if ($branch_name) {
         $repository_name .= ' (' . phutil_escape_html($branch_name) . ')';
     }
     $branch_uri = $drequest->getBranchURIComponent($drequest->getBranch());
     if (empty($spec['view']) && empty($spec['commit'])) {
         $crumb_list[] = $repository_name;
         return $crumb_list;
     }
     $crumb_list[] = phutil_render_tag('a', array('href' => "/diffusion/{$callsign}/"), $repository_name);
     $raw_commit = $drequest->getRawCommit();
     if (isset($spec['commit'])) {
         $crumb_list[] = "r{$callsign}{$raw_commit}";
         return $crumb_list;
     }
     $view = $spec['view'];
     $path = null;
     if (isset($spec['path'])) {
         $path = $drequest->getPath();
     }
     if ($raw_commit) {
         $commit_link = DiffusionView::linkCommit($repository, $raw_commit);
     } else {
         $commit_link = '';
     }
     switch ($view) {
         case 'history':
             $view_name = 'History';
             break;
         case 'browse':
             $view_name = 'Browse';
             break;
         case 'change':
             $view_name = 'Change';
             $crumb_list[] = phutil_escape_html($path) . ' (' . $commit_link . ')';
             return $crumb_list;
     }
     $view_root_uri = "/diffusion/{$callsign}/{$view}/{$branch_uri}";
     $jump_href = $view_root_uri;
     $view_tail_uri = null;
     if ($raw_commit) {
         $view_tail_uri = ';' . $drequest->getCommitURIComponent($raw_commit);
     }
     if (!strlen($path)) {
         $crumb_list[] = $view_name;
     } else {
         $crumb_list[] = phutil_render_tag('a', array('href' => $view_root_uri . $view_tail_uri), $view_name);
         $path_parts = explode('/', $path);
         do {
             $last = array_pop($path_parts);
         } while ($last == '');
         $path_sections = array();
         $thus_far = '';
         foreach ($path_parts as $path_part) {
             $thus_far .= $path_part . '/';
             $path_sections[] = phutil_render_tag('a', array('href' => $view_root_uri . $thus_far . $view_tail_uri), phutil_escape_html($path_part));
         }
         $path_sections[] = phutil_escape_html($last);
         $path_sections = '/' . implode('/', $path_sections);
         $jump_href = $view_root_uri . $thus_far . $last;
         $crumb_list[] = $path_sections;
     }
     $last_crumb = array_pop($crumb_list);
     if ($raw_commit) {
         $jump_link = phutil_render_tag('a', array('href' => $jump_href), 'Jump to HEAD');
         $last_crumb .= " @ {$commit_link} ({$jump_link})";
     } else {
         $last_crumb .= " @ HEAD";
     }
     $crumb_list[] = $last_crumb;
     return $crumb_list;
 }
 protected function processDiffusionRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $drequest = $this->getDiffusionRequest();
     $repository = $drequest->getRepository();
     if (!$drequest->supportsBranches()) {
         return $this->newDialog()->setTitle(pht('No Ref Support'))->appendParagraph(pht('The version control system this repository uses does not ' . 'support named references, so you can not resolve or list ' . 'repository refs in this repository.'))->addCancelButton($repository->getURI());
     }
     $ref_name = $drequest->getBranch();
     $cache_query = id(new DiffusionCachedResolveRefsQuery())->setRepository($repository);
     if ($ref_name !== null) {
         $cache_query->withRefs(array($ref_name));
     }
     $cache_refs = $cache_query->execute();
     $vcs_refs = DiffusionQuery::callConduitWithDiffusionRequest($viewer, $drequest, 'diffusion.resolverefs', array('refs' => array($ref_name)));
     $all = array();
     foreach ($cache_refs as $ref => $results) {
         foreach ($results as $result) {
             $id = $result['type'] . '/' . $result['identifier'];
             $all[$ref][$id]['cache'] = $result;
         }
     }
     foreach ($vcs_refs as $ref => $results) {
         foreach ($results as $result) {
             $id = $result['type'] . '/' . $result['identifier'];
             $all[$ref][$id]['vcs'] = $result;
         }
     }
     $rows = array();
     foreach ($all as $ref => $results) {
         foreach ($results as $info) {
             $cache = idx($info, 'cache', array());
             $vcs = idx($info, 'vcs', array());
             $type = idx($vcs, 'type');
             if (!$type) {
                 $type = idx($cache, 'type');
             }
             $hash = idx($vcs, 'identifier');
             if ($hash !== null) {
                 $hash = DiffusionView::linkCommit($repository, $hash);
             }
             $cached_hash = idx($cache, 'identifier');
             if ($cached_hash !== null) {
                 $cached_hash = DiffusionView::linkCommit($repository, $cached_hash);
             }
             $closed = idx($vcs, 'closed', false);
             if (!$vcs) {
                 $state = null;
             } else {
                 $state = $closed ? pht('Closed') : pht('Open');
             }
             $cached_closed = idx($cache, 'closed', false);
             if (!$cache) {
                 $cached_state = null;
             } else {
                 $cached_state = $cached_closed ? pht('Closed') : pht('Open');
             }
             $alternate = idx($vcs, 'alternate');
             if ($alternate !== null) {
                 $alternate = DiffusionView::linkCommit($repository, $alternate);
             }
             $rows[] = array($ref, $type, $hash, $cached_hash, $state, $cached_state, $alternate);
         }
     }
     $table = id(new AphrontTableView($rows))->setHeaders(array(pht('Ref'), pht('Type'), pht('Hash'), pht('Cached Hash'), pht('State'), pht('Cached State'), pht('Alternate')));
     $content = id(new PHUIObjectBoxView())->setHeaderText(pht('Ref "%s"', $ref_name))->setTable($table);
     $crumbs = $this->buildCrumbs(array());
     $crumbs->addTextCrumb(pht('Refs'));
     return $this->buildApplicationPage(array($crumbs, $content), array('title' => array(pht('Refs'), $repository->getMonogram(), $ref_name)));
 }