PageRenderTime 42ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/db-migrate-stage1.drush.php

https://github.com/mrsinguyen/drupalorg-git
PHP | 404 lines | 308 code | 50 blank | 46 comment | 14 complexity | d836d067a2fb2f2e7d5d5a07e5080cba MD5 | raw file
  1. <?php
  2. /**
  3. * @file
  4. * Perform the nuts-and-bolts db updates for the migration from CVS to git.
  5. *
  6. * This file expects to be executed in a bootstrapped environment, presumably
  7. * via `drush php-script`.
  8. */
  9. // Load shared functions.
  10. require_once dirname(__FILE__) . '/shared.php';
  11. if (!file_exists(dirname(__FILE__) . '/empties')) {
  12. git_log('Empties file with empty repo data could not be found, aborting to preserve idempotence.', 'WARN');
  13. exit(1);
  14. }
  15. $result = db_query('SELECT p.nid, p.uri, c.directory, n.status FROM {project_projects} AS p INNER JOIN {cvs_projects} AS c ON p.nid = c.nid INNER JOIN {node} AS n ON p.nid = n.nid');
  16. $projects = array();
  17. while ($row = db_fetch_object($result)) {
  18. $projects[] = $row;
  19. }
  20. // Get the repomgr queue up and ready
  21. drupal_queue_include();
  22. $queue = DrupalQueue::get('versioncontrol_repomgr');
  23. // ensure the plugin is loaded
  24. ctools_include('plugins');
  25. ctools_plugin_load_class('versioncontrol', 'vcs_auth', 'account', 'handler');
  26. $gitbackend = versioncontrol_get_backends('git');
  27. // Get the info on empty repos and store it in a useful way
  28. $empties_raw = file(dirname(__FILE__) . '/empties');
  29. $empties = array();
  30. foreach ($empties_raw as $empty) {
  31. $item = explode(',', trim($empty));
  32. $empties[(int) $item[1]] = $item[0];
  33. }
  34. unset($empties_raw);
  35. $auth_data = array(
  36. 'access' => VersioncontrolAuthHandlerMappedAccounts::ALL,
  37. 'branch_create' => VersioncontrolAuthHandlerMappedAccounts::DENY,
  38. 'branch_update' => VersioncontrolAuthHandlerMappedAccounts::DENY,
  39. 'branch_delete' => VersioncontrolAuthHandlerMappedAccounts::DENY,
  40. 'tag_create' => VersioncontrolAuthHandlerMappedAccounts::DENY,
  41. 'tag_update' => VersioncontrolAuthHandlerMappedAccounts::DENY,
  42. 'tag_delete' => VersioncontrolAuthHandlerMappedAccounts::DENY,
  43. 'per-label' => array()
  44. );
  45. // ensure vc_project's table is empty for a nice, clean insert
  46. db_delete('versioncontrol_project_projects')->execute();
  47. // A set of repos to assemble via cloning instead
  48. $cloners = array(
  49. 851266 => 'git://github.com/sdboyer/drupalorg-git.git', // tggm, woot!
  50. );
  51. $git_basedir = variable_get('drupalorg_git_basedir', '/var/git');
  52. $templatedir = "$git_basedir/templates/built/project";
  53. $repos = array();
  54. foreach ($projects as $project) {
  55. if (empty($project->nid)) {
  56. git_log('Project has no nid. This should NOT happen.', 'WARN', $project->uri);
  57. continue;
  58. }
  59. if (!is_dir('/var/git/repositories/project/' . $project->uri . '.git') && empty($empties[$project->nid]) && empty($cloners[$project->nid])) {
  60. git_log(strtr('Project has a CVS path listed, but no code was migrated into a git repository at the expected target location, !location.', array('!project' => $project->uri, '!location' => 'project/' . $project->uri . '.git')), 'WARN', $project->uri);
  61. continue;
  62. }
  63. git_log('Building a VersioncontrolGitRepository object for the project.', 'INFO', $project->uri);
  64. $data = array(
  65. 'name' => $project->uri,
  66. 'root' => '/var/git/repositories/project/' . $project->uri . '.git',
  67. 'plugins' => array(
  68. 'auth_handler' => 'account', // We can't rely on the $conf default for this b/c vc_project doesn't respect it
  69. ),
  70. 'vcs' => 'git',
  71. 'project_nid' => $project->nid,
  72. 'update_method' => 1,
  73. );
  74. // Build the repo object
  75. $repo = $gitbackend->buildEntity('repo', $data);
  76. // Save it, b/c doing it in the job could cause db deadlocks. Yay fast beanstalk!
  77. // Also ensure the versioncontrol_project_projects association is up to date
  78. $repo->save();
  79. db_merge('versioncontrol_project_projects')
  80. ->key(array('nid' => $repo->project_nid))
  81. ->fields(array('repo_id' => $repo->repo_id))
  82. ->execute();
  83. // Fetch all the maintainer data.
  84. $maintainers_result = db_select('cvs_project_maintainers', 'c')
  85. ->fields('c', array('uid'))
  86. ->condition('c.nid', $project->nid)
  87. ->execute();
  88. if (isset($cloners[$project->nid])) {
  89. $tgt_dir = "$git_basedir/repositories/project/$project->uri.git";
  90. $job = array(
  91. 'repository' => $repo,
  92. 'operation' => array(
  93. 'passthru' => array(
  94. "clone --branch launch --bare --template $templatedir {$cloners[$project->nid]} $tgt_dir",
  95. ),
  96. ),
  97. );
  98. }
  99. else if (isset($empties[$project->nid])) {
  100. // This is one of our projects missing a repo. Build a good init payload.
  101. $job = array(
  102. 'repository' => $repo,
  103. 'operation' => array(
  104. // Create the repo on disk, and attach all the right hooks.
  105. 'create' => array(),
  106. ),
  107. );
  108. }
  109. else {
  110. // The more typical case, where the repo was already created by cvs2git
  111. $job = array(
  112. 'repository' => $repo,
  113. 'operation' => array(
  114. // We need to properly init the hooks now and the config file, after the
  115. // translation & keyword stripping commits have been pushed in.
  116. 'reInit' => array(array('hooks', 'config')),
  117. ),
  118. );
  119. }
  120. // Add shared job ops.
  121. // Save user auth data.
  122. $job['operation']['setUserAuthData'] = array($maintainers_result->fetchAll(PDO::FETCH_COLUMN), $auth_data);
  123. // Set the description with a link to the project page
  124. $job['operation']['setDescription'] = array('For more information about this repository, visit the project page at ' . url('node/' . $repo->project_nid, array('absolute' => TRUE)));
  125. // Now handle special-case exceptions, typically filter-branches.
  126. switch ($project->nid) {
  127. // ubercart_marketplace
  128. case 277418:
  129. $job['operation']['passthru'] = array("filter-branch -f --prune-empty --tree-filter " . escapeshellarg("rm -rf mp_tokens") . " -- --all", TRUE);
  130. break;
  131. // adaptive_context
  132. case 176635:
  133. $job['operation']['passthru'] = array("filter-branch -f --prune-empty --tree-filter " . escapeshellarg("rm -rf ac_access ac_group jqselect") . " -- --all", TRUE);
  134. break;
  135. // ecommerce
  136. case 5841:
  137. $job['operation']['passthru'] = array("filter-branch -f --prune-empty --tree-filter " . escapeshellarg("rm -rf contrib/inventorymangement contrib/worldpay") . " -- --all", TRUE);
  138. break;
  139. // user_board
  140. case 471518:
  141. $job['operation']['passthru'] = array("filter-branch -f --prune-empty --tree-filter " . escapeshellarg("rm -rf user_board_activity user_board_userpoints user_board_views") . " -- --all", TRUE);
  142. break;
  143. // idthemes cluster of bullshit
  144. case 525938:
  145. $job['operation']['passthru'] = array("filter-branch -f --prune-empty --tree-filter " . escapeshellarg("rm -rf idt001 idt002 idt011 idt012") . " -- --all", TRUE);
  146. break;
  147. case 525904:
  148. case 525938:
  149. case 526216:
  150. case 526532:
  151. $job['operation']['passthru'] = array("filter-branch -f --prune-empty --tree-filter " . escapeshellarg("rm -rf branches") . " -- --all", TRUE);
  152. break;
  153. }
  154. git_log("Enqueuing repomgr job with the following payload:\n" . print_r($job['operation'], TRUE), 'DEBUG', $project->uri);
  155. if ($queue->createItem($job)) {
  156. git_log("Successfully enqueued repository initialization job.", 'INFO', $repo->name);
  157. }
  158. else {
  159. git_log("Failed to enqueue repository initialization job.", 'WARN', $repo->name);
  160. }
  161. }
  162. // Mark all project nodes as needing to be re-indexed in Solr.
  163. apachesolr_mark_node_type('project_project');
  164. // ------------------
  165. // Perform role & perm-related migration steps.
  166. $git_admin_rid = DRUPALORG_GIT_GATEWAY_ADMIN_RID;
  167. $git_vetted_rid = DRUPALORG_GIT_GATEWAY_VETTED_RID;
  168. $git_user_rid = DRUPALORG_GIT_GATEWAY_RID;
  169. $admin_rid = 3;
  170. $user_admin_rid = 7;
  171. // First do the new git perms.
  172. db_query('DELETE FROM {permission} WHERE rid IN (%d, %d, %d)', array($git_admin_rid, $git_vetted_rid, $git_user_rid));
  173. db_query('DELETE FROM {users_roles} WHERE rid IN (%d, %d, %d) AND uid NOT IN (%d, %d, %d)', array($git_admin_rid, $git_vetted_rid, $git_user_rid, 1118416, 1118412, 1123222));
  174. $perm_insert = db_insert('permission')->fields(array('rid', 'perm', 'tid'));
  175. $git_perms = array(
  176. $git_user_rid => array(
  177. 'opt-in or out of tracking', 'create images', 'edit own images', 'pift re-test files',
  178. 'use version control systems', 'create sandbox projects',
  179. ),
  180. $git_vetted_rid => array(
  181. 'create full projects',
  182. ),
  183. $git_admin_rid => array(
  184. 'access site-wide contact form', 'opt-in or out of tracking',
  185. 'administer projects', 'access administration pages', 'access site reports',
  186. 'administer version control systems', 'create full projects',
  187. ),
  188. );
  189. $perm = db_result(db_query('SELECT perm FROM {permission} WHERE rid = 2'));
  190. $perm = explode(', ', $perm);
  191. // For some reason, auth users are getting the 'create full projects' permission. Crazy. Make sure they don't.
  192. if ($idx = array_search('create full projects', $perm)) {
  193. unset($perm[$idx]);
  194. db_query("UPDATE {permission} SET perm = '%s' WHERE rid = 2", implode(', ', $perm));
  195. }
  196. foreach ($git_perms as $rid => $perms) {
  197. $perm_insert->values(array(
  198. 'rid' => $rid,
  199. 'perm' => implode(', ', $perms),
  200. 'tid' => 0,
  201. ));
  202. }
  203. $perm_insert->execute();
  204. // Now update existing roles' perms as needed.
  205. $other_perms = array(
  206. 1 => ', access commit messages',
  207. 2 => ', manage own SSH public keys, view own SSH public keys, access commit messages',
  208. $admin_rid => ', administer SSH public keys, manage any SSH public keys, view any SSH public keys, administer version control systems',
  209. $user_admin_rid => ', manage any SSH public keys, view any SSH public keys',
  210. );
  211. foreach ($other_perms as $rid => $perms) {
  212. db_query("UPDATE {permission} SET perm = CONCAT(perm, '%s') WHERE rid = %d", array($perms, $rid));
  213. }
  214. // Now translate exisitng users' perms, as appropriate.
  215. // Give all current CVS users the 'Git vetted user' role. Unfortunately, the 'CVS users' role is unreliable.
  216. db_query("DELETE FROM {users_roles} WHERE rid = 8", $git_vetted_rid);
  217. db_query('INSERT INTO {users_roles} (uid, rid) SELECT uid, %d FROM cvs_accounts WHERE status = 1 ON DUPLICATE KEY UPDATE rid=rid', DRUPALORG_GIT_GATEWAY_VETTED_RID);
  218. db_query('UPDATE {users} SET git_vetted = 1 WHERE uid IN ((SELECT uid FROM {cvs_accounts} WHERE status = 1))');
  219. // Turn CVS administrators into Git administrators.
  220. db_query("UPDATE {users_roles} SET rid = %d WHERE rid = 6", $git_admin_rid);
  221. // Get rid of the old CVS roles.
  222. db_query('DELETE FROM {role} WHERE rid IN (6, 8)');
  223. db_query('DELETE FROM {permission} WHERE rid IN (6, 8)');
  224. // ------------------
  225. /* Transfer CVS usernames over to the new Git username system. */
  226. // Grab all cvs account names from existing approved account list.
  227. $result = db_select('cvs_accounts', 'ca')->fields('ca', array('uid', 'cvs_user'))
  228. ->condition('status', 1)
  229. ->distinct()
  230. ->execute();
  231. // Handle requested alternate usernames from users.
  232. $exceptions = array(
  233. 62496 => 'mikey_p',
  234. 926382 => 'JoshTheGeek',
  235. 920 => 'betarobot',
  236. 384214 => 'nschloe',
  237. // 35369 => 'svendecabooter',
  238. 16327 => 'instanceofjamie',
  239. 80656 => 'nunoveloso',
  240. 32793 => 'mo6',
  241. 250828 => 'john.karahalis',
  242. 123980 => 'bradweikel',
  243. 25564 => 'twom',
  244. 270434 => 'babbage',
  245. 4299 => 'reyero',
  246. 47085 => 'lourdas_v',
  247. 241634 => 'tim.plunkett',
  248. 26398 => 'Crell',
  249. 24950 => 'bensheldon',
  250. 22079 => 'hunmonk',
  251. 8026 => 'mikehostetler',
  252. 11289 => 'joshuajabbour',
  253. 47135 => 'alonpeer',
  254. 12363 => 'jbrauer',
  255. 20975 => 'agentrickard',
  256. 195353 => 'bensnyder',
  257. 383424 => 'mr.baileys',
  258. 61601 => 'elliotttf',
  259. 22773 => 'chadcf',
  260. 358731 => 'wiifm',
  261. 193303 => 'lelizondo',
  262. 125384 => 'nhck',
  263. 219482 => 'beautifulmind',
  264. 88931 => 'Jacine',
  265. 186696 => 'ademarco',
  266. 322673 => 'baloo',
  267. 207484 => 'mmartinov',
  268. 183956 => 'tobiasb',
  269. 188571 => 'greghines',
  270. 186334 => 'justin',
  271. 6521 => 'benshell',
  272. 163737 => 'corey.aufang',
  273. 143 => 'singularo',
  274. 76026 => 'grobot',
  275. 571032 => 'arshad',
  276. 692532 => 'simme',
  277. 64383 => 'mlncn',
  278. 43205 => 'scb',
  279. 229048 => 'axel.rutz',
  280. 43568 => 'Ralf',
  281. 73919 => 'Magnus',
  282. 690640 => 'danpros',
  283. 216107 => 'alexjarvis',
  284. 54135 => 'levelos',
  285. 68905 => 'mhrabovcin',
  286. 100783 => 'adamdicarlo',
  287. 194674 => 'vinoth.3v',
  288. 123779 => 'macedigital',
  289. 103299 => 'DirkR',
  290. 203750 => 'abraham',
  291. 14475 => 'nsyll',
  292. 384578 => 'aaronbauman',
  293. 130383 => 'greg.harvey',
  294. 240860 => 'tedbow',
  295. 99872 => 'rich.yumul',
  296. 211387 => 'kylebrowning',
  297. 373605 => 'mundanity',
  298. 38806 => 'hadifarnoud',
  299. 185768 => 'aaronfulton',
  300. 221033 => 'jdelaune',
  301. 165089 => 'bob.hinrichs',
  302. 45449 => 'chulkilee',
  303. 132410 => 'tnanek',
  304. 62965 => 'Xano',
  305. 766132 => 'aaronlevy',
  306. 86970 => 'ivan.zugec',
  307. 398572 => 'Chia',
  308. 48898 => 'smk-ka',
  309. 46153 => 'yoran',
  310. 324696 => 'JayMatwichuk',
  311. 509892 => 'jm.federico',
  312. 80902 => 'jdleonard',
  313. 222669 => 'drupal-at-imediasee',
  314. 66894 => 'stella',
  315. 386087 => 'sfreudenberg',
  316. 367108 => 'j_ayen_green',
  317. 97023 => 'CrookedNumber',
  318. 44114 => 'liquidcms',
  319. 103709 => 'nvoyageur',
  320. 76033 => 'gazwal',
  321. 37266 => 'geodaniel',
  322. 297478 => 'coderintherye',
  323. 259320 => 'darrenmothersele',
  324. 665088 => 'tsitaru',
  325. 23728 => 'Sweetchuck',
  326. 37031 => 'dropcube',
  327. 103458 => 'socki',
  328. 66163 => 'floretan',
  329. 228712 => 'skyred',
  330. 310132 => 'Doc',
  331. 226976 => 'ZenDoodles',
  332. 8791 => 'sillygwailo',
  333. 138300 => 'dnotes',
  334. 18535 => 'claudioc',
  335. 191570 => 'smartinm',
  336. 537590 => 'cignex',
  337. 39343 => 'bboyjay',
  338. 41519 => 'stevepurkiss',
  339. 56346 => 'ominds',
  340. 10297 => 'cfennell',
  341. 651550 => 'adr_p',
  342. 106373 => 'wicher',
  343. 112063 => 'frankcarey',
  344. 96826 => 'irakli',
  345. 166383 => 'chrisshattuck',
  346. 45996 => 'Vacilando',
  347. 23570 => 'Michelle',
  348. 1111464 => 'git',
  349. );
  350. foreach($result as $record) {
  351. $git_username = empty($exceptions[$record->uid]) ? $record->cvs_user : $exceptions[$record->uid];
  352. db_update('users')->fields(array('git_username' => $git_username))
  353. ->condition('uid', $record->uid)->execute();
  354. }