first import

This commit is contained in:
Bachir Soussi Chiadmi
2015-04-08 11:40:19 +02:00
commit 1bc61b12ad
8435 changed files with 1582817 additions and 0 deletions

View File

@@ -0,0 +1,148 @@
<?php
/**
* @file Drush PM CVS extension
*/
/**
* Validate this package handler can run.
*/
function package_handler_validate() {
// Check cvs command exists. Disable possible output.
$debug = drush_get_context('DRUSH_DEBUG');
drush_set_context('DRUSH_DEBUG', FALSE);
$success = drush_shell_exec('cvs --version');
drush_set_context('DRUSH_DEBUG', $debug);
if (!$success) {
return drush_set_error('DRUSH_SHELL_COMMAND_NOT_FOUND', dt('cvs executable not found.'));
}
// Check cvs_deploy is enabled. Only for bootstrapped sites.
if (drush_get_context('DRUSH_BOOTSTRAP_PHASE') >= DRUSH_BOOTSTRAP_DRUPAL_FULL) {
if (!module_exists('cvs_deploy')) {
drush_log(dt('cvs package handler needs cvs_deploy module enabled to work properly.'), 'warning');
}
}
}
/**
* Install a project.
*
* @param $project The project array with name, base and full (final) paths.
* @param $release The release details array from drupal.org
*/
function package_handler_download_project(&$project, $release) {
// Check it out.
drush_pm_cvs($project, $release);
if (!drush_get_context('DRUSH_SIMULATE')) {
if (is_dir($project['full_project_path'])) {
drush_log("Checking out " . $project['name'] . " was successful.");
return TRUE;
}
else {
return drush_set_error('DRUSH_PM_CVS_CHECKOUT_PROBLEMS', dt("Unable to check out !project to !destination from cvs.drupal.org", array('!project' => $project['name'], '!destination' => $project['full_project_path'])));
}
}
}
/**
* Update a project (so far, only modules are supported).
*
* @param $project The project array with name, base and full (final) paths.
* @param $release The release details array from drupal.org
*/
function package_handler_update_project(&$project, $release) {
drush_log('Updating project ' . $project['name'] . ' ...');
// Check out a fresh copy, or update an existing one.
drush_pm_cvs($project, $release);
if (is_dir($project['full_project_path']) && !drush_get_context('DRUSH_SIMULATE')) {
drush_log("Updating of " . $project['name'] . " was successful.");
return TRUE;
}
else {
return drush_set_error('DRUSH_PM_CVS_UPDATE_PROBLEMS', dt("Unable to update !project from cvs.drupal.org", array('!project' => $project['name'])));
}
}
/**
* General CVS helper function.
*
* @param $project The project array with name, base and full (final) paths.
* @param $release The release details array from drupal.org
*/
function drush_pm_cvs(&$project, $release) {
// Build the cvs command to execute.
$command = array('cvs');
// Global options.
$command[] = '-z6';
// cvs root.
$cvsroot = '-d:pserver:' . drush_get_option('cvscredentials', 'anonymous:anonymous') . '@cvs.drupal.org:/cvs/';
$cvsroot .= ($project['project_type'] == 'core')?'drupal':'drupal-contrib';
$command[] = $cvsroot;
// CVS command ("cvs method").
$cvsmethod = drush_get_option('cvsmethod', FALSE);
if (empty($cvsmethod)) {
$cvsmethod = 'checkout';
// If we have an existing working copy we update.
if (is_dir($project['full_project_path'] . '/CVS')) {
$cvsmethod = 'update';
}
}
$command[] = $cvsmethod;
// CVS command options.
$cvsparams = drush_get_option('cvsparams', FALSE);
// common options for any command.
$command[] = '-r '. $release['tag'];
// command specific options.
if ($cvsmethod == 'checkout') {
// checkout dir.
$command[] = '-d ' . $project['project_dir'];
// path to cvs 'module' to check out.
if ($project['project_type'] == 'core') {
$command[] = $project['name']; // drupal
}
else {
// strtr for 'theme engine' type.
$command[] = 'contributions/' . strtr($project['project_type'], ' ' ,'-') . 's/' . $project['name'];
}
}
else {
if ($cvsparams === FALSE) {
// By default we update overwriting changes, however if we have an
// existing CVS checkout that is version controlled then the default is
// to update in place, which will attempt to merge changes but we assume
// anyone using a VCS is competent enough to deal with this!
$reserved_files = drush_version_control_reserved_files();
$overwrite = TRUE;
foreach ($reserved_files as $file) {
if (file_exists($project['full_project_path'] . '/' . $file)) {
$overwrite = FALSE;
break;
}
}
$command[] = $overwrite?'-dPC':'-dP';
}
// Directory to work on.
$command[] = $project['project_dir'];
}
// CVS only accepts relative paths. We will cd in the checkout path right
// before running the cvs command.
if (!drush_shell_cd_and_exec($project['base_project_path'], implode(' ', $command))) {
return drush_set_error('DRUSH_PM_UNABLE_CHECKOUT', dt('Unable to !op !project from cvs.drupal.org.', array('!op' => $cvsmethod, '!project' => $project['name'])));
}
}
/**
* Post download action.
*
* This action take place once the project is placed in its final location.
*/
function package_handler_post_download($project) {
}

View File

@@ -0,0 +1,191 @@
<?php
/**
* @file Drush PM drupal.org Git extension.
*/
/**
* Validate this package handler can run.
*/
function package_handler_validate() {
// Check git command exists. Disable possible output.
$debug = drush_get_context('DRUSH_DEBUG');
drush_set_context('DRUSH_DEBUG', FALSE);
$success = drush_shell_exec('git --version');
drush_set_context('DRUSH_DEBUG', $debug);
if (!$success) {
return drush_set_error('DRUSH_SHELL_COMMAND_NOT_FOUND', dt('git executable not found.'));
}
// Check git_deploy is enabled. Only for bootstrapped sites.
if (drush_get_context('DRUSH_BOOTSTRAP_PHASE') >= DRUSH_BOOTSTRAP_DRUPAL_FULL) {
if (!module_exists('git_deploy')) {
drush_log(dt('git package handler needs git_deploy module enabled to work properly.'), 'warning');
}
}
}
/**
* Download a project.
*
* @param $request
* The project array with name, base and full (final) paths.
* @param $release
* The release details array from drupal.org.
*/
function package_handler_download_project(&$request, $release) {
if ($username = drush_get_option('gitusername')) {
// Uses SSH, which enables pushing changes back to git.drupal.org.
$repository = $username . '@git.drupal.org:project/' . $request['name'] . '.git';
}
else {
$repository = 'git://git.drupal.org/project/' . $request['name'] . '.git';
}
$request['repository'] = $repository;
$tag = $release['tag'];
// If the --cache option was given, create a new git reference cache of the
// remote repository, or update the existing cache to fetch recent changes.
if (drush_get_option('cache') && ($cachedir = drush_directory_cache())) {
$gitcache = $cachedir . '/git';
$projectcache = $gitcache . '/' . $request['name'] . '.git';
drush_mkdir($gitcache);
// Setup a new cache, if we don't have this project yet.
if (!file_exists($projectcache)) {
// --mirror works similar to --bare, but retrieves all tags, local
// branches, remote branches, and any other refs (notes, stashes, etc).
// @see http://stackoverflow.com/questions/3959924
$command = 'git clone --mirror';
if (drush_get_context('DRUSH_VERBOSE')) {
$command .= ' --verbose --progress';
}
$command .= ' %s %s';
drush_shell_cd_and_exec($gitcache, $command, $repository, $request['name'] . '.git');
}
// If we already have this project, update it to speed up subsequent clones.
else {
// A --mirror clone is fully synchronized with `git remote update` instead
// of `git fetch --all`.
// @see http://stackoverflow.com/questions/6150188
drush_shell_cd_and_exec($projectcache, 'git remote update');
}
$gitcache = $projectcache;
}
// Clone the repo into its appropriate target location.
$command = 'git clone';
$command .= ' ' . drush_get_option('gitcloneparams');
if (drush_get_option('cache')) {
$command .= ' --reference ' . drush_escapeshellarg($gitcache);
}
if (drush_get_context('DRUSH_VERBOSE')) {
$command .= ' --verbose --progress';
}
$command .= ' ' . drush_escapeshellarg($repository);
$command .= ' ' . drush_escapeshellarg($request['full_project_path']);
if (!drush_shell_exec($command)) {
return drush_set_error('DRUSH_PM_GIT_CHECKOUT_PROBLEMS', dt('Unable to clone project !name from git.drupal.org.', array('!name' => $request['name'])));
}
// Check if the 'tag' from the release feed is a tag or a branch.
// If the tag exists, git will return it
if (!drush_shell_cd_and_exec($request['full_project_path'], 'git tag -l ' . drush_escapeshellarg($tag))) {
return drush_set_error('DRUSH_PM_GIT_CHECKOUT_PROBLEMS', dt('Unable to clone project !name from git.drupal.org.', array('!name' => $request['name'])));
}
$output = drush_shell_exec_output();
if (isset($output[0]) && ($output[0] == $tag)) {
// If we want a tag, simply checkout it. The checkout will end up in
// "detached head" state.
$command = 'git checkout ' . drush_get_option('gitcheckoutparams');
$command .= ' ' . drush_escapeshellarg($tag);
if (!drush_shell_cd_and_exec($request['full_project_path'], $command)) {
return drush_set_error('DRUSH_PM_UNABLE_CHECKOUT', 'Unable to retrieve ' . $request['name'] . ' from git.drupal.org.');
}
}
else {
// Else, we want to checkout a branch.
// First check if we are not already in the correct branch.
if (!drush_shell_cd_and_exec($request['full_project_path'], 'git symbolic-ref HEAD')) {
return drush_set_error('DRUSH_PM_UNABLE_CHECKOUT', 'Unable to retrieve ' . $request['name'] . ' from git.drupal.org.');
}
$output = drush_shell_exec_output();
$current_branch = preg_replace('@^refs/heads/@', '', $output[0]);
// If we are not on the correct branch already, switch to the correct one.
if ($current_branch != $tag) {
$command = 'git checkout';
$command .= ' ' . drush_get_option('gitcheckoutparams');
$command .= ' --track ' . drush_escapeshellarg('origin/' . $tag) . ' -b ' . drush_escapeshellarg($tag);
if (!drush_shell_cd_and_exec($request['full_project_path'], $command)) {
return drush_set_error('DRUSH_PM_UNABLE_CHECKOUT', 'Unable to retrieve ' . $request['name'] . ' from git.drupal.org.');
}
}
}
return TRUE;
}
/**
* Update a project (so far, only modules are supported).
*
* @param $request
* The project array with name, base and full (final) paths.
* @param $release
* The release details array from drupal.org.
*/
function package_handler_update_project($request, $release) {
drush_log('Updating project ' . $request['name'] . ' ...');
$commands = array();
if ($release['version_extra'] == 'dev') {
// Update the branch of the development repository.
$commands[] = 'git pull';
$commands[] = drush_get_option('gitpullparams');
}
else {
// Use a stable repository.
$commands[] = 'git fetch';
$commands[] = drush_get_option('gitfetchparams');
$commands[] = ';';
$commands[] = 'git checkout';
$commands[] = drush_get_option('gitcheckoutparams');
$commands[] = $release['version'];
}
if (!drush_shell_cd_and_exec($request['full_project_path'], implode(' ', $commands))) {
return drush_set_error('DRUSH_PM_UNABLE_CHECKOUT', 'Unable to update ' . $request['name'] . ' from git.drupal.org.');
}
return TRUE;
}
/**
* Post download action.
*
* This action take place once the project is placed in its final location.
*
* Here we add the project as a git submodule.
*/
function package_handler_post_download($project) {
if (drush_get_option('gitsubmodule', FALSE)) {
// Obtain the superproject path, then add as submodule.
if (drush_shell_cd_and_exec(dirname($project['full_project_path']), 'git rev-parse --show-toplevel')) {
$output = drush_shell_exec_output();
$superproject = $output[0];
// Add the downloaded project as a submodule of its git superproject.
$command = array();
$command[] = 'git submodule add';
$command[] = drush_get_option('gitsubmoduleaddparams');
$command[] = $project['repository'];
// We need the submodule relative path.
$command[] = substr($project['full_project_path'], strlen($superproject) + 1);
if (!drush_shell_cd_and_exec($superproject, implode(' ', $command))) {
return drush_set_error('DRUSH_PM_GIT_CHECKOUT_PROBLEMS', dt('Unable to add !name as a git submodule of !super.', array('!name' => $project['name'], '!super' => $superproject)));
}
}
else {
return drush_set_error('DRUSH_PM_GIT_SUBMODULE_PROBLEMS', dt('Unable to create !project as a git submodule: !dir is not in a Git repository.', array('!project' => $project['name'], '!dir' => dirname($project['full_project_path']))));
}
}
}

View File

@@ -0,0 +1,104 @@
<?php
/**
* @file Drush PM Wget extension
*/
/**
* Validate this package handler can run.
*/
function package_handler_validate() {
// Check wget or curl command exists. Disable possible output.
$debug = drush_get_context('DRUSH_DEBUG');
drush_set_context('DRUSH_DEBUG', FALSE);
$success = drush_shell_exec('wget --version');
if (!$success) {
$success = drush_shell_exec('curl --version');
// Old version of curl shipped in darwin returns error status for --version
// and --help. Give the chance to use it.
if (!$success) {
$success = drush_shell_exec('which curl');
}
}
drush_set_context('DRUSH_DEBUG', $debug);
if (!$success) {
return drush_set_error('DRUSH_SHELL_COMMAND_NOT_FOUND', dt('wget nor curl executables found.'));
}
}
/**
* Download a project.
*
* @param $request Array with information on the request to download.
* @param $release The release details array from drupal.org.
*/
function package_handler_download_project(&$request, $release) {
// Install profiles come in several variants. User may specify which one she wants.
if ($request['project_type'] == 'profile') {
// @todo Use xpath to get the right file url.
$files = $release['files'];
foreach ($files as $key => $file) {
if ((string)$file->variant == drush_get_option('variant', 'full') && (string)$file->archive_type == 'tar.gz') {
$release['download_link'] = (string)$file->url;
$release['mdhash'] = (string)$file->md5;
break;
}
}
}
$filename = explode('/', $release['download_link']);
$filename = array_pop($filename);
// Download the project.
if (!drush_shell_exec("wget -P . %s", $release['download_link'])) {
drush_shell_exec("curl -O %s", $release['download_link']);
}
if (file_exists($filename) || drush_get_context('DRUSH_SIMULATE')) {
drush_log("Downloading " . $filename . " was successful.");
}
else {
return drush_set_error('DRUSH_PM_DOWNLOAD_FAILED', 'Unable to download ' . $filename . ' to ' . $request['base_project_path'] . ' from '. $release['download_link']);
}
// Check Md5 hash.
if (drush_op('md5_file', $filename) != $release['mdhash'] && !drush_get_context('DRUSH_SIMULATE')) {
drush_set_error('DRUSH_PM_FILE_CORRUPT', "File $filename is corrupt (wrong md5 checksum).");
drush_op('unlink', $filename);
return FALSE;
}
else {
drush_log("Md5 checksum of $filename verified.");
}
// Extract the tarball.
$file_list = drush_tarball_extract($filename, $request['base_project_path'], TRUE);
drush_op('unlink', $filename);
// Move untarred directory to project_dir, if distinct.
if (($request['project_type'] == 'core') || (($request['project_type'] == 'profile') && (drush_get_option('variant', 'core') == 'core'))) {
// Obtain the dodgy project_dir for drupal core.
$project_dir = rtrim($file_list[0], DIRECTORY_SEPARATOR);
if ($request['project_dir'] != $project_dir) {
$path = $request['base_project_path'];
drush_move_dir($path . '/'. $project_dir, $path . '/' . $request['project_dir']);
}
}
return TRUE;
}
/**
* This is an alias of the download function, since they are identical
*/
function package_handler_update_project(&$request, $release) {
return package_handler_download_project($request, $release);
}
/**
* Post download action.
*
* This action take place once the project is placed in its final location.
*/
function package_handler_post_download($project) {
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,145 @@
<?php
function pm_update_filter(&$project) {
$update = FALSE;
switch($project['status']) {
case UPDATE_CURRENT:
$status = dt('Up to date');
$project['candidate_version'] = $project['recommended'];
break;
case UPDATE_NOT_CURRENT:
$status = dt('Update available');
pm_release_recommended($project);
break;
case UPDATE_NOT_SECURE:
$status = dt('SECURITY UPDATE available');
pm_release_recommended($project);
break;
case UPDATE_REVOKED:
$status = dt('Installed version REVOKED');
pm_release_recommended($project);
break;
case UPDATE_NOT_SUPPORTED:
$status = dt('Installed version not supported');
pm_release_recommended($project);
break;
case UPDATE_NOT_CHECKED:
$status = dt('Unable to check status');
break;
default:
$status = dt('Unknown');
break;
}
return $status;
}
function pm_update_last_check() {
return variable_get('update_last_check', 0);
}
/**
* Command callback. Refresh update status information.
*/
function _pm_refresh() {
drush_print(dt("Refreshing update status information ..."));
update_refresh();
drush_print(dt("Done."));
}
/**
* Get update information for all installed projects.
*
* @see update_get_available().
* @see update_manual_status().
*
* @return An array containing remote and local versions for all installed
* projects
*/
function _pm_get_update_info($projects) {
// Force to invalidate some caches that are only cleared
// when visiting update status report page. This allow to detect changes in
// .info files.
_update_cache_clear('update_project_data');
_update_cache_clear('update_project_projects');
// From update_get_available(): Iterate all projects and create a fetch task
// for those we have no information or is obsolete.
module_load_include('inc', 'update', 'update.compare');
$available = _update_get_cached_available_releases();
$update_projects = update_get_projects();
foreach ($update_projects as $key => $project) {
if (empty($available[$key])) {
update_create_fetch_task($project);
continue;
}
if ($project['info']['_info_file_ctime'] > $available[$key]['last_fetch']) {
$available[$key]['fetch_status'] = UPDATE_FETCH_PENDING;
}
if (empty($available[$key]['releases'])) {
$available[$key]['fetch_status'] = UPDATE_FETCH_PENDING;
}
if (!empty($available[$key]['fetch_status']) && $available[$key]['fetch_status'] == UPDATE_FETCH_PENDING) {
update_create_fetch_task($project);
}
}
// Set a batch to process all pending tasks.
$batch = array(
'operations' => array(
array('update_fetch_data_batch', array()),
),
'finished' => 'update_fetch_data_finished',
'file' => drupal_get_path('module', 'update') . '/update.fetch.inc',
);
batch_set($batch);
drush_backend_batch_process();
// Calculate update status data.
$available = _update_get_cached_available_releases();
$data = update_calculate_project_data($available);
foreach ($data as $project_name => $project) {
// Discard custom projects.
if ($project['status'] == UPDATE_UNKNOWN) {
unset($data[$project_name]);
continue;
}
// Allow to update disabled projects.
if (in_array($project['project_type'], array('module-disabled', 'theme-disabled'))) {
$data[$project_name]['project_type'] = substr($project['project_type'], 0, strpos($project['project_type'], '-'));
}
// Set 'includes' key to all extensions. By default it only contain enabled
// extensions and _pm_get_project_path() needs all of them.
$data[$project_name]['includes'] = drupal_map_assoc($projects[$project_name]['extensions']);
// Store all releases, not just the ones selected by update.module.
$data[$project_name]['releases'] = $available[$project_name]['releases'];
}
$data = _pm_get_project_path($data, 'includes');
return $data;
}
function pm_get_project_info($projects) {
$data = array();
include_once drupal_get_path('module', 'update') .'/update.fetch.inc';
foreach ($projects as $project_name => $project) {
$url = UPDATE_DEFAULT_URL. "/$project_name/". drush_drupal_major_version() . '.x';
$xml = drupal_http_request($url);
if (isset($xml->error)) {
drush_set_error(dt(
'HTTP Request to @request has failed. @error',
array('@request' => $xml->request, '@error' => $xml->error)
));
}
elseif (!$info = update_parse_xml($xml->data)) {
drush_set_error(dt(
'No release history found for @project_name',
array('@project_name' => $project_name)
));
}
else {
$data[$project_name] = $info;
}
}
return $data;
}

View File

@@ -0,0 +1,100 @@
<?php
function pm_update_filter(&$project) {
$update = FALSE;
switch($project['status']) {
case UPDATE_STATUS_CURRENT:
$status = dt('OK');
$project['candidate_version'] = $project['recommended'];
break;
case UPDATE_STATUS_NOT_CURRENT:
$status = dt('Update available');
pm_release_recommended($project);
break;
case UPDATE_STATUS_NOT_SECURE:
$status = dt('SECURITY UPDATE available');
pm_release_recommended($project);
break;
case UPDATE_STATUS_REVOKED:
$status = dt('Installed version REVOKED');
pm_release_recommended($project);
break;
case UPDATE_STATUS_NOT_SUPPORTED:
$status = dt('Installed version not supported');
pm_release_recommended($project);
break;
default:
$status = dt('Ignored: !reason', array('!reason' => $project['reason']));
$project['title'] = $project['name'];
$project['candidate_version'] = dt('Unknown');
break;
}
return $status;
}
function pm_update_last_check() {
return variable_get('update_status_last', 0);
}
/**
* Command callback. Refresh update status information.
*/
function _pm_refresh() {
drush_print(dt("Refreshing update status information ..."));
update_status_refresh();
drush_print(dt("Done."));
}
/**
* Get update information for all installed projects.
*
* @return An array containing remote and local versions for all installed projects
*/
function _pm_get_update_info($projects) {
// We force a refresh if the cache is not available.
if (!cache_get('update_status_info', 'cache')) {
_pm_refresh();
}
$info = update_status_get_available(TRUE);
// Force to invalidate some update_status caches that are only cleared
// when visiting update status report page.
_update_status_cache_clear('update_status_project_data');
_update_status_cache_clear('update_status_project_projects');
$data = update_status_calculate_project_data($info);
// update_status for drupal 5 can only process modules,
// so we need to add this here for backwards compatibility
// or pm_get_project_path() will fail
foreach ($data as $project_name => $project_data) {
$data[$project_name]['project_type'] = 'module';
$data[$project_name]['modules'] = drupal_map_assoc($projects[$project_name]['extensions']);
}
$data = _pm_get_project_path($data, 'modules');
return $data;
}
/**
* Get project information from drupal.org.
*
* @param $projects An array of project names/**
* Get project information from drupal.org.
*
* @param $projects An array of project names
*/
function pm_get_project_info($projects) {
$info = array();
$data = array();
foreach ($projects as $project_name => $project) {
$url = UPDATE_STATUS_DEFAULT_URL. "/$project_name/". UPDATE_STATUS_CORE_VERSION;
$xml = drupal_http_request($url);
$data[] = $xml->data;
}
if ($data) {
$parser = new update_status_xml_parser;
$info = $parser->parse($data);
}
return $info;
}

View File

@@ -0,0 +1,103 @@
<?php
function pm_update_filter(&$project) {
$update = FALSE;
switch($project['status']) {
case UPDATE_CURRENT:
$status = dt('Up to date');
$project['candidate_version'] = $project['recommended'];
break;
case UPDATE_NOT_CURRENT:
$status = dt('Update available');
pm_release_recommended($project);
break;
case UPDATE_NOT_SECURE:
$status = dt('SECURITY UPDATE available');
pm_release_recommended($project);
break;
case UPDATE_REVOKED:
$status = dt('Installed version REVOKED');
pm_release_recommended($project);
break;
case UPDATE_NOT_SUPPORTED:
$status = dt('Installed version not supported');
pm_release_recommended($project);
break;
case UPDATE_NOT_CHECKED:
$status = dt('Unable to check status');
break;
default:
$status = dt('Unknown');
break;
}
return $status;
}
function pm_update_last_check() {
return variable_get('update_last_check', 0);
}
/**
* Command callback. Refresh update status information.
*/
function _pm_refresh() {
drush_print(dt("Refreshing update status information ..."));
update_refresh();
drush_print(dt("Done."));
}
/**
* Get update information for all installed projects.
*
* @return An array containing remote and local versions for all installed projects
*/
function _pm_get_update_info($projects) {
// We force a refresh if the cache is not available.
if (!cache_get('update_available_releases', 'cache_update')) {
_pm_refresh();
}
$info = update_get_available(TRUE);
// Force to invalidate some update_status caches that are only cleared
// when visiting update status report page.
_update_cache_clear('update_project_data');
_update_cache_clear('update_project_projects');
$data = update_calculate_project_data($info);
foreach ($data as $project_name => $project) {
// Discard custom projects.
if ($project['status'] == UPDATE_UNKNOWN) {
unset($data[$project_name]);
continue;
}
if (in_array($project['project_type'], array('disabled-module', 'disabled-theme'))) {
$data[$project_name]['project_type'] = substr($project['project_type'], strpos($project['project_type'], '-') + 1);
}
$data[$project_name]['includes'] = drupal_map_assoc($projects[$project_name]['extensions']);
}
$data = _pm_get_project_path($data, 'includes');
return $data;
}
/**
* Get project information from drupal.org.
*
* @param $projects An array of project names
*/
function pm_get_project_info($projects) {
$info = array();
$data = array();
foreach ($projects as $project_name => $project) {
$url = UPDATE_DEFAULT_URL. "/$project_name/". drush_drupal_major_version() . '.x';
$xml = drupal_http_request($url);
$data[] = $xml->data;
}
if ($data) {
include_once drupal_get_path('module', 'update') .'/update.fetch.inc';
$parser = new update_xml_parser;
$info = $parser->parse($data);
}
return $info;
}

View File

@@ -0,0 +1,640 @@
<?php
/**
* Command callback. Displays update status info and allows to update installed
* projects.
* Pass specific projects as arguments, otherwise we update all that have
* candidate releases.
*
* This command prompts for confirmation before updating, so it is safe to run
* just to check on. In this case, say at the confirmation prompt.
*/
function drush_pm_updatecode() {
// We don't provide for other options here, so we supply an explicit path.
drush_include_engine('update_info', 'drupal', NULL, DRUSH_BASE_PATH . '/commands/pm/update_info');
// Find only security updates?
$security_only = drush_get_option('security-only');
// Get specific requests.
$requests = _convert_csv_to_array(func_get_args());
// Parse out project name and version.
$requests = pm_parse_project_version($requests);
// Get installed extensions and projects.
$extensions = drush_get_extensions();
$projects = drush_get_projects($extensions);
// Get update status information.
$update_info = _pm_get_update_info($projects);
// Process locks specified on the command line.
$locked_list = drush_pm_update_lock($update_info, drush_get_option_list('lock'), drush_get_option_list('unlock'), drush_get_option('lock-message'));
foreach ($extensions as $name => $extension) {
// Add an item to $update_info for each enabled extension which was obtained
// from cvs or git and its project is unknown (because of cvs_deploy or
// git_deploy is not enabled).
if (!isset($extension->info['project'])) {
if ((isset($extension->vcs)) && ($extension->status)) {
$update_info[$name] = array(
'title' => $extension->info['name'],
'existing_version' => 'Unknown',
'status' => DRUSH_PM_REQUESTED_PROJECT_NOT_PACKAGED,
'status_msg' => dt('Project was not packaged by drupal.org but obtained from !vcs. You need to enable !vcs_deploy module', array('!vcs' => $extension->vcs))
);
// The user may have requested to update a project matching this
// extension. If it was by coincidence or error we don't mind as we've
// already added an item to $update_info. Just clean up $requests.
if (isset($requests[$name])) {
unset($requests[$name]);
}
}
}
// Aditionally if the extension name is distinct to the project name and
// the user asked to update the extension, fix the request.
elseif ((isset($requests[$name])) && ($extension->name != $extension->info['project'])) {
$requests[$extension->info['project']] = $requests[$name];
unset($requests[$name]);
}
}
// Add an item to $update_info for each request not present in $update_info.
foreach ($requests as $name => $request) {
if (!isset($update_info[$name])) {
// Disabled projects.
if ((isset($projects[$name])) && ($projects[$name]['status'] == 0)) {
$update_info[$name] = array(
'title' => $name,
'existing_version' => $projects[$name]['version'],
'status' => DRUSH_PM_REQUESTED_PROJECT_NOT_UPDATEABLE
);
unset($requests[$name]);
}
// At this point we are unable to find matching installed project.
// It does not exist at all or it is mispelled,...
else {
$update_info[$name] = array(
'title' => $name,
'existing_version' => 'Unknown',
'status'=> DRUSH_PM_REQUESTED_PROJECT_NOT_FOUND,
);
}
}
}
// If specific versions were requested, match the requested release.
foreach ($requests as $name => $request) {
if (!empty($request['version'])) {
$release = pm_get_release($request, $update_info[$name]);
if (!$release) {
$update_info[$name]['status'] = DRUSH_PM_REQUESTED_VERSION_NOT_FOUND;
}
else if ($release['version'] == $update_info[$name]['existing_version']) {
$update_info[$name]['status'] = DRUSH_PM_REQUESTED_CURRENT;
}
else {
$update_info[$name]['status'] = DRUSH_PM_REQUESTED_UPDATE;
}
// Set the candidate version to the requested release.
$update_info[$name]['candidate_version'] = $release['version'];
}
}
// Table headers.
$rows[] = array(dt('Name'), dt('Installed version'), dt('Proposed version'), dt('Status'));
// Process releases, notifying user of status and
// building a list of proposed updates.
$updateable = pm_project_filter($update_info, $rows, $security_only);
// Pipe preparation.
if (drush_get_context('DRUSH_PIPE')) {
$pipe = "";
foreach($updateable as $project) {
$pipe .= $project['name']. " ";
$pipe .= $project['existing_version']. " ";
$pipe .= $project['candidate_version']. " ";
$pipe .= str_replace(' ', '-', pm_update_filter($project)). "\n";
}
drush_print_pipe($pipe);
// Automatically curtail update process if in pipe mode.
$updateable = array();
}
$tmpfile = drush_tempnam('pm-updatecode.');
$last = pm_update_last_check();
drush_print(dt('Update information last refreshed: ') . ($last ? format_date($last) : dt('Never')));
drush_print();
drush_print(dt("Update status information on all installed and enabled Drupal projects:"));
drush_print_table($rows, TRUE, array(3 => 40), $tmpfile);
$contents = file_get_contents($tmpfile);
drush_print($contents);
drush_print();
// If specific project updates were requested then remove releases for all
// others.
if (!empty($requests)) {
foreach ($updateable as $name => $project) {
if (!isset($requests[$name])) {
unset($updateable[$name]);
}
}
}
// Prevent update of core if --no-core was specified.
if (isset($updateable['drupal']) && drush_get_option('no-core', FALSE)) {
unset($updateable['drupal']);
drush_print(dt('Skipping core update (--no-core specified).'));
}
// If there are any locked projects that were not requested, then remove them.
if (!empty($locked_list)) {
foreach ($updateable as $name => $project) {
if ((isset($locked_list[$name])) && (!isset($requests[$name]))) {
unset($updateable[$name]);
}
}
}
// First check to see if there is a newer drush.
$drush_update_available = NULL;
if (drush_get_option('self-update', TRUE)) {
$drush_update_available = drush_check_self_update();
}
// Do no updates in simulated mode.
if (drush_get_context('DRUSH_SIMULATE')) {
return drush_log(dt('No action taken in simulated mode.'), 'ok');
return TRUE;
}
$core_update_available = FALSE;
if (isset($updateable['drupal'])) {
$drupal_project = $updateable['drupal'];
unset($update_info['drupal']);
unset($updateable['drupal']);
// At present we need to update drupal core after non-core projects
// are updated.
if (empty($updateable)) {
return _pm_update_core($drupal_project, $tmpfile);
}
// If there are modules other than drupal core enabled, then update them
// first.
else {
$core_update_available = TRUE;
if ($drupal_project['status'] == UPDATE_NOT_SECURE) {
drush_print(dt("NOTE: A security update for the Drupal core is available."));
}
else {
drush_print(dt("NOTE: A code update for the Drupal core is available."));
}
drush_print(dt("Drupal core will be updated after all of the non-core modules are updated.\n"));
}
}
// If there are no releases to update, then print a final
// exit message. Supress the message if we already printed
// a message about a drush update being available.
if (empty($updateable)) {
if ($drush_update_available === TRUE) {
return FALSE;
}
if ($security_only) {
return drush_log(dt('No security updates available.'), 'ok');
}
else {
return drush_log(dt('No code updates available.'), 'ok');
}
}
// Offer to update to the identified releases.
if (!pm_update_packages($updateable, $tmpfile)) {
return FALSE;
}
// After projects are updated we can update core.
if ($core_update_available) {
drush_print();
return _pm_update_core($drupal_project, $tmpfile);
}
}
/**
* Update drupal core, following interactive confirmation from the user.
*
* @param $project
* The drupal project information from the drupal.org update service,
* copied from $update_info['drupal']. @see drush_pm_updatecode.
*/
function _pm_update_core(&$project, $tmpfile) {
drush_include_engine('package_handler', drush_get_option('package-handler', 'wget'));
$drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT');
drush_print(dt('Code updates will be made to drupal core.'));
drush_print(dt("WARNING: Updating core will discard any modifications made to Drupal core files, most noteworthy among these are .htaccess and robots.txt. If you have made any modifications to these files, please back them up before updating so that you can re-create your modifications in the updated version of the file."));
drush_print(dt("Note: Updating core can potentially break your site. It is NOT recommended to update production sites without prior testing."));
drush_print();
if (drush_get_option('notes', FALSE)) {
drush_print('Obtaining release notes for above projects...');
_drush_pm_releasenotes(array('drupal'), TRUE, $tmpfile);
}
if(!drush_confirm(dt('Do you really want to continue?'))) {
drush_print(dt('Rolling back all changes. Run again with --no-core to update modules only.'));
return drush_user_abort();
}
// We need write permission on $drupal_root.
if (!is_writable($drupal_root)) {
return drush_set_error('DRUSH_PATH_NO_WRITABLE', dt('Drupal root path is not writable.'));
}
// Create a directory 'core' if it does not already exist.
$project['path'] = 'drupal-' . $project['candidate_version'];
$project['full_project_path'] = $drupal_root . '/' . $project['path'];
if (!is_dir($project['full_project_path'])) {
drush_mkdir($project['full_project_path']);
}
// Create a list of directories to exclude from the update process.
$skip_list = array('sites', $project['path']);
// Add non-writable directories: we can't move them around.
// We will also use $items_to_test later for $version_control check.
$items_to_test = drush_scan_directory($drupal_root, '/.*/', array_merge(array('.', '..'), $skip_list), 0, FALSE, 'basename', 0, TRUE);
foreach (array_keys($items_to_test) as $item) {
if (is_dir($item) && !is_writable($item)) {
$skip_list[] = $item;
unset($items_to_test[$item]);
}
}
$project['skip_list'] = $skip_list;
// Move all files and folders in $drupal_root to the new 'core' directory
// except for the items in the skip list
_pm_update_move_files($drupal_root, $project['full_project_path'], $project['skip_list']);
// Set a context variable to indicate that rollback should reverse
// the _pm_update_move_files above.
drush_set_context('DRUSH_PM_DRUPAL_CORE', $project);
if (!$version_control = drush_pm_include_version_control($project['full_project_path'])) {
return FALSE;
}
$project['base_project_path'] = dirname($project['full_project_path']);
// Check we have a version control system, and it clears its pre-flight.
if (!$version_control->pre_update($project, $items_to_test)) {
return FALSE;
}
// Package handlers want the project directory in project_dir.
$project['project_dir'] = $project['path'];
// Update core.
if (pm_update_project($project, $version_control) === FALSE) {
return FALSE;
}
// Take the updated files in the 'core' directory that have been updated,
// and move all except for the items in the skip list back to
// the drupal root
_pm_update_move_files($project['full_project_path'], $drupal_root, $project['skip_list']);
drush_delete_dir($project['full_project_path']);
// Version control engines expect full_project_path to exist and be accurate.
$project['full_project_path'] = $project['base_project_path'];
// If there is a backup target, then find items
// in the backup target that do not exist at the
// drupal root. These are to be moved back.
if (array_key_exists('backup_target', $project)) {
_pm_update_move_files($project['backup_target'], $drupal_root, $project['skip_list'], FALSE);
_pm_update_move_files($project['backup_target'] . '/profiles', $drupal_root . '/profiles', array('default'), FALSE);
}
pm_update_complete($project, $version_control);
return TRUE;
}
/**
* Move some files from one location to another
*/
function _pm_update_move_files($src_dir, $dest_dir, $skip_list, $remove_conflicts = TRUE) {
$items_to_move = drush_scan_directory($src_dir, '/.*/', array_merge(array('.', '..'), $skip_list), 0, FALSE, 'filename', 0, TRUE);
foreach ($items_to_move as $filename => $info) {
if ($remove_conflicts) {
drush_delete_dir($dest_dir . '/' . basename($filename));
}
if (!file_exists($dest_dir . '/' . basename($filename))) {
$move_result = drush_move_dir($filename, $dest_dir . '/' . basename($filename));
}
}
return TRUE;
}
/**
* Update projects according to an array of releases and print the release notes
* for each project, following interactive confirmation from the user.
*
* @param $update_info
* An array of projects from the drupal.org update service, with an additional
* array key candidate_version that specifies the version to be installed.
*/
function pm_update_packages($update_info, $tmpfile) {
drush_include_engine('package_handler', drush_get_option('package-handler', 'wget'));
$drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT');
$print = '';
$status = array();
foreach($update_info as $project) {
$print .= $project['title'] . " [" . $project['name'] . '-' . $project['candidate_version'] . "], ";
$status[$project['status']] = $project['status'];
}
// We print the list of the projects that need to be updated.
if (isset($status[UPDATE_NOT_SECURE])) {
if (isset($status[UPDATE_NOT_CURRENT])) {
$title = (dt('Security and code updates will be made to the following projects:'));
}
else {
$title = (dt('Security updates will be made to the following projects:'));
}
}
else {
$title = (dt('Code updates will be made to the following projects:'));
}
$print = "$title " . (substr($print, 0, strlen($print)-2));
drush_print($print);
file_put_contents($tmpfile, "\n\n$print\n\n", FILE_APPEND);
// Print the release notes for projects to be updated.
if (drush_get_option('notes', FALSE)) {
drush_print('Obtaining release notes for above projects...');
_drush_pm_releasenotes(array_keys($update_info), TRUE, $tmpfile);
}
// We print some warnings before the user confirms the update.
drush_print();
if (drush_get_option('no-backup', FALSE)) {
drush_print(dt("Note: You have selected to not store backups."));
}
else {
drush_print(dt("Note: A backup of your project will be stored to backups directory if it is not managed by a supported version control system."));
drush_print(dt('Note: If you have made any modifications to any file that belongs to one of these projects, you will have to migrate those modifications after updating.'));
}
if(!drush_confirm(dt('Do you really want to continue with the update process?'))) {
return drush_user_abort();
}
// Now we start the actual updating.
foreach($update_info as $project) {
if (empty($project['path'])) {
return drush_set_error('DRUSH_PM_UPDATING_NO_PROJECT_PATH', dt('The !project project path is not available, perhaps the !type is enabled but has been deleted from disk.', array('!project' => $project['name'], '!type' => $project['project_type'])));
}
drush_log(dt('Starting to update !project code at !dir...', array('!project' => $project['title'], '!dir' => $project['path'])));
// Create the projects directory and base (parent) directory.
$project['full_project_path'] = $drupal_root . '/' . $project['path'];
// Check that the directory exists, and is where we expect it to be.
if (stripos($project['path'], $project['project_type']) === FALSE || !is_dir($project['full_project_path'])) {
return drush_set_error('DRUSH_PM_UPDATING_PATH_NOT_FOUND', dt('The !project directory could not be found within the !types directory at !full_project_path, perhaps the project is enabled but has been deleted from disk.', array('!project' => $project['name'], '!type' => $project['project_type'], '!full_project_path' => $project['full_project_path'])));
}
if (!$version_control = drush_pm_include_version_control($project['full_project_path'])) {
return FALSE;
}
$project['base_project_path'] = dirname($project['full_project_path']);
// Check we have a version control system, and it clears its pre-flight.
if (!$version_control->pre_update($project)) {
return FALSE;
}
// Package handlers want the name of the directory in project_dir.
// It may be different to the project name for pm-download.
// Perhaps we want here filename($project['full_project_path']).
$project['project_dir'] = $project['name'];
// Run update on one project.
if (pm_update_project($project, $version_control) === FALSE) {
return FALSE;
}
pm_update_complete($project, $version_control);
}
return TRUE;
}
/**
* Update one project -- a module, theme or Drupal core.
*
* @param $project
* The project to upgrade. $project['full_project_path'] must be set
* to the location where this project is stored.
*/
function pm_update_project($project, $version_control) {
// 1. If the version control engine is a proper vcs we need to remove project
// files in order to not have orphan files after update.
// 2. If the package-handler is cvs or git, it will remove upstream removed
// files and no orphans will exist after update.
// So, we must remove all files previous update if the directory is not a
// working copy of cvs or git but we don't need to remove them if the version
// control engine is backup, as it did already move the project out to the
// backup directory.
if (($version_control->engine != 'backup') && (drush_get_option('package-handler', 'wget') == 'wget')) {
// Find and unlink all files but the ones in the vcs control directories.
$skip_list = array('.', '..');
$skip_list = array_merge($skip_list, drush_version_control_reserved_files());
drush_scan_directory($project['full_project_path'], '/.*/', $skip_list, 'unlink', TRUE, 'filename', 0, TRUE);
}
// Add the project to a context so we can roll back if needed.
$updated = drush_get_context('DRUSH_PM_UPDATED');
$updated[] = $project;
drush_set_context('DRUSH_PM_UPDATED', $updated);
if (!package_handler_update_project($project, $project['releases'][$project['candidate_version']])) {
return drush_set_error('DRUSH_PM_UPDATING_FAILED', dt('Updating project !project failed. Attempting to roll back to previously installed version.', array('!project' => $project['name'])));
}
// If the version control engine is a proper vcs we also need to remove
// orphan directories.
if (($version_control->engine != 'backup') && (drush_get_option('package-handler', 'wget') == 'wget')) {
$files = drush_find_empty_directories($project['full_project_path'], $version_control->reserved_files());
array_map('drush_delete_dir', $files);
}
return TRUE;
}
/**
* Run the post-update hooks after updatecode is complete for one project.
*/
function pm_update_complete($project, $version_control) {
drush_print(dt('Project !project was updated successfully. Installed version is now !version.', array('!project' => $project['name'], '!version' => $project['candidate_version'])));
drush_command_invoke_all('pm_post_update', $project['name'], $project['releases'][$project['candidate_version']]);
$version_control->post_update($project);
}
function drush_pm_updatecode_rollback() {
$projects = array_reverse(drush_get_context('DRUSH_PM_UPDATED', array()));
foreach($projects as $project) {
drush_log(dt('Rolling back update of !project code ...', array('!project' => $project['title'])));
// Check we have a version control system, and it clears it's pre-flight.
if (!$version_control = drush_pm_include_version_control($project['path'])) {
return FALSE;
}
$version_control->rollback($project);
}
// Post rollback, we will do additional repair if the project is drupal core.
$drupal_core = drush_get_context('DRUSH_PM_DRUPAL_CORE', FALSE);
if ($drupal_core) {
$drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT');
_pm_update_move_files($drupal_core['full_project_path'], $drupal_root, $drupal_core['skip_list']);
drush_delete_dir($drupal_core['full_project_path']);
}
}
/**
* Return an array of updateable projects and fill $rows.
*
* Array of updateable projects is obtained from calculated project update
* status and $security_only flag.
*/
function pm_project_filter(&$update_info, &$rows, $security_only) {
$updateable = array();
foreach ($update_info as $key => $project) {
if (empty($project['title'])) {
continue;
}
switch($project['status']) {
case DRUSH_PM_REQUESTED_UPDATE:
$status = dt('Specified version available');
$project['updateable'] = TRUE;
break;
case DRUSH_PM_REQUESTED_CURRENT:
$status = dt('Specified version already installed');
break;
case DRUSH_PM_REQUESTED_PROJECT_NOT_PACKAGED:
$status = $project['status_msg'];
break;
case DRUSH_PM_REQUESTED_VERSION_NOT_FOUND:
$status = dt('Specified version not found');
break;
case DRUSH_PM_REQUESTED_PROJECT_NOT_FOUND:
$status = dt('Specified project not found');
break;
case DRUSH_PM_REQUESTED_PROJECT_NOT_UPDATEABLE:
$status = dt('Project has no enabled extensions and can\'t be updated');
break;
default:
$status = pm_update_filter($project);
break;
}
// Special checking: if drush decides that the candidate version is older
// than the installed version, then we will set the candidate version to
// the installed version.
if (isset($project['candidate_version'], $project['releases'][$project['candidate_version']], $project['releases'][$project['existing_version']])) {
if ($project['releases'][$project['candidate_version']]['date'] < $project['releases'][$project['existing_version']]['date']) {
$project['candidate_version'] = $project['existing_version'];
}
}
if (isset($project['locked'])) {
$status = $project['locked'] . " ($status)";
}
// Persist candidate_version in $update_info (plural).
if (empty($project['candidate_version'])) {
$update_info[$key]['candidate_version'] = $project['existing_version']; // Default to no change
}
else {
$update_info[$key]['candidate_version'] = $project['candidate_version'];
}
if (!empty($project['updateable'])) {
$updateable[$key] = $project;
// Find only security updates
if ($security_only && ($project['status'] != UPDATE_NOT_SECURE)) {
unset($updateable[$key]);
}
}
$rows[] = array($project['title'], $project['existing_version'], $update_info[$key]['candidate_version'], $status);
}
return $updateable;
}
/**
* Set a release to a recommended version (if available), and set as updateable.
*/
function pm_release_recommended(&$project) {
if (isset($project['recommended'])) {
$project['candidate_version'] = $project['recommended'];
$project['updateable'] = TRUE;
}
}
/**
* Get the a best release match for a requested update.
*
* @param $request A information array for the requested project
* @param $project A project information array for this project, as returned by an update service from pm_get_extensions()
*/
function pm_get_release($request, $project) {
$minor = '';
$version_patch_changed = '';
if ($request['version']) {
// The user specified a specific version - try to find that exact version
foreach($project['releases'] as $version => $release) {
// Ignore unpublished releases.
if ($release['status'] != 'published') {
continue;
}
// Straight match
if (!isset($recommended_version) && $release['version'] == $request['version']) {
$recommended_version = $version;
}
}
}
else {
// No version specified - try to find the best version we can
foreach($project['releases'] as $version => $release) {
// Ignore unpublished releases.
if ($release['status'] != 'published') {
continue;
}
// If we haven't found a recommended version yet, put the dev
// version as recommended and hope it gets overwritten later.
// Look for the 'latest version' if we haven't found it yet.
// Latest version is defined as the most recent version for the
// default major version.
if (!isset($latest_version) && $release['version_major'] == $project['default_major']) {
$latest_version = $version;
}
if (!isset($recommended_version) && $release['version_major'] == $project['default_major']) {
if ($minor != $release['version_patch']) {
$minor = $release['version_patch'];
$version_patch_changed = $version;
}
if (empty($release['version_extra']) && $minor == $release['version_patch']) {
$recommended_version = $version_patch_changed;
}
continue;
}
}
}
if (isset($recommended_version)) {
return $project['releases'][$recommended_version];
}
else if (isset($latest_version)) {
return $project['releases'][$latest_version];
}
else {
return false;
}
}

View File

@@ -0,0 +1,79 @@
<?php
/**
* @file Drush pm directory copy backup extension
*/
class drush_pm_version_control_backup implements drush_pm_version_control {
/**
* Implementation of pre_update().
*/
public function pre_update(&$project, $items_to_test = array()) {
if (drush_get_option('no-backup', FALSE)) {
return TRUE;
}
if ($backup_target = $this->prepare_backup_dir()) {
if ($project['project_type'] != 'core') {
$backup_target .= '/' . $project['project_type'] . 's';
drush_mkdir($backup_target);
}
$backup_target .= '/'. $project['name'];
// Save for rollback or notifications.
$project['backup_target'] = $backup_target;
// Move or copy to backup target based in package-handler.
if (drush_get_option('package-handler', 'wget') == 'wget') {
if (drush_move_dir($project['full_project_path'], $backup_target)) {
return TRUE;
}
}
// cvs or git.
elseif (drush_copy_dir($project['full_project_path'], $backup_target)) {
return TRUE;
}
return drush_set_error('DRUSH_PM_BACKUP_FAILED', dt('Failed to backup project directory !project to !backup_target', array('!project' => $project['full_project_path'], '!backup_target' => $backup_target)));
}
}
/**
* Implementation of rollback().
*/
public function rollback($project) {
if (drush_get_option('no-backup', FALSE)) {
return;
}
if (drush_move_dir($project['backup_target'], $project['full_project_path'], TRUE)) {
return drush_log(dt("Backups were restored successfully."), 'ok');
}
return drush_set_error('DRUSH_PM_BACKUP_ROLLBACK_FAILED', dt('Could not restore backup and rollback from failed upgrade. You will need to resolve manually.'));
}
/**
* Implementation of post_update().
*/
public function post_update($project) {
if (drush_get_option('no-backup', FALSE)) {
return;
}
if ($project['backup_target']) {
drush_log(dt("Backups were saved into the directory !backup_target.", array('!backup_target' => $project['backup_target'])), 'ok');
}
}
/**
* Implementation of post_download().
*/
public function post_download($project) {
// NOOP
}
// Helper for pre_update.
public function prepare_backup_dir($subdir = NULL) {
return drush_prepare_backup_dir($subdir);
}
public static function reserved_files() {
return array();
}
}

View File

@@ -0,0 +1,134 @@
<?php
/**
* @file Drush pm Bazaar extension
*/
class drush_pm_version_control_bzr implements drush_pm_version_control {
/**
* Implementation of pre_update().
*
* Check that the project or drupal core directory looks clean
*/
public function pre_update(&$project, $items_to_test = array()) {
// Bazaar needs a list of items to test within the given project.
// If $items_to_test is empty we need to force it to test the project
// directory itself --once we've cd'ed to it.
if (empty($items_to_test)) {
$items_to_test = array('.' => '.');
}
$args = array_keys($items_to_test);
array_unshift($args, 'bzr status --short' . str_repeat(' %s', count($args)));
array_unshift($args, $project['full_project_path']);
if (call_user_func_array('drush_shell_cd_and_exec', $args)) {
$output = preg_grep('/^[\sRCP][\sNDKM][\s\*]/', drush_shell_exec_output());
if (!empty($output)) {
return drush_set_error('DRUSH_PM_BZR_LOCAL_CHANGES', dt("The Bazaar working copy at !path appears to have uncommitted changes (see below). Please commit or revert these changes before continuing:\n!output", array('!path' => $project['full_project_path'], '!output' => implode("\n", $output))));
}
}
else {
return drush_set_error('DRUSH_PM_BZR_NOT_FOUND', dt("Drush was unable to get the bzr status on !path. Check that you have Bazaar \ninstalled and that this directory is a Bazaar working copy.\nThe specific errors are below:\n!errors", array('!path' => $project['full_project_path'], '!errors' => implode("\n", drush_shell_exec_output()))));
}
return TRUE;
}
/**
* Implementation of rollback().
*/
public function rollback($project) {
if (drush_shell_exec('bzr revert %s', $project['full_project_path'])) {
$output = drush_shell_exec_output();
if (!empty($output)) {
return drush_set_error('DRUSH_PM_BZR_LOCAL_CHANGES', dt("The Bazaar working copy at !path appears to have uncommitted changes (see below). Please commit or revert these changes before continuing:\n!output", array('!path' => $project['full_project_path'], '!output' => implode("\n", $output))));
}
}
else {
return drush_set_error('DRUSH_PM_BZR_NOT_FOUND', dt("Drush was unable to get the Bazaar status on !path. Check that you have Bazaar \ninstalled and that this directory is a Bazaar working copy.\nThe specific errors are below:\n!errors", array('!path' => $project['full_project_path'], '!errors' => implode("\n", drush_shell_exec_output()))));
}
}
/**
* Implementation of post_update().
*/
public function post_update($project) {
if ($this->sync($project)) {
// Only attempt commit on a sucessful sync
$this->commit($project);
}
}
/**
* Implementation of post_download().
*/
public function post_download($project) {
if ($this->sync($project)) {
// Only attempt commit on a sucessful sync
$this->commit($project);
}
}
/**
* Automatically add any unversioned files to Bazaar and remove any files
* that have been deleted on the file system
*/
private function sync($project) {
if (drush_get_option('bzrsync')) {
$errors = '';
$root = array();
if (drush_shell_exec('bzr status --short %s', $project['full_project_path'])) {
$output = drush_shell_exec_output();
// All paths returned by bzr status are relative to the repository root.
if (drush_shell_exec('bzr root %s', $project['full_project_path'])) {
$root = drush_shell_exec_output();
}
foreach ($output as $line) {
if (preg_match('/^\?\s+(.*)/', $line, $matches)) {
$path = $root[0] .'/'. $matches[1];
if (!drush_shell_exec('bzr add --no-recurse %s', $path)) {
$errors .= implode("\n", drush_shell_exec_output());
}
}
else if (preg_match('/^\s+D\s+(.*)/', $line, $matches)) {
$path = $root[0] .'/'. $matches[1];
if (!drush_shell_exec('bzr remove %s', $path)) {
$errors .= implode("\n", drush_shell_exec_output());
}
}
}
if (!empty($errors)) {
return drush_set_error('DRUSH_PM_BZR_SYNC_PROBLEMS', dt("Problems were encountered adding or removing files to/from Bazaar.\nThe specific errors are below:\n!errors", array('!errors' => $errors)));
}
}
else {
return drush_set_error('DRUSH_PM_BZR_NOT_FOUND', dt("Drush was unable to get the bzr status. Check that you have Bazaar \ninstalled and that the site is a Bazaar working copy.\nThe specific errors are below:\n!errors", array('!errors' => implode("\n", drush_shell_exec_output()))));
}
return TRUE;
}
}
/**
* Automatically commit changes to the repository
*/
private function commit($project) {
if (drush_get_option('bzrcommit')) {
$message = drush_get_option('bzrmessage');
if (empty($message)) {
$message = dt("Drush automatic commit.\nProject: @name @type\nCommand: @arguments", array('@name' => $project['name'], '@type' => $project['project_type'], '@arguments' => implode(' ', $_SERVER['argv'])));
}
if (drush_shell_exec('bzr commit --message=%s %s', $message, $project['full_project_path'])) {
drush_log(dt('Project committed to Bazaar successfully'), 'ok');
}
else {
drush_set_error('DRUSH_PM_BZR_COMMIT_PROBLEMS', dt("Problems were encountered committing your changes to Bazaar.\nThe specific errors are below:\n!errors", array('!errors' => implode("\n", drush_shell_exec_output()))));
}
}
else {
drush_print(dt("You should consider committing the new code to your Bazaar repository.\nIf this version becomes undesireable, use Bazaar to roll back."));
}
}
public static function reserved_files() {
return array('.bzr', '.bzrignore', '.bzrtags');
}
}

View File

@@ -0,0 +1,135 @@
<?php
/**
* @file Drush pm SVN extension
*/
class drush_pm_version_control_svn implements drush_pm_version_control {
/**
* Implementation of pre_update().
*/
public function pre_update(&$project, $items_to_test = array()) {
// If items to test is empty, test everything; otherwise, pass just
// the list of files to test to svn status.
$args = array_keys($items_to_test);
array_unshift($args, 'svn status '. drush_get_option('svnstatusparams') . str_repeat('%s ', count($args)));
array_unshift($args, $project['full_project_path']);
if (call_user_func_array('drush_shell_cd_and_exec', $args)) {
$output = preg_grep('/^[ ACDMRX?!~][ CM][ L][ +][ SX][ K]/', drush_shell_exec_output());
if (!empty($output)) {
return drush_set_error('DRUSH_PM_SVN_LOCAL_CHANGES', dt("The SVN working copy at !path appears to have uncommitted changes (see below). Please commit or revert these changes before continuing:\n!output", array('!path' => $project['full_project_path'], '!output' => implode("\n", $output))));
}
}
else {
return drush_set_error('DRUSH_PM_SVN_NOT_FOUND', dt("Drush was unable to get the svn status on !path.\nThe specific errors are below:\n!errors", array('!path' => $project['full_project_path'], '!errors' => implode("\n", drush_shell_exec_output()))));
}
// Check for incoming updates
$args = array_keys($items_to_test);
array_unshift($args, 'svn status -u '. drush_get_option('svnstatusparams') . str_repeat('%s ', count($args)));
array_unshift($args, $project['full_project_path']);
if (call_user_func_array('drush_shell_cd_and_exec', $args)) {
$output = preg_grep('/\*/', drush_shell_exec_output());
if (!empty($output)) {
return drush_set_error('DRUSH_PM_SVN_REMOTE_CHANGES', dt("The SVN working copy at !path appears to be out of date with the repository (see below). Please run 'svn update' to pull down changes before continuing:\n!output", array('!path' => $project['full_project_path'], '!output' => implode("\n", $output))));
}
}
else {
return drush_set_error('DRUSH_PM_SVN_NOT_FOUND', dt("Drush was unable to get the svn remote status on !path. Check that you have connectivity to the repository.\nThe specific errors are below:\n!errors", array('!path' => $project['full_project_path'], '!errors' => implode("\n", drush_shell_exec_output()))));
}
return TRUE;
}
/**
* Implementation of rollback().
*/
public function rollback($project) {
if (drush_shell_exec('svn revert '. drush_get_option('svnrevertparams') .' '. $project['full_project_path'])) {
$output = drush_shell_exec_output();
if (!empty($output)) {
return drush_set_error('DRUSH_PM_SVN_LOCAL_CHANGES', dt("The SVN working copy at !path appears to have uncommitted changes (see below). Please commit or revert these changes before continuing:\n!output", array('!path' => $project['full_project_path'], '!output' => implode("\n", $output))));
}
}
else {
return drush_set_error('DRUSH_PM_SVN_NOT_FOUND', dt("Drush was unable to get the svn status on !path. Check that you have Subversion \ninstalled and that this directory is a subversion working copy.\nThe specific errors are below:\n!errors", array('!path' => $project['full_project_path'], '!errors' => implode("\n", drush_shell_exec_output()))));
}
}
/**
* Implementation of post_update().
*/
public function post_update($project) {
if ($this->sync($project)) {
// Only attempt commit on a sucessful sync
$this->commit($project);
}
}
/**
* Implementation of post_download().
*/
public function post_download($project) {
if ($this->sync($project)) {
// Only attempt commit on a sucessful sync
$this->commit($project);
}
}
/**
* Automatically add any unversioned files to Subversion and remove any files
* that have been deleted on the file system
*/
private function sync($project) {
if (drush_get_option('svnsync')) {
$errors = '';
if (drush_shell_exec('svn status '. drush_get_option('svnstatusparams') .' '. $project['full_project_path'])) {
$output = drush_shell_exec_output();
foreach ($output as $line) {
if (preg_match('/^\? *(.*)/', $line, $matches)) {
if (!drush_shell_exec('svn add '. drush_get_option('svnaddparams') .' '. $matches[1])) {
$errors .= implode("\n", drush_shell_exec_output());
}
}
if (preg_match('/^\! *(.*)/', $line, $matches)) {
if (!drush_shell_exec('svn remove '. drush_get_option('svnremoveparams') .' '. $matches[1])) {
$errors .= implode("\n", drush_shell_exec_output());
}
}
}
if (!empty($errors)) {
return drush_set_error('DRUSH_PM_SVN_SYNC_PROBLEMS', dt("Problems were encountered adding or removing files to/from this SVN working copy.\nThe specific errors are below:\n!errors", array('!errors' => $errors)));
}
}
else {
return drush_set_error('DRUSH_PM_SVN_NOT_FOUND', dt("Drush was unable to get the svn status on !path. Check that you have Subversion \ninstalled and that this directory is a subversion working copy.\nThe specific errors are below:\n!errors", array('!path' => $project['full_project_path'], '!errors' => implode("\n", drush_shell_exec_output()))));
}
return TRUE;
}
}
/**
* Automatically commit changes to the repository
*/
private function commit($project) {
if (drush_get_option('svncommit')) {
$message = drush_get_option('svnmessage');
if (empty($message)) {
$message = dt("Drush automatic commit: \n") . implode(' ', $_SERVER['argv']);
}
if (drush_shell_exec('svn commit '. drush_get_option('svncommitparams') .' -m "'. $message .'" '. $project['full_project_path'])) {
drush_log(dt('Project committed to Subversion successfully'), 'ok');
}
else {
drush_set_error('DRUSH_PM_SVN_COMMIT_PROBLEMS', dt("Problems were encountered committing your changes to Subversion.\nThe specific errors are below:\n!errors", array('!errors' => implode("\n", drush_shell_exec_output()))));
}
}
else {
drush_print(dt("You should consider committing the new code to your Subversion repository.\nIf this version becomes undesireable, use Subversion to roll back."));
}
}
public static function reserved_files() {
return array('.svn');
}
}