diff --git a/features/package-install.feature b/features/package-install.feature index 495d77af..fd91d45c 100644 --- a/features/package-install.feature +++ b/features/package-install.feature @@ -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 diff --git a/src/Package_Command.php b/src/Package_Command.php index 12e784a9..8e8c04b9 100644 --- a/src/Package_Command.php +++ b/src/Package_Command.php @@ -222,6 +222,8 @@ 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]; @@ -229,7 +231,11 @@ public function install( $args, $assoc_args ) { } 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 = []; @@ -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//[...subgroups...] or git@github.com:/[...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. *