From fef6e997abc5463f8c050f2283161a0cbff79ad3 Mon Sep 17 00:00:00 2001 From: TheMetMan Date: Mon, 26 Jun 2023 17:24:24 +0100 Subject: [PATCH 1/9] Add command to update Modules, Themes and Layouts (#290) This first phase updates modules, themes and layouts. It passes PHPCS. Further enhancements will be needed before ready for merging into 1.x-1.x Co-authored-by: Martin Price --- commands/update.bee.inc | 72 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/commands/update.bee.inc b/commands/update.bee.inc index 58ca49b0..989065f1 100644 --- a/commands/update.bee.inc +++ b/commands/update.bee.inc @@ -19,6 +19,18 @@ function update_bee_command() { 'bee update-db' => bt('Show a list of any pending database updates. You will then be prompted to apply them.'), ), ), + 'update' => array( + 'description' => bt('Updates backdrop, modules, themes and layouts with new releases'), + 'callback' => 'update_bee_callback', + 'aliases' => array('up', 'pm-update'), + 'bootstrap' => BEE_BOOTSTRAP_FULL, + 'optional_arguments' => array('project'), + 'multiple_argument' => 'project', + 'examples' => array( + 'bee update' => bt('Update everything with a new release.'), + 'bee update webform tatsu' => bt('Updates the Webform module and Tatsu theme only'), + ), + ), ); } @@ -40,7 +52,6 @@ function update_db_bee_callback() { bee_message(bt('There are no pending database updates.'), 'info'); return; } - // Process the list of updates. foreach ($pending as $module => $updates) { if (!isset($updates['start'])) { @@ -101,3 +112,62 @@ function update_db_bee_callback() { bee_message(bt('All pending updates applied.'), 'success'); } } + +/** + * Command callback: Show, and apply, module and theme updates. + * + * @todo Add core update. + * @todo Consider a way to download first, check the download has worked before delete. + * + */ +function update_bee_callback() { + global $_bee_backdrop_root; + require_once $_bee_backdrop_root . '/core/includes/file.inc'; + $data = NULL; + if ($available = update_get_available(TRUE)) { + module_load_include('inc', 'update', 'update.compare'); + $data = update_calculate_project_data($available); + } + if ($data != NULL) { + foreach ($data as $item) { + if ($item['name'] == 'backdrop') { + unset($data['backdrop']); + } + if ($item['existing_version'] == $item['latest_version']) { + unset($data[$item['name']]); + } + } + } + if ($data != NULL) { + foreach ($data as $item) { + $rows[] = array( + array('value' => $item['name']), + array('value' => $item['existing_version']), + array('value' => $item['latest_version']), + ); + } + bee_render_text(array('value' => bt("These are the items being updated:\n"))); + bee_render_table(array( + 'rows' => $rows, + 'header' => array( + array('value' => bt('Module')), + array('value' => bt('Existing')), + array('value' => bt('Latest')), + ), + )); + // Prompt to continue. + if (!bee_confirm(bt('Would you like to continue?'), FALSE)) { + return; + } + foreach ($data as $item) { + $folder = backdrop_get_path($item['project_type'], $item['name']); + if (is_dir($folder)) { + bee_delete($folder); + } + download_bee_callback(array('projects' => array($item['name']),), []); + echo ''; + } + } else { + bee_message(bt('No Modules or Themes to Update')); + } +} From 9316f13174accc02d710862451b6d125ee1aef2e Mon Sep 17 00:00:00 2001 From: Martin Price Date: Mon, 26 Jun 2023 17:52:59 +0100 Subject: [PATCH 2/9] Add support for command level short form options (#286) Tests have passed locally. #287 is still causing problems on workflow testing. PHPCS is fine. * Add support for command level short form options Support short form options in commands and status command. * Add other short options as suggested. --- commands/download.bee.inc | 3 +++ commands/help.bee.inc | 4 +++- commands/install.bee.inc | 2 ++ commands/projects.bee.inc | 3 +++ commands/status.bee.inc | 4 +++- includes/command.inc | 9 ++++++++- 6 files changed, 22 insertions(+), 3 deletions(-) diff --git a/commands/download.bee.inc b/commands/download.bee.inc index 417762b4..ebbb44ff 100644 --- a/commands/download.bee.inc +++ b/commands/download.bee.inc @@ -20,9 +20,11 @@ function download_bee_command() { 'options' => array( 'hide-progress' => array( 'description' => bt('Hide the download progress bar.'), + 'short' => 'h', ), 'allow-multisite-copy' => array( 'description' => bt('Override the check that would prevent the project being downloaded to a multisite site if the project exists in the shared project directory.'), + 'short' => 'f', ), ), 'aliases' => array('dl', 'pm-download'), @@ -44,6 +46,7 @@ function download_bee_command() { 'options' => array( 'hide-progress' => array( 'description' => bt('Hide the download progress bar.'), + 'short' => 'h', ), ), 'aliases' => array('dl-core'), diff --git a/commands/help.bee.inc b/commands/help.bee.inc index 92f711ad..9cb4e948 100644 --- a/commands/help.bee.inc +++ b/commands/help.bee.inc @@ -261,7 +261,9 @@ function help_bee_command_help(array $descriptor) { $rows = array(); foreach ($descriptor['options'] as $option_name => $option) { $value = !empty($option['value']) ? '=' . strtoupper($option['value']) : ''; - + if (isset($option['short'])) { + $option_name .= ', -' . $option['short']; + } $rows[] = array( array( 'value' => '--' . $option_name . $value, diff --git a/commands/install.bee.inc b/commands/install.bee.inc index 536d46bd..0f154830 100644 --- a/commands/install.bee.inc +++ b/commands/install.bee.inc @@ -64,9 +64,11 @@ function install_bee_command() { ), 'no-clean-urls' => array( 'description' => bt('Disable clean URLs.'), + 'short' >= 'n', ), 'auto' => array( 'description' => bt('Perform an automatic (i.e. non-interactive) installation. Any options not explicitly provided to the command will use default values, except the database connection string which will always prompt when not provided.'), + 'short' >= 'a', ), ), 'aliases' => array('si', 'site-install'), diff --git a/commands/projects.bee.inc b/commands/projects.bee.inc index cb045bc7..97b20d78 100644 --- a/commands/projects.bee.inc +++ b/commands/projects.bee.inc @@ -42,6 +42,7 @@ function projects_bee_command() { 'options' => array( 'no-dependency-checking' => array( 'description' => bt('Disable dependency-checking and enable module(s) regardless. This could cause problems if there are missing dependencies. Use with caution.'), + 'short' >= 'n', ), ), 'aliases' => array('en', 'pm-enable'), @@ -63,6 +64,7 @@ function projects_bee_command() { 'options' => array( 'no-dependency-checking' => array( 'description' => bt('Disable dependency-checking and disable module(s) regardless. This could cause problems if there are other enabled modules that depend on this one. Use with caution.'), + 'short' >= 'n', ), ), 'aliases' => array('dis', 'pm-disable'), @@ -84,6 +86,7 @@ function projects_bee_command() { 'options' => array( 'no-dependency-checking' => array( 'description' => bt('Disable dependency-checking and uninstall module(s) regardless. This could cause problems if there are other installed modules that depend on this one. Use with caution.'), + 'short' >= 'n', ), ), 'aliases' => array('pmu', 'pm-uninstall'), diff --git a/commands/status.bee.inc b/commands/status.bee.inc index d505d43a..c31e2892 100644 --- a/commands/status.bee.inc +++ b/commands/status.bee.inc @@ -16,6 +16,7 @@ function status_bee_command() { 'options' => array( 'show-password' => array( 'description' => bt('Show the database password.'), + 'short' => 'p', ), ), 'aliases' => array('st', 'info', 'core-status'), @@ -81,9 +82,10 @@ function status_bee_callback($arguments, $options) { array('value' => bt('Database username')), array('value' => rawurldecode($info['username'])), ); + $status_show_password = (isset($options['show-password']) || isset($options['p'])); $rows[] = array( array('value' => bt('Database password')), - array('value' => isset($options['show-password']) ? rawurldecode($info['password']) : '**********'), + array('value' => $status_show_password ? rawurldecode($info['password']) : '**********'), ); $rows[] = array( array('value' => bt('Database host')), diff --git a/includes/command.inc b/includes/command.inc index 1c08f19f..a6243ce5 100644 --- a/includes/command.inc +++ b/includes/command.inc @@ -282,8 +282,15 @@ function bee_validate_command(array $descriptor) { if (isset($descriptor['options'])) { // Remove any provided options that aren't used by the command. foreach ($_bee_options as $name => $value) { + // Check for long form command options. if (!isset($descriptor['options'][$name])) { - unset($_bee_options[$name]); + // Check for short form command options. + foreach ($descriptor['options'] as $command_option) { + if (!isset($command_option['short']) || $command_option['short'] != $name) { + // Remove any that don't match either long or short form options. + unset($_bee_options[$name]); + } + } } } } From d36840887e5ed2a0d83b45d956279ba2b955ee1f Mon Sep 17 00:00:00 2001 From: Martin Price Date: Tue, 11 Jul 2023 08:30:53 +0100 Subject: [PATCH 3/9] Remove BWPanda as maintainer --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e10d3cba..91b6f463 100644 --- a/README.md +++ b/README.md @@ -55,14 +55,18 @@ https://github.com/backdrop-contrib/bee/issues. ## Current Maintainers -- [Peter Anderson](https://github.com/BWPanda) - [Martin Price](https://github.com/yorkshire-pudding) - [System Horizons](https://www.systemhorizons.co.uk) +- Collaboration and co-maintainers welcome! ## Credits - Originally written for Backdrop CMS by [Geoff St. Pierre](https://github.com/serundeputy) (originally called 'Backdrop Console (a.k.a. `b`)'). +- Grateful thanks goes to previous maintainers and collaborators who have +helped bring Bee to where it is today. See the +[list of contributors](https://github.com/backdrop-contrib/bee/graphs/contributors) +for details. - Inspired by [Drush](https://github.com/drush-ops/drush). - [Bee icon](https://thenounproject.com/aomam/collection/bee-emoticons-line/?i=2257433) by AomAm from [the Noun Project](http://thenounproject.com). From ad751b07b98c723cca8258b601a37b3586d81774 Mon Sep 17 00:00:00 2001 From: Joseph Flatt Date: Wed, 22 Nov 2023 01:05:49 -0800 Subject: [PATCH 4/9] Issue #301: Added an argument to the update command to limit the projects that are updated. (#345) --- commands/update.bee.inc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/commands/update.bee.inc b/commands/update.bee.inc index 989065f1..cc255a81 100644 --- a/commands/update.bee.inc +++ b/commands/update.bee.inc @@ -24,8 +24,11 @@ function update_bee_command() { 'callback' => 'update_bee_callback', 'aliases' => array('up', 'pm-update'), 'bootstrap' => BEE_BOOTSTRAP_FULL, - 'optional_arguments' => array('project'), - 'multiple_argument' => 'project', + 'arguments' => array( + 'projects' => bt('One or more projects to update.'), + ), + 'optional_arguments' => array('projects'), + 'multiple_argument' => 'projects', 'examples' => array( 'bee update' => bt('Update everything with a new release.'), 'bee update webform tatsu' => bt('Updates the Webform module and Tatsu theme only'), @@ -120,7 +123,7 @@ function update_db_bee_callback() { * @todo Consider a way to download first, check the download has worked before delete. * */ -function update_bee_callback() { +function update_bee_callback($arguments) { global $_bee_backdrop_root; require_once $_bee_backdrop_root . '/core/includes/file.inc'; $data = NULL; @@ -133,6 +136,9 @@ function update_bee_callback() { if ($item['name'] == 'backdrop') { unset($data['backdrop']); } + if (!empty($arguments['projects']) && !in_array($item['name'], $arguments['projects'])) { + unset($data[$item['name']]); + } if ($item['existing_version'] == $item['latest_version']) { unset($data[$item['name']]); } From a04a6f919a8b339839892c83254551828153761c Mon Sep 17 00:00:00 2001 From: Joseph Flatt Date: Thu, 23 Nov 2023 01:58:40 -0800 Subject: [PATCH 5/9] Issue #303: Added a check that the latest_release is set on projects. (#346) --- commands/update.bee.inc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/commands/update.bee.inc b/commands/update.bee.inc index cc255a81..bf68300d 100644 --- a/commands/update.bee.inc +++ b/commands/update.bee.inc @@ -135,12 +135,19 @@ function update_bee_callback($arguments) { foreach ($data as $item) { if ($item['name'] == 'backdrop') { unset($data['backdrop']); + continue; } if (!empty($arguments['projects']) && !in_array($item['name'], $arguments['projects'])) { unset($data[$item['name']]); + continue; + } + if (!isset($item['latest_version'])) { + unset($data[$item['name']]); + continue; } if ($item['existing_version'] == $item['latest_version']) { unset($data[$item['name']]); + continue; } } } From dfd8683e90b7da5726364236c47a46aca20b2306 Mon Sep 17 00:00:00 2001 From: Anthony Nemirovsky Date: Sat, 9 Dec 2023 04:52:55 -0800 Subject: [PATCH 6/9] Issue #300: Add support for downloading only security updates to the `update` command (#349) Adds support for a --security-only OR -s flag to allow updates to be run just for modules with security releases. --- commands/update.bee.inc | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/commands/update.bee.inc b/commands/update.bee.inc index bf68300d..285e320c 100644 --- a/commands/update.bee.inc +++ b/commands/update.bee.inc @@ -29,8 +29,15 @@ function update_bee_command() { ), 'optional_arguments' => array('projects'), 'multiple_argument' => 'projects', + 'options' => array( + 'security-only' => array( + 'description' => bt('Only update modules that have security updates available.'), + 'short' => 's', + ), + ), 'examples' => array( 'bee update' => bt('Update everything with a new release.'), + 'bee update --security-only' => bt('Update everything that is a security update only'), 'bee update webform tatsu' => bt('Updates the Webform module and Tatsu theme only'), ), ), @@ -123,7 +130,7 @@ function update_db_bee_callback() { * @todo Consider a way to download first, check the download has worked before delete. * */ -function update_bee_callback($arguments) { +function update_bee_callback($arguments, $options) { global $_bee_backdrop_root; require_once $_bee_backdrop_root . '/core/includes/file.inc'; $data = NULL; @@ -149,6 +156,9 @@ function update_bee_callback($arguments) { unset($data[$item['name']]); continue; } + if ((isset($options['security-only']) || isset($options['s'])) && $item['status'] !== UPDATE_NOT_SECURE) { + unset($data[$item['name']]); + } } } if ($data != NULL) { From ffd8ea30065d37461e800c1e1817d817fb35aa93 Mon Sep 17 00:00:00 2001 From: Anthony Nemirovsky Date: Mon, 18 Dec 2023 12:17:59 -0800 Subject: [PATCH 7/9] Issue #350: Add an update-list command (#351) Lists the available updates either as table or list and optionally list just security releases. --- commands/update.bee.inc | 147 +++++++++++++++++++++++++++++++--------- 1 file changed, 115 insertions(+), 32 deletions(-) diff --git a/commands/update.bee.inc b/commands/update.bee.inc index 285e320c..f6725fc9 100644 --- a/commands/update.bee.inc +++ b/commands/update.bee.inc @@ -41,6 +41,32 @@ function update_bee_command() { 'bee update webform tatsu' => bt('Updates the Webform module and Tatsu theme only'), ), ), + 'update-list' => array( + 'description' => bt('Lists available updates for backdrop, modules, themes and layouts with new releases'), + 'callback' => 'update_list_bee_callback', + 'aliases' => array('ups', 'pm-updatestatus', 'update-status', 'upl'), + 'bootstrap' => BEE_BOOTSTRAP_FULL, + 'arguments' => array( + 'projects' => bt('One or more projects to list updates for.'), + ), + 'optional_arguments' => array('projects'), + 'multiple_argument' => 'projects', + 'options' => array( + 'security-only' => array( + 'description' => bt('Only list updates for modules that have security updates available.'), + 'short' => 's', + ), + 'format' => array( + 'description' => bt('Format to output update information in. Options are "table" (default), "list".'), + 'value' => bt('table'), + ), + ), + 'examples' => array( + 'bee update-list' => bt('List updates for everything with a new release.'), + 'bee update-list --security-only' => bt('List only security updates for everything with a new release.'), + 'bee update-list webform tatsu' => bt('List updates for the Webform module and Tatsu theme only'), + ), + ), ); } @@ -133,6 +159,57 @@ function update_db_bee_callback() { function update_bee_callback($arguments, $options) { global $_bee_backdrop_root; require_once $_bee_backdrop_root . '/core/includes/file.inc'; + $data = update_bee_get_available_updates($arguments, $options); + if ($data != NULL) { + update_bee_render_table_output($data); + // Prompt to continue. + if (!bee_confirm(bt('Would you like to continue?'), FALSE)) { + return; + } + foreach ($data as $item) { + $folder = backdrop_get_path($item['project_type'], $item['name']); + if (is_dir($folder)) { + bee_delete($folder); + } + download_bee_callback(array('projects' => array($item['name']),), []); + echo ''; + } + } else { + bee_message(bt('No Modules or Themes to Update')); + } +} + +/** + * Command callback: Show module and theme updates. + */ +function update_list_bee_callback(array $arguments, array $options) { + $data = update_bee_get_available_updates($arguments, $options); + $is_list_format = isset($options['format']) && $options['format'] === 'list'; + if ($data == NULL) { + if (!$is_list_format) { + bee_message(bt('No Modules or Themes to Update')); + } + return; + } + if ($is_list_format) { + update_bee_render_list_output($data); + } else { + update_bee_render_table_output($data); + } +} + +/** + * Get an array of available project updates. + * + * @param array $arguments + * A list of arguments passed to the command. + * @param array $options + * A list of options passed to the command. + * + * @return array|NULL + * An array of projects with updates available, or NULL if there are none. + */ +function update_bee_get_available_updates(array $arguments, array $options) { $data = NULL; if ($available = update_get_available(TRUE)) { module_load_include('inc', 'update', 'update.compare'); @@ -156,41 +233,47 @@ function update_bee_callback($arguments, $options) { unset($data[$item['name']]); continue; } - if ((isset($options['security-only']) || isset($options['s'])) && $item['status'] !== UPDATE_NOT_SECURE) { + if (isset($options['security-only']) && $item['status'] !== UPDATE_NOT_SECURE) { unset($data[$item['name']]); } } } - if ($data != NULL) { - foreach ($data as $item) { - $rows[] = array( - array('value' => $item['name']), - array('value' => $item['existing_version']), - array('value' => $item['latest_version']), - ); - } - bee_render_text(array('value' => bt("These are the items being updated:\n"))); - bee_render_table(array( - 'rows' => $rows, - 'header' => array( - array('value' => bt('Module')), - array('value' => bt('Existing')), - array('value' => bt('Latest')), - ), - )); - // Prompt to continue. - if (!bee_confirm(bt('Would you like to continue?'), FALSE)) { - return; - } - foreach ($data as $item) { - $folder = backdrop_get_path($item['project_type'], $item['name']); - if (is_dir($folder)) { - bee_delete($folder); - } - download_bee_callback(array('projects' => array($item['name']),), []); - echo ''; - } - } else { - bee_message(bt('No Modules or Themes to Update')); + return $data; +} + +/** + * Render available updates as a table. + * + * @param array $data + * An array of projects with updates available. + */ +function update_bee_render_table_output(array $data) { + foreach ($data as $item) { + $rows[] = array( + array('value' => $item['name']), + array('value' => $item['existing_version']), + array('value' => $item['latest_version']), + ); + } + bee_render_text(array('value' => bt("These are the items being updated:\n"))); + bee_render_table(array( + 'rows' => $rows, + 'header' => array( + array('value' => bt('Module')), + array('value' => bt('Existing')), + array('value' => bt('Latest')), + ), + )); +} + +/** + * Render available updates as a list. + * + * @param array $data + * An array of projects with updates available. + */ +function update_bee_render_list_output(array $data) { + foreach ($data as $item) { + bee_render_text(array('value' => $item['name'])); } } From 3d96869be9f64d7fed01bb1fa9fbdb1122f35628 Mon Sep 17 00:00:00 2001 From: Martin Price Date: Thu, 9 May 2024 09:08:09 +0100 Subject: [PATCH 8/9] Allow switch bee version in lando with rebuild --- .lando.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.lando.yml b/.lando.yml index 446f2560..eba6c509 100644 --- a/.lando.yml +++ b/.lando.yml @@ -9,6 +9,14 @@ config: bee: false services: appserver: + build_as_root: + # As bee is now added by default, we need to remove any existing versions + # of bee if you tested a versioned install of bee by adding in the config + # section above. + # Remove the parent folder if it exists. + - rm -rf /var/www/.bee + # Remove the symlink if it exists. + - rm -f /usr/local/bin/bee build: # Make symlink for `bee` pointing to this version. - ln -s /app/bee.php /usr/local/bin/bee From 5f242085938ef252d191d3a37df69d0091ed0d8b Mon Sep 17 00:00:00 2001 From: Martin Price Date: Sat, 26 Apr 2025 16:22:14 +0100 Subject: [PATCH 9/9] Handle terminal width better by providing a default if can't use tput cols --- includes/render.inc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/includes/render.inc b/includes/render.inc index 0b729a58..f4984e69 100644 --- a/includes/render.inc +++ b/includes/render.inc @@ -375,12 +375,13 @@ function bee_get_column_widths($rows, $header, $delimiter, $delimiter_left, $del $table_width += mb_strlen((string) $delimiter_right); $table_width += (count($widths) - 1) * mb_strlen((string) $delimiter); - // Adjust the width of the widest column to fit in the terminal. If a command - // outputting a table is run in a non-interactive shell (e.g. as part of an - // SSH command) then 'tput cols' on its own will create an error. This - // provides an alternative if 'tput cols' create an error. - $terminal_width = exec('if tput cols &>/dev/null; then echo $(tput cols); else $(echo $COLUMNS); fi'); + // Get the terminal width or set a reasonable default. + $terminal_width = (int) exec('echo "$(tput cols 2>/dev/null)"'); + if (!is_integer($terminal_width) || $terminal_width == 0) { + $terminal_width = 140; + } bee_instant_message(bt('The terminal width is: ') . $terminal_width, 'debug'); + // Adjust the width of the widest column to fit in the terminal. if ($terminal_width && $table_width > $terminal_width) { $diff = $table_width - $terminal_width; $widths[$widest_column] -= $diff;