Skip to content
96 changes: 96 additions & 0 deletions features/package-install.feature
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,102 @@ Feature: Install WP-CLI packages
Success: Uninstalled package.
"""

@github-api
Scenario: Install a package from a Git URL without .git suffix
Given an empty directory

When I run `wp package install https://github.com/wp-cli/google-sitemap-generator-cli`
Then STDOUT should contain:
"""
Installing package wp-cli/google-sitemap-generator-cli
"""
And STDOUT should contain:
"""
Registering https://github.com/wp-cli/google-sitemap-generator-cli.git as a VCS repository...
"""
And STDOUT should contain:
"""
Success: Package installed.
"""

When I run `wp package uninstall wp-cli/google-sitemap-generator-cli`
Then STDOUT should contain:
"""
Success: Uninstalled package.
"""

@github-api
Scenario: Install a package from a Git URL without .git suffix but with a version suffix
Given an empty directory

When I run `wp package install https://github.com/wp-cli/google-sitemap-generator-cli:dev-main`
Then STDOUT should contain:
"""
Installing package wp-cli/google-sitemap-generator-cli (dev-main)
"""
And STDOUT should contain:
"""
Registering https://github.com/wp-cli/google-sitemap-generator-cli.git as a VCS repository...
"""
And STDOUT should contain:
"""
Success: Package installed.
"""

When I run `wp package uninstall wp-cli/google-sitemap-generator-cli`
Then STDOUT should contain:
"""
Success: Uninstalled package.
"""

@github-api
Scenario: Install a package from a GitHub SSH URL without .git suffix
Given an empty directory

When I run `wp package install git@github.com:wp-cli/google-sitemap-generator-cli`
Then STDOUT should contain:
"""
Installing package wp-cli/google-sitemap-generator-cli
"""
And STDOUT should contain:
"""
Registering git@github.com:wp-cli/google-sitemap-generator-cli.git as a VCS repository...
"""
And STDOUT should contain:
"""
Success: Package installed.
"""

When I run `wp package uninstall wp-cli/google-sitemap-generator-cli`
Then STDOUT should contain:
"""
Success: Uninstalled package.
"""

@gitlab-api
Scenario: Install a package from a GitLab URL without .git suffix and nested groups
Given an empty directory

When I run `wp package install https://gitlab.com/wp-cli/wp-cli-test/test-command`
Then STDOUT should contain:
"""
Installing package wp-cli-test/test-command
"""
And STDOUT should contain:
"""
Registering https://gitlab.com/wp-cli/wp-cli-test/test-command.git as a VCS repository...
"""
And STDOUT should contain:
"""
Success: Package installed.
"""

When I run `wp package uninstall wp-cli-test/test-command`
Then STDOUT should contain:
"""
Success: Uninstalled package.
"""

@github-api
Scenario: Install a package from a Git URL with mixed-case git name but lowercase composer.json name
Given an empty directory
Expand Down
27 changes: 26 additions & 1 deletion src/Package_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -222,14 +222,20 @@ public function install( $args, $assoc_args ) {
$git_package = false;
$dir_package = false;
$version = '';
// Append .git suffix for GitHub/GitLab URLs that are missing it.
$package_name = $this->maybe_add_git_suffix( $package_name );
// Parse version suffix from a git URL (e.g. https://github.com/vendor/package.git:dev-main).
if ( preg_match( '#^(.+\.git):([^:]+)$#', $package_name, $url_version_matches ) ) {
$package_name = $url_version_matches[1];
$version = $url_version_matches[2];
}
if ( $this->is_git_repository( $package_name ) ) {
if ( '' === $version ) {
$version = "dev-{$this->get_github_default_branch( $package_name, $insecure )}";
if ( preg_match( '#^(?:https?://github\.com/|git@github\.com:)#i', $package_name ) ) {
$version = "dev-{$this->get_github_default_branch( $package_name, $insecure )}";
} else {
$version = 'dev-master';
}
}
$git_package = $package_name;
$matches = [];
Expand Down Expand Up @@ -1296,6 +1302,25 @@ private function is_git_repository( $package ) {
return '.git' === strtolower( substr( $package, -4, 4 ) );
}

/**
* Appends the .git suffix to GitHub or GitLab URLs that are missing it.
*
* @param string $package_name Package name or URL to normalize.
* @return string Normalized package name or URL.
*/
private function maybe_add_git_suffix( $package_name ) {
// Already has .git suffix (possibly followed by :version).
if ( preg_match( '#\.git(?::[^:]+)?$#i', $package_name ) ) {
return $package_name;
}
// Append .git for GitHub/GitLab HTTPS or SSH URLs, preserving any :version suffix.
// Pattern: (https?://github.com/<user>/<repo>[...subgroups...] or git@github.com:<user>/<repo>[...subgroups...])(:version)?
if ( preg_match( '#^((?:https?://(?:github|gitlab)\.com/|git@(?:github|gitlab)\.com:)[^/:]+(?:/[^/:]+)*)(:.*)?$#i', $package_name, $matches ) ) {
return $matches[1] . '.git' . ( $matches[2] ?? '' );
}
return $package_name;
}

/**
* Checks that `$package_name` matches the name in composer.json at Github.com, and return corrected value if not.
*
Expand Down