1
|
<?php
|
2
|
// $Id: drush_make.drush.inc,v 1.11.2.71 2010/09/04 16:17:42 dmitrig01 Exp $
|
3
|
|
4
|
define('DRUSH_MAKE_UPDATE_DEFAULT_URL', 'http://updates.drupal.org/release-history');
|
5
|
define('DRUSH_MAKE_VERSION_BEST', 'best');
|
6
|
|
7
|
include_once 'drush_make.utilities.inc';
|
8
|
include_once 'drush_make.download.inc';
|
9
|
include_once 'drush_make.project.inc';
|
10
|
|
11
|
/**
|
12
|
* Implement EXTENSION_drush_init().
|
13
|
*/
|
14
|
function drush_make_drush_init() {
|
15
|
// The default URL to use for retrieving update XML files.
|
16
|
drush_set_default('drush-make-update-default-url', DRUSH_MAKE_UPDATE_DEFAULT_URL);
|
17
|
}
|
18
|
|
19
|
/**
|
20
|
* Implementation of hook_drush_command().
|
21
|
*/
|
22
|
function drush_make_drush_command() {
|
23
|
$items['make'] = array(
|
24
|
'bootstrap' => DRUSH_BOOTSTRAP_DRUSH,
|
25
|
'description' => 'Turns a makefile into a working drupal install.',
|
26
|
'arguments' => array(
|
27
|
'makefile' => 'Filename of the makefile to use for this build.',
|
28
|
'build path' => 'The path at which to build the makefile.',
|
29
|
),
|
30
|
'examples' => array(
|
31
|
'drush make example.make example' => 'Build the example.make makefile in the example directory.',
|
32
|
),
|
33
|
'options' => array(
|
34
|
'--version' => 'Print the version and exit.',
|
35
|
'--contrib-destination=path' => 'Specify a path under which modules and themes should be placed. Defaults to sites/all.',
|
36
|
'--force-complete' => 'Force a complete build even if errors occur.',
|
37
|
'--md5' => 'Output an md5 hash of the current build after completion.',
|
38
|
'--no-clean' => 'Leave temporary build directories in place instead of cleaning up after completion.',
|
39
|
'--no-core' => 'Do not require a Drupal core project to be specified.',
|
40
|
'--no-patch-txt' => 'Do not write a PATCHES.txt file in the directory of each patched project.',
|
41
|
'--prepare-install' => 'Prepare the built site for installation. Generate a properly permissioned settings.php and files directory.',
|
42
|
'--tar' => 'Generate a tar archive of the build. The output filename will be [build path].tar.gz.',
|
43
|
'--test' => 'Run a temporary test build and clean up.',
|
44
|
'--translations=languages' => 'Retrieve translations for the specified comma-separated list of language(s) if available for all projects.',
|
45
|
'--working-copy' => 'Where possible, retrieve a working copy of projects from their respective repositories.',
|
46
|
),
|
47
|
);
|
48
|
|
49
|
$items['make-test'] = array(
|
50
|
'bootstrap' => DRUSH_BOOTSTRAP_DRUSH,
|
51
|
'description' => 'Run a drush make test.',
|
52
|
'arguments' => array(
|
53
|
'test' => 'Name of the test to run or ALL to run all tests.',
|
54
|
),
|
55
|
'examples' => array(
|
56
|
'drush make-test svn' => 'Run tests for SVN integration.',
|
57
|
),
|
58
|
);
|
59
|
|
60
|
$items['generate-makefile'] = array(
|
61
|
'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL,
|
62
|
'description' => 'Attempts to generate a makefile from the current drupal install.',
|
63
|
);
|
64
|
|
65
|
return $items;
|
66
|
}
|
67
|
|
68
|
/**
|
69
|
* Implementation of hook_drush_help().
|
70
|
*/
|
71
|
function drush_make_drush_help($section) {
|
72
|
switch ($section) {
|
73
|
case 'drush:make':
|
74
|
return dt('Turns a makefile into a working drupal install. For a full description of options and makefile syntax, see the README.txt included with drush make.');
|
75
|
case 'drush:make-test':
|
76
|
return dt('Run a drush make test.');
|
77
|
case 'drush:generate-makefile':
|
78
|
return dt('Attempts to generate a makefile from the current drupal install.');
|
79
|
}
|
80
|
}
|
81
|
|
82
|
/**
|
83
|
* Drush callback; make based on the makefile.
|
84
|
*/
|
85
|
function drush_drush_make_make($makefile = NULL, $build_path = NULL) {
|
86
|
if (!drush_make_ensure_version()) {
|
87
|
return;
|
88
|
}
|
89
|
if (drush_get_option('version', FALSE)) {
|
90
|
drush_print(drush_make_version());
|
91
|
return;
|
92
|
}
|
93
|
if (!($build_path = drush_make_build_path($build_path))) {
|
94
|
return;
|
95
|
}
|
96
|
if (!($info = drush_make_validate_info_file(drush_make_parse_info_file($makefile)))) {
|
97
|
return;
|
98
|
}
|
99
|
|
100
|
drush_make_projects(FALSE, drush_get_option('contrib-destination', 'sites/all'), $info, $build_path);
|
101
|
drush_make_libraries(drush_get_option('contrib-destination', 'sites/all'), $info, $build_path);
|
102
|
|
103
|
if (drush_get_option('prepare-install')) {
|
104
|
drush_make_prepare_install($build_path);
|
105
|
}
|
106
|
if (drush_get_option('md5')) {
|
107
|
drush_make_md5();
|
108
|
}
|
109
|
|
110
|
// Only take final build steps if not in testing mode.
|
111
|
if (!drush_get_option('test')) {
|
112
|
if (drush_get_option('tar')) {
|
113
|
drush_make_tar($build_path);
|
114
|
}
|
115
|
else {
|
116
|
drush_make_move_build($build_path);
|
117
|
}
|
118
|
}
|
119
|
|
120
|
drush_make_clean_tmp();
|
121
|
}
|
122
|
|
123
|
function drush_make_projects($recursion, $contrib_destination, $info, $build_path) {
|
124
|
$projects = array();
|
125
|
if (empty($info['projects'])) {
|
126
|
return;
|
127
|
}
|
128
|
foreach ($info['projects'] as $key => $project) {
|
129
|
// Merge the known data onto the project info.
|
130
|
$project += array(
|
131
|
'name' => $key,
|
132
|
'core' => $info['core'],
|
133
|
'build_path' => $build_path,
|
134
|
'contrib_destination' => $contrib_destination,
|
135
|
'version' => DRUSH_MAKE_VERSION_BEST,
|
136
|
'location' => drush_get_option('drush-make-update-default-url'),
|
137
|
'subdir' => '',
|
138
|
'directory_name' => '',
|
139
|
);
|
140
|
$project = drush_make_updatexml($project);
|
141
|
$class_name = 'DrushMakeProject_' . $project['type'];
|
142
|
$projects[($project['type'] == 'core' ? 'core' : 'contrib')][$project['name']] = new $class_name($project);
|
143
|
}
|
144
|
|
145
|
if (!empty($projects['core'])) {
|
146
|
$cores = count($projects['core']);
|
147
|
}
|
148
|
else {
|
149
|
$cores = 0;
|
150
|
}
|
151
|
|
152
|
if (drush_get_option('no-core')) {
|
153
|
unset($projects['core']);
|
154
|
}
|
155
|
elseif ($cores == 0 && !$recursion) {
|
156
|
drush_set_error(dt('No core project specified.'));
|
157
|
return FALSE;
|
158
|
}
|
159
|
elseif ($cores == 1 && $recursion) {
|
160
|
unset($projects['core']);
|
161
|
}
|
162
|
elseif ($cores > 1) {
|
163
|
drush_set_error(dt('More than one core project specified.'));
|
164
|
return FALSE;
|
165
|
}
|
166
|
if (isset($projects['core'])) {
|
167
|
foreach ($projects['core'] as $project) {
|
168
|
$project->make();
|
169
|
}
|
170
|
}
|
171
|
|
172
|
if (isset($projects['contrib'])) {
|
173
|
foreach ($projects['contrib'] as $project) {
|
174
|
$project->make();
|
175
|
}
|
176
|
}
|
177
|
}
|
178
|
|
179
|
function drush_make_libraries($contrib_destination, $info, $build_path) {
|
180
|
if (!empty($info['libraries'])) {
|
181
|
foreach ($info['libraries'] as $key => $library) {
|
182
|
if (!is_string($key) || !is_array($library)) {
|
183
|
// TODO Print a prettier message
|
184
|
continue;
|
185
|
}
|
186
|
// Merge the known data onto the library info.
|
187
|
$library += array(
|
188
|
'name' => $key,
|
189
|
'core' => $info['core'],
|
190
|
'build_path' => $build_path,
|
191
|
'contrib_destination' => $contrib_destination,
|
192
|
'subdir' => '',
|
193
|
'directory_name' => $key,
|
194
|
);
|
195
|
$class = new DrushMakeProject_Library($library);
|
196
|
$class->make();
|
197
|
}
|
198
|
}
|
199
|
}
|
200
|
|
201
|
function drush_make_updatexml($project) {
|
202
|
if (isset($project['download']) && isset($project['type'])) {
|
203
|
return $project;
|
204
|
}
|
205
|
if ($filename = _drush_make_download_file($project['location'] . '/' . $project['name'] . '/' . $project['core'])) {
|
206
|
$release_history = simplexml_load_string(file_get_contents($filename));
|
207
|
drush_op('unlink', $filename);
|
208
|
}
|
209
|
// First, get the release history.
|
210
|
if (!is_object($release_history) || !$release_history->title) {
|
211
|
drush_make_error('XML_ERROR', dt("Could not retrieve version information for %project.", array('%project' => $project['name'])));
|
212
|
return FALSE;
|
213
|
}
|
214
|
drush_log(dt('Project information for %project retrieved.', array('%project' => $project['name'])), 'ok');
|
215
|
$project['release_history'] = $release_history;
|
216
|
if (!isset($project['type'])) {
|
217
|
// Determine the project type.
|
218
|
$term_map = array(
|
219
|
'Modules' => 'module',
|
220
|
'Themes' => 'theme',
|
221
|
'Drupal project' => 'core',
|
222
|
'Installation profiles' => 'profile',
|
223
|
'Translations' => 'translation'
|
224
|
);
|
225
|
// Iterate through all terms related to this project.
|
226
|
foreach ($release_history->terms->term as $term) {
|
227
|
// If we find a term from the term map, add it.
|
228
|
if (in_array((string) $term->value, array_keys($term_map))) {
|
229
|
$project['type'] = $term_map[(string)$term->value];
|
230
|
break;
|
231
|
}
|
232
|
}
|
233
|
if (!isset($project['type'])) {
|
234
|
drush_make_error('BUILD_ERROR', dt("Unable to determine project type for %project.", array('%project' => $project['name'])));
|
235
|
return FALSE;
|
236
|
}
|
237
|
}
|
238
|
if (!isset($project['download'])) {
|
239
|
$project = drush_make_update_xml_download($project);
|
240
|
}
|
241
|
return $project;
|
242
|
}
|
243
|
|
244
|
function drush_make_update_xml_download($project) {
|
245
|
// Make an array of releases.
|
246
|
foreach ($project['release_history']->releases->release as $release) {
|
247
|
$version = (string) $release->version_major;
|
248
|
// there should be version_patch attribute for every stable release
|
249
|
// so checking whether the attribute exists should be enough
|
250
|
if (isset($release->version_patch)) {
|
251
|
$version .= '.' . (string) $release->version_patch;
|
252
|
}
|
253
|
// if version_patch attribute does not exist, then it should be a dev release
|
254
|
// and the version string should be in format MAJOR_VERSION.x-dev
|
255
|
else {
|
256
|
$version .= '.x';
|
257
|
}
|
258
|
if ($extra_version = (string) $release->version_extra) {
|
259
|
$version .= '-' . $extra_version;
|
260
|
}
|
261
|
$releases[$version] = array(
|
262
|
'file' => (string) $release->download_link,
|
263
|
'md5' => (string) $release->mdhash,
|
264
|
'version' => (string) $release->version,
|
265
|
);
|
266
|
foreach (array('major', 'patch', 'extra') as $part) {
|
267
|
$releases[$version][$part] = (string) $release->{'version_' . $part};
|
268
|
}
|
269
|
}
|
270
|
|
271
|
// Find the best release.
|
272
|
if ($project['version'] == DRUSH_MAKE_VERSION_BEST) {
|
273
|
$recommended_major = (string)$project['release_history']->recommended_major;
|
274
|
$project['version'] = _drush_make_update_xml_best_version($recommended_major, $releases);
|
275
|
}
|
276
|
// Find the best release for the specified version.
|
277
|
else {
|
278
|
$exploded_version = explode('.', $project['version']);
|
279
|
if (count($exploded_version) == 1) {
|
280
|
list($major) = $exploded_version;
|
281
|
$project['version'] = _drush_make_update_xml_best_version($major, $releases);
|
282
|
}
|
283
|
// Otherwise we have a full version.
|
284
|
}
|
285
|
|
286
|
$final_version = empty($project['version']) ? '' : $project['version'];
|
287
|
|
288
|
// Uh oh, couldn't find a valid version.
|
289
|
if (empty($final_version) || empty($releases[$final_version])) {
|
290
|
drush_make_error('BUILD_ERROR', dt("Invalid version %version for %project.", array('%version' => $final_version, '%project' => $project['name'])));
|
291
|
return FALSE;
|
292
|
}
|
293
|
|
294
|
$release = $releases[$final_version];
|
295
|
$project['download'] = array(
|
296
|
'type' => 'get',
|
297
|
'url' => $release['file'],
|
298
|
'md5' => $release['md5'],
|
299
|
);
|
300
|
return $project;
|
301
|
}
|
302
|
|
303
|
function _drush_make_update_xml_best_version($major, $releases) {
|
304
|
$best = NULL;
|
305
|
foreach ($releases as $version => $release_info) {
|
306
|
if ($release_info['major'] == $major && version_compare($best, $version, '<')) {
|
307
|
$best = $version;
|
308
|
}
|
309
|
}
|
310
|
return $best;
|
311
|
}
|
312
|
|
313
|
function drush_make_build_path($build_path) {
|
314
|
// Determine the base of the build.
|
315
|
if (drush_get_option('tar')) {
|
316
|
$build_path = dirname($build_path) . '/' . basename($build_path, '.tar.gz') . '.tar.gz';
|
317
|
}
|
318
|
elseif (isset($build_path) && (!empty($build_path) || $build_path == '.')) {
|
319
|
$build_path = rtrim($build_path, '/');
|
320
|
}
|
321
|
// Allow tests to run without a specified base path.
|
322
|
elseif (drush_get_option('test') || drush_confirm(dt("Make new site in the current directory?"))) {
|
323
|
$build_path = '.';
|
324
|
}
|
325
|
else {
|
326
|
drush_log(dt('Build aborted.'), 'ok');
|
327
|
return FALSE;
|
328
|
}
|
329
|
if ($build_path != '.' && file_exists($build_path)) {
|
330
|
drush_set_error(dt('Base path %path already exists', array('%path' => $build_path)));
|
331
|
return FALSE;
|
332
|
}
|
333
|
return $build_path;
|
334
|
}
|
335
|
|
336
|
function drush_make_move_build($build_path) {
|
337
|
$tmp_path = drush_make_tmp();
|
338
|
if ($build_path == '.') {
|
339
|
drush_shell_exec('ls -A %s', $tmp_path . '/__build__');
|
340
|
$info = drush_shell_exec_output();
|
341
|
foreach ($info as $file) {
|
342
|
drush_shell_exec("cp -Rf %s %s", $tmp_path . '/__build__/' . $file, $build_path);
|
343
|
}
|
344
|
}
|
345
|
else {
|
346
|
drush_make_mkdir(dirname($build_path));
|
347
|
drush_shell_exec("mv %s %s", $tmp_path . '/__build__', $tmp_path . '/' . basename($build_path));
|
348
|
drush_shell_exec("cp -Rf %s %s", $tmp_path . '/' . basename($build_path), dirname($build_path));
|
349
|
}
|
350
|
return TRUE;
|
351
|
}
|
352
|
|
353
|
function drush_make_version() {
|
354
|
return '2.0-dev';
|
355
|
}
|
356
|
|
357
|
/**
|
358
|
* Drush callback; make a makefile from the current install.
|
359
|
*/
|
360
|
function drush_drush_make_generate_makefile($file) {
|
361
|
include_once 'drush_make.generate.inc';
|
362
|
_drush_generate_makefile($file);
|
363
|
}
|
364
|
|
365
|
/**
|
366
|
* Drush callback; run a drush make test.
|
367
|
*/
|
368
|
function drush_drush_make_make_test($test = NULL) {
|
369
|
include_once 'drush_make.test.inc';
|
370
|
drush_make_test($test);
|
371
|
}
|