From 2d05bacb3f63261b65d5a73bdd82ca86f30bd060 Mon Sep 17 00:00:00 2001 From: Saul Baizman Date: Sun, 18 Jan 2026 17:12:30 -0500 Subject: [PATCH 1/6] Add is-installed subcommand. --- README.md | 24 +++++ composer.json | 3 +- features/package-install.feature | 160 +++++++++++++++++++++++++++++++ src/Package_Command.php | 39 +++++--- 4 files changed, 214 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 120790a2..0de674e0 100644 --- a/README.md +++ b/README.md @@ -297,6 +297,30 @@ wp package uninstall [--insecure] Removing package directories and regenerating autoloader... Success: Uninstalled package. + + +### wp package is-installed + +Checks if a given package is installed. + +~~~ +wp package is-installed +~~~ + +Returns exit code 0 when installed, 1 when uninstalled. + +**OPTIONS** + + + The package to check. + +**EXAMPLES** + + # Check whether "foo/bar" is installed; exit status 0 if installed, otherwise 1 + $ wp package is-installed foo/bar + $ echo $? + 1 + ## Installing This package is included with WP-CLI itself, no additional installation necessary. diff --git a/composer.json b/composer.json index 9b53625d..64caff7a 100644 --- a/composer.json +++ b/composer.json @@ -41,7 +41,8 @@ "package install", "package list", "package update", - "package uninstall" + "package uninstall", + "package is-installed" ] }, "autoload": { diff --git a/features/package-install.feature b/features/package-install.feature index fe76b4c5..3129520f 100644 --- a/features/package-install.feature +++ b/features/package-install.feature @@ -46,6 +46,11 @@ Feature: Install WP-CLI packages "url": "http://wp-cli.org/package-index/" """ + When I run `wp package is-installed wp-cli/restful` + Then the return code should be 0 + And STDERR should be empty + And STDOUT should be empty + @require-php-5.6 Scenario: Install a package with 'wp-cli/wp-cli' as a dependency Given a WP install @@ -60,6 +65,11 @@ Feature: Install WP-CLI packages requires wp-cli/wp-cli """ + When I run `wp package is-installed wp-cli-test/test-command` + Then the return code should be 0 + And STDERR should be empty + And STDOUT should be empty + When I run `wp test-command` Then STDOUT should contain: """ @@ -84,6 +94,11 @@ Feature: Install WP-CLI packages faker """ + When I run `wp package is-installed yoast/wp-cli-faker` + Then the return code should be 0 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should be a table containing rows: | name | @@ -111,6 +126,11 @@ Feature: Install WP-CLI packages fzaninotto """ + When I run `wp package is-installed yoast/wp-cli-faker` + Then the return code should be 1 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list` Then STDOUT should not contain: """ @@ -136,6 +156,11 @@ Feature: Install WP-CLI packages "wp-cli-test/package-name": "dev-master" """ + When I run `wp package is-installed wp-cli-test/package-name` + Then the return code should be 0 + And STDERR should be empty + And STDOUT should be empty + When I try `wp package install git@github.com:wp-cli.git` Then STDERR should contain: """ @@ -162,6 +187,11 @@ Feature: Install WP-CLI packages Success: Package installed. """ + When I run `wp package is-installed wp-cli/google-sitemap-generator-cli` + Then the return code should be 0 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should be a table containing rows: | name | @@ -195,6 +225,11 @@ Feature: Install WP-CLI packages Success: Uninstalled package. """ + When I run `wp package is-installed wp-cli/google-sitemap-generator-cli` + Then the return code should be 1 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should not contain: """ @@ -238,6 +273,11 @@ Feature: Install WP-CLI packages "CapitalWPCLI/examplecommand" """ + When I run `wp package is-installed capitalwpcli/examplecommand` + Then the return code should be 0 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should be a table containing rows: | name | @@ -261,6 +301,11 @@ Feature: Install WP-CLI packages """ And the contents of the {PACKAGE_PATH}composer.json file should match /\"gitlost\/(?:TestMixedCaseCommand|testmixedcasecommand)\"/ + When I run `wp package is-installed gitlost/TestMixedCaseCommand` + Then the return code should be 0 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should be a table containing rows: | name | @@ -296,6 +341,11 @@ Feature: Install WP-CLI packages Success: Package installed. """ + When I run `wp package is-installed wp-cli-test/github-test-command` + Then the return code should be 0 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name,version` Then STDOUT should be a table containing rows: | name | version | @@ -317,6 +367,11 @@ Feature: Install WP-CLI packages Success: Uninstalled package. """ + When I run `wp package is-installed wp-cli-test/github-test-command` + Then the return code should be 1 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should not contain: """ @@ -347,6 +402,11 @@ Feature: Install WP-CLI packages Success: Package installed. """ + When I run `wp package is-installed wp-cli-test/github-test-command` + Then the return code should be 0 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name,version` Then STDOUT should be a table containing rows: | name | version | @@ -368,6 +428,11 @@ Feature: Install WP-CLI packages Success: Uninstalled package. """ + When I run `wp package is-installed wp-cli-test/github-test-command` + Then the return code should be 1 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should not contain: """ @@ -405,6 +470,11 @@ Feature: Install WP-CLI packages Success: Package installed. """ + When I run `wp package is-installed wp-cli-test/github-test-command` + Then the return code should be 0 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name,version` Then STDOUT should be a table containing rows: | name | version | @@ -426,6 +496,11 @@ Feature: Install WP-CLI packages Success: Uninstalled package. """ + When I run `wp package is-installed wp-cli-test/github-test-command` + Then the return code should be 1 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should not contain: """ @@ -456,6 +531,11 @@ Feature: Install WP-CLI packages Success: Package installed. """ + When I run `wp package is-installed wp-cli-test/github-test-command` + Then the return code should be 0 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name,version` Then STDOUT should be a table containing rows: | name | version | @@ -477,6 +557,11 @@ Feature: Install WP-CLI packages Success: Uninstalled package. """ + When I run `wp package is-installed wp-cli-test/github-test-command` + Then the return code should be 1 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should not contain: """ @@ -507,6 +592,11 @@ Feature: Install WP-CLI packages Success: Package installed. """ + When I run `wp package is-installed wp-cli-test/github-test-command` + Then the return code should be 0 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name,version` Then STDOUT should be a table containing rows: | name | version | @@ -528,6 +618,11 @@ Feature: Install WP-CLI packages Success: Uninstalled package. """ + When I run `wp package is-installed wp-cli-test/github-test-command` + Then the return code should be 1 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should not contain: """ @@ -560,6 +655,11 @@ Feature: Install WP-CLI packages """ And the contents of the {PACKAGE_PATH}composer.json file should match /"wp-media\/wp-rocket-cli"/ + When I run `wp package is-installed wp-media/wp-rocket-cli` + Then the return code should be 0 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should be a table containing rows: | name | @@ -589,6 +689,11 @@ Feature: Install WP-CLI packages rocket """ + When I run `wp package is-installed wp-media/wp-rocket-cli` + Then the return code should be 1 + And STDERR should be empty + And STDOUT should be empty + # Install with lowercase name (for BC - no warning) and uninstall with lowercase name (for BC and convenience) When I run `wp package install geekpress/wp-rocket-cli` Then STDERR should be empty @@ -608,6 +713,11 @@ Feature: Install WP-CLI packages """ And the contents of the {PACKAGE_PATH}composer.json file should match /("?:GeekPress|geekpress)\/wp-rocket-cli"/ + When I run `wp package is-installed geekpress/wp-rocket-cli` + Then the return code should be 0 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should be a table containing rows: | name | @@ -633,6 +743,11 @@ Feature: Install WP-CLI packages rocket """ + When I run `wp package is-installed geekpress/wp-rocket-cli` + Then the return code should be 1 + And STDERR should be empty + And STDOUT should be empty + @github-api Scenario: Install a package with a composer.json that differs between versions Given an empty directory @@ -711,6 +826,11 @@ Feature: Install WP-CLI packages Success: Package installed. """ + When I run `wp package is-installed wp-cli/google-sitemap-generator-cli` + Then the return code should be 0 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should be a table containing rows: | name | @@ -732,6 +852,11 @@ Feature: Install WP-CLI packages Success: Uninstalled package. """ + When I run `wp package is-installed wp-cli/google-sitemap-generator-cli` + Then the return code should be 1 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should not contain: """ @@ -775,6 +900,11 @@ Feature: Install WP-CLI packages "CapitalWPCLI/examplecommand" """ + When I run `wp package is-installed capitalwpcli/examplecommand` + Then the return code should be 0 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should be a table containing rows: | name | @@ -830,6 +960,11 @@ Feature: Install WP-CLI packages Success: Package installed. """ + When I run `wp package is-installed wp-cli/google-sitemap-generator-cli` + Then the return code should be 0 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should be a table containing rows: | name | @@ -851,6 +986,11 @@ Feature: Install WP-CLI packages Success: Uninstalled package. """ + When I run `wp package is-installed wp-cli/google-sitemap-generator-cli` + Then the return code should be 1 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should not contain: """ @@ -918,6 +1058,11 @@ Feature: Install WP-CLI packages Success: Package installed. """ + When I run `wp package is-installed wp-cli/community-command` + Then the return code should be 0 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should be a table containing rows: | name | @@ -940,6 +1085,11 @@ Feature: Install WP-CLI packages """ And the path-command directory should exist + When I run `wp package is-installed wp-cli/community-command` + Then the return code should be 1 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should not contain: """ @@ -997,6 +1147,11 @@ Feature: Install WP-CLI packages Success: Package installed. """ + When I run `wp package is-installed wp-cli/community-command` + Then the return code should be 0 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should be a table containing rows: | name | @@ -1019,6 +1174,11 @@ Feature: Install WP-CLI packages """ And the path-command directory should exist + When I run `wp package is-installed wp-cli/community-command` + Then the return code should be 1 + And STDERR should be empty + And STDOUT should be empty + When I run `wp package list --fields=name` Then STDOUT should not contain: """ diff --git a/src/Package_Command.php b/src/Package_Command.php index e6f8273c..7f4e6468 100644 --- a/src/Package_Command.php +++ b/src/Package_Command.php @@ -644,6 +644,34 @@ public function uninstall( $args, $assoc_args ) { } } + /** + * Checks if a given package is installed. + * + * Returns exit code 0 when installed, 1 when uninstalled. + * + * ## OPTIONS + * + * + * : The package to check. + * + * ## EXAMPLES + * + * # Check whether "foo/bar" is installed; exit status 0 if installed, otherwise 1 + * $ wp package is-installed foo/bar + * $ echo $? + * 1 + * + * @subcommand is-installed + */ + public function is_installed( $args, $assoc_args ) { + list( $package_name ) = $args; + if ( $this->get_installed_package_by_name( $package_name ) ) { + WP_CLI::halt( 0 ); + } else { + WP_CLI::halt( 1 ); + } + } + /** * Checks whether a package is a WP-CLI community package based * on membership in our package index. @@ -920,17 +948,6 @@ private function get_installed_package_by_name( $package_name ) { return false; } - /** - * Checks if the package name provided is already installed. - */ - private function is_package_installed( $package_name ) { - if ( $this->get_installed_package_by_name( $package_name ) ) { - return true; - } else { - return false; - } - } - /** * Gets the name of the package from the composer.json in a directory path * From 9c937d3d96dfd2efa15df8de3eb697a6a6a77609 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 20 Jan 2026 10:13:51 +0100 Subject: [PATCH 2/6] Inline condition --- src/Package_Command.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Package_Command.php b/src/Package_Command.php index 7f4e6468..3514de11 100644 --- a/src/Package_Command.php +++ b/src/Package_Command.php @@ -665,11 +665,7 @@ public function uninstall( $args, $assoc_args ) { */ public function is_installed( $args, $assoc_args ) { list( $package_name ) = $args; - if ( $this->get_installed_package_by_name( $package_name ) ) { - WP_CLI::halt( 0 ); - } else { - WP_CLI::halt( 1 ); - } + WP_CLI::halt( $this->get_installed_package_by_name( $package_name ) ? 0 : 1 ); } /** From 7e0c3eb2de51925ffe2b3db6da54ffa4fb5f42f4 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 20 Jan 2026 10:24:09 +0100 Subject: [PATCH 3/6] Remove unused method --- src/Package_Command.php | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/Package_Command.php b/src/Package_Command.php index 3514de11..d0580b6a 100644 --- a/src/Package_Command.php +++ b/src/Package_Command.php @@ -668,17 +668,6 @@ public function is_installed( $args, $assoc_args ) { WP_CLI::halt( $this->get_installed_package_by_name( $package_name ) ? 0 : 1 ); } - /** - * Checks whether a package is a WP-CLI community package based - * on membership in our package index. - * - * @param object $package A package object - * @return bool - */ - private function is_community_package( $package ) { - return $this->package_index()->hasPackage( $package ); - } - /** * Gets a Composer instance. */ From 2ce6a7798c07ca5af9e60f92ee5d6452e705f2d0 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 20 Jan 2026 10:24:11 +0100 Subject: [PATCH 4/6] Fix docblock --- src/Package_Command.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Package_Command.php b/src/Package_Command.php index d0580b6a..7a3fff80 100644 --- a/src/Package_Command.php +++ b/src/Package_Command.php @@ -1095,6 +1095,9 @@ private function find_latest_package( PackageInterface $package, Composer $compo return $version_selector->findBestCandidate( $name, $target_version, $php_version, $best_stability ); } + /** + * @return VersionSelector + */ private function get_version_selector( Composer $composer ) { if ( ! $this->version_selector ) { if ( $this->is_composer_v2() ) { From 7fd686a7e6478e4f382774aeafb686dcffcca77e Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 20 Jan 2026 10:24:36 +0100 Subject: [PATCH 5/6] Use `try` if expecting failure --- features/package-install.feature | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/features/package-install.feature b/features/package-install.feature index 3129520f..026a65ef 100644 --- a/features/package-install.feature +++ b/features/package-install.feature @@ -126,7 +126,7 @@ Feature: Install WP-CLI packages fzaninotto """ - When I run `wp package is-installed yoast/wp-cli-faker` + When I try `wp package is-installed yoast/wp-cli-faker` Then the return code should be 1 And STDERR should be empty And STDOUT should be empty @@ -225,7 +225,7 @@ Feature: Install WP-CLI packages Success: Uninstalled package. """ - When I run `wp package is-installed wp-cli/google-sitemap-generator-cli` + When I try `wp package is-installed wp-cli/google-sitemap-generator-cli` Then the return code should be 1 And STDERR should be empty And STDOUT should be empty @@ -367,7 +367,7 @@ Feature: Install WP-CLI packages Success: Uninstalled package. """ - When I run `wp package is-installed wp-cli-test/github-test-command` + When I try `wp package is-installed wp-cli-test/github-test-command` Then the return code should be 1 And STDERR should be empty And STDOUT should be empty @@ -428,7 +428,7 @@ Feature: Install WP-CLI packages Success: Uninstalled package. """ - When I run `wp package is-installed wp-cli-test/github-test-command` + When I try `wp package is-installed wp-cli-test/github-test-command` Then the return code should be 1 And STDERR should be empty And STDOUT should be empty @@ -496,7 +496,7 @@ Feature: Install WP-CLI packages Success: Uninstalled package. """ - When I run `wp package is-installed wp-cli-test/github-test-command` + When I try `wp package is-installed wp-cli-test/github-test-command` Then the return code should be 1 And STDERR should be empty And STDOUT should be empty @@ -557,7 +557,7 @@ Feature: Install WP-CLI packages Success: Uninstalled package. """ - When I run `wp package is-installed wp-cli-test/github-test-command` + When I try `wp package is-installed wp-cli-test/github-test-command` Then the return code should be 1 And STDERR should be empty And STDOUT should be empty @@ -618,7 +618,7 @@ Feature: Install WP-CLI packages Success: Uninstalled package. """ - When I run `wp package is-installed wp-cli-test/github-test-command` + When I try `wp package is-installed wp-cli-test/github-test-command` Then the return code should be 1 And STDERR should be empty And STDOUT should be empty @@ -689,7 +689,7 @@ Feature: Install WP-CLI packages rocket """ - When I run `wp package is-installed wp-media/wp-rocket-cli` + When I try `wp package is-installed wp-media/wp-rocket-cli` Then the return code should be 1 And STDERR should be empty And STDOUT should be empty @@ -743,7 +743,7 @@ Feature: Install WP-CLI packages rocket """ - When I run `wp package is-installed geekpress/wp-rocket-cli` + When I try `wp package is-installed geekpress/wp-rocket-cli` Then the return code should be 1 And STDERR should be empty And STDOUT should be empty @@ -852,7 +852,7 @@ Feature: Install WP-CLI packages Success: Uninstalled package. """ - When I run `wp package is-installed wp-cli/google-sitemap-generator-cli` + When I try `wp package is-installed wp-cli/google-sitemap-generator-cli` Then the return code should be 1 And STDERR should be empty And STDOUT should be empty @@ -986,7 +986,7 @@ Feature: Install WP-CLI packages Success: Uninstalled package. """ - When I run `wp package is-installed wp-cli/google-sitemap-generator-cli` + When I try `wp package is-installed wp-cli/google-sitemap-generator-cli` Then the return code should be 1 And STDERR should be empty And STDOUT should be empty @@ -1085,7 +1085,7 @@ Feature: Install WP-CLI packages """ And the path-command directory should exist - When I run `wp package is-installed wp-cli/community-command` + When I try `wp package is-installed wp-cli/community-command` Then the return code should be 1 And STDERR should be empty And STDOUT should be empty @@ -1174,7 +1174,7 @@ Feature: Install WP-CLI packages """ And the path-command directory should exist - When I run `wp package is-installed wp-cli/community-command` + When I try `wp package is-installed wp-cli/community-command` Then the return code should be 1 And STDERR should be empty And STDOUT should be empty From 2cc93b5bb19e69ab3031e78b3fd2b01f50a7a333 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 20 Jan 2026 10:25:04 +0100 Subject: [PATCH 6/6] Specify `WP_CLI_PACKAGES_DIR` --- features/package-install.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/package-install.feature b/features/package-install.feature index 026a65ef..cafd1e84 100644 --- a/features/package-install.feature +++ b/features/package-install.feature @@ -46,7 +46,7 @@ Feature: Install WP-CLI packages "url": "http://wp-cli.org/package-index/" """ - When I run `wp package is-installed wp-cli/restful` + When I run `WP_CLI_PACKAGES_DIR=. wp package is-installed wp-cli/restful` Then the return code should be 0 And STDERR should be empty And STDOUT should be empty