a180b788ad4221413561d6081aafad3c82cbf587
[yaffs-website] / vendor / drush / drush / commands / make / generate.make.inc
1 <?php
2 /**
3  * @file
4  * Functions for the generate makefile command.
5  */
6
7 include_once DRUSH_DRUPAL_CORE . '/includes/install.inc';
8 include_once drupal_get_path('module', 'system') . '/system.install';
9 include_once 'generate.contents.make.inc';
10
11 /**
12  * Drush callback; generate makefile from the current build.
13  */
14 function drush_make_generate($file = NULL) {
15   $version_options = _drush_make_generate_get_version_options();
16   $all_extensions = drush_get_extensions();
17   list($projects, $libraries) = _drush_make_generate_projects($all_extensions, $version_options);
18   $core = drush_drupal_major_version() . '.x';
19   $contents = make_generate_makefile_contents($projects, $libraries, $core);
20
21   // Write or print our makefile.
22   make_generate_print($contents, $file);
23 }
24
25 /**
26  * Create the $version_options array from the --include-versions and
27  * --exclude-versions command line options.
28  */
29 function _drush_make_generate_get_version_options() {
30   // What projects should we pin the versions for?
31   // Check the command-line options for details.
32   foreach (array("include", "exclude") as $option) {
33     $version_options[$option] = drush_get_option("$option-versions");
34     if ($version_options[$option] !== TRUE) {
35       $version_options[$option] = array_filter(explode(",", $version_options[$option]));
36     }
37   }
38   return $version_options;
39 }
40
41 /**
42  * Generate the $projects makefile array for the current site.
43  */
44 function _drush_make_generate_projects($all_extensions, $version_options) {
45   $release_info = drush_get_engine('release_info');
46
47   $projects = array();
48   $project_libraries = array();
49
50   $system_requirements = system_requirements('runtime');
51   // Update xml expects the drupal version to be expressed as "7.x" or "8.x"
52   // We used to check $system_requirements['drupal']['value'], but this now
53   // contains values such as "7.10-dev".
54   $drupal_major_version = drush_drupal_major_version() . '.x';
55   $core_project = strtolower($system_requirements['drupal']['title']);
56   $projects[$core_project] = array('_type' => 'core');
57   if ($core_project != 'drupal') {
58     $projects[$core_project]['custom_download'] = TRUE;
59     $projects[$core_project]['type'] = 'core';
60   }
61   else {
62     // Drupal core - we can determine the version if required.
63     if (_drush_generate_track_version("drupal", $version_options)) {
64       $projects[$core_project]["version"] = drush_drupal_version();
65     }
66   }
67
68   $install_profile = drush_drupal_major_version() >= 7 ? drupal_get_profile() : variable_get('install_profile', '');
69   if (!in_array($install_profile, array('default', 'standard', 'minimal', 'testing')) && $install_profile != '') {
70     $projects[$install_profile]['type']
71       = $projects[$install_profile]['_type'] = 'profile';
72     $request = array(
73       'name' => $install_profile,
74       'drupal_version' => $drupal_major_version,
75     );
76     if (!$release_info->checkProject($request, 'profile')) {
77       $projects[$install_profile]['custom_download'] = TRUE;
78     }
79   }
80
81   // Iterate installed projects to build $projects array.
82   $extensions = $all_extensions;
83   $project_info = drush_get_projects($extensions);
84   foreach ($project_info as $name => $project) {
85     // Discard the extensions within this project. At the end $extensions will
86     // contain only extensions part of custom projects (not from drupal.org or
87     // other update service).
88     foreach ($project['extensions'] as $ext) {
89       unset($extensions[$ext]);
90     }
91     if ($name == 'drupal') {
92       continue;
93     }
94     $type = $project['type'];
95     // Discard projects with all modules disabled.
96     if (($type == 'module') && (!$project['status'])) {
97       continue;
98     }
99     $projects[$name] = array('_type' => $type);
100     // Check the project is on drupal.org or its own update service.
101     $request = array(
102       'name' => $name,
103       'drupal_version' => $drupal_major_version,
104     );
105     if (isset($project['status url'])) {
106       $request['status url'] = $project['status url'];
107       $projects[$name]['location'] = $project['status url'];
108     }
109     if (!$release_info->checkProject($request, $type)) {
110       // It is not a project on drupal.org neither an external update service.
111       $projects[$name]['type'] = $type;
112       $projects[$name]['custom_download'] = TRUE;
113     }
114     // Add 'subdir' if the project is installed in a non-default location.
115     if (isset($project['path'])) {
116       $projects[$name] += _drush_generate_makefile_check_path($project);
117     }
118     // Add version number if this project's version is to be tracked.
119     if (_drush_generate_track_version($name, $version_options) && $project["version"]) {
120       $version = preg_replace("/^" . drush_get_drupal_core_compatibility() . "-/", "", $project["version"]);
121       // Strip out MINOR+GIT_COMMIT strings for dev releases.
122       if (substr($version, -4) == '-dev' && strpos($version, '+')) {
123         $version = substr($version, 0, strrpos($version, '.')) . '.x-dev';
124       }
125       $projects[$name]['version'] = $version;
126     }
127     foreach ($project['extensions'] as $extension_name) {
128       _drush_make_generate_add_patch_files($projects[$name], _drush_extension_get_path($all_extensions[$extension_name]));
129     }
130   }
131
132   // Add a project for each unknown extension.
133   foreach ($extensions as $name => $extension) {
134     list($project_name, $project_data) = _drush_generate_custom_project($name, $extension, $version_options);
135     $projects[$project_name] = $project_data;
136   }
137
138   // Add libraries.
139   if (function_exists('libraries_get_libraries')) {
140     $libraries = libraries_get_libraries();
141     foreach ($libraries as $library_name => $library_path) {
142       $path = explode('/', $library_path);
143       $project_libraries[$library_name] = array(
144         'directory_name' => $path[(count($path) - 1)],
145         'custom_download' => TRUE,
146         'type' => 'library',
147         '_type' => 'librarie', // For plural.
148       );
149     }
150   }
151   return array($projects, $project_libraries);
152 }
153
154 /**
155  * Record any patches that were applied to this project
156  * per information stored in PATCHES.txt.
157  */
158 function _drush_make_generate_add_patch_files(&$project, $location) {
159   $patchfile = DRUPAL_ROOT . '/' . $location . '/PATCHES.txt';
160   if (is_file($patchfile)) {
161     foreach (file($patchfile) as $line) {
162       if (substr($line, 0, 2) == '- ') {
163         $project['patch'][] = trim(substr($line, 2));
164       }
165     }
166   }
167 }
168
169 /**
170  * Create a project record for an extension not downloaded from drupal.org
171  */
172 function _drush_generate_custom_project($name, $extension, $version_options) {
173   $project['_type'] = drush_extension_get_type($extension);
174   $project['type'] = drush_extension_get_type($extension);
175   $location = drush_extension_get_path($extension);
176   // To start off, we will presume that our custom extension is
177   // stored in a folder named after its project, and there are
178   // no subfolders between the .info file and the project root.
179   $project_name = basename($location);
180   drush_shell_cd_and_exec($location, 'git rev-parse --git-dir 2> ' . drush_bit_bucket());
181   $output = drush_shell_exec_output();
182   if (!empty($output)) {
183     $git_dir = $output[0];
184     // Find the actual base of the git repository.
185     $repo_root = $git_dir == ".git" ? $location : dirname($git_dir);
186     // If the repository root is at the drupal root or some parent
187     // of the drupal root, or some other location that could not
188     // pausibly be a project, then there is nothing we can do.
189     // (We can't tell Drush make to download some sub-part of a repo,
190     // can we?)
191     if ($repo_project_name = _drush_generate_validate_repo_location($repo_root)) {
192       $project_name = $repo_project_name;
193       drush_shell_cd_and_exec($repo_root, 'git remote show origin');
194       $output = drush_shell_exec_output();
195       foreach ($output as $line) {
196         if (strpos($line, "Fetch URL:") !== FALSE) {
197           $url = preg_replace('/ *Fetch URL: */', '', $line);
198           if (!empty($url)) {
199             // We use the unconventional-looking keys
200             // `download][type` and `download][url` so that
201             // we can produce output that appears to be two-dimensional
202             // arrays from a single-dimensional array.
203             $project['download][type'] = 'git';
204             $project['download][url'] = $url;
205
206             // Fill in the branch as well.
207             drush_shell_cd_and_exec($repo_root, 'git branch');
208             $output = drush_shell_exec_output();
209             foreach ($output as $line) {
210               if ($line{0} == '*') {
211                 $branch = substr($line, 2);
212                 if ($branch != "master") {
213                   $project['download][branch'] = $branch;
214                 }
215               }
216             }
217
218             // Put in the commit hash.
219             drush_shell_cd_and_exec($repo_root, 'git log');
220             $output = drush_shell_exec_output();
221             if (substr($output[0], 0, 7) == "commit ") {
222               $revision = substr($output[0], 7);
223               if (_drush_generate_track_version($project_name, $version_options)) {
224                 $project['download][revision'] = $revision;
225               }
226             }
227
228             // Add patch files, if any.
229             _drush_make_generate_add_patch_files($project, $repo_root);
230           }
231         }
232       }
233     }
234   }
235   // If we could not figure out where the extension came from, then give up and
236   // flag it as a "custom" download.
237   if (!isset($project['download][type'])) {
238     $project['custom_download'] = TRUE;
239   }
240   return array($project_name, $project);
241 }
242
243 /**
244  * If the user has checked in the Drupal root, or the 'sites/all/modules'
245  * folder into a git repository, then we do not want to confuse that location
246  * with a "project".
247  */
248 function _drush_generate_validate_repo_location($repo_root) {
249   $project_name = basename($repo_root);
250   // The Drupal root, or any folder immediately inside the Drupal
251   // root cannot be a project location.
252   if ((strlen(DRUPAL_ROOT) >= strlen($repo_root)) || (dirname($repo_root) == DRUPAL_ROOT)) {
253     return NULL;
254   }
255   // Also exclude sites/* and sites/*/{modules,themes} and profile/* and
256   // profile/*/{modules,themes}.
257   return $project_name;
258 }
259
260 /**
261  * Helper function to determine if a given project is to have its version
262  * tracked.
263  */
264 function _drush_generate_track_version($project, $version_options) {
265   // A. If --exclude-versions has been specified:
266   // A.a. if it's a boolean, check the --include-versions option.
267   if ($version_options["exclude"] === TRUE) {
268     // A.a.1 if --include-versions has been specified, ensure it's an array.
269     if (is_array($version_options["include"])) {
270       return in_array($project, $version_options["include"]);
271     }
272     // A.a.2 If no include array, then we're excluding versions for ALL
273     // projects.
274     return FALSE;
275   }
276   // A.b. if --exclude-versions is an array with items, check this project is in
277   // it: if so, then return FALSE.
278   elseif (is_array($version_options["exclude"]) && count($version_options["exclude"])) {
279     return !in_array($project, $version_options["exclude"]);
280   }
281
282   // B. If by now no --exclude-versions, but --include-versions is an array,
283   // examine it for this project.
284   if (is_array($version_options["include"]) && count($version_options["include"])) {
285     return in_array($project, $version_options["include"]);
286   }
287
288   // If none of the above conditions match, include version number by default.
289   return TRUE;
290 }
291
292 /**
293  * Helper function to check for a non-default installation location.
294  */
295 function _drush_generate_makefile_check_path($project) {
296   $info = array();
297   $type = $project['type'];
298   $path = dirname($project['path']);
299   // Check to see if the path is in a subdir sites/all/modules or
300   // profiles/profilename/modules
301   if (preg_match('@^sites/[a-zA-Z0-9_]*/' . $type . 's/..*@', $path) || preg_match('@^sites/[a-zA-Z0-9_]*/' . $type . 's/..*@', $path)) {
302     $subdir = preg_replace(array('@^[a-zA-Z0-9_]*/[a-zA-Z0-9_]*/' . $type . 's/*@', "@/$name" . '$@'), '', $path);
303     if (!empty($subdir)) {
304       $info['subdir'] = $subdir;
305     }
306   }
307   return $info;
308 }