From 0a212aee22352b1f163ae731c2ee3dd6c52c5a59 Mon Sep 17 00:00:00 2001 From: Greg Anderson Date: Sat, 10 Apr 2010 18:48:42 +0000 Subject: [PATCH] #757602 by greg.1.anderson: Download drush modules (e.g. drush_make) to $HOME/.drush, and allow drush commandfiles to affect dl destination --- commands/pm/pm.drush.inc | 66 ++++++++++++++++++++++++++++++++++++++++ drush.api.php | 13 ++++++-- includes/command.inc | 10 ++++-- 3 files changed, 85 insertions(+), 4 deletions(-) diff --git a/commands/pm/pm.drush.inc b/commands/pm/pm.drush.inc index 7d6657dde5..24000e2f28 100644 --- a/commands/pm/pm.drush.inc +++ b/commands/pm/pm.drush.inc @@ -1297,6 +1297,12 @@ function drush_pm_download() { return FALSE; } if (package_handler_install_project($project, $release)) { + // If the --destination option was not specified, then + // allow commandfiles that implement the adjust-download-destination + // hook to pick a new default location for the project. + if (drush_get_option('destination', FALSE) === FALSE) { + drush_pm_relocate_project($project, $release); + } drush_log(dt("Project !project (!version) downloaded to !dest.", array('!project' => $request['name'], '!version' => $release['version'], '!dest' => $project['full_project_path'])), 'success'); drush_command_invoke_all('drush_pm_post_download', $project, $release); $version_control->post_download($project); @@ -1312,3 +1318,63 @@ function drush_pm_download() { unset($error, $release, $releases, $types); } } + +/** + * drush_pm_relocate_project moves projects that should be relocated to a different + * installation directory to the location they belong in. For example, + * modules that are only collections of drush commands will be installed + * to $HOME/.drush. + * + * This function is called after the project is downloaded so that its + * contents can be examined to determine its optimal installation location. + * Every drush commandfile is given a chance to examine the project contents + * and decide where the project should be located. + */ +function drush_pm_relocate_project(&$project, $release) { + // Call the get-install-location hook to see if any drush commandfiles + // would like to adjust the install location for this project. + // drush_command_invoke_all() allows the first parameter to be passed by reference. + drush_command_invoke_all_ref('drush_pm_adjust_download_destination', $project, $release); + + if (isset($project['project_install_location']) && ($project['full_project_path'] != $project['project_install_location'])) { + if (rename($project['full_project_path'], $project['project_install_location'])) { + $project['full_project_path'] = $project['project_install_location']; + } + else { + return drush_set_error('DRUSH_PM_DOWNLOAD_FAILED', dt("Project !project (!version) could not be installed at !dest.", array('!project' => $request['name'], '!version' => $release['version'], '!dest' => $project['project_install_location']))); + } + } + return TRUE; +} + +/** + * Built-in adjust-download-destination hook. This particular version of + * the hook will move modules that contain only drush commands to + * /etc/drush if it exists, or $HOME/.drush if /etc/drush does not + * exist. + */ +function pm_drush_pm_adjust_download_destination(&$project, $release) { + // If this project is a module, but it has no .module file, then + // check to see if it contains drush commands. If that is all + // that it contains, then install it to $HOME/.drush. + if ($release['type'] == 'module') { + $module_files = drush_scan_directory($project['full_project_path'], '/.*\.module/'); + if (empty($module_files)) { + $drush_command_files = drush_scan_directory($project['full_project_path'], '/.*\.drush.inc/'); + if (!empty($drush_command_files)) { + $install_dir = drush_get_context('SHARE_PREFIX', '/usr') . '/share/drush/commands/'; + if (!is_dir($install_dir)) { + $install_dir = drush_server_home() . '/.drush/'; + } + // Make the .drush dir if it does not already exist + if (!is_dir($install_dir)) { + mkdir($install_dir); + } + // Change the location if the mkdir worked + if (is_dir($install_dir)) { + $project['project_install_location'] = $install_dir . basename($project['full_project_path']); + } + } + } + } +} diff --git a/drush.api.php b/drush.api.php index 983159c341..a6b86d774e 100644 --- a/drush.api.php +++ b/drush.api.php @@ -132,17 +132,26 @@ function hook_drush_exit() { /** * Take action after a project has been downloaded. */ -function hook_drush_pm_post_pm_download($project, $release, $destination) { +function hook_drush_pm_post_download($project, $release, $destination) { } /** * Take action after a project has been updated. */ -function hook_pm_post_updatedb($release_name, $release_candidate_version, $project_parent_path) { +function hook_pm_post_update($release_name, $release_candidate_version, $project_parent_path) { } +/** + * Adjust the location that a project should be downloaded to. + */ +function hook_drush_pm_adjust_download_destination(&$project, $release) { + if (...) { + $project['project_install_location'] = '/path/to/install/to/' . basename($project['full_project_path']); + } +} + /** * @} End of "addtogroup hooks". */ diff --git a/includes/command.inc b/includes/command.inc index 6ac7eab257..0f26c6d2a1 100644 --- a/includes/command.inc +++ b/includes/command.inc @@ -402,8 +402,14 @@ function drush_command() { */ function drush_command_invoke_all() { $args = func_get_args(); - $hook = $args[0]; - unset($args[0]); + return call_user_func_array('drush_command_invoke_all_ref', $args); +} + +function drush_command_invoke_all_ref($hook, &$reference_parameter) { + $args = func_get_args(); + array_shift($args); + // Insure that call_user_func_array can alter first parameter + $args[0] = &$reference_parameter; $return = array(); foreach (drush_command_implements($hook) as $module) { $function = $module .'_'. $hook;