Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions features/package-update.feature
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,99 @@ 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: 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
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
79 changes: 75 additions & 4 deletions src/Package_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -501,10 +501,16 @@ public function path( $args ) {
}

/**
* Updates all installed WP-CLI packages to their latest version.
* Updates installed WP-CLI packages to their latest version.
*
* ## OPTIONS
*
* [<package-name>...]
* : 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...
* ---
Expand All @@ -518,19 +524,63 @@ 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
// 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
$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;
Expand All @@ -544,7 +594,28 @@ 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.' );
$num_packages = count( $packages_to_update );
if ( $num_packages > 0 ) {
// 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( 'Updated %d of %d packages.', $num_updated, $num_packages ) );
}
} 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}." );
Expand Down