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