diff --git a/bin/storage b/bin/storage
new file mode 120000
index 0000000000..788528eb8d
--- /dev/null
+++ b/bin/storage
@@ -0,0 +1 @@
+../scripts/sql/manage_storage.php
\ No newline at end of file
diff --git a/scripts/__init_script__.php b/scripts/__init_script__.php
index e2551149c3..ea51f78e03 100644
--- a/scripts/__init_script__.php
+++ b/scripts/__init_script__.php
@@ -1,67 +1,77 @@
 <?php
 
 /*
  * Copyright 2012 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 error_reporting(E_ALL | E_STRICT);
 ini_set('display_errors', 1);
 
 $include_path = ini_get('include_path');
 ini_set(
   'include_path',
   $include_path.PATH_SEPARATOR.dirname(__FILE__).'/../../');
 @include_once 'libphutil/scripts/__init_script__.php';
 if (!@constant('__LIBPHUTIL__')) {
   echo "ERROR: Unable to load libphutil. Update your PHP 'include_path' to ".
        "include the parent directory of libphutil/.\n";
   exit(1);
 }
 
 phutil_load_library(dirname(__FILE__).'/../src/');
 
 // NOTE: This is dangerous in general, but we know we're in a script context and
 // are not vulnerable to CSRF.
 AphrontWriteGuard::allowDangerousUnguardedWrites(true);
 
 require_once dirname(dirname(__FILE__)).'/conf/__init_conf__.php';
 
 $env = isset($_SERVER['PHABRICATOR_ENV'])
   ? $_SERVER['PHABRICATOR_ENV']
   : getenv('PHABRICATOR_ENV');
 if (!$env) {
-  echo "Define PHABRICATOR_ENV before running this script.\n";
+  phutil_require_module('phutil', 'console');
+  echo phutil_console_wrap(
+    phutil_console_format(
+      "**ERROR**: PHABRICATOR_ENV Not Set\n\n".
+      "Define the __PHABRICATOR_ENV__ environment variable before running ".
+      "this script. You can do it on the command line like this:\n\n".
+      "  $ PHABRICATOR_ENV=__custom/myconfig__ %s ...\n\n".
+      "Replace __custom/myconfig__ with the path to your configuration file. ".
+      "For more information, see the 'Configuration Guide' in the ".
+      "Phabricator documentation.\n\n",
+      $argv[0]));
   exit(1);
 }
 
 $conf = phabricator_read_config_file($env);
 $conf['phabricator.env'] = $env;
 
 phutil_require_module('phabricator', 'infrastructure/env');
 PhabricatorEnv::setEnvConfig($conf);
 
 phutil_load_library('arcanist/src');
 
 foreach (PhabricatorEnv::getEnvConfig('load-libraries') as $library) {
   phutil_load_library($library);
 }
 
 PhutilErrorHandler::initialize();
 PhabricatorEventEngine::initialize();
 
 $tz = PhabricatorEnv::getEnvConfig('phabricator.timezone');
 if ($tz) {
   date_default_timezone_set($tz);
 }
diff --git a/scripts/install/update_phabricator.sh b/scripts/install/update_phabricator.sh
index c30b6ad385..77925e9cc9 100755
--- a/scripts/install/update_phabricator.sh
+++ b/scripts/install/update_phabricator.sh
@@ -1,77 +1,77 @@
 #!/bin/sh
 
 set -e
 set -x
 
 # This is an example script for updating Phabricator, similar to the one used to
 # update <https://secure.phabricator.com/>. It might not work perfectly on your
 # system, but hopefully it should be easy to adapt.
 
 # NOTE: This script assumes you are running it from a directory which contains
 # arcanist/, libphutil/, phabricator/, and possibly diviner/.
 
 ROOT=`pwd` # You can hard-code the path here instead.
 
 ### UPDATE WORKING COPIES ######################################################
 
 if [ -e $ROOT/diviner ]
 then
   cd $ROOT/diviner
   git pull
 fi
 
 cd $ROOT/libphutil
 git pull
 
 cd $ROOT/arcanist
 git pull
 
 cd $ROOT/phabricator
 git pull
 git submodule update --init
 
 
 ### RUN TESTS ##################################################################
 
 # This is an acceptance test that makes sure all symbols can be loaded to
 # avoid issues like missing methods in descendants of abstract base classes.
 cd $ROOT/phabricator
 ../arcanist/bin/arc unit src/infrastructure/__tests__/
 
 
 ### CYCLE APACHE AND DAEMONS ###################################################
 
 # Stop daemons.
 $ROOT/phabricator/bin/phd stop
 
 # Stop Apache. Depening on what system you're running, you may need to use
 # 'apachectl' or something else to cycle apache.
 sudo /etc/init.d/httpd stop
 
 # Upgrade the database schema.
-$ROOT/phabricator/scripts/sql/upgrade_schema.php -f
+$ROOT/phabricator/bin/storage upgrade --force
 
 # Restart apache.
 sudo /etc/init.d/httpd start
 
 # Restart daemons. Customize this to start whatever daemons you're running on
 # your system.
 
 # $ROOT/phabricator/bin/phd repository-launch-master
 # $ROOT/phabricator/bin/phd launch garbagecollector
 # $ROOT/phabricator/bin/phd launch 4 taskmaster
 # $ROOT/phabricator/bin/phd launch ircbot /config/bot.json
 
 
 ### GENERATE DOCUMENTATION #####################################################
 
 # This generates documentation if you have diviner/ checked out. You generally
 # don't need to do this unless you're contributing to Phabricator and want to
 # preview some of the amazing documentation you've just written.
 if [ -e $ROOT/diviner ]
 then
   cd $ROOT/diviner && $ROOT/diviner/bin/diviner .
   cd $ROOT/libphutil && $ROOT/diviner/bin/diviner .
   cd $ROOT/arcanist && $ROOT/diviner/bin/diviner .
   cd $ROOT/phabricator && $ROOT/diviner/bin/diviner .
 fi
diff --git a/scripts/sql/manage_storage.php b/scripts/sql/manage_storage.php
new file mode 100755
index 0000000000..e2ed32cc02
--- /dev/null
+++ b/scripts/sql/manage_storage.php
@@ -0,0 +1,123 @@
+#!/usr/bin/env php
+<?php
+
+/*
+ * Copyright 2012 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+$root = dirname(dirname(dirname(__FILE__)));
+require_once $root.'/scripts/__init_script__.php';
+
+$args = new PhutilArgumentParser($argv);
+$args->setTagline('manage Phabricator storage and schemata');
+$args->setSynopsis(<<<EOHELP
+**storage** __workflow__ [__options__]
+Manage Phabricator database storage and schema versioning.
+
+**storage** upgrade
+Initialize or upgrade Phabricator storage.
+
+**storage** upgrade --user __root__ --password __hunter2__
+Use administrative credentials for schema changes.
+EOHELP
+);
+$args->parseStandardArguments();
+
+$conf = PhabricatorEnv::newObjectFromConfig('mysql.configuration-provider');
+
+$default_user       = $conf->getUser();
+$default_password   = $conf->getPassword();
+$default_host       = $conf->getHost();
+$default_namespace  = 'phabricator';
+
+try {
+  $args->parsePartial(
+    array(
+      array(
+        'name'    => 'force',
+        'short'   => 'f',
+        'help'    => 'Do not prompt before performing dangerous operations.',
+      ),
+      array(
+        'name'    => 'user',
+        'short'   => 'u',
+        'param'   => 'username',
+        'default' => $default_user,
+        'help'    => "Connect with __username__ instead of the configured ".
+                     "default ('{$default_user}').",
+      ),
+      array(
+        'name'    => 'password',
+        'short'   => 'p',
+        'param'   => 'password',
+        'default' => $default_password,
+        'help'    => 'Use __password__ instead of the configured default.',
+      ),
+      array(
+        'name'    => 'namespace',
+        'param'   => 'name',
+        'default' => $default_namespace,
+        'help'    => "Use namespace __namespace__ instead of the configured ".
+                     "default ('{$default_namespace}'). This is an advanced ".
+                     "feature used by unit tests; you should not normally ".
+                     "use this flag.",
+      ),
+      array(
+        'name'  => 'dryrun',
+        'help'  => 'Do not actually change anything, just show what would be '.
+                   'changed.',
+      ),
+    ));
+} catch (PhutilArgumentUsageException $ex) {
+  $args->printUsageException($ex);
+  exit(77);
+}
+
+$api = new PhabricatorStorageManagementAPI();
+$api->setUser($args->getArg('user'));
+$api->setHost($default_host);
+$api->setPassword($args->getArg('password'));
+$api->setNamespace($args->getArg('namespace'));
+
+try {
+  queryfx(
+    $api->getConn('meta_data', $select_database = false),
+    'SELECT 1');
+} catch (AphrontQueryException $ex) {
+  echo phutil_console_format(
+    "**%s**: %s\n",
+    'Unable To Connect',
+    $ex->getMessage());
+  exit(1);
+}
+
+$workflows = array(
+  new PhabricatorStorageManagementDatabasesWorkflow(),
+  new PhabricatorStorageManagementDestroyWorkflow(),
+  new PhabricatorStorageManagementDumpWorkflow(),
+  new PhabricatorStorageManagementStatusWorkflow(),
+  new PhabricatorStorageManagementUpgradeWorkflow(),
+);
+
+$patches = PhabricatorSQLPatchList::buildAllPatches();
+
+foreach ($workflows as $workflow) {
+  $workflow->setAPI($api);
+  $workflow->setPatches($patches);
+}
+
+$workflows[] = new PhutilHelpArgumentWorkflow();
+
+$args->parseWorkflows($workflows);
diff --git a/scripts/sql/upgrade_schema.php b/scripts/sql/upgrade_schema.php
index 1eb362a0ef..16383493f9 100755
--- a/scripts/sql/upgrade_schema.php
+++ b/scripts/sql/upgrade_schema.php
@@ -1,220 +1,26 @@
 #!/usr/bin/env php
 <?php
 
 /*
  * Copyright 2012 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-$root = dirname(dirname(dirname(__FILE__)));
-require_once $root.'/scripts/__init_script__.php';
-
-phutil_require_module('phutil', 'console');
-phutil_require_module('phabricator', 'infrastructure/setup/sql');
-
-define('SCHEMA_VERSION_TABLE_NAME', 'schema_version');
-
-// TODO: getopt() is super terrible, move to something less terrible.
-$options = getopt('fhdv:u:p:m:') + array(
-  'v' => null, // Upgrade from specific version
-  'u' => null, // Override MySQL User
-  'p' => null, // Override MySQL Pass
-  'm' => null, // Specify max version to upgrade to
-);
-
-foreach (array('h', 'f', 'd') as $key) {
-  // By default, these keys are set to 'false' to indicate that the flag was
-  // passed.
-  if (array_key_exists($key, $options)) {
-    $options[$key] = true;
-  }
-}
-
-if (!empty($options['h']) || ($options['v'] && !is_numeric($options['v']))
-    || ($options['m'] && !is_numeric($options['m']))) {
-  usage();
-}
-
-if (empty($options['f']) && empty($options['d'])) {
-  echo phutil_console_wrap(
-    "Before running this script, you should take down the Phabricator web ".
-    "interface and stop any running Phabricator daemons.");
-
-  if (!phutil_console_confirm('Are you ready to continue?')) {
-    echo "Cancelled.\n";
-    exit(1);
-  }
-}
-
-// Use always the version from the commandline if it is defined
-$next_version = isset($options['v']) ? (int)$options['v'] : null;
-$max_version = isset($options['m']) ? (int)$options['m'] : null;
-
-$conf = PhabricatorEnv::newObjectFromConfig('mysql.configuration-provider');
-
-if ($options['u']) {
-  $conn_user = $options['u'];
-  $conn_pass = $options['p'];
-} else {
-  $conn_user = $conf->getUser();
-  $conn_pass = $conf->getPassword();
-}
-$conn_host = $conf->getHost();
-
-// Split out port information, since the command-line client requires a
-// separate flag for the port.
-$uri = new PhutilURI('mysql://'.$conn_host);
-if ($uri->getPort()) {
-  $conn_port = $uri->getPort();
-  $conn_bare_hostname = $uri->getDomain();
-} else {
-  $conn_port = null;
-  $conn_bare_hostname = $conn_host;
-}
-
-$conn = PhabricatorEnv::newObjectFromConfig(
-  'mysql.implementation',
-  array(
-    array(
-      'user'      => $conn_user,
-      'pass'      => $conn_pass,
-      'host'      => $conn_host,
-      'database'  => null,
-    ),
-  ));
-
-try {
-
-  $create_sql = <<<END
-  CREATE DATABASE IF NOT EXISTS `phabricator_meta_data`;
-END;
-  queryfx($conn, $create_sql);
-
-  $create_sql = <<<END
-  CREATE TABLE IF NOT EXISTS phabricator_meta_data.`schema_version` (
-    `version` INTEGER not null
-  );
-END;
-  queryfx($conn, $create_sql);
-
-  // Get the version only if commandline argument wasn't given
-  if ($next_version === null) {
-    $version = queryfx_one(
-      $conn,
-      'SELECT * FROM phabricator_meta_data.%T',
-      SCHEMA_VERSION_TABLE_NAME);
-
-    if (!$version) {
-      print "*** No version information in the database ***\n";
-      print "*** Give the first patch version which to  ***\n";
-      print "*** apply as the command line argument     ***\n";
-      exit(-1);
-    }
-
-    $next_version = $version['version'] + 1;
-  }
-
-  $patches = PhabricatorSQLPatchList::getPatchList();
-
-  $patch_applied = false;
-  foreach ($patches as $patch) {
-    if ($patch['version'] < $next_version) {
-      continue;
-    }
-
-    if ($max_version && $patch['version'] > $max_version) {
-      continue;
-    }
-
-    $short_name = basename($patch['path']);
-    print "Applying patch {$short_name}...\n";
-
-    if (!empty($options['d'])) {
-      $patch_applied = true;
-      continue;
-    }
-
-    if ($conn_port) {
-      $port = '--port='.(int)$conn_port;
-    } else {
-      $port = null;
-    }
-
-    if (preg_match('/\.php$/', $patch['path'])) {
-      $schema_conn = $conn;
-      require_once $patch['path'];
-    } else {
-      list($stdout, $stderr) = execx(
-        "mysql --user=%s --password=%s --host=%s {$port} ".
-        "--default-character-set=utf8 < %s",
-        $conn_user,
-        $conn_pass,
-        $conn_bare_hostname,
-        $patch['path']);
-
-      if ($stderr) {
-        print $stderr;
-        exit(-1);
-      }
-    }
-
-    // Patch was successful, update the db with the latest applied patch version
-    // 'DELETE' and 'INSERT' instead of update, because the table might be empty
-    queryfx(
-      $conn,
-      'DELETE FROM phabricator_meta_data.%T',
-      SCHEMA_VERSION_TABLE_NAME);
-    queryfx(
-      $conn,
-      'INSERT INTO phabricator_meta_data.%T VALUES (%d)',
-      SCHEMA_VERSION_TABLE_NAME,
-      $patch['version']);
-
-    $patch_applied = true;
-  }
-
-  if (!$patch_applied) {
-    print "Your database is already up-to-date.\n";
-  }
-
-} catch (AphrontQueryAccessDeniedException $ex) {
-  echo
-    "ACCESS DENIED\n".
-    "The user '{$conn_user}' does not have sufficient MySQL privileges to\n".
-    "execute the schema upgrade. Use the -u and -p flags to run as a user\n".
-    "with more privileges (e.g., root).".
-    "\n\n".
-    "EXCEPTION:\n".
-    $ex->getMessage().
-    "\n\n";
-  exit(1);
-}
-
-function usage() {
-  echo
-    "usage: upgrade_schema.php [-v version] [-u user -p pass] [-f] [-h]".
-    "\n\n".
-    "Run 'upgrade_schema.php -u root -p hunter2' to override the configured ".
-    "default user.\n".
-    "Run 'upgrade_schema.php -v 12' to apply all patches starting from ".
-    "version 12. It is very unlikely you need to do this.\n".
-    "Run 'upgrade_schema.php -m 110' to apply all patches up to and ".
-    "including version 110 (but nothing past).\n".
-    "Use the -f flag to upgrade noninteractively, without prompting.\n".
-    "Use the -d flag to do a dry run - patches that would be applied ".
-    "will be listed, but not applied.\n".
-    "Use the -h flag to show this help.\n";
-  exit(1);
-}
-
+echo "This script has been replaced by 'phabricator/bin/storage'.\n\n".
+     "Run:\n\n".
+     "  phabricator/bin $ ./storage help\n\n".
+     "...for help, or:\n\n".
+     "  phabricator/bin $ ./storage upgrade\n\n".
+     "...to upgrade storage.\n\n";
+exit(1);
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
index bd9c8e03f7..7f46fddf6f 100644
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1,1860 +1,1876 @@
 <?php
 
 /**
  * This file is automatically generated. Use 'phutil_mapper.php' to rebuild it.
  * @generated
  */
 
 phutil_register_library_map(array(
   'class' =>
   array(
     'Aphront304Response' => 'aphront/response/304',
     'Aphront400Response' => 'aphront/response/400',
     'Aphront403Response' => 'aphront/response/403',
     'Aphront404Response' => 'aphront/response/404',
     'AphrontAjaxResponse' => 'aphront/response/ajax',
     'AphrontApplicationConfiguration' => 'aphront/applicationconfiguration',
     'AphrontAttachedFileView' => 'view/control/attachedfile',
     'AphrontCSRFException' => 'aphront/exception/csrf',
     'AphrontCalendarMonthView' => 'applications/calendar/view/month',
     'AphrontContextBarView' => 'view/layout/contextbar',
     'AphrontController' => 'aphront/controller',
     'AphrontCrumbsView' => 'view/layout/crumbs',
     'AphrontDatabaseConnection' => 'storage/connection/base',
     'AphrontDatabaseTransactionState' => 'storage/transaction',
     'AphrontDefaultApplicationConfiguration' => 'aphront/default/configuration',
     'AphrontDialogResponse' => 'aphront/response/dialog',
     'AphrontDialogView' => 'view/dialog',
     'AphrontErrorView' => 'view/form/error',
     'AphrontException' => 'aphront/exception/base',
     'AphrontFilePreviewView' => 'view/layout/filepreview',
     'AphrontFileResponse' => 'aphront/response/file',
     'AphrontFormCheckboxControl' => 'view/form/control/checkbox',
     'AphrontFormControl' => 'view/form/control/base',
     'AphrontFormDateControl' => 'view/form/control/date',
     'AphrontFormDividerControl' => 'view/form/control/divider',
     'AphrontFormDragAndDropUploadControl' => 'view/form/control/draganddropupload',
     'AphrontFormFileControl' => 'view/form/control/file',
     'AphrontFormInsetView' => 'view/form/inset',
     'AphrontFormLayoutView' => 'view/form/layout',
     'AphrontFormMarkupControl' => 'view/form/control/markup',
     'AphrontFormPasswordControl' => 'view/form/control/password',
     'AphrontFormPolicyControl' => 'view/form/control/policy',
     'AphrontFormRadioButtonControl' => 'view/form/control/radio',
     'AphrontFormRecaptchaControl' => 'view/form/control/recaptcha',
     'AphrontFormSelectControl' => 'view/form/control/select',
     'AphrontFormStaticControl' => 'view/form/control/static',
     'AphrontFormSubmitControl' => 'view/form/control/submit',
     'AphrontFormTextAreaControl' => 'view/form/control/textarea',
     'AphrontFormTextControl' => 'view/form/control/text',
     'AphrontFormToggleButtonsControl' => 'view/form/control/togglebuttons',
     'AphrontFormTokenizerControl' => 'view/form/control/tokenizer',
     'AphrontFormView' => 'view/form/base',
     'AphrontHTTPSink' => 'aphront/sink/base',
     'AphrontHTTPSinkTestCase' => 'aphront/sink/base/__tests__',
     'AphrontHeadsupActionListView' => 'view/layout/headsup/actionlist',
     'AphrontHeadsupActionView' => 'view/layout/headsup/action',
     'AphrontHeadsupView' => 'view/layout/headsup/panel',
     'AphrontIDPagerView' => 'view/control/idpager',
     'AphrontIsolatedDatabaseConnection' => 'storage/connection/isolated',
     'AphrontIsolatedDatabaseConnectionTestCase' => 'storage/connection/isolated/__tests__',
     'AphrontIsolatedHTTPSink' => 'aphront/sink/test',
     'AphrontJSONResponse' => 'aphront/response/json',
     'AphrontJavelinView' => 'view/javelin-view',
     'AphrontKeyboardShortcutsAvailableView' => 'view/widget/keyboardshortcuts',
     'AphrontListFilterView' => 'view/layout/listfilter',
     'AphrontMiniPanelView' => 'view/layout/minipanel',
     'AphrontMySQLDatabaseConnection' => 'storage/connection/mysql/mysql',
     'AphrontMySQLDatabaseConnectionBase' => 'storage/connection/mysql/base',
     'AphrontMySQLDatabaseConnectionTestCase' => 'storage/connection/mysql/__tests__',
     'AphrontMySQLiDatabaseConnection' => 'storage/connection/mysql/mysqli',
     'AphrontNullView' => 'view/null',
     'AphrontPHPHTTPSink' => 'aphront/sink/php',
     'AphrontPageView' => 'view/page/base',
     'AphrontPagerView' => 'view/control/pager',
     'AphrontPanelView' => 'view/layout/panel',
     'AphrontPlainTextResponse' => 'aphront/response/plaintext',
     'AphrontProxyResponse' => 'aphront/response/proxy',
     'AphrontQueryAccessDeniedException' => 'storage/exception/accessdenied',
     'AphrontQueryConnectionException' => 'storage/exception/connection',
     'AphrontQueryConnectionLostException' => 'storage/exception/connectionlost',
     'AphrontQueryCountException' => 'storage/exception/count',
     'AphrontQueryDuplicateKeyException' => 'storage/exception/duplicatekey',
     'AphrontQueryException' => 'storage/exception/base',
     'AphrontQueryObjectMissingException' => 'storage/exception/objectmissing',
     'AphrontQueryParameterException' => 'storage/exception/parameter',
     'AphrontQueryRecoverableException' => 'storage/exception/recoverable',
     'AphrontQuerySchemaException' => 'storage/exception/schema',
     'AphrontRedirectException' => 'aphront/exception/redirect',
     'AphrontRedirectResponse' => 'aphront/response/redirect',
     'AphrontReloadResponse' => 'aphront/response/reload',
     'AphrontRequest' => 'aphront/request',
     'AphrontRequestFailureView' => 'view/page/failure',
     'AphrontRequestTestCase' => 'aphront/request/__tests__',
     'AphrontResponse' => 'aphront/response/base',
     'AphrontScopedUnguardedWriteCapability' => 'aphront/writeguard/scopeguard',
     'AphrontSideNavFilterView' => 'view/layout/sidenavfilter',
     'AphrontSideNavView' => 'view/layout/sidenav',
     'AphrontTableView' => 'view/control/table',
     'AphrontTokenizerTemplateView' => 'view/control/tokenizer',
     'AphrontTypeaheadTemplateView' => 'view/control/typeahead',
     'AphrontURIMapper' => 'aphront/mapper',
     'AphrontUsageException' => 'aphront/exception/usage',
     'AphrontView' => 'view/base',
     'AphrontWebpageResponse' => 'aphront/response/webpage',
     'AphrontWriteGuard' => 'aphront/writeguard',
     'CelerityAPI' => 'infrastructure/celerity/api',
     'CelerityResourceController' => 'infrastructure/celerity/controller',
     'CelerityResourceGraph' => 'infrastructure/celerity/graph',
     'CelerityResourceMap' => 'infrastructure/celerity/map',
     'CelerityResourceTransformer' => 'infrastructure/celerity/transformer',
     'CelerityResourceTransformerTestCase' => 'infrastructure/celerity/transformer/__tests__',
     'CelerityStaticResourceResponse' => 'infrastructure/celerity/response',
     'ConduitAPIMethod' => 'applications/conduit/method/base',
     'ConduitAPIRequest' => 'applications/conduit/protocol/request',
     'ConduitAPIResponse' => 'applications/conduit/protocol/response',
     'ConduitAPI_arcanist_Method' => 'applications/conduit/method/arcanist/base',
     'ConduitAPI_arcanist_projectinfo_Method' => 'applications/conduit/method/arcanist/projectinfo',
     'ConduitAPI_audit_Method' => 'applications/conduit/method/audit/base',
     'ConduitAPI_audit_query_Method' => 'applications/conduit/method/audit/query',
     'ConduitAPI_chatlog_Method' => 'applications/conduit/method/chatlog/base',
     'ConduitAPI_chatlog_query_Method' => 'applications/conduit/method/chatlog/query',
     'ConduitAPI_chatlog_record_Method' => 'applications/conduit/method/chatlog/record',
     'ConduitAPI_conduit_connect_Method' => 'applications/conduit/method/conduit/connect',
     'ConduitAPI_conduit_getcertificate_Method' => 'applications/conduit/method/conduit/getcertificate',
     'ConduitAPI_conduit_ping_Method' => 'applications/conduit/method/conduit/ping',
     'ConduitAPI_daemon_launched_Method' => 'applications/conduit/method/daemon/launched',
     'ConduitAPI_daemon_log_Method' => 'applications/conduit/method/daemon/log',
     'ConduitAPI_differential_close_Method' => 'applications/conduit/method/differential/close',
     'ConduitAPI_differential_createcomment_Method' => 'applications/conduit/method/differential/createcomment',
     'ConduitAPI_differential_creatediff_Method' => 'applications/conduit/method/differential/creatediff',
     'ConduitAPI_differential_createrevision_Method' => 'applications/conduit/method/differential/createrevision',
     'ConduitAPI_differential_find_Method' => 'applications/conduit/method/differential/find',
     'ConduitAPI_differential_getalldiffs_Method' => 'applications/conduit/method/differential/getalldiffs',
     'ConduitAPI_differential_getcommitmessage_Method' => 'applications/conduit/method/differential/getcommitmessage',
     'ConduitAPI_differential_getcommitpaths_Method' => 'applications/conduit/method/differential/getcommitpaths',
     'ConduitAPI_differential_getdiff_Method' => 'applications/conduit/method/differential/getdiff',
     'ConduitAPI_differential_getrevision_Method' => 'applications/conduit/method/differential/getrevision',
     'ConduitAPI_differential_getrevisioncomments_Method' => 'applications/conduit/method/differential/getrevisioncomments',
     'ConduitAPI_differential_getrevisionfeedback_Method' => 'applications/conduit/method/differential/getrevisionfeedback',
     'ConduitAPI_differential_markcommitted_Method' => 'applications/conduit/method/differential/markcommitted',
     'ConduitAPI_differential_parsecommitmessage_Method' => 'applications/conduit/method/differential/parsecommitmessage',
     'ConduitAPI_differential_query_Method' => 'applications/conduit/method/differential/query',
     'ConduitAPI_differential_setdiffproperty_Method' => 'applications/conduit/method/differential/setdiffproperty',
     'ConduitAPI_differential_updaterevision_Method' => 'applications/conduit/method/differential/updaterevision',
     'ConduitAPI_differential_updatetaskrevisionassoc_Method' => 'applications/conduit/method/differential/updatetaskrevisionassoc',
     'ConduitAPI_differential_updateunitresults_Method' => 'applications/conduit/method/differential/updateunitresults',
     'ConduitAPI_diffusion_findsymbols_Method' => 'applications/conduit/method/diffusion/findsymbols',
     'ConduitAPI_diffusion_getcommits_Method' => 'applications/conduit/method/diffusion/getcommits',
     'ConduitAPI_diffusion_getrecentcommitsbypath_Method' => 'applications/conduit/method/diffusion/getrecentcommitsbypath',
     'ConduitAPI_feed_publish_Method' => 'applications/conduit/method/feed/publish',
     'ConduitAPI_feed_query_Method' => 'applications/conduit/method/feed/query',
     'ConduitAPI_file_download_Method' => 'applications/conduit/method/file/download',
     'ConduitAPI_file_info_Method' => 'applications/conduit/method/file/info',
     'ConduitAPI_file_upload_Method' => 'applications/conduit/method/file/upload',
     'ConduitAPI_flag_Method' => 'applications/conduit/method/flag/base',
     'ConduitAPI_flag_query_Method' => 'applications/conduit/method/flag/query',
     'ConduitAPI_macro_Method' => 'applications/conduit/method/macro/base',
     'ConduitAPI_macro_query_Method' => 'applications/conduit/method/macro/query',
     'ConduitAPI_maniphest_Method' => 'applications/conduit/method/maniphest/base',
     'ConduitAPI_maniphest_createtask_Method' => 'applications/conduit/method/maniphest/createtask',
     'ConduitAPI_maniphest_find_Method' => 'applications/conduit/method/maniphest/find',
     'ConduitAPI_maniphest_gettasktransactions_Method' => 'applications/conduit/method/maniphest/gettasktransactions',
     'ConduitAPI_maniphest_info_Method' => 'applications/conduit/method/maniphest/info',
     'ConduitAPI_maniphest_update_Method' => 'applications/conduit/method/maniphest/update',
     'ConduitAPI_paste_Method' => 'applications/conduit/method/paste/base',
     'ConduitAPI_paste_create_Method' => 'applications/conduit/method/paste/create',
     'ConduitAPI_paste_info_Method' => 'applications/conduit/method/paste/info',
     'ConduitAPI_path_getowners_Method' => 'applications/conduit/method/path/getowners',
     'ConduitAPI_phid_Method' => 'applications/conduit/method/phid/base',
     'ConduitAPI_phid_info_Method' => 'applications/conduit/method/phid/info',
     'ConduitAPI_phid_query_Method' => 'applications/conduit/method/phid/query',
     'ConduitAPI_phriction_Method' => 'applications/conduit/method/phriction/base',
     'ConduitAPI_phriction_edit_Method' => 'applications/conduit/method/phriction/edit',
     'ConduitAPI_phriction_history_Method' => 'applications/conduit/method/phriction/history',
     'ConduitAPI_phriction_info_Method' => 'applications/conduit/method/phriction/info',
     'ConduitAPI_project_Method' => 'applications/conduit/method/project/base',
     'ConduitAPI_project_query_Method' => 'applications/conduit/method/project/query',
     'ConduitAPI_remarkup_process_Method' => 'applications/conduit/method/remarkup/process',
     'ConduitAPI_slowvote_info_Method' => 'applications/conduit/method/slowvote/info',
     'ConduitAPI_user_Method' => 'applications/conduit/method/user/base',
     'ConduitAPI_user_find_Method' => 'applications/conduit/method/user/find',
     'ConduitAPI_user_info_Method' => 'applications/conduit/method/user/info',
     'ConduitAPI_user_whoami_Method' => 'applications/conduit/method/user/whoami',
     'ConduitException' => 'applications/conduit/protocol/exception',
     'DarkConsoleConfigPlugin' => 'aphront/console/plugin/config',
     'DarkConsoleController' => 'aphront/console/controller',
     'DarkConsoleCore' => 'aphront/console/core',
     'DarkConsoleErrorLogPlugin' => 'aphront/console/plugin/errorlog',
     'DarkConsoleErrorLogPluginAPI' => 'aphront/console/plugin/errorlog/api',
     'DarkConsoleEventPlugin' => 'aphront/console/plugin/event',
     'DarkConsoleEventPluginAPI' => 'aphront/console/plugin/event/api',
     'DarkConsolePlugin' => 'aphront/console/plugin/base',
     'DarkConsoleRequestPlugin' => 'aphront/console/plugin/request',
     'DarkConsoleServicesPlugin' => 'aphront/console/plugin/services',
     'DarkConsoleXHProfPlugin' => 'aphront/console/plugin/xhprof',
     'DarkConsoleXHProfPluginAPI' => 'aphront/console/plugin/xhprof/api',
     'DatabaseConfigurationProvider' => 'applications/base/storage/configuration/base',
     'DefaultDatabaseConfigurationProvider' => 'applications/base/storage/configuration/default',
     'DifferentialAction' => 'applications/differential/constants/action',
     'DifferentialActionHasNoEffectException' => 'applications/differential/exception/noeffect',
     'DifferentialAddCommentView' => 'applications/differential/view/addcomment',
     'DifferentialAffectedPath' => 'applications/differential/storage/affectedpath',
     'DifferentialApplyPatchFieldSpecification' => 'applications/differential/field/specification/applypatch',
     'DifferentialArcanistProjectFieldSpecification' => 'applications/differential/field/specification/arcanistproject',
     'DifferentialAuditorsFieldSpecification' => 'applications/differential/field/specification/auditors',
     'DifferentialAuthorFieldSpecification' => 'applications/differential/field/specification/author',
     'DifferentialAuxiliaryField' => 'applications/differential/storage/auxiliaryfield',
     'DifferentialBlameRevisionFieldSpecification' => 'applications/differential/field/specification/blamerev',
     'DifferentialBranchFieldSpecification' => 'applications/differential/field/specification/branch',
     'DifferentialCCWelcomeMail' => 'applications/differential/mail/ccwelcome',
     'DifferentialCCsFieldSpecification' => 'applications/differential/field/specification/ccs',
     'DifferentialChangeType' => 'applications/differential/constants/changetype',
     'DifferentialChangeset' => 'applications/differential/storage/changeset',
     'DifferentialChangesetDetailView' => 'applications/differential/view/changesetdetailview',
     'DifferentialChangesetListView' => 'applications/differential/view/changesetlistview',
     'DifferentialChangesetParser' => 'applications/differential/parser/changeset',
     'DifferentialChangesetViewController' => 'applications/differential/controller/changesetview',
     'DifferentialComment' => 'applications/differential/storage/comment',
     'DifferentialCommentEditor' => 'applications/differential/editor/comment',
     'DifferentialCommentMail' => 'applications/differential/mail/comment',
     'DifferentialCommentPreviewController' => 'applications/differential/controller/commentpreview',
     'DifferentialCommentSaveController' => 'applications/differential/controller/commentsave',
     'DifferentialCommitsFieldSpecification' => 'applications/differential/field/specification/commits',
     'DifferentialController' => 'applications/differential/controller/base',
     'DifferentialDAO' => 'applications/differential/storage/base',
     'DifferentialDateCreatedFieldSpecification' => 'applications/differential/field/specification/datecreated',
     'DifferentialDateModifiedFieldSpecification' => 'applications/differential/field/specification/datemodified',
     'DifferentialDefaultFieldSelector' => 'applications/differential/field/selector/default',
     'DifferentialDependenciesFieldSpecification' => 'applications/differential/field/specification/dependencies',
     'DifferentialDiff' => 'applications/differential/storage/diff',
     'DifferentialDiffContentMail' => 'applications/differential/mail/diffcontent',
     'DifferentialDiffCreateController' => 'applications/differential/controller/diffcreate',
     'DifferentialDiffProperty' => 'applications/differential/storage/diffproperty',
     'DifferentialDiffTableOfContentsView' => 'applications/differential/view/difftableofcontents',
     'DifferentialDiffViewController' => 'applications/differential/controller/diffview',
     'DifferentialException' => 'applications/differential/exception/base',
     'DifferentialExceptionMail' => 'applications/differential/mail/exception',
     'DifferentialExportPatchFieldSpecification' => 'applications/differential/field/specification/exportpatch',
     'DifferentialFieldDataNotAvailableException' => 'applications/differential/field/exception/notavailable',
     'DifferentialFieldParseException' => 'applications/differential/field/exception/parse',
     'DifferentialFieldSelector' => 'applications/differential/field/selector/base',
     'DifferentialFieldSpecification' => 'applications/differential/field/specification/base',
     'DifferentialFieldSpecificationIncompleteException' => 'applications/differential/field/exception/incomplete',
     'DifferentialFieldValidationException' => 'applications/differential/field/exception/validation',
     'DifferentialGitSVNIDFieldSpecification' => 'applications/differential/field/specification/gitsvnid',
     'DifferentialHostFieldSpecification' => 'applications/differential/field/specification/host',
     'DifferentialHunk' => 'applications/differential/storage/hunk',
     'DifferentialInlineComment' => 'applications/differential/storage/inlinecomment',
     'DifferentialInlineCommentEditController' => 'applications/differential/controller/inlinecommentedit',
     'DifferentialInlineCommentEditView' => 'applications/differential/view/inlinecommentedit',
     'DifferentialInlineCommentPreviewController' => 'applications/differential/controller/inlinecommentpreview',
     'DifferentialInlineCommentView' => 'applications/differential/view/inlinecomment',
     'DifferentialLinesFieldSpecification' => 'applications/differential/field/specification/lines',
     'DifferentialLintFieldSpecification' => 'applications/differential/field/specification/lint',
     'DifferentialLintStatus' => 'applications/differential/constants/lintstatus',
     'DifferentialLocalCommitsView' => 'applications/differential/view/localcommits',
     'DifferentialMail' => 'applications/differential/mail/base',
     'DifferentialManiphestTasksFieldSpecification' => 'applications/differential/field/specification/maniphesttasks',
     'DifferentialNewDiffMail' => 'applications/differential/mail/newdiff',
     'DifferentialPathFieldSpecification' => 'applications/differential/field/specification/path',
     'DifferentialPrimaryPaneView' => 'applications/differential/view/primarypane',
     'DifferentialReplyHandler' => 'applications/differential/replyhandler',
     'DifferentialRevertPlanFieldSpecification' => 'applications/differential/field/specification/revertplan',
     'DifferentialReviewRequestMail' => 'applications/differential/mail/reviewrequest',
     'DifferentialReviewedByFieldSpecification' => 'applications/differential/field/specification/reviewedby',
     'DifferentialReviewersFieldSpecification' => 'applications/differential/field/specification/reviewers',
     'DifferentialRevision' => 'applications/differential/storage/revision',
     'DifferentialRevisionCommentListView' => 'applications/differential/view/revisioncommentlist',
     'DifferentialRevisionCommentView' => 'applications/differential/view/revisioncomment',
     'DifferentialRevisionControlSystem' => 'applications/differential/constants/revisioncontrolsystem',
     'DifferentialRevisionDetailRenderer' => 'applications/differential/controller/customrenderer',
     'DifferentialRevisionDetailView' => 'applications/differential/view/revisiondetail',
     'DifferentialRevisionEditController' => 'applications/differential/controller/revisionedit',
     'DifferentialRevisionEditor' => 'applications/differential/editor/revision',
     'DifferentialRevisionIDFieldParserTestCase' => 'applications/differential/field/specification/revisionid/__tests__',
     'DifferentialRevisionIDFieldSpecification' => 'applications/differential/field/specification/revisionid',
     'DifferentialRevisionListController' => 'applications/differential/controller/revisionlist',
     'DifferentialRevisionListData' => 'applications/differential/data/revisionlist',
     'DifferentialRevisionListView' => 'applications/differential/view/revisionlist',
     'DifferentialRevisionQuery' => 'applications/differential/query/revision',
     'DifferentialRevisionStatsController' => 'applications/differential/controller/revisionstats',
     'DifferentialRevisionStatsView' => 'applications/differential/view/revisionstats',
     'DifferentialRevisionStatusFieldSpecification' => 'applications/differential/field/specification/revisionstatus',
     'DifferentialRevisionUpdateHistoryView' => 'applications/differential/view/revisionupdatehistory',
     'DifferentialRevisionViewController' => 'applications/differential/controller/revisionview',
     'DifferentialSubscribeController' => 'applications/differential/controller/subscribe',
     'DifferentialSummaryFieldSpecification' => 'applications/differential/field/specification/summary',
     'DifferentialTasksAttacher' => 'applications/differential/tasks',
     'DifferentialTestPlanFieldSpecification' => 'applications/differential/field/specification/testplan',
     'DifferentialTitleFieldSpecification' => 'applications/differential/field/specification/title',
     'DifferentialUnitFieldSpecification' => 'applications/differential/field/specification/unit',
     'DifferentialUnitStatus' => 'applications/differential/constants/unitstatus',
     'DifferentialUnitTestResult' => 'applications/differential/constants/unittestresult',
     'DiffusionBranchInformation' => 'applications/diffusion/data/branch',
     'DiffusionBranchQuery' => 'applications/diffusion/query/branch/base',
     'DiffusionBranchTableView' => 'applications/diffusion/view/branchtable',
     'DiffusionBrowseController' => 'applications/diffusion/controller/browse',
     'DiffusionBrowseFileController' => 'applications/diffusion/controller/file',
     'DiffusionBrowseQuery' => 'applications/diffusion/query/browse/base',
     'DiffusionBrowseTableView' => 'applications/diffusion/view/browsetable',
     'DiffusionChangeController' => 'applications/diffusion/controller/change',
     'DiffusionCommentListView' => 'applications/diffusion/view/commentlist',
     'DiffusionCommentView' => 'applications/diffusion/view/comment',
     'DiffusionCommitChangeTableView' => 'applications/diffusion/view/commitchangetable',
     'DiffusionCommitController' => 'applications/diffusion/controller/commit',
     'DiffusionCommitParentsQuery' => 'applications/diffusion/query/parents/base',
     'DiffusionCommitTagsQuery' => 'applications/diffusion/query/committags/base',
     'DiffusionContainsQuery' => 'applications/diffusion/query/contains/base',
     'DiffusionController' => 'applications/diffusion/controller/base',
     'DiffusionDiffController' => 'applications/diffusion/controller/diff',
     'DiffusionDiffQuery' => 'applications/diffusion/query/diff/base',
     'DiffusionEmptyResultView' => 'applications/diffusion/view/emptyresult',
     'DiffusionExternalController' => 'applications/diffusion/controller/external',
     'DiffusionFileContent' => 'applications/diffusion/data/filecontent',
     'DiffusionFileContentQuery' => 'applications/diffusion/query/filecontent/base',
     'DiffusionGitBranchQuery' => 'applications/diffusion/query/branch/git',
     'DiffusionGitBranchQueryTestCase' => 'applications/diffusion/query/branch/git/__tests__',
     'DiffusionGitBrowseQuery' => 'applications/diffusion/query/browse/git',
     'DiffusionGitCommitParentsQuery' => 'applications/diffusion/query/parents/git',
     'DiffusionGitCommitTagsQuery' => 'applications/diffusion/query/committags/git',
     'DiffusionGitContainsQuery' => 'applications/diffusion/query/contains/git',
     'DiffusionGitDiffQuery' => 'applications/diffusion/query/diff/git',
     'DiffusionGitFileContentQuery' => 'applications/diffusion/query/filecontent/git',
     'DiffusionGitHistoryQuery' => 'applications/diffusion/query/history/git',
     'DiffusionGitLastModifiedQuery' => 'applications/diffusion/query/lastmodified/git',
     'DiffusionGitMergedCommitsQuery' => 'applications/diffusion/query/mergedcommits/git',
     'DiffusionGitRenameHistoryQuery' => 'applications/diffusion/query/renamehistory/git',
     'DiffusionGitRequest' => 'applications/diffusion/request/git',
     'DiffusionGitTagListQuery' => 'applications/diffusion/query/taglist/git',
     'DiffusionHistoryController' => 'applications/diffusion/controller/history',
     'DiffusionHistoryQuery' => 'applications/diffusion/query/history/base',
     'DiffusionHistoryTableView' => 'applications/diffusion/view/historytable',
     'DiffusionHomeController' => 'applications/diffusion/controller/home',
     'DiffusionInlineCommentController' => 'applications/diffusion/controller/inline',
     'DiffusionLastModifiedController' => 'applications/diffusion/controller/lastmodified',
     'DiffusionLastModifiedQuery' => 'applications/diffusion/query/lastmodified/base',
     'DiffusionMercurialBranchQuery' => 'applications/diffusion/query/branch/mercurial',
     'DiffusionMercurialBrowseQuery' => 'applications/diffusion/query/browse/mercurial',
     'DiffusionMercurialCommitParentsQuery' => 'applications/diffusion/query/parents/mercurial',
     'DiffusionMercurialCommitTagsQuery' => 'applications/diffusion/query/committags/mercurial',
     'DiffusionMercurialContainsQuery' => 'applications/diffusion/query/contains/mercurial',
     'DiffusionMercurialDiffQuery' => 'applications/diffusion/query/diff/mercurial',
     'DiffusionMercurialFileContentQuery' => 'applications/diffusion/query/filecontent/mercurial',
     'DiffusionMercurialHistoryQuery' => 'applications/diffusion/query/history/mercurial',
     'DiffusionMercurialLastModifiedQuery' => 'applications/diffusion/query/lastmodified/mercurial',
     'DiffusionMercurialMergedCommitsQuery' => 'applications/diffusion/query/mergedcommits/mercurial',
     'DiffusionMercurialRenameHistoryQuery' => 'applications/diffusion/query/renamehistory/mercurial',
     'DiffusionMercurialRequest' => 'applications/diffusion/request/mercurial',
     'DiffusionMercurialTagListQuery' => 'applications/diffusion/query/taglist/mercurial',
     'DiffusionMergedCommitsQuery' => 'applications/diffusion/query/mergedcommits/base',
     'DiffusionPathChange' => 'applications/diffusion/data/pathchange',
     'DiffusionPathChangeQuery' => 'applications/diffusion/query/pathchange/base',
     'DiffusionPathCompleteController' => 'applications/diffusion/controller/pathcomplete',
     'DiffusionPathIDQuery' => 'applications/diffusion/query/pathid/base',
     'DiffusionPathQuery' => 'applications/diffusion/query/path',
     'DiffusionPathQueryTestCase' => 'applications/diffusion/query/pathid/base/__tests__',
     'DiffusionPathValidateController' => 'applications/diffusion/controller/pathvalidate',
     'DiffusionQuery' => 'applications/diffusion/query/base',
     'DiffusionRenameHistoryQuery' => 'applications/diffusion/query/renamehistory/base',
     'DiffusionRepositoryController' => 'applications/diffusion/controller/repository',
     'DiffusionRepositoryPath' => 'applications/diffusion/data/repositorypath',
     'DiffusionRepositoryTag' => 'applications/diffusion/tag',
     'DiffusionRequest' => 'applications/diffusion/request/base',
     'DiffusionSvnBrowseQuery' => 'applications/diffusion/query/browse/svn',
     'DiffusionSvnCommitParentsQuery' => 'applications/diffusion/query/parents/svn',
     'DiffusionSvnCommitTagsQuery' => 'applications/diffusion/query/committags/svn',
     'DiffusionSvnContainsQuery' => 'applications/diffusion/query/contains/svn',
     'DiffusionSvnDiffQuery' => 'applications/diffusion/query/diff/svn',
     'DiffusionSvnFileContentQuery' => 'applications/diffusion/query/filecontent/svn',
     'DiffusionSvnHistoryQuery' => 'applications/diffusion/query/history/svn',
     'DiffusionSvnLastModifiedQuery' => 'applications/diffusion/query/lastmodified/svn',
     'DiffusionSvnMergedCommitsQuery' => 'applications/diffusion/query/mergedcommits/svn',
     'DiffusionSvnRenameHistoryQuery' => 'applications/diffusion/query/renamehistory/svn',
     'DiffusionSvnRequest' => 'applications/diffusion/request/svn',
     'DiffusionSvnTagListQuery' => 'applications/diffusion/query/taglist/svn',
     'DiffusionSymbolController' => 'applications/diffusion/controller/symbol',
     'DiffusionSymbolQuery' => 'applications/diffusion/query/symbol',
     'DiffusionTagListController' => 'applications/diffusion/controller/taglist',
     'DiffusionTagListQuery' => 'applications/diffusion/query/taglist/base',
     'DiffusionTagListView' => 'applications/diffusion/view/taglist',
     'DiffusionURITestCase' => 'applications/diffusion/request/base/__tests__',
     'DiffusionView' => 'applications/diffusion/view/base',
     'DrydockAllocator' => 'applications/drydock/allocator/resource',
     'DrydockAllocatorWorker' => 'applications/drydock/allocator/worker',
     'DrydockApacheWebrootBlueprint' => 'applications/drydock/blueprint/webroot/apache',
     'DrydockApacheWebrootInterface' => 'applications/drydock/interface/webroot/apache',
     'DrydockBlueprint' => 'applications/drydock/blueprint/base',
     'DrydockCommandInterface' => 'applications/drydock/interface/command/base',
     'DrydockConstants' => 'applications/drydock/constants/base',
     'DrydockController' => 'applications/drydock/controller/base',
     'DrydockDAO' => 'applications/drydock/storage/base',
     'DrydockEC2HostBlueprint' => 'applications/drydock/blueprint/ec2host',
     'DrydockInterface' => 'applications/drydock/interface/base',
     'DrydockLease' => 'applications/drydock/storage/lease',
     'DrydockLeaseListController' => 'applications/drydock/controller/leaselist',
     'DrydockLeaseStatus' => 'applications/drydock/constants/leasestatus',
     'DrydockLocalCommandInterface' => 'applications/drydock/interface/command/local',
     'DrydockLocalHostBlueprint' => 'applications/drydock/blueprint/localhost',
     'DrydockLog' => 'applications/drydock/storage/log',
     'DrydockLogController' => 'applications/drydock/controller/log',
     'DrydockLogQuery' => 'applications/drydock/query/log',
     'DrydockPhabricatorApplicationBlueprint' => 'applications/drydock/blueprint/application/phabricator',
     'DrydockRemoteHostBlueprint' => 'applications/drydock/blueprint/remotehost',
     'DrydockResource' => 'applications/drydock/storage/resource',
     'DrydockResourceAllocateController' => 'applications/drydock/controller/resourceallocate',
     'DrydockResourceListController' => 'applications/drydock/controller/resourcelist',
     'DrydockResourceStatus' => 'applications/drydock/constants/resourcestatus',
     'DrydockSSHCommandInterface' => 'applications/drydock/interface/command/ssh',
     'DrydockWebrootInterface' => 'applications/drydock/interface/webroot/base',
     'HeraldAction' => 'applications/herald/storage/action',
     'HeraldActionConfig' => 'applications/herald/config/action',
     'HeraldApplyTranscript' => 'applications/herald/storage/transcript/apply',
     'HeraldCommitAdapter' => 'applications/herald/adapter/commit',
     'HeraldCondition' => 'applications/herald/storage/condition',
     'HeraldConditionConfig' => 'applications/herald/config/condition',
     'HeraldConditionTranscript' => 'applications/herald/storage/transcript/condition',
     'HeraldContentTypeConfig' => 'applications/herald/config/contenttype',
     'HeraldController' => 'applications/herald/controller/base',
     'HeraldDAO' => 'applications/herald/storage/base',
     'HeraldDeleteController' => 'applications/herald/controller/delete',
     'HeraldDifferentialRevisionAdapter' => 'applications/herald/adapter/differential',
     'HeraldDryRunAdapter' => 'applications/herald/adapter/dryrun',
     'HeraldEditLogQuery' => 'applications/herald/query/log',
     'HeraldEffect' => 'applications/herald/engine/effect',
     'HeraldEngine' => 'applications/herald/engine/engine',
     'HeraldFieldConfig' => 'applications/herald/config/field',
     'HeraldHomeController' => 'applications/herald/controller/home',
     'HeraldInvalidConditionException' => 'applications/herald/engine/engine/exception',
     'HeraldInvalidFieldException' => 'applications/herald/engine/engine/exception',
     'HeraldNewController' => 'applications/herald/controller/new',
     'HeraldObjectAdapter' => 'applications/herald/adapter/base',
     'HeraldObjectTranscript' => 'applications/herald/storage/transcript/object',
     'HeraldRecursiveConditionsException' => 'applications/herald/engine/engine/exception',
     'HeraldRepetitionPolicyConfig' => 'applications/herald/config/repetitionpolicy',
     'HeraldRule' => 'applications/herald/storage/rule',
     'HeraldRuleController' => 'applications/herald/controller/rule',
     'HeraldRuleEdit' => 'applications/herald/storage/edithistory',
     'HeraldRuleEditHistoryController' => 'applications/herald/controller/edithistory',
     'HeraldRuleEditHistoryView' => 'applications/herald/view/edithistory',
     'HeraldRuleListView' => 'applications/herald/view/rulelist',
     'HeraldRuleQuery' => 'applications/herald/query/rule',
     'HeraldRuleTranscript' => 'applications/herald/storage/transcript/rule',
     'HeraldRuleTypeConfig' => 'applications/herald/config/ruletype',
     'HeraldTestConsoleController' => 'applications/herald/controller/test',
     'HeraldTranscript' => 'applications/herald/storage/transcript/base',
     'HeraldTranscriptController' => 'applications/herald/controller/transcript',
     'HeraldTranscriptListController' => 'applications/herald/controller/transcriptlist',
     'HeraldValueTypeConfig' => 'applications/herald/config/valuetype',
     'Javelin' => 'infrastructure/javelin/api',
     'JavelinReactorExample' => 'applications/uiexample/examples/reactor',
     'JavelinViewExample' => 'applications/uiexample/examples/client',
     'JavelinViewExampleServerView' => 'applications/uiexample/examples/client',
     'LiskDAO' => 'storage/lisk/dao',
     'LiskEphemeralObjectException' => 'storage/lisk/dao',
     'LiskIsolationTestCase' => 'storage/lisk/dao/__tests__',
     'LiskIsolationTestDAO' => 'storage/lisk/dao/__tests__',
     'LiskIsolationTestDAOException' => 'storage/lisk/dao/__tests__',
     'ManiphestAction' => 'applications/maniphest/constants/action',
     'ManiphestAuxiliaryFieldDefaultSpecification' => 'applications/maniphest/auxiliaryfield/default',
     'ManiphestAuxiliaryFieldSpecification' => 'applications/maniphest/auxiliaryfield/base',
     'ManiphestAuxiliaryFieldTypeException' => 'applications/maniphest/auxiliaryfield/typeexception',
     'ManiphestAuxiliaryFieldValidationException' => 'applications/maniphest/auxiliaryfield/validationexception',
     'ManiphestBatchEditController' => 'applications/maniphest/controller/batch',
     'ManiphestConstants' => 'applications/maniphest/constants/base',
     'ManiphestController' => 'applications/maniphest/controller/base',
     'ManiphestDAO' => 'applications/maniphest/storage/base',
     'ManiphestDefaultTaskExtensions' => 'applications/maniphest/extensions/task',
     'ManiphestExportController' => 'applications/maniphest/controller/export',
     'ManiphestReplyHandler' => 'applications/maniphest/replyhandler',
     'ManiphestReportController' => 'applications/maniphest/controller/report',
     'ManiphestSavedQuery' => 'applications/maniphest/storage/savedquery',
     'ManiphestSavedQueryDeleteController' => 'applications/maniphest/controller/savedquerydelete',
     'ManiphestSavedQueryEditController' => 'applications/maniphest/controller/savedqueryedit',
     'ManiphestSavedQueryListController' => 'applications/maniphest/controller/savedquerylist',
     'ManiphestSubpriorityController' => 'applications/maniphest/controller/subpriority',
     'ManiphestTask' => 'applications/maniphest/storage/task',
     'ManiphestTaskAuxiliaryStorage' => 'applications/maniphest/storage/auxiliary',
     'ManiphestTaskDescriptionChangeController' => 'applications/maniphest/controller/descriptionchange',
     'ManiphestTaskDescriptionPreviewController' => 'applications/maniphest/controller/descriptionpreview',
     'ManiphestTaskDetailController' => 'applications/maniphest/controller/taskdetail',
     'ManiphestTaskEditController' => 'applications/maniphest/controller/taskedit',
     'ManiphestTaskExtensions' => 'applications/maniphest/extensions/base',
     'ManiphestTaskListController' => 'applications/maniphest/controller/tasklist',
     'ManiphestTaskListView' => 'applications/maniphest/view/tasklist',
     'ManiphestTaskOwner' => 'applications/maniphest/constants/owner',
     'ManiphestTaskPriority' => 'applications/maniphest/constants/priority',
     'ManiphestTaskProject' => 'applications/maniphest/storage/taskproject',
     'ManiphestTaskProjectsView' => 'applications/maniphest/view/taskprojects',
     'ManiphestTaskQuery' => 'applications/maniphest/query',
     'ManiphestTaskStatus' => 'applications/maniphest/constants/status',
     'ManiphestTaskSubscriber' => 'applications/maniphest/storage/subscriber',
     'ManiphestTaskSummaryView' => 'applications/maniphest/view/tasksummary',
     'ManiphestTransaction' => 'applications/maniphest/storage/transaction',
     'ManiphestTransactionDetailView' => 'applications/maniphest/view/transactiondetail',
     'ManiphestTransactionEditor' => 'applications/maniphest/editor/transaction',
     'ManiphestTransactionListView' => 'applications/maniphest/view/transactionlist',
     'ManiphestTransactionPreviewController' => 'applications/maniphest/controller/transactionpreview',
     'ManiphestTransactionSaveController' => 'applications/maniphest/controller/transactionsave',
     'ManiphestTransactionType' => 'applications/maniphest/constants/transactiontype',
     'ManiphestView' => 'applications/maniphest/view/base',
     'MetaMTAConstants' => 'applications/metamta/constants/base',
     'MetaMTANotificationType' => 'applications/metamta/constants/notificationtype',
     'Phabricator404Controller' => 'applications/base/controller/404',
     'PhabricatorAccessLog' => 'infrastructure/accesslog',
     'PhabricatorAphlictTestPageController' => 'applications/notifications/controller/test',
     'PhabricatorAuditActionConstants' => 'applications/audit/constants/action',
     'PhabricatorAuditAddCommentController' => 'applications/audit/controller/addcomment',
     'PhabricatorAuditComment' => 'applications/audit/storage/auditcomment',
     'PhabricatorAuditCommentEditor' => 'applications/audit/editor/comment',
     'PhabricatorAuditCommitListView' => 'applications/audit/view/commitlist',
     'PhabricatorAuditCommitQuery' => 'applications/audit/query/commit',
     'PhabricatorAuditCommitStatusConstants' => 'applications/audit/constants/commitstatus',
     'PhabricatorAuditController' => 'applications/audit/controller/base',
     'PhabricatorAuditDAO' => 'applications/audit/storage/base',
     'PhabricatorAuditInlineComment' => 'applications/audit/storage/inlinecommment',
     'PhabricatorAuditListController' => 'applications/audit/controller/list',
     'PhabricatorAuditListView' => 'applications/audit/view/list',
     'PhabricatorAuditPreviewController' => 'applications/audit/controller/preview',
     'PhabricatorAuditQuery' => 'applications/audit/query/audit',
     'PhabricatorAuditReplyHandler' => 'applications/audit/replyhandler',
     'PhabricatorAuditStatusConstants' => 'applications/audit/constants/status',
     'PhabricatorAuthController' => 'applications/auth/controller/base',
+    'PhabricatorBuiltinPatchList' => 'infrastructure/setup/sql/phabricator',
     'PhabricatorCalendarBrowseController' => 'applications/calendar/controller/browse',
     'PhabricatorCalendarController' => 'applications/calendar/controller/base',
     'PhabricatorChangesetResponse' => 'infrastructure/diff/response',
     'PhabricatorChatLogChannelListController' => 'applications/chatlog/controller/channellist',
     'PhabricatorChatLogChannelLogController' => 'applications/chatlog/controller/channellog',
     'PhabricatorChatLogConstants' => 'applications/chatlog/constants/base',
     'PhabricatorChatLogController' => 'applications/chatlog/controller/base',
     'PhabricatorChatLogDAO' => 'applications/chatlog/storage/base',
     'PhabricatorChatLogEvent' => 'applications/chatlog/storage/event',
     'PhabricatorChatLogEventType' => 'applications/chatlog/constants/eventtype',
     'PhabricatorChatLogQuery' => 'applications/chatlog/query',
     'PhabricatorConduitAPIController' => 'applications/conduit/controller/api',
     'PhabricatorConduitCertificateToken' => 'applications/conduit/storage/token',
     'PhabricatorConduitConnectionLog' => 'applications/conduit/storage/connectionlog',
     'PhabricatorConduitConsoleController' => 'applications/conduit/controller/console',
     'PhabricatorConduitController' => 'applications/conduit/controller/base',
     'PhabricatorConduitDAO' => 'applications/conduit/storage/base',
     'PhabricatorConduitListController' => 'applications/conduit/controller/list',
     'PhabricatorConduitLogController' => 'applications/conduit/controller/log',
     'PhabricatorConduitMethodCallLog' => 'applications/conduit/storage/methodcalllog',
     'PhabricatorConduitTokenController' => 'applications/conduit/controller/token',
     'PhabricatorContentSource' => 'applications/metamta/contentsource/source',
     'PhabricatorContentSourceView' => 'applications/metamta/contentsource/view',
     'PhabricatorController' => 'applications/base/controller/base',
     'PhabricatorCountdownController' => 'applications/countdown/controller/base',
     'PhabricatorCountdownDAO' => 'applications/countdown/storage/base',
     'PhabricatorCountdownDeleteController' => 'applications/countdown/controller/delete',
     'PhabricatorCountdownEditController' => 'applications/countdown/controller/edit',
     'PhabricatorCountdownListController' => 'applications/countdown/controller/list',
     'PhabricatorCountdownViewController' => 'applications/countdown/controller/view',
     'PhabricatorDaemon' => 'infrastructure/daemon/base',
     'PhabricatorDaemonCombinedLogController' => 'applications/daemon/controller/combined',
     'PhabricatorDaemonConsoleController' => 'applications/daemon/controller/console',
     'PhabricatorDaemonControl' => 'infrastructure/daemon/control',
     'PhabricatorDaemonController' => 'applications/daemon/controller/base',
     'PhabricatorDaemonDAO' => 'infrastructure/daemon/storage/base',
     'PhabricatorDaemonLog' => 'infrastructure/daemon/storage/log',
     'PhabricatorDaemonLogEvent' => 'infrastructure/daemon/storage/event',
     'PhabricatorDaemonLogEventsView' => 'applications/daemon/view/daemonlogevents',
     'PhabricatorDaemonLogListController' => 'applications/daemon/controller/loglist',
     'PhabricatorDaemonLogListView' => 'applications/daemon/view/daemonloglist',
     'PhabricatorDaemonLogViewController' => 'applications/daemon/controller/logview',
     'PhabricatorDaemonReference' => 'infrastructure/daemon/control/reference',
     'PhabricatorDaemonTimelineConsoleController' => 'applications/daemon/controller/timeline',
     'PhabricatorDaemonTimelineEventController' => 'applications/daemon/controller/timelineevent',
     'PhabricatorDefaultFileStorageEngineSelector' => 'applications/files/engineselector/default',
     'PhabricatorDefaultSearchEngineSelector' => 'applications/search/selector/default',
     'PhabricatorDifferenceEngine' => 'infrastructure/diff/engine',
     'PhabricatorDirectoryController' => 'applications/directory/controller/base',
     'PhabricatorDirectoryMainController' => 'applications/directory/controller/main',
     'PhabricatorDisabledUserController' => 'applications/auth/controller/disabled',
     'PhabricatorDraft' => 'applications/draft/storage/draft',
     'PhabricatorDraftDAO' => 'applications/draft/storage/base',
     'PhabricatorEdgeConfig' => 'infrastructure/edges/constants/config',
     'PhabricatorEdgeConstants' => 'infrastructure/edges/constants/base',
     'PhabricatorEdgeEditor' => 'infrastructure/edges/editor/edge',
     'PhabricatorEdgeQuery' => 'infrastructure/edges/query/edge',
     'PhabricatorEmailLoginController' => 'applications/auth/controller/email',
     'PhabricatorEmailTokenController' => 'applications/auth/controller/emailtoken',
     'PhabricatorEnv' => 'infrastructure/env',
     'PhabricatorEnvTestCase' => 'infrastructure/env/__tests__',
     'PhabricatorErrorExample' => 'applications/uiexample/examples/error',
     'PhabricatorEvent' => 'infrastructure/events/event',
     'PhabricatorEventEngine' => 'infrastructure/events/engine',
     'PhabricatorEventType' => 'infrastructure/events/constant/type',
     'PhabricatorFeedBuilder' => 'applications/feed/builder/feed',
     'PhabricatorFeedConstants' => 'applications/feed/constants/base',
     'PhabricatorFeedController' => 'applications/feed/controller/base',
     'PhabricatorFeedDAO' => 'applications/feed/storage/base',
     'PhabricatorFeedPublicStreamController' => 'applications/feed/controller/publicstream',
     'PhabricatorFeedQuery' => 'applications/feed/query',
     'PhabricatorFeedStory' => 'applications/feed/story/base',
     'PhabricatorFeedStoryAudit' => 'applications/feed/story/audit',
     'PhabricatorFeedStoryData' => 'applications/feed/storage/story',
     'PhabricatorFeedStoryDifferential' => 'applications/feed/story/differential',
     'PhabricatorFeedStoryManiphest' => 'applications/feed/story/maniphest',
     'PhabricatorFeedStoryPhriction' => 'applications/feed/story/phriction',
     'PhabricatorFeedStoryProject' => 'applications/feed/story/project',
     'PhabricatorFeedStoryPublisher' => 'applications/feed/publisher',
     'PhabricatorFeedStoryReference' => 'applications/feed/storage/storyreference',
     'PhabricatorFeedStoryStatus' => 'applications/feed/story/status',
     'PhabricatorFeedStoryTypeConstants' => 'applications/feed/constants/story',
     'PhabricatorFeedStoryUnknown' => 'applications/feed/story/unknown',
     'PhabricatorFeedStoryView' => 'applications/feed/view/story',
     'PhabricatorFeedView' => 'applications/feed/view/base',
     'PhabricatorFile' => 'applications/files/storage/file',
     'PhabricatorFileController' => 'applications/files/controller/base',
     'PhabricatorFileDAO' => 'applications/files/storage/base',
     'PhabricatorFileDataController' => 'applications/files/controller/data',
     'PhabricatorFileDeleteController' => 'applications/files/controller/delete',
     'PhabricatorFileDropUploadController' => 'applications/files/controller/dropupload',
     'PhabricatorFileImageMacro' => 'applications/files/storage/imagemacro',
     'PhabricatorFileInfoController' => 'applications/files/controller/info',
     'PhabricatorFileListController' => 'applications/files/controller/list',
     'PhabricatorFileMacroDeleteController' => 'applications/files/controller/macrodelete',
     'PhabricatorFileMacroEditController' => 'applications/files/controller/macroedit',
     'PhabricatorFileMacroListController' => 'applications/files/controller/macrolist',
     'PhabricatorFileProxyController' => 'applications/files/controller/proxy',
     'PhabricatorFileProxyImage' => 'applications/files/storage/proxyimage',
     'PhabricatorFileSideNavView' => 'applications/files/view/sidenav',
     'PhabricatorFileStorageBlob' => 'applications/files/storage/storageblob',
     'PhabricatorFileStorageConfigurationException' => 'applications/files/exception/configuration',
     'PhabricatorFileStorageEngine' => 'applications/files/engine/base',
     'PhabricatorFileStorageEngineSelector' => 'applications/files/engineselector/base',
     'PhabricatorFileTransformController' => 'applications/files/controller/transform',
     'PhabricatorFileUploadController' => 'applications/files/controller/upload',
     'PhabricatorFileUploadException' => 'applications/files/exception/upload',
     'PhabricatorFileUploadView' => 'applications/files/view/upload',
     'PhabricatorFlag' => 'applications/flag/storage/flag',
     'PhabricatorFlagColor' => 'applications/flag/constants/color',
     'PhabricatorFlagConstants' => 'applications/flag/constants/base',
     'PhabricatorFlagController' => 'applications/flag/controller/base',
     'PhabricatorFlagDAO' => 'applications/flag/storage/base',
     'PhabricatorFlagDeleteController' => 'applications/flag/controller/delete',
     'PhabricatorFlagEditController' => 'applications/flag/controller/edit',
     'PhabricatorFlagListController' => 'applications/flag/controller/list',
     'PhabricatorFlagListView' => 'applications/flag/view/list',
     'PhabricatorFlagQuery' => 'applications/flag/query/flag',
     'PhabricatorFormExample' => 'applications/uiexample/examples/form',
     'PhabricatorGarbageCollectorDaemon' => 'infrastructure/daemon/garbagecollector',
     'PhabricatorGoodForNothingWorker' => 'infrastructure/daemon/workers/worker/goodfornothing',
     'PhabricatorHandleObjectSelectorDataView' => 'applications/phid/handle/view/selector',
     'PhabricatorHash' => 'infrastructure/util/hash',
     'PhabricatorHelpController' => 'applications/help/controller/base',
     'PhabricatorHelpKeyboardShortcutController' => 'applications/help/controller/keyboardshortcut',
     'PhabricatorIDPagedPolicyQuery' => 'infrastructure/query/policy/idpaged',
     'PhabricatorIRCBot' => 'infrastructure/daemon/irc/bot',
     'PhabricatorIRCDifferentialNotificationHandler' => 'infrastructure/daemon/irc/handler/differentialnotification',
     'PhabricatorIRCHandler' => 'infrastructure/daemon/irc/handler/base',
     'PhabricatorIRCLogHandler' => 'infrastructure/daemon/irc/handler/log',
     'PhabricatorIRCMacroHandler' => 'infrastructure/daemon/irc/handler/macro',
     'PhabricatorIRCMessage' => 'infrastructure/daemon/irc/message',
     'PhabricatorIRCObjectNameHandler' => 'infrastructure/daemon/irc/handler/objectname',
     'PhabricatorIRCProtocolHandler' => 'infrastructure/daemon/irc/handler/protocol',
     'PhabricatorIRCWhatsNewHandler' => 'infrastructure/daemon/irc/handler/whatsnew',
     'PhabricatorImageTransformer' => 'applications/files/transform',
     'PhabricatorInfrastructureTestCase' => 'infrastructure/__tests__',
     'PhabricatorInlineCommentController' => 'infrastructure/diff/controller',
     'PhabricatorInlineCommentInterface' => 'infrastructure/diff/interface/inline',
     'PhabricatorInlineSummaryView' => 'infrastructure/diff/view/inline',
     'PhabricatorJavelinLinter' => 'infrastructure/lint/linter/javelin',
     'PhabricatorJumpNavHandler' => 'applications/search/engine/jumpnav',
     'PhabricatorLintEngine' => 'infrastructure/lint/engine',
     'PhabricatorLiskDAO' => 'applications/base/storage/lisk',
     'PhabricatorLocalDiskFileStorageEngine' => 'applications/files/engine/localdisk',
     'PhabricatorLocalTimeTestCase' => 'view/utils/__tests__',
     'PhabricatorLoginController' => 'applications/auth/controller/login',
     'PhabricatorLoginValidateController' => 'applications/auth/controller/validate',
     'PhabricatorLogoutController' => 'applications/auth/controller/logout',
     'PhabricatorMailImplementationAdapter' => 'applications/metamta/adapter/base',
     'PhabricatorMailImplementationAmazonSESAdapter' => 'applications/metamta/adapter/amazonses',
     'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/phpmailerlite',
     'PhabricatorMailImplementationSendGridAdapter' => 'applications/metamta/adapter/sendgrid',
     'PhabricatorMailImplementationTestAdapter' => 'applications/metamta/adapter/test',
     'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/base',
     'PhabricatorMarkupEngine' => 'applications/markup/engine',
     'PhabricatorMetaMTAAttachment' => 'applications/metamta/storage/mail',
     'PhabricatorMetaMTAController' => 'applications/metamta/controller/base',
     'PhabricatorMetaMTADAO' => 'applications/metamta/storage/base',
     'PhabricatorMetaMTAEmailBodyParser' => 'applications/metamta/parser',
     'PhabricatorMetaMTAEmailBodyParserTestCase' => 'applications/metamta/parser/__tests__',
     'PhabricatorMetaMTAListController' => 'applications/metamta/controller/list',
     'PhabricatorMetaMTAMail' => 'applications/metamta/storage/mail',
     'PhabricatorMetaMTAMailTestCase' => 'applications/metamta/storage/mail/__tests__',
     'PhabricatorMetaMTAMailingList' => 'applications/metamta/storage/mailinglist',
     'PhabricatorMetaMTAMailingListEditController' => 'applications/metamta/controller/mailinglistedit',
     'PhabricatorMetaMTAMailingListsController' => 'applications/metamta/controller/mailinglists',
     'PhabricatorMetaMTAReceiveController' => 'applications/metamta/controller/receive',
     'PhabricatorMetaMTAReceivedListController' => 'applications/metamta/controller/receivedlist',
     'PhabricatorMetaMTAReceivedMail' => 'applications/metamta/storage/receivedmail',
     'PhabricatorMetaMTASendController' => 'applications/metamta/controller/send',
     'PhabricatorMetaMTASendGridReceiveController' => 'applications/metamta/controller/sendgridreceive',
     'PhabricatorMetaMTAViewController' => 'applications/metamta/controller/view',
     'PhabricatorMetaMTAWorker' => 'applications/metamta/worker',
     'PhabricatorMySQLFileStorageEngine' => 'applications/files/engine/mysql',
     'PhabricatorNotificationsController' => 'applications/notifications/controller/base',
     'PhabricatorOAuthClientAuthorization' => 'applications/oauthserver/storage/clientauthorization',
     'PhabricatorOAuthClientAuthorizationBaseController' => 'applications/oauthserver/controller/clientauthorization/base',
     'PhabricatorOAuthClientAuthorizationDeleteController' => 'applications/oauthserver/controller/clientauthorization/delete',
     'PhabricatorOAuthClientAuthorizationEditController' => 'applications/oauthserver/controller/clientauthorization/edit',
     'PhabricatorOAuthClientAuthorizationListController' => 'applications/oauthserver/controller/clientauthorization/list',
     'PhabricatorOAuthClientAuthorizationQuery' => 'applications/oauthserver/query/clientauthorization',
     'PhabricatorOAuthClientBaseController' => 'applications/oauthserver/controller/client/base',
     'PhabricatorOAuthClientDeleteController' => 'applications/oauthserver/controller/client/delete',
     'PhabricatorOAuthClientEditController' => 'applications/oauthserver/controller/client/edit',
     'PhabricatorOAuthClientListController' => 'applications/oauthserver/controller/client/list',
     'PhabricatorOAuthClientViewController' => 'applications/oauthserver/controller/client/view',
     'PhabricatorOAuthDefaultRegistrationController' => 'applications/auth/controller/oauthregistration/default',
     'PhabricatorOAuthDiagnosticsController' => 'applications/auth/controller/oauthdiagnostics',
     'PhabricatorOAuthFailureView' => 'applications/auth/view/oauthfailure',
     'PhabricatorOAuthLoginController' => 'applications/auth/controller/oauth',
     'PhabricatorOAuthProvider' => 'applications/auth/oauth/provider/base',
     'PhabricatorOAuthProviderFacebook' => 'applications/auth/oauth/provider/facebook',
     'PhabricatorOAuthProviderGitHub' => 'applications/auth/oauth/provider/github',
     'PhabricatorOAuthProviderGoogle' => 'applications/auth/oauth/provider/google',
     'PhabricatorOAuthProviderPhabricator' => 'applications/auth/oauth/provider/phabricator',
     'PhabricatorOAuthRegistrationController' => 'applications/auth/controller/oauthregistration/base',
     'PhabricatorOAuthResponse' => 'applications/oauthserver/response',
     'PhabricatorOAuthServer' => 'applications/oauthserver/server',
     'PhabricatorOAuthServerAccessToken' => 'applications/oauthserver/storage/accesstoken',
     'PhabricatorOAuthServerAuthController' => 'applications/oauthserver/controller/auth',
     'PhabricatorOAuthServerAuthorizationCode' => 'applications/oauthserver/storage/authorizationcode',
     'PhabricatorOAuthServerClient' => 'applications/oauthserver/storage/client',
     'PhabricatorOAuthServerClientQuery' => 'applications/oauthserver/query/client',
     'PhabricatorOAuthServerController' => 'applications/oauthserver/controller/base',
     'PhabricatorOAuthServerDAO' => 'applications/oauthserver/storage/base',
     'PhabricatorOAuthServerScope' => 'applications/oauthserver/scope',
     'PhabricatorOAuthServerTestCase' => 'applications/oauthserver/server/__tests__',
     'PhabricatorOAuthServerTestController' => 'applications/oauthserver/controller/test',
     'PhabricatorOAuthServerTokenController' => 'applications/oauthserver/controller/token',
     'PhabricatorOAuthUnlinkController' => 'applications/auth/controller/unlink',
     'PhabricatorObjectAttachmentEditor' => 'applications/search/editor/attach',
     'PhabricatorObjectGraph' => 'applications/phid/graph',
     'PhabricatorObjectHandle' => 'applications/phid/handle',
     'PhabricatorObjectHandleConstants' => 'applications/phid/handle/const/base',
     'PhabricatorObjectHandleData' => 'applications/phid/handle/data',
     'PhabricatorObjectHandleStatus' => 'applications/phid/handle/const/status',
     'PhabricatorObjectSelectorDialog' => 'view/control/objectselector',
     'PhabricatorOffsetPagedQuery' => 'infrastructure/query/offsetpaged',
     'PhabricatorOwnerPathQuery' => 'applications/owners/query/path',
     'PhabricatorOwnersController' => 'applications/owners/controller/base',
     'PhabricatorOwnersDAO' => 'applications/owners/storage/base',
     'PhabricatorOwnersDeleteController' => 'applications/owners/controller/delete',
     'PhabricatorOwnersDetailController' => 'applications/owners/controller/detail',
     'PhabricatorOwnersEditController' => 'applications/owners/controller/edit',
     'PhabricatorOwnersListController' => 'applications/owners/controller/list',
     'PhabricatorOwnersOwner' => 'applications/owners/storage/owner',
     'PhabricatorOwnersPackage' => 'applications/owners/storage/package',
     'PhabricatorOwnersPath' => 'applications/owners/storage/path',
     'PhabricatorPHID' => 'applications/phid/storage/phid',
     'PhabricatorPHIDConstants' => 'applications/phid/constants',
     'PhabricatorPHIDController' => 'applications/phid/controller/base',
     'PhabricatorPHIDDAO' => 'applications/phid/storage/base',
     'PhabricatorPHIDLookupController' => 'applications/phid/controller/lookup',
     'PhabricatorPaste' => 'applications/paste/storage/paste',
     'PhabricatorPasteController' => 'applications/paste/controller/base',
     'PhabricatorPasteDAO' => 'applications/paste/storage/base',
     'PhabricatorPasteListController' => 'applications/paste/controller/list',
     'PhabricatorPasteQuery' => 'applications/paste/query/paste',
     'PhabricatorPasteViewController' => 'applications/paste/controller/view',
     'PhabricatorPeopleController' => 'applications/people/controller/base',
     'PhabricatorPeopleEditController' => 'applications/people/controller/edit',
     'PhabricatorPeopleListController' => 'applications/people/controller/list',
     'PhabricatorPeopleLogsController' => 'applications/people/controller/logs',
     'PhabricatorPeopleProfileController' => 'applications/people/controller/profile',
     'PhabricatorPolicies' => 'applications/policy/constants/policy',
     'PhabricatorPolicyCapability' => 'applications/policy/constants/capability',
     'PhabricatorPolicyConstants' => 'applications/policy/constants/base',
     'PhabricatorPolicyException' => 'applications/policy/exception/base',
     'PhabricatorPolicyFilter' => 'applications/policy/filter/policy',
     'PhabricatorPolicyInterface' => 'applications/policy/interface/policy',
     'PhabricatorPolicyQuery' => 'infrastructure/query/policy/base',
     'PhabricatorPolicyTestCase' => 'applications/policy/__tests__',
     'PhabricatorPolicyTestObject' => 'applications/policy/__tests__',
     'PhabricatorPolicyTestQuery' => 'applications/policy/__tests__',
     'PhabricatorProfileHeaderView' => 'view/layout/profileheader',
     'PhabricatorProject' => 'applications/project/storage/project',
     'PhabricatorProjectAffiliation' => 'applications/project/storage/affiliation',
     'PhabricatorProjectConstants' => 'applications/project/constants/base',
     'PhabricatorProjectController' => 'applications/project/controller/base',
     'PhabricatorProjectCreateController' => 'applications/project/controller/create',
     'PhabricatorProjectDAO' => 'applications/project/storage/base',
     'PhabricatorProjectEditor' => 'applications/project/editor/project',
     'PhabricatorProjectListController' => 'applications/project/controller/list',
     'PhabricatorProjectNameCollisionException' => 'applications/project/exception/namecollison',
     'PhabricatorProjectProfile' => 'applications/project/storage/profile',
     'PhabricatorProjectProfileController' => 'applications/project/controller/profile',
     'PhabricatorProjectProfileEditController' => 'applications/project/controller/profileedit',
     'PhabricatorProjectQuery' => 'applications/project/query/project',
     'PhabricatorProjectStatus' => 'applications/project/constants/status',
     'PhabricatorProjectSubproject' => 'applications/project/storage/subproject',
     'PhabricatorProjectTransaction' => 'applications/project/storage/transaction',
     'PhabricatorProjectTransactionType' => 'applications/project/constants/transaction',
     'PhabricatorProjectUpdateController' => 'applications/project/controller/update',
     'PhabricatorQuery' => 'infrastructure/query/base',
     'PhabricatorRedirectController' => 'applications/base/controller/redirect',
     'PhabricatorRefreshCSRFController' => 'applications/auth/controller/refresh',
     'PhabricatorRemarkupRuleDifferential' => 'infrastructure/markup/remarkup/markuprule/differential',
     'PhabricatorRemarkupRuleDifferentialHandle' => 'infrastructure/markup/remarkup/markuprule/handle/differential',
     'PhabricatorRemarkupRuleDiffusion' => 'infrastructure/markup/remarkup/markuprule/diffusion',
     'PhabricatorRemarkupRuleEmbedFile' => 'infrastructure/markup/remarkup/markuprule/embedobject',
     'PhabricatorRemarkupRuleImageMacro' => 'infrastructure/markup/remarkup/markuprule/imagemacro',
     'PhabricatorRemarkupRuleManiphest' => 'infrastructure/markup/remarkup/markuprule/maniphest',
     'PhabricatorRemarkupRuleManiphestHandle' => 'infrastructure/markup/remarkup/markuprule/handle/maniphest',
     'PhabricatorRemarkupRuleMention' => 'infrastructure/markup/remarkup/markuprule/mention',
     'PhabricatorRemarkupRuleObjectHandle' => 'infrastructure/markup/remarkup/markuprule/handle',
     'PhabricatorRemarkupRuleObjectName' => 'infrastructure/markup/remarkup/markuprule/objectname',
     'PhabricatorRemarkupRulePaste' => 'infrastructure/markup/remarkup/markuprule/paste',
     'PhabricatorRemarkupRulePhriction' => 'infrastructure/markup/remarkup/markuprule/phriction',
     'PhabricatorRemarkupRuleProxyImage' => 'infrastructure/markup/remarkup/markuprule/proxyimage',
     'PhabricatorRemarkupRuleYoutube' => 'infrastructure/markup/remarkup/markuprule/youtube',
     'PhabricatorRepository' => 'applications/repository/storage/repository',
     'PhabricatorRepositoryArcanistProject' => 'applications/repository/storage/arcanistproject',
     'PhabricatorRepositoryArcanistProjectEditController' => 'applications/repository/controller/arcansistprojectedit',
     'PhabricatorRepositoryAuditRequest' => 'applications/repository/storage/auditrequest',
     'PhabricatorRepositoryCommit' => 'applications/repository/storage/commit',
     'PhabricatorRepositoryCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/base',
     'PhabricatorRepositoryCommitData' => 'applications/repository/storage/commitdata',
     'PhabricatorRepositoryCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/base',
     'PhabricatorRepositoryCommitHeraldWorker' => 'applications/repository/worker/herald',
     'PhabricatorRepositoryCommitMessageDetailParser' => 'applications/repository/parser/base',
     'PhabricatorRepositoryCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/base',
     'PhabricatorRepositoryCommitOwnersWorker' => 'applications/repository/worker/owner',
     'PhabricatorRepositoryCommitParserWorker' => 'applications/repository/worker/base',
     'PhabricatorRepositoryCommitTaskDaemon' => 'applications/repository/daemon/committask',
     'PhabricatorRepositoryController' => 'applications/repository/controller/base',
     'PhabricatorRepositoryCreateController' => 'applications/repository/controller/create',
     'PhabricatorRepositoryDAO' => 'applications/repository/storage/base',
     'PhabricatorRepositoryDaemon' => 'applications/repository/daemon/base',
     'PhabricatorRepositoryDefaultCommitMessageDetailParser' => 'applications/repository/parser/default',
     'PhabricatorRepositoryDeleteController' => 'applications/repository/controller/delete',
     'PhabricatorRepositoryEditController' => 'applications/repository/controller/edit',
     'PhabricatorRepositoryGitCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/git',
     'PhabricatorRepositoryGitCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/git',
     'PhabricatorRepositoryGitCommitDiscoveryDaemonTestCase' => 'applications/repository/daemon/commitdiscovery/git/__tests__',
     'PhabricatorRepositoryGitCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/git',
     'PhabricatorRepositoryGitFetchDaemon' => 'applications/repository/daemon/gitfetch',
     'PhabricatorRepositoryListController' => 'applications/repository/controller/list',
     'PhabricatorRepositoryMercurialCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/mercurial',
     'PhabricatorRepositoryMercurialCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/mercurial',
     'PhabricatorRepositoryMercurialCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/mercurial',
     'PhabricatorRepositoryMercurialPullDaemon' => 'applications/repository/daemon/mercurialpull',
     'PhabricatorRepositoryPullLocalDaemon' => 'applications/repository/daemon/pulllocal',
     'PhabricatorRepositoryShortcut' => 'applications/repository/storage/shortcut',
     'PhabricatorRepositorySvnCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/svn',
     'PhabricatorRepositorySvnCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/svn',
     'PhabricatorRepositorySvnCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/svn',
     'PhabricatorRepositorySymbol' => 'applications/repository/storage/symbol',
     'PhabricatorRepositoryTestCase' => 'applications/repository/storage/repository/__tests__',
     'PhabricatorRepositoryType' => 'applications/repository/constants/repositorytype',
     'PhabricatorS3FileStorageEngine' => 'applications/files/engine/s3',
-    'PhabricatorSQLPatchList' => 'infrastructure/setup/sql',
+    'PhabricatorSQLPatchList' => 'infrastructure/setup/sql/base',
     'PhabricatorScopedEnv' => 'infrastructure/env',
     'PhabricatorSearchAbstractDocument' => 'applications/search/index/abstractdocument',
     'PhabricatorSearchAttachController' => 'applications/search/controller/attach',
     'PhabricatorSearchBaseController' => 'applications/search/controller/base',
     'PhabricatorSearchCommitIndexer' => 'applications/search/index/indexer/repository',
     'PhabricatorSearchController' => 'applications/search/controller/search',
     'PhabricatorSearchDAO' => 'applications/search/storage/base',
     'PhabricatorSearchDifferentialIndexer' => 'applications/search/index/indexer/differential',
     'PhabricatorSearchDocument' => 'applications/search/storage/document/document',
     'PhabricatorSearchDocumentField' => 'applications/search/storage/document/field',
     'PhabricatorSearchDocumentIndexer' => 'applications/search/index/indexer/base',
     'PhabricatorSearchDocumentRelationship' => 'applications/search/storage/document/relationship',
     'PhabricatorSearchEngine' => 'applications/search/engine/base',
     'PhabricatorSearchEngineElastic' => 'applications/search/engine/elastic',
     'PhabricatorSearchEngineMySQL' => 'applications/search/engine/mysql',
     'PhabricatorSearchEngineSelector' => 'applications/search/selector/base',
     'PhabricatorSearchField' => 'applications/search/constants/field',
     'PhabricatorSearchIndexController' => 'applications/search/controller/index',
     'PhabricatorSearchManiphestIndexer' => 'applications/search/index/indexer/maniphest',
     'PhabricatorSearchPhrictionIndexer' => 'applications/search/index/indexer/phriction',
     'PhabricatorSearchQuery' => 'applications/search/storage/query',
     'PhabricatorSearchRelationship' => 'applications/search/constants/relationship',
     'PhabricatorSearchResultView' => 'applications/search/view/searchresult',
     'PhabricatorSearchScope' => 'applications/search/constants/scope',
     'PhabricatorSearchSelectController' => 'applications/search/controller/select',
     'PhabricatorSearchUserIndexer' => 'applications/search/index/indexer/user',
     'PhabricatorSetup' => 'infrastructure/setup',
     'PhabricatorSlowvoteChoice' => 'applications/slowvote/storage/choice',
     'PhabricatorSlowvoteComment' => 'applications/slowvote/storage/comment',
     'PhabricatorSlowvoteController' => 'applications/slowvote/controller/base',
     'PhabricatorSlowvoteCreateController' => 'applications/slowvote/controller/create',
     'PhabricatorSlowvoteDAO' => 'applications/slowvote/storage/base',
     'PhabricatorSlowvoteListController' => 'applications/slowvote/controller/list',
     'PhabricatorSlowvoteOption' => 'applications/slowvote/storage/option',
     'PhabricatorSlowvotePoll' => 'applications/slowvote/storage/poll',
     'PhabricatorSlowvotePollController' => 'applications/slowvote/controller/poll',
     'PhabricatorSlug' => 'infrastructure/util/slug',
     'PhabricatorSlugTestCase' => 'infrastructure/util/slug/__tests__',
     'PhabricatorSortTableExample' => 'applications/uiexample/examples/sorttable',
     'PhabricatorStandardPageView' => 'view/page/standard',
     'PhabricatorStatusController' => 'applications/status/base',
+    'PhabricatorStorageManagementAPI' => 'infrastructure/setup/storage/management',
+    'PhabricatorStorageManagementDatabasesWorkflow' => 'infrastructure/setup/storage/workflow/databases',
+    'PhabricatorStorageManagementDestroyWorkflow' => 'infrastructure/setup/storage/workflow/destroy',
+    'PhabricatorStorageManagementDumpWorkflow' => 'infrastructure/setup/storage/workflow/dump',
+    'PhabricatorStorageManagementStatusWorkflow' => 'infrastructure/setup/storage/workflow/status',
+    'PhabricatorStorageManagementUpgradeWorkflow' => 'infrastructure/setup/storage/workflow/upgrade',
+    'PhabricatorStorageManagementWorkflow' => 'infrastructure/setup/storage/workflow/base',
+    'PhabricatorStoragePatch' => 'infrastructure/setup/storage/patch',
     'PhabricatorSymbolNameLinter' => 'infrastructure/lint/hook/xhpastsymbolname',
     'PhabricatorSyntaxHighlighter' => 'applications/markup/syntax',
     'PhabricatorTaskmasterDaemon' => 'infrastructure/daemon/workers/taskmaster',
     'PhabricatorTestCase' => 'infrastructure/testing/testcase',
     'PhabricatorTimelineCursor' => 'infrastructure/daemon/timeline/storage/cursor',
     'PhabricatorTimelineDAO' => 'infrastructure/daemon/timeline/storage/base',
     'PhabricatorTimelineEvent' => 'infrastructure/daemon/timeline/storage/event',
     'PhabricatorTimelineEventData' => 'infrastructure/daemon/timeline/storage/eventdata',
     'PhabricatorTimelineIterator' => 'infrastructure/daemon/timeline/cursor/iterator',
     'PhabricatorTimer' => 'applications/countdown/storage/timer',
     'PhabricatorTransactionView' => 'view/layout/transaction',
     'PhabricatorTransformedFile' => 'applications/files/storage/transformed',
     'PhabricatorTrivialTestCase' => 'infrastructure/testing/testcase/__tests__',
     'PhabricatorTypeaheadCommonDatasourceController' => 'applications/typeahead/controller/common',
     'PhabricatorTypeaheadDatasourceController' => 'applications/typeahead/controller/base',
     'PhabricatorUIExample' => 'applications/uiexample/examples/base',
     'PhabricatorUIExampleController' => 'applications/uiexample/controller/base',
     'PhabricatorUIExampleRenderController' => 'applications/uiexample/controller/render',
     'PhabricatorUIListFilterExample' => 'applications/uiexample/examples/listfilter',
     'PhabricatorUIPagerExample' => 'applications/uiexample/examples/pager',
     'PhabricatorUITooltipExample' => 'applications/uiexample/examples/tooltip',
     'PhabricatorUser' => 'applications/people/storage/user',
     'PhabricatorUserAccountSettingsPanelController' => 'applications/people/controller/settings/panels/account',
     'PhabricatorUserConduitSettingsPanelController' => 'applications/people/controller/settings/panels/conduit',
     'PhabricatorUserDAO' => 'applications/people/storage/base',
     'PhabricatorUserEmailPreferenceSettingsPanelController' => 'applications/people/controller/settings/panels/emailpref',
     'PhabricatorUserEmailSettingsPanelController' => 'applications/people/controller/settings/panels/email',
     'PhabricatorUserLog' => 'applications/people/storage/log',
     'PhabricatorUserOAuthInfo' => 'applications/people/storage/useroauthinfo',
     'PhabricatorUserOAuthSettingsPanelController' => 'applications/people/controller/settings/panels/oauth',
     'PhabricatorUserPasswordSettingsPanelController' => 'applications/people/controller/settings/panels/password',
     'PhabricatorUserPreferenceSettingsPanelController' => 'applications/people/controller/settings/panels/preferences',
     'PhabricatorUserPreferences' => 'applications/people/storage/preferences',
     'PhabricatorUserProfile' => 'applications/people/storage/profile',
     'PhabricatorUserProfileSettingsPanelController' => 'applications/people/controller/settings/panels/profile',
     'PhabricatorUserSSHKey' => 'applications/people/storage/usersshkey',
     'PhabricatorUserSSHKeysSettingsPanelController' => 'applications/people/controller/settings/panels/sshkeys',
     'PhabricatorUserSearchSettingsPanelController' => 'applications/people/controller/settings/panels/search',
     'PhabricatorUserSettingsController' => 'applications/people/controller/settings',
     'PhabricatorUserSettingsPanelController' => 'applications/people/controller/settings/panels/base',
     'PhabricatorUserTestCase' => 'applications/people/storage/user/__tests__',
     'PhabricatorWorker' => 'infrastructure/daemon/workers/worker',
     'PhabricatorWorkerDAO' => 'infrastructure/daemon/workers/storage/base',
     'PhabricatorWorkerTask' => 'infrastructure/daemon/workers/storage/task',
     'PhabricatorWorkerTaskData' => 'infrastructure/daemon/workers/storage/taskdata',
     'PhabricatorWorkerTaskDetailController' => 'applications/daemon/controller/workertaskdetail',
     'PhabricatorWorkerTaskUpdateController' => 'applications/daemon/controller/workertaskupdate',
     'PhabricatorXHPASTViewController' => 'applications/xhpastview/controller/base',
     'PhabricatorXHPASTViewDAO' => 'applications/xhpastview/storage/base',
     'PhabricatorXHPASTViewFrameController' => 'applications/xhpastview/controller/viewframe',
     'PhabricatorXHPASTViewFramesetController' => 'applications/xhpastview/controller/viewframeset',
     'PhabricatorXHPASTViewInputController' => 'applications/xhpastview/controller/viewinput',
     'PhabricatorXHPASTViewPanelController' => 'applications/xhpastview/controller/viewpanel',
     'PhabricatorXHPASTViewParseTree' => 'applications/xhpastview/storage/parsetree',
     'PhabricatorXHPASTViewRunController' => 'applications/xhpastview/controller/run',
     'PhabricatorXHPASTViewStreamController' => 'applications/xhpastview/controller/viewstream',
     'PhabricatorXHPASTViewTreeController' => 'applications/xhpastview/controller/viewtree',
     'PhabricatorXHProfController' => 'applications/xhprof/controller/base',
     'PhabricatorXHProfProfileController' => 'applications/xhprof/controller/profile',
     'PhabricatorXHProfProfileSymbolView' => 'applications/xhprof/view/symbol',
     'PhabricatorXHProfProfileTopLevelView' => 'applications/xhprof/view/toplevel',
     'PhabricatorXHProfProfileView' => 'applications/xhprof/view/base',
     'PhameController' => 'applications/phame/controller/base',
     'PhameDAO' => 'applications/phame/storage/base',
     'PhameDraftListController' => 'applications/phame/controller/post/list/drafts',
     'PhamePost' => 'applications/phame/storage/post',
     'PhamePostDeleteController' => 'applications/phame/controller/post/delete',
     'PhamePostDetailView' => 'applications/phame/view/postdetail',
     'PhamePostEditController' => 'applications/phame/controller/post/edit',
     'PhamePostListBaseController' => 'applications/phame/controller/post/list/base',
     'PhamePostListController' => 'applications/phame/controller/post/list/posts',
     'PhamePostListView' => 'applications/phame/view/postlist',
     'PhamePostPreviewController' => 'applications/phame/controller/post/preview',
     'PhamePostQuery' => 'applications/phame/query/post',
     'PhamePostViewController' => 'applications/phame/controller/post/view',
     'PhortuneMonthYearExpiryControl' => 'applications/phortune/control/monthyearexpiry',
     'PhortuneStripeBaseController' => 'applications/phortune/stripe/controller/base',
     'PhortuneStripePaymentFormView' => 'applications/phortune/stripe/view/paymentform',
     'PhortuneStripeTestPaymentFormController' => 'applications/phortune/stripe/controller/testpaymentform',
     'PhrictionActionConstants' => 'applications/phriction/constants/action',
     'PhrictionChangeType' => 'applications/phriction/constants/changetype',
     'PhrictionConstants' => 'applications/phriction/constants/base',
     'PhrictionContent' => 'applications/phriction/storage/content',
     'PhrictionController' => 'applications/phriction/controller/base',
     'PhrictionDAO' => 'applications/phriction/storage/base',
     'PhrictionDeleteController' => 'applications/phriction/controller/delete',
     'PhrictionDiffController' => 'applications/phriction/controller/diff',
     'PhrictionDocument' => 'applications/phriction/storage/document',
     'PhrictionDocumentController' => 'applications/phriction/controller/document',
     'PhrictionDocumentEditor' => 'applications/phriction/editor/document',
     'PhrictionDocumentPreviewController' => 'applications/phriction/controller/documentpreview',
     'PhrictionDocumentStatus' => 'applications/phriction/constants/documentstatus',
     'PhrictionDocumentTestCase' => 'applications/phriction/storage/document/__tests__',
     'PhrictionEditController' => 'applications/phriction/controller/edit',
     'PhrictionHistoryController' => 'applications/phriction/controller/history',
     'PhrictionListController' => 'applications/phriction/controller/list',
     'QueryFormattingTestCase' => 'storage/qsprintf/__tests__',
   ),
   'function' =>
   array(
     '_phabricator_date_format' => 'view/utils',
     '_qsprintf_check_scalar_type' => 'storage/qsprintf',
     '_qsprintf_check_type' => 'storage/qsprintf',
     'celerity_generate_unique_node_id' => 'infrastructure/celerity/api',
     'celerity_get_resource_uri' => 'infrastructure/celerity/api',
     'celerity_register_resource_map' => 'infrastructure/celerity/map',
     'javelin_render_tag' => 'infrastructure/javelin/markup',
     'phabricator_date' => 'view/utils',
     'phabricator_datetime' => 'view/utils',
     'phabricator_format_local_time' => 'view/utils',
     'phabricator_format_relative_time' => 'view/utils',
     'phabricator_format_units_generic' => 'view/utils',
     'phabricator_on_relative_date' => 'view/utils',
     'phabricator_relative_date' => 'view/utils',
     'phabricator_render_form' => 'infrastructure/javelin/markup',
     'phabricator_time' => 'view/utils',
     'phid_get_type' => 'applications/phid/utils',
     'phid_group_by_type' => 'applications/phid/utils',
     'qsprintf' => 'storage/qsprintf',
     'queryfx' => 'storage/queryfx',
     'queryfx_all' => 'storage/queryfx',
     'queryfx_one' => 'storage/queryfx',
     'require_celerity_resource' => 'infrastructure/celerity/api',
     'vqsprintf' => 'storage/qsprintf',
     'vqueryfx' => 'storage/queryfx',
     'vqueryfx_all' => 'storage/queryfx',
     'xsprintf_query' => 'storage/qsprintf',
   ),
   'requires_class' =>
   array(
     'Aphront304Response' => 'AphrontResponse',
     'Aphront400Response' => 'AphrontResponse',
     'Aphront403Response' => 'AphrontWebpageResponse',
     'Aphront404Response' => 'AphrontWebpageResponse',
     'AphrontAjaxResponse' => 'AphrontResponse',
     'AphrontAttachedFileView' => 'AphrontView',
     'AphrontCSRFException' => 'AphrontException',
     'AphrontCalendarMonthView' => 'AphrontView',
     'AphrontContextBarView' => 'AphrontView',
     'AphrontCrumbsView' => 'AphrontView',
     'AphrontDefaultApplicationConfiguration' => 'AphrontApplicationConfiguration',
     'AphrontDialogResponse' => 'AphrontResponse',
     'AphrontDialogView' => 'AphrontView',
     'AphrontErrorView' => 'AphrontView',
     'AphrontFilePreviewView' => 'AphrontView',
     'AphrontFileResponse' => 'AphrontResponse',
     'AphrontFormCheckboxControl' => 'AphrontFormControl',
     'AphrontFormControl' => 'AphrontView',
     'AphrontFormDateControl' => 'AphrontFormControl',
     'AphrontFormDividerControl' => 'AphrontFormControl',
     'AphrontFormDragAndDropUploadControl' => 'AphrontFormControl',
     'AphrontFormFileControl' => 'AphrontFormControl',
     'AphrontFormInsetView' => 'AphrontView',
     'AphrontFormLayoutView' => 'AphrontView',
     'AphrontFormMarkupControl' => 'AphrontFormControl',
     'AphrontFormPasswordControl' => 'AphrontFormControl',
     'AphrontFormPolicyControl' => 'AphrontFormControl',
     'AphrontFormRadioButtonControl' => 'AphrontFormControl',
     'AphrontFormRecaptchaControl' => 'AphrontFormControl',
     'AphrontFormSelectControl' => 'AphrontFormControl',
     'AphrontFormStaticControl' => 'AphrontFormControl',
     'AphrontFormSubmitControl' => 'AphrontFormControl',
     'AphrontFormTextAreaControl' => 'AphrontFormControl',
     'AphrontFormTextControl' => 'AphrontFormControl',
     'AphrontFormToggleButtonsControl' => 'AphrontFormControl',
     'AphrontFormTokenizerControl' => 'AphrontFormControl',
     'AphrontFormView' => 'AphrontView',
     'AphrontHTTPSinkTestCase' => 'PhabricatorTestCase',
     'AphrontHeadsupActionListView' => 'AphrontView',
     'AphrontHeadsupActionView' => 'AphrontView',
     'AphrontHeadsupView' => 'AphrontView',
     'AphrontIDPagerView' => 'AphrontView',
     'AphrontIsolatedDatabaseConnection' => 'AphrontDatabaseConnection',
     'AphrontIsolatedDatabaseConnectionTestCase' => 'PhabricatorTestCase',
     'AphrontIsolatedHTTPSink' => 'AphrontHTTPSink',
     'AphrontJSONResponse' => 'AphrontResponse',
     'AphrontJavelinView' => 'AphrontView',
     'AphrontKeyboardShortcutsAvailableView' => 'AphrontView',
     'AphrontListFilterView' => 'AphrontView',
     'AphrontMiniPanelView' => 'AphrontView',
     'AphrontMySQLDatabaseConnection' => 'AphrontMySQLDatabaseConnectionBase',
     'AphrontMySQLDatabaseConnectionBase' => 'AphrontDatabaseConnection',
     'AphrontMySQLDatabaseConnectionTestCase' => 'PhabricatorTestCase',
     'AphrontMySQLiDatabaseConnection' => 'AphrontMySQLDatabaseConnectionBase',
     'AphrontNullView' => 'AphrontView',
     'AphrontPHPHTTPSink' => 'AphrontHTTPSink',
     'AphrontPageView' => 'AphrontView',
     'AphrontPagerView' => 'AphrontView',
     'AphrontPanelView' => 'AphrontView',
     'AphrontPlainTextResponse' => 'AphrontResponse',
     'AphrontProxyResponse' => 'AphrontResponse',
     'AphrontQueryAccessDeniedException' => 'AphrontQueryRecoverableException',
     'AphrontQueryConnectionException' => 'AphrontQueryException',
     'AphrontQueryConnectionLostException' => 'AphrontQueryRecoverableException',
     'AphrontQueryCountException' => 'AphrontQueryException',
     'AphrontQueryDuplicateKeyException' => 'AphrontQueryException',
     'AphrontQueryObjectMissingException' => 'AphrontQueryException',
     'AphrontQueryParameterException' => 'AphrontQueryException',
     'AphrontQueryRecoverableException' => 'AphrontQueryException',
     'AphrontQuerySchemaException' => 'AphrontQueryException',
     'AphrontRedirectException' => 'AphrontException',
     'AphrontRedirectResponse' => 'AphrontResponse',
     'AphrontReloadResponse' => 'AphrontRedirectResponse',
     'AphrontRequestFailureView' => 'AphrontView',
     'AphrontRequestTestCase' => 'PhabricatorTestCase',
     'AphrontSideNavFilterView' => 'AphrontView',
     'AphrontSideNavView' => 'AphrontView',
     'AphrontTableView' => 'AphrontView',
     'AphrontTokenizerTemplateView' => 'AphrontView',
     'AphrontTypeaheadTemplateView' => 'AphrontView',
     'AphrontUsageException' => 'AphrontException',
     'AphrontWebpageResponse' => 'AphrontResponse',
     'CelerityResourceController' => 'AphrontController',
     'CelerityResourceGraph' => 'AbstractDirectedGraph',
     'CelerityResourceTransformerTestCase' => 'PhabricatorTestCase',
     'ConduitAPI_arcanist_Method' => 'ConduitAPIMethod',
     'ConduitAPI_arcanist_projectinfo_Method' => 'ConduitAPI_arcanist_Method',
     'ConduitAPI_audit_Method' => 'ConduitAPIMethod',
     'ConduitAPI_audit_query_Method' => 'ConduitAPI_audit_Method',
     'ConduitAPI_chatlog_Method' => 'ConduitAPIMethod',
     'ConduitAPI_chatlog_query_Method' => 'ConduitAPI_chatlog_Method',
     'ConduitAPI_chatlog_record_Method' => 'ConduitAPI_chatlog_Method',
     'ConduitAPI_conduit_connect_Method' => 'ConduitAPIMethod',
     'ConduitAPI_conduit_getcertificate_Method' => 'ConduitAPIMethod',
     'ConduitAPI_conduit_ping_Method' => 'ConduitAPIMethod',
     'ConduitAPI_daemon_launched_Method' => 'ConduitAPIMethod',
     'ConduitAPI_daemon_log_Method' => 'ConduitAPIMethod',
     'ConduitAPI_differential_close_Method' => 'ConduitAPIMethod',
     'ConduitAPI_differential_createcomment_Method' => 'ConduitAPIMethod',
     'ConduitAPI_differential_creatediff_Method' => 'ConduitAPIMethod',
     'ConduitAPI_differential_createrevision_Method' => 'ConduitAPIMethod',
     'ConduitAPI_differential_find_Method' => 'ConduitAPIMethod',
     'ConduitAPI_differential_getalldiffs_Method' => 'ConduitAPIMethod',
     'ConduitAPI_differential_getcommitmessage_Method' => 'ConduitAPIMethod',
     'ConduitAPI_differential_getcommitpaths_Method' => 'ConduitAPIMethod',
     'ConduitAPI_differential_getdiff_Method' => 'ConduitAPIMethod',
     'ConduitAPI_differential_getrevision_Method' => 'ConduitAPIMethod',
     'ConduitAPI_differential_getrevisioncomments_Method' => 'ConduitAPIMethod',
     'ConduitAPI_differential_getrevisionfeedback_Method' => 'ConduitAPIMethod',
     'ConduitAPI_differential_markcommitted_Method' => 'ConduitAPIMethod',
     'ConduitAPI_differential_parsecommitmessage_Method' => 'ConduitAPIMethod',
     'ConduitAPI_differential_query_Method' => 'ConduitAPIMethod',
     'ConduitAPI_differential_setdiffproperty_Method' => 'ConduitAPIMethod',
     'ConduitAPI_differential_updaterevision_Method' => 'ConduitAPIMethod',
     'ConduitAPI_differential_updatetaskrevisionassoc_Method' => 'ConduitAPIMethod',
     'ConduitAPI_differential_updateunitresults_Method' => 'ConduitAPIMethod',
     'ConduitAPI_diffusion_findsymbols_Method' => 'ConduitAPIMethod',
     'ConduitAPI_diffusion_getcommits_Method' => 'ConduitAPIMethod',
     'ConduitAPI_diffusion_getrecentcommitsbypath_Method' => 'ConduitAPIMethod',
     'ConduitAPI_feed_publish_Method' => 'ConduitAPIMethod',
     'ConduitAPI_feed_query_Method' => 'ConduitAPIMethod',
     'ConduitAPI_file_download_Method' => 'ConduitAPIMethod',
     'ConduitAPI_file_info_Method' => 'ConduitAPIMethod',
     'ConduitAPI_file_upload_Method' => 'ConduitAPIMethod',
     'ConduitAPI_flag_Method' => 'ConduitAPIMethod',
     'ConduitAPI_flag_query_Method' => 'ConduitAPI_flag_Method',
     'ConduitAPI_macro_Method' => 'ConduitAPIMethod',
     'ConduitAPI_macro_query_Method' => 'ConduitAPI_macro_Method',
     'ConduitAPI_maniphest_Method' => 'ConduitAPIMethod',
     'ConduitAPI_maniphest_createtask_Method' => 'ConduitAPI_maniphest_Method',
     'ConduitAPI_maniphest_find_Method' => 'ConduitAPI_maniphest_Method',
     'ConduitAPI_maniphest_gettasktransactions_Method' => 'ConduitAPI_maniphest_Method',
     'ConduitAPI_maniphest_info_Method' => 'ConduitAPI_maniphest_Method',
     'ConduitAPI_maniphest_update_Method' => 'ConduitAPI_maniphest_Method',
     'ConduitAPI_paste_Method' => 'ConduitAPIMethod',
     'ConduitAPI_paste_create_Method' => 'ConduitAPI_paste_Method',
     'ConduitAPI_paste_info_Method' => 'ConduitAPI_paste_Method',
     'ConduitAPI_path_getowners_Method' => 'ConduitAPIMethod',
     'ConduitAPI_phid_Method' => 'ConduitAPIMethod',
     'ConduitAPI_phid_info_Method' => 'ConduitAPI_phid_Method',
     'ConduitAPI_phid_query_Method' => 'ConduitAPI_phid_Method',
     'ConduitAPI_phriction_Method' => 'ConduitAPIMethod',
     'ConduitAPI_phriction_edit_Method' => 'ConduitAPI_phriction_Method',
     'ConduitAPI_phriction_history_Method' => 'ConduitAPI_phriction_Method',
     'ConduitAPI_phriction_info_Method' => 'ConduitAPI_phriction_Method',
     'ConduitAPI_project_Method' => 'ConduitAPIMethod',
     'ConduitAPI_project_query_Method' => 'ConduitAPI_project_Method',
     'ConduitAPI_remarkup_process_Method' => 'ConduitAPIMethod',
     'ConduitAPI_slowvote_info_Method' => 'ConduitAPIMethod',
     'ConduitAPI_user_Method' => 'ConduitAPIMethod',
     'ConduitAPI_user_find_Method' => 'ConduitAPI_user_Method',
     'ConduitAPI_user_info_Method' => 'ConduitAPI_user_Method',
     'ConduitAPI_user_whoami_Method' => 'ConduitAPI_user_Method',
     'DarkConsoleConfigPlugin' => 'DarkConsolePlugin',
     'DarkConsoleController' => 'PhabricatorController',
     'DarkConsoleErrorLogPlugin' => 'DarkConsolePlugin',
     'DarkConsoleEventPlugin' => 'DarkConsolePlugin',
     'DarkConsoleEventPluginAPI' => 'PhutilEventListener',
     'DarkConsoleRequestPlugin' => 'DarkConsolePlugin',
     'DarkConsoleServicesPlugin' => 'DarkConsolePlugin',
     'DarkConsoleXHProfPlugin' => 'DarkConsolePlugin',
     'DifferentialActionHasNoEffectException' => 'DifferentialException',
     'DifferentialAddCommentView' => 'AphrontView',
     'DifferentialAffectedPath' => 'DifferentialDAO',
     'DifferentialApplyPatchFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialArcanistProjectFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialAuditorsFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialAuthorFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialAuxiliaryField' => 'DifferentialDAO',
     'DifferentialBlameRevisionFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialBranchFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialCCWelcomeMail' => 'DifferentialReviewRequestMail',
     'DifferentialCCsFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialChangeset' => 'DifferentialDAO',
     'DifferentialChangesetDetailView' => 'AphrontView',
     'DifferentialChangesetListView' => 'AphrontView',
     'DifferentialChangesetViewController' => 'DifferentialController',
     'DifferentialComment' => 'DifferentialDAO',
     'DifferentialCommentMail' => 'DifferentialMail',
     'DifferentialCommentPreviewController' => 'DifferentialController',
     'DifferentialCommentSaveController' => 'DifferentialController',
     'DifferentialCommitsFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialController' => 'PhabricatorController',
     'DifferentialDAO' => 'PhabricatorLiskDAO',
     'DifferentialDateCreatedFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialDateModifiedFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialDefaultFieldSelector' => 'DifferentialFieldSelector',
     'DifferentialDependenciesFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialDiff' => 'DifferentialDAO',
     'DifferentialDiffContentMail' => 'DifferentialMail',
     'DifferentialDiffCreateController' => 'DifferentialController',
     'DifferentialDiffProperty' => 'DifferentialDAO',
     'DifferentialDiffTableOfContentsView' => 'AphrontView',
     'DifferentialDiffViewController' => 'DifferentialController',
     'DifferentialExceptionMail' => 'DifferentialMail',
     'DifferentialExportPatchFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialGitSVNIDFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialHostFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialHunk' => 'DifferentialDAO',
     'DifferentialInlineComment' => 'DifferentialDAO',
     'DifferentialInlineCommentEditController' => 'PhabricatorInlineCommentController',
     'DifferentialInlineCommentEditView' => 'AphrontView',
     'DifferentialInlineCommentPreviewController' => 'DifferentialController',
     'DifferentialInlineCommentView' => 'AphrontView',
     'DifferentialLinesFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialLintFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialLocalCommitsView' => 'AphrontView',
     'DifferentialManiphestTasksFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialNewDiffMail' => 'DifferentialReviewRequestMail',
     'DifferentialPathFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialPrimaryPaneView' => 'AphrontView',
     'DifferentialReplyHandler' => 'PhabricatorMailReplyHandler',
     'DifferentialRevertPlanFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialReviewRequestMail' => 'DifferentialMail',
     'DifferentialReviewedByFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialReviewersFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialRevision' => 'DifferentialDAO',
     'DifferentialRevisionCommentListView' => 'AphrontView',
     'DifferentialRevisionCommentView' => 'AphrontView',
     'DifferentialRevisionDetailView' => 'AphrontView',
     'DifferentialRevisionEditController' => 'DifferentialController',
     'DifferentialRevisionIDFieldParserTestCase' => 'PhabricatorTestCase',
     'DifferentialRevisionIDFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialRevisionListController' => 'DifferentialController',
     'DifferentialRevisionListView' => 'AphrontView',
     'DifferentialRevisionStatsController' => 'DifferentialController',
     'DifferentialRevisionStatsView' => 'AphrontView',
     'DifferentialRevisionStatusFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialRevisionUpdateHistoryView' => 'AphrontView',
     'DifferentialRevisionViewController' => 'DifferentialController',
     'DifferentialSubscribeController' => 'DifferentialController',
     'DifferentialSummaryFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialTestPlanFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialTitleFieldSpecification' => 'DifferentialFieldSpecification',
     'DifferentialUnitFieldSpecification' => 'DifferentialFieldSpecification',
     'DiffusionBranchTableView' => 'DiffusionView',
     'DiffusionBrowseController' => 'DiffusionController',
     'DiffusionBrowseFileController' => 'DiffusionController',
     'DiffusionBrowseTableView' => 'DiffusionView',
     'DiffusionChangeController' => 'DiffusionController',
     'DiffusionCommentListView' => 'AphrontView',
     'DiffusionCommentView' => 'AphrontView',
     'DiffusionCommitChangeTableView' => 'DiffusionView',
     'DiffusionCommitController' => 'DiffusionController',
     'DiffusionCommitParentsQuery' => 'DiffusionQuery',
     'DiffusionCommitTagsQuery' => 'DiffusionQuery',
     'DiffusionContainsQuery' => 'DiffusionQuery',
     'DiffusionController' => 'PhabricatorController',
     'DiffusionDiffController' => 'DiffusionController',
     'DiffusionDiffQuery' => 'DiffusionQuery',
     'DiffusionEmptyResultView' => 'DiffusionView',
     'DiffusionExternalController' => 'DiffusionController',
     'DiffusionFileContentQuery' => 'DiffusionQuery',
     'DiffusionGitBranchQuery' => 'DiffusionBranchQuery',
     'DiffusionGitBranchQueryTestCase' => 'PhabricatorTestCase',
     'DiffusionGitBrowseQuery' => 'DiffusionBrowseQuery',
     'DiffusionGitCommitParentsQuery' => 'DiffusionCommitParentsQuery',
     'DiffusionGitCommitTagsQuery' => 'DiffusionCommitTagsQuery',
     'DiffusionGitContainsQuery' => 'DiffusionContainsQuery',
     'DiffusionGitDiffQuery' => 'DiffusionDiffQuery',
     'DiffusionGitFileContentQuery' => 'DiffusionFileContentQuery',
     'DiffusionGitHistoryQuery' => 'DiffusionHistoryQuery',
     'DiffusionGitLastModifiedQuery' => 'DiffusionLastModifiedQuery',
     'DiffusionGitMergedCommitsQuery' => 'DiffusionMergedCommitsQuery',
     'DiffusionGitRenameHistoryQuery' => 'DiffusionRenameHistoryQuery',
     'DiffusionGitRequest' => 'DiffusionRequest',
     'DiffusionGitTagListQuery' => 'DiffusionTagListQuery',
     'DiffusionHistoryController' => 'DiffusionController',
     'DiffusionHistoryQuery' => 'DiffusionQuery',
     'DiffusionHistoryTableView' => 'DiffusionView',
     'DiffusionHomeController' => 'DiffusionController',
     'DiffusionInlineCommentController' => 'PhabricatorInlineCommentController',
     'DiffusionLastModifiedController' => 'DiffusionController',
     'DiffusionLastModifiedQuery' => 'DiffusionQuery',
     'DiffusionMercurialBranchQuery' => 'DiffusionBranchQuery',
     'DiffusionMercurialBrowseQuery' => 'DiffusionBrowseQuery',
     'DiffusionMercurialCommitParentsQuery' => 'DiffusionCommitParentsQuery',
     'DiffusionMercurialCommitTagsQuery' => 'DiffusionCommitTagsQuery',
     'DiffusionMercurialContainsQuery' => 'DiffusionContainsQuery',
     'DiffusionMercurialDiffQuery' => 'DiffusionDiffQuery',
     'DiffusionMercurialFileContentQuery' => 'DiffusionFileContentQuery',
     'DiffusionMercurialHistoryQuery' => 'DiffusionHistoryQuery',
     'DiffusionMercurialLastModifiedQuery' => 'DiffusionLastModifiedQuery',
     'DiffusionMercurialMergedCommitsQuery' => 'DiffusionMergedCommitsQuery',
     'DiffusionMercurialRenameHistoryQuery' => 'DiffusionRenameHistoryQuery',
     'DiffusionMercurialRequest' => 'DiffusionRequest',
     'DiffusionMercurialTagListQuery' => 'DiffusionTagListQuery',
     'DiffusionMergedCommitsQuery' => 'DiffusionQuery',
     'DiffusionPathCompleteController' => 'DiffusionController',
     'DiffusionPathQueryTestCase' => 'PhabricatorTestCase',
     'DiffusionPathValidateController' => 'DiffusionController',
     'DiffusionRenameHistoryQuery' => 'DiffusionQuery',
     'DiffusionRepositoryController' => 'DiffusionController',
     'DiffusionSvnBrowseQuery' => 'DiffusionBrowseQuery',
     'DiffusionSvnCommitParentsQuery' => 'DiffusionCommitParentsQuery',
     'DiffusionSvnCommitTagsQuery' => 'DiffusionCommitTagsQuery',
     'DiffusionSvnContainsQuery' => 'DiffusionContainsQuery',
     'DiffusionSvnDiffQuery' => 'DiffusionDiffQuery',
     'DiffusionSvnFileContentQuery' => 'DiffusionFileContentQuery',
     'DiffusionSvnHistoryQuery' => 'DiffusionHistoryQuery',
     'DiffusionSvnLastModifiedQuery' => 'DiffusionLastModifiedQuery',
     'DiffusionSvnMergedCommitsQuery' => 'DiffusionMergedCommitsQuery',
     'DiffusionSvnRenameHistoryQuery' => 'DiffusionRenameHistoryQuery',
     'DiffusionSvnRequest' => 'DiffusionRequest',
     'DiffusionSvnTagListQuery' => 'DiffusionTagListQuery',
     'DiffusionSymbolController' => 'DiffusionController',
     'DiffusionTagListController' => 'DiffusionController',
     'DiffusionTagListQuery' => 'DiffusionQuery',
     'DiffusionTagListView' => 'DiffusionView',
     'DiffusionURITestCase' => 'ArcanistPhutilTestCase',
     'DiffusionView' => 'AphrontView',
     'DrydockAllocatorWorker' => 'PhabricatorWorker',
     'DrydockApacheWebrootBlueprint' => 'DrydockBlueprint',
     'DrydockApacheWebrootInterface' => 'DrydockWebrootInterface',
     'DrydockCommandInterface' => 'DrydockInterface',
     'DrydockController' => 'PhabricatorController',
     'DrydockDAO' => 'PhabricatorLiskDAO',
     'DrydockEC2HostBlueprint' => 'DrydockRemoteHostBlueprint',
     'DrydockLease' => 'DrydockDAO',
     'DrydockLeaseListController' => 'DrydockController',
     'DrydockLeaseStatus' => 'DrydockConstants',
     'DrydockLocalCommandInterface' => 'DrydockCommandInterface',
     'DrydockLocalHostBlueprint' => 'DrydockBlueprint',
     'DrydockLog' => 'DrydockDAO',
     'DrydockLogController' => 'DrydockController',
     'DrydockLogQuery' => 'PhabricatorOffsetPagedQuery',
     'DrydockPhabricatorApplicationBlueprint' => 'DrydockBlueprint',
     'DrydockRemoteHostBlueprint' => 'DrydockBlueprint',
     'DrydockResource' => 'DrydockDAO',
     'DrydockResourceAllocateController' => 'DrydockController',
     'DrydockResourceListController' => 'DrydockController',
     'DrydockResourceStatus' => 'DrydockConstants',
     'DrydockSSHCommandInterface' => 'DrydockCommandInterface',
     'DrydockWebrootInterface' => 'DrydockInterface',
     'HeraldAction' => 'HeraldDAO',
     'HeraldApplyTranscript' => 'HeraldDAO',
     'HeraldCommitAdapter' => 'HeraldObjectAdapter',
     'HeraldCondition' => 'HeraldDAO',
     'HeraldController' => 'PhabricatorController',
     'HeraldDAO' => 'PhabricatorLiskDAO',
     'HeraldDeleteController' => 'HeraldController',
     'HeraldDifferentialRevisionAdapter' => 'HeraldObjectAdapter',
     'HeraldDryRunAdapter' => 'HeraldObjectAdapter',
     'HeraldEditLogQuery' => 'PhabricatorOffsetPagedQuery',
     'HeraldHomeController' => 'HeraldController',
     'HeraldNewController' => 'HeraldController',
     'HeraldRule' => 'HeraldDAO',
     'HeraldRuleController' => 'HeraldController',
     'HeraldRuleEdit' => 'HeraldDAO',
     'HeraldRuleEditHistoryController' => 'HeraldController',
     'HeraldRuleEditHistoryView' => 'AphrontView',
     'HeraldRuleListView' => 'AphrontView',
     'HeraldRuleQuery' => 'PhabricatorOffsetPagedQuery',
     'HeraldTestConsoleController' => 'HeraldController',
     'HeraldTranscript' => 'HeraldDAO',
     'HeraldTranscriptController' => 'HeraldController',
     'HeraldTranscriptListController' => 'HeraldController',
     'JavelinReactorExample' => 'PhabricatorUIExample',
     'JavelinViewExample' => 'PhabricatorUIExample',
     'JavelinViewExampleServerView' => 'AphrontView',
     'LiskIsolationTestCase' => 'PhabricatorTestCase',
     'LiskIsolationTestDAO' => 'LiskDAO',
     'ManiphestAction' => 'PhrictionConstants',
     'ManiphestAuxiliaryFieldDefaultSpecification' => 'ManiphestAuxiliaryFieldSpecification',
     'ManiphestBatchEditController' => 'ManiphestController',
     'ManiphestController' => 'PhabricatorController',
     'ManiphestDAO' => 'PhabricatorLiskDAO',
     'ManiphestDefaultTaskExtensions' => 'ManiphestTaskExtensions',
     'ManiphestExportController' => 'ManiphestController',
     'ManiphestReplyHandler' => 'PhabricatorMailReplyHandler',
     'ManiphestReportController' => 'ManiphestController',
     'ManiphestSavedQuery' => 'ManiphestDAO',
     'ManiphestSavedQueryDeleteController' => 'ManiphestController',
     'ManiphestSavedQueryEditController' => 'ManiphestController',
     'ManiphestSavedQueryListController' => 'ManiphestController',
     'ManiphestSubpriorityController' => 'ManiphestController',
     'ManiphestTask' => 'ManiphestDAO',
     'ManiphestTaskAuxiliaryStorage' => 'ManiphestDAO',
     'ManiphestTaskDescriptionChangeController' => 'ManiphestController',
     'ManiphestTaskDescriptionPreviewController' => 'ManiphestController',
     'ManiphestTaskDetailController' => 'ManiphestController',
     'ManiphestTaskEditController' => 'ManiphestController',
     'ManiphestTaskListController' => 'ManiphestController',
     'ManiphestTaskListView' => 'ManiphestView',
     'ManiphestTaskOwner' => 'ManiphestConstants',
     'ManiphestTaskPriority' => 'ManiphestConstants',
     'ManiphestTaskProject' => 'ManiphestDAO',
     'ManiphestTaskProjectsView' => 'ManiphestView',
     'ManiphestTaskStatus' => 'ManiphestConstants',
     'ManiphestTaskSubscriber' => 'ManiphestDAO',
     'ManiphestTaskSummaryView' => 'ManiphestView',
     'ManiphestTransaction' => 'ManiphestDAO',
     'ManiphestTransactionDetailView' => 'ManiphestView',
     'ManiphestTransactionListView' => 'ManiphestView',
     'ManiphestTransactionPreviewController' => 'ManiphestController',
     'ManiphestTransactionSaveController' => 'ManiphestController',
     'ManiphestTransactionType' => 'ManiphestConstants',
     'ManiphestView' => 'AphrontView',
     'MetaMTANotificationType' => 'MetaMTAConstants',
     'Phabricator404Controller' => 'PhabricatorController',
     'PhabricatorAphlictTestPageController' => 'PhabricatorNotificationsController',
     'PhabricatorAuditAddCommentController' => 'PhabricatorAuditController',
     'PhabricatorAuditComment' => 'PhabricatorAuditDAO',
     'PhabricatorAuditCommitListView' => 'AphrontView',
     'PhabricatorAuditController' => 'PhabricatorController',
     'PhabricatorAuditDAO' => 'PhabricatorLiskDAO',
     'PhabricatorAuditInlineComment' => 'PhabricatorAuditDAO',
     'PhabricatorAuditListController' => 'PhabricatorAuditController',
     'PhabricatorAuditListView' => 'AphrontView',
     'PhabricatorAuditPreviewController' => 'PhabricatorAuditController',
     'PhabricatorAuditReplyHandler' => 'PhabricatorMailReplyHandler',
     'PhabricatorAuthController' => 'PhabricatorController',
+    'PhabricatorBuiltinPatchList' => 'PhabricatorSQLPatchList',
     'PhabricatorCalendarBrowseController' => 'PhabricatorCalendarController',
     'PhabricatorCalendarController' => 'PhabricatorController',
     'PhabricatorChangesetResponse' => 'AphrontProxyResponse',
     'PhabricatorChatLogChannelListController' => 'PhabricatorChatLogController',
     'PhabricatorChatLogChannelLogController' => 'PhabricatorChatLogController',
     'PhabricatorChatLogController' => 'PhabricatorController',
     'PhabricatorChatLogDAO' => 'PhabricatorLiskDAO',
     'PhabricatorChatLogEvent' => 'PhabricatorChatLogDAO',
     'PhabricatorChatLogEventType' => 'PhabricatorChatLogConstants',
     'PhabricatorChatLogQuery' => 'PhabricatorOffsetPagedQuery',
     'PhabricatorConduitAPIController' => 'PhabricatorConduitController',
     'PhabricatorConduitCertificateToken' => 'PhabricatorConduitDAO',
     'PhabricatorConduitConnectionLog' => 'PhabricatorConduitDAO',
     'PhabricatorConduitConsoleController' => 'PhabricatorConduitController',
     'PhabricatorConduitController' => 'PhabricatorController',
     'PhabricatorConduitDAO' => 'PhabricatorLiskDAO',
     'PhabricatorConduitListController' => 'PhabricatorConduitController',
     'PhabricatorConduitLogController' => 'PhabricatorConduitController',
     'PhabricatorConduitMethodCallLog' => 'PhabricatorConduitDAO',
     'PhabricatorConduitTokenController' => 'PhabricatorConduitController',
     'PhabricatorContentSourceView' => 'AphrontView',
     'PhabricatorController' => 'AphrontController',
     'PhabricatorCountdownController' => 'PhabricatorController',
     'PhabricatorCountdownDAO' => 'PhabricatorLiskDAO',
     'PhabricatorCountdownDeleteController' => 'PhabricatorCountdownController',
     'PhabricatorCountdownEditController' => 'PhabricatorCountdownController',
     'PhabricatorCountdownListController' => 'PhabricatorCountdownController',
     'PhabricatorCountdownViewController' => 'PhabricatorCountdownController',
     'PhabricatorDaemon' => 'PhutilDaemon',
     'PhabricatorDaemonCombinedLogController' => 'PhabricatorDaemonController',
     'PhabricatorDaemonConsoleController' => 'PhabricatorDaemonController',
     'PhabricatorDaemonController' => 'PhabricatorController',
     'PhabricatorDaemonDAO' => 'PhabricatorLiskDAO',
     'PhabricatorDaemonLog' => 'PhabricatorDaemonDAO',
     'PhabricatorDaemonLogEvent' => 'PhabricatorDaemonDAO',
     'PhabricatorDaemonLogEventsView' => 'AphrontView',
     'PhabricatorDaemonLogListController' => 'PhabricatorDaemonController',
     'PhabricatorDaemonLogListView' => 'AphrontView',
     'PhabricatorDaemonLogViewController' => 'PhabricatorDaemonController',
     'PhabricatorDaemonTimelineConsoleController' => 'PhabricatorDaemonController',
     'PhabricatorDaemonTimelineEventController' => 'PhabricatorDaemonController',
     'PhabricatorDefaultFileStorageEngineSelector' => 'PhabricatorFileStorageEngineSelector',
     'PhabricatorDefaultSearchEngineSelector' => 'PhabricatorSearchEngineSelector',
     'PhabricatorDirectoryController' => 'PhabricatorController',
     'PhabricatorDirectoryMainController' => 'PhabricatorController',
     'PhabricatorDisabledUserController' => 'PhabricatorAuthController',
     'PhabricatorDraft' => 'PhabricatorDraftDAO',
     'PhabricatorDraftDAO' => 'PhabricatorLiskDAO',
     'PhabricatorEdgeConfig' => 'PhabricatorEdgeConstants',
     'PhabricatorEdgeQuery' => 'PhabricatorQuery',
     'PhabricatorEmailLoginController' => 'PhabricatorAuthController',
     'PhabricatorEmailTokenController' => 'PhabricatorAuthController',
     'PhabricatorEnvTestCase' => 'PhabricatorTestCase',
     'PhabricatorErrorExample' => 'PhabricatorUIExample',
     'PhabricatorEvent' => 'PhutilEvent',
     'PhabricatorEventType' => 'PhutilEventType',
     'PhabricatorFeedController' => 'PhabricatorController',
     'PhabricatorFeedDAO' => 'PhabricatorLiskDAO',
     'PhabricatorFeedPublicStreamController' => 'PhabricatorFeedController',
     'PhabricatorFeedStoryAudit' => 'PhabricatorFeedStory',
     'PhabricatorFeedStoryData' => 'PhabricatorFeedDAO',
     'PhabricatorFeedStoryDifferential' => 'PhabricatorFeedStory',
     'PhabricatorFeedStoryManiphest' => 'PhabricatorFeedStory',
     'PhabricatorFeedStoryPhriction' => 'PhabricatorFeedStory',
     'PhabricatorFeedStoryProject' => 'PhabricatorFeedStory',
     'PhabricatorFeedStoryReference' => 'PhabricatorFeedDAO',
     'PhabricatorFeedStoryStatus' => 'PhabricatorFeedStory',
     'PhabricatorFeedStoryTypeConstants' => 'PhabricatorFeedConstants',
     'PhabricatorFeedStoryUnknown' => 'PhabricatorFeedStory',
     'PhabricatorFeedStoryView' => 'PhabricatorFeedView',
     'PhabricatorFeedView' => 'AphrontView',
     'PhabricatorFile' => 'PhabricatorFileDAO',
     'PhabricatorFileController' => 'PhabricatorController',
     'PhabricatorFileDAO' => 'PhabricatorLiskDAO',
     'PhabricatorFileDataController' => 'PhabricatorFileController',
     'PhabricatorFileDeleteController' => 'PhabricatorFileController',
     'PhabricatorFileDropUploadController' => 'PhabricatorFileController',
     'PhabricatorFileImageMacro' => 'PhabricatorFileDAO',
     'PhabricatorFileInfoController' => 'PhabricatorFileController',
     'PhabricatorFileListController' => 'PhabricatorFileController',
     'PhabricatorFileMacroDeleteController' => 'PhabricatorFileController',
     'PhabricatorFileMacroEditController' => 'PhabricatorFileController',
     'PhabricatorFileMacroListController' => 'PhabricatorFileController',
     'PhabricatorFileProxyController' => 'PhabricatorFileController',
     'PhabricatorFileProxyImage' => 'PhabricatorFileDAO',
     'PhabricatorFileSideNavView' => 'AphrontView',
     'PhabricatorFileStorageBlob' => 'PhabricatorFileDAO',
     'PhabricatorFileTransformController' => 'PhabricatorFileController',
     'PhabricatorFileUploadController' => 'PhabricatorFileController',
     'PhabricatorFileUploadView' => 'AphrontView',
     'PhabricatorFlag' => 'PhabricatorFlagDAO',
     'PhabricatorFlagColor' => 'PhabricatorFlagConstants',
     'PhabricatorFlagController' => 'PhabricatorController',
     'PhabricatorFlagDAO' => 'PhabricatorLiskDAO',
     'PhabricatorFlagDeleteController' => 'PhabricatorFlagController',
     'PhabricatorFlagEditController' => 'PhabricatorFlagController',
     'PhabricatorFlagListController' => 'PhabricatorFlagController',
     'PhabricatorFlagListView' => 'AphrontView',
     'PhabricatorFormExample' => 'PhabricatorUIExample',
     'PhabricatorGarbageCollectorDaemon' => 'PhabricatorDaemon',
     'PhabricatorGoodForNothingWorker' => 'PhabricatorWorker',
     'PhabricatorHelpController' => 'PhabricatorController',
     'PhabricatorHelpKeyboardShortcutController' => 'PhabricatorHelpController',
     'PhabricatorIDPagedPolicyQuery' => 'PhabricatorPolicyQuery',
     'PhabricatorIRCBot' => 'PhabricatorDaemon',
     'PhabricatorIRCDifferentialNotificationHandler' => 'PhabricatorIRCHandler',
     'PhabricatorIRCLogHandler' => 'PhabricatorIRCHandler',
     'PhabricatorIRCMacroHandler' => 'PhabricatorIRCHandler',
     'PhabricatorIRCObjectNameHandler' => 'PhabricatorIRCHandler',
     'PhabricatorIRCProtocolHandler' => 'PhabricatorIRCHandler',
     'PhabricatorIRCWhatsNewHandler' => 'PhabricatorIRCHandler',
     'PhabricatorInfrastructureTestCase' => 'PhabricatorTestCase',
     'PhabricatorInlineCommentController' => 'PhabricatorController',
     'PhabricatorInlineSummaryView' => 'AphrontView',
     'PhabricatorJavelinLinter' => 'ArcanistLinter',
     'PhabricatorLintEngine' => 'PhutilLintEngine',
     'PhabricatorLiskDAO' => 'LiskDAO',
     'PhabricatorLocalDiskFileStorageEngine' => 'PhabricatorFileStorageEngine',
     'PhabricatorLocalTimeTestCase' => 'PhabricatorTestCase',
     'PhabricatorLoginController' => 'PhabricatorAuthController',
     'PhabricatorLoginValidateController' => 'PhabricatorAuthController',
     'PhabricatorLogoutController' => 'PhabricatorAuthController',
     'PhabricatorMailImplementationAmazonSESAdapter' => 'PhabricatorMailImplementationPHPMailerLiteAdapter',
     'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter',
     'PhabricatorMailImplementationSendGridAdapter' => 'PhabricatorMailImplementationAdapter',
     'PhabricatorMailImplementationTestAdapter' => 'PhabricatorMailImplementationAdapter',
     'PhabricatorMetaMTAController' => 'PhabricatorController',
     'PhabricatorMetaMTADAO' => 'PhabricatorLiskDAO',
     'PhabricatorMetaMTAEmailBodyParserTestCase' => 'PhabricatorTestCase',
     'PhabricatorMetaMTAListController' => 'PhabricatorMetaMTAController',
     'PhabricatorMetaMTAMail' => 'PhabricatorMetaMTADAO',
     'PhabricatorMetaMTAMailTestCase' => 'PhabricatorTestCase',
     'PhabricatorMetaMTAMailingList' => 'PhabricatorMetaMTADAO',
     'PhabricatorMetaMTAMailingListEditController' => 'PhabricatorMetaMTAController',
     'PhabricatorMetaMTAMailingListsController' => 'PhabricatorMetaMTAController',
     'PhabricatorMetaMTAReceiveController' => 'PhabricatorMetaMTAController',
     'PhabricatorMetaMTAReceivedListController' => 'PhabricatorMetaMTAController',
     'PhabricatorMetaMTAReceivedMail' => 'PhabricatorMetaMTADAO',
     'PhabricatorMetaMTASendController' => 'PhabricatorMetaMTAController',
     'PhabricatorMetaMTASendGridReceiveController' => 'PhabricatorMetaMTAController',
     'PhabricatorMetaMTAViewController' => 'PhabricatorMetaMTAController',
     'PhabricatorMetaMTAWorker' => 'PhabricatorWorker',
     'PhabricatorMySQLFileStorageEngine' => 'PhabricatorFileStorageEngine',
     'PhabricatorNotificationsController' => 'PhabricatorController',
     'PhabricatorOAuthClientAuthorization' => 'PhabricatorOAuthServerDAO',
     'PhabricatorOAuthClientAuthorizationBaseController' => 'PhabricatorOAuthServerController',
     'PhabricatorOAuthClientAuthorizationDeleteController' => 'PhabricatorOAuthClientAuthorizationBaseController',
     'PhabricatorOAuthClientAuthorizationEditController' => 'PhabricatorOAuthClientAuthorizationBaseController',
     'PhabricatorOAuthClientAuthorizationListController' => 'PhabricatorOAuthClientAuthorizationBaseController',
     'PhabricatorOAuthClientAuthorizationQuery' => 'PhabricatorOffsetPagedQuery',
     'PhabricatorOAuthClientBaseController' => 'PhabricatorOAuthServerController',
     'PhabricatorOAuthClientDeleteController' => 'PhabricatorOAuthClientBaseController',
     'PhabricatorOAuthClientEditController' => 'PhabricatorOAuthClientBaseController',
     'PhabricatorOAuthClientListController' => 'PhabricatorOAuthClientBaseController',
     'PhabricatorOAuthClientViewController' => 'PhabricatorOAuthClientBaseController',
     'PhabricatorOAuthDefaultRegistrationController' => 'PhabricatorOAuthRegistrationController',
     'PhabricatorOAuthDiagnosticsController' => 'PhabricatorAuthController',
     'PhabricatorOAuthFailureView' => 'AphrontView',
     'PhabricatorOAuthLoginController' => 'PhabricatorAuthController',
     'PhabricatorOAuthProviderFacebook' => 'PhabricatorOAuthProvider',
     'PhabricatorOAuthProviderGitHub' => 'PhabricatorOAuthProvider',
     'PhabricatorOAuthProviderGoogle' => 'PhabricatorOAuthProvider',
     'PhabricatorOAuthProviderPhabricator' => 'PhabricatorOAuthProvider',
     'PhabricatorOAuthRegistrationController' => 'PhabricatorAuthController',
     'PhabricatorOAuthResponse' => 'AphrontResponse',
     'PhabricatorOAuthServerAccessToken' => 'PhabricatorOAuthServerDAO',
     'PhabricatorOAuthServerAuthController' => 'PhabricatorAuthController',
     'PhabricatorOAuthServerAuthorizationCode' => 'PhabricatorOAuthServerDAO',
     'PhabricatorOAuthServerClient' => 'PhabricatorOAuthServerDAO',
     'PhabricatorOAuthServerClientQuery' => 'PhabricatorOffsetPagedQuery',
     'PhabricatorOAuthServerController' => 'PhabricatorController',
     'PhabricatorOAuthServerDAO' => 'PhabricatorLiskDAO',
     'PhabricatorOAuthServerTestCase' => 'PhabricatorTestCase',
     'PhabricatorOAuthServerTestController' => 'PhabricatorOAuthServerController',
     'PhabricatorOAuthServerTokenController' => 'PhabricatorAuthController',
     'PhabricatorOAuthUnlinkController' => 'PhabricatorAuthController',
     'PhabricatorObjectGraph' => 'AbstractDirectedGraph',
     'PhabricatorObjectHandleStatus' => 'PhabricatorObjectHandleConstants',
     'PhabricatorOffsetPagedQuery' => 'PhabricatorQuery',
     'PhabricatorOwnersController' => 'PhabricatorController',
     'PhabricatorOwnersDAO' => 'PhabricatorLiskDAO',
     'PhabricatorOwnersDeleteController' => 'PhabricatorOwnersController',
     'PhabricatorOwnersDetailController' => 'PhabricatorOwnersController',
     'PhabricatorOwnersEditController' => 'PhabricatorOwnersController',
     'PhabricatorOwnersListController' => 'PhabricatorOwnersController',
     'PhabricatorOwnersOwner' => 'PhabricatorOwnersDAO',
     'PhabricatorOwnersPackage' => 'PhabricatorOwnersDAO',
     'PhabricatorOwnersPath' => 'PhabricatorOwnersDAO',
     'PhabricatorPHID' => 'PhabricatorPHIDDAO',
     'PhabricatorPHIDController' => 'PhabricatorController',
     'PhabricatorPHIDDAO' => 'PhabricatorLiskDAO',
     'PhabricatorPHIDLookupController' => 'PhabricatorPHIDController',
     'PhabricatorPaste' => 'PhabricatorPasteDAO',
     'PhabricatorPasteController' => 'PhabricatorController',
     'PhabricatorPasteDAO' => 'PhabricatorLiskDAO',
     'PhabricatorPasteListController' => 'PhabricatorPasteController',
     'PhabricatorPasteQuery' => 'PhabricatorIDPagedPolicyQuery',
     'PhabricatorPasteViewController' => 'PhabricatorPasteController',
     'PhabricatorPeopleController' => 'PhabricatorController',
     'PhabricatorPeopleEditController' => 'PhabricatorPeopleController',
     'PhabricatorPeopleListController' => 'PhabricatorPeopleController',
     'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController',
     'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController',
     'PhabricatorPolicies' => 'PhabricatorPolicyConstants',
     'PhabricatorPolicyCapability' => 'PhabricatorPolicyConstants',
     'PhabricatorPolicyQuery' => 'PhabricatorQuery',
     'PhabricatorPolicyTestCase' => 'PhabricatorTestCase',
     'PhabricatorPolicyTestQuery' => 'PhabricatorPolicyQuery',
     'PhabricatorProfileHeaderView' => 'AphrontView',
     'PhabricatorProject' => 'PhabricatorProjectDAO',
     'PhabricatorProjectAffiliation' => 'PhabricatorProjectDAO',
     'PhabricatorProjectController' => 'PhabricatorController',
     'PhabricatorProjectCreateController' => 'PhabricatorProjectController',
     'PhabricatorProjectDAO' => 'PhabricatorLiskDAO',
     'PhabricatorProjectListController' => 'PhabricatorProjectController',
     'PhabricatorProjectProfile' => 'PhabricatorProjectDAO',
     'PhabricatorProjectProfileController' => 'PhabricatorProjectController',
     'PhabricatorProjectProfileEditController' => 'PhabricatorProjectController',
     'PhabricatorProjectSubproject' => 'PhabricatorProjectDAO',
     'PhabricatorProjectTransaction' => 'PhabricatorProjectDAO',
     'PhabricatorProjectTransactionType' => 'PhabricatorProjectConstants',
     'PhabricatorProjectUpdateController' => 'PhabricatorProjectController',
     'PhabricatorRedirectController' => 'PhabricatorController',
     'PhabricatorRefreshCSRFController' => 'PhabricatorAuthController',
     'PhabricatorRemarkupRuleDifferential' => 'PhabricatorRemarkupRuleObjectName',
     'PhabricatorRemarkupRuleDifferentialHandle' => 'PhabricatorRemarkupRuleObjectHandle',
     'PhabricatorRemarkupRuleDiffusion' => 'PhutilRemarkupRule',
     'PhabricatorRemarkupRuleEmbedFile' => 'PhutilRemarkupRule',
     'PhabricatorRemarkupRuleImageMacro' => 'PhutilRemarkupRule',
     'PhabricatorRemarkupRuleManiphest' => 'PhabricatorRemarkupRuleObjectName',
     'PhabricatorRemarkupRuleManiphestHandle' => 'PhabricatorRemarkupRuleObjectHandle',
     'PhabricatorRemarkupRuleMention' => 'PhutilRemarkupRule',
     'PhabricatorRemarkupRuleObjectHandle' => 'PhutilRemarkupRule',
     'PhabricatorRemarkupRuleObjectName' => 'PhutilRemarkupRule',
     'PhabricatorRemarkupRulePaste' => 'PhabricatorRemarkupRuleObjectName',
     'PhabricatorRemarkupRulePhriction' => 'PhutilRemarkupRule',
     'PhabricatorRemarkupRuleProxyImage' => 'PhutilRemarkupRule',
     'PhabricatorRemarkupRuleYoutube' => 'PhutilRemarkupRule',
     'PhabricatorRepository' => 'PhabricatorRepositoryDAO',
     'PhabricatorRepositoryArcanistProject' => 'PhabricatorRepositoryDAO',
     'PhabricatorRepositoryArcanistProjectEditController' => 'PhabricatorRepositoryController',
     'PhabricatorRepositoryAuditRequest' => 'PhabricatorRepositoryDAO',
     'PhabricatorRepositoryCommit' => 'PhabricatorRepositoryDAO',
     'PhabricatorRepositoryCommitChangeParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
     'PhabricatorRepositoryCommitData' => 'PhabricatorRepositoryDAO',
     'PhabricatorRepositoryCommitDiscoveryDaemon' => 'PhabricatorRepositoryDaemon',
     'PhabricatorRepositoryCommitHeraldWorker' => 'PhabricatorRepositoryCommitParserWorker',
     'PhabricatorRepositoryCommitMessageParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
     'PhabricatorRepositoryCommitOwnersWorker' => 'PhabricatorRepositoryCommitParserWorker',
     'PhabricatorRepositoryCommitParserWorker' => 'PhabricatorWorker',
     'PhabricatorRepositoryCommitTaskDaemon' => 'PhabricatorRepositoryDaemon',
     'PhabricatorRepositoryController' => 'PhabricatorController',
     'PhabricatorRepositoryCreateController' => 'PhabricatorRepositoryController',
     'PhabricatorRepositoryDAO' => 'PhabricatorLiskDAO',
     'PhabricatorRepositoryDaemon' => 'PhabricatorDaemon',
     'PhabricatorRepositoryDefaultCommitMessageDetailParser' => 'PhabricatorRepositoryCommitMessageDetailParser',
     'PhabricatorRepositoryDeleteController' => 'PhabricatorRepositoryController',
     'PhabricatorRepositoryEditController' => 'PhabricatorRepositoryController',
     'PhabricatorRepositoryGitCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker',
     'PhabricatorRepositoryGitCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon',
     'PhabricatorRepositoryGitCommitDiscoveryDaemonTestCase' => 'PhabricatorTestCase',
     'PhabricatorRepositoryGitCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
     'PhabricatorRepositoryGitFetchDaemon' => 'PhabricatorRepositoryPullLocalDaemon',
     'PhabricatorRepositoryListController' => 'PhabricatorRepositoryController',
     'PhabricatorRepositoryMercurialCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker',
     'PhabricatorRepositoryMercurialCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon',
     'PhabricatorRepositoryMercurialCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
     'PhabricatorRepositoryMercurialPullDaemon' => 'PhabricatorRepositoryPullLocalDaemon',
     'PhabricatorRepositoryPullLocalDaemon' => 'PhabricatorRepositoryDaemon',
     'PhabricatorRepositoryShortcut' => 'PhabricatorRepositoryDAO',
     'PhabricatorRepositorySvnCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker',
     'PhabricatorRepositorySvnCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon',
     'PhabricatorRepositorySvnCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
     'PhabricatorRepositorySymbol' => 'PhabricatorRepositoryDAO',
     'PhabricatorRepositoryTestCase' => 'PhabricatorTestCase',
     'PhabricatorS3FileStorageEngine' => 'PhabricatorFileStorageEngine',
     'PhabricatorSearchAttachController' => 'PhabricatorSearchBaseController',
     'PhabricatorSearchBaseController' => 'PhabricatorController',
     'PhabricatorSearchCommitIndexer' => 'PhabricatorSearchDocumentIndexer',
     'PhabricatorSearchController' => 'PhabricatorSearchBaseController',
     'PhabricatorSearchDAO' => 'PhabricatorLiskDAO',
     'PhabricatorSearchDifferentialIndexer' => 'PhabricatorSearchDocumentIndexer',
     'PhabricatorSearchDocument' => 'PhabricatorSearchDAO',
     'PhabricatorSearchDocumentField' => 'PhabricatorSearchDAO',
     'PhabricatorSearchDocumentRelationship' => 'PhabricatorSearchDAO',
     'PhabricatorSearchEngineElastic' => 'PhabricatorSearchEngine',
     'PhabricatorSearchEngineMySQL' => 'PhabricatorSearchEngine',
     'PhabricatorSearchIndexController' => 'PhabricatorSearchBaseController',
     'PhabricatorSearchManiphestIndexer' => 'PhabricatorSearchDocumentIndexer',
     'PhabricatorSearchPhrictionIndexer' => 'PhabricatorSearchDocumentIndexer',
     'PhabricatorSearchQuery' => 'PhabricatorSearchDAO',
     'PhabricatorSearchResultView' => 'AphrontView',
     'PhabricatorSearchSelectController' => 'PhabricatorSearchBaseController',
     'PhabricatorSearchUserIndexer' => 'PhabricatorSearchDocumentIndexer',
     'PhabricatorSlowvoteChoice' => 'PhabricatorSlowvoteDAO',
     'PhabricatorSlowvoteComment' => 'PhabricatorSlowvoteDAO',
     'PhabricatorSlowvoteController' => 'PhabricatorController',
     'PhabricatorSlowvoteCreateController' => 'PhabricatorSlowvoteController',
     'PhabricatorSlowvoteDAO' => 'PhabricatorLiskDAO',
     'PhabricatorSlowvoteListController' => 'PhabricatorSlowvoteController',
     'PhabricatorSlowvoteOption' => 'PhabricatorSlowvoteDAO',
     'PhabricatorSlowvotePoll' => 'PhabricatorSlowvoteDAO',
     'PhabricatorSlowvotePollController' => 'PhabricatorSlowvoteController',
     'PhabricatorSlugTestCase' => 'PhabricatorTestCase',
     'PhabricatorSortTableExample' => 'PhabricatorUIExample',
     'PhabricatorStandardPageView' => 'AphrontPageView',
     'PhabricatorStatusController' => 'PhabricatorController',
+    'PhabricatorStorageManagementDatabasesWorkflow' => 'PhabricatorStorageManagementWorkflow',
+    'PhabricatorStorageManagementDestroyWorkflow' => 'PhabricatorStorageManagementWorkflow',
+    'PhabricatorStorageManagementDumpWorkflow' => 'PhabricatorStorageManagementWorkflow',
+    'PhabricatorStorageManagementStatusWorkflow' => 'PhabricatorStorageManagementWorkflow',
+    'PhabricatorStorageManagementUpgradeWorkflow' => 'PhabricatorStorageManagementWorkflow',
+    'PhabricatorStorageManagementWorkflow' => 'PhutilArgumentWorkflow',
     'PhabricatorSymbolNameLinter' => 'ArcanistXHPASTLintNamingHook',
     'PhabricatorTaskmasterDaemon' => 'PhabricatorDaemon',
     'PhabricatorTestCase' => 'ArcanistPhutilTestCase',
     'PhabricatorTimelineCursor' => 'PhabricatorTimelineDAO',
     'PhabricatorTimelineDAO' => 'PhabricatorLiskDAO',
     'PhabricatorTimelineEvent' => 'PhabricatorTimelineDAO',
     'PhabricatorTimelineEventData' => 'PhabricatorTimelineDAO',
     'PhabricatorTimer' => 'PhabricatorCountdownDAO',
     'PhabricatorTransactionView' => 'AphrontView',
     'PhabricatorTransformedFile' => 'PhabricatorFileDAO',
     'PhabricatorTrivialTestCase' => 'PhabricatorTestCase',
     'PhabricatorTypeaheadCommonDatasourceController' => 'PhabricatorTypeaheadDatasourceController',
     'PhabricatorTypeaheadDatasourceController' => 'PhabricatorController',
     'PhabricatorUIExampleController' => 'PhabricatorController',
     'PhabricatorUIExampleRenderController' => 'PhabricatorUIExampleController',
     'PhabricatorUIListFilterExample' => 'PhabricatorUIExample',
     'PhabricatorUIPagerExample' => 'PhabricatorUIExample',
     'PhabricatorUITooltipExample' => 'PhabricatorUIExample',
     'PhabricatorUser' => 'PhabricatorUserDAO',
     'PhabricatorUserAccountSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
     'PhabricatorUserConduitSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
     'PhabricatorUserDAO' => 'PhabricatorLiskDAO',
     'PhabricatorUserEmailPreferenceSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
     'PhabricatorUserEmailSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
     'PhabricatorUserLog' => 'PhabricatorUserDAO',
     'PhabricatorUserOAuthInfo' => 'PhabricatorUserDAO',
     'PhabricatorUserOAuthSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
     'PhabricatorUserPasswordSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
     'PhabricatorUserPreferenceSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
     'PhabricatorUserPreferences' => 'PhabricatorUserDAO',
     'PhabricatorUserProfile' => 'PhabricatorUserDAO',
     'PhabricatorUserProfileSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
     'PhabricatorUserSSHKey' => 'PhabricatorUserDAO',
     'PhabricatorUserSSHKeysSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
     'PhabricatorUserSearchSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
     'PhabricatorUserSettingsController' => 'PhabricatorPeopleController',
     'PhabricatorUserSettingsPanelController' => 'PhabricatorPeopleController',
     'PhabricatorUserTestCase' => 'PhabricatorTestCase',
     'PhabricatorWorkerDAO' => 'PhabricatorLiskDAO',
     'PhabricatorWorkerTask' => 'PhabricatorWorkerDAO',
     'PhabricatorWorkerTaskData' => 'PhabricatorWorkerDAO',
     'PhabricatorWorkerTaskDetailController' => 'PhabricatorDaemonController',
     'PhabricatorWorkerTaskUpdateController' => 'PhabricatorDaemonController',
     'PhabricatorXHPASTViewController' => 'PhabricatorController',
     'PhabricatorXHPASTViewDAO' => 'PhabricatorLiskDAO',
     'PhabricatorXHPASTViewFrameController' => 'PhabricatorXHPASTViewController',
     'PhabricatorXHPASTViewFramesetController' => 'PhabricatorXHPASTViewController',
     'PhabricatorXHPASTViewInputController' => 'PhabricatorXHPASTViewPanelController',
     'PhabricatorXHPASTViewPanelController' => 'PhabricatorXHPASTViewController',
     'PhabricatorXHPASTViewParseTree' => 'PhabricatorXHPASTViewDAO',
     'PhabricatorXHPASTViewRunController' => 'PhabricatorXHPASTViewController',
     'PhabricatorXHPASTViewStreamController' => 'PhabricatorXHPASTViewPanelController',
     'PhabricatorXHPASTViewTreeController' => 'PhabricatorXHPASTViewPanelController',
     'PhabricatorXHProfController' => 'PhabricatorController',
     'PhabricatorXHProfProfileController' => 'PhabricatorXHProfController',
     'PhabricatorXHProfProfileSymbolView' => 'PhabricatorXHProfProfileView',
     'PhabricatorXHProfProfileTopLevelView' => 'PhabricatorXHProfProfileView',
     'PhabricatorXHProfProfileView' => 'AphrontView',
     'PhameController' => 'PhabricatorController',
     'PhameDAO' => 'PhabricatorLiskDAO',
     'PhameDraftListController' => 'PhamePostListBaseController',
     'PhamePost' => 'PhameDAO',
     'PhamePostDeleteController' => 'PhameController',
     'PhamePostDetailView' => 'AphrontView',
     'PhamePostEditController' => 'PhameController',
     'PhamePostListBaseController' => 'PhameController',
     'PhamePostListController' => 'PhamePostListBaseController',
     'PhamePostListView' => 'AphrontView',
     'PhamePostPreviewController' => 'PhameController',
     'PhamePostQuery' => 'PhabricatorOffsetPagedQuery',
     'PhamePostViewController' => 'PhameController',
     'PhortuneMonthYearExpiryControl' => 'AphrontFormControl',
     'PhortuneStripeBaseController' => 'PhabricatorController',
     'PhortuneStripePaymentFormView' => 'AphrontView',
     'PhortuneStripeTestPaymentFormController' => 'PhortuneStripeBaseController',
     'PhrictionActionConstants' => 'PhrictionConstants',
     'PhrictionChangeType' => 'PhrictionConstants',
     'PhrictionContent' => 'PhrictionDAO',
     'PhrictionController' => 'PhabricatorController',
     'PhrictionDAO' => 'PhabricatorLiskDAO',
     'PhrictionDeleteController' => 'PhrictionController',
     'PhrictionDiffController' => 'PhrictionController',
     'PhrictionDocument' => 'PhrictionDAO',
     'PhrictionDocumentController' => 'PhrictionController',
     'PhrictionDocumentPreviewController' => 'PhrictionController',
     'PhrictionDocumentStatus' => 'PhrictionConstants',
     'PhrictionDocumentTestCase' => 'PhabricatorTestCase',
     'PhrictionEditController' => 'PhrictionController',
     'PhrictionHistoryController' => 'PhrictionController',
     'PhrictionListController' => 'PhrictionController',
     'QueryFormattingTestCase' => 'PhabricatorTestCase',
   ),
   'requires_interface' =>
   array(
     'DefaultDatabaseConfigurationProvider' =>
     array(
       0 => 'DatabaseConfigurationProvider',
     ),
     'DifferentialInlineComment' =>
     array(
       0 => 'PhabricatorInlineCommentInterface',
     ),
     'PhabricatorAuditInlineComment' =>
     array(
       0 => 'PhabricatorInlineCommentInterface',
     ),
     'PhabricatorPaste' =>
     array(
       0 => 'PhabricatorPolicyInterface',
     ),
     'PhabricatorPolicyTestObject' =>
     array(
       0 => 'PhabricatorPolicyInterface',
     ),
   ),
 ));
diff --git a/src/applications/base/storage/configuration/base/DatabaseConfigurationProvider.php b/src/applications/base/storage/configuration/base/DatabaseConfigurationProvider.php
index 44baabed2c..d90b115ce8 100644
--- a/src/applications/base/storage/configuration/base/DatabaseConfigurationProvider.php
+++ b/src/applications/base/storage/configuration/base/DatabaseConfigurationProvider.php
@@ -1,30 +1,34 @@
 <?php
 
 /*
  * Copyright 2012 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 /**
  * @stable
  */
 interface DatabaseConfigurationProvider {
 
-  public function __construct(LiskDAO $dao = null, $mode = 'r');
+  public function __construct(
+    LiskDAO $dao = null,
+    $mode = 'r',
+    $namespace = 'phabricator');
+
   public function getUser();
   public function getPassword();
   public function getHost();
   public function getDatabase();
 
 }
diff --git a/src/applications/base/storage/configuration/default/DefaultDatabaseConfigurationProvider.php b/src/applications/base/storage/configuration/default/DefaultDatabaseConfigurationProvider.php
index a55ddfbcf3..55b8989b26 100644
--- a/src/applications/base/storage/configuration/default/DefaultDatabaseConfigurationProvider.php
+++ b/src/applications/base/storage/configuration/default/DefaultDatabaseConfigurationProvider.php
@@ -1,53 +1,59 @@
 <?php
 
 /*
  * Copyright 2012 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 final class DefaultDatabaseConfigurationProvider
   implements DatabaseConfigurationProvider {
 
   private $dao;
   private $mode;
+  private $namespace;
+
+  public function __construct(
+    LiskDAO $dao = null,
+    $mode = 'r',
+    $namespace = 'phabricator') {
 
-  public function __construct(LiskDAO $dao = null, $mode = 'r') {
     $this->dao = $dao;
     $this->mode = $mode;
+    $this->namespace = $namespace;
   }
 
   public function getUser() {
     return PhabricatorEnv::getEnvConfig('mysql.user');
   }
 
   public function getPassword() {
     return PhabricatorEnv::getEnvConfig('mysql.pass');
   }
 
   public function getHost() {
     return PhabricatorEnv::getEnvConfig('mysql.host');
   }
 
   public function getDatabase() {
     if (!$this->getDao()) {
       return null;
     }
-    return 'phabricator_'.$this->getDao()->getApplicationName();
+    return $this->namespace.'_'.$this->getDao()->getApplicationName();
   }
 
   final protected function getDao() {
     return $this->dao;
   }
 
 }
diff --git a/src/applications/base/storage/lisk/PhabricatorLiskDAO.php b/src/applications/base/storage/lisk/PhabricatorLiskDAO.php
index 675531ee35..c6324fc4ff 100644
--- a/src/applications/base/storage/lisk/PhabricatorLiskDAO.php
+++ b/src/applications/base/storage/lisk/PhabricatorLiskDAO.php
@@ -1,112 +1,120 @@
 <?php
 
 /*
  * Copyright 2012 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 /**
  * @task edges  Managing Edges
  * @task config Configuring Storage
  */
 abstract class PhabricatorLiskDAO extends LiskDAO {
 
   private $edges = array();
+  private static $namespace = 'phabricator';
 
 
 /* -(  Managing Edges  )----------------------------------------------------- */
 
 
   /**
    * @task edges
    */
   public function attachEdges(array $edges) {
     foreach ($edges as $type => $type_edges) {
       $this->edges[$type] = $type_edges;
     }
     return $this;
   }
 
 
   /**
    * @task edges
    */
   public function getEdges($type) {
     $edges = idx($this->edges, $type);
     if ($edges === null) {
       throw new Exception("Call attachEdges() before getEdges()!");
     }
     return $edges;
   }
 
 
   /**
    * @task edges
    */
   public function getEdgePHIDs($type) {
     return ipull($this->getEdges($type), 'dst');
   }
 
 
 /* -(  Configuring Storage  )------------------------------------------------ */
 
+  /**
+   * @task config
+   */
+  public static function setApplicationNamespace($namespace) {
+    self::$namespace = $namespace;
+  }
+
 
   /**
    * @task config
    */
   public function establishLiveConnection($mode) {
     $conf = PhabricatorEnv::newObjectFromConfig(
       'mysql.configuration-provider',
-      array($this, $mode));
+      array($this, $mode, self::$namespace));
 
     return PhabricatorEnv::newObjectFromConfig(
       'mysql.implementation',
       array(
         array(
           'user'      => $conf->getUser(),
           'pass'      => $conf->getPassword(),
           'host'      => $conf->getHost(),
           'database'  => $conf->getDatabase(),
         ),
       ));
   }
 
   /**
    * @task config
    */
   public function getTableName() {
     $str = 'phabricator';
     $len = strlen($str);
 
     $class = strtolower(get_class($this));
     if (!strncmp($class, $str, $len)) {
       $class = substr($class, $len);
     }
     $app = $this->getApplicationName();
     if (!strncmp($class, $app, strlen($app))) {
       $class = substr($class, strlen($app));
     }
 
     if (strlen($class)) {
       return $app.'_'.$class;
     } else {
       return $app;
     }
   }
 
   /**
    * @task config
    */
   abstract public function getApplicationName();
 }
diff --git a/src/docs/configuration/configuration_guide.diviner b/src/docs/configuration/configuration_guide.diviner
index 2d9e47b944..1fd98c9c48 100644
--- a/src/docs/configuration/configuration_guide.diviner
+++ b/src/docs/configuration/configuration_guide.diviner
@@ -1,213 +1,232 @@
 @title Configuration Guide
 @group config
 
 This document contains basic configuration instructions for Phabricator.
 
 = Prerequisites =
 
 This document assumes you've already installed all the components you need.
 If you haven't, see @{article:Installation Guide}.
 
-= Configuring MySQL =
-
-Get MySQL running and verify you can connect to it. Consult the MySQL
-documentation for help. When MySQL works, you need to load the Phabricator
-schemata into it. First, load the initial database schema.
-
-  mysql -uroot < path/to/phabricator/resources/sql/init/initialize.sql
-
-After this you need to upgrade the schema (see @{article:Upgrading Schema}),
-but you need to finish the rest of the configuration first.
-
 = Configuring Phabricator =
 
 Create a new file here:
 
   path/to/phabricator/conf/custom/myconfig.conf.php
 
 ...where ##myconfig## is some name which identifies your installation. Put this
 in the file:
 
   name=myconfig.conf.php, lang=php
   <?php
 
   return array(
 
     // Important! This will put Phabricator into setup mode to help you
     // configure things.
     'phabricator.setup' => true,
 
     // This will be the base domain for your install, and must be configured.
     // Use "https://" if you have SSL. See below for some notes.
     'phabricator.base-uri' => 'http://phabricator.example.com/',
 
     // Connection information for MySQL.
     'mysql.host' => 'localhost',
     'mysql.user' => 'root',
     'mysql.pass' => 'trustno1hunter2',
 
     // Basic email domain configuration.
     'metamta.default-address' => 'noreply@phabricator.example.com',
     'metamta.domain'          => 'phabricator.example.com',
 
     // NOTE: Check default.conf.php for detailed explanations of all the
     // configuration options, including these.
 
   ) + phabricator_read_config_file('production');
 
 For the last line, you can also use ##'development'## instead of
 ##'production'## if you are planning to develop Phabricator itself. This will
 turn on some debugging features.
 
+= PHABRICATOR_ENV Environment Variable =
+
+When running Phabricator scripts, they will ask you to set the `PHABRICATOR_ENV`
+environment variable to point at your config. If you put your script in
+`custom/myconfig.conf.php`, you can identify the config with
+`custom/myconfig`, like this:
+
+  $ PHABRICATOR_ENV=custom/myconfig ./some_phabricator_command
+
+NOTE: Make sure you put 'PHABRICATOR_ENV=...' at the beginning of the line, not
+in the middle. The shell won't parse environmental variables declared after the
+command. You can also ##export PHABRICATOR_ENV=...## in your ~/.bashrc or
+~/.profile or similar, depending on which shell you use and how your system is
+configured.
+
+= Storage: Configuring MySQL =
+
+Get MySQL running and verify you can connect to it. Consult the MySQL
+documentation for help. When MySQL works, you need to load the Phabricator
+schemata into it. To do this, run:
+
+  phabricator/ $ ./bin/storage upgrade
+
+If your configuration uses an unprivileged user to connect to the database, you
+may have to override the default user so the schema changes can be applied with
+root or some other admin user:
+
+  phabricator/ $ ./bin/storage upgrade --user <user> --password <password>
+
+You can avoid the prompt the script issues by passing the ##--force## flag (for
+example, if you are scripting the upgrade process).
+
+  phabricator/ $ ./bin/storage upgrade --force
+
+NOTE: When you update Phabricator, run `storage upgrade` again to apply any
+new updates.
+
 = Webserver: Configuring Apache =
 
 Get Apache running and verify it's serving a test page. Consult the Apache
 documentation for help. Make sure ##mod_php## and ##mod_rewrite## are enabled,
 and ##mod_ssl## if you intend to set up SSL.
 
 If you haven't already, set up a domain name to point to the host you're
 installing on. You can either install Phabricator on a subdomain (like
 phabricator.example.com) or an entire domain, but you can not install it in
 some subdirectory of an existing website. Navigate to whatever domain you're
 going to use and make sure Apache serves you something to verify that DNS
 is correctly configured.
 
 Now, either create a VirtualHost entry (to put Phabricator on a subdomain)
 or edit the Directory entry for the DocumentRoot. It should look something like
 this:
 
   name=httpd.conf
   <VirtualHost *>
     # Change this to the domain which points to your host, i.e. the domain
     # you set as "phabricator.base-uri".
     ServerName phabricator.example.com
 
     # Change this to the path where you put 'phabricator' when you checked it
     # out from github when following the Installation Guide.
     DocumentRoot /path/to/phabricator/webroot
 
     RewriteEngine on
     RewriteRule ^/rsrc/(.*)     -                       [L,QSA]
     RewriteRule ^/favicon.ico   -                       [L,QSA]
     RewriteRule ^(.*)$          /index.php?__path__=$1  [B,L,QSA]
 
     # This will use the config file you set up in the previous step. If you
     # called it something other than 'myconfig', put that here.
     SetEnv PHABRICATOR_ENV custom/myconfig
   </VirtualHost>
 
 Continue to "Setup" below.
 
 = Webserver: Configuring nginx =
 
 For nginx, use a configuration like this:
 
   name=nginx.conf
   server {
     server_name phabricator.example.com;
 
     root      /path/to/phabricator/webroot;
     try_files $uri $uri/ /index.php;
 
     location / {
       index   index.php;
 
       if ( !-f $request_filename )
       {
         rewrite ^/(.*)$ /index.php?__path__=/$1 last;
         break;
       }
     }
 
     location ~ \.php$ {
       fastcgi_pass   localhost:9000;
       fastcgi_index   index.php;
 
       #custom environment variable
       fastcgi_param PHABRICATOR_ENV     "custom/myconfig";
 
       #required if PHP was built with --enable-force-cgi-redirect
       fastcgi_param  REDIRECT_STATUS    200;
 
       #variables to make the $_SERVER populate in PHP
       fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
       fastcgi_param  QUERY_STRING       $query_string;
       fastcgi_param  REQUEST_METHOD     $request_method;
       fastcgi_param  CONTENT_TYPE       $content_type;
       fastcgi_param  CONTENT_LENGTH     $content_length;
 
       fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
 
       fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
       fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;
 
       fastcgi_param  REMOTE_ADDR        $remote_addr;
     }
   }
 
-= Upgrading Schema =
-
-Now, it's time for you to upgrade the database schema -- see
-@{article:Upgrading Schema}. You'll also need to do this after you update the
-code in the future.
-
 = Setup =
 
 Now, restart your webserver and navigate to whichever subdomain you set up. You
 should either see the Phabricator setup screen, which is a simple text page that
 looks something like this:
 
   PHABRICATOR SETUP
 
   This setup mode will guide you through setting up your Phabricator
   configuration.
 
   >>>  REQUIRED PHP EXTENSIONS  ------------------------------------------------
   ...
 
 If you see this, you're in good shape. Follow the instructions and correct any
 problems setup detects. If you don't see it but you do see a useful error
 message, try to fix that. If neither of these cover you, something is wrong.
 If you can't figure it out, come get help in IRC or on the mailing list (see
 http://phabricator.org/ for links).
 
 = Configuring Phabricator =
 
 Now that basic setup is complete, you should configure Phabricator for your
 installation. Phabricator configuration options which control how the
 applications behave are documented here:
 
   /path/to/phabricator/conf/default.conf.php
 
 There are several builtin configurations:
 
   - ##default.conf.php##: root configuration, lists every configuration option
     and sets some default for it. Look in this file to figure out what you can
     configure.
   - ##development.conf.php##: pulls in ##default.conf.php##, but overrides some
     configuration options to better values for doing development on Phabricator.
     You probably don't need to even look at this file unless you're making
     changes to Phabricator itself.
   - ##production.conf.php##: pulls in ##default.conf.php##, but overrides some
     configuration options to provide better values for a production install.
 
 To actually configure your install, edit your ##custom/myconfig.conf.php## file
 and override values from either the ##'production'## or ##'development'##
 configurations. You should not edit the builtin configurations directly because
 that will make upgrading Phabricator more difficult in the future.
 
 = Next Steps =
 
 Continue by:
 
-  - upgrading the database schema with @{article:Upgrading Schema}; or
   - setting up your admin account and login/registration with
     @{article:Configuring Accounts and Registration}; or
   - configuring where uploaded fils and attachments will be stored with
     @{article:Configuring File Storage}; or
   - configuring Phabricator so it can send mail with
     @{article:Configuring Outbound Email}; or
   - configuring inbound mail with @{article:Configuring Inbound Email}; or
   - importing repositories with @{article:Diffusion User Guide}; or
   - learning about daemons with @{article:Managing Daemons with phd}; or
   - contributing to Phabricator with @{article:Contributor Introduction}.
diff --git a/src/docs/configuration/upgrade_schema.diviner b/src/docs/configuration/upgrade_schema.diviner
deleted file mode 100644
index 4374d8f81a..0000000000
--- a/src/docs/configuration/upgrade_schema.diviner
+++ /dev/null
@@ -1,36 +0,0 @@
-@title Upgrading Schema
-@group config
-
-This document describes how to upgrade the database schema.
-
-= Prerequisites =
-
-This document assumes you've already initialized the MySQL database and
-configured your Phabricator environment. If you haven't, see
-@{article:Configuration Guide}.
-
-= Loading patches =
-
-To upgrade your database schema to the latest version, just run this command:
-
-  PHABRICATOR_ENV=<your_config> path/to/phabricator/scripts/sql/upgrade_schema.php
-
-NOTE: Make sure you put 'PHABRICATOR_ENV=...' at the beginning of the line, not
-in the middle. The shell won't parse environmental variables declared after the
-command. You can also ##export PHABRICATOR_ENV=...## in your ~/.bashrc or
-~/.profile or similar, depending on which shell you use and how your system is
-configured.
-
-This will install all the patches that are new since you installed, or since the
-last time you ran this script.
-
-If your configuration uses an unprivileged user to connect to the database, you
-may have to override the default user so the schema changes can be applied with
-root or some other admin user:
-
-  PHABRICATOR_ENV=<your_config> path/to/phabricator/scripts/sql/upgrade_schema.php -u <user> -p <pass>
-
-You can avoid the prompt the script issues by passing the ##-f## flag (for
-example, if you are scripting the upgrade process).
-
-  PHABRICATOR_ENV=<your_config> path/to/phabricator/scripts/sql/upgrade_schema.php -f
diff --git a/src/docs/installation_guide.diviner b/src/docs/installation_guide.diviner
index ad5a178228..3e6651a09a 100644
--- a/src/docs/installation_guide.diviner
+++ b/src/docs/installation_guide.diviner
@@ -1,130 +1,139 @@
 @title Installation Guide
 @group intro
 
 This document contains basic install instructions to get Phabricator up and
 running.
 
 = Installation Requirements =
 
 Phabricator is a LAMP application suite, so you basically need LAMP:
 
   - **Linux**: Some flavor of Linux is required. Mac OS X is an acceptable
     flavor of Linux. Windows is not an acceptable flavor of Linux. Phabricator
     will not install or work properly on Windows. (If you want it to, send
     patches.) Phabricator has active contributors running it on Mac OS X, Amazon
     Linux, Ubuntu, RHEL and CentOS; if you run into issues on other flavors,
     send patches or complaints.
   - **Apache** (or nginx): You need Apache (or nginx). You might be able to use
     something else, but you're on your own.
   - **MySQL**: You need MySQL.
   - **PHP**: You need PHP 5.2 or newer.
 
 NOTE: The command line interface to Phabricator, "Arcanist", //does// work on
 Windows. For instructions, see @{article:Arcanist User Guide: Windows}.
 
 You'll probably also need a **domain name** and you'll certainly need
 **a computer** with a connection to **the internet**.
 
 = Installing Required Components =
 
 If you are installing on Ubuntu or an RedHat derivative, there are install
 scripts available which should handle most of the things discussed in this
 document for you:
 
   - **RedHat Derivatives**: <http://www.phabricator.com/rsrc/install/install_rhel-derivs.sh>
   - **Ubuntu**: <http://www.phabricator.com/rsrc/install/install_ubuntu.sh>
 
 If those work for you, you can skip directly to the
 @{article:Configuration Guide}. These scripts are also available in the
 ##scripts/install## directory in the project itself.
 
 Otherwise, here's a general description of what you need to install:
 
   - git (usually called "git" in package management systems)
   - Apache (usually "httpd" or "apache2") (or nginx)
   - MySQL Server (usually "mysqld" or "mysql-server")
   - PHP (usually "php")
   - Required PHP extensions: mbstring, iconv, mysql, curl, pcntl (these might be
     something like "php-mysql" or "php5-mysql")
   - Optional PHP extensions: gd, apc (special instructions for APC are available
     below if you have difficulty installing it), xhprof (instructions below,
     you only need this if you are developing Phabricator)
 
 If you already have LAMP setup, you've probably already got everything you need.
 It may also be helpful to refer to the install scripts above, even if they don't
 work for your system.
 
 Now that you have all that stuff installed, grab Phabricator and its
 dependencies:
 
   $ cd somewhere/ # pick some install directory
   somewhere/ $ git clone git://github.com/facebook/libphutil.git
   somewhere/ $ git clone git://github.com/facebook/arcanist.git
   somewhere/ $ git clone git://github.com/facebook/phabricator.git
   somewhere/ $ cd phabricator
   somewhere/phabricator/ $ git submodule update --init
 
 = Installing APC (Optional) =
 
 Like everything else written in PHP, Phabricator will run much faster with APC
 installed. You likely need to install "pcre-devel" first:
 
   sudo yum install pcre-devel
 
 Then you have two options. Either install via PECL (try this first):
 
   sudo yum install php-pear
   sudo pecl install apc
 
 **If that doesn't work**, grab the package from PECL directly and follow the
 build instructions there:
 
   http://pecl.php.net/package/APC
 
 Installing APC is optional but **strongly recommended**, especially on
 production hosts.
 
 Once APC is installed, test that it is available by running:
 
   php -i | grep apc
 
 If it doesn't show up, add:
 
   extension=apc.so
 
 ..to "/etc/php.d/apc.ini" or the "php.ini" file indicated by "php -i".
 
 = Installing XHProf (Optional) =
 
 XHProf is a PHP profiling tool. You don't need to install it unless you are
 developing Phabricator and making performance changes.
 
 You can install xhprof with:
 
   $ pecl install xhprof
 
 If you have a PEAR version prior to 1.9.3, you may run into a `phpize` failure.
 If so, you can download the source and build it with:
 
   $ cd extension/
   $ phpize
   $ ./configure
   $ make
   $ sudo make install
 
 You may also need to add "##extension=xhprof.so#" to your php.ini.
 
 See <https://bugs.php.net/bug.php?id=59747> for more information.
 
 = Updating Phabricator =
 
-Since Phabricator is under active development, you should update frequently.
-You can use a script similar to this one to automate the process:
+Since Phabricator is under active development, you should update frequently. To
+update Phabricator:
+
+  - Stop the webserver.
+  - Run `git pull && git submodule update --init` in `libphutil/`,
+    `arcanist/` and `phabricator/`.
+  - Run `phabricator/bin/storage upgrade`.
+  - Restart the webserver.
+
+For more details, see @{article:Configuration Guide}. You can use a script
+similar to this one to automate the process:
 
   http://www.phabricator.com/rsrc/install/update_phabricator.sh
 
 = Next Steps =
 
 Continue by:
 
   - configuring Phabricator with the @{article:Configuration Guide}.
diff --git a/src/infrastructure/setup/PhabricatorSetup.php b/src/infrastructure/setup/PhabricatorSetup.php
index fac8101665..2ce57a9193 100644
--- a/src/infrastructure/setup/PhabricatorSetup.php
+++ b/src/infrastructure/setup/PhabricatorSetup.php
@@ -1,837 +1,818 @@
 <?php
 
 /*
  * Copyright 2012 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 final class PhabricatorSetup {
 
   public static function runSetup() {
     header("Content-Type: text/plain");
     self::write("PHABRICATOR SETUP\n\n");
 
     // Force browser to stop buffering.
     self::write(str_repeat(' ', 2048));
     usleep(250000);
 
     self::write("This setup mode will guide you through setting up your ".
                 "Phabricator configuration.\n");
 
     self::writeHeader("CORE CONFIGURATION");
 
     // NOTE: Test this first since other tests depend on the ability to
     // execute system commands and will fail if safe_mode is enabled.
     $safe_mode = ini_get('safe_mode');
     if ($safe_mode) {
       self::writeFailure();
       self::write(
         "Setup failure! You have 'safe_mode' enabled. Phabricator will not ".
         "run in safe mode, and it has been deprecated in PHP 5.3 and removed ".
         "in PHP 5.4.\n");
       return;
     } else {
       self::write(" okay  PHP's deprecated 'safe_mode' is disabled.\n");
     }
 
     // NOTE: Also test this early since we can't include files from other
     // libraries if this is set strictly.
 
     $open_basedir = ini_get('open_basedir');
     if ($open_basedir) {
 
       // 'open_basedir' restricts which files we're allowed to access with
       // file operations. This might be okay -- we don't need to write to
       // arbitrary places in the filesystem -- but we need to access certain
       // resources. This setting is unlikely to be providing any real measure
       // of security so warn even if things look OK.
 
       try {
         phutil_require_module('phutil', 'utils');
         $open_libphutil = true;
       } catch (Exception $ex) {
         $message = $ex->getMessage();
         self::write("Unable to load modules from libphutil: {$message}\n");
         $open_libphutil = false;
       }
 
       try {
         phutil_require_module('arcanist', 'workflow/base');
         $open_arcanist = true;
       } catch (Exception $ex) {
         $message = $ex->getMessage();
         self::write("Unable to load modules from Arcanist: {$message}\n");
         $open_arcanist = false;
       }
 
       $open_urandom = false;
       try {
         Filesystem::readRandomBytes(1);
         $open_urandom = true;
       } catch (FilesystemException $ex) {
         self::write($ex->getMessage()."\n");
       }
 
       try {
         $tmp = new TempFile();
         file_put_contents($tmp, '.');
         $open_tmp = @fopen((string)$tmp, 'r');
       } catch (Exception $ex) {
         $message = $ex->getMessage();
         $dir = sys_get_temp_dir();
         self::write("Unable to open temp files from '{$dir}': {$message}\n");
         $open_tmp = false;
       }
 
       if (!$open_urandom || !$open_tmp || !$open_libphutil || !$open_arcanist) {
         self::writeFailure();
         self::write(
           "Setup failure! Your server is configured with 'open_basedir' in ".
           "php.ini which prevents Phabricator from opening files it needs to ".
           "access. Either make the setting more permissive or remove it. It ".
           "is unlikely you derive significant security benefits from having ".
           "this configured; files outside this directory can still be ".
           "accessed through system command execution.");
         return;
       } else {
         self::write(
           "[WARN] You have an 'open_basedir' configured in your php.ini. ".
           "Although the setting seems permissive enough that Phabricator ".
           "will run properly, you may run into problems because of it. It is ".
           "unlikely you gain much real security benefit from having it ".
           "configured, because the application can still access files outside ".
           "the 'open_basedir' by running system commands.\n");
       }
     } else {
       self::write(" okay  'open_basedir' is not set.\n");
     }
 
     if (!PhabricatorEnv::getEnvConfig('security.alternate-file-domain')) {
       self::write(
         "[WARN] You have not configured 'security.alternate-file-domain'. ".
         "This makes your installation vulnerable to attack. Make sure you ".
         "read the documentation for this parameter and understand the ".
         "consequences of leaving it unconfigured.\n");
     }
 
     $path = getenv('PATH');
     if (empty($path)) {
       self::writeFailure();
       self::write(
         "Setup failure! The environmental \$PATH variable is empty. ".
         "Phabricator needs to execute system commands like 'svn', 'git', ".
         "'hg', and 'diff'. Set up your webserver so that it passes a valid ".
         "\$PATH to the PHP process.\n\n");
       if (php_sapi_name() == 'fpm-fcgi') {
         self::write(
           "You're running php-fpm, so the easiest way to do this is to add ".
           "this line to your php-fpm.conf:\n\n".
           "  env[PATH] = /usr/local/bin:/usr/bin:/bin\n\n".
           "Then restart php-fpm.\n");
       }
       return;
     } else {
       self::write(" okay  \$PATH is nonempty.\n");
     }
 
     self::write("[OKAY] Core configuration OKAY.\n");
 
     self::writeHeader("REQUIRED PHP EXTENSIONS");
     $extensions = array(
       'mysql',
       'hash',
       'json',
       'openssl',
       'mbstring',
       'iconv',
 
       // There is a chance we might not need this, but some configurations (like
       // Amazon SES) will require it. Just mark it 'required' since it's widely
       // available and relatively core.
       'curl',
     );
     foreach ($extensions as $extension) {
       $ok = self::requireExtension($extension);
       if (!$ok) {
         self::writeFailure();
         self::write("Setup failure! Install PHP extension '{$extension}'.");
         return;
       }
     }
 
     list($err, $stdout, $stderr) = exec_manual('which php');
     if ($err) {
       self::writeFailure();
       self::write("Unable to locate 'php' on the command line from the web ".
                   "server. Verify that 'php' is in the webserver's PATH.\n".
                   "   err: {$err}\n".
                   "stdout: {$stdout}\n".
                   "stderr: {$stderr}\n");
       return;
     } else {
       self::write(" okay  PHP binary found on the command line.\n");
       $php_bin = trim($stdout);
     }
 
     // NOTE: In cPanel + suphp installs, 'php' may be the PHP CGI SAPI, not the
     // PHP CLI SAPI. proc_open() will pass the environment to the child process,
     // which will re-execute the webpage (causing an infinite number of
     // processes to spawn). To test that the 'php' binary is safe to execute,
     // we call php_sapi_name() using "env -i" to wipe the environment so it
     // doesn't execute another reuqest if it's the wrong binary. We can't use
     // "-r" because php-cgi doesn't support that flag.
 
     $tmp_file = new TempFile('sapi.php');
     Filesystem::writeFile($tmp_file, '<?php echo php_sapi_name();');
 
     list($err, $stdout, $stderr) = exec_manual(
       '/usr/bin/env -i %s -f %s',
       $php_bin,
       $tmp_file);
     if ($err) {
       self::writeFailure();
       self::write("Unable to execute 'php' on the command line from the web ".
                   "server.\n".
                   "   err: {$err}\n".
                   "stdout: {$stdout}\n".
                   "stderr: {$stderr}\n");
       return;
     } else {
       self::write(" okay  PHP is available from the command line.\n");
 
       $sapi = trim($stdout);
       if ($sapi != 'cli') {
         self::writeFailure();
         self::write(
           "The 'php' binary on this system uses the '{$sapi}' SAPI, but the ".
           "'cli' SAPI is expected. Replace 'php' with the php-cli SAPI ".
           "binary, or edit your webserver configuration so the first 'php' ".
           "in PATH is the 'cli' SAPI.\n\n".
           "If you're running cPanel with suphp, the easiest way to fix this ".
           "is to add '/usr/local/bin' before '/usr/bin' for 'env_path' in ".
           "suconf.php:\n\n".
           '  env_path="/bin:/usr/local/bin:/usr/bin"'.
           "\n\n");
         return;
       } else {
         self::write(" okay  'php' is CLI SAPI.\n");
       }
     }
 
     $root = dirname(phutil_get_library_root('phabricator'));
 
     // On RHEL6, doing a distro install of pcntl makes it available from the
     // CLI binary but not from the Apache module. This isn't entirely
     // unreasonable and we don't need it from Apache, so do an explicit test
     // for CLI availability.
     list($err, $stdout, $stderr) = exec_manual(
       'php %s',
       "{$root}/scripts/setup/pcntl_available.php");
     if ($err) {
       self::writeFailure();
       self::write("Unable to execute scripts/setup/pcntl_available.php to ".
                   "test for the availability of pcntl from the CLI.\n".
                   "   err: {$err}\n".
                   "stdout: {$stdout}\n".
                   "stderr: {$stderr}\n");
       return;
     } else {
       if (trim($stdout) == 'YES') {
         self::write(" okay  pcntl is available from the command line.\n");
         self::write("[OKAY] All extensions OKAY\n");
       } else {
         self::write(" warn  pcntl is not available!\n");
         self::write("[WARN] *** WARNING *** pcntl extension not available. ".
                     "You will not be able to run daemons.\n");
       }
     }
 
     self::writeHeader("GIT SUBMODULES");
     if (!Filesystem::pathExists($root.'/.git')) {
       self::write(" skip  Not a git clone.\n\n");
     } else {
       list($info) = execx(
         '(cd %s && git submodule status)',
         $root);
       foreach (explode("\n", rtrim($info)) as $line) {
         $matches = null;
         if (!preg_match('/^(.)([0-9a-f]{40}) (\S+)(?: |$)/', $line, $matches)) {
           self::writeFailure();
           self::write(
             "Setup failure! 'git submodule' produced unexpected output:\n".
             $line);
           return;
         }
 
         $status = $matches[1];
         $module = $matches[3];
 
         switch ($status) {
           case '-':
           case '+':
           case 'U':
             self::writeFailure();
             self::write(
               "Setup failure! Git submodule '{$module}' is not up to date. ".
               "Run:\n\n".
               "  cd {$root} && git submodule update --init\n\n".
               "...to update submodules.");
             return;
           case ' ':
             self::write(" okay  Git submodule '{$module}' up to date.\n");
             break;
           default:
             self::writeFailure();
             self::write(
               "Setup failure! 'git submodule' reported unknown status ".
               "'{$status}' for submodule '{$module}'. This is a bug; report ".
               "it to the Phabricator maintainers.");
             return;
         }
       }
     }
     self::write("[OKAY] All submodules OKAY.\n");
 
     self::writeHeader("BASIC CONFIGURATION");
 
     $env = PhabricatorEnv::getEnvConfig('phabricator.env');
     if ($env == 'production' || $env == 'default' || $env == 'development') {
       self::writeFailure();
       self::write(
         "Setup failure! Your PHABRICATOR_ENV is set to '{$env}', which is ".
         "a Phabricator environmental default. You should create a custom ".
         "environmental configuration instead of editing the defaults ".
         "directly. See this document for instructions:\n");
         self::writeDoc('article/Configuration_Guide.html');
       return;
     } else {
       $host = PhabricatorEnv::getEnvConfig('phabricator.base-uri');
       $host_uri = new PhutilURI($host);
       $protocol = $host_uri->getProtocol();
       $allowed_protocols = array(
         'http'  => true,
         'https' => true,
       );
       if (empty($allowed_protocols[$protocol])) {
         self::writeFailure();
         self::write(
           "You must specify the protocol over which your host works (e.g.: ".
           "\"http:// or https://\")\nin your custom config file.\nRefer to ".
           "'default.conf.php' for documentation on configuration options.\n");
         return;
       }
       if (preg_match('/.*\/$/', $host)) {
         self::write(" okay  phabricator.base-uri protocol\n");
       } else {
         self::writeFailure();
         self::write(
           "You must add a trailing slash at the end of the host\n(e.g.: ".
           "\"http://phabricator.example.com/ instead of ".
           "http://phabricator.example.com\")\nin your custom config file.".
           "\nRefer to 'default.conf.php' for documentation on configuration ".
           "options.\n");
         return;
       }
 
       $host_domain = $host_uri->getDomain();
       if (strpos($host_domain, '.') !== false) {
         self::write(" okay  phabricator.base-uri domain\n");
       } else {
         self::writeFailure();
         self::write(
           "You must host Phabricator on a domain that contains a dot ('.'). ".
           "The current domain, '{$host_domain}', does not have a dot, so some ".
           "browsers will not set cookies on it. For instance, ".
           "'http://example.com/ is OK, but 'http://example/' won't work. ".
           "If you are using localhost, create an entry in the hosts file like ".
           "'127.0.0.1 example.com', and access the localhost with ".
           "'http://example.com/'.");
         return;
       }
     }
 
     $timezone = nonempty(
       PhabricatorEnv::getEnvConfig('phabricator.timezone'),
       ini_get('date.timezone'));
     if (!$timezone) {
       self::writeFailure();
       self::write(
         "Setup failure! Your configuration fails to specify a server ".
         "timezone. Either set 'date.timezone' in your php.ini or ".
         "'phabricator.timezone' in your Phabricator configuration. See the ".
         "PHP documentation for a list of supported timezones:\n\n".
         "http://us.php.net/manual/en/timezones.php\n");
       return;
     } else {
       self::write(" okay  Timezone '{$timezone}' configured.\n");
     }
 
     self::write("[OKAY] Basic configuration OKAY\n");
 
 
     $issue_gd_warning = false;
     self::writeHeader('GD LIBRARY');
     if (extension_loaded('gd')) {
       self::write(" okay  Extension 'gd' is loaded.\n");
       $image_type_map = array(
         'imagepng'  => 'PNG',
         'imagegif'  => 'GIF',
         'imagejpeg' => 'JPEG',
       );
       foreach ($image_type_map as $function => $image_type) {
         if (function_exists($function)) {
           self::write(" okay  Support for '{$image_type}' is available.\n");
         } else {
           self::write(" warn  Support for '{$image_type}' is not available!\n");
           $issue_gd_warning = true;
         }
       }
     } else {
       self::write(" warn  Extension 'gd' is not loaded.\n");
       $issue_gd_warning = true;
     }
 
     if ($issue_gd_warning) {
       self::write(
         "[WARN] The 'gd' library is missing or lacks full support. ".
         "Phabricator will not be able to generate image thumbnails without ".
         "gd.\n");
     } else {
       self::write("[OKAY] 'gd' loaded and has full image type support.\n");
     }
 
 
     self::writeHeader('FACEBOOK INTEGRATION');
     $fb_auth = PhabricatorEnv::getEnvConfig('facebook.auth-enabled');
     if (!$fb_auth) {
       self::write(" skip  'facebook.auth-enabled' not enabled.\n");
     } else {
       self::write(" okay  'facebook.auth-enabled' is enabled.\n");
       $app_id = PhabricatorEnv::getEnvConfig('facebook.application-id');
       $app_secret = PhabricatorEnv::getEnvConfig('facebook.application-secret');
 
       if (!$app_id) {
         self::writeFailure();
         self::write(
           "Setup failure! 'facebook.auth-enabled' is true but there is no ".
           "setting for 'facebook.application-id'.\n");
         return;
       } else {
         self::write(" okay  'facebook.application-id' is set.\n");
       }
 
       if (!is_string($app_id)) {
         self::writeFailure();
         self::write(
           "Setup failure! 'facebook.application-id' should be a string.");
         return;
       } else {
         self::write(" okay  'facebook.application-id' is string.\n");
       }
 
       if (!$app_secret) {
         self::writeFailure();
         self::write(
           "Setup failure! 'facebook.auth-enabled' is true but there is no ".
           "setting for 'facebook.application-secret'.");
         return;
       } else {
         self::write(" okay  'facebook.application-secret is set.\n");
       }
 
       self::write("[OKAY] Facebook integration OKAY\n");
     }
 
     self::writeHeader("MySQL DATABASE & STORAGE CONFIGURATION");
 
     $conf = PhabricatorEnv::newObjectFromConfig('mysql.configuration-provider');
     $conn_user = $conf->getUser();
     $conn_pass = $conf->getPassword();
     $conn_host = $conf->getHost();
 
     $timeout = ini_get('mysql.connect_timeout');
     if ($timeout > 5) {
       self::writeNote(
         "Your MySQL connect timeout is very high ({$timeout} seconds). ".
         "Consider reducing it to 5 or below by setting ".
         "'mysql.connect_timeout' in your php.ini.");
     }
 
     self::write(" okay  Trying to connect to MySQL database ".
                 "{$conn_user}@{$conn_host}...\n");
 
     ini_set('mysql.connect_timeout', 2);
 
     $conn_raw = PhabricatorEnv::newObjectFromConfig(
       'mysql.implementation',
       array(
         array(
           'user'      => $conn_user,
           'pass'      => $conn_pass,
           'host'      => $conn_host,
           'database'  => null,
         ),
       ));
 
     try {
       queryfx($conn_raw, 'SELECT 1');
       self::write(" okay  Connection successful!\n");
     } catch (AphrontQueryConnectionException $ex) {
       $message = $ex->getMessage();
       self::writeFailure();
       self::write(
         "Setup failure! MySQL exception: {$message} \n".
         "Edit Phabricator configuration keys 'mysql.user', ".
         "'mysql.host' and 'mysql.pass' to enable Phabricator ".
         "to connect.");
       return;
     }
 
     $engines = queryfx_all($conn_raw, 'SHOW ENGINES');
     $engines = ipull($engines, 'Support', 'Engine');
 
     $innodb = idx($engines, 'InnoDB');
     if ($innodb != 'YES' && $innodb != 'DEFAULT') {
       self::writeFailure();
       self::write(
         "Setup failure! The 'InnoDB' engine is not available. Enable ".
         "InnoDB in your MySQL configuration. If you already created tables, ".
         "MySQL incorrectly used some other engine. You need to convert ".
         "them or drop and reinitialize them.");
       return;
     } else {
       self::write(" okay  InnoDB is available.\n");
     }
 
     $databases = queryfx_all($conn_raw, 'SHOW DATABASES');
     $databases = ipull($databases, 'Database', 'Database');
     if (empty($databases['phabricator_meta_data'])) {
       self::writeFailure();
       self::write(
-        "Setup failure! You haven't loaded the 'initialize.sql' file into ".
-        "MySQL. This file initializes necessary databases. See this guide for ".
-        "instructions:\n");
+        "Setup failure! You haven't run 'bin/storage upgrade'. See this ".
+        "article for instructions:\n");
       self::writeDoc('article/Configuration_Guide.html');
       return;
     } else {
       self::write(" okay  Databases have been initialized.\n");
     }
 
-    $schema_version = queryfx_one(
-      $conn_raw,
-      'SELECT version FROM phabricator_meta_data.schema_version');
-    $schema_version = idx($schema_version, 'version', 'null');
-
-    $expect = PhabricatorSQLPatchList::getExpectedSchemaVersion();
-    if ($schema_version != $expect) {
-      self::writeFailure();
-      self::write(
-        "Setup failure! You haven't upgraded your database schema to the ".
-        "latest version. Expected version is '{$expect}', but your local ".
-        "version is '{$schema_version}'. See this guide for instructions:\n");
-      self::writeDoc('article/Upgrading_Schema.html');
-      return;
-    } else {
-      self::write(" okay  Database schema are up to date (v{$expect}).\n");
-    }
-
     $index_min_length = queryfx_one(
       $conn_raw,
       'SHOW VARIABLES LIKE %s',
       'ft_min_word_len');
     $index_min_length = idx($index_min_length, 'Value', 4);
     if ($index_min_length >= 4) {
       self::writeNote(
         "MySQL is configured with a 'ft_min_word_len' of 4 or greater, which ".
         "means you will not be able to search for 3-letter terms. Consider ".
         "setting this in your configuration:\n".
         "\n".
         "    [mysqld]\n".
         "        ft_min_word_len=3\n".
         "\n".
         "Then optionally run:\n".
         "\n".
         "    REPAIR TABLE phabricator_search.search_documentfield QUICK;\n".
         "\n".
         "...to reindex existing documents.");
     }
 
     $max_allowed_packet = queryfx_one(
       $conn_raw,
       'SHOW VARIABLES LIKE %s',
       'max_allowed_packet');
     $max_allowed_packet = idx($max_allowed_packet, 'Value', PHP_INT_MAX);
 
     $recommended_minimum = 1024 * 1024;
     if ($max_allowed_packet < $recommended_minimum) {
       self::writeNote(
         "MySQL is configured with a small 'max_allowed_packet' ".
         "('{$max_allowed_packet}'), which may cause some large writes to ".
         "fail. Consider raising this to at least {$recommended_minimum}.");
     } else {
       self::write(" okay  max_allowed_packet = {$max_allowed_packet}.\n");
     }
 
     $mysql_key = 'storage.mysql-engine.max-size';
     $mysql_limit = PhabricatorEnv::getEnvConfig($mysql_key);
 
     if ($mysql_limit && ($mysql_limit + 8192) > $max_allowed_packet) {
       self::writeFailure();
       self::write(
         "Setup failure! Your Phabricator 'storage.mysql-engine.max-size' ".
         "configuration ('{$mysql_limit}') must be at least 8KB smaller ".
         "than your MySQL 'max_allowed_packet' configuration ".
         "('{$max_allowed_packet}'). Raise the 'max_allowed_packet' in your ".
         "MySQL configuration, or reduce the maximum file size allowed by ".
         "the Phabricator configuration.\n");
       return;
     } else if (!$mysql_limit) {
       self::write(" skip  MySQL file storage engine not configured.\n");
     } else {
       self::write(" okay  MySQL file storage engine configuration okay.\n");
     }
 
     $local_key = 'storage.local-disk.path';
     $local_path = PhabricatorEnv::getEnvConfig($local_key);
     if ($local_path) {
       if (!Filesystem::pathExists($local_path) ||
           !is_readable($local_path) ||
           !is_writable($local_path)) {
         self::writeFailure();
         self::write(
           "Setup failure! You have configured local disk storage but the ".
           "path you specified ('{$local_path}') does not exist or is not ".
           "readable or writable.\n");
         if ($open_basedir) {
           self::write(
             "You have an 'open_basedir' setting -- make sure Phabricator is ".
             "allowed to open files in the local storage directory.\n");
         }
         return;
       } else {
         self::write(" okay  Local disk storage exists and is writable.\n");
       }
     } else {
       self::write(" skip  Not configured for local disk storage.\n");
     }
 
     $selector = PhabricatorEnv::getEnvConfig('storage.engine-selector');
 
     try {
       $storage_selector_exists = class_exists($selector);
     } catch (Exception $ex) {
       $storage_selector_exists = false;
     }
 
     if ($storage_selector_exists) {
       self::write(" okay  Using '{$selector}' as a storage engine selector.\n");
     } else {
       self::writeFailure();
       self::write(
         "Setup failure! You have configured '{$selector}' as a storage engine ".
         "selector but it does not exist or could not be loaded.\n");
       return;
     }
 
     self::write("[OKAY] Database and storage configuration OKAY\n");
 
 
     self::writeHeader("OUTBOUND EMAIL CONFIGURATION");
 
     $have_adapter = false;
     $is_ses = false;
 
     $adapter = PhabricatorEnv::getEnvConfig('metamta.mail-adapter');
     switch ($adapter) {
       case 'PhabricatorMailImplementationPHPMailerLiteAdapter':
 
         $have_adapter = true;
 
         if (!Filesystem::pathExists('/usr/bin/sendmail') &&
           !Filesystem::pathExists('/usr/sbin/sendmail')) {
           self::writeFailure();
           self::write(
             "Setup failure! You don't have a 'sendmail' binary on this system ".
             "but outbound email is configured to use sendmail. Install an MTA ".
             "(like sendmail, qmail or postfix) or use a different outbound ".
             "mail configuration. See this guide for configuring outbound ".
             "email:\n");
           self::writeDoc('article/Configuring_Outbound_Email.html');
           return;
         } else {
           self::write(" okay  Sendmail is configured.\n");
         }
 
         break;
       case 'PhabricatorMailImplementationAmazonSESAdapter':
 
         $is_ses = true;
         $have_adapter = true;
 
         if (PhabricatorEnv::getEnvConfig('metamta.can-send-as-user')) {
           self::writeFailure();
           self::write(
             "Setup failure! 'metamta.can-send-as-user' must be false when ".
             "configured with Amazon SES.");
           return;
         } else {
           self::write(" okay  Sender config looks okay.\n");
         }
 
         if (!PhabricatorEnv::getEnvConfig('amazon-ses.access-key')) {
           self::writeFailure();
           self::write(
             "Setup failure! 'amazon-ses.access-key' is not set, but ".
             "outbound mail is configured to deliver via Amazon SES.");
           return;
         } else {
           self::write(" okay Amazon SES access key is set.\n");
         }
 
         if (!PhabricatorEnv::getEnvConfig('amazon-ses.secret-key')) {
           self::writeFailure();
           self::write(
             "Setup failure! 'amazon-ses.secret-key' is not set, but ".
             "outbound mail is configured to deliver via Amazon SES.");
           return;
         } else {
           self::write(" okay Amazon SES secret key is set.\n");
         }
 
         if (PhabricatorEnv::getEnvConfig('metamta.send-immediately')) {
           self::writeNote(
             "Your configuration uses Amazon SES to deliver email but tries ".
             "to send it immediately. This will work, but it's slow. ".
             "Consider configuring the MetaMTA daemon.");
         }
         break;
       case 'PhabricatorMailImplementationTestAdapter':
         self::write(" skip  You have disabled outbound email.\n");
         break;
       default:
         self::write(" skip  Configured with a custom adapter.\n");
         break;
     }
 
     if ($have_adapter) {
       $default = PhabricatorEnv::getEnvConfig('metamta.default-address');
       if (!$default || $default == 'noreply@example.com') {
         self::writeFailure();
         self::write(
           "Setup failure! You have not set 'metamta.default-address'.");
         return;
       } else {
         self::write(" okay  metamta.default-address is set.\n");
       }
 
       if ($is_ses) {
         self::writeNote(
           "Make sure you've verified your 'from' address ('{$default}') with ".
           "Amazon SES. Until you verify it, you will be unable to send mail ".
           "using Amazon SES.");
       }
 
       $domain = PhabricatorEnv::getEnvConfig('metamta.domain');
       if (!$domain || $domain == 'example.com') {
         self::writeFailure();
         self::write(
           "Setup failure! You have not set 'metamta.domain'.");
         return;
       } else {
         self::write(" okay  metamta.domain is set.\n");
       }
 
       self::write("[OKAY] Mail configuration OKAY\n");
     }
 
     self::writeHeader('CONFIG CLASSES');
     foreach (PhabricatorEnv::getRequiredClasses() as $key => $instanceof) {
       $config = PhabricatorEnv::getEnvConfig($key);
       if (!$config) {
         self::writeNote("'$key' is not set.");
       } else {
         try {
           $r = new ReflectionClass($config);
           if (!$r->isSubclassOf($instanceof)) {
             throw new Exception(
               "Config setting '$key' must be an instance of '$instanceof'.");
           } else if (!$r->isInstantiable()) {
             throw new Exception("Config setting '$key' must be instantiable.");
           }
         } catch (Exception $ex) {
           self::writeFailure();
           self::write("Setup failure! ".$ex->getMessage());
           return;
         }
       }
     }
     self::write("[OKAY] Config classes OKAY\n");
 
     self::writeHeader('SUCCESS!');
     self::write(
       "Congratulations! Your setup seems mostly correct, or at least fairly ".
       "reasonable.\n\n".
       "*** NEXT STEP ***\n".
       "Edit your configuration file (conf/{$env}.conf.php) and remove the ".
       "'phabricator.setup' line to finish installation.");
 
   }
 
   public static function requireExtension($extension) {
     if (extension_loaded($extension)) {
       self::write(" okay  Extension '{$extension}' installed.\n");
       return true;
     } else {
       self::write("[FAIL] Extension '{$extension}' is NOT INSTALLED!\n");
       return false;
     }
   }
 
   private static function writeFailure() {
     self::write("\n\n<<< *** FAILURE! *** >>>\n");
   }
 
   private static function write($str) {
     echo $str;
     ob_flush();
     flush();
 
     // This, uh, makes it look cool. -_-
     usleep(20000);
   }
 
   private static function writeNote($note) {
     $note = "*** NOTE: ".wordwrap($note, 75, "\n", true);
     $note = "\n".str_replace("\n", "\n          ", $note)."\n\n";
     self::write($note);
   }
 
   public static function writeHeader($header) {
     $template = '>>>'.str_repeat('-', 77);
     $template = substr_replace(
       $template,
       '  '.$header.'  ',
       3,
       strlen($header) + 4);
     self::write("\n\n{$template}\n\n");
   }
 
   public static function writeDoc($doc) {
     self::write(
       "\n".
       '    http://www.phabricator.com/docs/phabricator/'.$doc.
       "\n\n");
   }
 
 }
diff --git a/src/infrastructure/setup/__init__.php b/src/infrastructure/setup/__init__.php
index 36ade10b12..2e5332c1ed 100644
--- a/src/infrastructure/setup/__init__.php
+++ b/src/infrastructure/setup/__init__.php
@@ -1,21 +1,20 @@
 <?php
 /**
  * This file is automatically generated. Lint this module to rebuild it.
  * @generated
  */
 
 
 
 phutil_require_module('phabricator', 'infrastructure/env');
-phutil_require_module('phabricator', 'infrastructure/setup/sql');
 phutil_require_module('phabricator', 'storage/queryfx');
 
 phutil_require_module('phutil', 'filesystem');
 phutil_require_module('phutil', 'filesystem/tempfile');
 phutil_require_module('phutil', 'future/exec');
 phutil_require_module('phutil', 'moduleutils');
 phutil_require_module('phutil', 'parser/uri');
 phutil_require_module('phutil', 'utils');
 
 
 phutil_require_source('PhabricatorSetup.php');
diff --git a/src/infrastructure/setup/sql/PhabricatorSQLPatchList.php b/src/infrastructure/setup/sql/PhabricatorSQLPatchList.php
deleted file mode 100644
index 6200bf45ae..0000000000
--- a/src/infrastructure/setup/sql/PhabricatorSQLPatchList.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php
-
-/*
- * Copyright 2012 Facebook, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-final class PhabricatorSQLPatchList {
-
-  public static function getPatchList() {
-    $root = dirname(phutil_get_library_root('phabricator'));
-
-    // Find the patch files
-    $patches_dir = $root.'/resources/sql/patches/';
-    $finder = new FileFinder($patches_dir);
-    $results = $finder->find();
-
-    $versions = array();
-    $patches = array();
-    foreach ($results as $path) {
-      $matches = array();
-      if (!preg_match('/(\d+)\..*\.(sql|php)$/', $path, $matches)) {
-        continue;
-      }
-      $version = (int)$matches[1];
-      $patches[] = array(
-        'version' => $version,
-        'path'    => $patches_dir.$path,
-      );
-      if (empty($versions[$version])) {
-        $versions[$version] = true;
-      } else {
-        throw new Exception("Two patches have version {$version}!");
-      }
-    }
-
-    // Files are in some 'random' order returned by the operating system
-    // We need to apply them in proper order
-    $patches = isort($patches, 'version');
-
-    return $patches;
-  }
-
-  public static function getExpectedSchemaVersion() {
-    $patches = self::getPatchList();
-    $versions = ipull($patches, 'version');
-    $max_version = max($versions);
-    return $max_version;
-  }
-
-}
diff --git a/src/infrastructure/setup/sql/__init__.php b/src/infrastructure/setup/sql/__init__.php
index 248a60848c..62a8e8f4a0 100644
--- a/src/infrastructure/setup/sql/__init__.php
+++ b/src/infrastructure/setup/sql/__init__.php
@@ -1,14 +1,9 @@
 <?php
 /**
  * This file is automatically generated. Lint this module to rebuild it.
  * @generated
  */
 
 
 
-phutil_require_module('phutil', 'filesystem/filefinder');
-phutil_require_module('phutil', 'moduleutils');
-phutil_require_module('phutil', 'utils');
 
-
-phutil_require_source('PhabricatorSQLPatchList.php');
diff --git a/src/infrastructure/setup/sql/base/PhabricatorSQLPatchList.php b/src/infrastructure/setup/sql/base/PhabricatorSQLPatchList.php
new file mode 100644
index 0000000000..224dfcc187
--- /dev/null
+++ b/src/infrastructure/setup/sql/base/PhabricatorSQLPatchList.php
@@ -0,0 +1,164 @@
+<?php
+
+/*
+ * Copyright 2012 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+abstract class PhabricatorSQLPatchList {
+
+  abstract function getNamespace();
+  abstract function getPatches();
+
+  final public static function buildAllPatches() {
+    $patch_lists = id(new PhutilSymbolLoader())
+      ->setAncestorClass('PhabricatorSQLPatchList')
+      ->setConcreteOnly(true)
+      ->selectAndLoadSymbols();
+
+    $specs = array();
+    $seen_namespaces = array();
+
+    foreach ($patch_lists as $patch_class) {
+      $patch_class = $patch_class['name'];
+      $patch_list = newv($patch_class, array());
+
+      $namespace = $patch_list->getNamespace();
+      if (isset($seen_namespaces[$namespace])) {
+        $prior = $seen_namespaces[$namespace];
+        throw new Exception(
+          "PatchList '{$patch_class}' has the same namespace, '{$namespace}', ".
+          "as another patch list class, '{$prior}'. Each patch list MUST have ".
+          "a unique namespace.");
+      }
+
+      $last_key = null;
+      foreach ($patch_list->getPatches() as $key => $patch) {
+        if (!is_array($patch)) {
+          throw new Exception(
+            "PatchList '{$patch_class}' has a patch '{$key}' which is not ".
+            "an array.");
+        }
+
+        $valid = array(
+          'type'    => true,
+          'name'    => true,
+          'after'   => true,
+          'legacy'  => true,
+        );
+
+        foreach ($patch as $pkey => $pval) {
+          if (empty($valid[$pkey])) {
+            throw new Exception(
+              "PatchList '{$patch_class}' has a patch, '{$key}', with an ".
+              "unknown property, '{$pkey}'. Patches must have only valid ".
+              "keys: ".implode(', ', array_keys($valid)).'.');
+          }
+        }
+
+        if (is_numeric($key)) {
+          throw new Exception(
+            "PatchList '{$patch_class}' has a patch with a numeric key, ".
+            "'{$key}'. Patches must use string keys.");
+        }
+
+        if (strpos($key, ':') !== false) {
+          throw new Exception(
+            "PatchList '{$patch_class}' has a patch with a colon in the ".
+            "key name, '{$key}'. Patch keys may not contain colons.");
+        }
+
+        $full_key = "{$namespace}:{$key}";
+
+        if (isset($specs[$full_key])) {
+          throw new Exception(
+            "PatchList '{$patch_class}' has a patch '{$key}' which ".
+            "duplicates an existing patch key.");
+        }
+
+        $patch['key']     = $key;
+        $patch['fullKey'] = $full_key;
+
+        if (isset($patch['legacy'])) {
+          if ($namespace != 'phabricator') {
+            throw new Exception(
+              "Only patches in the 'phabricator' namespace may contain ".
+              "'legacy' keys.");
+          }
+        } else {
+          $patch['legacy'] = false;
+        }
+
+        if (!array_key_exists('after', $patch)) {
+          if ($last_key === null) {
+            throw new Exception(
+              "Patch '{$full_key}' is missing key 'after', and is the first ".
+              "patch in the patch list '{$patch_class}', so its application ".
+              "order can not be determined implicitly. The first patch in a ".
+              "patch list must list the patch or patches it depends on ".
+              "explicitly.");
+          } else {
+            $patch['after'] = array($last_key);
+          }
+        }
+        $last_key = $full_key;
+
+        foreach ($patch['after'] as $after_key => $after) {
+          if (strpos($after, ':') === false) {
+            $patch['after'][$after_key] = $namespace.':'.$after;
+          }
+        }
+
+        $type = idx($patch, 'type');
+        if (!$type) {
+          throw new Exception(
+            "Patch '{$namespace}:{$key}' is missing key 'type'. Every patch ".
+            "must have a type.");
+        }
+
+        switch ($type) {
+          case 'db':
+          case 'sql':
+          case 'php':
+            break;
+          default:
+            throw new Exception(
+              "Patch '{$namespace}:{$key}' has unknown patch type '{$type}'.");
+        }
+
+        $specs[$full_key] = $patch;
+      }
+    }
+
+    foreach ($specs as $key => $patch) {
+      foreach ($patch['after'] as $after) {
+        if (empty($specs[$after])) {
+          throw new Exception(
+            "Patch '{$key}' references nonexistent dependency, '{$after}'. ".
+            "Patches may only depend on patches which actually exist.");
+        }
+      }
+    }
+
+    $patches = array();
+    foreach ($specs as $full_key => $spec) {
+      $patches[$full_key] = new PhabricatorStoragePatch($spec);
+    }
+
+    // TODO: Detect cycles?
+
+    return $patches;
+  }
+
+}
diff --git a/src/infrastructure/setup/sql/__init__.php b/src/infrastructure/setup/sql/base/__init__.php
similarity index 62%
copy from src/infrastructure/setup/sql/__init__.php
copy to src/infrastructure/setup/sql/base/__init__.php
index 248a60848c..495c0c6b60 100644
--- a/src/infrastructure/setup/sql/__init__.php
+++ b/src/infrastructure/setup/sql/base/__init__.php
@@ -1,14 +1,15 @@
 <?php
 /**
  * This file is automatically generated. Lint this module to rebuild it.
  * @generated
  */
 
 
 
-phutil_require_module('phutil', 'filesystem/filefinder');
-phutil_require_module('phutil', 'moduleutils');
+phutil_require_module('phabricator', 'infrastructure/setup/storage/patch');
+
+phutil_require_module('phutil', 'symbols');
 phutil_require_module('phutil', 'utils');
 
 
 phutil_require_source('PhabricatorSQLPatchList.php');
diff --git a/src/infrastructure/setup/sql/phabricator/PhabricatorBuiltinPatchList.php b/src/infrastructure/setup/sql/phabricator/PhabricatorBuiltinPatchList.php
new file mode 100644
index 0000000000..c5517c2a71
--- /dev/null
+++ b/src/infrastructure/setup/sql/phabricator/PhabricatorBuiltinPatchList.php
@@ -0,0 +1,853 @@
+<?php
+
+/*
+ * Copyright 2012 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
+
+  public function getNamespace() {
+    return 'phabricator';
+  }
+
+  private function getPatchPath($file) {
+    $root = dirname(phutil_get_library_root('phabricator'));
+    $path = $root.'/resources/sql/patches/'.$file;
+
+    // Make sure it exists.
+    Filesystem::readFile($path);
+
+    return $path;
+  }
+
+  public function getPatches() {
+    return array(
+      'db.audit' => array(
+        'type'  => 'db',
+        'name'  => 'audit',
+        'after' => array( /* First Patch */ ),
+      ),
+      'db.chatlog' => array(
+        'type'  => 'db',
+        'name'  => 'chatlog',
+      ),
+      'db.conduit' => array(
+        'type'  => 'db',
+        'name'  => 'conduit',
+      ),
+      'db.countdown' => array(
+        'type'  => 'db',
+        'name'  => 'countdown',
+      ),
+      'db.daemon' => array(
+        'type'  => 'db',
+        'name'  => 'daemon',
+      ),
+      'db.differential' => array(
+        'type'  => 'db',
+        'name'  => 'differential',
+      ),
+      'db.draft' => array(
+        'type'  => 'db',
+        'name'  => 'draft',
+      ),
+      'db.drydock' => array(
+        'type'  => 'db',
+        'name'  => 'drydock',
+      ),
+      'db.feed' => array(
+        'type'  => 'db',
+        'name'  => 'feed',
+      ),
+      'db.file' => array(
+        'type'  => 'db',
+        'name'  => 'file',
+      ),
+      'db.flag' => array(
+        'type'  => 'db',
+        'name'  => 'flag',
+      ),
+      'db.herald' => array(
+        'type'  => 'db',
+        'name'  => 'herald',
+      ),
+      'db.maniphest' => array(
+        'type'  => 'db',
+        'name'  => 'maniphest',
+      ),
+      'db.meta_data' => array(
+        'type'  => 'db',
+        'name'  => 'meta_data',
+      ),
+      'db.metamta' => array(
+        'type'  => 'db',
+        'name'  => 'metamta',
+      ),
+      'db.oauth_server' => array(
+        'type'  => 'db',
+        'name'  => 'oauth_server',
+      ),
+      'db.owners' => array(
+        'type'  => 'db',
+        'name'  => 'owners',
+      ),
+      'db.pastebin' => array(
+        'type'  => 'db',
+        'name'  => 'pastebin',
+      ),
+      'db.phame' => array(
+        'type'  => 'db',
+        'name'  => 'phame',
+      ),
+      'db.phid' => array(
+        'type'  => 'db',
+        'name'  => 'phid',
+      ),
+      'db.phriction' => array(
+        'type'  => 'db',
+        'name'  => 'phriction',
+      ),
+      'db.project' => array(
+        'type'  => 'db',
+        'name'  => 'project',
+      ),
+      'db.repository' => array(
+        'type'  => 'db',
+        'name'  => 'repository',
+      ),
+      'db.search' => array(
+        'type'  => 'db',
+        'name'  => 'search',
+      ),
+      'db.slowvote' => array(
+        'type'  => 'db',
+        'name'  => 'slowvote',
+      ),
+      'db.timeline' => array(
+        'type'  => 'db',
+        'name'  => 'timeline',
+      ),
+      'db.user' => array(
+        'type'  => 'db',
+        'name'  => 'user',
+      ),
+      'db.worker' => array(
+        'type'  => 'db',
+        'name'  => 'worker',
+      ),
+      'db.xhpastview' => array(
+        'type'  => 'db',
+        'name'  => 'xhpastview',
+      ),
+      '0000.legacy.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('0000.legacy.sql'),
+        'legacy'  => 0,
+      ),
+      '000.project.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('000.project.sql'),
+        'legacy'  => 0,
+      ),
+      '001.maniphest_projects.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('001.maniphest_projects.sql'),
+        'legacy'  => 1,
+      ),
+      '002.oauth.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('002.oauth.sql'),
+        'legacy'  => 2,
+      ),
+      '003.more_oauth.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('003.more_oauth.sql'),
+        'legacy'  => 3,
+      ),
+      '004.daemonrepos.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('004.daemonrepos.sql'),
+        'legacy'  => 4,
+      ),
+      '005.workers.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('005.workers.sql'),
+        'legacy'  => 5,
+      ),
+      '006.repository.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('006.repository.sql'),
+        'legacy'  => 6,
+      ),
+      '007.daemonlog.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('007.daemonlog.sql'),
+        'legacy'  => 7,
+      ),
+      '008.repoopt.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('008.repoopt.sql'),
+        'legacy'  => 8,
+      ),
+      '009.repo_summary.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('009.repo_summary.sql'),
+        'legacy'  => 9,
+      ),
+      '010.herald.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('010.herald.sql'),
+        'legacy'  => 10,
+      ),
+      '011.badcommit.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('011.badcommit.sql'),
+        'legacy'  => 11,
+      ),
+      '012.dropphidtype.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('012.dropphidtype.sql'),
+        'legacy'  => 12,
+      ),
+      '013.commitdetail.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('013.commitdetail.sql'),
+        'legacy'  => 13,
+      ),
+      '014.shortcuts.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('014.shortcuts.sql'),
+        'legacy'  => 14,
+      ),
+      '015.preferences.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('015.preferences.sql'),
+        'legacy'  => 15,
+      ),
+      '016.userrealnameindex.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('016.userrealnameindex.sql'),
+        'legacy'  => 16,
+      ),
+      '017.sessionkeys.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('017.sessionkeys.sql'),
+        'legacy'  => 17,
+      ),
+      '018.owners.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('018.owners.sql'),
+        'legacy'  => 18,
+      ),
+      '019.arcprojects.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('019.arcprojects.sql'),
+        'legacy'  => 19,
+      ),
+      '020.pathcapital.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('020.pathcapital.sql'),
+        'legacy'  => 20,
+      ),
+      '021.xhpastview.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('021.xhpastview.sql'),
+        'legacy'  => 21,
+      ),
+      '022.differentialcommit.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('022.differentialcommit.sql'),
+        'legacy'  => 22,
+      ),
+      '023.dxkeys.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('023.dxkeys.sql'),
+        'legacy'  => 23,
+      ),
+      '024.mlistkeys.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('024.mlistkeys.sql'),
+        'legacy'  => 24,
+      ),
+      '025.commentopt.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('025.commentopt.sql'),
+        'legacy'  => 25,
+      ),
+      '026.diffpropkey.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('026.diffpropkey.sql'),
+        'legacy'  => 26,
+      ),
+      '027.metamtakeys.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('027.metamtakeys.sql'),
+        'legacy'  => 27,
+      ),
+      '028.systemagent.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('028.systemagent.sql'),
+        'legacy'  => 28,
+      ),
+      '029.cursors.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('029.cursors.sql'),
+        'legacy'  => 29,
+      ),
+      '030.imagemacro.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('030.imagemacro.sql'),
+        'legacy'  => 30,
+      ),
+      '031.workerrace.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('031.workerrace.sql'),
+        'legacy'  => 31,
+      ),
+      '032.viewtime.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('032.viewtime.sql'),
+        'legacy'  => 32,
+      ),
+      '033.privtest.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('033.privtest.sql'),
+        'legacy'  => 33,
+      ),
+      '034.savedheader.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('034.savedheader.sql'),
+        'legacy'  => 34,
+      ),
+      '035.proxyimage.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('035.proxyimage.sql'),
+        'legacy'  => 35,
+      ),
+      '036.mailkey.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('036.mailkey.sql'),
+        'legacy'  => 36,
+      ),
+      '037.setuptest.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('037.setuptest.sql'),
+        'legacy'  => 37,
+      ),
+      '038.admin.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('038.admin.sql'),
+        'legacy'  => 38,
+      ),
+      '039.userlog.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('039.userlog.sql'),
+        'legacy'  => 39,
+      ),
+      '040.transform.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('040.transform.sql'),
+        'legacy'  => 40,
+      ),
+      '041.heraldrepetition.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('041.heraldrepetition.sql'),
+        'legacy'  => 41,
+      ),
+      '042.commentmetadata.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('042.commentmetadata.sql'),
+        'legacy'  => 42,
+      ),
+      '043.pastebin.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('043.pastebin.sql'),
+        'legacy'  => 43,
+      ),
+      '044.countdown.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('044.countdown.sql'),
+        'legacy'  => 44,
+      ),
+      '045.timezone.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('045.timezone.sql'),
+        'legacy'  => 45,
+      ),
+      '046.conduittoken.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('046.conduittoken.sql'),
+        'legacy'  => 46,
+      ),
+      '047.projectstatus.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('047.projectstatus.sql'),
+        'legacy'  => 47,
+      ),
+      '048.relationshipkeys.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('048.relationshipkeys.sql'),
+        'legacy'  => 48,
+      ),
+      '049.projectowner.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('049.projectowner.sql'),
+        'legacy'  => 49,
+      ),
+      '050.taskdenormal.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('050.taskdenormal.sql'),
+        'legacy'  => 50,
+      ),
+      '051.projectfilter.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('051.projectfilter.sql'),
+        'legacy'  => 51,
+      ),
+      '052.pastelanguage.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('052.pastelanguage.sql'),
+        'legacy'  => 52,
+      ),
+      '053.feed.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('053.feed.sql'),
+        'legacy'  => 53,
+      ),
+      '054.subscribers.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('054.subscribers.sql'),
+        'legacy'  => 54,
+      ),
+      '055.add_author_to_files.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('055.add_author_to_files.sql'),
+        'legacy'  => 55,
+      ),
+      '056.slowvote.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('056.slowvote.sql'),
+        'legacy'  => 56,
+      ),
+      '057.parsecache.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('057.parsecache.sql'),
+        'legacy'  => 57,
+      ),
+      '058.missingkeys.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('058.missingkeys.sql'),
+        'legacy'  => 58,
+      ),
+      '059.engines.php' => array(
+        'type'    => 'php',
+        'name'    => $this->getPatchPath('059.engines.php'),
+        'legacy'  => 59,
+      ),
+      '060.phriction.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('060.phriction.sql'),
+        'legacy'  => 60,
+      ),
+      '061.phrictioncontent.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('061.phrictioncontent.sql'),
+        'legacy'  => 61,
+      ),
+      '062.phrictionmenu.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('062.phrictionmenu.sql'),
+        'legacy'  => 62,
+      ),
+      '063.pasteforks.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('063.pasteforks.sql'),
+        'legacy'  => 63,
+      ),
+      '064.subprojects.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('064.subprojects.sql'),
+        'legacy'  => 64,
+      ),
+      '065.sshkeys.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('065.sshkeys.sql'),
+        'legacy'  => 65,
+      ),
+      '066.phrictioncontent.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('066.phrictioncontent.sql'),
+        'legacy'  => 66,
+      ),
+      '067.preferences.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('067.preferences.sql'),
+        'legacy'  => 67,
+      ),
+      '068.maniphestauxiliarystorage.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('068.maniphestauxiliarystorage.sql'),
+        'legacy'  => 68,
+      ),
+      '069.heraldxscript.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('069.heraldxscript.sql'),
+        'legacy'  => 69,
+      ),
+      '070.differentialaux.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('070.differentialaux.sql'),
+        'legacy'  => 70,
+      ),
+      '071.contentsource.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('071.contentsource.sql'),
+        'legacy'  => 71,
+      ),
+      '072.blamerevert.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('072.blamerevert.sql'),
+        'legacy'  => 72,
+      ),
+      '073.reposymbols.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('073.reposymbols.sql'),
+        'legacy'  => 73,
+      ),
+      '074.affectedpath.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('074.affectedpath.sql'),
+        'legacy'  => 74,
+      ),
+      '075.revisionhash.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('075.revisionhash.sql'),
+        'legacy'  => 75,
+      ),
+      '076.indexedlanguages.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('076.indexedlanguages.sql'),
+        'legacy'  => 76,
+      ),
+      '077.originalemail.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('077.originalemail.sql'),
+        'legacy'  => 77,
+      ),
+      '078.nametoken.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('078.nametoken.sql'),
+        'legacy'  => 78,
+      ),
+      '079.nametokenindex.php' => array(
+        'type'    => 'php',
+        'name'    => $this->getPatchPath('079.nametokenindex.php'),
+        'legacy'  => 79,
+      ),
+      '080.filekeys.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('080.filekeys.sql'),
+        'legacy'  => 80,
+      ),
+      '081.filekeys.php' => array(
+        'type'    => 'php',
+        'name'    => $this->getPatchPath('081.filekeys.php'),
+        'legacy'  => 81,
+      ),
+      '082.xactionkey.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('082.xactionkey.sql'),
+        'legacy'  => 82,
+      ),
+      '083.dxviewtime.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('083.dxviewtime.sql'),
+        'legacy'  => 83,
+      ),
+      '084.pasteauthorkey.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('084.pasteauthorkey.sql'),
+        'legacy'  => 84,
+      ),
+      '085.packagecommitrelationship.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('085.packagecommitrelationship.sql'),
+        'legacy'  => 85,
+      ),
+      '086.formeraffil.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('086.formeraffil.sql'),
+        'legacy'  => 86,
+      ),
+      '087.phrictiondelete.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('087.phrictiondelete.sql'),
+        'legacy'  => 87,
+      ),
+      '088.audit.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('088.audit.sql'),
+        'legacy'  => 88,
+      ),
+      '089.projectwiki.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('089.projectwiki.sql'),
+        'legacy'  => 89,
+      ),
+      '090.forceuniqueprojectnames.php' => array(
+        'type'    => 'php',
+        'name'    => $this->getPatchPath('090.forceuniqueprojectnames.php'),
+        'legacy'  => 90,
+      ),
+      '091.uniqueslugkey.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('091.uniqueslugkey.sql'),
+        'legacy'  => 91,
+      ),
+      '092.dropgithubnotification.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('092.dropgithubnotification.sql'),
+        'legacy'  => 92,
+      ),
+      '093.gitremotes.php' => array(
+        'type'    => 'php',
+        'name'    => $this->getPatchPath('093.gitremotes.php'),
+        'legacy'  => 93,
+      ),
+      '094.phrictioncolumn.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('094.phrictioncolumn.sql'),
+        'legacy'  => 94,
+      ),
+      '095.directory.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('095.directory.sql'),
+        'legacy'  => 95,
+      ),
+      '096.filename.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('096.filename.sql'),
+        'legacy'  => 96,
+      ),
+      '097.heraldruletypes.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('097.heraldruletypes.sql'),
+        'legacy'  => 97,
+      ),
+      '098.heraldruletypemigration.php' => array(
+        'type'    => 'php',
+        'name'    => $this->getPatchPath('098.heraldruletypemigration.php'),
+        'legacy'  => 98,
+      ),
+      '099.drydock.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('099.drydock.sql'),
+        'legacy'  => 99,
+      ),
+      '100.projectxaction.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('100.projectxaction.sql'),
+        'legacy'  => 100,
+      ),
+      '101.heraldruleapplied.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('101.heraldruleapplied.sql'),
+        'legacy'  => 101,
+      ),
+      '102.heraldcleanup.php' => array(
+        'type'    => 'php',
+        'name'    => $this->getPatchPath('102.heraldcleanup.php'),
+        'legacy'  => 102,
+      ),
+      '103.heraldedithistory.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('103.heraldedithistory.sql'),
+        'legacy'  => 103,
+      ),
+      '104.searchkey.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('104.searchkey.sql'),
+        'legacy'  => 104,
+      ),
+      '105.mimetype.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('105.mimetype.sql'),
+        'legacy'  => 105,
+      ),
+      '106.chatlog.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('106.chatlog.sql'),
+        'legacy'  => 106,
+      ),
+      '107.oauthserver.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('107.oauthserver.sql'),
+        'legacy'  => 107,
+      ),
+      '108.oauthscope.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('108.oauthscope.sql'),
+        'legacy'  => 108,
+      ),
+      '109.oauthclientphidkey.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('109.oauthclientphidkey.sql'),
+        'legacy'  => 109,
+      ),
+      '110.commitaudit.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('110.commitaudit.sql'),
+        'legacy'  => 110,
+      ),
+      '111.commitauditmigration.php' => array(
+        'type'    => 'php',
+        'name'    => $this->getPatchPath('111.commitauditmigration.php'),
+        'legacy'  => 111,
+      ),
+      '112.oauthaccesscoderedirecturi.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('112.oauthaccesscoderedirecturi.sql'),
+        'legacy'  => 112,
+      ),
+      '113.lastreviewer.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('113.lastreviewer.sql'),
+        'legacy'  => 113,
+      ),
+      '114.auditrequest.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('114.auditrequest.sql'),
+        'legacy'  => 114,
+      ),
+      '115.prepareutf8.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('115.prepareutf8.sql'),
+        'legacy'  => 115,
+      ),
+      '116.utf8-backup-first-expect-wait.sql' => array(
+        'type'    => 'sql',
+        'name'    =>
+          $this->getPatchPath('116.utf8-backup-first-expect-wait.sql'),
+        'legacy'  => 116,
+      ),
+      '117.repositorydescription.php' => array(
+        'type'    => 'php',
+        'name'    => $this->getPatchPath('117.repositorydescription.php'),
+        'legacy'  => 117,
+      ),
+      '118.auditinline.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('118.auditinline.sql'),
+        'legacy'  => 118,
+      ),
+      '119.filehash.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('119.filehash.sql'),
+        'legacy'  => 119,
+      ),
+      '120.noop.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('120.noop.sql'),
+        'legacy'  => 120,
+      ),
+      '121.drydocklog.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('121.drydocklog.sql'),
+        'legacy'  => 121,
+      ),
+      '122.flag.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('122.flag.sql'),
+        'legacy'  => 122,
+      ),
+      '123.heraldrulelog.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('123.heraldrulelog.sql'),
+        'legacy'  => 123,
+      ),
+      '124.subpriority.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('124.subpriority.sql'),
+        'legacy'  => 124,
+      ),
+      '125.ipv6.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('125.ipv6.sql'),
+        'legacy'  => 125,
+      ),
+      '126.edges.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('126.edges.sql'),
+        'legacy'  => 126,
+      ),
+      '127.userkeybody.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('127.userkeybody.sql'),
+        'legacy'  => 127,
+      ),
+      '128.phabricatorcom.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('128.phabricatorcom.sql'),
+        'legacy'  => 128,
+      ),
+      '129.savedquery.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('129.savedquery.sql'),
+        'legacy'  => 129,
+      ),
+      '130.denormalrevisionquery.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('130.denormalrevisionquery.sql'),
+        'legacy'  => 130,
+      ),
+      '131.migraterevisionquery.php' => array(
+        'type'    => 'php',
+        'name'    => $this->getPatchPath('131.migraterevisionquery.php'),
+        'legacy'  => 131,
+      ),
+      '132.phame.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('132.phame.sql'),
+        'legacy'  => 132,
+      ),
+      '133.imagemacro.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('133.imagemacro.sql'),
+        'legacy'  => 133,
+      ),
+      '134.emptysearch.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('134.emptysearch.sql'),
+        'legacy'  => 134,
+      ),
+      '135.datecommitted.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('135.datecommitted.sql'),
+        'legacy'  => 135,
+      ),
+      '136.sex.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('136.sex.sql'),
+        'legacy'  => 136,
+      ),
+      '137.auditmetadata.sql' => array(
+        'type'    => 'sql',
+        'name'    => $this->getPatchPath('137.auditmetadata.sql'),
+        'legacy'  => 137,
+      ),
+    );
+  }
+
+}
diff --git a/src/infrastructure/setup/sql/phabricator/__init__.php b/src/infrastructure/setup/sql/phabricator/__init__.php
new file mode 100644
index 0000000000..092ff2773d
--- /dev/null
+++ b/src/infrastructure/setup/sql/phabricator/__init__.php
@@ -0,0 +1,15 @@
+<?php
+/**
+ * This file is automatically generated. Lint this module to rebuild it.
+ * @generated
+ */
+
+
+
+phutil_require_module('phabricator', 'infrastructure/setup/sql/base');
+
+phutil_require_module('phutil', 'filesystem');
+phutil_require_module('phutil', 'moduleutils');
+
+
+phutil_require_source('PhabricatorBuiltinPatchList.php');
diff --git a/src/infrastructure/setup/storage/management/PhabricatorStorageManagementAPI.php b/src/infrastructure/setup/storage/management/PhabricatorStorageManagementAPI.php
new file mode 100644
index 0000000000..2b7ea1c140
--- /dev/null
+++ b/src/infrastructure/setup/storage/management/PhabricatorStorageManagementAPI.php
@@ -0,0 +1,193 @@
+<?php
+
+/*
+ * Copyright 2012 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+final class PhabricatorStorageManagementAPI {
+
+  private $host;
+  private $user;
+  private $password;
+  private $namespace;
+
+  public function setNamespace($namespace) {
+    $this->namespace = $namespace;
+    PhabricatorLiskDAO::setApplicationNamespace($namespace);
+    return $this;
+  }
+
+  public function getNamespace() {
+    return $this->namespace;
+  }
+
+  public function setUser($user) {
+    $this->user = $user;
+    return $this;
+  }
+
+  public function getUser() {
+    return $this->user;
+  }
+
+  public function setPassword($password) {
+    $this->password = $password;
+    return $this;
+  }
+
+  public function getPassword() {
+    return $this->password;
+  }
+
+  public function setHost($host) {
+    $this->host = $host;
+    return $this;
+  }
+
+  public function getHost() {
+    return $this->host;
+  }
+
+  public function getDatabaseName($fragment) {
+    return $this->namespace.'_'.$fragment;
+  }
+
+  public function getDatabaseList(array $patches) {
+    assert_instances_of($patches, 'PhabricatorStoragePatch');
+
+    $list = array();
+
+    foreach ($patches as $patch) {
+      if ($patch->getType() == 'db') {
+        $list[] = $this->getDatabaseName($patch->getName());
+      }
+    }
+
+    return $list;
+  }
+
+  public function getConn($fragment, $select_database = true) {
+    return PhabricatorEnv::newObjectFromConfig(
+      'mysql.implementation',
+      array(
+        array(
+          'user'      => $this->user,
+          'pass'      => $this->password,
+          'host'      => $this->host,
+          'database'  => $select_database
+            ? $this->getDatabaseName($fragment)
+            : null,
+        ),
+      ));
+  }
+
+  public function getAppliedPatches() {
+    try {
+      $applied = queryfx_all(
+        $this->getConn('meta_data'),
+        'SELECT patch FROM patch_status');
+      return ipull($applied, 'patch');
+    } catch (AphrontQueryException $ex) {
+      return null;
+    }
+  }
+
+  public function createDatabase($fragment) {
+    queryfx(
+      $this->getConn($fragment, $select_database = false),
+      'CREATE DATABASE IF NOT EXISTS %T COLLATE utf8_general_ci',
+      $this->getDatabaseName($fragment));
+  }
+
+  public function createTable($fragment, $table, array $cols) {
+    queryfx(
+      $this->getConn($fragment),
+      'CREATE TABLE IF NOT EXISTS %T.%T (%Q) '.
+      'ENGINE=InnoDB, COLLATE utf8_general_ci',
+      $this->getDatabaseName($fragment),
+      $table,
+      implode(', ', $cols));
+  }
+
+  public function getLegacyPatches(array $patches) {
+    assert_instances_of($patches, 'PhabricatorStoragePatch');
+
+    try {
+      $row = queryfx_one(
+        $this->getConn('meta_data'),
+        'SELECT version FROM %T',
+        'schema_version');
+      $version = $row['version'];
+    } catch (AphrontQueryException $ex) {
+      return array();
+    }
+
+    $legacy = array();
+    foreach ($patches as $key => $patch) {
+      if ($patch->getLegacy() !== false && $patch->getLegacy() <= $version) {
+        $legacy[] = $key;
+      }
+    }
+
+    return $legacy;
+  }
+
+  public function markPatchApplied($patch) {
+    queryfx(
+      $this->getConn('meta_data'),
+      'INSERT INTO %T (patch, applied) VALUES (%s, %d)',
+      'patch_status',
+      $patch,
+      time());
+  }
+
+  public function applyPatch(PhabricatorStoragePatch $patch) {
+    $type = $patch->getType();
+    $name = $patch->getName();
+    switch ($type) {
+      case 'db':
+        $this->createDatabase($name);
+        break;
+      case 'sql':
+        $this->applyPatchSQL($name);
+        break;
+      case 'php':
+        $this->applyPatchPHP($name);
+        break;
+      default:
+        throw new Exception("Unable to apply patch of type '{$type}'.");
+    }
+  }
+
+  public function applyPatchSQL($sql) {
+    $sql = Filesystem::readFile($sql);
+    $queries = preg_split('/;\s+/', $sql);
+    $queries = array_filter($queries);
+
+    foreach ($queries as $query) {
+      $query = str_replace('{$NAMESPACE}', $this->namespace, $query);
+      queryfx(
+        $this->getConn('meta_data', $select_database = false),
+        '%Q',
+        $query);
+    }
+  }
+
+  public function applyPatchPHP($script) {
+    $schema_conn = $this->getConn('meta_data', $select_database = false);
+    require_once $script;
+  }
+
+}
diff --git a/src/infrastructure/setup/__init__.php b/src/infrastructure/setup/storage/management/__init__.php
similarity index 50%
copy from src/infrastructure/setup/__init__.php
copy to src/infrastructure/setup/storage/management/__init__.php
index 36ade10b12..15e71f43d4 100644
--- a/src/infrastructure/setup/__init__.php
+++ b/src/infrastructure/setup/storage/management/__init__.php
@@ -1,21 +1,17 @@
 <?php
 /**
  * This file is automatically generated. Lint this module to rebuild it.
  * @generated
  */
 
 
 
+phutil_require_module('phabricator', 'applications/base/storage/lisk');
 phutil_require_module('phabricator', 'infrastructure/env');
-phutil_require_module('phabricator', 'infrastructure/setup/sql');
 phutil_require_module('phabricator', 'storage/queryfx');
 
 phutil_require_module('phutil', 'filesystem');
-phutil_require_module('phutil', 'filesystem/tempfile');
-phutil_require_module('phutil', 'future/exec');
-phutil_require_module('phutil', 'moduleutils');
-phutil_require_module('phutil', 'parser/uri');
 phutil_require_module('phutil', 'utils');
 
 
-phutil_require_source('PhabricatorSetup.php');
+phutil_require_source('PhabricatorStorageManagementAPI.php');
diff --git a/src/infrastructure/setup/storage/patch/PhabricatorStoragePatch.php b/src/infrastructure/setup/storage/patch/PhabricatorStoragePatch.php
new file mode 100644
index 0000000000..10972f2e24
--- /dev/null
+++ b/src/infrastructure/setup/storage/patch/PhabricatorStoragePatch.php
@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * Copyright 2012 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+final class PhabricatorStoragePatch {
+
+  private $key;
+  private $fullKey;
+  private $name;
+  private $type;
+  private $after;
+  private $legacy;
+
+  public function __construct(array $dict) {
+    $this->key      = $dict['key'];
+    $this->type     = $dict['type'];
+    $this->fullKey  = $dict['fullKey'];
+    $this->legacy   = $dict['legacy'];
+    $this->name     = $dict['name'];
+    $this->after    = $dict['after'];
+  }
+
+  public function getLegacy() {
+    return $this->legacy;
+  }
+
+  public function getAfter() {
+    return $this->after;
+  }
+
+  public function getType() {
+    return $this->type;
+  }
+
+  public function getName() {
+    return $this->name;
+  }
+
+  public function getFullKey() {
+    return $this->fullKey;
+  }
+
+  public function getKey() {
+    return $this->key;
+  }
+
+}
diff --git a/src/infrastructure/setup/storage/patch/__init__.php b/src/infrastructure/setup/storage/patch/__init__.php
new file mode 100644
index 0000000000..e4524d1884
--- /dev/null
+++ b/src/infrastructure/setup/storage/patch/__init__.php
@@ -0,0 +1,10 @@
+<?php
+/**
+ * This file is automatically generated. Lint this module to rebuild it.
+ * @generated
+ */
+
+
+
+
+phutil_require_source('PhabricatorStoragePatch.php');
diff --git a/src/storage/exception/schema/AphrontQuerySchemaException.php b/src/infrastructure/setup/storage/workflow/base/PhabricatorStorageManagementWorkflow.php
similarity index 51%
copy from src/storage/exception/schema/AphrontQuerySchemaException.php
copy to src/infrastructure/setup/storage/workflow/base/PhabricatorStorageManagementWorkflow.php
index a7cdd9f5d9..b07893cbc8 100644
--- a/src/storage/exception/schema/AphrontQuerySchemaException.php
+++ b/src/infrastructure/setup/storage/workflow/base/PhabricatorStorageManagementWorkflow.php
@@ -1,34 +1,48 @@
 <?php
 
 /*
  * Copyright 2012 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-/**
- * @group storage
- */
-final class AphrontQuerySchemaException extends AphrontQueryException {
+abstract class PhabricatorStorageManagementWorkflow
+  extends PhutilArgumentWorkflow {
+
+  private $patches;
+  private $api;
 
-  public function __construct($message) {
-    $message .=
-      "\n\n".
-      "NOTE: This usually indicates that the MySQL schema has not been ".
-      "properly upgraded. Run scripts/sql/upgrade_schema.php to ensure your ".
-      "schema is up to date.";
+  public function setPatches(array $patches) {
+    assert_instances_of($patches, 'PhabricatorStoragePatch');
+    $this->patches = $patches;
+    return $this;
+  }
+
+  public function getPatches() {
+    return $this->patches;
+  }
+
+  final public function setAPI(PhabricatorStorageManagementAPI $api) {
+    $this->api = $api;
+    return $this;
+  }
+
+  final public function getAPI() {
+    return $this->api;
+  }
 
-    parent::__construct($message);
+  public function isExecutable() {
+    return true;
   }
 
 }
diff --git a/src/infrastructure/setup/storage/workflow/base/__init__.php b/src/infrastructure/setup/storage/workflow/base/__init__.php
new file mode 100644
index 0000000000..894c23d92e
--- /dev/null
+++ b/src/infrastructure/setup/storage/workflow/base/__init__.php
@@ -0,0 +1,13 @@
+<?php
+/**
+ * This file is automatically generated. Lint this module to rebuild it.
+ * @generated
+ */
+
+
+
+phutil_require_module('phutil', 'parser/argument/workflow/base');
+phutil_require_module('phutil', 'utils');
+
+
+phutil_require_source('PhabricatorStorageManagementWorkflow.php');
diff --git a/src/storage/exception/schema/AphrontQuerySchemaException.php b/src/infrastructure/setup/storage/workflow/databases/PhabricatorStorageManagementDatabasesWorkflow.php
similarity index 54%
copy from src/storage/exception/schema/AphrontQuerySchemaException.php
copy to src/infrastructure/setup/storage/workflow/databases/PhabricatorStorageManagementDatabasesWorkflow.php
index a7cdd9f5d9..deb8708903 100644
--- a/src/storage/exception/schema/AphrontQuerySchemaException.php
+++ b/src/infrastructure/setup/storage/workflow/databases/PhabricatorStorageManagementDatabasesWorkflow.php
@@ -1,34 +1,39 @@
 <?php
 
 /*
  * Copyright 2012 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-/**
- * @group storage
- */
-final class AphrontQuerySchemaException extends AphrontQueryException {
+final class PhabricatorStorageManagementDatabasesWorkflow
+  extends PhabricatorStorageManagementWorkflow {
+
+  public function didConstruct() {
+    $this
+      ->setName('databases')
+      ->setExamples('**databases** [__options__]')
+      ->setSynopsis('List Phabricator databases.');
+  }
+
+  public function execute(PhutilArgumentParser $args) {
+    $api = $this->getAPI();
+    $patches = $this->getPatches();
 
-  public function __construct($message) {
-    $message .=
-      "\n\n".
-      "NOTE: This usually indicates that the MySQL schema has not been ".
-      "properly upgraded. Run scripts/sql/upgrade_schema.php to ensure your ".
-      "schema is up to date.";
+    $databases = $api->getDatabaseList($patches);
+    echo implode("\n", $databases)."\n";
 
-    parent::__construct($message);
+    return 0;
   }
 
 }
diff --git a/src/infrastructure/setup/storage/workflow/databases/__init__.php b/src/infrastructure/setup/storage/workflow/databases/__init__.php
new file mode 100644
index 0000000000..8269d2ee90
--- /dev/null
+++ b/src/infrastructure/setup/storage/workflow/databases/__init__.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * This file is automatically generated. Lint this module to rebuild it.
+ * @generated
+ */
+
+
+
+phutil_require_module('phabricator', 'infrastructure/setup/storage/workflow/base');
+
+
+phutil_require_source('PhabricatorStorageManagementDatabasesWorkflow.php');
diff --git a/src/infrastructure/setup/storage/workflow/destroy/PhabricatorStorageManagementDestroyWorkflow.php b/src/infrastructure/setup/storage/workflow/destroy/PhabricatorStorageManagementDestroyWorkflow.php
new file mode 100644
index 0000000000..5bc13ecd94
--- /dev/null
+++ b/src/infrastructure/setup/storage/workflow/destroy/PhabricatorStorageManagementDestroyWorkflow.php
@@ -0,0 +1,74 @@
+<?php
+
+/*
+ * Copyright 2012 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+final class PhabricatorStorageManagementDestroyWorkflow
+  extends PhabricatorStorageManagementWorkflow {
+
+  public function didConstruct() {
+    $this
+      ->setName('destroy')
+      ->setExamples('**destroy** [__options__]')
+      ->setSynopsis('Permanently destroy all storage and data.');
+  }
+
+  public function execute(PhutilArgumentParser $args) {
+    $is_dry = $args->getArg('dryrun');
+    $is_force = $args->getArg('force');
+
+    if (!$is_dry && !$is_force) {
+      echo phutil_console_wrap(
+        "Are you completely sure you really want to permanently destroy all ".
+        "storage for Phabricator data? This operation can not be undone and ".
+        "your data will not be recoverable if you proceed.");
+
+      if (!phutil_console_confirm('Permanently destroy all data?')) {
+        echo "Cancelled.\n";
+        exit(1);
+      }
+
+      if (!phutil_console_confirm('Really destroy all data forever?')) {
+        echo "Cancelled.\n";
+        exit(1);
+      }
+    }
+
+    $api = $this->getAPI();
+    $patches = $this->getPatches();
+
+    $databases = $api->getDatabaseList($patches);
+    $databases[] = $api->getDatabaseName('meta_data');
+    foreach ($databases as $database) {
+      if ($is_dry) {
+        echo "DRYRUN: Would drop database '{$database}'.\n";
+      } else {
+        echo "Dropping database '{$database}'...\n";
+        queryfx(
+          $api->getConn('meta_data', $select_database = false),
+          'DROP DATABASE IF EXISTS %T',
+          $database);
+      }
+    }
+
+    if (!$is_dry) {
+      echo "Storage was destroyed.\n";
+    }
+
+    return 0;
+  }
+
+}
diff --git a/src/infrastructure/setup/storage/workflow/destroy/__init__.php b/src/infrastructure/setup/storage/workflow/destroy/__init__.php
new file mode 100644
index 0000000000..d81769095a
--- /dev/null
+++ b/src/infrastructure/setup/storage/workflow/destroy/__init__.php
@@ -0,0 +1,15 @@
+<?php
+/**
+ * This file is automatically generated. Lint this module to rebuild it.
+ * @generated
+ */
+
+
+
+phutil_require_module('phabricator', 'infrastructure/setup/storage/workflow/base');
+phutil_require_module('phabricator', 'storage/queryfx');
+
+phutil_require_module('phutil', 'console');
+
+
+phutil_require_source('PhabricatorStorageManagementDestroyWorkflow.php');
diff --git a/src/infrastructure/setup/storage/workflow/dump/PhabricatorStorageManagementDumpWorkflow.php b/src/infrastructure/setup/storage/workflow/dump/PhabricatorStorageManagementDumpWorkflow.php
new file mode 100644
index 0000000000..a58d4ba673
--- /dev/null
+++ b/src/infrastructure/setup/storage/workflow/dump/PhabricatorStorageManagementDumpWorkflow.php
@@ -0,0 +1,83 @@
+<?php
+
+/*
+ * Copyright 2012 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+final class PhabricatorStorageManagementDumpWorkflow
+  extends PhabricatorStorageManagementWorkflow {
+
+  public function didConstruct() {
+    $this
+      ->setName('dump')
+      ->setExamples('**dump** [__options__]')
+      ->setSynopsis('Dump all data in storage to stdout.');
+  }
+
+  public function execute(PhutilArgumentParser $args) {
+    $api = $this->getAPI();
+    $patches = $this->getPatches();
+
+    $applied = $api->getAppliedPatches();
+    if ($applied === null) {
+      $namespace = $api->getNamespace();
+      echo phutil_console_wrap(
+        phutil_console_format(
+          "**No Storage**: There is no database storage initialized in this ".
+          "storage namespace ('{$namespace}'). Use '**storage upgrade**' to ".
+          "initialize storage.\n"));
+      return 1;
+    }
+
+    $databases = $api->getDatabaseList($patches);
+
+    list($host, $port) = $this->getBareHostAndPort($api->getHost());
+
+    $flag_password = $api->getPassword()
+      ? csprintf('-p %s', $api->getPassword())
+      : '';
+
+    $flag_port = $port
+      ? csprintf('--port %d', $port)
+      : '';
+
+    return phutil_passthru(
+
+      'mysqldump --default-character-set=utf8 '.
+      '-u %s %C -h %s %C --databases %Ls',
+
+      $api->getUser(),
+      $flag_password,
+      $host,
+      $flag_port,
+      $databases);
+  }
+
+  private function getBareHostAndPort($host) {
+    // Split out port information, since the command-line client requires a
+    // separate flag for the port.
+    $uri = new PhutilURI('mysql://'.$host);
+    if ($uri->getPort()) {
+      $port = $uri->getPort();
+      $bare_hostname = $uri->getDomain();
+    } else {
+      $port = null;
+      $bare_hostname = $host;
+    }
+
+    return array($bare_hostname, $port);
+  }
+
+}
diff --git a/src/infrastructure/setup/storage/workflow/dump/__init__.php b/src/infrastructure/setup/storage/workflow/dump/__init__.php
new file mode 100644
index 0000000000..2fccc76c8a
--- /dev/null
+++ b/src/infrastructure/setup/storage/workflow/dump/__init__.php
@@ -0,0 +1,17 @@
+<?php
+/**
+ * This file is automatically generated. Lint this module to rebuild it.
+ * @generated
+ */
+
+
+
+phutil_require_module('phabricator', 'infrastructure/setup/storage/workflow/base');
+
+phutil_require_module('phutil', 'console');
+phutil_require_module('phutil', 'future/exec');
+phutil_require_module('phutil', 'parser/uri');
+phutil_require_module('phutil', 'xsprintf/csprintf');
+
+
+phutil_require_source('PhabricatorStorageManagementDumpWorkflow.php');
diff --git a/src/infrastructure/setup/storage/workflow/status/PhabricatorStorageManagementStatusWorkflow.php b/src/infrastructure/setup/storage/workflow/status/PhabricatorStorageManagementStatusWorkflow.php
new file mode 100644
index 0000000000..8f78789f6a
--- /dev/null
+++ b/src/infrastructure/setup/storage/workflow/status/PhabricatorStorageManagementStatusWorkflow.php
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * Copyright 2012 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+final class PhabricatorStorageManagementStatusWorkflow
+  extends PhabricatorStorageManagementWorkflow {
+
+  public function didConstruct() {
+    $this
+      ->setName('status')
+      ->setExamples('**status** [__options__]')
+      ->setSynopsis('Show patch application status.');
+  }
+
+  public function execute(PhutilArgumentParser $args) {
+    $api = $this->getAPI();
+    $patches = $this->getPatches();
+
+    $applied = $api->getAppliedPatches();
+
+    if ($applied === null) {
+      echo phutil_console_format(
+        "**Database Not Initialized**: Run **storage upgrade** to ".
+        "initialize.\n");
+
+      return 1;
+    }
+
+    $len = 0;
+    foreach ($patches as $patch) {
+      $len = max($len, strlen($patch->getFullKey()));
+    }
+
+    foreach ($patches as $patch) {
+      printf(
+
+        "% -".($len + 2)."s ".
+        "%-".strlen("Not Applied")."s   ".
+        "%-4s   ".
+        "%s\n",
+
+        $patch->getFullKey(),
+        in_array($patch->getFullKey(), $applied)
+          ? 'Applied'
+          : 'Not Applied',
+        $patch->getType(),
+        $patch->getName());
+    }
+
+    return 0;
+  }
+
+}
diff --git a/src/infrastructure/setup/storage/workflow/status/__init__.php b/src/infrastructure/setup/storage/workflow/status/__init__.php
new file mode 100644
index 0000000000..ec7209d0f6
--- /dev/null
+++ b/src/infrastructure/setup/storage/workflow/status/__init__.php
@@ -0,0 +1,14 @@
+<?php
+/**
+ * This file is automatically generated. Lint this module to rebuild it.
+ * @generated
+ */
+
+
+
+phutil_require_module('phabricator', 'infrastructure/setup/storage/workflow/base');
+
+phutil_require_module('phutil', 'console');
+
+
+phutil_require_source('PhabricatorStorageManagementStatusWorkflow.php');
diff --git a/src/infrastructure/setup/storage/workflow/upgrade/PhabricatorStorageManagementUpgradeWorkflow.php b/src/infrastructure/setup/storage/workflow/upgrade/PhabricatorStorageManagementUpgradeWorkflow.php
new file mode 100644
index 0000000000..50b2990fc6
--- /dev/null
+++ b/src/infrastructure/setup/storage/workflow/upgrade/PhabricatorStorageManagementUpgradeWorkflow.php
@@ -0,0 +1,209 @@
+<?php
+
+/*
+ * Copyright 2012 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+final class PhabricatorStorageManagementUpgradeWorkflow
+  extends PhabricatorStorageManagementWorkflow {
+
+  public function didConstruct() {
+    $this
+      ->setName('upgrade')
+      ->setExamples('**upgrade** [__options__]')
+      ->setSynopsis("Upgrade database schemata.")
+      ->setArguments(
+        array(
+          array(
+            'name'  => 'apply',
+            'param' => 'patch',
+            'help'  => 'Apply __patch__ explicitly. This is an advanced '.
+                       'feature for development and debugging; you should '.
+                       'not normally use this flag.',
+          ),
+          array(
+            'name'  => 'no-quickstart',
+            'help'  => 'Build storage patch-by-patch from scatch, even if it '.
+                       'could be loaded from the quickstart template.',
+          ),
+          array(
+            'name'  => 'init-only',
+            'help'  => 'Initialize storage only; do not apply patches.',
+          ),
+        ));
+  }
+
+  public function execute(PhutilArgumentParser $args) {
+    $is_dry = $args->getArg('dryrun');
+    $is_force = $args->getArg('force');
+
+    $api = $this->getAPI();
+    $patches = $this->getPatches();
+
+    if (!$is_dry && !$is_force) {
+      echo phutil_console_wrap(
+        "Before running storage upgrades, you should take down the ".
+        "Phabricator web interface and stop any running Phabricator ".
+        "daemons (you can disable this warning with --force).");
+
+      if (!phutil_console_confirm('Are you ready to continue?')) {
+        echo "Cancelled.\n";
+        return 1;
+      }
+    }
+
+    $apply_only = $args->getArg('apply');
+    if ($apply_only) {
+      if (empty($patches[$apply_only])) {
+        throw new PhutilArgumentUsageException(
+          "--apply argument '{$apply_only}' is not a valid patch. Use ".
+          "'storage status' to show patch status.");
+      }
+    }
+
+    $no_quickstart = $args->getArg('no-quickstart');
+    $init_only = $args->getArg('init-only');
+
+    $applied = $api->getAppliedPatches();
+    if ($applied === null) {
+
+      if ($is_dry) {
+        echo "DRYRUN: Patch metadata storage doesn't exist yet, it would ".
+             "be created.\n";
+        return 0;
+      }
+
+      if ($apply_only) {
+        throw new PhutilArgumentUsageException(
+          "Storage has not been initialized yet, you must initialize storage ".
+          "before selectively applying patches.");
+        return 1;
+      }
+
+      $legacy = $api->getLegacyPatches($patches);
+      if ($legacy || $no_quickstart || $init_only) {
+
+        // If we have legacy patches, we can't quickstart.
+
+        $api->createDatabase('meta_data');
+        $api->createTable(
+          'meta_data',
+          'patch_status',
+          array(
+            'patch VARCHAR(255) NOT NULL PRIMARY KEY COLLATE utf8_general_ci',
+            'applied INT UNSIGNED NOT NULL',
+          ));
+
+        foreach ($legacy as $patch) {
+          $api->markPatchApplied($patch);
+        }
+      } else {
+        echo "Loading quickstart template...\n";
+        $root = dirname(phutil_get_library_root('phabricator'));
+        $sql  = $root.'/resources/sql/quickstart.sql';
+        $api->applyPatchSQL($sql);
+      }
+    }
+
+    if ($init_only) {
+      echo "Storage initialized.\n";
+      return 0;
+    }
+
+    $applied = $api->getAppliedPatches();
+    $applied = array_fill_keys($applied, true);
+
+    $skip_mark = false;
+    if ($apply_only) {
+      if (isset($applied[$apply_only])) {
+
+        unset($applied[$apply_only]);
+        $skip_mark = true;
+
+        if (!$is_force && !$is_dry) {
+          echo phutil_console_wrap(
+            "Patch '{$apply_only}' has already been applied. Are you sure ".
+            "you want to apply it again? This may put your storage in a state ".
+            "that the upgrade scripts can not automatically manage.");
+          if (!phutil_console_confirm('Apply patch again?')) {
+            echo "Cancelled.\n";
+            return 1;
+          }
+        }
+      }
+    }
+
+    while (true) {
+      $applied_something = false;
+      foreach ($patches as $key => $patch) {
+        if (isset($applied[$key])) {
+          unset($patches[$key]);
+          continue;
+        }
+
+        if ($apply_only && $apply_only != $key) {
+          unset($patches[$key]);
+          continue;
+        }
+
+        $can_apply = true;
+        foreach ($patch->getAfter() as $after) {
+          if (empty($applied[$after])) {
+            if ($apply_only) {
+              echo "Unable to apply patch '{$apply_only}' because it depends ".
+                   "on patch '{$after}', which has not been applied.\n";
+              return 1;
+            }
+            $can_apply = false;
+            break;
+          }
+        }
+
+        if (!$can_apply) {
+          continue;
+        }
+
+        $applied_something = true;
+
+        if ($is_dry) {
+          echo "DRYRUN: Would apply patch '{$key}'.\n";
+        } else {
+          echo "Applying patch '{$key}'...\n";
+          $api->applyPatch($patch);
+          if (!$skip_mark) {
+            $api->markPatchApplied($key);
+          }
+        }
+
+        unset($patches[$key]);
+        $applied[$key] = true;
+      }
+
+      if (!$applied_something) {
+        if (count($patches)) {
+          throw new Exception(
+            "Some patches could not be applied: ".
+            implode(', ', array_keys($patches)));
+        } else if (!$is_dry && !$apply_only) {
+          echo "Storage is up to date. Use 'storage status' for details.\n";
+        }
+        break;
+      }
+    }
+
+    return 0;
+  }
+
+}
diff --git a/src/infrastructure/setup/storage/workflow/upgrade/__init__.php b/src/infrastructure/setup/storage/workflow/upgrade/__init__.php
new file mode 100644
index 0000000000..778aca94d0
--- /dev/null
+++ b/src/infrastructure/setup/storage/workflow/upgrade/__init__.php
@@ -0,0 +1,16 @@
+<?php
+/**
+ * This file is automatically generated. Lint this module to rebuild it.
+ * @generated
+ */
+
+
+
+phutil_require_module('phabricator', 'infrastructure/setup/storage/workflow/base');
+
+phutil_require_module('phutil', 'console');
+phutil_require_module('phutil', 'moduleutils');
+phutil_require_module('phutil', 'parser/argument/exception/usage');
+
+
+phutil_require_source('PhabricatorStorageManagementUpgradeWorkflow.php');
diff --git a/src/storage/exception/schema/AphrontQuerySchemaException.php b/src/storage/exception/schema/AphrontQuerySchemaException.php
index a7cdd9f5d9..02f9f095ec 100644
--- a/src/storage/exception/schema/AphrontQuerySchemaException.php
+++ b/src/storage/exception/schema/AphrontQuerySchemaException.php
@@ -1,34 +1,34 @@
 <?php
 
 /*
  * Copyright 2012 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 /**
  * @group storage
  */
 final class AphrontQuerySchemaException extends AphrontQueryException {
 
   public function __construct($message) {
     $message .=
       "\n\n".
       "NOTE: This usually indicates that the MySQL schema has not been ".
-      "properly upgraded. Run scripts/sql/upgrade_schema.php to ensure your ".
+      "properly upgraded. Run 'bin/storage upgrade' to ensure your ".
       "schema is up to date.";
 
     parent::__construct($message);
   }
 
 }