PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/db-migrate-stage2.drush.php

https://github.com/mrsinguyen/drupalorg-git
PHP | 210 lines | 133 code | 27 blank | 50 comment | 29 complexity | 1eb8febf8538c5c8ec15bd7295b637f1 MD5 | raw file
  1. <?php
  2. /**
  3. * @file
  4. * Perform the second stage of nuts-and-bolts db migration on the d.o db. This
  5. * includes:
  6. *
  7. * - Enqueuing jobs to re-init repositories with proper hook directories and
  8. * set correct descriptions for gitweb
  9. * - Updating release node tags
  10. *
  11. * This file expects to be executed in a bootstrapped environment, presumably
  12. * via `drush php-script`.
  13. */
  14. // Load shared functions.
  15. require_once dirname(__FILE__) . '/shared.php';
  16. if (!file_exists(dirname(__FILE__) . '/empties')) {
  17. git_log('Empties file with empty repo data could not be found, aborting to preserve idempotence.', 'WARN');
  18. exit(1);
  19. }
  20. // Get the info on empty repos and store it in a useful way
  21. $empties_raw = file(dirname(__FILE__) . '/empties');
  22. $empties = array();
  23. foreach ($empties_raw as $empty) {
  24. $item = explode(',', trim($empty));
  25. $empties[(int) $item[1]] = $item[0];
  26. }
  27. unset($empties_raw);
  28. // Kill release nodes associated with projects that have repos we know to be empty.
  29. db_delete('project_release_nodes')
  30. ->condition('pid', array_keys($empties))
  31. // ->condition('tag', 'HEAD'),
  32. ->execute();
  33. // Do release node conversion. Yuck.
  34. global $rename_patterns;
  35. // Unpublish all release nodes that are associated with unpublished projects
  36. $result = db_query('select prn.nid from project_release_nodes prn inner join node np on prn.pid = np.nid INNER JOIN node npr on prn.nid = npr.nid where np.status = 0 and npr.status = 1');
  37. $unpublish = array();
  38. while ($row = db_fetch_object($result)) {
  39. $unpublish[] = $row->nid;
  40. }
  41. if (!empty($unpublish)) {
  42. db_update('node')
  43. ->fields(array('status' => 0))
  44. ->condition('nid', $unpublish)
  45. ->execute();
  46. }
  47. // Get the repomgr queue up and ready
  48. drupal_queue_include();
  49. $queue = DrupalQueue::get('versioncontrol_repomgr');
  50. // Retrieve list of nids for which we cannot safely do master renames
  51. $result = db_query("SELECT prn.nid
  52. FROM {project_release_nodes} AS prn
  53. INNER JOIN {versioncontrol_project_projects} AS vpp ON vpp.nid = prn.pid
  54. INNER JOIN {versioncontrol_labels} AS vl ON vpp.repo_id = vl.repo_id AND SUBSTRING_INDEX(prn.version, '-dev', 1) = vl.name
  55. WHERE prn.tag = 'HEAD' and prn.version != 'HEAD'");
  56. $no_master_transform = array();
  57. while ($row = db_fetch_object($result)) {
  58. $no_master_transform[] = $row->nid;
  59. }
  60. $result = db_query('SELECT p.nid, vp.repo_id FROM {project_projects} AS p INNER JOIN {versioncontrol_project_projects} AS vp ON p.nid = vp.nid');
  61. // Ensure no stale data.
  62. db_query('TRUNCATE TABLE {versioncontrol_release_labels}');
  63. $missingtags = new SplFileObject(dirname(__FILE__) . '/missingtags', 'w+');
  64. $missingbranches = new SplFileObject(dirname(__FILE__) . '/missingbranches', 'w+');
  65. while ($row = db_fetch_object($result)) {
  66. $repos = versioncontrol_repository_load_multiple(array($row->repo_id), array(), array('may cache' => FALSE));
  67. $repo = reset($repos);
  68. $query = 'SELECT prn.pid, prn.nid, prn.version, prn.tag, prn.version_extra, COALESCE(ct.branch, prn.rebuild) as branch, n.status, p.uri
  69. FROM {project_release_nodes} AS prn
  70. INNER JOIN {project_projects} AS p ON prn.pid = p.nid
  71. INNER JOIN {node} AS n ON prn.nid = n.nid
  72. LEFT JOIN {cvs_tags} AS ct ON prn.pid = ct.nid AND prn.tag = ct.tag
  73. WHERE prn.pid = %d';
  74. $release_query = db_query($query, $row->nid);
  75. $insert = db_insert('versioncontrol_release_labels')
  76. ->fields(array('release_nid', 'label_id', 'project_nid'));
  77. while ($release_data = db_fetch_object($release_query)) {
  78. unset($label, $transformed);
  79. $vars = array(
  80. '%nid' => $release_data->nid,
  81. '%label' => $release_data->tag,
  82. '%version' => $release_data->version,
  83. );
  84. $msg = "Processing release node %nid, tied to label %label and given release version %version";
  85. git_log(strtr($msg, $vars), 'INFO', $release_data->uri);
  86. $patterns = $row->nid == 3060 ? $rename_patterns['core'] : $rename_patterns['contrib'];
  87. if ($release_data->branch == 1 || $release_data->tag == 'HEAD') { // HEAD doesn't get an entry in {cvs_tags} as a branch.
  88. /*
  89. * Special-case HEAD. There are ~3275 release nodes pointing to HEAD.
  90. *
  91. * There are three ways we handle releases tied to HEAD:
  92. *
  93. * 1. When the release version is also HEAD, we just transform both to
  94. * master and call it done. There are ~820 release nodes like this which
  95. * are basically all defunct, as the HEAD/HEAD pattern hasn't been
  96. * allowed for years.
  97. *
  98. * 2. When the release version is something other than HEAD, we derive the
  99. * appropriate branch name from that version string, rename the branch
  100. * accordingly in git and update the release node - iff a branch does
  101. * not already exist with that name. There are ~2000 release nodes
  102. * without a conflict that get this rename. <<<< SKIPPING THIS AT LAUNCH
  103. *
  104. * 3. If there IS a conflict discovered in the logic in #2, we just leave
  105. * the release node & git branch as-is, and leave it up to the
  106. * maintainer to resolve the problem on their own.
  107. */
  108. if ($release_data->tag == 'HEAD') {
  109. // Case 1 first, do a straight transform
  110. if ($release_data->version == 'HEAD') {
  111. git_log('TYPE 1 handling for master branch (master/master).' . " (prn.nid = {$release_data->nid})", 'INFO', $release_data->uri);
  112. $release_data->version = 'master';
  113. $transformed = 'master';
  114. }
  115. // Conflicting branch name, so just change HEAD -> master in the tag
  116. else {
  117. git_log(strtr('TYPE 3 handling for master branch (%mapto branch already exists).' . " (prn.nid = {$release_data->nid})", array('%mapto' => substr($release_data->version, 0, -4))), 'INFO', $release_data->uri);
  118. $transformed = 'master';
  119. }
  120. }
  121. else {
  122. // The strtolower is probably redundant now, but oh well
  123. $transformed = strtolower(preg_replace(array_keys($patterns['branches']), array_values($patterns['branches']), $release_data->tag));
  124. }
  125. git_log("Transformed CVS branch '$release_data->tag' into git branch '$transformed'" . " (prn.nid = {$release_data->nid})", 'INFO', $repo->name);
  126. // Don't reload the label if we already have it (if we did a HEAD/master transform)
  127. if (empty($label)) {
  128. $labels = $repo->loadBranches(array(), array('name' => $transformed), array('may cache' => FALSE));
  129. $label = reset($labels);
  130. }
  131. }
  132. else {
  133. if (!preg_match($patterns['tagmatch'], $release_data->tag)) {
  134. // Take the literal value, as passing it through a transform will strip
  135. // the ^DRUPAL- out and cause erroneous errors.
  136. $transformed = $release_data->tag;
  137. if (!empty($release_data->status)) {
  138. git_log("Release tag '$release_data->tag' did not match the acceptable tag pattern." . " (prn.nid = {$release_data->nid})", 'QUIET', $repo->name);
  139. git_log("Loaded release data from non-conforming tag '$release_data->tag':\n" . print_r($release_data, TRUE), 'DEBUG', $repo->name);
  140. }
  141. else {
  142. git_log("Unpublished release tag '$release_data->tag' did not match the acceptable tag pattern. Annoying, but not critical." . " (prn.nid = {$release_data->nid})", 'NORMAL', $repo->name);
  143. }
  144. }
  145. else {
  146. $transformed = strtolower(preg_replace(array_keys($patterns['tags']), array_values($patterns['tags']), $release_data->tag));
  147. }
  148. git_log("Transformed CVS tag '$release_data->tag' into git tag '$transformed'" . " (prn.nid = {$release_data->nid})", 'INFO', $repo->name);
  149. $labels = $repo->loadTags(array(), array('name' => $transformed), array('may cache' => FALSE));
  150. $label = reset($labels);
  151. }
  152. if (empty($label) || empty($label->label_id)) {
  153. // No label could be found - big problem if the release node is published, will cause packaging errors.
  154. $vars = array(
  155. '%type' => empty($release_data->branch) ? 'tag' : 'branch',
  156. '%name' => $repo->name,
  157. '%transformed' => $transformed,
  158. );
  159. if (!empty($release_data->status)) {
  160. git_log(strtr("No %type found in repository '%name' with name '%transformed'." . " (prn.nid = {$release_data->nid})", $vars), 'WARN', $repo->name);
  161. git_log("Loaded release data corresponding to published released node with missing label:\n" . print_r($release_data, TRUE), 'DEBUG', $repo->name);
  162. $logger = empty($release_data->branch) ? $missingtags : $missingbranches;
  163. $logger->fwrite("{$release_data->nid}\n");
  164. continue;
  165. }
  166. else {
  167. git_log(strtr("No %type found in repository '%name' with name '%transformed'. However, release node is unpublished, so just really freakin annoying." . " (prn.nid = {$release_data->nid})", $vars), 'QUIET', $repo->name);
  168. continue;
  169. }
  170. }
  171. // Update project release node listings
  172. db_query("UPDATE {project_release_nodes} SET tag = '%s', version = '%s' WHERE nid = %d", array($label->name, $release_data->version, $release_data->nid));
  173. $values = array(
  174. 'release_nid' => $release_data->nid,
  175. 'label_id' => $label->label_id,
  176. 'project_nid' => $release_data->pid,
  177. );
  178. git_log("Enqueuing the following release data for insertion into {versioncontrol_release_labels}:\n" . print_r($values, TRUE), 'DEBUG', $repo->name);
  179. $insert->values($values);
  180. }
  181. // Insert data into versioncontrol_release_labels, the equivalent to cvs_tags.
  182. $insert->execute();
  183. }