Skip to content

Commit 8c9f749

Browse files
authored
Merge branch 'main' into copilot/add-non-interactive-option
2 parents f937d6a + d662e02 commit 8c9f749

6 files changed

Lines changed: 548 additions & 33 deletions

File tree

README.md

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,30 @@ for future authorization requests.
248248

249249

250250

251+
### wp package is-installed
252+
253+
Checks if a given package is installed.
254+
255+
~~~
256+
wp package is-installed <name>
257+
~~~
258+
259+
Returns exit code 0 when installed, 1 when uninstalled.
260+
261+
**OPTIONS**
262+
263+
<name>
264+
The package to check.
265+
266+
**EXAMPLES**
267+
268+
# Check whether "foo/bar" is installed; exit status 0 if installed, otherwise 1
269+
$ wp package is-installed foo/bar
270+
$ echo $?
271+
1
272+
273+
274+
251275
### wp package list
252276

253277
Lists installed WP-CLI packages.
@@ -310,6 +334,37 @@ These fields are optionally available:
310334

311335

312336

337+
### wp package path
338+
339+
Gets the path to an installed WP-CLI package, or the package directory.
340+
341+
~~~
342+
wp package path [<name>]
343+
~~~
344+
345+
If you want to contribute to a package, this is a great way to jump to it.
346+
347+
**OPTIONS**
348+
349+
[<name>]
350+
Name of the package to get the directory for.
351+
352+
**EXAMPLES**
353+
354+
# Get package path.
355+
$ wp package path
356+
/home/person/.wp-cli/packages/
357+
358+
# Get path to an installed package.
359+
$ wp package path wp-cli/server-command
360+
/home/person/.wp-cli/packages/vendor/wp-cli/server-command
361+
362+
# Change directory to package path.
363+
$ cd $(wp package path) && pwd
364+
/home/vagrant/.wp-cli/packages
365+
366+
367+
313368
### wp package update
314369

315370
Updates installed WP-CLI packages to their latest version.
@@ -376,30 +431,6 @@ wp package uninstall <name> [--insecure]
376431
Removing package directories and regenerating autoloader...
377432
Success: Uninstalled package.
378433

379-
380-
381-
### wp package is-installed
382-
383-
Checks if a given package is installed.
384-
385-
~~~
386-
wp package is-installed <name>
387-
~~~
388-
389-
Returns exit code 0 when installed, 1 when uninstalled.
390-
391-
**OPTIONS**
392-
393-
<name>
394-
The package to check.
395-
396-
**EXAMPLES**
397-
398-
# Check whether "foo/bar" is installed; exit status 0 if installed, otherwise 1
399-
$ wp package is-installed foo/bar
400-
$ echo $?
401-
1
402-
403434
## Installing
404435

405436
This package is included with WP-CLI itself, no additional installation necessary.

composer.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,11 @@
4040
"package browse",
4141
"package get",
4242
"package install",
43+
"package is-installed",
4344
"package list",
45+
"package path",
4446
"package update",
45-
"package uninstall",
46-
"package is-installed"
47+
"package uninstall"
4748
]
4849
},
4950
"autoload": {

features/package-auth.feature

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
Feature: Composer authentication for various git providers
2+
3+
Scenario: GitHub OAuth token is set in COMPOSER_AUTH
4+
Given an empty directory
5+
When I run `GITHUB_TOKEN=ghp_test123456789 wp package path`
6+
Then STDOUT should not be empty
7+
And the return code should be 0
8+
9+
Scenario: GitLab OAuth token is set in COMPOSER_AUTH
10+
Given an empty directory
11+
When I run `GITLAB_OAUTH_TOKEN=glpat_test123456789 wp package path`
12+
Then STDOUT should not be empty
13+
And the return code should be 0
14+
15+
Scenario: GitLab personal access token is set in COMPOSER_AUTH
16+
Given an empty directory
17+
When I run `GITLAB_TOKEN=glpat_test123456789 wp package path`
18+
Then STDOUT should not be empty
19+
And the return code should be 0
20+
21+
Scenario: Bitbucket OAuth consumer is set in COMPOSER_AUTH
22+
Given an empty directory
23+
When I run `BITBUCKET_CONSUMER_KEY=test_key BITBUCKET_CONSUMER_SECRET=test_secret wp package path`
24+
Then STDOUT should not be empty
25+
And the return code should be 0
26+
27+
Scenario: HTTP Basic Auth is set in COMPOSER_AUTH
28+
Given an empty directory
29+
When I run `HTTP_BASIC_AUTH='{"repo.example.com":{"username":"user","password":"pass"}}' wp package path`
30+
Then STDOUT should not be empty
31+
And the return code should be 0
32+
33+
Scenario: Multiple auth providers can be used together
34+
Given an empty directory
35+
When I run `GITHUB_TOKEN=ghp_test123 GITLAB_TOKEN=glpat_test456 wp package path`
36+
Then STDOUT should not be empty
37+
And the return code should be 0
38+
39+
Scenario: Invalid HTTP_BASIC_AUTH JSON is ignored
40+
Given an empty directory
41+
When I run `HTTP_BASIC_AUTH='not-valid-json' wp package path`
42+
Then STDOUT should not be empty
43+
And the return code should be 0

features/package-install.feature

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,50 @@ Feature: Install WP-CLI packages
4545
"""
4646
"url": "http://wp-cli.org/package-index/"
4747
"""
48+
And the composer.json file should contain:
49+
"""
50+
"canonical": false
51+
"""
4852

4953
When I run `WP_CLI_PACKAGES_DIR=. wp package is-installed wp-cli/restful`
5054
Then the return code should be 0
5155
And STDERR should be empty
5256
And STDOUT should be empty
5357

58+
Scenario: Install a package updates the package index repository to be non-canonical
59+
Given an empty directory
60+
And a composer.json file:
61+
"""
62+
{
63+
"repositories": {
64+
"test" : {
65+
"type": "path",
66+
"url": "./dummy-package/"
67+
},
68+
"wp-cli": {
69+
"type": "composer",
70+
"url": "https://wp-cli.org/package-index/"
71+
}
72+
}
73+
}
74+
"""
75+
And a dummy-package/composer.json file:
76+
"""
77+
{
78+
"name": "wp-cli/restful",
79+
"description": "This is a dummy package we will install instead of actually installing the real package. This prevents the test from hanging indefinitely for some reason, even though it passes. The 'name' must match a real package as it is checked against the package index."
80+
}
81+
"""
82+
When I run `WP_CLI_PACKAGES_DIR=. wp package install wp-cli/restful`
83+
Then STDOUT should contain:
84+
"""
85+
Success: Package installed
86+
"""
87+
And the composer.json file should contain:
88+
"""
89+
"canonical": false
90+
"""
91+
5492
@require-php-5.6
5593
Scenario: Install a package with 'wp-cli/wp-cli' as a dependency
5694
Given a WP install
@@ -236,6 +274,30 @@ Feature: Install WP-CLI packages
236274
wp-cli/google-sitemap-generator-cli
237275
"""
238276

277+
@github-api
278+
Scenario: Install a package from a Git URL with a version suffix
279+
Given an empty directory
280+
281+
When I run `wp package install https://github.com/wp-cli/google-sitemap-generator-cli.git:dev-main`
282+
Then STDOUT should contain:
283+
"""
284+
Installing package wp-cli/google-sitemap-generator-cli (dev-main)
285+
"""
286+
And STDOUT should contain:
287+
"""
288+
Registering https://github.com/wp-cli/google-sitemap-generator-cli.git as a VCS repository...
289+
"""
290+
And STDOUT should contain:
291+
"""
292+
Success: Package installed.
293+
"""
294+
295+
When I run `wp package uninstall wp-cli/google-sitemap-generator-cli`
296+
Then STDOUT should contain:
297+
"""
298+
Success: Uninstalled package.
299+
"""
300+
239301
@github-api
240302
Scenario: Install a package from a Git URL with mixed-case git name but lowercase composer.json name
241303
Given an empty directory

src/Package_Command.php

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,9 @@ class Package_Command extends WP_CLI_Command {
9292
* @var array
9393
*/
9494
private $composer_type_package = [
95-
'type' => 'composer',
96-
'url' => self::PACKAGE_INDEX_URL,
95+
'type' => 'composer',
96+
'url' => self::PACKAGE_INDEX_URL,
97+
'canonical' => false,
9798
];
9899

99100
/**
@@ -229,8 +230,15 @@ public function install( $args, $assoc_args ) {
229230
$git_package = false;
230231
$dir_package = false;
231232
$version = '';
233+
// Parse version suffix from a git URL (e.g. https://github.com/vendor/package.git:dev-main).
234+
if ( preg_match( '#^(.+\.git):([^:]+)$#', $package_name, $url_version_matches ) ) {
235+
$package_name = $url_version_matches[1];
236+
$version = $url_version_matches[2];
237+
}
232238
if ( $this->is_git_repository( $package_name ) ) {
233-
$version = "dev-{$this->get_github_default_branch( $package_name, $insecure )}";
239+
if ( '' === $version ) {
240+
$version = "dev-{$this->get_github_default_branch( $package_name, $insecure )}";
241+
}
234242
$git_package = $package_name;
235243
$matches = [];
236244
if ( preg_match( '#([^:\/]+\/[^\/]+)\.git#', $package_name, $matches ) ) {
@@ -373,12 +381,13 @@ public function install( $args, $assoc_args ) {
373381
);
374382
}
375383
// If the composer file does not contain the current package index repository, refresh the repository definition.
376-
if ( empty( $composer_backup_decoded['repositories']['wp-cli']['url'] ) || self::PACKAGE_INDEX_URL !== $composer_backup_decoded['repositories']['wp-cli']['url'] ) {
384+
if ( empty( $composer_backup_decoded['repositories']['wp-cli']['url'] )
385+
|| self::PACKAGE_INDEX_URL !== $composer_backup_decoded['repositories']['wp-cli']['url']
386+
|| ( $composer_backup_decoded['repositories']['wp-cli']['canonical'] ?? true ) !== false ) {
377387
WP_CLI::log( 'Updating package index repository url...' );
378-
$package_args = $this->composer_type_package;
379388
$json_manipulator->addRepository(
380389
'wp-cli',
381-
$package_args
390+
$this->composer_type_package
382391
);
383392
}
384393

@@ -1528,11 +1537,54 @@ private function set_composer_auth_env_var() {
15281537
if ( empty( $composer_auth ) || ! is_array( $composer_auth ) ) {
15291538
$composer_auth = [];
15301539
}
1540+
1541+
// GitHub OAuth token.
15311542
$github_token = getenv( 'GITHUB_TOKEN' );
1532-
if ( ! isset( $composer_auth['github-oauth'] ) && is_string( $github_token ) ) {
1543+
if ( ! isset( $composer_auth['github-oauth'] ) && is_string( $github_token ) && '' !== $github_token ) {
15331544
$composer_auth['github-oauth'] = [ 'github.com' => $github_token ];
15341545
$changed = true;
15351546
}
1547+
1548+
// GitLab OAuth token.
1549+
$gitlab_oauth_token = getenv( 'GITLAB_OAUTH_TOKEN' );
1550+
if ( ! isset( $composer_auth['gitlab-oauth'] ) && is_string( $gitlab_oauth_token ) && '' !== $gitlab_oauth_token ) {
1551+
$composer_auth['gitlab-oauth'] = [ 'gitlab.com' => $gitlab_oauth_token ];
1552+
$changed = true;
1553+
}
1554+
1555+
// GitLab personal access token.
1556+
$gitlab_token = getenv( 'GITLAB_TOKEN' );
1557+
if ( ! isset( $composer_auth['gitlab-token'] ) && is_string( $gitlab_token ) && '' !== $gitlab_token ) {
1558+
$composer_auth['gitlab-token'] = [ 'gitlab.com' => $gitlab_token ];
1559+
$changed = true;
1560+
}
1561+
1562+
// Bitbucket OAuth consumer.
1563+
$bitbucket_key = getenv( 'BITBUCKET_CONSUMER_KEY' );
1564+
$bitbucket_secret = getenv( 'BITBUCKET_CONSUMER_SECRET' );
1565+
if ( ! isset( $composer_auth['bitbucket-oauth'] )
1566+
&& is_string( $bitbucket_key ) && '' !== $bitbucket_key
1567+
&& is_string( $bitbucket_secret ) && '' !== $bitbucket_secret
1568+
) {
1569+
$composer_auth['bitbucket-oauth'] = [
1570+
'bitbucket.org' => [
1571+
'consumer-key' => $bitbucket_key,
1572+
'consumer-secret' => $bitbucket_secret,
1573+
],
1574+
];
1575+
$changed = true;
1576+
}
1577+
1578+
// HTTP Basic Authentication.
1579+
$http_basic_auth = getenv( 'HTTP_BASIC_AUTH' );
1580+
if ( ! isset( $composer_auth['http-basic'] ) && is_string( $http_basic_auth ) && '' !== $http_basic_auth ) {
1581+
$http_basic_auth_decoded = json_decode( $http_basic_auth, true /*assoc*/ );
1582+
if ( is_array( $http_basic_auth_decoded ) ) {
1583+
$composer_auth['http-basic'] = $http_basic_auth_decoded;
1584+
$changed = true;
1585+
}
1586+
}
1587+
15361588
if ( $changed ) {
15371589
putenv( 'COMPOSER_AUTH=' . json_encode( $composer_auth ) );
15381590
}

0 commit comments

Comments
 (0)