1 |
85ad3d82
|
Assos Assos
|
<?php
|
2 |
|
|
// $Id: drush_make_d_o.convert.inc,v 1.1.2.17 2010/09/09 07:11:00 dmitrig01 Exp $
|
3 |
|
|
|
4 |
|
|
class DrushMakeDrupalorgVersionChecker {
|
5 |
|
|
function latestVersion($project_name, $version) {
|
6 |
|
|
|
7 |
|
|
// Project types that are valid for the version checker.
|
8 |
|
|
$allowed_project_types = array(
|
9 |
|
|
'core',
|
10 |
|
|
'module',
|
11 |
|
|
'theme',
|
12 |
|
|
);
|
13 |
|
|
|
14 |
|
|
$project = array(
|
15 |
|
|
'name' => $project_name,
|
16 |
|
|
'core' => $this->core,
|
17 |
|
|
'version' => $version,
|
18 |
|
|
'location' => drush_get_option('drush-make-update-default-url'),
|
19 |
|
|
);
|
20 |
|
|
$project = drush_make_updatexml($project);
|
21 |
|
|
|
22 |
|
|
// Because the version data we get back from the XML may not be the same
|
23 |
|
|
// data we passed, and because we can fail even if version data is
|
24 |
|
|
// returned, track both the success/failure of the request, and the
|
25 |
|
|
// version data.
|
26 |
|
|
|
27 |
|
|
// Check for bad projects and branch releases.
|
28 |
|
|
if (empty($project) || preg_match('/.*-dev$/', $project['version'])) {
|
29 |
|
|
// Use the passed version if no version was returned.
|
30 |
|
|
if (empty($project)) {
|
31 |
|
|
$final_version = $version;
|
32 |
|
|
}
|
33 |
|
|
else {
|
34 |
|
|
$final_version = $project['version'];
|
35 |
|
|
}
|
36 |
|
|
if ($project_name == 'drupal') {
|
37 |
|
|
drush_make_error('BUILD_ERROR', dt("Drupal core does not have an official release for version '%version' yet.", array('%version' => $final_version)));
|
38 |
|
|
}
|
39 |
|
|
else {
|
40 |
|
|
drush_make_error('BUILD_ERROR', dt("Project '%project' does not have an official release for version '%version'.", array('%project' => $project_name, '%version' => $final_version)));
|
41 |
|
|
}
|
42 |
|
|
$result = FALSE;
|
43 |
|
|
}
|
44 |
|
|
// Make sure the project is an allowed project type.
|
45 |
|
|
elseif (!in_array($project['type'], $allowed_project_types)) {
|
46 |
|
|
drush_make_error('BUILD_ERROR', dt("Project %project of type '%type' is not permitted.", array('%project' => $project_name, '%type' => $project['type'])));
|
47 |
|
|
$final_version = $project['version'];
|
48 |
|
|
$result = FALSE;
|
49 |
|
|
}
|
50 |
|
|
else {
|
51 |
|
|
$final_version = $project['version'];
|
52 |
|
|
$result = TRUE;
|
53 |
|
|
}
|
54 |
|
|
return array($result, $final_version);
|
55 |
|
|
}
|
56 |
|
|
}
|
57 |
|
|
|
58 |
|
|
class DrushMakeDrupalorgConverter extends DrushMakeDrupalorgVersionChecker {
|
59 |
|
|
function __construct($from, $to = NULL) {
|
60 |
|
|
$this->from = $from;
|
61 |
|
|
$this->to = $to;
|
62 |
|
|
$this->log = array();
|
63 |
|
|
}
|
64 |
|
|
|
65 |
|
|
function run() {
|
66 |
|
|
if ($this->read()) {
|
67 |
|
|
if ($this->convert()) {
|
68 |
|
|
$this->write();
|
69 |
|
|
}
|
70 |
|
|
}
|
71 |
|
|
}
|
72 |
|
|
|
73 |
|
|
function read() {
|
74 |
|
|
if (!($this->old_info = drush_make_parse_info_file($this->from))) {
|
75 |
|
|
drush_make_error('FILE_ERROR', dt("Unable to parse file %file", array('%file' => $this->from)));
|
76 |
|
|
return FALSE;
|
77 |
|
|
}
|
78 |
|
|
return TRUE;
|
79 |
|
|
}
|
80 |
|
|
|
81 |
|
|
function log($message, $type = 'ok') {
|
82 |
|
|
// Save the log messages so they can be put into the output for the .make
|
83 |
|
|
// file.
|
84 |
|
|
if (empty($this->to)) {
|
85 |
|
|
$this->log[] = "[$type]: \t $message";
|
86 |
|
|
}
|
87 |
|
|
// Only log to screen if we're outputting the conversion to file.
|
88 |
|
|
else {
|
89 |
|
|
drush_log($message, $type);
|
90 |
|
|
}
|
91 |
|
|
}
|
92 |
|
|
|
93 |
|
|
function convert() {
|
94 |
|
|
// Run the regular validation first. This performs basic syntax
|
95 |
|
|
// validation, and also pre-converts special syntax into a standard
|
96 |
|
|
// format. Since the info file validation doesn't return any data if
|
97 |
|
|
// validation fails, we have to bail here.
|
98 |
|
|
if (!($this->old_info = drush_make_validate_info_file($this->old_info))) {
|
99 |
|
|
return FALSE;
|
100 |
|
|
}
|
101 |
|
|
|
102 |
|
|
// The list of currently allowed top-leval attributes.
|
103 |
|
|
$top_level_attribute_whitelist = array('core', 'api', 'core_release', 'projects');
|
104 |
|
|
|
105 |
|
|
// The list of currently allowed project-level attributes.
|
106 |
|
|
$project_attribute_whitelist = array('version', 'subdir', 'patch');
|
107 |
|
|
|
108 |
|
|
// The list of currently disallowed projects.
|
109 |
|
|
$project_disallowed_list = array('drupal');
|
110 |
|
|
|
111 |
|
|
// Assume no errors to start.
|
112 |
|
|
$errors = FALSE;
|
113 |
|
|
|
114 |
|
|
// First order of business: convert core version.
|
115 |
|
|
$parts = explode('.', $this->old_info['core']);
|
116 |
|
|
$core_major = $parts[0];
|
117 |
|
|
$this->core = $core_major . '.x';
|
118 |
|
|
|
119 |
|
|
// Check for a stable release on the branch.
|
120 |
|
|
list($result, $final_version) = $this->latestVersion('drupal', $core_major);
|
121 |
|
|
if ($result) {
|
122 |
|
|
$this->new_info['core'] = $final_version;
|
123 |
|
|
$this->log(dt('Setting the Drupal core version to %version.', array('%version' => $final_version)));
|
124 |
|
|
}
|
125 |
|
|
else {
|
126 |
|
|
$errors = TRUE;
|
127 |
|
|
}
|
128 |
|
|
$this->new_info['api'] = 2;
|
129 |
|
|
|
130 |
|
|
if (isset($this->old_info['projects'])) {
|
131 |
|
|
foreach ($this->old_info['projects'] as $project => $project_data) {
|
132 |
|
|
|
133 |
|
|
// Skip conversion for disallowed projects.
|
134 |
|
|
if (in_array($project, $project_disallowed_list)) {
|
135 |
|
|
if ($project == 'drupal') {
|
136 |
|
|
$this->log(dt("It is not permitted to include Drupal core as a project in an install profile -- it has been removed"), 'warning');
|
137 |
|
|
}
|
138 |
|
|
else {
|
139 |
|
|
$this->log(dt("Removed disallowed project '%project'", array('%project' => $project)), 'warning');
|
140 |
|
|
}
|
141 |
|
|
continue;
|
142 |
|
|
}
|
143 |
|
|
|
144 |
|
|
// Clean out disallowed project attributes.
|
145 |
|
|
foreach ($project_data as $attribute => $attribute_value) {
|
146 |
|
|
if (!in_array($attribute, $project_attribute_whitelist)) {
|
147 |
|
|
$this->log(dt("The '%attribute' attribute is not allowed for the '%project' project, removing.", array('%attribute' => $attribute, '%project' => $project)), 'warning');
|
148 |
|
|
unset($project_data[$attribute]);
|
149 |
|
|
}
|
150 |
|
|
}
|
151 |
|
|
|
152 |
|
|
// Check that patches do in fact come from drupal.org.
|
153 |
|
|
if (isset($project_data['patch'])) {
|
154 |
|
|
foreach ($project_data['patch'] as $key => $patch) {
|
155 |
|
|
if (strpos($patch, 'http://drupal.org/files/issues') !== 0) {
|
156 |
|
|
$this->log(dt("The patch '%patch' is not hosted on drupal.org -- it has been removed.", array('%patch' => $patch)), 'warning');
|
157 |
|
|
unset($project_data['patches'][$key]);
|
158 |
|
|
}
|
159 |
|
|
}
|
160 |
|
|
}
|
161 |
|
|
|
162 |
|
|
// Reset the versioning variables to start fresh for every project.
|
163 |
|
|
$version = NULL;
|
164 |
|
|
$result = FALSE;
|
165 |
|
|
$final_version = '';
|
166 |
|
|
|
167 |
|
|
// Figure out the basic version string.
|
168 |
|
|
if (empty($project_data['version'])) {
|
169 |
|
|
$version = DRUSH_MAKE_VERSION_BEST;
|
170 |
|
|
}
|
171 |
|
|
elseif (preg_match('/^(\d+)((\.\d+)(-[a-z0-9]+)?)?$/', $project_data['version'], $matches)) {
|
172 |
|
|
// Branch version only.
|
173 |
|
|
if (empty($matches[2])) {
|
174 |
|
|
$version = $matches[1];
|
175 |
|
|
}
|
176 |
|
|
// Development snapshots not allowed.
|
177 |
|
|
elseif (!empty($matches[4]) && $matches[4] == '-dev') {
|
178 |
|
|
drush_make_error('BUILD_ERROR', dt("An official release is required for '%project' -- a development version cannot be used.", array('%project' => $project)));
|
179 |
|
|
$errors = TRUE;
|
180 |
|
|
// Move on, nothing more needs to be done with this project.
|
181 |
|
|
continue;
|
182 |
|
|
}
|
183 |
|
|
// All regular releases.
|
184 |
|
|
else {
|
185 |
|
|
$version = $matches[1] . $matches[2];
|
186 |
|
|
}
|
187 |
|
|
}
|
188 |
|
|
|
189 |
|
|
// Use the update XML to verify this project actually has a valid
|
190 |
|
|
// release.
|
191 |
|
|
if (isset($version)) {
|
192 |
|
|
list($result, $final_version) = $this->latestVersion($project, $version);
|
193 |
|
|
}
|
194 |
|
|
if ($result) {
|
195 |
|
|
$this->log(dt("Setting version for project '%project' to '%version'", array('%project' => $project, '%version' => $final_version)));
|
196 |
|
|
$project_data['version'] = $final_version;
|
197 |
|
|
if (array_keys($project_data) == array('version')) {
|
198 |
|
|
$project_data = $project_data['version'];
|
199 |
|
|
}
|
200 |
|
|
|
201 |
|
|
$this->new_info['projects'][$project] = $project_data;
|
202 |
|
|
}
|
203 |
|
|
else {
|
204 |
|
|
$errors = TRUE;
|
205 |
|
|
}
|
206 |
|
|
}
|
207 |
|
|
}
|
208 |
|
|
|
209 |
|
|
// Clean out disallowed top-level attributes.
|
210 |
|
|
foreach ($this->old_info as $attribute => $attribute_value) {
|
211 |
|
|
if (!in_array($attribute, $top_level_attribute_whitelist)) {
|
212 |
|
|
$this->log(dt("The '%attribute' make file attribute is not allowed, removing.", array('%attribute' => $attribute, )), 'warning');
|
213 |
|
|
}
|
214 |
|
|
}
|
215 |
|
|
|
216 |
|
|
if ($errors) {
|
217 |
|
|
return FALSE;
|
218 |
|
|
}
|
219 |
|
|
return TRUE;
|
220 |
|
|
}
|
221 |
|
|
|
222 |
|
|
function write() {
|
223 |
|
|
$output = $this->render($this->new_info);
|
224 |
|
|
// Write to stdout.
|
225 |
|
|
if (empty($this->to)) {
|
226 |
|
|
$log = '';
|
227 |
|
|
if (!empty($this->log)) {
|
228 |
|
|
$log .= dt("; Logged conversion messages follow. The final converted .make file follows these messages.\n");
|
229 |
|
|
foreach ($this->log as $message) {
|
230 |
|
|
$log .= "; $message\n";
|
231 |
|
|
}
|
232 |
|
|
}
|
233 |
|
|
print $log . $output;
|
234 |
|
|
}
|
235 |
|
|
// Write to file.
|
236 |
|
|
else {
|
237 |
|
|
if (file_put_contents($this->to, $output)) {
|
238 |
|
|
drush_log(dt("Successfully wrote converted .make file %file.", array('%file' => $this->to)), 'ok');
|
239 |
|
|
}
|
240 |
|
|
else {
|
241 |
|
|
drush_make_error('FILE_ERROR', dt("Unable to write .make file %file.", array('%file' => $this->to)));
|
242 |
|
|
}
|
243 |
|
|
}
|
244 |
|
|
}
|
245 |
|
|
|
246 |
|
|
function render($info, $parents = array()) {
|
247 |
|
|
$output = '';
|
248 |
|
|
foreach ($info as $key => $value) {
|
249 |
|
|
if (is_numeric($key)) {
|
250 |
|
|
$key = '';
|
251 |
|
|
}
|
252 |
|
|
if (is_array($value)) {
|
253 |
|
|
$p = $parents;
|
254 |
|
|
$p[] = $key;
|
255 |
|
|
$output .= $this->render($value, $p);
|
256 |
|
|
}
|
257 |
|
|
else {
|
258 |
|
|
// For simplicity
|
259 |
|
|
$first = TRUE;
|
260 |
|
|
$p = $parents;
|
261 |
|
|
$p[] = $key;
|
262 |
|
|
foreach ($p as $parent) {
|
263 |
|
|
if ($first) {
|
264 |
|
|
$key_definition = $parent;
|
265 |
|
|
$first = FALSE;
|
266 |
|
|
}
|
267 |
|
|
else {
|
268 |
|
|
$key_definition .= '[' . $parent . ']';
|
269 |
|
|
}
|
270 |
|
|
}
|
271 |
|
|
$output .= "$key_definition = $value\n";
|
272 |
|
|
}
|
273 |
|
|
if (count($parents) < 2) {
|
274 |
|
|
$output .= "\n";
|
275 |
|
|
}
|
276 |
|
|
}
|
277 |
|
|
return $output;
|
278 |
|
|
}
|
279 |
|
|
|
280 |
|
|
}
|
281 |
|
|
|
282 |
|
|
class DrushMakeDrupalorgVerifier extends DrushMakeDrupalorgVersionChecker {
|
283 |
|
|
function __construct($makefile) {
|
284 |
|
|
$this->makefile = $makefile;
|
285 |
|
|
}
|
286 |
|
|
|
287 |
|
|
function run() {
|
288 |
|
|
if ($makefile = $this->read($this->makefile)) {
|
289 |
|
|
$this->verify($makefile);
|
290 |
|
|
}
|
291 |
|
|
}
|
292 |
|
|
|
293 |
|
|
function read($makefile) {
|
294 |
|
|
if (!($makefile = drush_make_parse_info_file($makefile))) {
|
295 |
|
|
drush_make_error('FILE_ERROR', dt("Unable to parse file %file", array('%file' => $makefile)));
|
296 |
|
|
return FALSE;
|
297 |
|
|
}
|
298 |
|
|
return $makefile;
|
299 |
|
|
}
|
300 |
|
|
|
301 |
|
|
function verify($makefile) {
|
302 |
|
|
// Run the regular validation first. This performs basic syntax
|
303 |
|
|
// validation, and also pre-converts special syntax into a standard
|
304 |
|
|
// format. Since the info file validation doesn't return any data if
|
305 |
|
|
// validation fails, we have to bail here.
|
306 |
|
|
if (!($makefile = drush_make_validate_info_file($makefile))) {
|
307 |
|
|
return FALSE;
|
308 |
|
|
}
|
309 |
|
|
|
310 |
|
|
// Now run drupal.org specific validation on the file.
|
311 |
|
|
if (!($makefile = drush_make_d_o_validate_info_file($makefile))) {
|
312 |
|
|
return FALSE;
|
313 |
|
|
}
|
314 |
|
|
|
315 |
|
|
$this->core = $makefile['core'];
|
316 |
|
|
// Check for a stable release on the branch.
|
317 |
|
|
list($result, $final_version) = $this->latestVersion('drupal', $makefile['core_release']);
|
318 |
|
|
if (!$result) {
|
319 |
|
|
$errors = TRUE;
|
320 |
|
|
}
|
321 |
|
|
|
322 |
|
|
if (isset($makefile['projects'])) {
|
323 |
|
|
|
324 |
|
|
// The list of currently disallowed projects.
|
325 |
|
|
$project_disallowed_list = array('drupal');
|
326 |
|
|
foreach ($makefile['projects'] as $project => $project_data) {
|
327 |
|
|
// Error out on disallowed projects.
|
328 |
|
|
if (in_array($project, $project_disallowed_list)) {
|
329 |
|
|
if ($project == 'drupal') {
|
330 |
|
|
drush_make_error('BUILD_ERROR', dt("It is not permitted to include Drupal core as a project in an install profile."));
|
331 |
|
|
}
|
332 |
|
|
else {
|
333 |
|
|
drush_make_error('BUILD_ERROR', dt("Project '%project' is not permitted in an install profile.", array('%project' => $project)));
|
334 |
|
|
}
|
335 |
|
|
$errors = TRUE;
|
336 |
|
|
}
|
337 |
|
|
else {
|
338 |
|
|
// Use the update XML to verify this project actually has this
|
339 |
|
|
// release.
|
340 |
|
|
list($result, $final_version) = $this->latestVersion($project, $project_data['version']);
|
341 |
|
|
if (!$result) {
|
342 |
|
|
$errors = TRUE;
|
343 |
|
|
}
|
344 |
|
|
}
|
345 |
|
|
}
|
346 |
|
|
}
|
347 |
|
|
if (!$errors) {
|
348 |
|
|
drush_log(dt('No errors were found.'), 'ok');
|
349 |
|
|
}
|
350 |
|
|
else {
|
351 |
|
|
drush_make_error('BUILD_ERROR', dt('Errors were found.'));
|
352 |
|
|
}
|
353 |
|
|
}
|
354 |
|
|
}
|
355 |
|
|
|
356 |
|
|
|
357 |
|
|
/**
|
358 |
|
|
* Custom logging function for conversions going to STDOUT.
|
359 |
|
|
*
|
360 |
|
|
* Drush doesn't output drush_set_error() messages to STDERR, lame-o... :(
|
361 |
|
|
*
|
362 |
|
|
* This helper function overcomes that deficiency by manually writing error
|
363 |
|
|
* messages to STDERR in the case where output is going to STDOUT.
|
364 |
|
|
*/
|
365 |
|
|
function drush_make_d_o_convert_log_stdout_handler($entry) {
|
366 |
|
|
if ($entry['type'] == 'error' || $entry['type'] == 'failed') {
|
367 |
|
|
fwrite(STDERR, dt("ERROR") . ": " . $entry['message'] . "\n");
|
368 |
|
|
}
|
369 |
|
|
}
|