Page MenuHomePhabricator

D9316.id22108.diff
No OneTemporary

D9316.id22108.diff

diff --git a/resources/sql/autopatches/20142805.chronicle.1.sql b/resources/sql/autopatches/20142805.chronicle.1.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20142805.chronicle.1.sql
@@ -0,0 +1,14 @@
+CREATE TABLE {$NAMESPACE}_chronicle.chronicle_trigger (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ phid VARCHAR(64) NOT NULL COLLATE utf8_bin,
+ name VARCHAR(254) NOT NULL COLLATE utf8_bin,
+ epoch INT UNSIGNED NOT NULL,
+ epochRepeat INT UNSIGNED NOT NULL,
+ actionClass VARCHAR(254) NOT NULL COLLATE utf8_bin,
+ actionData VARCHAR(4000) NOT NULL COLLATE utf8_bin,
+ viewPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin,
+ editPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin,
+ dateCreated INT UNSIGNED NOT NULL,
+ dateModified INT UNSIGNED NOT NULL,
+ UNIQUE KEY `key_phid` (phid)
+) ENGINE=InnoDB, COLLATE utf8_general_ci;
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -112,6 +112,18 @@
'CelerityResourcesOnDisk' => 'infrastructure/celerity/resources/CelerityResourcesOnDisk.php',
'CeleritySpriteGenerator' => 'infrastructure/celerity/CeleritySpriteGenerator.php',
'CelerityStaticResourceResponse' => 'infrastructure/celerity/CelerityStaticResourceResponse.php',
+ 'ChronicleAction' => 'applications/chronicle/action/ChronicleAction.php',
+ 'ChronicleCapabilityManagePlans' => 'applications/chronicle/capability/ChronicleCapabilityManageTriggers.php',
+ 'ChronicleController' => 'applications/chronicle/controller/ChronicleController.php',
+ 'ChronicleDAO' => 'applications/chronicle/storage/ChronicleDAO.php',
+ 'ChroniclePHIDTypeTrigger' => 'applications/chronicle/phid/ChroniclePHIDTypeTrigger.php',
+ 'ChronicleStartHarbormasterBuildAction' => 'applications/chronicle/action/ChronicleStartHarbormasterBuildAction.php',
+ 'ChronicleTrigger' => 'applications/chronicle/storage/ChronicleTrigger.php',
+ 'ChronicleTriggerAddController' => 'applications/chronicle/controller/ChronicleTriggerAddController.php',
+ 'ChronicleTriggerController' => 'applications/chronicle/controller/ChronicleTriggerController.php',
+ 'ChronicleTriggerListController' => 'applications/chronicle/controller/ChronicleTriggerListController.php',
+ 'ChronicleTriggerQuery' => 'applications/chronicle/query/ChronicleTriggerQuery.php',
+ 'ChronicleTriggerSearchEngine' => 'applications/chronicle/query/ChronicleTriggerSearchEngine.php',
'ConduitAPIMethod' => 'applications/conduit/method/ConduitAPIMethod.php',
'ConduitAPIRequest' => 'applications/conduit/protocol/ConduitAPIRequest.php',
'ConduitAPIResponse' => 'applications/conduit/protocol/ConduitAPIResponse.php',
@@ -1111,6 +1123,7 @@
'PhabricatorApplicationAuth' => 'applications/auth/application/PhabricatorApplicationAuth.php',
'PhabricatorApplicationCalendar' => 'applications/calendar/application/PhabricatorApplicationCalendar.php',
'PhabricatorApplicationChatLog' => 'applications/chatlog/applications/PhabricatorApplicationChatLog.php',
+ 'PhabricatorApplicationChronicle' => 'applications/chronicle/application/PhabricatorApplicationChronicle.php',
'PhabricatorApplicationConduit' => 'applications/conduit/application/PhabricatorApplicationConduit.php',
'PhabricatorApplicationConfig' => 'applications/config/application/PhabricatorApplicationConfig.php',
'PhabricatorApplicationConfigOptions' => 'applications/config/option/PhabricatorApplicationConfigOptions.php',
@@ -2786,6 +2799,21 @@
'CelerityResourceGraph' => 'AbstractDirectedGraph',
'CelerityResourceTransformerTestCase' => 'PhabricatorTestCase',
'CelerityResourcesOnDisk' => 'CelerityPhysicalResources',
+ 'ChronicleCapabilityManagePlans' => 'PhabricatorPolicyCapability',
+ 'ChronicleController' => 'PhabricatorController',
+ 'ChronicleDAO' => 'PhabricatorLiskDAO',
+ 'ChroniclePHIDTypeTrigger' => 'PhabricatorPHIDType',
+ 'ChronicleStartHarbormasterBuildAction' => 'ChronicleAction',
+ 'ChronicleTrigger' =>
+ array(
+ 0 => 'ChronicleDAO',
+ 1 => 'PhabricatorPolicyInterface',
+ ),
+ 'ChronicleTriggerAddController' => 'ChronicleTriggerController',
+ 'ChronicleTriggerController' => 'ChronicleController',
+ 'ChronicleTriggerListController' => 'ChronicleTriggerController',
+ 'ChronicleTriggerQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
+ 'ChronicleTriggerSearchEngine' => 'PhabricatorApplicationSearchEngine',
'ConduitAPIMethod' =>
array(
0 => 'Phobject',
@@ -3866,6 +3894,7 @@
'PhabricatorApplicationAuth' => 'PhabricatorApplication',
'PhabricatorApplicationCalendar' => 'PhabricatorApplication',
'PhabricatorApplicationChatLog' => 'PhabricatorApplication',
+ 'PhabricatorApplicationChronicle' => 'PhabricatorApplication',
'PhabricatorApplicationConduit' => 'PhabricatorApplication',
'PhabricatorApplicationConfig' => 'PhabricatorApplication',
'PhabricatorApplicationConfigOptions' => 'Phobject',
diff --git a/src/applications/chronicle/action/ChronicleAction.php b/src/applications/chronicle/action/ChronicleAction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/chronicle/action/ChronicleAction.php
@@ -0,0 +1,75 @@
+<?php
+
+abstract class ChronicleAction {
+
+ public static function getImplementations() {
+ return id(new PhutilSymbolLoader())
+ ->setAncestorClass('ChronicleAction')
+ ->loadObjects();
+ }
+
+ public static function getImplementation($class) {
+ $base = idx(self::getImplementations(), $class);
+
+ if ($base) {
+ return (clone $base);
+ }
+
+ return null;
+ }
+
+ public static function requireImplementation($class) {
+ if (!$class) {
+ throw new Exception(pht('No implementation is specified!'));
+ }
+
+ $implementation = self::getImplementation($class);
+ if (!$implementation) {
+ throw new Exception(pht('No such implementation "%s" exists!', $class));
+ }
+
+ return $implementation;
+ }
+
+ /**
+ * The name of the implementation.
+ */
+ abstract public function getName();
+
+ /**
+ * The description of the implementation.
+ */
+ public function getDescription() {
+ return '';
+ }
+
+ /**
+ * Run the build target against the specified build.
+ */
+ abstract public function execute();
+
+ /**
+ * Gets the settings for this build step.
+ */
+ public function getSettings() {
+ return $this->settings;
+ }
+
+ public function getSetting($key, $default = null) {
+ return idx($this->settings, $key, $default);
+ }
+
+ /**
+ * Loads the settings for this build step implementation from a build
+ * step or target.
+ */
+ public final function loadSettings($action_data) {
+ $this->settings = $action_data;
+ return $this;
+ }
+
+ public function getFieldSpecifications() {
+ return array();
+ }
+
+}
diff --git a/src/applications/chronicle/action/ChronicleStartHarbormasterBuildAction.php b/src/applications/chronicle/action/ChronicleStartHarbormasterBuildAction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/chronicle/action/ChronicleStartHarbormasterBuildAction.php
@@ -0,0 +1,38 @@
+<?php
+
+final class ChronicleStartHarbormasterBuildAction
+ extends ChronicleAction {
+
+ public function getName() {
+ return pht('Start Harbormaster Build');
+ }
+
+ public function getDescription() {
+ return pht('Starts a Harbormaster build against a branch in a repository');
+ }
+
+ public function execute() {
+ return;
+ }
+
+ public function getFieldSpecifications() {
+ return array(
+ 'callsign' => array(
+ 'name' => pht('Repository Callsign'),
+ 'type' => 'text',
+ 'required' => true,
+ ),
+ 'branch' => array(
+ 'name' => pht('Branch or Reference'),
+ 'type' => 'text',
+ 'required' => true
+ ),
+ 'planid' => array(
+ 'name' => pht('Build Plan ID'),
+ 'type' => 'text',
+ 'required' => true,
+ ),
+ );
+ }
+
+}
diff --git a/src/applications/chronicle/application/PhabricatorApplicationChronicle.php b/src/applications/chronicle/application/PhabricatorApplicationChronicle.php
new file mode 100644
--- /dev/null
+++ b/src/applications/chronicle/application/PhabricatorApplicationChronicle.php
@@ -0,0 +1,59 @@
+<?php
+
+final class PhabricatorApplicationChronicle extends PhabricatorApplication {
+
+ public function getBaseURI() {
+ return '/chronicle/';
+ }
+
+ public function getShortDescription() {
+ return pht('Timed Events');
+ }
+
+ public function getIconName() {
+ return 'chronicle';
+ }
+
+ public function getTitleGlyph() {
+ return "\xE2\x99\xBB";
+ }
+
+ public function getApplicationGroup() {
+ return self::GROUP_UTILITIES;
+ }
+
+ public function isBeta() {
+ return true;
+ }
+
+ public function getRoutes() {
+ return array(
+ '/chronicle/' => array(
+ '(?:query/(?P<queryKey>[^/]+)/)?'
+ => 'ChronicleTriggerListController',
+ 'trigger/' => array(
+ 'add/(?:(?P<id>\d+)/)?' => 'ChronicleTriggerAddController',
+ // 'new/(?P<plan>\d+)/(?P<class>[^/]+)/'
+ // => 'ChronicleTriggerEditController',
+ // 'edit/(?:(?P<id>\d+)/)?' => 'ChronicleTriggerEditController',
+ // 'view/(?:(?P<id>\d+)/)?' => 'ChronicleTriggerViewController',
+ // 'delete/(?:(?P<id>\d+)/)?' => 'ChronicleTriggerDeleteController',
+ ),
+ ),
+ );
+ }
+
+ public function getCustomCapabilities() {
+ return array(
+ ChronicleCapabilityManagePlans::CAPABILITY => array(
+ 'caption' => pht('Can create and manage triggers.'),
+ 'default' => PhabricatorPolicies::POLICY_ADMIN,
+ ),
+ );
+ }
+
+ public function shouldAppearInLaunchView() {
+ return false;
+ }
+
+}
diff --git a/src/applications/chronicle/capability/ChronicleCapabilityManageTriggers.php b/src/applications/chronicle/capability/ChronicleCapabilityManageTriggers.php
new file mode 100644
--- /dev/null
+++ b/src/applications/chronicle/capability/ChronicleCapabilityManageTriggers.php
@@ -0,0 +1,21 @@
+<?php
+
+final class ChronicleCapabilityManagePlans
+ extends PhabricatorPolicyCapability {
+
+ const CAPABILITY = 'chronicle.triggers';
+
+ public function getCapabilityKey() {
+ return self::CAPABILITY;
+ }
+
+ public function getCapabilityName() {
+ return pht('Can Manage Triggers');
+ }
+
+ public function describeCapabilityRejection() {
+ return pht(
+ 'You do not have permission to manage Chronicle triggers.');
+ }
+
+}
diff --git a/src/applications/chronicle/controller/ChronicleController.php b/src/applications/chronicle/controller/ChronicleController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/chronicle/controller/ChronicleController.php
@@ -0,0 +1,18 @@
+<?php
+
+abstract class ChronicleController extends PhabricatorController {
+
+ public function buildApplicationCrumbs() {
+ $crumbs = parent::buildApplicationCrumbs();
+
+ $crumbs->addAction(
+ id(new PHUIListItemView())
+ ->setName(pht('New Trigger'))
+ ->setHref($this->getApplicationURI('trigger/add/'))
+ ->setIcon('fa-plus-square')
+ ->setWorkflow(true));
+
+ return $crumbs;
+ }
+
+}
diff --git a/src/applications/chronicle/controller/ChronicleTriggerAddController.php b/src/applications/chronicle/controller/ChronicleTriggerAddController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/chronicle/controller/ChronicleTriggerAddController.php
@@ -0,0 +1,57 @@
+<?php
+
+final class ChronicleTriggerAddController
+ extends ChronicleTriggerController {
+
+ public function processRequest() {
+ $request = $this->getRequest();
+ $viewer = $request->getUser();
+
+ $this->requireApplicationCapability(
+ ChronicleCapabilityManagePlans::CAPABILITY);
+
+ $cancel_uri = $this->getApplicationURI('/');
+
+ $errors = array();
+ if ($request->isFormPost()) {
+
+ $errors[] = pht(
+ 'Not yet implemented.');
+
+ $class = $request->getStr('class');
+ if (!ChronicleAction::getImplementation($class)) {
+ $errors[] = pht(
+ 'Choose the type of build step you want to add.');
+ }
+ if (!$errors) {
+ $new_uri = $this->getApplicationURI("trigger/new/{$class}/");
+ return id(new AphrontRedirectResponse())->setURI($new_uri);
+ }
+ }
+
+ $control = id(new AphrontFormRadioButtonControl())
+ ->setName('class');
+
+ $all = ChronicleAction::getImplementations();
+ foreach ($all as $class => $implementation) {
+ $control->addButton(
+ $class,
+ $implementation->getName(),
+ $implementation->getDescription());
+ }
+
+ if ($errors) {
+ $errors = id(new AphrontErrorView())
+ ->setErrors($errors);
+ }
+
+ return $this->newDialog()
+ ->setTitle(pht('Create New Trigger'))
+ ->addSubmitButton(pht('Create New Trigger'))
+ ->addCancelButton($cancel_uri)
+ ->appendChild($errors)
+ ->appendParagraph(pht('Choose a type of build step to add:'))
+ ->appendChild($control);
+ }
+
+}
diff --git a/src/applications/chronicle/controller/ChronicleTriggerController.php b/src/applications/chronicle/controller/ChronicleTriggerController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/chronicle/controller/ChronicleTriggerController.php
@@ -0,0 +1,5 @@
+<?php
+
+abstract class ChronicleTriggerController extends ChronicleController {
+
+}
diff --git a/src/applications/chronicle/controller/ChronicleTriggerListController.php b/src/applications/chronicle/controller/ChronicleTriggerListController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/chronicle/controller/ChronicleTriggerListController.php
@@ -0,0 +1,44 @@
+<?php
+
+final class ChronicleTriggerListController extends ChronicleTriggerController {
+
+ private $queryKey;
+
+ public function shouldAllowPublic() {
+ return true;
+ }
+
+ public function willProcessRequest(array $data) {
+ $this->queryKey = idx($data, 'queryKey');
+ }
+
+ public function processRequest() {
+ $request = $this->getRequest();
+ $controller = id(new PhabricatorApplicationSearchController($request))
+ ->setQueryKey($this->queryKey)
+ ->setSearchEngine(new ChronicleTriggerSearchEngine())
+ ->setNavigation($this->buildSideNavView());
+
+ return $this->delegateToController($controller);
+ }
+
+ public function buildSideNavView($for_app = false) {
+ $user = $this->getRequest()->getUser();
+
+ $nav = new AphrontSideNavFilterView();
+ $nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
+
+ id(new ChronicleTriggerSearchEngine())
+ ->setViewer($user)
+ ->addNavigationItems($nav->getMenu());
+
+ $nav->selectFilter(null);
+
+ return $nav;
+ }
+
+ public function buildApplicationMenu() {
+ return $this->buildSideNavView(true)->getMenu();
+ }
+
+}
diff --git a/src/applications/chronicle/phid/ChroniclePHIDTypeTrigger.php b/src/applications/chronicle/phid/ChroniclePHIDTypeTrigger.php
new file mode 100644
--- /dev/null
+++ b/src/applications/chronicle/phid/ChroniclePHIDTypeTrigger.php
@@ -0,0 +1,45 @@
+<?php
+
+final class ChroniclePHIDTypeTrigger extends PhabricatorPHIDType {
+
+ const TYPECONST = 'CHRT';
+
+ public function getTypeConstant() {
+ return self::TYPECONST;
+ }
+
+ public function getTypeName() {
+ return pht('Chronicle Trigger');
+ }
+
+ public function newObject() {
+ return new ChronicleTrigger();
+ }
+
+ protected function buildQueryForObjects(
+ PhabricatorObjectQuery $query,
+ array $phids) {
+
+ return id(new ChronicleTriggerQuery())
+ ->withPHIDs($phids)
+ ->needBuildableHandles(true);
+ }
+
+ public function loadHandles(
+ PhabricatorHandleQuery $query,
+ array $handles,
+ array $objects) {
+
+ foreach ($handles as $phid => $handle) {
+ $trigger = $objects[$phid];
+
+ $id = $trigger->getID();
+ $name = $trigger->getName();
+
+ $handle->setURI("/chronicle/trigger/view/{$id}");
+ $handle->setName("Chronicle Trigger {$id}");
+ $handle->setFullName("Chronicle Trigger {$id}: ".$name);
+ }
+ }
+
+}
diff --git a/src/applications/chronicle/query/ChronicleTriggerQuery.php b/src/applications/chronicle/query/ChronicleTriggerQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/chronicle/query/ChronicleTriggerQuery.php
@@ -0,0 +1,60 @@
+<?php
+
+final class ChronicleTriggerQuery
+ extends PhabricatorCursorPagedPolicyAwareQuery {
+
+ private $ids;
+ private $phids;
+
+ public function withIDs(array $ids) {
+ $this->ids = $ids;
+ return $this;
+ }
+
+ public function withPHIDs(array $phids) {
+ $this->phids = $phids;
+ return $this;
+ }
+
+ protected function loadPage() {
+ $table = new ChronicleTrigger();
+ $conn_r = $table->establishConnection('r');
+
+ $data = queryfx_all(
+ $conn_r,
+ 'SELECT * FROM %T %Q %Q %Q',
+ $table->getTableName(),
+ $this->buildWhereClause($conn_r),
+ $this->buildOrderClause($conn_r),
+ $this->buildLimitClause($conn_r));
+
+ return $table->loadAllFromArray($data);
+ }
+
+ private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ $where = array();
+
+ if ($this->ids !== null) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'id IN (%Ld)',
+ $this->ids);
+ }
+
+ if ($this->phids !== null) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'phid IN (%Ls)',
+ $this->phids);
+ }
+
+ $where[] = $this->buildPagingClause($conn_r);
+
+ return $this->formatWhereClause($where);
+ }
+
+ public function getQueryApplicationClass() {
+ return 'PhabricatorApplicationChronicle';
+ }
+
+}
diff --git a/src/applications/chronicle/query/ChronicleTriggerSearchEngine.php b/src/applications/chronicle/query/ChronicleTriggerSearchEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/chronicle/query/ChronicleTriggerSearchEngine.php
@@ -0,0 +1,80 @@
+<?php
+
+final class ChronicleTriggerSearchEngine
+ extends PhabricatorApplicationSearchEngine {
+
+ public function getApplicationClassName() {
+ return 'PhabricatorApplicationChronicle';
+ }
+
+ public function buildSavedQueryFromRequest(AphrontRequest $request) {
+ $saved = new PhabricatorSavedQuery();
+
+ return $saved;
+ }
+
+ public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
+ $query = id(new ChronicleTriggerQuery());
+
+ return $query;
+ }
+
+ public function buildSearchForm(
+ AphrontFormView $form,
+ PhabricatorSavedQuery $saved_query) {
+
+ // TODO
+ }
+
+ protected function getURI($path) {
+ return '/chronicle/'.$path;
+ }
+
+ public function getBuiltinQueryNames() {
+ $names = array(
+ 'all' => pht('All Triggers'),
+ );
+
+ return $names;
+ }
+
+ public function buildSavedQueryFromBuiltin($query_key) {
+
+ $query = $this->newSavedQuery();
+ $query->setQueryKey($query_key);
+
+ switch ($query_key) {
+ case 'all':
+ return $query;
+ }
+
+ return parent::buildSavedQueryFromBuiltin($query_key);
+ }
+
+ protected function renderResultList(
+ array $triggers,
+ PhabricatorSavedQuery $query,
+ array $handles) {
+ assert_instances_of($triggers, 'ChronicleTrigger');
+
+ $viewer = $this->requireViewer();
+
+ $list = new PHUIObjectItemListView();
+ $list->setCards(true);
+ foreach ($triggers as $trigger) {
+ $id = $trigger->getID();
+
+ $item = id(new PHUIObjectItemView())
+ ->setHeader(pht('Chronicle Trigger %d', $id));
+
+ if ($id) {
+ $item->setHref("/chronicle/trigger/view/{$id}");
+ }
+
+ $list->addItem($item);
+
+ }
+
+ return $list;
+ }
+}
diff --git a/src/applications/chronicle/storage/ChronicleDAO.php b/src/applications/chronicle/storage/ChronicleDAO.php
new file mode 100644
--- /dev/null
+++ b/src/applications/chronicle/storage/ChronicleDAO.php
@@ -0,0 +1,9 @@
+<?php
+
+abstract class ChronicleDAO extends PhabricatorLiskDAO {
+
+ public function getApplicationName() {
+ return 'chronicle';
+ }
+
+}
diff --git a/src/applications/chronicle/storage/ChronicleTrigger.php b/src/applications/chronicle/storage/ChronicleTrigger.php
new file mode 100644
--- /dev/null
+++ b/src/applications/chronicle/storage/ChronicleTrigger.php
@@ -0,0 +1,54 @@
+<?php
+
+final class ChronicleTrigger extends ChronicleDAO
+ implements PhabricatorPolicyInterface {
+
+ protected $name;
+ protected $epoch;
+ protected $epochRepeat;
+ protected $actionClass;
+ protected $actionData = array();
+
+ public function getConfiguration() {
+ return array(
+ self::CONFIG_AUX_PHID => true,
+ self::CONFIG_SERIALIZATION => array(
+ 'actionData' => self::SERIALIZATION_JSON,
+ )
+ ) + parent::getConfiguration();
+ }
+
+ public function generatePHID() {
+ return PhabricatorPHID::generateNewPHID(
+ ChroniclePHIDTypeTrigger::TYPECONST);
+ }
+
+
+/* -( PhabricatorPolicyInterface )----------------------------------------- */
+
+
+ public function getCapabilities() {
+ return array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ );
+ }
+
+ public function getPolicy($capability) {
+ switch ($capability) {
+ case PhabricatorPolicyCapability::CAN_VIEW:
+ return $this->getViewPolicy();
+ case PhabricatorPolicyCapability::CAN_EDIT:
+ return $this->getEditPolicy();
+ }
+ }
+
+ public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
+ return false;
+ }
+
+ public function describeAutomaticCapability($capability) {
+ return null;
+ }
+
+}
diff --git a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
--- a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
+++ b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
@@ -119,6 +119,7 @@
'db.phragment' => array(),
'db.dashboard' => array(),
'db.system' => array(),
+ 'db.chronicle' => array(),
'0000.legacy.sql' => array(
'legacy' => 0,
),

File Metadata

Mime Type
text/plain
Expires
Thu, Jul 31, 5:20 PM (4 d, 16 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
8763166
Default Alt Text
D9316.id22108.diff (21 KB)

Event Timeline