Path: blob/master/src/applications/diffusion/controller/DiffusionCompareController.php
12242 views
<?php12final class DiffusionCompareController extends DiffusionController {34public function shouldAllowPublic() {5return true;6}78public function handleRequest(AphrontRequest $request) {9$response = $this->loadDiffusionContext();10if ($response) {11return $response;12}1314$viewer = $this->getViewer();15$drequest = $this->getDiffusionRequest();16$repository = $drequest->getRepository();17require_celerity_resource('diffusion-css');1819if (!$repository->supportsBranchComparison()) {20return $this->newDialog()21->setTitle(pht('Not Supported'))22->appendParagraph(23pht(24'Branch comparison is not supported for this version control '.25'system.'))26->addCancelButton($this->getApplicationURI(), pht('Okay'));27}2829$head_ref = $request->getStr('head');30$against_ref = $request->getStr('against');3132$must_prompt = false;33if (!$request->isFormPost()) {34if (!strlen($head_ref)) {35$head_ref = $drequest->getSymbolicCommit();36if (!strlen($head_ref)) {37$head_ref = $drequest->getBranch();38}39}4041if (!strlen($against_ref)) {42$default_branch = $repository->getDefaultBranch();43if ($default_branch != $head_ref) {44$against_ref = $default_branch;4546// If we filled this in by default, we want to prompt the user to47// confirm that this is really what they want.48$must_prompt = true;49}50}51}5253$refs = $drequest->resolveRefs(54array_filter(55array(56$head_ref,57$against_ref,58)));5960$identical = false;61if ($head_ref === $against_ref) {62$identical = true;63} else {64if (count($refs) == 2) {65if ($refs[$head_ref] === $refs[$against_ref]) {66$identical = true;67}68}69}7071if ($must_prompt || count($refs) != 2 || $identical) {72return $this->buildCompareDialog(73$head_ref,74$against_ref,75$refs,76$identical);77}7879if ($request->isFormPost()) {80// Redirect to a stable URI that can be copy/pasted.81$compare_uri = $drequest->generateURI(82array(83'action' => 'compare',84'head' => $head_ref,85'against' => $against_ref,86));8788return id(new AphrontRedirectResponse())->setURI($compare_uri);89}9091$crumbs = $this->buildCrumbs(92array(93'view' => 'compare',94));95$crumbs->setBorder(true);9697$pager = id(new PHUIPagerView())98->readFromRequest($request);99100$history = null;101try {102$history_results = $this->callConduitWithDiffusionRequest(103'diffusion.historyquery',104array(105'commit' => $head_ref,106'against' => $against_ref,107'path' => $drequest->getPath(),108'offset' => $pager->getOffset(),109'limit' => $pager->getPageSize() + 1,110));111$history = DiffusionPathChange::newFromConduit(112$history_results['pathChanges']);113$history = $pager->sliceResults($history);114115$history_view = $this->newHistoryView(116$history_results,117$history,118$pager,119$head_ref,120$against_ref);121122} catch (Exception $ex) {123if ($repository->isImporting()) {124$history_view = $this->renderStatusMessage(125pht('Still Importing...'),126pht(127'This repository is still importing. History is not yet '.128'available.'));129} else {130$history_view = $this->renderStatusMessage(131pht('Unable to Retrieve History'),132$ex->getMessage());133}134}135136$header = id(new PHUIHeaderView())137->setHeader(138pht(139'Changes on %s but not %s',140phutil_tag('em', array(), $head_ref),141phutil_tag('em', array(), $against_ref)));142143$curtain = $this->buildCurtain($head_ref, $against_ref);144145$column_view = id(new PHUITwoColumnView())146->setHeader($header)147->setCurtain($curtain)148->setMainColumn(149array(150$history_view,151));152153return $this->newPage()154->setTitle(155array(156$repository->getName(),157$repository->getDisplayName(),158))159->setCrumbs($crumbs)160->appendChild($column_view);161}162163private function buildCompareDialog(164$head_ref,165$against_ref,166array $resolved,167$identical) {168169$viewer = $this->getViewer();170$request = $this->getRequest();171$drequest = $this->getDiffusionRequest();172$repository = $drequest->getRepository();173174$e_head = null;175$e_against = null;176$errors = array();177if ($request->isFormPost()) {178if (!strlen($head_ref)) {179$e_head = pht('Required');180$errors[] = pht(181'You must provide two different commits to compare.');182} else if (!isset($resolved[$head_ref])) {183$e_head = pht('Not Found');184$errors[] = pht(185'Commit "%s" is not a valid commit in this repository.',186$head_ref);187}188189if (!strlen($against_ref)) {190$e_against = pht('Required');191$errors[] = pht(192'You must provide two different commits to compare.');193} else if (!isset($resolved[$against_ref])) {194$e_against = pht('Not Found');195$errors[] = pht(196'Commit "%s" is not a valid commit in this repository.',197$against_ref);198}199200if ($identical) {201$e_head = pht('Identical');202$e_against = pht('Identical');203$errors[] = pht(204'Both references identify the same commit. You can not compare a '.205'commit against itself.');206}207}208209$form = id(new AphrontFormView())210->setViewer($viewer)211->appendControl(212id(new AphrontFormTextControl())213->setLabel(pht('Head'))214->setName('head')215->setError($e_head)216->setValue($head_ref))217->appendControl(218id(new AphrontFormTextControl())219->setLabel(pht('Against'))220->setName('against')221->setError($e_against)222->setValue($against_ref));223224$cancel_uri = $repository->generateURI(225array(226'action' => 'browse',227));228229return $this->newDialog()230->setTitle(pht('Compare Against'))231->setWidth(AphrontDialogView::WIDTH_FORM)232->setErrors($errors)233->appendForm($form)234->addSubmitButton(pht('Compare'))235->addCancelButton($cancel_uri, pht('Cancel'));236}237238private function buildCurtain($head_ref, $against_ref) {239$viewer = $this->getViewer();240$request = $this->getRequest();241$drequest = $this->getDiffusionRequest();242$repository = $drequest->getRepository();243244$curtain = $this->newCurtainView(null);245246$reverse_uri = $drequest->generateURI(247array(248'action' => 'compare',249'head' => $against_ref,250'against' => $head_ref,251));252253$curtain->addAction(254id(new PhabricatorActionView())255->setName(pht('Reverse Comparison'))256->setHref($reverse_uri)257->setIcon('fa-refresh'));258259$compare_uri = $drequest->generateURI(260array(261'action' => 'compare',262'head' => $head_ref,263));264265$curtain->addAction(266id(new PhabricatorActionView())267->setName(pht('Compare Against...'))268->setIcon('fa-code-fork')269->setWorkflow(true)270->setHref($compare_uri));271272// TODO: Provide a "Show Diff" action.273274return $curtain;275}276277private function newHistoryView(278array $results,279array $history,280PHUIPagerView $pager,281$head_ref,282$against_ref) {283284$request = $this->getRequest();285$viewer = $this->getViewer();286$drequest = $this->getDiffusionRequest();287288if (!$history) {289return $this->renderStatusMessage(290pht('Up To Date'),291pht(292'There are no commits on %s that are not already on %s.',293phutil_tag('strong', array(), $head_ref),294phutil_tag('strong', array(), $against_ref)));295}296297$history_view = id(new DiffusionCommitGraphView())298->setViewer($viewer)299->setDiffusionRequest($drequest)300->setHistory($history)301->setParents($results['parents'])302->setFilterParents(true)303->setIsHead(!$pager->getOffset())304->setIsTail(!$pager->getHasMorePages());305306return $history_view;307}308}309310311