Find this useful? Enter your email to receive occasional updates for securing PHP code.
Signing you up...
Thank you for signing up!
PHP Decode
<?php abstract class PhabricatorStorageManagementWorkflow extends PhabricatorManagementWo..
Decoded Output download
<?php
abstract class PhabricatorStorageManagementWorkflow extends PhabricatorManagementWorkflow { private $apis = array(); private $dryRun; private $force; private $patches; private $didInitialize; public final function setAPIs(array $apis) { $this->apis = $apis; return $this; } public final function getAnyAPI() { return head($this->getAPIs()); } public final function getMasterAPIs() { $apis = $this->getAPIs(); $results = array(); foreach ($apis as $api) { if ($api->getRef()->getIsMaster()) { $results[] = $api; } } if (!$results) { throw new PhutilArgumentUsageException(pht("This command only operates on database masters, but the selected " . "database hosts do not include any masters.")); } return $results; } public final function getSingleAPI() { $apis = $this->getAPIs(); if (count($apis) == 1) { return head($apis); } throw new PhutilArgumentUsageException(pht("This server is configured in cluster mode, with multiple database " . "hosts. Use "--host" to specify which host you want to operate on.")); } public final function getAPIs() { return $this->apis; } protected final function isDryRun() { return $this->dryRun; } protected final function setDryRun($dry_run) { $this->dryRun = $dry_run; return $this; } protected final function isForce() { return $this->force; } protected final function setForce($force) { $this->force = $force; return $this; } public function getPatches() { return $this->patches; } public function setPatches(array $patches) { assert_instances_of($patches, "PhabricatorStoragePatch"); $this->patches = $patches; return $this; } protected function isReadOnlyWorkflow() { return false; } public function execute(PhutilArgumentParser $args) { $this->setDryRun($args->getArg("dryrun")); $this->setForce($args->getArg("force")); if (!$this->isReadOnlyWorkflow()) { if (PhabricatorEnv::isReadOnly()) { if ($this->isForce()) { PhabricatorEnv::setReadOnly(false, null); } else { throw new PhutilArgumentUsageException(pht("This server is currently in read-only mode. Use --force to " . "override this mode.")); } } } return $this->didExecute($args); } public function didExecute(PhutilArgumentParser $args) { } private function loadSchemata(PhabricatorStorageManagementAPI $api) { $query = id(new PhabricatorConfigSchemaQuery()); $ref = $api->getRef(); $ref_key = $ref->getRefKey(); $query->setAPIs(array($api)); $query->setRefs(array($ref)); $actual = $query->loadActualSchemata(); $expect = $query->loadExpectedSchemata(); $comp = $query->buildComparisonSchemata($expect, $actual); return array($comp[$ref_key], $expect[$ref_key], $actual[$ref_key]); } protected final function adjustSchemata(PhabricatorStorageManagementAPI $api, $unsafe) { $lock = $this->lock($api); try { $err = $this->doAdjustSchemata($api, $unsafe); if (!$this->dryRun) { $should_analyze = $err == 0 || $err == 2; if ($should_analyze) { $this->analyzeTables($api); } } } catch (Exception $ex) { $lock->unlock(); throw $ex; } $lock->unlock(); return $err; } private function doAdjustSchemata(PhabricatorStorageManagementAPI $api, $unsafe) { $console = PhutilConsole::getConsole(); $console->writeOut("%s\xa", pht("Verifying database schemata on "%s"...", $api->getRef()->getRefKey())); list($adjustments, $errors) = $this->findAdjustments($api); if (!$adjustments) { $console->writeOut("%s\xa", pht("Found no adjustments for schemata.")); return $this->printErrors($errors, 0); } 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 recommend upgrading " . "to 5.5 or newer.\xa
" . "If you apply adjustments now and later update MySQL to 5.5 or newer, " . "you'll need to apply adjustments again (and they will take a long " . "time).\xa
" . "You can exit this workflow, update MySQL now, and then run this " . "workflow again. This is recommended, but may cause a lot of downtime " . "right now.
" . "You can exit this workflow, continue using this software without " . "applying adjustments, update MySQL at a later date, and then run " . "this workflow again. This is also a good approach, and will let you " . "delay downtime until later.\xa\xa" . "You can proceed with this workflow, and then optionally update " . "MySQL at a later date. After you do, you'll need to apply " . "adjustments again.
" . "For more information, see "Managing Storage Adjustments" in " . "the documentation."); $console->writeOut("
**<bg:yellow> %s </bg>**
\xa%s
", pht("OLD MySQL VERSION"), phutil_console_wrap($message)); $prompt = pht("Continue with old MySQL version?"); if (!phutil_console_confirm($prompt, $default_no = true)) { return; } } $table = id(new PhutilConsoleTable())->addColumn("database", array("title" => pht("Database")))->addColumn("table", array("title" => pht("Table")))->addColumn("name", array("title" => pht("Name")))->addColumn("info", array("title" => pht("Issues"))); foreach ($adjustments as $adjust) { $info = array(); foreach ($adjust["issues"] as $issue) { $info[] = PhabricatorConfigStorageSchema::getIssueName($issue); } $table->addRow(array("database" => $adjust["database"], "table" => idx($adjust, "table"), "name" => idx($adjust, "name"), "info" => implode(", ", $info))); } $console->writeOut("\xa
"); $table->draw(); if ($this->dryRun) { $console->writeOut("%s
", pht("DRYRUN: Would apply adjustments.")); return 0; } else { if ($this->didInitialize) { } else { if (!$this->force) { $console->writeOut("
%s
", pht("Found %s adjustment(s) to apply, detailed above.
" . "You can review adjustments in more detail from the web interface, " . "in Config > Database Status. To better understand the adjustment " . "workflow, see "Managing Storage Adjustments" in the " . "documentation.
\xa" . "MySQL needs to copy table data to make some adjustments, so these " . "migrations may take some time.", phutil_count($adjustments))); $prompt = pht("Apply these schema adjustments?"); if (!phutil_console_confirm($prompt, $default_no = true)) { return 1; } } } } $console->writeOut("%s
", pht("Applying schema adjustments...")); $conn = $api->getConn(null); if ($unsafe) { queryfx($conn, "SET SESSION sql_mode = %s", ''); } else { queryfx($conn, "SET SESSION sql_mode = %s", "STRICT_ALL_TABLES"); } $failed = array(); $phases = array("drop_auto", "drop_keys", "main", "add_keys", "add_auto"); $bar = id(new PhutilConsoleProgressBar())->setTotal(count($adjustments) * count($phases)); foreach ($phases as $phase) { foreach ($adjustments as $adjust) { try { switch ($adjust["kind"]) { case "database": if ($phase == "main") { queryfx($conn, "ALTER DATABASE %T CHARACTER SET = %s COLLATE = %s", $adjust["database"], $adjust["charset"], $adjust["collation"]); } break; case "table": if ($phase == "main") { queryfx($conn, "ALTER TABLE %T.%T COLLATE = %s, ENGINE = %s", $adjust["database"], $adjust["table"], $adjust["collation"], $adjust["engine"]); } break; case "column": $apply = false; $auto = false; $new_auto = idx($adjust, "auto"); if ($phase == "drop_auto") { if ($new_auto === false) { $apply = true; $auto = false; } } else { if ($phase == "main") { $apply = true; if ($new_auto === false) { $auto = false; } else { $auto = $adjust["is_auto"]; } } else { if ($phase == "add_auto") { if ($new_auto === true) { $apply = true; $auto = true; } } } } if ($apply) { $parts = array(); if ($auto) { $parts[] = qsprintf($conn, "AUTO_INCREMENT"); } if ($adjust["charset"]) { switch ($adjust["charset"]) { case "binary": $charset_value = qsprintf($conn, "binary"); break; case "utf8": $charset_value = qsprintf($conn, "utf8"); break; case "utf8mb4": $charset_value = qsprintf($conn, "utf8mb4"); break; default: throw new Exception(pht("Unsupported character set "%s".", $adjust["charset"])); } switch ($adjust["collation"]) { case "binary": $collation_value = qsprintf($conn, "binary"); break; case "utf8_general_ci": $collation_value = qsprintf($conn, "utf8_general_ci"); break; case "utf8mb4_bin": $collation_value = qsprintf($conn, "utf8mb4_bin"); break; case "utf8mb4_unicode_ci": $collation_value = qsprintf($conn, "utf8mb4_unicode_ci"); break; default: throw new Exception(pht("Unsupported collation set "%s".", $adjust["collation"])); } $parts[] = qsprintf($conn, "CHARACTER SET %Q COLLATE %Q", $charset_value, $collation_value); } if ($parts) { $parts = qsprintf($conn, "%LJ", $parts); } else { $parts = qsprintf($conn, ''); } if ($adjust["nullable"]) { $nullable = qsprintf($conn, "NULL"); } else { $nullable = qsprintf($conn, "NOT NULL"); } queryfx($conn, "ALTER TABLE %T.%T MODIFY %T %Z %Q %Q", $adjust["database"], $adjust["table"], $adjust["name"], $adjust["type"], $parts, $nullable); } break; case "key": if ($phase == "drop_keys" && $adjust["exists"]) { if ($adjust["name"] == "PRIMARY") { $key_name = qsprintf($conn, "PRIMARY KEY"); } else { $key_name = qsprintf($conn, "KEY %T", $adjust["name"]); } queryfx($conn, "ALTER TABLE %T.%T DROP %Q", $adjust["database"], $adjust["table"], $key_name); } if ($phase == "add_keys" && $adjust["keep"]) { if ($adjust["name"] == "PRIMARY") { $key_name = qsprintf($conn, "PRIMARY KEY"); } else { if ($adjust["indexType"] == "FULLTEXT") { $key_name = qsprintf($conn, "FULLTEXT %T", $adjust["name"]); } else { if ($adjust["unique"]) { $key_name = qsprintf($conn, "UNIQUE KEY %T", $adjust["name"]); } else { $key_name = qsprintf($conn, "/* NONUNIQUE */ KEY %T", $adjust["name"]); } } } queryfx($conn, "ALTER TABLE %T.%T ADD %Q (%LK)", $adjust["database"], $adjust["table"], $key_name, $adjust["columns"]); } break; default: throw new Exception(pht("Unknown schema adjustment kind "%s"!", $adjust["kind"])); } } catch (AphrontQueryException $ex) { $failed[] = array($adjust, $ex); } $bar->update(1); } } $bar->done(); if (!$failed) { $console->writeOut("%s
", pht("Completed applying all schema adjustments.")); $err = 0; } else { $table = id(new PhutilConsoleTable())->addColumn("target", array("title" => pht("Target")))->addColumn("error", array("title" => pht("Error"))); foreach ($failed as $failure) { list($adjust, $ex) = $failure; $pieces = array_select_keys($adjust, array("database", "table", "name")); $pieces = array_filter($pieces); $target = implode(".", $pieces); $table->addRow(array("target" => $target, "error" => $ex->getMessage())); } $console->writeOut("\xa"); $table->draw(); $console->writeOut("\xa%s
", pht("Failed to make some schema adjustments, detailed above.")); $console->writeOut("%s\xa", pht("For help troubleshooting adjustments, see "Managing Storage " . "Adjustments" in the documentation.")); $err = 1; } return $this->printErrors($errors, $err); } private function findAdjustments(PhabricatorStorageManagementAPI $api) { list($comp, $expect, $actual) = $this->loadSchemata($api); $issue_charset = PhabricatorConfigStorageSchema::ISSUE_CHARSET; $issue_collation = PhabricatorConfigStorageSchema::ISSUE_COLLATION; $issue_columntype = PhabricatorConfigStorageSchema::ISSUE_COLUMNTYPE; $issue_surpluskey = PhabricatorConfigStorageSchema::ISSUE_SURPLUSKEY; $issue_missingkey = PhabricatorConfigStorageSchema::ISSUE_MISSINGKEY; $issue_columns = PhabricatorConfigStorageSchema::ISSUE_KEYCOLUMNS; $issue_unique = PhabricatorConfigStorageSchema::ISSUE_UNIQUE; $issue_longkey = PhabricatorConfigStorageSchema::ISSUE_LONGKEY; $issue_auto = PhabricatorConfigStorageSchema::ISSUE_AUTOINCREMENT; $issue_engine = PhabricatorConfigStorageSchema::ISSUE_ENGINE; $adjustments = array(); $errors = array(); foreach ($comp->getDatabases() as $database_name => $database) { foreach ($this->findErrors($database) as $issue) { $errors[] = array("database" => $database_name, "issue" => $issue); } $expect_database = $expect->getDatabase($database_name); $actual_database = $actual->getDatabase($database_name); if (!$expect_database || !$actual_database) { continue; } if ($actual_database->getAccessDenied()) { continue; } $issues = array(); if ($database->hasIssue($issue_charset)) { $issues[] = $issue_charset; } if ($database->hasIssue($issue_collation)) { $issues[] = $issue_collation; } if ($issues) { $adjustments[] = array("kind" => "database", "database" => $database_name, "issues" => $issues, "charset" => $expect_database->getCharacterSet(), "collation" => $expect_database->getCollation()); } foreach ($database->getTables() as $table_name => $table) { foreach ($this->findErrors($table) as $issue) { $errors[] = array("database" => $database_name, "table" => $table_name, "issue" => $issue); } $expect_table = $expect_database->getTable($table_name); $actual_table = $actual_database->getTable($table_name); if (!$expect_table || !$actual_table) { continue; } $issues = array(); if ($table->hasIssue($issue_collation)) { $issues[] = $issue_collation; } if ($table->hasIssue($issue_engine)) { $issues[] = $issue_engine; } if ($issues) { $adjustments[] = array("kind" => "table", "database" => $database_name, "table" => $table_name, "issues" => $issues, "collation" => $expect_table->getCollation(), "engine" => $expect_table->getEngine()); } foreach ($table->getColumns() as $column_name => $column) { foreach ($this->findErrors($column) as $issue) { $errors[] = array("database" => $database_name, "table" => $table_name, "name" => $column_name, "issue" => $issue); } $expect_column = $expect_table->getColumn($column_name); $actual_column = $actual_table->getColumn($column_name); if (!$expect_column || !$actual_column) { continue; } $issues = array(); if ($column->hasIssue($issue_collation)) { $issues[] = $issue_collation; } if ($column->hasIssue($issue_charset)) { $issues[] = $issue_charset; } if ($column->hasIssue($issue_columntype)) { $issues[] = $issue_columntype; } if ($column->hasIssue($issue_auto)) { $issues[] = $issue_auto; } if ($issues) { if ($expect_column->getCharacterSet() === null) { $charset = null; $collation = null; } else { $charset = $expect_column->getCharacterSet(); $collation = $expect_column->getCollation(); } $adjustment = array("kind" => "column", "database" => $database_name, "table" => $table_name, "name" => $column_name, "issues" => $issues, "collation" => $collation, "charset" => $charset, "type" => $expect_column->getColumnType(), "nullable" => $actual_column->getNullable(), "is_auto" => $actual_column->getAutoIncrement()); if ($column->hasIssue($issue_auto)) { $adjustment["auto"] = $expect_column->getAutoIncrement(); } $adjustments[] = $adjustment; } } foreach ($table->getKeys() as $key_name => $key) { foreach ($this->findErrors($key) as $issue) { $errors[] = array("database" => $database_name, "table" => $table_name, "name" => $key_name, "issue" => $issue); } $expect_key = $expect_table->getKey($key_name); $actual_key = $actual_table->getKey($key_name); $issues = array(); $keep_key = true; if ($key->hasIssue($issue_surpluskey)) { $issues[] = $issue_surpluskey; $keep_key = false; } if ($key->hasIssue($issue_missingkey)) { $issues[] = $issue_missingkey; } if ($key->hasIssue($issue_columns)) { $issues[] = $issue_columns; } if ($key->hasIssue($issue_unique)) { $issues[] = $issue_unique; } if ($key->hasIssue($issue_longkey)) { $issues[] = $issue_longkey; } if ($issues) { $adjustment = array("kind" => "key", "database" => $database_name, "table" => $table_name, "name" => $key_name, "issues" => $issues, "exists" => (bool) $actual_key, "keep" => $keep_key); if ($keep_key) { $adjustment += array("columns" => $expect_key->getColumnNames(), "unique" => $expect_key->getUnique(), "indexType" => $expect_key->getIndexType()); } $adjustments[] = $adjustment; } } } } return array($adjustments, $errors); } private function findErrors(PhabricatorConfigStorageSchema $schema) { $result = array(); foreach ($schema->getLocalIssues() as $issue) { $status = PhabricatorConfigStorageSchema::getIssueStatus($issue); if ($status == PhabricatorConfigStorageSchema::STATUS_FAIL) { $result[] = $issue; } } return $result; } private function printErrors(array $errors, $default_return) { if (!$errors) { return $default_return; } $console = PhutilConsole::getConsole(); $table = id(new PhutilConsoleTable())->addColumn("target", array("title" => pht("Target")))->addColumn("error", array("title" => pht("Error"))); $any_surplus = false; $all_surplus = true; $any_access = false; $all_access = true; foreach ($errors as $error) { $pieces = array_select_keys($error, array("database", "table", "name")); $pieces = array_filter($pieces); $target = implode(".", $pieces); $name = PhabricatorConfigStorageSchema::getIssueName($error["issue"]); $issue = $error["issue"]; if ($issue === PhabricatorConfigStorageSchema::ISSUE_SURPLUS) { $any_surplus = true; } else { $all_surplus = false; } if ($issue === PhabricatorConfigStorageSchema::ISSUE_ACCESSDENIED) { $any_access = true; } else { $all_access = false; } $table->addRow(array("target" => $target, "error" => $name)); } $console->writeOut("\xa"); $table->draw(); $console->writeOut("
"); $message = array(); if ($all_surplus) { $message[] = pht("You have surplus schemata (extra tables or columns which this " . "software does not expect). For information on resolving these " . "issues, see the "Surplus Schemata" section in the "Managing Storage " . "Adjustments" article in the documentation."); } else { if ($all_access) { $message[] = pht("The user you are connecting to MySQL with does not have the correct " . "permissions, and can not access some databases or tables that it " . "needs to be able to access. GRANT the user additional permissions."); } else { $message[] = pht("The schemata have errors (detailed above) which the adjustment " . "workflow can not fix."); if ($any_access) { $message[] = pht("Some of these errors are caused by access control problems. " . "The user you are connecting with does not have permission to see " . "all of the database or tables that this software uses. You need to " . "GRANT the user more permission, or use a different user."); } if ($any_surplus) { $message[] = pht("Some of these errors are caused by surplus schemata (extra " . "tables or columns which this software does not expect). These are " . "not serious. For information on resolving these issues, see the " . ""Surplus Schemata" section in the "Managing Storage Adjustments" " . "article in the documentation."); } $message[] = pht("If you are not developing %s itself, report this issue to " . "the upstream.", PlatformSymbols::getPlatformServerName()); $message[] = pht("If you are developing %s, these errors usually indicate " . "that your schema specifications do not agree with the schemata your " . "code actually builds.", PlatformSymbols::getPlatformServerName()); } } $message = implode("\xa
", $message); if ($all_surplus) { $console->writeOut("**<bg:yellow> %s </bg>**
%s\xa", pht("SURPLUS SCHEMATA"), phutil_console_wrap($message)); } else { if ($all_access) { $console->writeOut("**<bg:yellow> %s </bg>**\xa
%s\xa", pht("ACCESS DENIED"), phutil_console_wrap($message)); } else { $console->writeOut("**<bg:red> %s </bg>**\xa\xa%s
", pht("SCHEMATA ERRORS"), phutil_console_wrap($message)); } } return 2; } protected final function upgradeSchemata(array $apis, $apply_only = null, $no_quickstart = false, $init_only = false) { $locks = array(); foreach ($apis as $api) { $locks[] = $this->lock($api); } try { $this->doUpgradeSchemata($apis, $apply_only, $no_quickstart, $init_only); } catch (Exception $ex) { foreach ($locks as $lock) { $lock->unlock(); } throw $ex; } foreach ($locks as $lock) { $lock->unlock(); } } private function doUpgradeSchemata(array $apis, $apply_only, $no_quickstart, $init_only) { $patches = $this->patches; $is_dryrun = $this->dryRun; $patches = msortv($patches, "newSortVector"); $api_map = array(); foreach ($apis as $api) { $api_map[$api->getRef()->getRefKey()] = $api; } foreach ($api_map as $ref_key => $api) { $applied = $api->getAppliedPatches(); $needs_init = $applied === null; if (!$needs_init) { continue; } if ($is_dryrun) { echo tsprintf("%s\xa", pht("DRYRUN: Storage on host "%s" does not exist yet, so it " . "would be created.", $ref_key)); continue; } if ($apply_only) { throw new PhutilArgumentUsageException(pht("Storage on host "%s" has not been initialized yet. You must " . "initialize storage before selectively applying patches.", $ref_key)); } $this->didInitialize = true; $legacy = $api->getLegacyPatches($patches); if ($legacy || $no_quickstart || $init_only) { $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 tsprintf("%s
", pht("Loading quickstart template onto "%s"...", $ref_key)); $root = dirname(phutil_get_library_root("phabricator")); $sql = $root . "/resources/sql/quickstart.sql"; $api->applyPatchSQL($sql); } } if ($init_only) { echo pht("Storage initialized.") . "
"; return 0; } $applied_map = array(); $state_map = array(); foreach ($api_map as $ref_key => $api) { $applied = $api->getAppliedPatches(); if ($applied === null) { if ($is_dryrun) { continue; } else { throw new Exception(pht("Database initialization on host "%s" applied no patches!", $ref_key)); } } $applied = array_fuse($applied); $state_map[$ref_key] = $applied; if ($apply_only) { if (isset($applied[$apply_only])) { if (!$this->force && !$is_dryrun) { echo phutil_console_wrap(pht("Patch "%s" has already been applied on host "%s". 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, $ref_key)); if (!phutil_console_confirm(pht("Apply patch again?"))) { echo pht("Cancelled.") . "\xa"; return 1; } } unset($applied[$apply_only]); } } $applied_map[$ref_key] = $applied; } if ($apply_only) { $patches = array_select_keys($patches, array($apply_only)); } $duration_map = array(); foreach ($patches as $key => $patch) { if ($patch->getIsGlobalPatch()) { foreach ($applied_map as $ref_key => $applied) { if (isset($applied[$key])) { $duration_map[$key] = 1; } } } } while (true) { $applied_something = false; foreach ($patches as $key => $patch) { $need_patch = array(); foreach ($applied_map as $ref_key => $applied) { if (isset($applied[$key])) { continue; } $need_patch[] = $ref_key; } if (!$need_patch) { unset($patches[$key]); continue; } $missing_patch = null; foreach ($patch->getAfter() as $after) { foreach ($applied_map as $ref_key => $applied) { if (isset($applied[$after])) { continue; } $missing_patch = $after; break 2; } } if ($missing_patch) { if ($apply_only) { echo tsprintf("%s
", pht("Unable to apply patch "%s" because it depends on patch " . ""%s", which has not been applied on some hosts: %s.", $apply_only, $missing_patch, implode(", ", $need_patch))); return 1; } else { continue; } } $is_global = $patch->getIsGlobalPatch(); $patch_apis = array_select_keys($api_map, $need_patch); foreach ($patch_apis as $ref_key => $api) { if ($is_global) { $duration = idx($duration_map, $key); } else { $duration = null; } if ($duration === null) { if ($is_dryrun) { echo tsprintf("%s
", pht("DRYRUN: Would apply patch "%s" to host "%s".", $key, $ref_key)); } else { echo tsprintf("%s\xa", pht("Applying patch "%s" to host "%s"...", $key, $ref_key)); } $t_begin = microtime(true); if (!$is_dryrun) { $api->applyPatch($patch); } $t_end = microtime(true); $duration = $t_end - $t_begin; $duration_map[$key] = $duration; } if (!isset($state_map[$ref_key][$key])) { if (!$is_dryrun) { $api->markPatchApplied($key, $t_end - $t_begin); } $applied_map[$ref_key][$key] = true; } } unset($patches[$key]); $applied_something = true; } if (!$applied_something) { if ($patches) { throw new Exception(pht("Some patches could not be applied: %s", implode(", ", array_keys($patches)))); } else { if (!$is_dryrun && !$apply_only) { echo pht("Storage is up to date. Use "%s" for details.", "storage status") . "\xa"; } } break; } } } protected final function getBareHostAndPort($host) { $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); } protected final function lock(PhabricatorStorageManagementAPI $api) { $parameters = array("refKey" => $api->getRef()->getRefKey()); return PhabricatorGlobalLock::newLock("adjust", $parameters)->setExternalConnection($api->getConn(null))->setDisableLogging(true)->lock(); } protected final function analyzeTables(PhabricatorStorageManagementAPI $api) { $conn = $api->getConn(null); $patches = $this->getPatches(); $databases = $api->getDatabaseList($patches, true); $this->logInfo(pht("ANALYZE"), pht("Analyzing tables...")); $targets = array(); foreach ($databases as $database) { queryfx($conn, "USE %C", $database); $tables = queryfx_all($conn, "SHOW TABLE STATUS"); foreach ($tables as $table) { $table_name = $table["Name"]; $targets[] = array("database" => $database, "table" => $table_name); } } $bar = id(new PhutilConsoleProgressBar())->setTotal(count($targets)); foreach ($targets as $target) { queryfx($conn, "ANALYZE TABLE %T.%T", $target["database"], $target["table"]); $bar->update(1); } $bar->done(); $this->logOkay(pht("ANALYZED"), pht("Analyzed %d table(s).", count($targets))); } } ?>
Did this file decode correctly?
Original Code
<?php
abstract class PhabricatorStorageManagementWorkflow extends PhabricatorManagementWorkflow { private $apis = array(); private $dryRun; private $force; private $patches; private $didInitialize; public final function setAPIs(array $apis) { $this->apis = $apis; return $this; } public final function getAnyAPI() { return head($this->getAPIs()); } public final function getMasterAPIs() { $apis = $this->getAPIs(); $results = array(); foreach ($apis as $api) { if ($api->getRef()->getIsMaster()) { $results[] = $api; } } if (!$results) { throw new PhutilArgumentUsageException(pht("\124\150\x69\163\40\x63\157\155\155\141\156\x64\x20\157\156\154\171\40\157\160\145\162\141\164\145\163\x20\x6f\156\x20\144\141\164\141\x62\141\x73\145\x20\x6d\x61\163\x74\145\162\x73\54\x20\x62\x75\164\x20\164\150\145\x20\163\145\x6c\x65\143\x74\x65\144\x20" . "\x64\x61\x74\141\x62\141\163\x65\x20\x68\157\x73\164\163\x20\144\x6f\40\156\157\x74\x20\x69\x6e\143\154\165\144\145\x20\x61\x6e\x79\x20\x6d\141\x73\x74\145\162\x73\56")); } return $results; } public final function getSingleAPI() { $apis = $this->getAPIs(); if (count($apis) == 1) { return head($apis); } throw new PhutilArgumentUsageException(pht("\124\150\x69\163\x20\163\145\162\x76\145\162\x20\x69\x73\40\143\157\156\146\x69\147\x75\x72\145\x64\40\x69\156\40\143\154\165\x73\x74\x65\162\x20\155\x6f\x64\145\54\x20\x77\x69\164\x68\x20\x6d\x75\154\x74\x69\160\154\x65\40\x64\x61\164\141\x62\x61\163\x65\40" . "\x68\157\163\164\x73\56\40\125\x73\145\x20\x22\55\x2d\x68\157\x73\164\x22\x20\164\157\40\163\x70\x65\143\x69\x66\171\x20\x77\x68\151\143\150\x20\150\157\163\164\x20\x79\157\x75\x20\167\x61\156\164\40\x74\157\40\157\160\145\162\141\164\x65\40\157\x6e\x2e")); } public final function getAPIs() { return $this->apis; } protected final function isDryRun() { return $this->dryRun; } protected final function setDryRun($dry_run) { $this->dryRun = $dry_run; return $this; } protected final function isForce() { return $this->force; } protected final function setForce($force) { $this->force = $force; return $this; } public function getPatches() { return $this->patches; } public function setPatches(array $patches) { assert_instances_of($patches, "\x50\x68\141\x62\162\x69\x63\x61\x74\157\x72\x53\164\x6f\x72\141\x67\x65\x50\x61\x74\x63\150"); $this->patches = $patches; return $this; } protected function isReadOnlyWorkflow() { return false; } public function execute(PhutilArgumentParser $args) { $this->setDryRun($args->getArg("\x64\162\x79\x72\x75\156")); $this->setForce($args->getArg("\x66\x6f\162\143\145")); if (!$this->isReadOnlyWorkflow()) { if (PhabricatorEnv::isReadOnly()) { if ($this->isForce()) { PhabricatorEnv::setReadOnly(false, null); } else { throw new PhutilArgumentUsageException(pht("\x54\150\x69\x73\40\163\145\x72\166\145\x72\x20\151\163\40\x63\x75\162\162\x65\156\164\154\171\40\x69\x6e\40\x72\x65\141\144\55\157\x6e\154\171\x20\x6d\x6f\x64\x65\x2e\x20\125\163\x65\x20\55\55\146\x6f\162\x63\x65\40\x74\157\40" . "\x6f\166\x65\162\162\151\x64\x65\40\x74\150\151\163\40\155\x6f\144\145\x2e")); } } } return $this->didExecute($args); } public function didExecute(PhutilArgumentParser $args) { } private function loadSchemata(PhabricatorStorageManagementAPI $api) { $query = id(new PhabricatorConfigSchemaQuery()); $ref = $api->getRef(); $ref_key = $ref->getRefKey(); $query->setAPIs(array($api)); $query->setRefs(array($ref)); $actual = $query->loadActualSchemata(); $expect = $query->loadExpectedSchemata(); $comp = $query->buildComparisonSchemata($expect, $actual); return array($comp[$ref_key], $expect[$ref_key], $actual[$ref_key]); } protected final function adjustSchemata(PhabricatorStorageManagementAPI $api, $unsafe) { $lock = $this->lock($api); try { $err = $this->doAdjustSchemata($api, $unsafe); if (!$this->dryRun) { $should_analyze = $err == 0 || $err == 2; if ($should_analyze) { $this->analyzeTables($api); } } } catch (Exception $ex) { $lock->unlock(); throw $ex; } $lock->unlock(); return $err; } private function doAdjustSchemata(PhabricatorStorageManagementAPI $api, $unsafe) { $console = PhutilConsole::getConsole(); $console->writeOut("\x25\163\xa", pht("\x56\x65\162\x69\x66\171\x69\x6e\x67\40\144\141\164\141\142\x61\x73\145\x20\163\x63\x68\145\x6d\x61\164\141\x20\x6f\x6e\x20\42\x25\163\42\x2e\x2e\56", $api->getRef()->getRefKey())); list($adjustments, $errors) = $this->findAdjustments($api); if (!$adjustments) { $console->writeOut("\x25\163\xa", pht("\x46\157\165\156\x64\x20\156\x6f\40\141\x64\152\x75\163\x74\155\x65\x6e\164\x73\x20\146\x6f\162\40\x73\143\x68\145\155\x61\x74\x61\56")); return $this->printErrors($errors, 0); } if (!$this->force && !$api->isCharacterSetAvailable("\165\x74\x66\70\x6d\x62\x34")) { $message = pht("\x59\x6f\x75\x20\150\x61\166\x65\x20\x61\156\40\x6f\154\x64\40\166\145\x72\163\151\x6f\x6e\x20\x6f\x66\40\115\171\123\121\x4c\40\x28\x6f\154\x64\145\x72\x20\164\x68\141\156\40\65\x2e\x35\x29\40\167\x68\x69\143\150\40\144\157\x65\x73\40\x6e\x6f\164\40" . "\163\165\160\160\157\x72\x74\x20\x74\x68\x65\x20\x75\x74\x66\x38\x6d\x62\x34\x20\x63\x68\x61\162\x61\x63\x74\145\x72\40\x73\145\164\56\x20\127\145\40\163\x74\x72\x6f\x6e\147\154\x79\40\x72\145\143\x6f\155\155\145\x6e\144\40\165\160\x67\162\x61\x64\x69\x6e\147\x20" . "\x74\x6f\x20\x35\56\65\x20\157\x72\x20\x6e\x65\167\x65\x72\56\xa\12" . "\111\146\x20\171\157\165\40\141\x70\160\154\x79\40\x61\x64\152\x75\x73\164\155\x65\156\x74\163\x20\x6e\x6f\x77\x20\x61\156\144\x20\x6c\x61\164\145\162\x20\165\160\x64\x61\164\145\x20\x4d\171\123\121\x4c\40\x74\157\x20\x35\x2e\x35\40\157\x72\x20\x6e\x65\167\145\162\x2c\40" . "\x79\x6f\165\47\x6c\154\x20\156\145\145\x64\x20\164\x6f\40\141\x70\x70\x6c\x79\x20\141\x64\152\165\x73\x74\155\x65\156\x74\x73\x20\x61\x67\x61\x69\156\40\x28\141\x6e\x64\40\x74\x68\145\x79\x20\x77\x69\x6c\x6c\40\x74\x61\x6b\x65\40\x61\x20\x6c\157\156\147\40" . "\x74\151\x6d\145\51\56\xa\12" . "\131\157\165\40\x63\x61\x6e\x20\x65\170\x69\164\x20\x74\x68\151\163\40\x77\x6f\x72\153\x66\x6c\x6f\x77\54\40\x75\x70\x64\x61\164\145\x20\x4d\x79\x53\121\114\x20\x6e\x6f\167\x2c\x20\141\x6e\144\40\x74\x68\145\x6e\40\162\x75\156\x20\164\150\x69\x73\x20" . "\x77\157\162\153\146\154\157\167\40\x61\x67\141\x69\156\56\40\124\x68\151\163\x20\151\163\x20\x72\145\143\x6f\x6d\x6d\145\156\x64\145\x64\x2c\40\142\165\164\40\155\x61\x79\40\143\141\165\163\145\x20\141\40\154\x6f\164\40\x6f\146\40\x64\157\x77\x6e\x74\x69\155\145\x20" . "\162\x69\147\150\x74\40\x6e\x6f\x77\x2e\12\12" . "\x59\x6f\165\40\143\x61\156\x20\x65\x78\x69\x74\40\164\150\151\x73\40\x77\x6f\162\x6b\146\154\157\167\54\x20\143\157\x6e\164\151\156\165\x65\40\165\x73\x69\156\147\40\164\x68\151\x73\x20\163\x6f\146\x74\x77\141\x72\x65\40\x77\x69\164\x68\157\x75\x74\x20" . "\x61\160\160\x6c\171\151\156\147\x20\x61\x64\152\165\x73\x74\x6d\x65\156\x74\163\54\x20\165\x70\144\141\164\145\x20\x4d\x79\123\x51\114\40\x61\x74\x20\x61\40\x6c\141\164\x65\x72\40\x64\x61\x74\x65\54\x20\x61\156\x64\40\164\150\x65\156\x20\x72\165\x6e\40" . "\x74\150\151\x73\40\167\x6f\x72\153\x66\154\x6f\x77\40\141\x67\x61\151\x6e\56\40\x54\150\151\x73\x20\151\163\40\x61\154\163\157\x20\141\40\x67\x6f\x6f\x64\x20\x61\160\x70\162\157\141\143\150\x2c\x20\141\x6e\x64\40\x77\x69\154\154\x20\154\145\x74\40\171\x6f\165\40" . "\x64\x65\x6c\x61\x79\x20\144\157\x77\x6e\x74\x69\155\145\x20\165\156\164\151\154\x20\x6c\x61\164\x65\162\x2e\xa\xa" . "\x59\157\165\x20\143\x61\156\40\x70\x72\x6f\143\x65\x65\x64\40\x77\151\164\150\40\x74\x68\x69\x73\x20\167\157\x72\x6b\146\154\157\167\x2c\40\x61\156\x64\x20\164\150\x65\x6e\40\x6f\x70\x74\151\x6f\x6e\141\x6c\x6c\x79\40\165\160\144\141\164\x65\40" . "\x4d\x79\123\x51\x4c\x20\x61\164\x20\x61\40\154\141\164\x65\162\x20\144\x61\164\145\56\40\x41\146\x74\x65\162\40\x79\157\x75\40\144\157\x2c\40\x79\157\165\x27\154\x6c\x20\x6e\145\x65\144\40\164\x6f\40\x61\x70\x70\x6c\171\40" . "\x61\x64\152\165\x73\x74\155\145\156\x74\163\x20\x61\147\141\151\156\x2e\12\12" . "\x46\x6f\x72\x20\x6d\157\x72\x65\x20\x69\x6e\146\x6f\x72\x6d\141\164\151\x6f\156\54\40\163\145\x65\x20\x22\x4d\x61\x6e\141\x67\151\156\x67\x20\x53\x74\157\162\x61\x67\145\40\101\144\152\x75\x73\x74\x6d\x65\x6e\164\x73\x22\x20\151\x6e\x20" . "\164\x68\145\40\x64\157\143\165\155\145\156\164\141\x74\x69\157\x6e\x2e"); $console->writeOut("\12\x2a\x2a\74\142\x67\x3a\171\x65\x6c\x6c\157\x77\x3e\40\45\163\40\74\57\x62\x67\x3e\52\x2a\12\xa\45\x73\12", pht("\117\114\x44\40\x4d\171\x53\121\x4c\40\126\x45\122\123\x49\117\116"), phutil_console_wrap($message)); $prompt = pht("\x43\157\x6e\x74\151\156\165\x65\x20\167\151\164\x68\x20\157\x6c\144\40\115\x79\123\x51\114\x20\x76\145\162\x73\x69\157\x6e\77"); if (!phutil_console_confirm($prompt, $default_no = true)) { return; } } $table = id(new PhutilConsoleTable())->addColumn("\x64\141\164\141\142\141\x73\x65", array("\164\x69\x74\154\x65" => pht("\104\x61\x74\141\142\x61\163\x65")))->addColumn("\x74\x61\142\x6c\145", array("\164\151\x74\154\145" => pht("\124\x61\x62\x6c\145")))->addColumn("\156\x61\x6d\x65", array("\164\151\164\154\145" => pht("\x4e\x61\x6d\x65")))->addColumn("\x69\156\x66\x6f", array("\x74\151\164\154\145" => pht("\111\163\x73\165\145\x73"))); foreach ($adjustments as $adjust) { $info = array(); foreach ($adjust["\x69\163\x73\165\x65\x73"] as $issue) { $info[] = PhabricatorConfigStorageSchema::getIssueName($issue); } $table->addRow(array("\x64\141\164\141\142\141\x73\x65" => $adjust["\x64\x61\164\x61\142\141\163\x65"], "\x74\141\x62\x6c\145" => idx($adjust, "\164\141\142\154\145"), "\x6e\x61\x6d\x65" => idx($adjust, "\156\141\x6d\x65"), "\151\156\x66\157" => implode("\54\x20", $info))); } $console->writeOut("\xa\12"); $table->draw(); if ($this->dryRun) { $console->writeOut("\x25\163\12", pht("\104\122\131\x52\x55\116\72\40\x57\x6f\165\x6c\144\40\141\x70\160\x6c\171\x20\141\144\x6a\x75\x73\x74\155\x65\x6e\164\163\x2e")); return 0; } else { if ($this->didInitialize) { } else { if (!$this->force) { $console->writeOut("\12\45\x73\12", pht("\106\157\165\x6e\x64\40\x25\x73\40\x61\144\x6a\x75\163\164\155\x65\156\x74\50\x73\x29\40\164\x6f\x20\x61\160\160\x6c\171\54\40\144\x65\x74\141\151\154\x65\x64\40\141\142\x6f\166\145\56\12\12" . "\131\157\x75\x20\143\x61\156\40\162\x65\166\x69\145\167\x20\x61\x64\x6a\165\x73\x74\x6d\x65\156\x74\163\40\151\156\x20\155\157\162\x65\x20\x64\x65\164\x61\151\154\x20\146\x72\157\x6d\x20\164\150\145\x20\x77\145\x62\x20\151\156\164\x65\162\146\141\143\x65\x2c\40" . "\x69\x6e\40\x43\157\x6e\146\x69\x67\40\76\x20\104\141\x74\x61\142\141\x73\145\40\123\164\x61\164\165\x73\x2e\40\124\x6f\40\x62\145\164\164\x65\x72\x20\165\x6e\144\145\162\163\x74\141\x6e\144\40\x74\x68\x65\40\x61\x64\152\165\163\x74\155\x65\x6e\x74\x20" . "\x77\157\x72\153\146\x6c\x6f\x77\x2c\40\x73\145\145\x20\42\115\x61\x6e\141\147\151\156\x67\x20\x53\164\x6f\x72\x61\x67\x65\x20\x41\144\152\x75\163\164\155\145\156\x74\x73\x22\40\151\x6e\x20\164\x68\x65\x20" . "\x64\x6f\x63\x75\155\x65\x6e\x74\141\x74\151\157\156\x2e\12\xa" . "\x4d\171\123\x51\114\x20\x6e\145\145\144\x73\40\x74\157\x20\x63\x6f\x70\171\x20\164\141\x62\154\x65\40\144\x61\164\x61\x20\x74\157\40\155\141\153\x65\40\163\157\155\x65\40\x61\x64\x6a\165\163\164\155\145\156\164\x73\x2c\40\163\157\40\164\150\145\163\145\40" . "\155\x69\x67\162\141\x74\x69\x6f\156\x73\x20\x6d\x61\171\40\164\x61\x6b\145\40\x73\x6f\155\145\40\164\151\x6d\x65\x2e", phutil_count($adjustments))); $prompt = pht("\101\160\x70\x6c\171\x20\x74\150\145\163\145\40\163\143\150\145\155\x61\40\x61\144\152\x75\x73\x74\155\145\156\164\x73\x3f"); if (!phutil_console_confirm($prompt, $default_no = true)) { return 1; } } } } $console->writeOut("\45\x73\12", pht("\101\160\160\x6c\x79\x69\x6e\x67\40\163\x63\x68\145\x6d\x61\40\141\x64\x6a\x75\x73\164\155\145\x6e\164\x73\x2e\x2e\56")); $conn = $api->getConn(null); if ($unsafe) { queryfx($conn, "\123\105\124\40\x53\105\123\123\111\x4f\x4e\x20\x73\161\154\137\155\x6f\144\x65\40\x3d\40\45\x73", ''); } else { queryfx($conn, "\x53\x45\x54\x20\123\x45\x53\123\x49\117\116\40\163\161\x6c\x5f\155\157\x64\x65\x20\x3d\x20\x25\x73", "\x53\x54\x52\111\x43\124\x5f\x41\x4c\x4c\x5f\124\101\x42\114\105\123"); } $failed = array(); $phases = array("\144\x72\157\x70\x5f\141\x75\164\x6f", "\x64\x72\x6f\x70\137\x6b\x65\171\x73", "\155\141\151\x6e", "\141\x64\144\x5f\x6b\145\x79\163", "\141\144\x64\x5f\x61\165\x74\157"); $bar = id(new PhutilConsoleProgressBar())->setTotal(count($adjustments) * count($phases)); foreach ($phases as $phase) { foreach ($adjustments as $adjust) { try { switch ($adjust["\x6b\x69\x6e\x64"]) { case "\144\x61\164\141\x62\141\x73\x65": if ($phase == "\155\x61\x69\x6e") { queryfx($conn, "\101\114\124\x45\x52\40\x44\x41\x54\x41\x42\x41\123\105\40\45\124\x20\x43\110\x41\122\101\x43\x54\105\x52\x20\123\105\x54\40\75\x20\45\163\x20\x43\117\114\114\101\x54\105\x20\x3d\x20\x25\163", $adjust["\144\x61\164\x61\142\x61\163\145"], $adjust["\143\150\x61\x72\163\145\x74"], $adjust["\143\157\x6c\x6c\x61\164\x69\x6f\x6e"]); } break; case "\x74\x61\x62\x6c\145": if ($phase == "\x6d\141\151\156") { queryfx($conn, "\x41\114\124\x45\x52\x20\124\101\x42\x4c\105\x20\x25\124\x2e\45\x54\40\x43\117\x4c\114\x41\x54\x45\x20\x3d\40\x25\163\x2c\40\105\116\107\x49\x4e\x45\40\x3d\x20\45\163", $adjust["\144\141\164\141\142\x61\x73\x65"], $adjust["\164\141\x62\x6c\x65"], $adjust["\143\x6f\x6c\x6c\141\164\151\x6f\x6e"], $adjust["\145\156\x67\151\156\145"]); } break; case "\143\x6f\154\165\x6d\x6e": $apply = false; $auto = false; $new_auto = idx($adjust, "\x61\x75\164\157"); if ($phase == "\144\162\x6f\x70\x5f\141\165\x74\x6f") { if ($new_auto === false) { $apply = true; $auto = false; } } else { if ($phase == "\x6d\x61\151\x6e") { $apply = true; if ($new_auto === false) { $auto = false; } else { $auto = $adjust["\151\163\137\141\x75\164\157"]; } } else { if ($phase == "\x61\x64\x64\137\141\x75\x74\157") { if ($new_auto === true) { $apply = true; $auto = true; } } } } if ($apply) { $parts = array(); if ($auto) { $parts[] = qsprintf($conn, "\x41\125\x54\x4f\x5f\111\116\x43\122\105\115\105\116\x54"); } if ($adjust["\143\150\141\162\163\145\x74"]) { switch ($adjust["\143\x68\x61\x72\163\x65\164"]) { case "\142\151\156\141\x72\171": $charset_value = qsprintf($conn, "\142\151\156\x61\x72\171"); break; case "\165\x74\x66\70": $charset_value = qsprintf($conn, "\165\164\146\70"); break; case "\x75\x74\x66\70\x6d\x62\64": $charset_value = qsprintf($conn, "\165\x74\x66\x38\155\x62\x34"); break; default: throw new Exception(pht("\125\156\x73\165\160\160\157\x72\164\x65\144\40\x63\150\141\162\x61\x63\164\x65\x72\40\163\x65\164\x20\42\45\x73\42\x2e", $adjust["\143\150\141\162\x73\x65\164"])); } switch ($adjust["\143\x6f\154\154\x61\164\151\x6f\x6e"]) { case "\142\151\x6e\141\162\x79": $collation_value = qsprintf($conn, "\142\x69\156\x61\162\171"); break; case "\165\164\146\70\137\147\145\156\x65\x72\141\154\x5f\143\x69": $collation_value = qsprintf($conn, "\x75\164\x66\70\x5f\147\145\156\x65\x72\x61\x6c\x5f\x63\x69"); break; case "\x75\x74\146\x38\155\142\64\x5f\x62\151\156": $collation_value = qsprintf($conn, "\165\x74\146\70\x6d\x62\x34\137\142\x69\156"); break; case "\165\164\x66\x38\155\x62\x34\137\165\156\151\143\x6f\x64\145\137\143\x69": $collation_value = qsprintf($conn, "\x75\164\146\x38\x6d\x62\64\x5f\x75\156\x69\143\157\x64\x65\137\143\151"); break; default: throw new Exception(pht("\x55\x6e\x73\165\160\x70\x6f\162\x74\145\x64\40\143\x6f\x6c\154\x61\x74\151\157\156\40\163\x65\x74\40\x22\x25\x73\x22\x2e", $adjust["\143\x6f\154\x6c\x61\x74\x69\x6f\156"])); } $parts[] = qsprintf($conn, "\103\x48\101\122\x41\x43\x54\x45\122\x20\x53\x45\x54\40\x25\121\x20\x43\117\x4c\114\101\x54\105\x20\x25\121", $charset_value, $collation_value); } if ($parts) { $parts = qsprintf($conn, "\x25\114\x4a", $parts); } else { $parts = qsprintf($conn, ''); } if ($adjust["\156\x75\154\154\141\x62\x6c\145"]) { $nullable = qsprintf($conn, "\x4e\x55\x4c\114"); } else { $nullable = qsprintf($conn, "\116\x4f\124\40\116\x55\114\114"); } queryfx($conn, "\x41\114\x54\x45\122\x20\x54\101\102\114\x45\40\x25\x54\56\x25\124\x20\115\x4f\x44\111\106\131\x20\45\124\40\45\132\40\45\121\40\x25\121", $adjust["\144\x61\x74\141\x62\141\x73\145"], $adjust["\164\x61\142\154\x65"], $adjust["\x6e\141\x6d\145"], $adjust["\x74\x79\x70\145"], $parts, $nullable); } break; case "\153\145\x79": if ($phase == "\144\162\x6f\x70\x5f\153\x65\171\x73" && $adjust["\145\x78\x69\x73\x74\163"]) { if ($adjust["\156\x61\x6d\x65"] == "\120\122\x49\115\x41\122\131") { $key_name = qsprintf($conn, "\x50\x52\111\115\101\122\x59\x20\113\x45\x59"); } else { $key_name = qsprintf($conn, "\113\105\131\40\45\124", $adjust["\156\x61\155\x65"]); } queryfx($conn, "\x41\114\x54\105\x52\40\x54\101\x42\114\105\40\45\124\56\x25\x54\x20\x44\x52\x4f\120\x20\x25\x51", $adjust["\144\x61\x74\x61\142\x61\x73\x65"], $adjust["\x74\x61\x62\154\x65"], $key_name); } if ($phase == "\x61\144\x64\137\x6b\x65\x79\163" && $adjust["\x6b\145\145\160"]) { if ($adjust["\x6e\x61\155\x65"] == "\x50\x52\111\x4d\x41\x52\x59") { $key_name = qsprintf($conn, "\120\122\111\x4d\101\x52\x59\x20\x4b\105\x59"); } else { if ($adjust["\x69\x6e\144\x65\170\124\x79\160\145"] == "\106\x55\x4c\x4c\x54\105\x58\124") { $key_name = qsprintf($conn, "\106\125\114\114\124\105\x58\124\x20\45\124", $adjust["\156\x61\155\x65"]); } else { if ($adjust["\x75\156\x69\x71\165\x65"]) { $key_name = qsprintf($conn, "\125\x4e\111\x51\125\105\40\x4b\x45\x59\40\45\x54", $adjust["\x6e\141\x6d\x65"]); } else { $key_name = qsprintf($conn, "\57\x2a\x20\x4e\117\116\125\x4e\x49\121\125\105\40\52\57\x20\x4b\105\131\x20\x25\x54", $adjust["\156\x61\x6d\145"]); } } } queryfx($conn, "\x41\x4c\124\x45\x52\x20\x54\x41\x42\x4c\105\40\x25\124\56\x25\x54\x20\101\104\104\x20\45\x51\x20\x28\45\x4c\113\x29", $adjust["\x64\x61\164\x61\x62\141\x73\145"], $adjust["\x74\141\142\154\145"], $key_name, $adjust["\143\x6f\154\165\x6d\156\x73"]); } break; default: throw new Exception(pht("\x55\156\x6b\x6e\157\x77\156\x20\x73\143\x68\x65\x6d\141\x20\141\144\x6a\x75\163\164\155\x65\x6e\164\40\x6b\151\156\144\x20\x22\45\163\42\x21", $adjust["\x6b\151\156\144"])); } } catch (AphrontQueryException $ex) { $failed[] = array($adjust, $ex); } $bar->update(1); } } $bar->done(); if (!$failed) { $console->writeOut("\x25\163\12", pht("\103\x6f\x6d\160\154\145\x74\145\144\x20\x61\x70\160\154\171\151\156\x67\40\141\x6c\154\40\x73\143\150\x65\155\x61\x20\x61\144\x6a\x75\163\x74\x6d\x65\x6e\x74\163\56")); $err = 0; } else { $table = id(new PhutilConsoleTable())->addColumn("\164\x61\x72\x67\x65\x74", array("\x74\x69\x74\154\x65" => pht("\124\141\162\147\145\x74")))->addColumn("\x65\x72\x72\x6f\162", array("\164\151\164\154\145" => pht("\105\162\162\157\x72"))); foreach ($failed as $failure) { list($adjust, $ex) = $failure; $pieces = array_select_keys($adjust, array("\x64\x61\164\x61\x62\x61\x73\145", "\x74\x61\142\154\x65", "\x6e\x61\155\x65")); $pieces = array_filter($pieces); $target = implode("\x2e", $pieces); $table->addRow(array("\x74\141\x72\x67\x65\x74" => $target, "\145\x72\x72\x6f\162" => $ex->getMessage())); } $console->writeOut("\xa"); $table->draw(); $console->writeOut("\xa\45\x73\12", pht("\106\x61\151\154\x65\x64\40\x74\x6f\40\x6d\x61\153\x65\x20\x73\157\155\x65\40\x73\x63\x68\145\155\141\x20\x61\x64\152\x75\x73\164\155\x65\x6e\x74\x73\x2c\40\144\145\164\x61\151\154\x65\x64\x20\141\x62\x6f\x76\x65\56")); $console->writeOut("\x25\x73\xa", pht("\106\x6f\x72\40\x68\x65\x6c\160\40\164\x72\x6f\x75\x62\x6c\x65\163\x68\x6f\157\164\151\x6e\147\x20\x61\144\152\x75\163\x74\155\x65\x6e\164\163\x2c\40\163\x65\x65\x20\42\115\141\x6e\x61\147\x69\x6e\x67\x20\123\x74\x6f\162\x61\147\145\40" . "\x41\144\152\x75\x73\164\x6d\145\x6e\164\163\x22\x20\x69\156\40\x74\x68\x65\x20\x64\157\x63\165\x6d\x65\x6e\164\x61\164\x69\157\x6e\56")); $err = 1; } return $this->printErrors($errors, $err); } private function findAdjustments(PhabricatorStorageManagementAPI $api) { list($comp, $expect, $actual) = $this->loadSchemata($api); $issue_charset = PhabricatorConfigStorageSchema::ISSUE_CHARSET; $issue_collation = PhabricatorConfigStorageSchema::ISSUE_COLLATION; $issue_columntype = PhabricatorConfigStorageSchema::ISSUE_COLUMNTYPE; $issue_surpluskey = PhabricatorConfigStorageSchema::ISSUE_SURPLUSKEY; $issue_missingkey = PhabricatorConfigStorageSchema::ISSUE_MISSINGKEY; $issue_columns = PhabricatorConfigStorageSchema::ISSUE_KEYCOLUMNS; $issue_unique = PhabricatorConfigStorageSchema::ISSUE_UNIQUE; $issue_longkey = PhabricatorConfigStorageSchema::ISSUE_LONGKEY; $issue_auto = PhabricatorConfigStorageSchema::ISSUE_AUTOINCREMENT; $issue_engine = PhabricatorConfigStorageSchema::ISSUE_ENGINE; $adjustments = array(); $errors = array(); foreach ($comp->getDatabases() as $database_name => $database) { foreach ($this->findErrors($database) as $issue) { $errors[] = array("\144\141\164\x61\142\141\x73\145" => $database_name, "\x69\x73\163\165\145" => $issue); } $expect_database = $expect->getDatabase($database_name); $actual_database = $actual->getDatabase($database_name); if (!$expect_database || !$actual_database) { continue; } if ($actual_database->getAccessDenied()) { continue; } $issues = array(); if ($database->hasIssue($issue_charset)) { $issues[] = $issue_charset; } if ($database->hasIssue($issue_collation)) { $issues[] = $issue_collation; } if ($issues) { $adjustments[] = array("\153\x69\x6e\144" => "\144\x61\x74\141\142\x61\x73\145", "\144\141\x74\141\x62\141\163\x65" => $database_name, "\151\x73\x73\x75\145\x73" => $issues, "\143\150\x61\x72\x73\145\164" => $expect_database->getCharacterSet(), "\x63\157\154\x6c\x61\164\x69\x6f\156" => $expect_database->getCollation()); } foreach ($database->getTables() as $table_name => $table) { foreach ($this->findErrors($table) as $issue) { $errors[] = array("\x64\141\164\141\x62\141\x73\145" => $database_name, "\164\141\142\154\x65" => $table_name, "\x69\x73\x73\x75\x65" => $issue); } $expect_table = $expect_database->getTable($table_name); $actual_table = $actual_database->getTable($table_name); if (!$expect_table || !$actual_table) { continue; } $issues = array(); if ($table->hasIssue($issue_collation)) { $issues[] = $issue_collation; } if ($table->hasIssue($issue_engine)) { $issues[] = $issue_engine; } if ($issues) { $adjustments[] = array("\x6b\x69\x6e\x64" => "\x74\x61\142\154\x65", "\x64\x61\164\141\142\141\163\x65" => $database_name, "\x74\x61\142\x6c\145" => $table_name, "\x69\163\163\x75\145\x73" => $issues, "\x63\157\154\x6c\141\x74\x69\x6f\156" => $expect_table->getCollation(), "\x65\156\147\x69\156\x65" => $expect_table->getEngine()); } foreach ($table->getColumns() as $column_name => $column) { foreach ($this->findErrors($column) as $issue) { $errors[] = array("\x64\x61\164\x61\x62\x61\x73\145" => $database_name, "\164\141\x62\154\x65" => $table_name, "\156\x61\155\145" => $column_name, "\x69\163\163\x75\x65" => $issue); } $expect_column = $expect_table->getColumn($column_name); $actual_column = $actual_table->getColumn($column_name); if (!$expect_column || !$actual_column) { continue; } $issues = array(); if ($column->hasIssue($issue_collation)) { $issues[] = $issue_collation; } if ($column->hasIssue($issue_charset)) { $issues[] = $issue_charset; } if ($column->hasIssue($issue_columntype)) { $issues[] = $issue_columntype; } if ($column->hasIssue($issue_auto)) { $issues[] = $issue_auto; } if ($issues) { if ($expect_column->getCharacterSet() === null) { $charset = null; $collation = null; } else { $charset = $expect_column->getCharacterSet(); $collation = $expect_column->getCollation(); } $adjustment = array("\x6b\x69\156\x64" => "\x63\x6f\x6c\165\155\x6e", "\x64\141\x74\x61\142\x61\163\145" => $database_name, "\164\141\x62\154\145" => $table_name, "\x6e\141\155\x65" => $column_name, "\x69\x73\163\165\x65\x73" => $issues, "\143\157\154\154\x61\x74\151\x6f\x6e" => $collation, "\x63\x68\141\162\x73\145\x74" => $charset, "\x74\171\160\x65" => $expect_column->getColumnType(), "\x6e\x75\154\154\141\x62\154\x65" => $actual_column->getNullable(), "\151\x73\x5f\141\165\x74\157" => $actual_column->getAutoIncrement()); if ($column->hasIssue($issue_auto)) { $adjustment["\141\x75\x74\157"] = $expect_column->getAutoIncrement(); } $adjustments[] = $adjustment; } } foreach ($table->getKeys() as $key_name => $key) { foreach ($this->findErrors($key) as $issue) { $errors[] = array("\x64\x61\164\141\142\141\x73\x65" => $database_name, "\164\x61\142\x6c\x65" => $table_name, "\x6e\141\x6d\145" => $key_name, "\x69\x73\x73\x75\145" => $issue); } $expect_key = $expect_table->getKey($key_name); $actual_key = $actual_table->getKey($key_name); $issues = array(); $keep_key = true; if ($key->hasIssue($issue_surpluskey)) { $issues[] = $issue_surpluskey; $keep_key = false; } if ($key->hasIssue($issue_missingkey)) { $issues[] = $issue_missingkey; } if ($key->hasIssue($issue_columns)) { $issues[] = $issue_columns; } if ($key->hasIssue($issue_unique)) { $issues[] = $issue_unique; } if ($key->hasIssue($issue_longkey)) { $issues[] = $issue_longkey; } if ($issues) { $adjustment = array("\x6b\x69\156\144" => "\x6b\x65\x79", "\x64\x61\164\141\142\x61\163\145" => $database_name, "\164\x61\x62\154\x65" => $table_name, "\156\x61\155\145" => $key_name, "\x69\x73\x73\x75\145\x73" => $issues, "\x65\x78\x69\163\164\163" => (bool) $actual_key, "\153\x65\145\x70" => $keep_key); if ($keep_key) { $adjustment += array("\143\x6f\154\165\155\156\x73" => $expect_key->getColumnNames(), "\x75\x6e\x69\x71\x75\x65" => $expect_key->getUnique(), "\x69\x6e\x64\145\x78\124\x79\x70\145" => $expect_key->getIndexType()); } $adjustments[] = $adjustment; } } } } return array($adjustments, $errors); } private function findErrors(PhabricatorConfigStorageSchema $schema) { $result = array(); foreach ($schema->getLocalIssues() as $issue) { $status = PhabricatorConfigStorageSchema::getIssueStatus($issue); if ($status == PhabricatorConfigStorageSchema::STATUS_FAIL) { $result[] = $issue; } } return $result; } private function printErrors(array $errors, $default_return) { if (!$errors) { return $default_return; } $console = PhutilConsole::getConsole(); $table = id(new PhutilConsoleTable())->addColumn("\x74\x61\x72\x67\x65\164", array("\164\x69\164\154\x65" => pht("\124\x61\162\147\x65\164")))->addColumn("\145\x72\x72\157\x72", array("\164\x69\x74\154\145" => pht("\x45\162\x72\x6f\x72"))); $any_surplus = false; $all_surplus = true; $any_access = false; $all_access = true; foreach ($errors as $error) { $pieces = array_select_keys($error, array("\144\141\164\x61\x62\141\x73\145", "\x74\x61\x62\154\145", "\x6e\141\155\145")); $pieces = array_filter($pieces); $target = implode("\56", $pieces); $name = PhabricatorConfigStorageSchema::getIssueName($error["\151\163\163\x75\145"]); $issue = $error["\151\163\163\x75\x65"]; if ($issue === PhabricatorConfigStorageSchema::ISSUE_SURPLUS) { $any_surplus = true; } else { $all_surplus = false; } if ($issue === PhabricatorConfigStorageSchema::ISSUE_ACCESSDENIED) { $any_access = true; } else { $all_access = false; } $table->addRow(array("\x74\x61\x72\x67\x65\x74" => $target, "\145\x72\162\157\x72" => $name)); } $console->writeOut("\xa"); $table->draw(); $console->writeOut("\12"); $message = array(); if ($all_surplus) { $message[] = pht("\x59\157\x75\40\150\x61\166\x65\40\x73\x75\x72\x70\154\165\163\40\163\143\150\145\x6d\x61\164\x61\x20\50\x65\x78\164\162\141\40\x74\x61\142\x6c\145\x73\40\x6f\x72\40\x63\x6f\154\x75\x6d\x6e\x73\x20\x77\150\x69\x63\x68\40\164\x68\151\163\40" . "\x73\x6f\146\164\167\141\x72\x65\x20\x64\x6f\x65\x73\40\x6e\x6f\164\40\145\170\x70\145\x63\x74\x29\56\40\x46\x6f\x72\40\x69\156\146\x6f\162\x6d\141\164\151\157\x6e\x20\x6f\x6e\40\162\x65\163\x6f\x6c\x76\151\x6e\147\x20\164\x68\x65\x73\x65\40" . "\x69\163\x73\165\x65\x73\x2c\40\163\145\x65\40\x74\150\x65\x20\x22\x53\165\162\160\x6c\x75\x73\40\123\x63\150\145\x6d\x61\x74\141\x22\40\163\145\x63\x74\151\x6f\x6e\x20\x69\x6e\x20\x74\x68\145\x20\x22\115\141\156\141\x67\x69\156\147\x20\x53\x74\157\162\141\x67\145\x20" . "\x41\x64\x6a\165\x73\x74\x6d\x65\156\x74\163\42\40\141\162\164\151\x63\154\145\x20\151\x6e\40\164\150\145\40\x64\x6f\143\165\155\x65\x6e\x74\141\x74\x69\x6f\x6e\56"); } else { if ($all_access) { $message[] = pht("\x54\150\145\x20\x75\x73\145\x72\x20\171\157\x75\40\141\x72\145\40\143\x6f\x6e\156\145\x63\164\151\156\x67\x20\164\157\40\x4d\171\x53\x51\114\x20\x77\x69\x74\150\x20\144\157\x65\163\40\156\x6f\164\40\x68\x61\166\145\x20\x74\150\145\x20\143\157\x72\x72\145\143\x74\40" . "\160\145\x72\155\151\163\x73\x69\157\x6e\x73\x2c\40\x61\156\x64\x20\143\141\x6e\40\x6e\157\x74\x20\141\143\143\145\163\163\40\x73\157\155\x65\40\x64\141\164\141\142\141\163\x65\x73\x20\157\162\40\164\141\142\154\145\163\x20\x74\150\x61\164\x20\151\164\x20" . "\x6e\145\145\x64\163\x20\164\157\40\x62\x65\40\x61\142\x6c\145\40\164\x6f\x20\141\143\143\145\x73\163\x2e\40\107\x52\x41\x4e\124\x20\x74\150\x65\x20\x75\x73\x65\x72\40\x61\x64\144\x69\x74\151\x6f\156\141\154\40\x70\145\162\x6d\151\163\x73\x69\x6f\x6e\x73\x2e"); } else { $message[] = pht("\x54\150\x65\x20\x73\143\150\145\x6d\x61\x74\141\40\x68\x61\166\145\40\145\162\x72\x6f\162\x73\x20\50\144\145\164\141\151\154\x65\x64\40\x61\142\x6f\166\145\51\x20\x77\x68\x69\x63\150\x20\x74\x68\145\x20\141\x64\152\165\163\164\155\145\156\164\x20" . "\167\x6f\162\x6b\146\154\157\167\x20\x63\141\156\40\156\157\164\40\x66\x69\170\56"); if ($any_access) { $message[] = pht("\x53\157\155\145\40\157\x66\x20\164\150\145\163\145\x20\145\x72\162\157\162\x73\x20\141\x72\145\40\143\x61\x75\163\x65\144\x20\142\171\x20\141\143\143\x65\x73\x73\40\143\x6f\156\x74\162\x6f\x6c\40\160\162\157\x62\x6c\x65\155\163\x2e\x20" . "\124\x68\145\40\x75\163\x65\x72\40\x79\x6f\165\x20\141\162\x65\40\143\x6f\x6e\156\145\x63\164\151\156\147\x20\167\x69\x74\150\x20\x64\x6f\145\x73\x20\x6e\x6f\x74\40\150\x61\x76\145\x20\x70\145\x72\155\x69\163\163\151\x6f\x6e\x20\x74\x6f\40\x73\145\145\x20" . "\141\x6c\x6c\x20\157\x66\x20\x74\x68\x65\40\144\141\164\x61\x62\x61\163\145\x20\157\162\40\164\x61\x62\154\x65\x73\40\x74\x68\x61\x74\40\x74\150\x69\x73\40\x73\157\146\164\x77\141\x72\145\x20\165\x73\x65\x73\56\40\131\157\x75\x20\x6e\x65\145\x64\x20\164\x6f\40" . "\x47\122\101\x4e\124\x20\164\150\145\40\x75\163\x65\162\x20\x6d\x6f\x72\x65\x20\x70\145\x72\x6d\151\x73\x73\151\157\156\x2c\x20\x6f\x72\x20\165\163\x65\40\141\40\144\x69\x66\x66\x65\x72\145\156\164\40\165\x73\x65\162\x2e"); } if ($any_surplus) { $message[] = pht("\x53\157\155\x65\x20\157\x66\40\x74\150\x65\163\x65\40\145\162\162\157\162\163\40\141\x72\145\40\x63\141\165\163\x65\144\40\x62\x79\x20\x73\165\162\160\154\165\x73\x20\163\x63\x68\145\x6d\141\164\141\40\50\x65\x78\x74\x72\141\40" . "\x74\x61\142\154\x65\163\x20\x6f\x72\x20\x63\157\x6c\165\155\156\163\40\x77\150\x69\x63\x68\x20\164\x68\x69\x73\x20\x73\157\146\164\x77\141\162\145\40\x64\x6f\145\x73\x20\x6e\x6f\164\x20\145\170\x70\x65\143\x74\x29\x2e\x20\x54\150\x65\x73\x65\x20\141\162\x65\x20" . "\x6e\x6f\164\40\x73\x65\x72\151\157\x75\x73\x2e\40\106\157\162\x20\151\x6e\x66\x6f\162\x6d\x61\x74\x69\157\x6e\40\157\x6e\40\x72\x65\163\x6f\x6c\166\151\x6e\147\40\x74\150\x65\x73\x65\x20\151\x73\x73\165\145\x73\x2c\40\x73\145\145\x20\x74\150\145\x20" . "\x22\123\x75\x72\x70\154\x75\163\x20\123\143\x68\x65\155\x61\164\x61\42\40\x73\145\143\x74\151\x6f\156\40\x69\x6e\40\x74\x68\x65\40\42\115\141\156\141\147\151\156\147\40\x53\164\x6f\162\x61\147\145\x20\101\144\x6a\x75\x73\164\155\145\x6e\164\x73\42\x20" . "\141\x72\164\x69\x63\x6c\145\40\x69\156\40\x74\x68\x65\x20\144\157\143\x75\x6d\145\x6e\x74\x61\x74\x69\157\x6e\56"); } $message[] = pht("\111\146\40\171\157\x75\40\x61\162\x65\40\156\x6f\164\40\x64\145\x76\x65\x6c\x6f\x70\x69\x6e\x67\x20\x25\x73\x20\151\164\x73\x65\x6c\x66\54\x20\162\x65\160\x6f\162\164\40\x74\x68\151\163\40\x69\x73\163\x75\x65\40\164\157\x20" . "\164\x68\145\40\x75\160\x73\x74\x72\x65\141\x6d\x2e", PlatformSymbols::getPlatformServerName()); $message[] = pht("\111\x66\40\x79\x6f\165\40\141\x72\x65\x20\x64\145\166\x65\x6c\157\x70\x69\x6e\x67\x20\x25\x73\54\40\164\150\x65\x73\x65\x20\x65\x72\162\157\x72\x73\x20\165\163\x75\x61\x6c\154\171\x20\151\156\144\151\x63\141\164\x65\40" . "\x74\x68\141\164\x20\x79\x6f\165\x72\40\163\x63\150\145\x6d\x61\x20\163\160\x65\x63\151\146\x69\x63\141\164\x69\x6f\x6e\x73\40\x64\157\40\156\x6f\x74\40\x61\x67\x72\145\145\40\x77\x69\164\x68\40\x74\x68\x65\40\163\x63\150\x65\x6d\x61\164\x61\x20\x79\x6f\x75\162\40" . "\143\x6f\144\x65\40\x61\x63\x74\165\141\154\x6c\171\x20\x62\x75\151\x6c\144\163\56", PlatformSymbols::getPlatformServerName()); } } $message = implode("\xa\12", $message); if ($all_surplus) { $console->writeOut("\x2a\52\74\x62\147\72\171\145\154\x6c\x6f\x77\76\x20\45\163\40\74\57\x62\x67\x3e\x2a\52\12\12\x25\163\xa", pht("\x53\x55\122\x50\114\x55\x53\x20\x53\103\x48\105\115\101\x54\101"), phutil_console_wrap($message)); } else { if ($all_access) { $console->writeOut("\x2a\x2a\x3c\x62\147\x3a\171\x65\x6c\x6c\x6f\x77\x3e\x20\x25\x73\x20\74\57\142\147\x3e\52\52\xa\12\45\163\xa", pht("\101\x43\103\105\123\x53\x20\104\x45\116\111\x45\x44"), phutil_console_wrap($message)); } else { $console->writeOut("\x2a\52\x3c\x62\x67\x3a\162\145\x64\x3e\x20\x25\163\x20\74\57\x62\147\x3e\x2a\52\xa\xa\x25\163\12", pht("\123\x43\110\x45\x4d\101\124\101\40\x45\122\122\117\122\x53"), phutil_console_wrap($message)); } } return 2; } protected final function upgradeSchemata(array $apis, $apply_only = null, $no_quickstart = false, $init_only = false) { $locks = array(); foreach ($apis as $api) { $locks[] = $this->lock($api); } try { $this->doUpgradeSchemata($apis, $apply_only, $no_quickstart, $init_only); } catch (Exception $ex) { foreach ($locks as $lock) { $lock->unlock(); } throw $ex; } foreach ($locks as $lock) { $lock->unlock(); } } private function doUpgradeSchemata(array $apis, $apply_only, $no_quickstart, $init_only) { $patches = $this->patches; $is_dryrun = $this->dryRun; $patches = msortv($patches, "\156\145\167\x53\x6f\x72\164\x56\x65\143\x74\x6f\x72"); $api_map = array(); foreach ($apis as $api) { $api_map[$api->getRef()->getRefKey()] = $api; } foreach ($api_map as $ref_key => $api) { $applied = $api->getAppliedPatches(); $needs_init = $applied === null; if (!$needs_init) { continue; } if ($is_dryrun) { echo tsprintf("\45\x73\xa", pht("\104\x52\131\x52\125\x4e\72\40\123\164\x6f\x72\141\147\145\40\157\156\x20\x68\x6f\x73\164\x20\42\x25\x73\42\x20\144\157\x65\163\x20\156\x6f\x74\40\145\170\x69\x73\164\40\x79\x65\164\54\40\163\x6f\40\151\164\40" . "\x77\x6f\x75\154\x64\40\142\x65\40\143\162\145\x61\x74\x65\x64\x2e", $ref_key)); continue; } if ($apply_only) { throw new PhutilArgumentUsageException(pht("\123\164\157\162\x61\x67\145\40\157\156\40\150\157\163\x74\40\42\45\x73\x22\x20\150\x61\163\x20\x6e\157\164\x20\142\145\x65\156\x20\151\x6e\151\x74\x69\141\x6c\151\x7a\145\144\x20\x79\x65\x74\x2e\x20\x59\157\x75\x20\155\x75\163\164\40" . "\x69\156\151\x74\151\x61\154\x69\x7a\145\40\x73\164\x6f\x72\141\x67\145\x20\142\145\146\x6f\x72\145\40\163\145\x6c\145\x63\164\151\x76\145\x6c\x79\x20\141\160\x70\x6c\x79\151\x6e\147\40\x70\x61\x74\143\150\145\163\x2e", $ref_key)); } $this->didInitialize = true; $legacy = $api->getLegacyPatches($patches); if ($legacy || $no_quickstart || $init_only) { $api->createDatabase("\x6d\145\x74\x61\137\x64\141\164\141"); $api->createTable("\x6d\145\164\141\x5f\144\141\x74\141", "\x70\141\164\x63\x68\x5f\x73\164\x61\x74\x75\x73", array("\160\141\x74\143\150\x20\126\x41\x52\103\110\101\122\50\x32\65\x35\51\x20\x4e\x4f\x54\x20\x4e\x55\114\114\40\x50\x52\111\x4d\x41\122\x59\x20\x4b\x45\x59\40\103\x4f\x4c\x4c\101\124\x45\40\x75\164\146\x38\137\147\145\156\x65\162\141\154\137\x63\151", "\x61\160\x70\154\x69\x65\x64\40\x49\116\x54\x20\x55\116\123\x49\107\116\x45\104\40\x4e\117\x54\x20\116\125\x4c\x4c")); foreach ($legacy as $patch) { $api->markPatchApplied($patch); } } else { echo tsprintf("\x25\163\12", pht("\114\157\x61\x64\x69\x6e\147\40\161\x75\x69\x63\153\x73\164\141\162\x74\x20\x74\x65\155\160\x6c\141\x74\x65\x20\157\156\x74\x6f\x20\x22\x25\x73\x22\56\56\x2e", $ref_key)); $root = dirname(phutil_get_library_root("\x70\150\141\142\x72\x69\x63\x61\x74\x6f\162")); $sql = $root . "\x2f\x72\x65\163\x6f\165\x72\143\x65\163\57\x73\161\x6c\57\161\165\151\143\153\163\x74\x61\162\x74\56\x73\x71\154"; $api->applyPatchSQL($sql); } } if ($init_only) { echo pht("\x53\x74\157\162\141\147\x65\x20\x69\156\151\164\x69\x61\x6c\x69\172\x65\x64\x2e") . "\12"; return 0; } $applied_map = array(); $state_map = array(); foreach ($api_map as $ref_key => $api) { $applied = $api->getAppliedPatches(); if ($applied === null) { if ($is_dryrun) { continue; } else { throw new Exception(pht("\x44\x61\x74\x61\142\141\x73\x65\x20\x69\x6e\x69\x74\x69\141\x6c\x69\172\x61\x74\x69\x6f\156\40\157\x6e\40\150\x6f\x73\x74\x20\x22\45\x73\x22\40\141\x70\x70\154\151\x65\x64\40\x6e\x6f\40\160\141\x74\x63\150\x65\163\x21", $ref_key)); } } $applied = array_fuse($applied); $state_map[$ref_key] = $applied; if ($apply_only) { if (isset($applied[$apply_only])) { if (!$this->force && !$is_dryrun) { echo phutil_console_wrap(pht("\120\141\164\143\x68\40\42\45\163\x22\x20\150\x61\x73\40\141\154\162\145\141\x64\171\x20\142\145\145\x6e\40\x61\160\x70\154\x69\145\144\40\157\156\40\150\157\163\x74\40\42\x25\x73\42\56\40\x41\162\x65\40\171\x6f\x75\40" . "\163\x75\162\145\x20\171\157\165\40\167\141\156\x74\x20\x74\x6f\40\141\160\x70\154\171\x20\151\x74\x20\x61\147\141\151\156\x3f\x20\x54\x68\151\x73\x20\155\x61\x79\x20\160\165\x74\x20\171\x6f\165\162\x20\163\x74\157\x72\141\147\145\40" . "\151\156\x20\x61\x20\163\164\141\164\x65\x20\164\x68\x61\164\x20\164\x68\x65\40\165\160\147\x72\x61\144\145\40\163\x63\162\151\x70\x74\163\40\143\x61\x6e\x20\x6e\x6f\164\40\x61\x75\x74\157\x6d\141\164\x69\x63\x61\x6c\x6c\171\40" . "\x6d\141\156\x61\x67\145\56", $apply_only, $ref_key)); if (!phutil_console_confirm(pht("\x41\160\160\x6c\x79\40\160\x61\164\143\150\40\x61\x67\141\x69\x6e\77"))) { echo pht("\103\141\x6e\x63\x65\154\154\x65\x64\56") . "\xa"; return 1; } } unset($applied[$apply_only]); } } $applied_map[$ref_key] = $applied; } if ($apply_only) { $patches = array_select_keys($patches, array($apply_only)); } $duration_map = array(); foreach ($patches as $key => $patch) { if ($patch->getIsGlobalPatch()) { foreach ($applied_map as $ref_key => $applied) { if (isset($applied[$key])) { $duration_map[$key] = 1; } } } } while (true) { $applied_something = false; foreach ($patches as $key => $patch) { $need_patch = array(); foreach ($applied_map as $ref_key => $applied) { if (isset($applied[$key])) { continue; } $need_patch[] = $ref_key; } if (!$need_patch) { unset($patches[$key]); continue; } $missing_patch = null; foreach ($patch->getAfter() as $after) { foreach ($applied_map as $ref_key => $applied) { if (isset($applied[$after])) { continue; } $missing_patch = $after; break 2; } } if ($missing_patch) { if ($apply_only) { echo tsprintf("\x25\163\12", pht("\x55\x6e\x61\142\x6c\145\40\x74\157\40\141\160\160\154\171\x20\x70\141\x74\143\150\x20\42\45\163\42\x20\142\145\143\x61\165\163\145\x20\x69\164\x20\x64\x65\160\x65\x6e\x64\163\40\157\156\40\x70\x61\164\143\x68\40" . "\42\x25\x73\x22\54\40\167\150\x69\143\150\x20\x68\x61\x73\40\156\x6f\164\x20\142\145\x65\156\40\x61\160\x70\154\x69\x65\144\40\x6f\156\x20\x73\157\x6d\x65\40\150\x6f\x73\x74\163\72\40\x25\x73\x2e", $apply_only, $missing_patch, implode("\x2c\40", $need_patch))); return 1; } else { continue; } } $is_global = $patch->getIsGlobalPatch(); $patch_apis = array_select_keys($api_map, $need_patch); foreach ($patch_apis as $ref_key => $api) { if ($is_global) { $duration = idx($duration_map, $key); } else { $duration = null; } if ($duration === null) { if ($is_dryrun) { echo tsprintf("\x25\163\12", pht("\x44\x52\x59\122\125\x4e\x3a\40\x57\x6f\165\154\144\x20\x61\x70\160\x6c\x79\x20\x70\141\164\143\x68\40\42\45\163\42\40\164\x6f\x20\150\157\163\x74\x20\x22\45\x73\42\56", $key, $ref_key)); } else { echo tsprintf("\x25\163\xa", pht("\x41\160\160\154\x79\x69\x6e\147\x20\160\141\164\143\150\40\x22\45\x73\42\x20\164\157\x20\x68\157\x73\x74\x20\42\45\x73\42\56\56\x2e", $key, $ref_key)); } $t_begin = microtime(true); if (!$is_dryrun) { $api->applyPatch($patch); } $t_end = microtime(true); $duration = $t_end - $t_begin; $duration_map[$key] = $duration; } if (!isset($state_map[$ref_key][$key])) { if (!$is_dryrun) { $api->markPatchApplied($key, $t_end - $t_begin); } $applied_map[$ref_key][$key] = true; } } unset($patches[$key]); $applied_something = true; } if (!$applied_something) { if ($patches) { throw new Exception(pht("\x53\157\155\x65\x20\160\141\x74\x63\x68\x65\163\40\x63\157\165\154\144\x20\x6e\x6f\x74\x20\x62\x65\x20\141\x70\160\x6c\x69\145\144\x3a\x20\45\x73", implode("\x2c\x20", array_keys($patches)))); } else { if (!$is_dryrun && !$apply_only) { echo pht("\x53\164\157\162\141\x67\x65\x20\x69\163\x20\x75\x70\x20\x74\x6f\40\144\x61\164\145\56\40\125\163\x65\x20\42\x25\x73\42\40\146\157\162\x20\x64\x65\x74\141\x69\x6c\163\56", "\x73\164\x6f\162\x61\147\x65\40\x73\164\x61\164\165\x73") . "\xa"; } } break; } } } protected final function getBareHostAndPort($host) { $uri = new PhutilURI("\155\x79\163\x71\154\72\x2f\x2f" . $host); if ($uri->getPort()) { $port = $uri->getPort(); $bare_hostname = $uri->getDomain(); } else { $port = null; $bare_hostname = $host; } return array($bare_hostname, $port); } protected final function lock(PhabricatorStorageManagementAPI $api) { $parameters = array("\x72\x65\146\113\x65\171" => $api->getRef()->getRefKey()); return PhabricatorGlobalLock::newLock("\141\144\x6a\x75\x73\164", $parameters)->setExternalConnection($api->getConn(null))->setDisableLogging(true)->lock(); } protected final function analyzeTables(PhabricatorStorageManagementAPI $api) { $conn = $api->getConn(null); $patches = $this->getPatches(); $databases = $api->getDatabaseList($patches, true); $this->logInfo(pht("\101\116\101\114\131\x5a\x45"), pht("\101\156\141\x6c\171\x7a\151\x6e\147\40\x74\141\142\154\145\x73\x2e\56\56")); $targets = array(); foreach ($databases as $database) { queryfx($conn, "\x55\x53\x45\40\x25\103", $database); $tables = queryfx_all($conn, "\x53\110\117\x57\40\x54\101\x42\x4c\105\40\x53\x54\x41\x54\x55\123"); foreach ($tables as $table) { $table_name = $table["\116\141\x6d\145"]; $targets[] = array("\x64\x61\x74\141\142\141\x73\x65" => $database, "\x74\141\142\x6c\x65" => $table_name); } } $bar = id(new PhutilConsoleProgressBar())->setTotal(count($targets)); foreach ($targets as $target) { queryfx($conn, "\101\116\x41\114\131\132\105\x20\124\x41\102\114\x45\x20\45\x54\x2e\45\124", $target["\x64\141\164\x61\142\141\163\x65"], $target["\x74\x61\142\x6c\x65"]); $bar->update(1); } $bar->done(); $this->logOkay(pht("\x41\x4e\x41\x4c\x59\132\105\x44"), pht("\101\x6e\141\x6c\171\172\145\144\x20\x25\x64\x20\x74\x61\142\x6c\x65\x28\x73\51\x2e", count($targets))); } }
Function Calls
None |
Stats
MD5 | d3f6b075b33a81ee6487d100d0be0cf3 |
Eval Count | 0 |
Decode Time | 125 ms |