diff --git a/src/applications/differential/controller/changesetview/DifferentialChangesetViewController.php b/src/applications/differential/controller/changesetview/DifferentialChangesetViewController.php index 5bdfcdf8ee..d761ffe025 100644 --- a/src/applications/differential/controller/changesetview/DifferentialChangesetViewController.php +++ b/src/applications/differential/controller/changesetview/DifferentialChangesetViewController.php @@ -54,9 +54,9 @@ class DifferentialChangesetViewController extends DifferentialController { } switch ($view) { case 'new': - return $this->buildRawFileResponse($changeset->makeNewFile()); + return $this->buildRawFileResponse($changeset, $is_new = true); case 'old': - return $this->buildRawFileResponse($changeset->makeOldFile()); + return $this->buildRawFileResponse($changeset, $is_new = false); default: return new Aphront400Response(); } @@ -256,10 +256,53 @@ class DifferentialChangesetViewController extends DifferentialController { $author_phid); } - private function buildRawFileResponse($text) { - return id(new AphrontFileResponse()) - ->setMimeType('text/plain') - ->setContent($text); + private function buildRawFileResponse( + DifferentialChangeset $changeset, + $is_new) { + + if ($is_new) { + $key = 'raw:new:phid'; + } else { + $key = 'raw:old:phid'; + } + + $metadata = $changeset->getMetadata(); + + $file = null; + $phid = idx($metadata, $key); + if ($phid) { + $file = id(new PhabricatorFile())->loadOneWhere( + 'phid = %s', + $phid); + } + + if (!$file) { + // This is just building a cache of the changeset content in the file + // tool, and is safe to run on a read pathway. + $unguard = AphrontWriteGuard::beginScopedUnguardedWrites(); + + if ($is_new) { + $data = $changeset->makeNewFile(); + } else { + $data = $changeset->makeOldFile(); + } + + $file = PhabricatorFile::newFromFileData( + $data, + array( + 'name' => $changeset->getFilename(), + 'mime-type' => 'text/plain', + )); + + $metadata[$key] = $file->getPHID(); + $changeset->setMetadata($metadata); + $changeset->save(); + + unset($unguard); + } + + return id(new AphrontRedirectResponse()) + ->setURI($file->getBestURI()); } private function buildLintInlineComments($changeset) { diff --git a/src/applications/differential/controller/changesetview/__init__.php b/src/applications/differential/controller/changesetview/__init__.php index c1564fe51c..ab6be1cc2a 100644 --- a/src/applications/differential/controller/changesetview/__init__.php +++ b/src/applications/differential/controller/changesetview/__init__.php @@ -11,8 +11,8 @@ phutil_require_module('arcanist', 'unit/result'); phutil_require_module('phabricator', 'aphront/response/400'); phutil_require_module('phabricator', 'aphront/response/404'); phutil_require_module('phabricator', 'aphront/response/ajax'); -phutil_require_module('phabricator', 'aphront/response/file'); phutil_require_module('phabricator', 'aphront/response/redirect'); +phutil_require_module('phabricator', 'aphront/writeguard'); phutil_require_module('phabricator', 'applications/differential/controller/base'); phutil_require_module('phabricator', 'applications/differential/parser/changeset'); phutil_require_module('phabricator', 'applications/differential/storage/changeset'); @@ -20,6 +20,7 @@ phutil_require_module('phabricator', 'applications/differential/storage/diffprop phutil_require_module('phabricator', 'applications/differential/storage/inlinecomment'); phutil_require_module('phabricator', 'applications/differential/view/changesetdetailview'); phutil_require_module('phabricator', 'applications/differential/view/primarypane'); +phutil_require_module('phabricator', 'applications/files/storage/file'); phutil_require_module('phabricator', 'applications/markup/engine'); phutil_require_module('phabricator', 'applications/phid/handle/data'); phutil_require_module('phabricator', 'infrastructure/diff/engine');