diff --git a/features/package-install.feature b/features/package-install.feature index 71733c806..b1f69e8db 100644 --- a/features/package-install.feature +++ b/features/package-install.feature @@ -360,10 +360,18 @@ Feature: Install WP-CLI packages Scenario: Install a package from Git using a shortened package identifier with a specific version Given an empty directory - When I run `wp package install schlessera/test-command:0.1.0` + # Need to specify actual tag. + When I try `wp package install schlessera/test-command:0.1.0` + Then STDERR should contain: + """ + Error: Couldn't download composer.json file from 'https://raw.githubusercontent.com/schlessera/test-command/0.1.0/composer.json' (HTTP code 404). + """ + And STDOUT should be empty + + When I run `wp package install schlessera/test-command:v0.1.0` Then STDOUT should contain: """ - Installing package schlessera/test-command (0.1.0) + Installing package schlessera/test-command (v0.1.0) Updating {PACKAGE_PATH}composer.json to require the package... Registering https://github.com/schlessera/test-command.git as a VCS repository... Using Composer to install the package... @@ -588,6 +596,52 @@ Feature: Install WP-CLI packages rocket """ + @github-api + Scenario: Install a package with a composer.json that differs between versions + Given an empty directory + + When I run `wp package install wp-cli-test/version-composer-json-different:v1.0.0` + Then STDOUT should contain: + """ + Installing package wp-cli-test/version-composer-json-different (v1.0.0) + Updating {PACKAGE_PATH}composer.json to require the package... + """ + And STDOUT should contain: + """ + Success: Package installed. + """ + And the {PACKAGE_PATH}/vendor/wp-cli-test/version-composer-json-different/composer.json file should exist + And the {PACKAGE_PATH}/vendor/wp-cli-test/version-composer-json-different/composer.json file should contain: + """ + 1.0.0 + """ + And the {PACKAGE_PATH}/vendor/wp-cli-test/version-composer-json-different/composer.json file should not contain: + """ + 1.0.1 + """ + And the {PACKAGE_PATH}/vendor/wp-cli/profile-command directory should not exist + + When I run `wp package install wp-cli-test/version-composer-json-different:v1.0.1` + Then STDOUT should contain: + """ + Installing package wp-cli-test/version-composer-json-different (v1.0.1) + Updating {PACKAGE_PATH}composer.json to require the package... + """ + And STDOUT should contain: + """ + Success: Package installed. + """ + And the {PACKAGE_PATH}/vendor/wp-cli-test/version-composer-json-different/composer.json file should exist + And the {PACKAGE_PATH}/vendor/wp-cli-test/version-composer-json-different/composer.json file should contain: + """ + 1.0.1 + """ + And the {PACKAGE_PATH}/vendor/wp-cli-test/version-composer-json-different/composer.json file should not contain: + """ + 1.0.0 + """ + And the {PACKAGE_PATH}/vendor/wp-cli/profile-command directory should exist + Scenario: Install a package from a local zip Given an empty directory And I run `wget -q -O google-sitemap-generator-cli.zip https://github.com/wp-cli/google-sitemap-generator-cli/archive/master.zip` diff --git a/src/Package_Command.php b/src/Package_Command.php index 971a62c72..6ad7d8145 100644 --- a/src/Package_Command.php +++ b/src/Package_Command.php @@ -278,7 +278,7 @@ public function install( $args, $assoc_args ) { if ( is_string( $package ) ) { if ( $this->is_git_repository( $package ) ) { $git_package = $package; - $package_name = $this->check_git_package_name( $package_name ); + $package_name = $this->check_git_package_name( $package_name, $version ); } } elseif ( $package_name !== $package->getPrettyName() ) { // BC support for specifying lowercase names for mixed-case package index packages - don't bother warning. @@ -972,10 +972,14 @@ private function is_git_repository( $package ) { /** * Checks that `$package_name` matches the name in the repo composer.json, and return corrected value if not. + * + * @string $package_name Package name to check. + * @string $version Optional. Package version. Default 'master'. + * @string Package name, possibly changed to match that in repo. */ - private function check_git_package_name( $package_name ) { + private function check_git_package_name( $package_name, $version = '' ) { // Generate raw git URL of composer.json file. - $raw_content_url = 'https://raw.githubusercontent.com/' . $package_name . '/master/composer.json'; + $raw_content_url = 'https://raw.githubusercontent.com/' . $package_name . '/' . $this->get_raw_git_version( $version ) . '/composer.json'; $github_token = getenv( 'GITHUB_TOKEN' ); // Use GITHUB_TOKEN if available to avoid authorization failures or rate-limiting. $headers = $github_token ? array( 'Authorization' => 'token ' . $github_token ) : array(); @@ -1004,6 +1008,32 @@ private function check_git_package_name( $package_name ) { return $package_name; } + /** + * Get the version to use for raw github request. Very basic. + * + * @string $version Package version. + * @string Version to use for github request. + */ + private function get_raw_git_version( $version ) { + if ( '' !== $version ) { + // If Composer hash given then just use whatever's after it. + if ( false !== ( $hash_pos = strpos( $version, '#' ) ) ) { + $version = substr( $version, $hash_pos + 1 ); + } else { + // Strip any Composer 'dev-' prefix. + if ( 0 === strncmp( $version, 'dev-', 4 ) ) { + $version = substr( $version, 4 ); + } + // Ignore/strip any relative suffixes. + if ( false !== ( $rel_pos = strpos( $version, '^' ) ) || false !== ( $rel_pos = strpos( $version, '~' ) ) ) { + $version = substr( $version, 0, $rel_pos ); + } + } + } + // Default to master. + return '' === $version ? 'master' : $version; + } + /** * Sets `COMPOSER_AUTH` environment variable (which Composer merges into the config setup in `Composer\Factory::createConfig()`) depending on available environment variables. * Avoids authorization failures when accessing various sites.