Skip to content

Commit b2b5700

Browse files
authored
Merge pull request #208 from wp-cli/copilot/add-package-name-argument
2 parents 9c3d92c + b34a928 commit b2b5700

File tree

2 files changed

+171
-4
lines changed

2 files changed

+171
-4
lines changed

features/package-update.feature

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,99 @@ Feature: Update WP-CLI packages
9898
"""
9999
Success: Packages updated.
100100
"""
101+
102+
Scenario: Update a specific package by name
103+
Given an empty directory
104+
105+
When I run `wp package install wp-cli-test/updateable-package:v1.0.0`
106+
Then STDOUT should contain:
107+
"""
108+
Success: Package installed.
109+
"""
110+
111+
When I run `wp package install danielbachhuber/wp-cli-reset-post-date-command`
112+
Then STDOUT should contain:
113+
"""
114+
Success: Package installed.
115+
"""
116+
117+
When I run `sed -i.bak s/v1.0.0/\>=1.0.0/g {PACKAGE_PATH}/composer.json`
118+
Then the return code should be 0
119+
120+
When I run `wp package update wp-cli-test/updateable-package`
121+
Then STDOUT should contain:
122+
"""
123+
Using Composer to update packages...
124+
"""
125+
And STDOUT should contain:
126+
"""
127+
Success: Package updated successfully.
128+
"""
129+
130+
When I run `wp package list --fields=name,update`
131+
Then STDOUT should be a table containing rows:
132+
| name | update |
133+
| wp-cli-test/updateable-package | none |
134+
135+
Scenario: Update multiple specific packages by name
136+
Given an empty directory
137+
138+
When I run `wp package install wp-cli-test/updateable-package:v1.0.0`
139+
Then STDOUT should contain:
140+
"""
141+
Success: Package installed.
142+
"""
143+
144+
When I run `wp package install danielbachhuber/wp-cli-reset-post-date-command`
145+
Then STDOUT should contain:
146+
"""
147+
Success: Package installed.
148+
"""
149+
150+
When I run `sed -i.bak s/v1.0.0/\>=1.0.0/g {PACKAGE_PATH}/composer.json`
151+
Then the return code should be 0
152+
153+
When I run `wp package update wp-cli-test/updateable-package danielbachhuber/wp-cli-reset-post-date-command`
154+
Then STDOUT should contain:
155+
"""
156+
Using Composer to update packages...
157+
"""
158+
And STDOUT should contain:
159+
"""
160+
Success: Updated 1 of 2 packages.
161+
"""
162+
163+
Scenario: Update package that is already up to date
164+
Given an empty directory
165+
166+
When I run `wp package install danielbachhuber/wp-cli-reset-post-date-command`
167+
Then STDOUT should contain:
168+
"""
169+
Success: Package installed.
170+
"""
171+
172+
When I run `wp package update danielbachhuber/wp-cli-reset-post-date-command`
173+
Then STDOUT should contain:
174+
"""
175+
Using Composer to update packages...
176+
"""
177+
And STDOUT should contain:
178+
"""
179+
Success: Package already at latest version.
180+
"""
181+
182+
Scenario: Error when trying to update a non-existent package
183+
Given an empty directory
184+
185+
When I run `wp package install danielbachhuber/wp-cli-reset-post-date-command`
186+
Then STDOUT should contain:
187+
"""
188+
Success: Package installed.
189+
"""
190+
191+
When I try `wp package update non-existent/package`
192+
Then STDERR should contain:
193+
"""
194+
Error: Package 'non-existent/package' is not installed.
195+
"""
196+
And the return code should be 1

src/Package_Command.php

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -512,10 +512,16 @@ public function path( $args ) {
512512
}
513513

514514
/**
515-
* Updates all installed WP-CLI packages to their latest version.
515+
* Updates installed WP-CLI packages to their latest version.
516+
*
517+
* ## OPTIONS
518+
*
519+
* [<package-name>...]
520+
* : One or more package names to update. If not specified, all packages will be updated.
516521
*
517522
* ## EXAMPLES
518523
*
524+
* # Update all packages.
519525
* $ wp package update
520526
* Using Composer to update packages...
521527
* ---
@@ -529,19 +535,63 @@ public function path( $args ) {
529535
* Generating autoload files
530536
* ---
531537
* Success: Packages updated.
538+
*
539+
* # Update a specific package.
540+
* $ wp package update wp-cli/server-command
541+
* Using Composer to update packages...
542+
* ---
543+
* Loading composer repositories with package information
544+
* Updating dependencies
545+
* Writing lock file
546+
* Generating autoload files
547+
* ---
548+
* Success: Package updated successfully.
532549
*/
533-
public function update() {
550+
public function update( $args = [] ) {
534551
$this->set_composer_auth_env_var();
552+
553+
// Validate package names if provided
554+
$packages_to_update = [];
555+
if ( ! empty( $args ) ) {
556+
foreach ( $args as $package_name ) {
557+
$package = $this->get_installed_package_by_name( $package_name );
558+
if ( false === $package ) {
559+
WP_CLI::error( sprintf( "Package '%s' is not installed.", $package_name ) );
560+
}
561+
// Use the package's pretty name (case-sensitive) from composer
562+
$packages_to_update[] = $package->getPrettyName();
563+
}
564+
}
565+
535566
$composer = $this->get_composer();
536567

537-
// Set up the EventSubscriber
568+
// Set up the EventSubscriber with tracking for updates
569+
$updated_packages = [];
538570
$event_subscriber = new PackageManagerEventSubscriber();
539571
$composer->getEventDispatcher()->addSubscriber( $event_subscriber );
540572

573+
// Add a listener to track actual package updates
574+
$composer->getEventDispatcher()->addListener(
575+
'post-package-update',
576+
function ( $event ) use ( &$updated_packages ) {
577+
$operation = $event->getOperation();
578+
if ( method_exists( $operation, 'getTargetPackage' ) ) {
579+
$package = $operation->getTargetPackage();
580+
$updated_packages[] = $package->getPrettyName();
581+
}
582+
}
583+
);
584+
541585
// Set up the installer
542586
$install = Installer::create( new ComposerIO(), $composer );
543587
$install->setUpdate( true ); // Installer class will only override composer.lock with this flag
544588
$install->setPreferSource( true ); // Use VCS when VCS for easier contributions.
589+
590+
// If specific packages are provided, use the allow list
591+
if ( ! empty( $packages_to_update ) ) {
592+
$install->setUpdateAllowList( $packages_to_update );
593+
}
594+
545595
WP_CLI::log( 'Using Composer to update packages...' );
546596
WP_CLI::log( '---' );
547597
$res = false;
@@ -555,7 +605,28 @@ public function update() {
555605
// TODO: The --insecure (to be added here) flag should cause another Composer run with verify disabled.
556606

557607
if ( 0 === $res ) {
558-
WP_CLI::success( 'Packages updated.' );
608+
$num_packages = count( $packages_to_update );
609+
if ( $num_packages > 0 ) {
610+
// When specific packages were requested, report on actual updates
611+
$num_updated = count( $updated_packages );
612+
if ( 0 === $num_updated ) {
613+
if ( 1 === $num_packages ) {
614+
WP_CLI::success( 'Package already at latest version.' );
615+
} else {
616+
WP_CLI::success( 'Packages already at latest versions.' );
617+
}
618+
} elseif ( $num_updated === $num_packages ) {
619+
if ( 1 === $num_packages ) {
620+
WP_CLI::success( 'Package updated successfully.' );
621+
} else {
622+
WP_CLI::success( sprintf( 'All %d packages updated successfully.', $num_packages ) );
623+
}
624+
} else {
625+
WP_CLI::success( sprintf( 'Updated %d of %d packages.', $num_updated, $num_packages ) );
626+
}
627+
} else {
628+
WP_CLI::success( 'Packages updated.' );
629+
}
559630
} else {
560631
$res_msg = $res ? " (Composer return code {$res})" : ''; // $res may be null apparently.
561632
WP_CLI::error( "Failed to update packages{$res_msg}." );

0 commit comments

Comments
 (0)