From 8a882018b92b3facccf0e4955103050c44ee23a9 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 17 Jan 2023 10:19:43 +0100 Subject: [PATCH] Initial commit of differential baking changes NOTE: This branch is not to be deployed as a website, but instead to be used as a client of a cluster (to have access to the database) and run the baking script in a unattended mode. A lot of tweaks all over the place to make the generated HTML suitable for use in a static HTML with remapped paths to be relative and so on. NOTE: Because of those tweaks the file rendering and access will not work as expected when viewed from the website: it will be 404 because it has different means accessing files than the static HTML. It is not possible to keep website rendering correct, but it makes it harder to investigate what parts needs attention without running the baker. The baking script is found in `scripts/bake/bake_differential.php` and it receives a single argument which is a directory with the baked files. Covers the following aspects: - File attachments - Image previews - Pastes The user avatars are replaced with the default user avatar. --- resources/celerity/map.php | 6 +- scripts/bake/bake_differential.php | 293 ++++++++++++++++++ .../base/controller/PhabricatorController.php | 2 +- .../DifferentialRevisionViewController.php | 72 ++--- .../phid/DifferentialDiffPHIDType.php | 3 +- .../DifferentialChangesetHTMLRenderer.php | 16 +- .../storage/DifferentialRevision.php | 2 +- .../view/DifferentialChangesetListView.php | 200 +++++++++++- .../DifferentialRevisionUpdateHistoryView.php | 36 ++- .../PhabricatorEmbedFileRemarkupRule.php | 11 +- .../files/storage/PhabricatorFile.php | 18 +- .../PhabricatorFlagsUIEventListener.php | 2 +- .../phid/PhabricatorPastePastePHIDType.php | 2 +- .../query/PhabricatorPasteSearchEngine.php | 2 +- .../paste/storage/PhabricatorPaste.php | 2 +- .../paste/view/PasteEmbedView.php | 2 +- .../people/storage/PhabricatorUser.php | 6 + .../phid/PhabricatorObjectHandle.php | 12 +- .../handle/pool/PhabricatorHandlePool.php | 4 + ...habricatorSubscriptionsUIEventListener.php | 4 +- .../event/PhabricatorTokenUIEventListener.php | 2 +- ...catorApplicationTransactionCommentView.php | 1 + .../PhabricatorApplicationTransactionView.php | 2 +- .../view/PHUIDiffInlineCommentDetailView.php | 2 +- src/view/AphrontView.php | 2 +- src/view/phui/PHUITimelineEventView.php | 15 +- .../differential/revision-history.css | 5 + 27 files changed, 625 insertions(+), 99 deletions(-) create mode 100644 scripts/bake/bake_differential.php diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 07d1e3480d..ed08bc1d92 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -12,7 +12,7 @@ return array( 'core.pkg.css' => '0fbedea0', 'core.pkg.js' => '74ad315f', 'dark-console.pkg.js' => '187792c2', - 'differential.pkg.css' => '5c459f92', + 'differential.pkg.css' => '32879ab6', 'differential.pkg.js' => '218fda21', 'diffusion.pkg.css' => '42c75c37', 'diffusion.pkg.js' => 'a98c0bf7', @@ -67,7 +67,7 @@ return array( 'rsrc/css/application/differential/core.css' => '7300a73e', 'rsrc/css/application/differential/phui-inline-comment.css' => '9863a85e', 'rsrc/css/application/differential/revision-comment.css' => '7dbc8d1d', - 'rsrc/css/application/differential/revision-history.css' => '8aa3eac5', + 'rsrc/css/application/differential/revision-history.css' => '04edcc29', 'rsrc/css/application/differential/revision-list.css' => '93d2df7d', 'rsrc/css/application/differential/table-of-contents.css' => 'bba788b9', 'rsrc/css/application/diffusion/diffusion-icons.css' => '23b31a1b', @@ -574,7 +574,7 @@ return array( 'differential-core-view-css' => '7300a73e', 'differential-revision-add-comment-css' => '7e5900d9', 'differential-revision-comment-css' => '7dbc8d1d', - 'differential-revision-history-css' => '8aa3eac5', + 'differential-revision-history-css' => '04edcc29', 'differential-revision-list-css' => '93d2df7d', 'differential-table-of-contents-css' => 'bba788b9', 'diffusion-css' => 'b54c77b0', diff --git a/scripts/bake/bake_differential.php b/scripts/bake/bake_differential.php new file mode 100644 index 0000000000..070ea1b392 --- /dev/null +++ b/scripts/bake/bake_differential.php @@ -0,0 +1,293 @@ +#!/usr/local/bin/php +\n"); + die; +} + +$OUTPUT_DIR = $argv[1]; + +///////////////////////////////////////////////////////////////////////////////// +// Global configuration. + +$HOST = 'phabricator.local'; + +///////////////////////////////////////////////////////////////////////////////// +// Utilities. + +// Create an instance of the AphrontApplicationConfiguration configured with all +// invariant settings (settings which do not change between handlers of different +// revisions). +function CreateApplicationConfiguration() { + global $HOST; + + $application_configuration = new AphrontApplicationConfiguration(); + $application_configuration->setHost($HOST); + return $application_configuration; +} + +///////////////////////////////////////////////////////////////////////////////// +// Global state. + +$site = id(new PhabricatorPlatformSite()); + +$viewer = PhabricatorUser::getOmnipotentUser(); + +$application_configuration = CreateApplicationConfiguration(); + +$application = id(new PhabricatorDifferentialApplication()); +$revision_controller = id(new DifferentialRevisionViewController()) + ->setCurrentApplication($application); + +$routing_map = id(new AphrontRoutingMap()) + ->setSite($site) + ->setApplication($application) + ->setRoutes($application->getRoutes()); + +///////////////////////////////////////////////////////////////////////////////// +// Baking logic and loop. + +function EnsureDirectoryOrDie($dir) { + if (!is_dir($dir)) { + if (!mkdir($dir, 0777, true)) { + print("Error creating output durectory $dir\n"); + die; + } + } +} + +function EnsureOutputDirectoryOrDie() { + global $OUTPUT_DIR; + EnsureDirectoryOrDie($OUTPUT_DIR); +} + +function MakeGenericOutputDirectory($subject) { + global $OUTPUT_DIR; + + $dir = $OUTPUT_DIR . DIRECTORY_SEPARATOR . $subject; + EnsureDirectoryOrDie($dir); + + return $dir; +} + +function MakeRevisionBaseOutputFileName($revision, $diff_id, $subject) { + $dir = MakeGenericOutputDirectory($subject); + + $file_name = $dir . DIRECTORY_SEPARATOR . 'D' . $revision->getID(); + + if (!is_null($diff_id)) { + $file_name .= '.' . $diff_id; + } + + return $file_name; +} + +function MakeRevisionHTMLOutputFileName($revision, $diff_id) { + return MakeRevisionBaseOutputFileName( + $revision, $diff_id, 'revision') . '.html'; +} + +function MakeRawDiffOutputFileName($revision, $diff_id) { + return MakeRevisionBaseOutputFileName( + $revision, $diff_id, 'raw_diff') . '.diff'; +} + +function MakePasteOutputFileNameFromHandle($handle) { + return MakeGenericOutputDirectory('paste') . + DIRECTORY_SEPARATOR . + $handle->getName() . '.txt'; +} + + +function MakeFileOutputFileNameFromFile($file) { + $dir = MakeGenericOutputDirectory('file'); + + $id = $file->getID(); + + EnsureDirectoryOrDie($dir . DIRECTORY_SEPARATOR . 'F' . $id); + + return $dir. + DIRECTORY_SEPARATOR . + $file->getSafeFileNameForBake(); +} + +function BakeDifferentialToResponse($revision, $diff_id = NULL) { + global $application_configuration; + global $revision_controller; + global $routing_map; + global $viewer; + + $revision_id = $revision->getID(); + + if (is_null($diff_id)) { + printf('Baking D' . $revision_id . ' ...' . "\n"); + } else { + printf('Baking D' . $revision_id . ', diff ' . $diff_id . ' ...' . "\n"); + } + + $path = '/D' . $revision_id; + + $route_result = $routing_map->routePath($path); + $uri_data = $route_result->getURIData(); + + $application_configuration->setPath($path); + + $request_data = array( + ); + + if (!is_null($diff_id)) { + $request_data['id'] = $diff_id; + } + + $request = $application_configuration->buildRequest() + ->setUser($viewer) + ->setRequestData($request_data) + ->setURIMap($uri_data); + + $response = id($revision_controller) + ->setRequest($request) + ->handleRequest($request); + + return $response; +} + +function BakeResponseToHTML($response) { + $html = ''; + foreach ($response->renderChildren() as $child) { + $html .= $child->render(); + } + + return $html; +} + +function StorePasteHandle($handle) { + global $viewer; + + $file_name = MakePasteOutputFileNameFromHandle($handle); + if (file_exists($file_name)) { + return; + } + + $paste = id(new PhabricatorPasteQuery()) + ->setViewer($viewer) + ->withPHIDs(array($handle->getPHID())) + ->needRawContent(true) + ->executeOne(); + + file_put_contents($file_name, $paste->getRawContent()); +} + +function StoreFile($file) { + $file_name = MakeFileOutputFileNameFromFile($file); + file_put_contents($file_name, $file->loadFileData()); +} + +function StoreFileHandle($handle) { + global $viewer; + + $file = id(new PhabricatorFileQuery()) + ->setViewer($viewer) + ->withPHIDs(array($handle->getPHID())) + ->needTransforms( + array( + PhabricatorFileThumbnailTransform::TRANSFORM_PREVIEW, + )) + ->executeOne(); + + $file_name = MakeFileOutputFileNameFromFile($file); + if (file_exists($file_name)) { + return; + } + + StoreFile($file); + + $preview_xform = $file->getTransform(PhabricatorFileThumbnailTransform::TRANSFORM_PREVIEW); + if ($preview_xform) { + StoreFile($preview_xform); + } +} + +function StoreResponseAttachments($response) { + $user = $response->getRequest()->getUser(); + $handlePool = $user->getHandlePool(); + $handles = $handlePool->getHandles(); + + foreach ($handles as $phid => $handle) { + $type = $handle->getType(); + if ($type == PhabricatorPastePastePHIDType::TYPECONST) { + StorePasteHandle($handle); + } else if ($type == PhabricatorFileFilePHIDType::TYPECONST) { + StoreFileHandle($handle); + } else { + // print("$type\n"); + } + } +} + +function StoreRawDiff($revision, $diff_id) { + if (is_null($diff_id)) { + return; + } + + global $viewer; + + $diff = id(new DifferentialDiffQuery()) + ->setViewer($viewer) + ->withIDs(array($diff_id)) + ->needChangesets(true) + ->executeOne(); + + $raw_changes = $diff->buildChangesList(); + + $changes = array(); + foreach ($raw_changes as $changedict) { + $changes[] = ArcanistDiffChange::newFromDictionary($changedict); + } + + $bundle = ArcanistBundle::newFromChanges($changes); + $raw_diff = $bundle->toGitPatch(); + + $output_file = MakeRawDiffOutputFileName($revision, $diff_id); + file_put_contents($output_file, $raw_diff); +} + +function BakeDifferentialToFile($revision, $diff_id = NULL) { + $response = BakeDifferentialToResponse($revision, $diff_id); + + $html = BakeResponseToHTML($response); + + $output_file = MakeRevisionHTMLOutputFileName($revision, $diff_id); + file_put_contents($output_file, $html); + + file_put_contents($output_file . '.title', $response->getTitle()); + + StoreResponseAttachments($response); + StoreRawDiff($revision, $diff_id); +} + +EnsureOutputDirectoryOrDie(); + +$revisions = id(new DifferentialRevisionQuery()) + ->setViewer($viewer) + ->needDiffIDs(true) + ->execute(); + +foreach ($revisions as $revision_id => $revision) { + BakeDifferentialToFile($revision); + + foreach ($revision->getDiffIDs() as $diff_id) { + BakeDifferentialToFile($revision, $diff_id); + } +} + +?> diff --git a/src/applications/base/controller/PhabricatorController.php b/src/applications/base/controller/PhabricatorController.php index a463c741d1..d6cca9b358 100644 --- a/src/applications/base/controller/PhabricatorController.php +++ b/src/applications/base/controller/PhabricatorController.php @@ -334,7 +334,7 @@ abstract class PhabricatorController extends AphrontController { } $crumbs[] = id(new PHUICrumbView()) - ->setHref($this->getApplicationURI()) + // ->setHref($this->getApplicationURI()) ->setName($application->getName()) ->setIcon($icon); } diff --git a/src/applications/differential/controller/DifferentialRevisionViewController.php b/src/applications/differential/controller/DifferentialRevisionViewController.php index ccb4b85867..ace42559e3 100644 --- a/src/applications/differential/controller/DifferentialRevisionViewController.php +++ b/src/applications/differential/controller/DifferentialRevisionViewController.php @@ -180,7 +180,7 @@ final class DifferentialRevisionViewController $request_uri = $request->getRequestURI(); - $large = $request->getStr('large'); + $large = $request->getStr('large') && true; $large_warning = ($this->isLargeDiff()) && @@ -310,7 +310,7 @@ final class DifferentialRevisionViewController $header = $this->buildHeader($revision); $subheader = $this->buildSubheaderView($revision); $details = $this->buildDetails($revision, $field_list); - $curtain = $this->buildCurtain($revision); + $curtain = $this->buildCurtain($revision, $target_id); $repository = $revision->getRepository(); if ($repository) { @@ -553,7 +553,8 @@ final class DifferentialRevisionViewController $tab_header = id(new PHUIHeaderView()) ->setHeader(pht('Revision Contents')) - ->addActionLink($view_button); + // ->addActionLink($view_button) + ; $tab_view = id(new PHUIObjectBoxView()) ->setHeader($tab_header) @@ -663,7 +664,7 @@ final class DifferentialRevisionViewController $view = id(new PHUIHeaderView()) ->setHeader($revision->getTitle($revision)) ->setUser($this->getViewer()) - ->setPolicyObject($revision) + // ->setPolicyObject($revision) ->setHeaderIcon('fa-cog'); $status_tag = id(new PHUITagView()) @@ -737,7 +738,7 @@ final class DifferentialRevisionViewController ->appendChild($properties); } - private function buildCurtain(DifferentialRevision $revision) { + private function buildCurtain(DifferentialRevision $revision, $diff_id) { $viewer = $this->getViewer(); $revision_id = $revision->getID(); $revision_phid = $revision->getPHID(); @@ -748,48 +749,48 @@ final class DifferentialRevisionViewController $revision, PhabricatorPolicyCapability::CAN_EDIT); - $curtain->addAction( - id(new PhabricatorActionView()) - ->setIcon('fa-pencil') - ->setHref("/differential/revision/edit/{$revision_id}/") - ->setName(pht('Edit Revision')) - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit)); + // $curtain->addAction( + // id(new PhabricatorActionView()) + // ->setIcon('fa-pencil') + // ->setHref("/differential/revision/edit/{$revision_id}/") + // ->setName(pht('Edit Revision')) + // ->setDisabled(!$can_edit) + // ->setWorkflow(!$can_edit)); - $curtain->addAction( - id(new PhabricatorActionView()) - ->setIcon('fa-upload') - ->setHref("/differential/revision/update/{$revision_id}/") - ->setName(pht('Update Diff')) - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit)); + // $curtain->addAction( + // id(new PhabricatorActionView()) + // ->setIcon('fa-upload') + // ->setHref("/differential/revision/update/{$revision_id}/") + // ->setName(pht('Update Diff')) + // ->setDisabled(!$can_edit) + // ->setWorkflow(!$can_edit)); $request_uri = $this->getRequest()->getRequestURI(); $curtain->addAction( id(new PhabricatorActionView()) ->setIcon('fa-download') ->setName(pht('Download Raw Diff')) - ->setHref($request_uri->alter('download', 'true'))); + ->setHref('raw_diff/D' . $revision_id . '.' . $diff_id . '.diff')); $relationship_list = PhabricatorObjectRelationshipList::newForObject( $viewer, $revision); - $revision_actions = array( - DifferentialRevisionHasParentRelationship::RELATIONSHIPKEY, - DifferentialRevisionHasChildRelationship::RELATIONSHIPKEY, - ); - - $revision_submenu = $relationship_list->newActionSubmenu($revision_actions) - ->setName(pht('Edit Related Revisions...')) - ->setIcon('fa-cog'); - - $curtain->addAction($revision_submenu); - - $relationship_submenu = $relationship_list->newActionMenu(); - if ($relationship_submenu) { - $curtain->addAction($relationship_submenu); - } + // $revision_actions = array( + // DifferentialRevisionHasParentRelationship::RELATIONSHIPKEY, + // DifferentialRevisionHasChildRelationship::RELATIONSHIPKEY, + // ); + // + // $revision_submenu = $relationship_list->newActionSubmenu($revision_actions) + // ->setName(pht('Edit Related Revisions...')) + // ->setIcon('fa-cog'); + // + // $curtain->addAction($revision_submenu); + // + // $relationship_submenu = $relationship_list->newActionMenu(); + // if ($relationship_submenu) { + // $curtain->addAction($relationship_submenu); + // } $repository = $revision->getRepository(); if ($repository && $repository->canPerformAutomation()) { @@ -870,6 +871,7 @@ final class DifferentialRevisionViewController $raw_changesets = id(new DifferentialChangesetQuery()) ->setViewer($viewer) ->withDiffs($load_diffs) + ->needHunks(true) ->execute(); $changeset_groups = mgroup($raw_changesets, 'getDiffID'); diff --git a/src/applications/differential/phid/DifferentialDiffPHIDType.php b/src/applications/differential/phid/DifferentialDiffPHIDType.php index 746da368c7..2b1445829d 100644 --- a/src/applications/differential/phid/DifferentialDiffPHIDType.php +++ b/src/applications/differential/phid/DifferentialDiffPHIDType.php @@ -33,9 +33,10 @@ final class DifferentialDiffPHIDType extends PhabricatorPHIDType { $diff = $objects[$phid]; $id = $diff->getID(); + $revision_id = $diff->getRevisionID(); $handle->setName(pht('Diff %d', $id)); - $handle->setURI("/differential/diff/{$id}/"); + $handle->setURI("D{$revision_id}.{$id}.html"); } } diff --git a/src/applications/differential/render/DifferentialChangesetHTMLRenderer.php b/src/applications/differential/render/DifferentialChangesetHTMLRenderer.php index 7612f9e876..1e79554714 100644 --- a/src/applications/differential/render/DifferentialChangesetHTMLRenderer.php +++ b/src/applications/differential/render/DifferentialChangesetHTMLRenderer.php @@ -589,15 +589,15 @@ abstract class DifferentialChangesetHTMLRenderer $reference = $this->getRenderingReference(); return javelin_tag( - 'a', + 'span', array( - 'href' => '#', - 'mustcapture' => true, - 'sigil' => 'show-more', - 'meta' => array( - 'type' => ($is_all ? 'all' : null), - 'range' => $range, - ), + // 'href' => '#', + // 'mustcapture' => true, + // 'sigil' => 'show-more', + // 'meta' => array( + // 'type' => ($is_all ? 'all' : null), + // 'range' => $range, + // ), ), $text); } diff --git a/src/applications/differential/storage/DifferentialRevision.php b/src/applications/differential/storage/DifferentialRevision.php index 2ab9d59821..6c553a8976 100644 --- a/src/applications/differential/storage/DifferentialRevision.php +++ b/src/applications/differential/storage/DifferentialRevision.php @@ -147,7 +147,7 @@ final class DifferentialRevision extends DifferentialDAO } public function getURI() { - return '/'.$this->getMonogram(); + return $this->getMonogram() . '.html'; } public function getCommitPHIDs() { diff --git a/src/applications/differential/view/DifferentialChangesetListView.php b/src/applications/differential/view/DifferentialChangesetListView.php index cab63eb998..bb519a053f 100644 --- a/src/applications/differential/view/DifferentialChangesetListView.php +++ b/src/applications/differential/view/DifferentialChangesetListView.php @@ -187,13 +187,13 @@ final class DifferentialChangesetListView extends AphrontView { $uniq_id = 'diff-'.$changeset->getAnchorName(); $detail->setID($uniq_id); - $view_options = $this->renderViewOptionsDropdown( - $detail, - $ref, - $changeset); + // $view_options = $this->renderViewOptionsDropdown( + // $detail, + // $ref, + // $changeset); $detail->setChangeset($changeset); - $detail->addButton($view_options); + // $detail->addButton($view_options); $detail->setSymbolIndex(idx($this->symbolIndexes, $key)); $detail->setVsChangesetID(idx($this->vsMap, $changeset->getID())); $detail->setEditable(true); @@ -202,7 +202,107 @@ final class DifferentialChangesetListView extends AphrontView { $detail->setRenderURI($this->renderURI); - $parser = $this->getParser(); + // $parser = $this->getParser(); + + $revision_id = $diff->getRevisionID(); + $revision = id(new DifferentialRevisionQuery()) + ->setViewer($viewer) + ->withIDs(array($revision_id)) + ->executeOne(); + + $old = array(); + $new = array(); + + $right = $changeset; + $left = null; + + $right_source = $right->getID(); + $right_new = true; + $left_source = $right->getID(); + $left_new = false; + + $render_cache_key = $right->getID(); + + $old[] = $changeset; + $new[] = $changeset; + + $parser = id(new DifferentialChangesetParser()) + ->setViewer($viewer) + ->setViewState(new PhabricatorChangesetViewState()) + // ->setCoverage($coverage) + ->setChangeset($changeset) + ->setRenderingReference($ref) + ->setRenderCacheKey($render_cache_key) + ->setRightSideCommentMapping($right_source, $right_new) + ->setLeftSideCommentMapping($left_source, $left_new) + ->setMask(array()) + ; + + if ($left && $right) { + $parser->setOriginals($left, $right); + } + + if ($revision) { + $inlines = id(new DifferentialDiffInlineCommentQuery()) + ->setViewer($viewer) + ->withRevisionPHIDs(array($revision->getPHID())) + ->withPublishableComments(true) + ->withPublishedComments(true) + ->needHidden(true) + ->needInlineContext(true) + ->execute(); + + $inlines = mpull($inlines, 'newInlineCommentObject'); + + $inlines = id(new PhabricatorInlineCommentAdjustmentEngine()) + ->setViewer($viewer) + ->setRevision($revision) + ->setOldChangesets($old) + ->setNewChangesets($new) + ->setInlines($inlines) + ->execute(); + } else { + $inlines = array(); + } + + if ($left_new) { + $inlines = array_merge( + $inlines, + $this->buildLintInlineComments($left)); + } + + if ($right_new) { + $inlines = array_merge( + $inlines, + $this->buildLintInlineComments($right)); + } + + $phids = array(); + foreach ($inlines as $inline) { + $parser->parseInlineComment($inline); + if ($inline->getAuthorPHID()) { + $phids[$inline->getAuthorPHID()] = true; + } + } + $phids = array_keys($phids); + + $handles = $this->loadViewerHandles($phids); + $parser->setHandles($handles); + + $engine = new PhabricatorMarkupEngine(); + $engine->setViewer($viewer); + + foreach ($inlines as $inline) { + $engine->addObject( + $inline, + PhabricatorInlineComment::MARKUP_FIELD_BODY); + } + + $engine->process(); + + $parser + ->setMarkupEngine($engine); + if ($parser) { $response = $parser->newChangesetResponse(); $detail->setChangesetResponse($response); @@ -471,4 +571,92 @@ final class DifferentialChangesetListView extends AphrontView { return $uri; } + private function buildLintInlineComments($changeset) { + $diff = $changeset->getDiff(); + + $target_phids = $diff->getBuildTargetPHIDs(); + if (!$target_phids) { + return array(); + } + + $messages = id(new HarbormasterBuildLintMessage())->loadAllWhere( + 'buildTargetPHID IN (%Ls) AND path = %s', + $target_phids, + $changeset->getFilename()); + + if (!$messages) { + return array(); + } + + $change_type = $changeset->getChangeType(); + if (DifferentialChangeType::isDeleteChangeType($change_type)) { + // If this is a lint message on a deleted file, show it on the left + // side of the UI because there are no source code lines on the right + // side of the UI so inlines don't have anywhere to render. See PHI416. + $is_new = 0; + } else { + $is_new = 1; + } + + $template = id(new DifferentialInlineComment()) + ->setChangesetID($changeset->getID()) + ->setIsNewFile($is_new) + ->setLineLength(0); + + $inlines = array(); + foreach ($messages as $message) { + $description = $message->getProperty('description'); + + $inlines[] = id(clone $template) + ->setSyntheticAuthor(pht('Lint: %s', $message->getName())) + ->setLineNumber($message->getLine()) + ->setContent($description); + } + + return $inlines; + } + + private function loadCoverage(DifferentialChangeset $changeset) { + $viewer = $this->getViewer(); + + $target_phids = $changeset->getDiff()->getBuildTargetPHIDs(); + if (!$target_phids) { + return null; + } + + $unit = id(new HarbormasterBuildUnitMessageQuery()) + ->setViewer($viewer) + ->withBuildTargetPHIDs($target_phids) + ->execute(); + if (!$unit) { + return null; + } + + $coverage = array(); + foreach ($unit as $message) { + $test_coverage = $message->getProperty('coverage'); + if ($test_coverage === null) { + continue; + } + $coverage_data = idx($test_coverage, $changeset->getFileName()); + if (!strlen($coverage_data)) { + continue; + } + $coverage[] = $coverage_data; + } + + if (!$coverage) { + return null; + } + + return ArcanistUnitTestResult::mergeCoverage($coverage); + } + + protected function loadViewerHandles(array $phids) { + return id(new PhabricatorHandleQuery()) + ->setViewer($this->getViewer()) + ->withPHIDs($phids) + ->execute(); + } + } diff --git a/src/applications/differential/view/DifferentialRevisionUpdateHistoryView.php b/src/applications/differential/view/DifferentialRevisionUpdateHistoryView.php index 07ca983bc0..2e1a8bf4f5 100644 --- a/src/applications/differential/view/DifferentialRevisionUpdateHistoryView.php +++ b/src/applications/differential/view/DifferentialRevisionUpdateHistoryView.php @@ -178,7 +178,7 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView { $id_link = phutil_tag( 'a', array( - 'href' => '/D'.$revision_id.'?id='.$id, + 'href' => 'D'.$revision_id.'.'.$id.'.html', ), $id); } else { @@ -196,19 +196,27 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView { $base, $desc, $age, - $lint, - $unit, - $old, - $new, + // $lint, + // $unit, + // $old, + // $new, ); $classes = array(); + + /* if ($old_class) { $classes[] = 'differential-update-history-old-now'; } if ($new_class) { $classes[] = 'differential-update-history-new-now'; } + */ + + if ($id && $this->selectedDiffID == $id) { + $classes[] = 'differential-update-history-current'; + } + $rowc[] = nonempty(implode(' ', $classes), null); } @@ -226,10 +234,10 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView { pht('Base'), pht('Description'), pht('Created'), - pht('Lint'), - pht('Unit'), - '', - '', + // pht('Lint'), + // pht('Unit'), + // '', + // '', )); $table->setColumnClasses( array( @@ -238,8 +246,8 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView { '', 'wide', 'date', - 'center', - 'center', + // 'center', + // 'center', 'center differential-update-history-old', 'center differential-update-history-new', )); @@ -251,8 +259,8 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView { false, true, false, - false, - false, + // false, + // false, true, true, )); @@ -276,7 +284,7 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView { ), array( $table, - $show_diff, + // $show_diff, )); return $content; diff --git a/src/applications/files/markup/PhabricatorEmbedFileRemarkupRule.php b/src/applications/files/markup/PhabricatorEmbedFileRemarkupRule.php index 983dea4a02..bee14ccbbb 100644 --- a/src/applications/files/markup/PhabricatorEmbedFileRemarkupRule.php +++ b/src/applications/files/markup/PhabricatorEmbedFileRemarkupRule.php @@ -143,11 +143,12 @@ final class PhabricatorEmbedFileRemarkupRule $xform = PhabricatorFileTransform::getTransformByKey($preview_key); $existing_xform = $file->getTransform($preview_key); - if ($existing_xform) { - $xform_uri = $existing_xform->getCDNURI('data'); - } else { - $xform_uri = $file->getURIForTransform($xform); - } + // if ($existing_xform) { + // $xform_uri = $existing_xform->getCDNURI('data'); + // } else { + // $xform_uri = $file->getURIForTransform($xform); + // } + $xform_uri = $existing_xform->getInfoURI(); $attrs['src'] = $xform_uri; diff --git a/src/applications/files/storage/PhabricatorFile.php b/src/applications/files/storage/PhabricatorFile.php index 25adc21055..6ca54cef8f 100644 --- a/src/applications/files/storage/PhabricatorFile.php +++ b/src/applications/files/storage/PhabricatorFile.php @@ -829,7 +829,6 @@ final class PhabricatorFile extends PhabricatorFileDAO throw new Exception( pht('You must save a file before you can generate a view URI.')); } - return $this->getCDNURI('data'); } @@ -875,13 +874,23 @@ final class PhabricatorFile extends PhabricatorFileDAO } } + public static function makeFileNameForURI($id, $name) { + // $safe_name = preg_replace('/[\\/\\\\]/', '_', $name); + $safe_name = preg_replace('/[^A-Za-z0-9\\-_\\+\\.]/', '_', $name); + return 'F' . $id . DIRECTORY_SEPARATOR . $safe_name; + } + + public function getSafeFileNameForBake() { + return PhabricatorFile::makeFileNameForURI( + $this->getID(), $this->getName()); + } public function getInfoURI() { - return '/'.$this->getMonogram(); + return 'file/'.$this->getSafeFileNameForBake(); } public function getBestURI() { - if ($this->isViewableInBrowser()) { + if ($this->isViewableInBrowser() && false) { return $this->getViewURI(); } else { return $this->getInfoURI(); @@ -889,7 +898,8 @@ final class PhabricatorFile extends PhabricatorFileDAO } public function getDownloadURI() { - return $this->getCDNURI('download'); + return $this->getInfoURI(); + // return $this->getCDNURI('download'); } public function getURIForTransform(PhabricatorFileTransform $transform) { diff --git a/src/applications/flag/events/PhabricatorFlagsUIEventListener.php b/src/applications/flag/events/PhabricatorFlagsUIEventListener.php index 872b495a93..035363c41d 100644 --- a/src/applications/flag/events/PhabricatorFlagsUIEventListener.php +++ b/src/applications/flag/events/PhabricatorFlagsUIEventListener.php @@ -55,7 +55,7 @@ final class PhabricatorFlagsUIEventListener extends PhabricatorEventListener { } $actions = $event->getValue('actions'); - $actions[] = $flag_action; + // $actions[] = $flag_action; $event->setValue('actions', $actions); } diff --git a/src/applications/paste/phid/PhabricatorPastePastePHIDType.php b/src/applications/paste/phid/PhabricatorPastePastePHIDType.php index d08d52e2e1..10f128b245 100644 --- a/src/applications/paste/phid/PhabricatorPastePastePHIDType.php +++ b/src/applications/paste/phid/PhabricatorPastePastePHIDType.php @@ -37,7 +37,7 @@ final class PhabricatorPastePastePHIDType extends PhabricatorPHIDType { $handle->setName("P{$id}"); $handle->setFullName($name); - $handle->setURI("/P{$id}"); + $handle->setURI("paste/P{$id}.txt"); } } diff --git a/src/applications/paste/query/PhabricatorPasteSearchEngine.php b/src/applications/paste/query/PhabricatorPasteSearchEngine.php index e269088f60..0aebefc152 100644 --- a/src/applications/paste/query/PhabricatorPasteSearchEngine.php +++ b/src/applications/paste/query/PhabricatorPasteSearchEngine.php @@ -176,7 +176,7 @@ final class PhabricatorPasteSearchEngine $item = id(new PHUIObjectItemView()) ->setObjectName('P'.$paste->getID()) ->setHeader($title) - ->setHref('/P'.$paste->getID()) + ->setHref('paste/P'.$paste->getID().'.txt') ->setObject($paste) ->addByline(pht('Author: %s', $author)) ->addIcon('none', $created) diff --git a/src/applications/paste/storage/PhabricatorPaste.php b/src/applications/paste/storage/PhabricatorPaste.php index 3d19a00230..0e5dede2b9 100644 --- a/src/applications/paste/storage/PhabricatorPaste.php +++ b/src/applications/paste/storage/PhabricatorPaste.php @@ -60,7 +60,7 @@ final class PhabricatorPaste extends PhabricatorPasteDAO } public function getURI() { - return '/'.$this->getMonogram(); + return 'paste/'.$this->getMonogram(); } public function getMonogram() { diff --git a/src/applications/paste/view/PasteEmbedView.php b/src/applications/paste/view/PasteEmbedView.php index e5121b496b..a623f703aa 100644 --- a/src/applications/paste/view/PasteEmbedView.php +++ b/src/applications/paste/view/PasteEmbedView.php @@ -38,7 +38,7 @@ final class PasteEmbedView extends AphrontView { $link = phutil_tag( 'a', array( - 'href' => '/P'.$this->paste->getID(), + 'href' => 'paste/P'.$this->paste->getID().'.txt', ), $this->handle->getFullName()); diff --git a/src/applications/people/storage/PhabricatorUser.php b/src/applications/people/storage/PhabricatorUser.php index 821abb80f9..007d3351db 100644 --- a/src/applications/people/storage/PhabricatorUser.php +++ b/src/applications/people/storage/PhabricatorUser.php @@ -608,6 +608,8 @@ final class PhabricatorUser } public function getProfileImageURI() { + return '/rsrc/image/avatar.png'; + $uri_key = PhabricatorUserProfileImageCacheType::KEY_URI; return $this->requireCacheData($uri_key); } @@ -982,6 +984,10 @@ final class PhabricatorUser return $this->handlePool->newHandleList($phids); } + public function getHandlePool() { + return $this->handlePool; + } + /** * Get a @{class:PHUIHandleView} for a single handle. diff --git a/src/applications/phid/PhabricatorObjectHandle.php b/src/applications/phid/PhabricatorObjectHandle.php index 6b7f01d596..f32a9e3d88 100644 --- a/src/applications/phid/PhabricatorObjectHandle.php +++ b/src/applications/phid/PhabricatorObjectHandle.php @@ -146,7 +146,15 @@ final class PhabricatorObjectHandle } public function getURI() { - return $this->uri; + $type = $this->getType(); + if ($type == 'TASK') { + // XXX: Use real link to gitea task + // At least for now rely on the existence of the manip[hest task redirector. + return 'https://developer.blender.org' . $this->uri; + } else if ($type == 'DREV' || $type == 'DIFF' || $type == 'PSTE' || $type == 'FILE') { + return $this->uri; + } + return null; } public function setPHID($phid) { @@ -357,7 +365,7 @@ final class PhabricatorObjectHandle ); return javelin_tag( - $uri ? 'a' : 'span', + $uri ? 'a' : 'b', $attributes, array($circle, $icon, $name)); } diff --git a/src/applications/phid/handle/pool/PhabricatorHandlePool.php b/src/applications/phid/handle/pool/PhabricatorHandlePool.php index eaa48828a4..ccad45f8fc 100644 --- a/src/applications/phid/handle/pool/PhabricatorHandlePool.php +++ b/src/applications/phid/handle/pool/PhabricatorHandlePool.php @@ -22,6 +22,10 @@ final class PhabricatorHandlePool extends Phobject { return $this->viewer; } + public function getHandles() { + return $this->handles; + } + public function newHandleList(array $phids) { // Mark any PHIDs we haven't loaded yet as unloaded. This will let us bulk // load them later. diff --git a/src/applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php b/src/applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php index 2077160b7c..38d0ba989b 100644 --- a/src/applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php +++ b/src/applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php @@ -112,8 +112,8 @@ final class PhabricatorSubscriptionsUIEventListener $actions = $event->getValue('actions'); - $actions[] = $sub_action; - $actions[] = $mute_action; + // $actions[] = $sub_action; + // $actions[] = $mute_action; $event->setValue('actions', $actions); } diff --git a/src/applications/tokens/event/PhabricatorTokenUIEventListener.php b/src/applications/tokens/event/PhabricatorTokenUIEventListener.php index 047c5504bf..4a858690f9 100644 --- a/src/applications/tokens/event/PhabricatorTokenUIEventListener.php +++ b/src/applications/tokens/event/PhabricatorTokenUIEventListener.php @@ -74,7 +74,7 @@ final class PhabricatorTokenUIEventListener } $actions = $event->getValue('actions'); - $actions[] = $token_action; + // $actions[] = $token_action; $event->setValue('actions', $actions); } diff --git a/src/applications/transactions/view/PhabricatorApplicationTransactionCommentView.php b/src/applications/transactions/view/PhabricatorApplicationTransactionCommentView.php index 8ec7ef0d8f..2b98b71a8a 100644 --- a/src/applications/transactions/view/PhabricatorApplicationTransactionCommentView.php +++ b/src/applications/transactions/view/PhabricatorApplicationTransactionCommentView.php @@ -184,6 +184,7 @@ final class PhabricatorApplicationTransactionCommentView if ($this->getNoPermission()) { return null; } + return null; $lock = $this->getEditEngineLock(); if ($lock) { diff --git a/src/applications/transactions/view/PhabricatorApplicationTransactionView.php b/src/applications/transactions/view/PhabricatorApplicationTransactionView.php index 8cb0d28f5e..1186c5841d 100644 --- a/src/applications/transactions/view/PhabricatorApplicationTransactionView.php +++ b/src/applications/transactions/view/PhabricatorApplicationTransactionView.php @@ -203,7 +203,7 @@ class PhabricatorApplicationTransactionView extends AphrontView { throw new PhutilInvalidStateException('setObjectPHID'); } - $view = $this->buildPHUITimelineView(); + $view = $this->buildPHUITimelineView(false); if ($this->getShowEditActions()) { Javelin::initBehavior('phabricator-transaction-list'); diff --git a/src/infrastructure/diff/view/PHUIDiffInlineCommentDetailView.php b/src/infrastructure/diff/view/PHUIDiffInlineCommentDetailView.php index fdaa99ac7e..7ebe8e8c5f 100644 --- a/src/infrastructure/diff/view/PHUIDiffInlineCommentDetailView.php +++ b/src/infrastructure/diff/view/PHUIDiffInlineCommentDetailView.php @@ -377,7 +377,7 @@ final class PHUIDiffInlineCommentDetailView } $actions = null; - if ($action_buttons || $menu_items) { + if (($action_buttons || $menu_items) && false) { $actions = new PHUIButtonBarView(); $actions->setBorderless(true); $actions->addClass('inline-button-divider'); diff --git a/src/view/AphrontView.php b/src/view/AphrontView.php index 669742f29b..1928af5345 100644 --- a/src/view/AphrontView.php +++ b/src/view/AphrontView.php @@ -125,7 +125,7 @@ abstract class AphrontView extends Phobject * @return wild Renderable children. * @task */ - final protected function renderChildren() { + final public function renderChildren() { return $this->children; } diff --git a/src/view/phui/PHUITimelineEventView.php b/src/view/phui/PHUITimelineEventView.php index 73acf437af..32c213ca8e 100644 --- a/src/view/phui/PHUITimelineEventView.php +++ b/src/view/phui/PHUITimelineEventView.php @@ -331,12 +331,12 @@ final class PHUITimelineEventView extends AphrontView { $menu = null; $items = array(); - if (!$this->getIsPreview() && !$this->getHideCommentOptions()) { - foreach ($this->getEventGroup() as $event) { - $items[] = $event->getMenuItems($this->anchor); - } - $items = array_mergev($items); - } + // if (!$this->getIsPreview() && !$this->getHideCommentOptions()) { + // foreach ($this->getEventGroup() as $event) { + // $items[] = $event->getMenuItems($this->anchor); + // } + // $items = array_mergev($items); + // } if ($items) { $icon = id(new PHUIIconView()) @@ -431,11 +431,10 @@ final class PHUITimelineEventView extends AphrontView { $badges = null; if ($image_uri) { $image = javelin_tag( - ($this->userHandle->getURI()) ? 'a' : 'div', + 'div', array( 'style' => 'background-image: url('.$image_uri.')', 'class' => 'phui-timeline-image', - 'href' => $this->userHandle->getURI(), 'aural' => false, ), ''); diff --git a/webroot/rsrc/css/application/differential/revision-history.css b/webroot/rsrc/css/application/differential/revision-history.css index eca1a95ceb..01fb2c3165 100644 --- a/webroot/rsrc/css/application/differential/revision-history.css +++ b/webroot/rsrc/css/application/differential/revision-history.css @@ -37,6 +37,11 @@ background: #d0ffd0; } +.aphront-table-view tr.differential-update-history-current td, +.aphront-table-view tr.alt-differential-update-history-current td { + background: #d0ffd0; +} + .aphront-table-view .differential-update-history-old-now td.differential-update-history-old,