From f16787c75513b61aa891de1e32ebefbcc8b6248d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 12:29:58 +0000 Subject: [PATCH 1/4] Initial plan From c5bd2b3377509794ed184e3fdf70578890541a92 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 12:34:47 +0000 Subject: [PATCH 2/4] Add optional package name argument to wp package update command Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/package-update.feature | 77 +++++++++++++++++++++++++++++++++ src/Package_Command.php | 49 ++++++++++++++++++++- 2 files changed, 124 insertions(+), 2 deletions(-) diff --git a/features/package-update.feature b/features/package-update.feature index c5981277..b6c07898 100644 --- a/features/package-update.feature +++ b/features/package-update.feature @@ -98,3 +98,80 @@ Feature: Update WP-CLI packages """ Success: Packages updated. """ + + Scenario: Update a specific package by name + Given an empty directory + + When I run `wp package install wp-cli-test/updateable-package:v1.0.0` + Then STDOUT should contain: + """ + Success: Package installed. + """ + + When I run `wp package install danielbachhuber/wp-cli-reset-post-date-command` + Then STDOUT should contain: + """ + Success: Package installed. + """ + + When I run `sed -i.bak s/v1.0.0/\>=1.0.0/g {PACKAGE_PATH}/composer.json` + Then the return code should be 0 + + When I run `wp package update wp-cli-test/updateable-package` + Then STDOUT should contain: + """ + Using Composer to update packages... + """ + And STDOUT should contain: + """ + Success: Package updated successfully. + """ + + When I run `wp package list --fields=name,update` + Then STDOUT should be a table containing rows: + | name | update | + | wp-cli-test/updateable-package | none | + + Scenario: Update multiple specific packages by name + Given an empty directory + + When I run `wp package install wp-cli-test/updateable-package:v1.0.0` + Then STDOUT should contain: + """ + Success: Package installed. + """ + + When I run `wp package install danielbachhuber/wp-cli-reset-post-date-command` + Then STDOUT should contain: + """ + Success: Package installed. + """ + + When I run `sed -i.bak s/v1.0.0/\>=1.0.0/g {PACKAGE_PATH}/composer.json` + Then the return code should be 0 + + When I run `wp package update wp-cli-test/updateable-package danielbachhuber/wp-cli-reset-post-date-command` + Then STDOUT should contain: + """ + Using Composer to update packages... + """ + And STDOUT should contain: + """ + Success: 2 packages updated successfully. + """ + + Scenario: Error when trying to update a non-existent package + Given an empty directory + + When I run `wp package install danielbachhuber/wp-cli-reset-post-date-command` + Then STDOUT should contain: + """ + Success: Package installed. + """ + + When I try `wp package update non-existent/package` + Then STDERR should contain: + """ + Error: Package 'non-existent/package' is not installed. + """ + And the return code should be 1 diff --git a/src/Package_Command.php b/src/Package_Command.php index 9e13c0d6..478329d2 100644 --- a/src/Package_Command.php +++ b/src/Package_Command.php @@ -503,8 +503,14 @@ public function path( $args ) { /** * Updates all installed WP-CLI packages to their latest version. * + * ## OPTIONS + * + * [...] + * : One or more package names to update. If not specified, all packages will be updated. + * * ## EXAMPLES * + * # Update all packages. * $ wp package update * Using Composer to update packages... * --- @@ -518,9 +524,34 @@ public function path( $args ) { * Generating autoload files * --- * Success: Packages updated. + * + * # Update a specific package. + * $ wp package update wp-cli/server-command + * Using Composer to update packages... + * --- + * Loading composer repositories with package information + * Updating dependencies + * Writing lock file + * Generating autoload files + * --- + * Success: Package updated successfully. */ - public function update() { + public function update( $args = [] ) { $this->set_composer_auth_env_var(); + + // Validate package names if provided + $packages_to_update = []; + if ( ! empty( $args ) ) { + foreach ( $args as $package_name ) { + $package = $this->get_installed_package_by_name( $package_name ); + if ( false === $package ) { + WP_CLI::error( sprintf( "Package '%s' is not installed.", $package_name ) ); + } + // Use the package's pretty name (case-sensitive) from composer + $packages_to_update[] = $package->getPrettyName(); + } + } + $composer = $this->get_composer(); // Set up the EventSubscriber @@ -531,6 +562,12 @@ public function update() { $install = Installer::create( new ComposerIO(), $composer ); $install->setUpdate( true ); // Installer class will only override composer.lock with this flag $install->setPreferSource( true ); // Use VCS when VCS for easier contributions. + + // If specific packages are provided, use the allow list + if ( ! empty( $packages_to_update ) ) { + $install->setUpdateAllowList( $packages_to_update ); + } + WP_CLI::log( 'Using Composer to update packages...' ); WP_CLI::log( '---' ); $res = false; @@ -544,7 +581,15 @@ public function update() { // TODO: The --insecure (to be added here) flag should cause another Composer run with verify disabled. if ( 0 === $res ) { - WP_CLI::success( 'Packages updated.' ); + if ( ! empty( $packages_to_update ) ) { + if ( 1 === count( $packages_to_update ) ) { + WP_CLI::success( 'Package updated successfully.' ); + } else { + WP_CLI::success( sprintf( '%d packages updated successfully.', count( $packages_to_update ) ) ); + } + } else { + WP_CLI::success( 'Packages updated.' ); + } } else { $res_msg = $res ? " (Composer return code {$res})" : ''; // $res may be null apparently. WP_CLI::error( "Failed to update packages{$res_msg}." ); From 0f8cfc6891b5c1cd6901ee6629b2ca2c49c646ba Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 12:36:10 +0000 Subject: [PATCH 3/4] Address code review feedback - improve method description and message logic Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Package_Command.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Package_Command.php b/src/Package_Command.php index 478329d2..883384fa 100644 --- a/src/Package_Command.php +++ b/src/Package_Command.php @@ -501,7 +501,7 @@ public function path( $args ) { } /** - * Updates all installed WP-CLI packages to their latest version. + * Updates installed WP-CLI packages to their latest version. * * ## OPTIONS * @@ -581,11 +581,12 @@ public function update( $args = [] ) { // TODO: The --insecure (to be added here) flag should cause another Composer run with verify disabled. if ( 0 === $res ) { - if ( ! empty( $packages_to_update ) ) { - if ( 1 === count( $packages_to_update ) ) { + $num_packages = count( $packages_to_update ); + if ( $num_packages > 0 ) { + if ( 1 === $num_packages ) { WP_CLI::success( 'Package updated successfully.' ); } else { - WP_CLI::success( sprintf( '%d packages updated successfully.', count( $packages_to_update ) ) ); + WP_CLI::success( sprintf( '%d packages updated successfully.', $num_packages ) ); } } else { WP_CLI::success( 'Packages updated.' ); From fb1aceced0a033282073813652d96b91a53a08b2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 15:44:31 +0000 Subject: [PATCH 4/4] Track actual package updates and provide accurate success messaging - Add event listener for 'post-package-update' to track which packages are actually updated - Differentiate success messages based on update outcomes: - "Package already at latest version" for single package with no update - "Packages already at latest versions" for multiple packages with no updates - "Package updated successfully" for single package updated - "All N packages updated successfully" when all requested packages are updated - "Updated X of Y packages" when only some packages are updated - Update tests to reflect new messaging behavior - Add test scenario for package already at latest version Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/package-update.feature | 21 ++++++++++++++++++++- src/Package_Command.php | 33 +++++++++++++++++++++++++++++---- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/features/package-update.feature b/features/package-update.feature index b6c07898..afeec92c 100644 --- a/features/package-update.feature +++ b/features/package-update.feature @@ -157,7 +157,26 @@ Feature: Update WP-CLI packages """ And STDOUT should contain: """ - Success: 2 packages updated successfully. + Success: Updated 1 of 2 packages. + """ + + Scenario: Update package that is already up to date + Given an empty directory + + When I run `wp package install danielbachhuber/wp-cli-reset-post-date-command` + Then STDOUT should contain: + """ + Success: Package installed. + """ + + When I run `wp package update danielbachhuber/wp-cli-reset-post-date-command` + Then STDOUT should contain: + """ + Using Composer to update packages... + """ + And STDOUT should contain: + """ + Success: Package already at latest version. """ Scenario: Error when trying to update a non-existent package diff --git a/src/Package_Command.php b/src/Package_Command.php index 883384fa..ebb4cc87 100644 --- a/src/Package_Command.php +++ b/src/Package_Command.php @@ -554,10 +554,23 @@ public function update( $args = [] ) { $composer = $this->get_composer(); - // Set up the EventSubscriber + // Set up the EventSubscriber with tracking for updates + $updated_packages = []; $event_subscriber = new PackageManagerEventSubscriber(); $composer->getEventDispatcher()->addSubscriber( $event_subscriber ); + // Add a listener to track actual package updates + $composer->getEventDispatcher()->addListener( + 'post-package-update', + function ( $event ) use ( &$updated_packages ) { + $operation = $event->getOperation(); + if ( method_exists( $operation, 'getTargetPackage' ) ) { + $package = $operation->getTargetPackage(); + $updated_packages[] = $package->getPrettyName(); + } + } + ); + // Set up the installer $install = Installer::create( new ComposerIO(), $composer ); $install->setUpdate( true ); // Installer class will only override composer.lock with this flag @@ -583,10 +596,22 @@ public function update( $args = [] ) { if ( 0 === $res ) { $num_packages = count( $packages_to_update ); if ( $num_packages > 0 ) { - if ( 1 === $num_packages ) { - WP_CLI::success( 'Package updated successfully.' ); + // When specific packages were requested, report on actual updates + $num_updated = count( $updated_packages ); + if ( 0 === $num_updated ) { + if ( 1 === $num_packages ) { + WP_CLI::success( 'Package already at latest version.' ); + } else { + WP_CLI::success( 'Packages already at latest versions.' ); + } + } elseif ( $num_updated === $num_packages ) { + if ( 1 === $num_packages ) { + WP_CLI::success( 'Package updated successfully.' ); + } else { + WP_CLI::success( sprintf( 'All %d packages updated successfully.', $num_packages ) ); + } } else { - WP_CLI::success( sprintf( '%d packages updated successfully.', $num_packages ) ); + WP_CLI::success( sprintf( 'Updated %d of %d packages.', $num_updated, $num_packages ) ); } } else { WP_CLI::success( 'Packages updated.' );