PageRenderTime 40ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/scripts/sql/upgrade_schema.php

http://github.com/facebook/phabricator
PHP | 200 lines | 143 code | 32 blank | 25 comment | 19 complexity | 47fc5da2d4917cb20aaafb0eaeaddfd6 MD5 | raw file
Possible License(s): JSON, MPL-2.0-no-copyleft-exception, Apache-2.0, BSD-3-Clause, LGPL-2.0, MIT, LGPL-2.1, LGPL-3.0
  1. #!/usr/bin/env php
  2. <?php
  3. /*
  4. * Copyright 2011 Facebook, Inc.
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. $root = dirname(dirname(dirname(__FILE__)));
  19. require_once $root.'/scripts/__init_script__.php';
  20. phutil_require_module('phutil', 'console');
  21. phutil_require_module('phabricator', 'infrastructure/setup/sql');
  22. define('SCHEMA_VERSION_TABLE_NAME', 'schema_version');
  23. // TODO: getopt() is super terrible, move to something less terrible.
  24. $options = getopt('fhv:u:p:') + array(
  25. 'v' => null, // Upgrade from specific version
  26. 'u' => null, // Override MySQL User
  27. 'p' => null, // Override MySQL Pass
  28. );
  29. foreach (array('h', 'f') as $key) {
  30. // By default, these keys are set to 'false' to indicate that the flag was
  31. // passed.
  32. if (array_key_exists($key, $options)) {
  33. $options[$key] = true;
  34. }
  35. }
  36. if (!empty($options['h']) || ($options['v'] && !is_numeric($options['v']))) {
  37. usage();
  38. }
  39. if (empty($options['f'])) {
  40. echo phutil_console_wrap(
  41. "Before running this script, you should take down the Phabricator web ".
  42. "interface and stop any running Phabricator daemons.");
  43. if (!phutil_console_confirm('Are you ready to continue?')) {
  44. echo "Cancelled.\n";
  45. exit(1);
  46. }
  47. }
  48. // Use always the version from the commandline if it is defined
  49. $next_version = isset($options['v']) ? (int)$options['v'] : null;
  50. $conf = DatabaseConfigurationProvider::getConfiguration();
  51. if ($options['u']) {
  52. $conn_user = $options['u'];
  53. $conn_pass = $options['p'];
  54. } else {
  55. $conn_user = $conf->getUser();
  56. $conn_pass = $conf->getPassword();
  57. }
  58. $conn_host = $conf->getHost();
  59. // Split out port information, since the command-line client requires a
  60. // separate flag for the port.
  61. $uri = new PhutilURI('mysql://'.$conn_host);
  62. if ($uri->getPort()) {
  63. $conn_port = $uri->getPort();
  64. $conn_bare_hostname = $uri->getDomain();
  65. } else {
  66. $conn_port = null;
  67. $conn_bare_hostname = $conn_host;
  68. }
  69. $conn = new AphrontMySQLDatabaseConnection(
  70. array(
  71. 'user' => $conn_user,
  72. 'pass' => $conn_pass,
  73. 'host' => $conn_host,
  74. 'database' => null,
  75. ));
  76. try {
  77. $create_sql = <<<END
  78. CREATE DATABASE IF NOT EXISTS `phabricator_meta_data`;
  79. END;
  80. queryfx($conn, $create_sql);
  81. $create_sql = <<<END
  82. CREATE TABLE IF NOT EXISTS phabricator_meta_data.`schema_version` (
  83. `version` INTEGER not null
  84. );
  85. END;
  86. queryfx($conn, $create_sql);
  87. // Get the version only if commandline argument wasn't given
  88. if ($next_version === null) {
  89. $version = queryfx_one(
  90. $conn,
  91. 'SELECT * FROM phabricator_meta_data.%T',
  92. SCHEMA_VERSION_TABLE_NAME);
  93. if (!$version) {
  94. print "*** No version information in the database ***\n";
  95. print "*** Give the first patch version which to ***\n";
  96. print "*** apply as the command line argument ***\n";
  97. exit(-1);
  98. }
  99. $next_version = $version['version'] + 1;
  100. }
  101. $patches = PhabricatorSQLPatchList::getPatchList();
  102. $patch_applied = false;
  103. foreach ($patches as $patch) {
  104. if ($patch['version'] < $next_version) {
  105. continue;
  106. }
  107. $short_name = basename($patch['path']);
  108. print "Applying patch {$short_name}...\n";
  109. if ($conn_port) {
  110. $port = '--port='.(int)$conn_port;
  111. } else {
  112. $port = null;
  113. }
  114. if (preg_match('/\.php$/', $patch['path'])) {
  115. $schema_conn = $conn;
  116. require_once $patch['path'];
  117. } else {
  118. list($stdout, $stderr) = execx(
  119. "mysql --user=%s --password=%s --host=%s {$port} < %s",
  120. $conn_user,
  121. $conn_pass,
  122. $conn_bare_hostname,
  123. $patch['path']);
  124. if ($stderr) {
  125. print $stderr;
  126. exit(-1);
  127. }
  128. }
  129. // Patch was successful, update the db with the latest applied patch version
  130. // 'DELETE' and 'INSERT' instead of update, because the table might be empty
  131. queryfx(
  132. $conn,
  133. 'DELETE FROM phabricator_meta_data.%T',
  134. SCHEMA_VERSION_TABLE_NAME);
  135. queryfx(
  136. $conn,
  137. 'INSERT INTO phabricator_meta_data.%T VALUES (%d)',
  138. SCHEMA_VERSION_TABLE_NAME,
  139. $patch['version']);
  140. $patch_applied = true;
  141. }
  142. if (!$patch_applied) {
  143. print "Your database is already up-to-date.\n";
  144. }
  145. } catch (AphrontQueryAccessDeniedException $ex) {
  146. echo
  147. "ACCESS DENIED\n".
  148. "The user '{$conn_user}' does not have sufficient MySQL privileges to\n".
  149. "execute the schema upgrade. Use the -u and -p flags to run as a user\n".
  150. "with more privileges (e.g., root).".
  151. "\n\n".
  152. "EXCEPTION:\n".
  153. $ex->getMessage().
  154. "\n\n";
  155. exit(1);
  156. }
  157. function usage() {
  158. echo
  159. "usage: upgrade_schema.php [-v version] [-u user -p pass] [-f] [-h]".
  160. "\n\n".
  161. "Run 'upgrade_schema.php -u root -p hunter2' to override the configured ".
  162. "default user.\n".
  163. "Run 'upgrade_schema.php -v 12' to apply all patches starting from ".
  164. "version 12. It is very unlikely you need to do this.\n".
  165. "Use the -f flag to upgrade noninteractively, without prompting.\n".
  166. "Use the -h flag to show this help.\n";
  167. exit(1);
  168. }