Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14473963
D14463.id35039.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
29 KB
Referenced Files
None
Subscribers
None
D14463.id35039.diff
View Options
diff --git a/scripts/sql/manage_storage.php b/scripts/sql/manage_storage.php
--- a/scripts/sql/manage_storage.php
+++ b/scripts/sql/manage_storage.php
@@ -63,16 +63,17 @@
$default_namespace),
),
array(
- 'name' => 'dryrun',
- 'help' => pht(
+ 'name' => 'dryrun',
+ 'help' => pht(
'Do not actually change anything, just show what would be changed.'),
),
array(
- 'name' => 'disable-utf8mb4',
- 'help' => pht(
- 'Disable utf8mb4, even if the database supports it. This is an '.
+ 'name' => 'disable-utf8mb4',
+ 'help' => pht(
+ 'Disable %s, even if the database supports it. This is an '.
'advanced feature used for testing changes to Phabricator; you '.
- 'should not normally use this flag.'),
+ 'should not normally use this flag.',
+ 'utf8mb4'),
),
));
} catch (PhutilArgumentUsageException $ex) {
@@ -83,12 +84,12 @@
// First, test that the Phabricator configuration is set up correctly. After
// we know this works we'll test any administrative credentials specifically.
-$test_api = new PhabricatorStorageManagementAPI();
-$test_api->setUser($default_user);
-$test_api->setHost($default_host);
-$test_api->setPort($default_port);
-$test_api->setPassword($conf->getPassword());
-$test_api->setNamespace($args->getArg('namespace'));
+$test_api = id(new PhabricatorStorageManagementAPI())
+ ->setUser($default_user)
+ ->setHost($default_host)
+ ->setPort($default_port)
+ ->setPassword($conf->getPassword())
+ ->setNamespace($args->getArg('namespace'));
try {
queryfx(
@@ -113,13 +114,10 @@
'--password'),
pht('Raw MySQL Error'),
$ex->getMessage());
-
echo phutil_console_wrap($message);
-
exit(1);
}
-
if ($args->getArg('password') === null) {
// This is already a PhutilOpaqueEnvelope.
$password = $conf->getPassword();
@@ -129,14 +127,14 @@
PhabricatorEnv::overrideConfig('mysql.pass', $args->getArg('password'));
}
-$api = new PhabricatorStorageManagementAPI();
-$api->setUser($args->getArg('user'));
-PhabricatorEnv::overrideConfig('mysql.user', $args->getArg('user'));
-$api->setHost($default_host);
-$api->setPort($default_port);
-$api->setPassword($password);
-$api->setNamespace($args->getArg('namespace'));
-$api->setDisableUTF8MB4($args->getArg('disable-utf8mb4'));
+$api = id(new PhabricatorStorageManagementAPI())
+ ->setUser($args->getArg('user'))
+ ->setHost($default_host)
+ ->setPort($default_port)
+ ->setPassword($password)
+ ->setNamespace($args->getArg('namespace'))
+ ->setDisableUTF8MB4($args->getArg('disable-utf8mb4'));
+PhabricatorEnv::overrideConfig('mysql.user', $api->getUser());
try {
queryfx(
@@ -154,9 +152,7 @@
'--password'),
pht('Raw MySQL Error'),
$ex->getMessage());
-
echo phutil_console_wrap($message);
-
exit(1);
}
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementAdjustWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementAdjustWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementAdjustWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementAdjustWorkflow.php
@@ -25,12 +25,12 @@
}
public function execute(PhutilArgumentParser $args) {
- $force = $args->getArg('force');
+ parent::execute($args);
+
$unsafe = $args->getArg('unsafe');
- $dry_run = $args->getArg('dryrun');
$this->requireAllPatchesApplied();
- return $this->adjustSchemata($force, $unsafe, $dry_run);
+ return $this->adjustSchemata($unsafe);
}
private function requireAllPatchesApplied() {
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDatabasesWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDatabasesWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDatabasesWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDatabasesWorkflow.php
@@ -11,12 +11,13 @@
}
public function execute(PhutilArgumentParser $args) {
- $api = $this->getAPI();
+ parent::execute($args);
+
+ $api = $this->getAPI();
$patches = $this->getPatches();
- $databases = $api->getDatabaseList($patches, $only_living = true);
+ $databases = $api->getDatabaseList($patches, true);
echo implode("\n", $databases)."\n";
-
return 0;
}
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDestroyWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDestroyWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDestroyWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDestroyWorkflow.php
@@ -21,28 +21,30 @@
}
public function execute(PhutilArgumentParser $args) {
- $is_dry = $args->getArg('dryrun');
- $is_force = $args->getArg('force');
+ parent::execute($args);
- if (!$is_dry && !$is_force) {
- echo phutil_console_wrap(
- pht(
- '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.'));
+ $console = PhutilConsole::getConsole();
+
+ if (!$this->isDryRun() && !$this->isForce()) {
+ $console->writeOut(
+ phutil_console_wrap(
+ pht(
+ '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(pht('Permanently destroy all data?'))) {
- echo pht('Cancelled.')."\n";
+ $console->writeOut("%s\n", pht('Cancelled.'));
exit(1);
}
if (!phutil_console_confirm(pht('Really destroy all data forever?'))) {
- echo pht('Cancelled.')."\n";
+ $console->writeOut("%s\n", pht('Cancelled.'));
exit(1);
}
}
- $api = $this->getAPI();
+ $api = $this->getAPI();
$patches = $this->getPatches();
if ($args->getArg('unittest-fixtures')) {
@@ -55,18 +57,23 @@
PhabricatorTestCase::NAMESPACE_PREFIX);
$databases = ipull($databases, 'db');
} else {
- $databases = $api->getDatabaseList($patches);
+ $databases = $api->getDatabaseList($patches);
$databases[] = $api->getDatabaseName('meta_data');
+
// These are legacy databases that were dropped long ago. See T2237.
$databases[] = $api->getDatabaseName('phid');
$databases[] = $api->getDatabaseName('directory');
}
foreach ($databases as $database) {
- if ($is_dry) {
- echo pht("DRYRUN: Would drop database '%s'.", $database)."\n";
+ if ($this->isDryRun()) {
+ $console->writeOut(
+ "%s\n",
+ pht("DRYRUN: Would drop database '%s'.", $database));
} else {
- echo pht("Dropping database '%s'...", $database)."\n";
+ $console->writeOut(
+ "%s\n",
+ pht("Dropping database '%s'...", $database));
queryfx(
$api->getConn(null),
'DROP DATABASE IF EXISTS %T',
@@ -74,8 +81,8 @@
}
}
- if (!$is_dry) {
- echo pht('Storage was destroyed.')."\n";
+ if (!$this->isDryRun()) {
+ $console->writeOut("%s\n", pht('Storage was destroyed.'));
}
return 0;
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php
@@ -11,10 +11,13 @@
}
public function execute(PhutilArgumentParser $args) {
- $console = PhutilConsole::getConsole();
- $api = $this->getAPI();
+ parent::execute($args);
+
+ $api = $this->getAPI();
$patches = $this->getPatches();
+ $console = PhutilConsole::getConsole();
+
$applied = $api->getAppliedPatches();
if ($applied === null) {
$namespace = $api->getNamespace();
@@ -24,11 +27,11 @@
'initialized in this storage namespace ("%s"). Use '.
'**%s** to initialize storage.',
$namespace,
- 'storage upgrade'));
+ './bin/storage upgrade'));
return 1;
}
- $databases = $api->getDatabaseList($patches, $only_living = true);
+ $databases = $api->getDatabaseList($patches, true);
list($host, $port) = $this->getBareHostAndPort($api->getHost());
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementProbeWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementProbeWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementProbeWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementProbeWorkflow.php
@@ -11,14 +11,16 @@
}
public function execute(PhutilArgumentParser $args) {
+ parent::execute($args);
+
$console = PhutilConsole::getConsole();
$console->writeErr(
"%s\n",
pht('Analyzing table sizes (this may take a moment)...'));
- $api = $this->getAPI();
- $patches = $this->getPatches();
- $databases = $api->getDatabaseList($patches, $only_living = true);
+ $api = $this->getAPI();
+ $patches = $this->getPatches();
+ $databases = $api->getDatabaseList($patches, true);
$conn_r = $api->getConn(null);
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementQuickstartWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementQuickstartWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementQuickstartWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementQuickstartWorkflow.php
@@ -22,6 +22,8 @@
}
public function execute(PhutilArgumentParser $args) {
+ parent::execute($args);
+
$output = $args->getArg('output');
if (!$output) {
throw new PhutilArgumentUsageException(
@@ -38,8 +40,10 @@
throw new PhutilArgumentUsageException(
pht(
'You can only generate a new quickstart file if MySQL supports '.
- 'the utf8mb4 character set (available in MySQL 5.5 and newer). The '.
- 'configured server does not support utf8mb4.'));
+ 'the %s character set (available in MySQL 5.5 and newer). The '.
+ 'configured server does not support %s.',
+ 'utf8mb4',
+ 'utf8mb4'));
}
$err = phutil_passthru(
@@ -139,7 +143,7 @@
$dump = preg_replace('/^--.*$/m', '', $dump);
// Remove table drops, locks, and unlocks. These are never relevant when
- // performing q quickstart.
+ // performing a quickstart.
$dump = preg_replace(
'/^(DROP TABLE|LOCK TABLES|UNLOCK TABLES).*$/m',
'',
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementRenamespaceWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementRenamespaceWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementRenamespaceWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementRenamespaceWorkflow.php
@@ -31,24 +31,32 @@
}
public function execute(PhutilArgumentParser $args) {
+ parent::execute($args);
+
$console = PhutilConsole::getConsole();
$in = $args->getArg('in');
if (!strlen($in)) {
throw new PhutilArgumentUsageException(
- pht('Specify the dumpfile to read with --in.'));
+ pht(
+ 'Specify the dumpfile to read with %s.',
+ '--in'));
}
$from = $args->getArg('from');
if (!strlen($from)) {
throw new PhutilArgumentUsageException(
- pht('Specify namespace to rename from with --from.'));
+ pht(
+ 'Specify namespace to rename from with %s.',
+ '--from'));
}
$to = $args->getArg('to');
if (!strlen($to)) {
throw new PhutilArgumentUsageException(
- pht('Specify namespace to rename to with --to.'));
+ pht(
+ 'Specify namespace to rename to with %s.',
+ '--to'));
}
$patterns = array(
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementShellWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementShellWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementShellWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementShellWorkflow.php
@@ -11,6 +11,8 @@
}
public function execute(PhutilArgumentParser $args) {
+ parent::execute($args);
+
$api = $this->getAPI();
list($host, $port) = $this->getBareHostAndPort($api->getHost());
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementStatusWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementStatusWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementStatusWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementStatusWorkflow.php
@@ -11,7 +11,9 @@
}
public function execute(PhutilArgumentParser $args) {
- $api = $this->getAPI();
+ parent::execute($args);
+
+ $api = $this->getAPI();
$patches = $this->getPatches();
$applied = $api->getAppliedPatches();
@@ -20,18 +22,18 @@
echo phutil_console_format(
"**%s**: %s\n",
pht('Database Not Initialized'),
- pht('Run **%s** to initialize.', 'storage upgrade'));
+ pht('Run **%s** to initialize.', './bin/storage upgrade'));
return 1;
}
$table = id(new PhutilConsoleTable())
->setShowHeader(false)
- ->addColumn('id', array('title' => pht('ID')))
- ->addColumn('status', array('title' => pht('Status')))
+ ->addColumn('id', array('title' => pht('ID')))
+ ->addColumn('status', array('title' => pht('Status')))
->addColumn('duration', array('title' => pht('Duration')))
- ->addColumn('type', array('title' => pht('Type')))
- ->addColumn('name', array('title' => pht('Name')));
+ ->addColumn('type', array('title' => pht('Type')))
+ ->addColumn('name', array('title' => pht('Name')));
$durations = $api->getPatchDurations();
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementUpgradeWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementUpgradeWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementUpgradeWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementUpgradeWorkflow.php
@@ -21,7 +21,7 @@
array(
'name' => 'no-quickstart',
'help' => pht(
- 'Build storage patch-by-patch from scatch, even if it could '.
+ 'Build storage patch-by-patch from scratch, even if it could '.
'be loaded from the quickstart template.'),
),
array(
@@ -38,22 +38,22 @@
}
public function execute(PhutilArgumentParser $args) {
- $is_dry = $args->getArg('dryrun');
- $is_force = $args->getArg('force');
+ parent::execute($args);
- $api = $this->getAPI();
+ $console = PhutilConsole::getConsole();
$patches = $this->getPatches();
- if (!$is_dry && !$is_force) {
- echo phutil_console_wrap(
- pht(
- 'Before running storage upgrades, you should take down the '.
- 'Phabricator web interface and stop any running Phabricator '.
- 'daemons (you can disable this warning with %s).',
- '--force'));
+ if (!$this->isDryRun() && !$this->isForce()) {
+ $console->writeOut(
+ phutil_console_wrap(
+ pht(
+ 'Before running storage upgrades, you should take down the '.
+ 'Phabricator web interface and stop any running Phabricator '.
+ 'daemons (you can disable this warning with %s).',
+ '--force')));
if (!phutil_console_confirm(pht('Are you ready to continue?'))) {
- echo pht('Cancelled.')."\n";
+ $console->writeOut("%s\n", pht('Cancelled.'));
return 1;
}
}
@@ -67,163 +67,23 @@
"Use '%s' to show patch status.",
'--apply',
$apply_only,
- 'storage status'));
+ './bin/storage status'));
}
}
$no_quickstart = $args->getArg('no-quickstart');
- $init_only = $args->getArg('init-only');
- $no_adjust = $args->getArg('no-adjust');
-
- $applied = $api->getAppliedPatches();
- if ($applied === null) {
-
- if ($is_dry) {
- echo pht(
- "DRYRUN: Patch metadata storage doesn't exist yet, ".
- "it would be created.\n");
- return 0;
- }
-
- if ($apply_only) {
- throw new PhutilArgumentUsageException(
- pht(
- '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 pht('Loading quickstart template...')."\n";
- $root = dirname(phutil_get_library_root('phabricator'));
- $sql = $root.'/resources/sql/quickstart.sql';
- $api->applyPatchSQL($sql);
- }
- }
-
- if ($init_only) {
- echo pht('Storage initialized.')."\n";
- return 0;
- }
+ $init_only = $args->getArg('init-only');
+ $no_adjust = $args->getArg('no-adjust');
- $applied = $api->getAppliedPatches();
- $applied = array_fuse($applied);
+ $this->upgradeSchemata($apply_only, $no_quickstart, $init_only);
- $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(
- pht(
- "Patch '%s' 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.",
- $apply_only));
- if (!phutil_console_confirm(pht('Apply patch again?'))) {
- echo pht('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 pht(
- "Unable to apply patch '%s' because it depends ".
- "on patch '%s', which has not been applied.\n",
- $apply_only,
- $after);
- return 1;
- }
- $can_apply = false;
- break;
- }
- }
-
- if (!$can_apply) {
- continue;
- }
-
- $applied_something = true;
-
- if ($is_dry) {
- echo pht("DRYRUN: Would apply patch '%s'.", $key)."\n";
- } else {
- echo pht("Applying patch '%s'...", $key)."\n";
-
- $t_begin = microtime(true);
- $api->applyPatch($patch);
- $t_end = microtime(true);
-
- if (!$skip_mark) {
- $api->markPatchApplied($key, ($t_end - $t_begin));
- }
- }
-
- unset($patches[$key]);
- $applied[$key] = true;
- }
-
- if (!$applied_something) {
- if (count($patches)) {
- throw new Exception(
- pht(
- 'Some patches could not be applied: %s',
- implode(', ', array_keys($patches))));
- } else if (!$is_dry && !$apply_only) {
- echo pht(
- "Storage is up to date. Use '%s' for details.",
- 'storage status')."\n";
- }
- break;
- }
- }
-
- $console = PhutilConsole::getConsole();
if ($no_adjust || $init_only || $apply_only) {
$console->writeOut(
"%s\n",
pht('Declining to apply storage adjustments.'));
return 0;
} else {
- return $this->adjustSchemata($is_force, $unsafe = false, $is_dry);
+ return $this->adjustSchemata(false);
}
}
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php
@@ -3,12 +3,35 @@
abstract class PhabricatorStorageManagementWorkflow
extends PhabricatorManagementWorkflow {
- private $patches;
private $api;
+ private $dryRun;
+ private $force;
+ private $patches;
- public function setPatches(array $patches) {
- assert_instances_of($patches, 'PhabricatorStoragePatch');
- $this->patches = $patches;
+ final public function getAPI() {
+ return $this->api;
+ }
+
+ final public function setAPI(PhabricatorStorageManagementAPI $api) {
+ $this->api = $api;
+ return $this;
+ }
+
+ final protected function isDryRun() {
+ return $this->dryRun;
+ }
+
+ final protected function setDryRun($dry_run) {
+ $this->dryRun = $dry_run;
+ return $this;
+ }
+
+ final protected function isForce() {
+ return $this->force;
+ }
+
+ final protected function setForce($force) {
+ $this->force = $force;
return $this;
}
@@ -16,13 +39,16 @@
return $this->patches;
}
- final public function setAPI(PhabricatorStorageManagementAPI $api) {
- $this->api = $api;
+ public function setPatches(array $patches) {
+ assert_instances_of($patches, 'PhabricatorStoragePatch');
+ $this->patches = $patches;
return $this;
}
- final public function getAPI() {
- return $this->api;
+
+ public function execute(PhutilArgumentParser $args) {
+ $this->setDryRun($args->getArg('dryrun'));
+ $this->setForce($args->getArg('force'));
}
private function loadSchemata() {
@@ -36,7 +62,20 @@
return array($comp, $expect, $actual);
}
- protected function adjustSchemata($force, $unsafe, $dry_run) {
+ final protected function adjustSchemata($unsafe) {
+ $lock = $this->lock();
+
+ try {
+ $this->doAdjustSchemata($unsafe);
+ } catch (Exception $ex) {
+ $lock->unlock();
+ throw $ex;
+ }
+
+ $lock->unlock();
+ }
+
+ final private function doAdjustSchemata($unsafe) {
$console = PhutilConsole::getConsole();
$console->writeOut(
@@ -54,7 +93,7 @@
return $this->printErrors($errors, 0);
}
- if (!$force && !$api->isCharacterSetAvailable('utf8mb4')) {
+ if (!$this->force && !$api->isCharacterSetAvailable('utf8mb4')) {
$message = pht(
"You have an old version of MySQL (older than 5.5) which does not ".
"support the utf8mb4 character set. We strongly recomend upgrading to ".
@@ -110,12 +149,12 @@
$table->draw();
- if ($dry_run) {
+ if ($this->dryRun) {
$console->writeOut(
"%s\n",
pht('DRYRUN: Would apply adjustments.'));
return 0;
- } else if (!$force) {
+ } else if (!$this->force) {
$console->writeOut(
"\n%s\n",
pht(
@@ -665,6 +704,171 @@
return 2;
}
+ final protected function upgradeSchemata(
+ $apply_only = null,
+ $no_quickstart = false,
+ $init_only = false) {
+
+ $lock = $this->lock();
+
+ try {
+ $this->doUpgradeSchemata($apply_only, $no_quickstart, $init_only);
+ } catch (Exception $ex) {
+ $lock->unlock();
+ throw $ex;
+ }
+
+ $lock->unlock();
+ }
+
+ final private function doUpgradeSchemata(
+ $apply_only,
+ $no_quickstart,
+ $init_only) {
+
+ $api = $this->getAPI();
+
+ $applied = $this->getApi()->getAppliedPatches();
+ if ($applied === null) {
+ if ($this->dryRun) {
+ echo pht(
+ "DRYRUN: Patch metadata storage doesn't exist yet, ".
+ "it would be created.\n");
+ return 0;
+ }
+
+ if ($apply_only) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Storage has not been initialized yet, you must initialize '.
+ 'storage before selectively applying patches.'));
+ return 1;
+ }
+
+ $legacy = $api->getLegacyPatches($this->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 pht('Loading quickstart template...')."\n";
+ $root = dirname(phutil_get_library_root('phabricator'));
+ $sql = $root.'/resources/sql/quickstart.sql';
+ $api->applyPatchSQL($sql);
+ }
+ }
+
+ if ($init_only) {
+ echo pht('Storage initialized.')."\n";
+ return 0;
+ }
+
+ $applied = $api->getAppliedPatches();
+ $applied = array_fuse($applied);
+
+ $skip_mark = false;
+ if ($apply_only) {
+ if (isset($applied[$apply_only])) {
+
+ unset($applied[$apply_only]);
+ $skip_mark = true;
+
+ if (!$this->force && !$this->dryRun) {
+ echo phutil_console_wrap(
+ pht(
+ "Patch '%s' 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.",
+ $apply_only));
+ if (!phutil_console_confirm(pht('Apply patch again?'))) {
+ echo pht('Cancelled.')."\n";
+ return 1;
+ }
+ }
+ }
+ }
+
+ while (true) {
+ $applied_something = false;
+ foreach ($this->patches as $key => $patch) {
+ if (isset($applied[$key])) {
+ unset($this->patches[$key]);
+ continue;
+ }
+
+ if ($apply_only && $apply_only != $key) {
+ unset($this->patches[$key]);
+ continue;
+ }
+
+ $can_apply = true;
+ foreach ($patch->getAfter() as $after) {
+ if (empty($applied[$after])) {
+ if ($apply_only) {
+ echo pht(
+ "Unable to apply patch '%s' because it depends ".
+ "on patch '%s', which has not been applied.\n",
+ $apply_only,
+ $after);
+ return 1;
+ }
+ $can_apply = false;
+ break;
+ }
+ }
+
+ if (!$can_apply) {
+ continue;
+ }
+
+ $applied_something = true;
+
+ if ($this->dryRun) {
+ echo pht("DRYRUN: Would apply patch '%s'.", $key)."\n";
+ } else {
+ echo pht("Applying patch '%s'...", $key)."\n";
+
+ $t_begin = microtime(true);
+ $api->applyPatch($patch);
+ $t_end = microtime(true);
+
+ if (!$skip_mark) {
+ $api->markPatchApplied($key, ($t_end - $t_begin));
+ }
+ }
+
+ unset($this->patches[$key]);
+ $applied[$key] = true;
+ }
+
+ if (!$applied_something) {
+ if (count($this->patches)) {
+ throw new Exception(
+ pht(
+ 'Some patches could not be applied: %s',
+ implode(', ', array_keys($this->patches))));
+ } else if (!$this->dryRun && !$apply_only) {
+ echo pht(
+ "Storage is up to date. Use '%s' for details.",
+ 'storage status')."\n";
+ }
+ break;
+ }
+ }
+ }
+
final protected function getBareHostAndPort($host) {
// Split out port information, since the command-line client requires a
// separate flag for the port.
@@ -680,4 +884,13 @@
return array($bare_hostname, $port);
}
+ /**
+ * Acquires a @{class:PhabricatorGlobalLock}.
+ *
+ * @return PhabricatorGlobalLock
+ */
+ final protected function lock() {
+ return PhabricatorGlobalLock::newLock(__CLASS__);
+ }
+
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Dec 28, 3:16 PM (7 h, 30 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6939880
Default Alt Text
D14463.id35039.diff (29 KB)
Attached To
Mode
D14463: Add a lock to storage upgrade and adjustment
Attached
Detach File
Event Timeline
Log In to Comment