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.
This commit is contained in:
293
scripts/bake/bake_differential.php
Normal file
293
scripts/bake/bake_differential.php
Normal file
@@ -0,0 +1,293 @@
|
||||
#!/usr/local/bin/php
|
||||
<?php
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// Bootstrap.
|
||||
|
||||
$PHABRICATOR_ROOT = dirname(dirname(dirname(__FILE__)));
|
||||
require_once $PHABRICATOR_ROOT.'/scripts/__init_script__.php';
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// Command line.
|
||||
|
||||
if (count($argv) != 2) {
|
||||
print("Usage: $argv[0] <output_directory>\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);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
Reference in New Issue
Block a user