From f8cdf2949bdce5b37ea09c64b208407f9e60a2e7 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sun, 18 Jun 2017 20:00:19 +0100 Subject: [PATCH 001/214] Add paging to github release query. Get tests to work locally. --- features/bootstrap/FeatureContext.php | 34 +++++++++++++++++---------- features/cli-info.feature | 5 ++++ features/cli.feature | 21 +++++++---------- features/steps/given.php | 11 ++++++++- php/commands/src/CLI_Command.php | 29 ++++++++++++++++++----- php/utils.php | 2 +- 6 files changed, 69 insertions(+), 33 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 96e1647dfa..16a1bdc604 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -8,6 +8,9 @@ use \WP_CLI\Process; use \WP_CLI\Utils; +use Symfony\Component\Filesystem\Filesystem, + Symfony\Component\Filesystem\Exception\IOExceptionInterface; + // Inside a community package if ( file_exists( __DIR__ . '/utils.php' ) ) { require_once __DIR__ . '/utils.php'; @@ -44,7 +47,7 @@ */ class FeatureContext extends BehatContext implements ClosuredContextInterface { - private static $cache_dir, $suite_cache_dir; + private static $cache_dir, $suite_cache_dir, $fs; private static $db_settings = array( 'dbname' => 'wp_cli_test', @@ -113,7 +116,7 @@ public static function prepare( SuiteEvent $event ) { */ public static function afterSuite( SuiteEvent $event ) { if ( self::$suite_cache_dir ) { - Process::create( Utils\esc_cmd( 'rm -r %s', self::$suite_cache_dir ), null, self::get_process_env_variables() )->run(); + self::$fs->remove( self::$suite_cache_dir ); } } @@ -131,13 +134,13 @@ public function afterScenario( $event ) { if ( isset( $this->variables['RUN_DIR'] ) ) { // remove altered WP install, unless there's an error if ( $event->getResult() < 4 && 0 === strpos( $this->variables['RUN_DIR'], sys_get_temp_dir() ) ) { - $this->proc( Utils\esc_cmd( 'rm -rf %s', $this->variables['RUN_DIR'] ) )->run(); + self::$fs->remove( $this->variables['RUN_DIR'] ); } } // Remove WP-CLI package directory if ( isset( $this->variables['PACKAGE_PATH'] ) ) { - $this->proc( Utils\esc_cmd( 'rm -rf %s', $this->variables['PACKAGE_PATH'] ) )->run(); + self::$fs->remove( $this->variables['PACKAGE_PATH'] ); } foreach ( $this->running_procs as $proc ) { @@ -192,6 +195,9 @@ public function __construct( array $parameters ) { $this->drop_db(); $this->set_cache_dir(); $this->variables['CORE_CONFIG_SETTINGS'] = Utils\assoc_args_to_str( self::$db_settings ); + if ( ! self::$fs ) { + self::$fs = new FileSystem; + } } public function getStepDefinitionResources() { @@ -294,20 +300,17 @@ public function download_phar( $version = 'same' ) { . '.phar'; Process::create( \WP_CLI\Utils\esc_cmd( - 'curl -sSL %s > %s', + 'curl -sSL %1$s > %2$s && chmod +x %2$s', $download_url, $this->variables['PHAR_PATH'] ) )->run_check(); - - Process::create( \WP_CLI\Utils\esc_cmd( - 'chmod +x %s', - $this->variables['PHAR_PATH'] - ) )->run_check(); } private function set_cache_dir() { $path = sys_get_temp_dir() . '/wp-cli-test-cache'; - $this->proc( Utils\esc_cmd( 'mkdir -p %s', $path ) )->run_check(); + if ( ! file_exists( $path ) ) { + mkdir( $path, 0777, true ); + } $this->variables['CACHE_DIR'] = $path; } @@ -375,6 +378,13 @@ public function move_files( $src, $dest ) { rename( $this->variables['RUN_DIR'] . "/$src", $this->variables['RUN_DIR'] . "/$dest" ); } + /** + * Remove a directory (recursive). + */ + public function remove_dir( $dir ) { + self::$fs->remove( $dir ); + } + public function add_line_to_wp_config( &$wp_config_code, $line ) { $token = "/* That's all, stop editing!"; @@ -388,7 +398,7 @@ public function download_wp( $subdir = '' ) { mkdir( $dest_dir ); } - $this->proc( Utils\esc_cmd( "cp -r %s/* %s", self::$cache_dir, $dest_dir ) )->run_check(); + self::$fs->mirror( self::$cache_dir, $dest_dir ); // disable emailing mkdir( $dest_dir . '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/wp-content/mu-plugins' ); diff --git a/features/cli-info.feature b/features/cli-info.feature index b5cedc1457..bbef21cffd 100644 --- a/features/cli-info.feature +++ b/features/cli-info.feature @@ -1,7 +1,12 @@ Feature: Review CLI information + Background: + When I run `wp package path` + Then save STDOUT as {PACKAGE_PATH} + Scenario: Get the path to the packages directory Given an empty directory + And an empty {PACKAGE_PATH} directory When I run `wp cli info --format=json` Then STDOUT should be JSON containing: diff --git a/features/cli.feature b/features/cli.feature index 4634b09ab7..20479a2ee9 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -15,19 +15,17 @@ Feature: `wp cli` tasks {TRUE_VERSION} """ - @github-api Scenario: Check for updates Given an empty directory And a new Phar with version "0.0.0" - When I run `{PHAR_PATH} cli check-update` + When I run `WP_CLI_TEST_USE_GITHUB_API_CACHE=1 {PHAR_PATH} cli check-update` Then STDOUT should contain: """ package_url """ And STDERR should be empty - @github-api Scenario: Do WP-CLI Update Given an empty directory And a new Phar with version "0.0.0" @@ -42,7 +40,7 @@ Feature: `wp cli` tasks 0.0.0 """ - When I run `{PHAR_PATH} cli update --yes` + When I run `WP_CLI_TEST_USE_GITHUB_API_CACHE=1 {PHAR_PATH} cli update --yes` Then STDOUT should contain: """ md5 hash verified: @@ -64,7 +62,7 @@ Feature: `wp cli` tasks 0.0.0 """ - @github-api + # The WP_CLI_TEST_USE_GITHUB_API_CACHE (github-api-cache.unyson.io) server doesn't do paging so can't use here. Scenario: Patch update from 0.14.0 to 0.14.1 Given an empty directory And a new Phar with version "0.14.0" @@ -93,12 +91,11 @@ Feature: `wp cli` tasks WP-CLI 0.14.1 """ - @github-api Scenario: Not a patch update from 0.14.0 Given an empty directory And a new Phar with version "0.14.0" - When I run `{PHAR_PATH} cli update --no-patch --yes` + When I run `WP_CLI_TEST_USE_GITHUB_API_CACHE=1 {PHAR_PATH} cli update --no-patch --yes` Then STDOUT should contain: """ Success: @@ -110,12 +107,11 @@ Feature: `wp cli` tasks And STDERR should be empty And the return code should be 0 - @require-php-5.6 Scenario: Install WP-CLI nightly Given an empty directory And a new Phar with version "0.14.0" - When I run `{PHAR_PATH} cli update --nightly --yes` + When I run `WP_CLI_TEST_USE_GITHUB_API_CACHE=1 {PHAR_PATH} cli update --nightly --yes` Then STDOUT should contain: """ md5 hash verified: @@ -128,7 +124,6 @@ Feature: `wp cli` tasks And STDERR should be empty And the return code should be 0 - @github-api @less-than-php-7 Scenario: Install WP-CLI stable Given an empty directory And a new Phar with version "0.14.0" @@ -137,11 +132,11 @@ Feature: `wp cli` tasks y """ - When I run `{PHAR_PATH} cli check-update --minor --field=version` + When I run `WP_CLI_TEST_USE_GITHUB_API_CACHE=1 {PHAR_PATH} cli check-update --field=version | head -1` Then STDOUT should not be empty And save STDOUT as {UPDATE_VERSION} - When I run `{PHAR_PATH} cli update --stable < session` + When I run `WP_CLI_TEST_USE_GITHUB_API_CACHE=1 {PHAR_PATH} cli update --stable < session` Then STDOUT should contain: """ You have version 0.14.0. Would you like to update to the latest stable release? [y/n] @@ -157,7 +152,7 @@ Feature: `wp cli` tasks And STDERR should be empty And the return code should be 0 - When I run `{PHAR_PATH} cli check-update` + When I run `WP_CLI_TEST_USE_GITHUB_API_CACHE=1 {PHAR_PATH} cli check-update` Then STDOUT should be: """ Success: WP-CLI is at the latest version. diff --git a/features/steps/given.php b/features/steps/given.php index c785df1137..3e92c1b8f0 100644 --- a/features/steps/given.php +++ b/features/steps/given.php @@ -10,6 +10,12 @@ function ( $world ) { } ); +$steps->Given( '/^an empty ([^\s]+) directory$/', + function ( $world, $dir ) { + $world->remove_dir( $world->replace_variables( $dir ) ); + } +); + $steps->Given( '/^an empty cache/', function ( $world ) { $world->variables['SUITE_CACHE_DIR'] = FeatureContext::create_cache_dir(); @@ -20,7 +26,10 @@ function ( $world ) { function ( $world, $path, PyStringNode $content ) { $content = (string) $content . "\n"; $full_path = $world->variables['RUN_DIR'] . "/$path"; - Process::create( \WP_CLI\utils\esc_cmd( 'mkdir -p %s', dirname( $full_path ) ) )->run_check(); + $dir = dirname( $full_path ); + if ( ! file_exists( $dir ) ) { + mkdir( $dir, 0777, true ); + } file_put_contents( $full_path, $content ); } ); diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index 69437a0198..3ccf03a051 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -343,7 +343,14 @@ class_exists( '\cli\Colors' ); // This autoloads \cli\Colors - after we move the * Returns update information. */ private function get_updates( $assoc_args ) { - $url = 'https://api.github.com/repos/wp-cli/wp-cli/releases'; + $github_server = 'https://api.github.com'; + $cache_server = 'http://github-api-cache.unyson.io'; + + if ( getenv( 'WP_CLI_TEST_USE_GITHUB_API_CACHE' ) ) { + $url = $cache_server . '/repos/wp-cli/wp-cli/releases'; + } else { + $url = $github_server . '/repos/wp-cli/wp-cli/releases'; + } $options = array( 'timeout' => 30 @@ -352,13 +359,23 @@ private function get_updates( $assoc_args ) { $headers = array( 'Accept' => 'application/json' ); - $response = Utils\http_request( 'GET', $url, $headers, $options ); - if ( ! $response->success || 200 !== $response->status_code ) { - WP_CLI::error( sprintf( "Failed to get latest version (HTTP code %d).", $response->status_code ) ); - } + $release_data = array(); + + while ( true ) { + $response = Utils\http_request( 'GET', $url, $headers, $options ); + + if ( ! $response->success || 200 !== $response->status_code ) { + WP_CLI::error( sprintf( "Failed to get latest version (HTTP code %d).", $response->status_code ) ); + } + + $release_data = array_merge( $release_data, json_decode( $response->body ) ); - $release_data = json_decode( $response->body ); + if ( empty( $response->headers['link'] ) || ! preg_match( '/<([^>]+)>; rel="next"/', $response->headers['link'], $matches ) ) { + break; + } + $url = $matches[1]; + } $updates = array( 'major' => false, diff --git a/php/utils.php b/php/utils.php index dd187cd6d5..0ab0747e10 100644 --- a/php/utils.php +++ b/php/utils.php @@ -568,7 +568,7 @@ function http_request( $method, $url, $data = null, $headers = array(), $options } } if ( empty( $options['verify'] ) ){ - WP_CLI::error_log( "Cannot find SSL certificate." ); + WP_CLI::error( "Cannot find SSL certificate." ); } } From 521f3a46402f5d7a019eac6d32413563e8e9c07b Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 19 Jun 2017 10:18:47 +0100 Subject: [PATCH 002/214] Use cache in github requests. --- features/bootstrap/FeatureContext.php | 8 ++- features/cli.feature | 15 +++-- php/WP_CLI/Process.php | 35 ++++++++---- php/WP_CLI/ProcessRun.php | 3 + php/commands/src/CLI_Command.php | 53 ++++++++++++------ utils/make-phar-spec.php | 7 +++ utils/make-phar.php | 80 +++++++++++++++++++-------- 7 files changed, 141 insertions(+), 60 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 16a1bdc604..00484d0fa3 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -118,6 +118,10 @@ public static function afterSuite( SuiteEvent $event ) { if ( self::$suite_cache_dir ) { self::$fs->remove( self::$suite_cache_dir ); } + if ( getenv( 'WP_CLI_TEST_PROCESS_RUN_TIMES' ) ) { + arsort( Process::$run_times ); + error_log( "afterSuite: run_times\n" . print_r( Process::$run_times, true ) ); + } } /** @@ -278,7 +282,7 @@ public function build_phar( $version = 'same' ) { } $this->proc( Utils\esc_cmd( - 'php -dphar.readonly=0 %1$s %2$s --version=%3$s && chmod +x %2$s', + 'php -dphar.readonly=0 %1$s %2$s --version=%3$s --quiet --min-build && chmod +x %2$s', $make_phar_path, $this->variables['PHAR_PATH'], $version @@ -300,7 +304,7 @@ public function download_phar( $version = 'same' ) { . '.phar'; Process::create( \WP_CLI\Utils\esc_cmd( - 'curl -sSL %1$s > %2$s && chmod +x %2$s', + 'curl -sSfL %1$s > %2$s && chmod +x %2$s', $download_url, $this->variables['PHAR_PATH'] ) )->run_check(); diff --git a/features/cli.feature b/features/cli.feature index 20479a2ee9..9fa34533bc 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -19,7 +19,7 @@ Feature: `wp cli` tasks Given an empty directory And a new Phar with version "0.0.0" - When I run `WP_CLI_TEST_USE_GITHUB_API_CACHE=1 {PHAR_PATH} cli check-update` + When I run `{PHAR_PATH} cli check-update` Then STDOUT should contain: """ package_url @@ -40,7 +40,7 @@ Feature: `wp cli` tasks 0.0.0 """ - When I run `WP_CLI_TEST_USE_GITHUB_API_CACHE=1 {PHAR_PATH} cli update --yes` + When I run `{PHAR_PATH} cli update --yes` Then STDOUT should contain: """ md5 hash verified: @@ -62,7 +62,6 @@ Feature: `wp cli` tasks 0.0.0 """ - # The WP_CLI_TEST_USE_GITHUB_API_CACHE (github-api-cache.unyson.io) server doesn't do paging so can't use here. Scenario: Patch update from 0.14.0 to 0.14.1 Given an empty directory And a new Phar with version "0.14.0" @@ -95,7 +94,7 @@ Feature: `wp cli` tasks Given an empty directory And a new Phar with version "0.14.0" - When I run `WP_CLI_TEST_USE_GITHUB_API_CACHE=1 {PHAR_PATH} cli update --no-patch --yes` + When I run `{PHAR_PATH} cli update --no-patch --yes` Then STDOUT should contain: """ Success: @@ -111,7 +110,7 @@ Feature: `wp cli` tasks Given an empty directory And a new Phar with version "0.14.0" - When I run `WP_CLI_TEST_USE_GITHUB_API_CACHE=1 {PHAR_PATH} cli update --nightly --yes` + When I run `{PHAR_PATH} cli update --nightly --yes` Then STDOUT should contain: """ md5 hash verified: @@ -132,11 +131,11 @@ Feature: `wp cli` tasks y """ - When I run `WP_CLI_TEST_USE_GITHUB_API_CACHE=1 {PHAR_PATH} cli check-update --field=version | head -1` + When I run `{PHAR_PATH} cli check-update --field=version | head -1` Then STDOUT should not be empty And save STDOUT as {UPDATE_VERSION} - When I run `WP_CLI_TEST_USE_GITHUB_API_CACHE=1 {PHAR_PATH} cli update --stable < session` + When I run `{PHAR_PATH} cli update --stable < session` Then STDOUT should contain: """ You have version 0.14.0. Would you like to update to the latest stable release? [y/n] @@ -152,7 +151,7 @@ Feature: `wp cli` tasks And STDERR should be empty And the return code should be 0 - When I run `WP_CLI_TEST_USE_GITHUB_API_CACHE=1 {PHAR_PATH} cli check-update` + When I run `{PHAR_PATH} cli check-update` Then STDOUT should be: """ Success: WP-CLI is at the latest version. diff --git a/php/WP_CLI/Process.php b/php/WP_CLI/Process.php index 74939c5d0d..09a2c28490 100644 --- a/php/WP_CLI/Process.php +++ b/php/WP_CLI/Process.php @@ -23,6 +23,13 @@ public static function create( $command, $cwd = null, $env = array() ) { } private $command, $cwd, $env; + private static $descriptors = array( + 0 => STDIN, + 1 => array( 'pipe', 'w' ), + 2 => array( 'pipe', 'w' ), + ); + + static $run_times = array(); private function __construct() {} @@ -32,15 +39,9 @@ private function __construct() {} * @return ProcessRun */ public function run() { - $cwd = $this->cwd; - - $descriptors = array( - 0 => STDIN, - 1 => array( 'pipe', 'w' ), - 2 => array( 'pipe', 'w' ), - ); + $start_time = microtime( true ); - $proc = proc_open( $this->command, $descriptors, $pipes, $cwd, $this->env ); + $proc = proc_open( $this->command, self::$descriptors, $pipes, $this->cwd, $this->env ); $stdout = stream_get_contents( $pipes[1] ); fclose( $pipes[1] ); @@ -48,13 +49,25 @@ public function run() { $stderr = stream_get_contents( $pipes[2] ); fclose( $pipes[2] ); + $return_code = proc_close( $proc ); + + $run_time = microtime( true ) - $start_time; + + if ( getenv( 'WP_CLI_TEST_PROCESS_RUN_TIMES' ) ) { + if ( ! isset( self::$run_times[ $this->command ] ) ) { + self::$run_times[ $this->command ] = 0; + } + self::$run_times[ $this->command ] += $run_time; + } + return new ProcessRun( array( 'stdout' => $stdout, 'stderr' => $stderr, - 'return_code' => proc_close( $proc ), + 'return_code' => $return_code, 'command' => $this->command, - 'cwd' => $cwd, - 'env' => $this->env + 'cwd' => $this->cwd, + 'env' => $this->env, + 'run_time' => $run_time, ) ); } diff --git a/php/WP_CLI/ProcessRun.php b/php/WP_CLI/ProcessRun.php index 4611cfbb63..6157acf114 100644 --- a/php/WP_CLI/ProcessRun.php +++ b/php/WP_CLI/ProcessRun.php @@ -7,6 +7,8 @@ */ class ProcessRun { + var $stdout, $stderr, $return_code, $command, $cwd, $env, $run_time; + /** * @var array $props Properties of executed command. */ @@ -25,6 +27,7 @@ public function __toString() { $out = "$ $this->command\n"; $out .= "$this->stdout\n$this->stderr"; $out .= "cwd: $this->cwd\n"; + $out .= "run time: $this->run_time\n"; $out .= "exit status: $this->return_code"; return $out; diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index 3ccf03a051..73c0ee247e 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -343,14 +343,7 @@ class_exists( '\cli\Colors' ); // This autoloads \cli\Colors - after we move the * Returns update information. */ private function get_updates( $assoc_args ) { - $github_server = 'https://api.github.com'; - $cache_server = 'http://github-api-cache.unyson.io'; - - if ( getenv( 'WP_CLI_TEST_USE_GITHUB_API_CACHE' ) ) { - $url = $cache_server . '/repos/wp-cli/wp-cli/releases'; - } else { - $url = $github_server . '/repos/wp-cli/wp-cli/releases'; - } + $url = 'https://api.github.com/repos/wp-cli/wp-cli/releases'; $options = array( 'timeout' => 30 @@ -362,19 +355,47 @@ private function get_updates( $assoc_args ) { $release_data = array(); - while ( true ) { - $response = Utils\http_request( 'GET', $url, $headers, $options ); + // Cache results. + $cache = WP_CLI::get_cache(); + $cache_key = 'github_releases'; - if ( ! $response->success || 200 !== $response->status_code ) { - WP_CLI::error( sprintf( "Failed to get latest version (HTTP code %d).", $response->status_code ) ); + if ( $cache->has( $cache_key ) ) { + $data = unserialize( $cache->read( $cache_key ) ); + if ( time() < $data['time'] + $data['max_age'] ) { + $release_data = $data['release_data']; + } else { + $cache->remove( $cache_key ); } + unset( $data ); + } - $release_data = array_merge( $release_data, json_decode( $response->body ) ); + if ( ! $release_data ) { + $max_age = $time = 0; + while ( true ) { + $response = Utils\http_request( 'GET', $url, $headers, $options ); - if ( empty( $response->headers['link'] ) || ! preg_match( '/<([^>]+)>; rel="next"/', $response->headers['link'], $matches ) ) { - break; + if ( ! $response->success || 200 !== $response->status_code ) { + WP_CLI::error( sprintf( "Failed to get latest version (HTTP code %d).", $response->status_code ) ); + } + + $release_data = array_merge( $release_data, json_decode( $response->body ) ); + + if ( ! $max_age && isset( $response->headers['cache-control'] ) && preg_match( '/max-age=([0-9]+)/', $response->headers['cache-control'], $matches ) ) { + $max_age = (int) $matches[1]; + if ( empty( $response->headers['date'] ) || false === ( $time = strtotime( $response->headers['date'] ) ) ) { + $time = time(); + } + } + + if ( empty( $response->headers['link'] ) || ! preg_match( '/<([^>]+)>; rel="next"/', $response->headers['link'], $matches ) ) { + break; + } + + $url = $matches[1]; + } + if ( $max_age ) { + $cache->write( $cache_key, serialize( compact( 'max_age', 'time', 'release_data' ) ) ); } - $url = $matches[1]; } $updates = array( diff --git a/utils/make-phar-spec.php b/utils/make-phar-spec.php index d5f3165c43..2e4f446c74 100644 --- a/utils/make-phar-spec.php +++ b/utils/make-phar-spec.php @@ -26,5 +26,12 @@ 'default' => false, 'desc' => 'Suppress informational messages', ), + + 'min-build' => array( + 'runtime' => '', + 'file' => '', + 'default' => false, + 'desc' => 'Create minimum build, leaving out support files', + ), ); diff --git a/utils/make-phar.php b/utils/make-phar.php index 241565446c..6b0932976d 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -32,6 +32,8 @@ define( 'BE_QUIET', isset( $runtime_config['quiet'] ) && $runtime_config['quiet'] ); +define( 'MIN_BUILD', isset( $runtime_config['min-build'] ) && $runtime_config['min-build'] ); + $current_version = trim( file_get_contents( WP_CLI_ROOT . '/VERSION' ) ); if ( isset( $runtime_config['version'] ) ) { @@ -69,28 +71,58 @@ function set_file_contents( $phar, $path, $content ) { // PHP files $finder = new Finder(); -$finder - ->files() - ->ignoreVCS(true) - ->name('*.php') - ->in(WP_CLI_ROOT . '/php') - ->in(WP_CLI_ROOT . '/features') - ->in(WP_CLI_VENDOR_DIR . '/wp-cli') - ->in(WP_CLI_VENDOR_DIR . '/mustache') - ->in(WP_CLI_VENDOR_DIR . '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/rmccue/requests') - ->in(WP_CLI_VENDOR_DIR . '/composer') - ->in(WP_CLI_VENDOR_DIR . '/psr') - ->in(WP_CLI_VENDOR_DIR . '/seld') - ->in(WP_CLI_VENDOR_DIR . '/symfony') - ->in(WP_CLI_VENDOR_DIR . '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/nb/oxymel') - ->in(WP_CLI_VENDOR_DIR . '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/ramsey/array_column') - ->in(WP_CLI_VENDOR_DIR . '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/justinrainbow/json-schema') - ->exclude('test') - ->exclude('tests') - ->exclude('Test') - ->exclude('Tests') - ->exclude('php-cli-tools/examples') - ; +if ( MIN_BUILD ) { + $finder + ->files() + ->ignoreVCS(true) + ->name('*.php') + ->in(WP_CLI_ROOT . '/php') + ->in(WP_CLI_VENDOR_DIR . '/wp-cli') + ->in(WP_CLI_VENDOR_DIR . '/mustache') + ->in(WP_CLI_VENDOR_DIR . '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/rmccue/requests') + ->in(WP_CLI_VENDOR_DIR . '/composer') + ->in(WP_CLI_VENDOR_DIR . '/psr') + ->in(WP_CLI_VENDOR_DIR . '/seld') + ->in(WP_CLI_VENDOR_DIR . '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/symfony/finder') + ->in(WP_CLI_VENDOR_DIR . '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/symfony/polyfill-mbstring') + ->in(WP_CLI_VENDOR_DIR . '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/ramsey/array_column') + ->in(WP_CLI_VENDOR_DIR . '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/justinrainbow/json-schema') + ->notName('behat-tags.php') + ->exclude('composer/ca-bundle') + ->exclude('composer/semver') + ->exclude('composer/spdx-licenses') + ->exclude('composer/src') + ->exclude('examples') + ->exclude('features') + ->exclude('test') + ->exclude('tests') + ->exclude('Test') + ->exclude('Tests') + ; +} else { + $finder + ->files() + ->ignoreVCS(true) + ->name('*.php') + ->in(WP_CLI_ROOT . '/php') + ->in(WP_CLI_ROOT . '/features') + ->in(WP_CLI_VENDOR_DIR . '/wp-cli') + ->in(WP_CLI_VENDOR_DIR . '/mustache') + ->in(WP_CLI_VENDOR_DIR . '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/rmccue/requests') + ->in(WP_CLI_VENDOR_DIR . '/composer') + ->in(WP_CLI_VENDOR_DIR . '/psr') + ->in(WP_CLI_VENDOR_DIR . '/seld') + ->in(WP_CLI_VENDOR_DIR . '/symfony') + ->in(WP_CLI_VENDOR_DIR . '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/nb/oxymel') + ->in(WP_CLI_VENDOR_DIR . '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/ramsey/array_column') + ->in(WP_CLI_VENDOR_DIR . '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/justinrainbow/json-schema') + ->exclude('test') + ->exclude('tests') + ->exclude('Test') + ->exclude('Tests') + ->exclude('php-cli-tools/examples') + ; +} foreach ( $finder as $file ) { add_file( $phar, $file ); @@ -155,7 +187,9 @@ function set_file_contents( $phar, $path, $content ) { add_file( $phar, WP_CLI_VENDOR_DIR . '/autoload.php' ); add_file( $phar, WP_CLI_VENDOR_DIR . '/autoload_commands.php' ); add_file( $phar, WP_CLI_VENDOR_DIR . '/autoload_framework.php' ); -add_file( $phar, WP_CLI_ROOT . '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/ci/behat-tags.php' ); +if ( ! MIN_BUILD ) { + add_file( $phar, WP_CLI_ROOT . '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/ci/behat-tags.php' ); +} add_file( $phar, WP_CLI_VENDOR_DIR . '/composer/ca-bundle/res/cacert.pem' ); add_file( $phar, WP_CLI_VENDOR_DIR . '/composer/composer/LICENSE' ); add_file( $phar, WP_CLI_VENDOR_DIR . '/composer/composer/res/composer-schema.json' ); From 37dcab6d037f05fe4b4dc79b76fd40c69c2fde0e Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 19 Jun 2017 11:05:56 +0100 Subject: [PATCH 003/214] Put back github-api tags but try only setting for PHP < 5.6. --- ci/behat-tags.php | 6 ++++-- features/cli.feature | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ci/behat-tags.php b/ci/behat-tags.php index ee51fc91ee..16e70ef481 100644 --- a/ci/behat-tags.php +++ b/ci/behat-tags.php @@ -44,8 +44,10 @@ function version_tags( $prefix, $current, $operator = '<' ) { version_tags( 'less-than-php', PHP_VERSION, '>' ) ); -# Skip Github API tests by default because of rate limiting. See https://github.com/wp-cli/wp-cli/issues/1612 -$skip_tags[] = '@github-api'; +# Skip Github API tests by default for PHP < 5.6 because of rate limiting. See https://github.com/wp-cli/wp-cli/issues/1612 +if ( versions_compare( PHP_VERSION, '5.6', '<' ) { + $skip_tags[] = '@github-api'; +} # Skip tests known to be broken. $skip_tags[] = '@broken'; diff --git a/features/cli.feature b/features/cli.feature index 9fa34533bc..ed433a0467 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -15,6 +15,7 @@ Feature: `wp cli` tasks {TRUE_VERSION} """ + @github-api Scenario: Check for updates Given an empty directory And a new Phar with version "0.0.0" @@ -26,6 +27,7 @@ Feature: `wp cli` tasks """ And STDERR should be empty + @github-api Scenario: Do WP-CLI Update Given an empty directory And a new Phar with version "0.0.0" @@ -62,6 +64,7 @@ Feature: `wp cli` tasks 0.0.0 """ + @github-api Scenario: Patch update from 0.14.0 to 0.14.1 Given an empty directory And a new Phar with version "0.14.0" @@ -90,6 +93,7 @@ Feature: `wp cli` tasks WP-CLI 0.14.1 """ + @github-api Scenario: Not a patch update from 0.14.0 Given an empty directory And a new Phar with version "0.14.0" @@ -106,6 +110,7 @@ Feature: `wp cli` tasks And STDERR should be empty And the return code should be 0 + @github-api Scenario: Install WP-CLI nightly Given an empty directory And a new Phar with version "0.14.0" @@ -123,6 +128,7 @@ Feature: `wp cli` tasks And STDERR should be empty And the return code should be 0 + @github-api Scenario: Install WP-CLI stable Given an empty directory And a new Phar with version "0.14.0" From e3baa665e2211d31510f7eabfd5364623b92d76c Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 19 Jun 2017 11:14:19 +0100 Subject: [PATCH 004/214] Fix syntax error. --- ci/behat-tags.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/behat-tags.php b/ci/behat-tags.php index 16e70ef481..da935436ab 100644 --- a/ci/behat-tags.php +++ b/ci/behat-tags.php @@ -45,7 +45,7 @@ function version_tags( $prefix, $current, $operator = '<' ) { ); # Skip Github API tests by default for PHP < 5.6 because of rate limiting. See https://github.com/wp-cli/wp-cli/issues/1612 -if ( versions_compare( PHP_VERSION, '5.6', '<' ) { +if ( versions_compare( PHP_VERSION, '5.6', '<' ) ) { $skip_tags[] = '@github-api'; } From eb7b3f7b932415549443fec4668c0be0d8ba30c9 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 19 Jun 2017 11:15:17 +0100 Subject: [PATCH 005/214] Fix func spelling. --- ci/behat-tags.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/behat-tags.php b/ci/behat-tags.php index da935436ab..b055e3b98b 100644 --- a/ci/behat-tags.php +++ b/ci/behat-tags.php @@ -45,7 +45,7 @@ function version_tags( $prefix, $current, $operator = '<' ) { ); # Skip Github API tests by default for PHP < 5.6 because of rate limiting. See https://github.com/wp-cli/wp-cli/issues/1612 -if ( versions_compare( PHP_VERSION, '5.6', '<' ) ) { +if ( version_compare( PHP_VERSION, '5.6', '<' ) ) { $skip_tags[] = '@github-api'; } From 89834577fc41cd893da24149ccfacfca949b0dbc Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 19 Jun 2017 12:29:43 +0100 Subject: [PATCH 006/214] Try not setting github-api tag but artificially bumping max_arg if BEHAT_RUN. --- ci/behat-tags.php | 5 ----- features/cli.feature | 1 - php/commands/src/CLI_Command.php | 15 +++++++-------- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/ci/behat-tags.php b/ci/behat-tags.php index b055e3b98b..28b63b3757 100644 --- a/ci/behat-tags.php +++ b/ci/behat-tags.php @@ -44,11 +44,6 @@ function version_tags( $prefix, $current, $operator = '<' ) { version_tags( 'less-than-php', PHP_VERSION, '>' ) ); -# Skip Github API tests by default for PHP < 5.6 because of rate limiting. See https://github.com/wp-cli/wp-cli/issues/1612 -if ( version_compare( PHP_VERSION, '5.6', '<' ) ) { - $skip_tags[] = '@github-api'; -} - # Skip tests known to be broken. $skip_tags[] = '@broken'; diff --git a/features/cli.feature b/features/cli.feature index ed433a0467..e223fa518c 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -110,7 +110,6 @@ Feature: `wp cli` tasks And STDERR should be empty And the return code should be 0 - @github-api Scenario: Install WP-CLI nightly Given an empty directory And a new Phar with version "0.14.0" diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index 73c0ee247e..78251772e1 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -361,7 +361,7 @@ private function get_updates( $assoc_args ) { if ( $cache->has( $cache_key ) ) { $data = unserialize( $cache->read( $cache_key ) ); - if ( time() < $data['time'] + $data['max_age'] ) { + if ( time() <= $data['time'] + $data['max_age'] ) { $release_data = $data['release_data']; } else { $cache->remove( $cache_key ); @@ -371,7 +371,7 @@ private function get_updates( $assoc_args ) { if ( ! $release_data ) { $max_age = $time = 0; - while ( true ) { + do { $response = Utils\http_request( 'GET', $url, $headers, $options ); if ( ! $response->success || 200 !== $response->status_code ) { @@ -382,17 +382,16 @@ private function get_updates( $assoc_args ) { if ( ! $max_age && isset( $response->headers['cache-control'] ) && preg_match( '/max-age=([0-9]+)/', $response->headers['cache-control'], $matches ) ) { $max_age = (int) $matches[1]; + if ( getenv( 'BEHAT_RUN' ) ) { + // Bump it up artificially for behat test runs. + $max_age = max( $max_age, 600 ); + } if ( empty( $response->headers['date'] ) || false === ( $time = strtotime( $response->headers['date'] ) ) ) { $time = time(); } } + } while ( ! empty( $response->headers['link'] ) && preg_match( '/<([^>]+)>; rel="next"/', $response->headers['link'], $matches ) && ( $url = $matches[1] ) ); - if ( empty( $response->headers['link'] ) || ! preg_match( '/<([^>]+)>; rel="next"/', $response->headers['link'], $matches ) ) { - break; - } - - $url = $matches[1]; - } if ( $max_age ) { $cache->write( $cache_key, serialize( compact( 'max_age', 'time', 'release_data' ) ) ); } From 6ab5281efaee0e551c8ff8dde5cfc04c2593f1aa Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 19 Jun 2017 13:16:22 +0100 Subject: [PATCH 007/214] Debug PHP 5.3 fail. --- .travis.yml | 12 ------------ ci/test.sh | 2 +- php/commands/src/CLI_Command.php | 4 ++++ 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index e3c0571b72..1ed9e611e2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,18 +8,6 @@ env: matrix: include: - - php: 7.1 - env: WP_VERSION=latest - - php: 7.0 - env: WP_VERSION=latest - - php: 5.6 - env: WP_VERSION=trunk - - php: 5.6 - env: WP_VERSION=latest - - php: 5.6 - env: WP_VERSION=latest BUILD=git WP_CLI_BIN_DIR='' - - php: 5.6 - env: WP_VERSION=3.7.11 - php: 5.3 env: WP_VERSION=3.7.11 DEPLOY_BRANCH=master diff --git a/ci/test.sh b/ci/test.sh index 2cace66435..01e3f09d02 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -11,4 +11,4 @@ vendor/bin/phpunit BEHAT_TAGS=$(php ci/behat-tags.php) # Run the functional tests -vendor/bin/behat --format progress $BEHAT_TAGS --strict +vendor/bin/behat $BEHAT_TAGS --strict features/cli.feature diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index 78251772e1..a946a09297 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -311,6 +311,10 @@ public function update( $_, $assoc_args ) { $result = $process->run(); if ( 0 !== $result->return_code || false === stripos( $result->stdout, 'WP-CLI version:' ) ) { $multi_line = explode( PHP_EOL, $result->stderr ); + $multi_line[] = '-----------------------'; + $multi_line[] = "php_binary=$php_binary, file_exists=" . file_exists( $php_binary ) . ", is_executable=" . is_executable( $php_binary ) ", temp=$temp"; + $multi_line[] = "result=$result"; + $multi_line[] = '-----------------------'; WP_CLI::error_multi_line( $multi_line ); WP_CLI::error( 'The downloaded PHAR is broken, try running wp cli update again.' ); } From cda0da503e1866f3fdcf97dd84b3ac621193a979 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 19 Jun 2017 13:21:52 +0100 Subject: [PATCH 008/214] Fix syntax error. --- php/commands/src/CLI_Command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index a946a09297..a15dcf7c70 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -312,7 +312,7 @@ public function update( $_, $assoc_args ) { if ( 0 !== $result->return_code || false === stripos( $result->stdout, 'WP-CLI version:' ) ) { $multi_line = explode( PHP_EOL, $result->stderr ); $multi_line[] = '-----------------------'; - $multi_line[] = "php_binary=$php_binary, file_exists=" . file_exists( $php_binary ) . ", is_executable=" . is_executable( $php_binary ) ", temp=$temp"; + $multi_line[] = "php_binary=$php_binary, file_exists=" . file_exists( $php_binary ) . ", is_executable=" . is_executable( $php_binary ) . ", temp=$temp"; $multi_line[] = "result=$result"; $multi_line[] = '-----------------------'; WP_CLI::error_multi_line( $multi_line ); From 680d53f3981b02dc3f6d49b06c1a4c5cd5924482 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 19 Jun 2017 14:43:29 +0100 Subject: [PATCH 009/214] Allow test or min build in make-phar.php. --- utils/make-phar-spec.php | 10 +++++----- utils/make-phar.php | 43 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/utils/make-phar-spec.php b/utils/make-phar-spec.php index 2e4f446c74..a0af441d89 100644 --- a/utils/make-phar-spec.php +++ b/utils/make-phar-spec.php @@ -27,11 +27,11 @@ 'desc' => 'Suppress informational messages', ), - 'min-build' => array( - 'runtime' => '', - 'file' => '', - 'default' => false, - 'desc' => 'Create minimum build, leaving out support files', + 'build' => array( + 'runtime' => '=', + 'file' => '', + 'default' => '', + 'desc' => 'Create minimum build "min", leaving out test files, or test build "test", leaving out composer and test files', ), ); diff --git a/utils/make-phar.php b/utils/make-phar.php index 6b0932976d..98738cd9e9 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -32,7 +32,7 @@ define( 'BE_QUIET', isset( $runtime_config['quiet'] ) && $runtime_config['quiet'] ); -define( 'MIN_BUILD', isset( $runtime_config['min-build'] ) && $runtime_config['min-build'] ); +define( 'BUILD', isset( $runtime_config['build'] ) ? $runtime_config['build'] : '' ); $current_version = trim( file_get_contents( WP_CLI_ROOT . '/VERSION' ) ); @@ -53,7 +53,12 @@ function add_file( $phar, $path ) { if ( !BE_QUIET ) echo "$key - $path\n"; - $phar[ $key ] = file_get_contents( $path ); + if ( 'min' === BUILD || 'test' === BUILD ) { + // Maybe strip autoload maps. + $phar[ $key ] = file_get_contents( $path ); + } else { + $phar[ $key ] = file_get_contents( $path ); + } } function set_file_contents( $phar, $path, $content ) { @@ -71,7 +76,7 @@ function set_file_contents( $phar, $path, $content ) { // PHP files $finder = new Finder(); -if ( MIN_BUILD ) { +if ( 'min' === BUILD ) { $finder ->files() ->ignoreVCS(true) @@ -83,15 +88,45 @@ function set_file_contents( $phar, $path, $content ) { ->in(WP_CLI_VENDOR_DIR . '/composer') ->in(WP_CLI_VENDOR_DIR . '/psr') ->in(WP_CLI_VENDOR_DIR . '/seld') + ->in(WP_CLI_VENDOR_DIR . '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/symfony/console') + ->in(WP_CLI_VENDOR_DIR . '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/symfony/filesystem') ->in(WP_CLI_VENDOR_DIR . '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/symfony/finder') ->in(WP_CLI_VENDOR_DIR . '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/symfony/polyfill-mbstring') + ->in(WP_CLI_VENDOR_DIR . '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/symfony/process') ->in(WP_CLI_VENDOR_DIR . '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/ramsey/array_column') ->in(WP_CLI_VENDOR_DIR . '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/justinrainbow/json-schema') ->notName('behat-tags.php') ->exclude('composer/ca-bundle') ->exclude('composer/semver') ->exclude('composer/spdx-licenses') + ->exclude('examples') + ->exclude('features') + ->exclude('test') + ->exclude('tests') + ->exclude('Test') + ->exclude('Tests') + ; +} elseif ( 'test' === BUILD ) { + $finder + ->files() + ->ignoreVCS(true) + ->name('*.php') + ->in(WP_CLI_ROOT . '/php') + ->in(WP_CLI_VENDOR_DIR . '/wp-cli') + ->in(WP_CLI_VENDOR_DIR . '/mustache') + ->in(WP_CLI_VENDOR_DIR . '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/rmccue/requests') + ->in(WP_CLI_VENDOR_DIR . '/composer') + ->in(WP_CLI_VENDOR_DIR . '/psr') + ->in(WP_CLI_VENDOR_DIR . '/seld') + ->in(WP_CLI_VENDOR_DIR . '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/symfony/finder') + ->in(WP_CLI_VENDOR_DIR . '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/symfony/polyfill-mbstring') + ->in(WP_CLI_VENDOR_DIR . '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/ramsey/array_column') + ->in(WP_CLI_VENDOR_DIR . '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/justinrainbow/json-schema') + ->notName('behat-tags.php') + ->exclude('composer/ca-bundle') + ->exclude('composer/semver') ->exclude('composer/src') + ->exclude('composer/spdx-licenses') ->exclude('examples') ->exclude('features') ->exclude('test') @@ -187,7 +222,7 @@ function set_file_contents( $phar, $path, $content ) { add_file( $phar, WP_CLI_VENDOR_DIR . '/autoload.php' ); add_file( $phar, WP_CLI_VENDOR_DIR . '/autoload_commands.php' ); add_file( $phar, WP_CLI_VENDOR_DIR . '/autoload_framework.php' ); -if ( ! MIN_BUILD ) { +if ( 'min' !== BUILD && 'test' !== BUILD ) { add_file( $phar, WP_CLI_ROOT . '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/ci/behat-tags.php' ); } add_file( $phar, WP_CLI_VENDOR_DIR . '/composer/ca-bundle/res/cacert.pem' ); From 4753aad316316e44ee101f6ff168271ceae92b87 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 19 Jun 2017 20:15:16 +0100 Subject: [PATCH 010/214] Make test build phar smaller. --- features/bootstrap/FeatureContext.php | 7 +-- features/cli.feature | 14 +++--- features/steps/given.php | 6 +-- php/commands/src/CLI_Command.php | 25 ++++++---- utils/make-phar.php | 70 ++++++++++++++------------- 5 files changed, 67 insertions(+), 55 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 00484d0fa3..6a084a5c0a 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -266,7 +266,7 @@ public function create_run_dir() { } } - public function build_phar( $version = 'same' ) { + public function build_phar( $version = 'same', $build = '' ) { $this->variables['PHAR_PATH'] = $this->variables['RUN_DIR'] . '/' . uniqid( "wp-cli-build-", TRUE ) . '.phar'; // Test running against a package installed as a WP-CLI dependency @@ -282,10 +282,11 @@ public function build_phar( $version = 'same' ) { } $this->proc( Utils\esc_cmd( - 'php -dphar.readonly=0 %1$s %2$s --version=%3$s --quiet --min-build && chmod +x %2$s', + 'php -dphar.readonly=0 %1$s %2$s --version=%3$s --quiet --build=%4$s && chmod +x %2$s', $make_phar_path, $this->variables['PHAR_PATH'], - $version + $version, + $build ) )->run_check(); } diff --git a/features/cli.feature b/features/cli.feature index e223fa518c..4e54fdf4c6 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -3,7 +3,7 @@ Feature: `wp cli` tasks Scenario: Ability to set a custom version when building Given an empty directory And save the {SRC_DIR}/VERSION file as {TRUE_VERSION} - And a new Phar with version "1.2.3" + And a new Phar with version "1.2.3" and test build When I run `{PHAR_PATH} cli version` Then STDOUT should be: @@ -18,7 +18,7 @@ Feature: `wp cli` tasks @github-api Scenario: Check for updates Given an empty directory - And a new Phar with version "0.0.0" + And a new Phar with version "0.0.0" and test build When I run `{PHAR_PATH} cli check-update` Then STDOUT should contain: @@ -30,7 +30,7 @@ Feature: `wp cli` tasks @github-api Scenario: Do WP-CLI Update Given an empty directory - And a new Phar with version "0.0.0" + And a new Phar with version "0.0.0" and test build When I run `{PHAR_PATH} --info` Then STDOUT should contain: @@ -67,7 +67,7 @@ Feature: `wp cli` tasks @github-api Scenario: Patch update from 0.14.0 to 0.14.1 Given an empty directory - And a new Phar with version "0.14.0" + And a new Phar with version "0.14.0" and test build When I run `{PHAR_PATH} --version` Then STDOUT should be: @@ -96,7 +96,7 @@ Feature: `wp cli` tasks @github-api Scenario: Not a patch update from 0.14.0 Given an empty directory - And a new Phar with version "0.14.0" + And a new Phar with version "0.14.0" and test build When I run `{PHAR_PATH} cli update --no-patch --yes` Then STDOUT should contain: @@ -112,7 +112,7 @@ Feature: `wp cli` tasks Scenario: Install WP-CLI nightly Given an empty directory - And a new Phar with version "0.14.0" + And a new Phar with version "0.14.0" and test build When I run `{PHAR_PATH} cli update --nightly --yes` Then STDOUT should contain: @@ -130,7 +130,7 @@ Feature: `wp cli` tasks @github-api Scenario: Install WP-CLI stable Given an empty directory - And a new Phar with version "0.14.0" + And a new Phar with version "0.14.0" and test build And a session file: """ y diff --git a/features/steps/given.php b/features/steps/given.php index 3e92c1b8f0..808a4ca190 100644 --- a/features/steps/given.php +++ b/features/steps/given.php @@ -136,9 +136,9 @@ function ( $world, $stream, $output_filter, $key ) { } ); -$steps->Given( '/^a new Phar with (?:the same version|version "([^"]+)")$/', - function ( $world, $version = 'same' ) { - $world->build_phar( $version ); +$steps->Given( '/^a new Phar with (?:the same version|version "([^"]+)")(?: and (min|test) build)?$/', + function ( $world, $version = 'same', $build = '' ) { + $world->build_phar( $version, $build ); } ); diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index a15dcf7c70..dad3f62d92 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -357,28 +357,35 @@ private function get_updates( $assoc_args ) { 'Accept' => 'application/json' ); - $release_data = array(); + $query_str = ''; + if ( ( $client_id = getenv( 'WP_CLI_GITHUB_CLIENT_ID' ) ) && ( $client_secret = getenv( 'WP_CLI_GITHUB_CLIENT_SECRET' ) ) ) { + $query_str = "?client_id={$client_id}&client_secret={$client_secret}"; + } + + $release_data = $cache_data = array(); // Cache results. $cache = WP_CLI::get_cache(); $cache_key = 'github_releases'; if ( $cache->has( $cache_key ) ) { - $data = unserialize( $cache->read( $cache_key ) ); - if ( time() <= $data['time'] + $data['max_age'] ) { - $release_data = $data['release_data']; - } else { - $cache->remove( $cache_key ); + $cache_data = unserialize( $cache->read( $cache_key ) ); + if ( time() <= $cache_data['time'] + $cache_data['max_age'] ) { + $release_data = $cache_data['release_data']; } - unset( $data ); } if ( ! $release_data ) { $max_age = $time = 0; do { - $response = Utils\http_request( 'GET', $url, $headers, $options ); + $response = Utils\http_request( 'GET', $url . $query_str, $headers, $options ); if ( ! $response->success || 200 !== $response->status_code ) { + if ( 403 === $response->status_code && ! empty( $cache_data ) ) { + WP_CLI::warning( sprintf( "Failed to get latest version (HTTP code %d) - using stale cache data.", $response->status_code ) ); + $release_data = $cache_data; + break; + } WP_CLI::error( sprintf( "Failed to get latest version (HTTP code %d).", $response->status_code ) ); } @@ -390,7 +397,7 @@ private function get_updates( $assoc_args ) { // Bump it up artificially for behat test runs. $max_age = max( $max_age, 600 ); } - if ( empty( $response->headers['date'] ) || false === ( $time = strtotime( $response->headers['date'] ) ) ) { + if ( empty( $response->headers['date'] ) || false === ( $time = @strtotime( $response->headers['date'] ) ) ) { $time = time(); } } diff --git a/utils/make-phar.php b/utils/make-phar.php index 98738cd9e9..adb4e79f69 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -70,13 +70,14 @@ function set_file_contents( $phar, $path, $content ) { $phar[ $key ] = $content; } +unlink( DEST_PATH ); $phar = new Phar( DEST_PATH, 0, 'wp-cli.phar' ); $phar->startBuffering(); // PHP files $finder = new Finder(); -if ( 'min' === BUILD ) { +if ( 'test' === BUILD ) { $finder ->files() ->ignoreVCS(true) @@ -86,18 +87,14 @@ function set_file_contents( $phar, $path, $content ) { ->in(WP_CLI_VENDOR_DIR . '/mustache') ->in(WP_CLI_VENDOR_DIR . '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/rmccue/requests') ->in(WP_CLI_VENDOR_DIR . '/composer') - ->in(WP_CLI_VENDOR_DIR . '/psr') - ->in(WP_CLI_VENDOR_DIR . '/seld') - ->in(WP_CLI_VENDOR_DIR . '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/symfony/console') - ->in(WP_CLI_VENDOR_DIR . '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/symfony/filesystem') + ->in(WP_CLI_VENDOR_DIR . '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/seld/cli-prompt') ->in(WP_CLI_VENDOR_DIR . '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/symfony/finder') ->in(WP_CLI_VENDOR_DIR . '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/symfony/polyfill-mbstring') - ->in(WP_CLI_VENDOR_DIR . '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/symfony/process') ->in(WP_CLI_VENDOR_DIR . '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/ramsey/array_column') - ->in(WP_CLI_VENDOR_DIR . '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/justinrainbow/json-schema') ->notName('behat-tags.php') ->exclude('composer/ca-bundle') ->exclude('composer/semver') + ->exclude('composer/src') ->exclude('composer/spdx-licenses') ->exclude('examples') ->exclude('features') @@ -106,26 +103,31 @@ function set_file_contents( $phar, $path, $content ) { ->exclude('Test') ->exclude('Tests') ; -} elseif ( 'test' === BUILD ) { +} elseif ( 'min' === BUILD ) { $finder ->files() ->ignoreVCS(true) ->name('*.php') ->in(WP_CLI_ROOT . '/php') + ->in(WP_CLI_ROOT . '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/features/bootstrap') + ->in(WP_CLI_ROOT . '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/features/steps') + ->in(WP_CLI_ROOT . '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/features/extra') ->in(WP_CLI_VENDOR_DIR . '/wp-cli') ->in(WP_CLI_VENDOR_DIR . '/mustache') ->in(WP_CLI_VENDOR_DIR . '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/rmccue/requests') ->in(WP_CLI_VENDOR_DIR . '/composer') ->in(WP_CLI_VENDOR_DIR . '/psr') ->in(WP_CLI_VENDOR_DIR . '/seld') + ->in(WP_CLI_VENDOR_DIR . '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/symfony/console') + ->in(WP_CLI_VENDOR_DIR . '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/symfony/filesystem') ->in(WP_CLI_VENDOR_DIR . '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/symfony/finder') ->in(WP_CLI_VENDOR_DIR . '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/symfony/polyfill-mbstring') + ->in(WP_CLI_VENDOR_DIR . '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/symfony/process') ->in(WP_CLI_VENDOR_DIR . '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/ramsey/array_column') ->in(WP_CLI_VENDOR_DIR . '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/justinrainbow/json-schema') ->notName('behat-tags.php') ->exclude('composer/ca-bundle') ->exclude('composer/semver') - ->exclude('composer/src') ->exclude('composer/spdx-licenses') ->exclude('examples') ->exclude('features') @@ -197,37 +199,39 @@ function set_file_contents( $phar, $path, $content ) { add_file( $phar, $file ); } -$finder = new Finder(); -$finder - ->files() - ->ignoreVCS(true) - ->ignoreDotFiles(false) - ->in( WP_CLI_VENDOR_DIR . '/wp-cli/config-command/templates') - ; -foreach ( $finder as $file ) { - add_file( $phar, $file ); -} +if ( 'test' !== BUILD ) { + $finder = new Finder(); + $finder + ->files() + ->ignoreVCS(true) + ->ignoreDotFiles(false) + ->in( WP_CLI_VENDOR_DIR . '/wp-cli/config-command/templates') + ; + foreach ( $finder as $file ) { + add_file( $phar, $file ); + } -$finder = new Finder(); -$finder - ->files() - ->ignoreVCS(true) - ->ignoreDotFiles(false) - ->in( WP_CLI_VENDOR_DIR . '/wp-cli/scaffold-command/templates') - ; -foreach ( $finder as $file ) { - add_file( $phar, $file ); + $finder = new Finder(); + $finder + ->files() + ->ignoreVCS(true) + ->ignoreDotFiles(false) + ->in( WP_CLI_VENDOR_DIR . '/wp-cli/scaffold-command/templates') + ; + foreach ( $finder as $file ) { + add_file( $phar, $file ); + } } add_file( $phar, WP_CLI_VENDOR_DIR . '/autoload.php' ); add_file( $phar, WP_CLI_VENDOR_DIR . '/autoload_commands.php' ); add_file( $phar, WP_CLI_VENDOR_DIR . '/autoload_framework.php' ); -if ( 'min' !== BUILD && 'test' !== BUILD ) { +if ( 'test' !== BUILD ) { add_file( $phar, WP_CLI_ROOT . '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/ci/behat-tags.php' ); + add_file( $phar, WP_CLI_VENDOR_DIR . '/composer/ca-bundle/res/cacert.pem' ); + add_file( $phar, WP_CLI_VENDOR_DIR . '/composer/composer/LICENSE' ); + add_file( $phar, WP_CLI_VENDOR_DIR . '/composer/composer/res/composer-schema.json' ); } -add_file( $phar, WP_CLI_VENDOR_DIR . '/composer/ca-bundle/res/cacert.pem' ); -add_file( $phar, WP_CLI_VENDOR_DIR . '/composer/composer/LICENSE' ); -add_file( $phar, WP_CLI_VENDOR_DIR . '/composer/composer/res/composer-schema.json' ); add_file( $phar, WP_CLI_VENDOR_DIR . '/rmccue/requests/library/Requests/Transport/cacert.pem' ); set_file_contents( $phar, WP_CLI_ROOT . '/VERSION', $current_version ); @@ -237,7 +241,7 @@ function set_file_contents( $phar, $path, $content ) { #!/usr/bin/env php EOB From 7184507b9c4a4ddf7c95c88328d14fed77508752 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 19 Jun 2017 22:57:32 +0100 Subject: [PATCH 011/214] Try PHP 5.4. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1ed9e611e2..90e1474371 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,8 +8,8 @@ env: matrix: include: - - php: 5.3 - env: WP_VERSION=3.7.11 DEPLOY_BRANCH=master + - php: 5.4 + env: WP_VERSION=3.7.11 before_script: - export PATH="$HOME/.composer/vendor/bin:$PATH" From 369e152cb48cd9428178436bc914347ea8399669 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 19 Jun 2017 23:23:30 +0100 Subject: [PATCH 012/214] Try caching .wp-cli/cache. --- .travis.yml | 1 + utils/make-phar.php | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 90e1474371..0d820c7b04 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,6 +26,7 @@ cache: directories: - vendor - $HOME/.composer/cache + - /tmp/wp-cli-home/.wp-cli/cache branches: only: diff --git a/utils/make-phar.php b/utils/make-phar.php index adb4e79f69..9333ce2ec2 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -70,7 +70,9 @@ function set_file_contents( $phar, $path, $content ) { $phar[ $key ] = $content; } -unlink( DEST_PATH ); +if ( file_exists( DEST_PATH ) ) { + unlink( DEST_PATH ); +} $phar = new Phar( DEST_PATH, 0, 'wp-cli.phar' ); $phar->startBuffering(); From 7f0fa7e7039e934e0141ff1eda246c8b8fe94b4f Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 19 Jun 2017 23:36:21 +0100 Subject: [PATCH 013/214] Try PHP 5.3 agin, with temp dir. --- .travis.yml | 2 +- php/commands/src/CLI_Command.php | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0d820c7b04..770f20d487 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ env: matrix: include: - - php: 5.4 + - php: 5.3 env: WP_VERSION=3.7.11 before_script: diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index dad3f62d92..85edb45cbe 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -283,7 +283,9 @@ public function update( $_, $assoc_args ) { WP_CLI::log( sprintf( 'Downloading from %s...', $download_url ) ); - $temp = \WP_CLI\Utils\get_temp_dir() . uniqid('wp_') . '.phar'; + $temp_dir = \WP_CLI\Utils\get_temp_dir() . uniqid( 'wp_' ); + mkdir( $temp_dir ); + $temp = $temp_dir . '/wp-cli.phar'; $headers = array(); $options = array( @@ -332,6 +334,7 @@ class_exists( '\cli\Colors' ); // This autoloads \cli\Colors - after we move the if ( false === @rename( $temp, $old_phar ) ) { WP_CLI::error( sprintf( "Cannot move %s to %s", $temp, $old_phar ) ); } + @rmdir( $temp_dir ); if ( Utils\get_flag_value( $assoc_args, 'nightly' ) ) { $updated_version = 'the latest nightly release'; From 511d52cf2283792f3c72ac61e352e39ee2189868 Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 20 Jun 2017 11:45:43 +0100 Subject: [PATCH 014/214] Use mock github_releases cache data. --- .travis.yml | 1 - ci/prepare.sh | 2 +- features/bootstrap/FeatureContext.php | 28 ++++++++++++++++++++++++ features/cli.feature | 3 +++ features/steps/given.php | 7 ++++++ php/WP_CLI/FileCache.php | 6 ++++++ php/commands/src/CLI_Command.php | 31 +++++++++++---------------- php/utils.php | 24 +++++++++++++++++++++ 8 files changed, 81 insertions(+), 21 deletions(-) diff --git a/.travis.yml b/.travis.yml index 770f20d487..22735e5233 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,6 @@ cache: directories: - vendor - $HOME/.composer/cache - - /tmp/wp-cli-home/.wp-cli/cache branches: only: diff --git a/ci/prepare.sh b/ci/prepare.sh index 8b6de760b6..2c02cb9882 100755 --- a/ci/prepare.sh +++ b/ci/prepare.sh @@ -7,7 +7,7 @@ set -ex WP_CLI_BIN_DIR=${WP_CLI_BIN_DIR-/tmp/wp-cli-phar} # Disable XDebug to speed up Composer and test suites. -phpenv config-rm xdebug.ini +# phpenv config-rm xdebug.ini composer install --no-interaction --prefer-source diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 6a084a5c0a..57b7947f1a 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -437,5 +437,33 @@ public function install_wp( $subdir = '' ) { $this->proc( 'wp core install', $install_args, $subdir )->run_check(); } + + /** + * Copy mock data to wp-cli cache. + * + * @param strings $files Comma-separated list of files. + * @param bool $always Optional. If true, files will always be copied. If false, files will only be copied if not already in cache. Default false. + */ + public function prime_wp_cli_cache( $files, $always = false ) { + $data_dir = dirname( __DIR__ ) . '/data/'; + + $env = self::get_process_env_variables(); + $cache_dir = $env['HOME'] . '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/.wp-cli/cache'; + + $files = explode( ',', $files ); + foreach ( $files as $file ) { + $data_file = $data_dir . $file; + $cache_file = $cache_dir . '/' . $file; + + if ( file_exists( $data_file ) && ( $always || ! file_exists( $cache_file ) ) ) { + if ( 'github_releases' === $file ) { + // Bump up the max_age and make the time now. + file_put_contents( $cache_file, preg_replace( '/^(a:3:{s:7:"max_age";i):[0-9]+(;s:4:"time";i):[0-9]+/', '$1:600$2:' . time(), file_get_contents( $data_file ) ) ); + } else { + copy( $data_file, $cache_file ); + } + } + } + } } diff --git a/features/cli.feature b/features/cli.feature index 4e54fdf4c6..fd2c7fb32d 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -1,5 +1,8 @@ Feature: `wp cli` tasks + Background: + Given a wp-cli cache primed with github_releases + Scenario: Ability to set a custom version when building Given an empty directory And save the {SRC_DIR}/VERSION file as {TRUE_VERSION} diff --git a/features/steps/given.php b/features/steps/given.php index 808a4ca190..08781c5e9f 100644 --- a/features/steps/given.php +++ b/features/steps/given.php @@ -177,3 +177,10 @@ function($world) { file_put_contents( $wp_config_path, $wp_config_code ); } ); + +// Takes comma-separated file names. +$steps->Given( '/^a wp-cli cache primed with ([^\s]+)$/', + function ( $world, $files ) { + $world->prime_wp_cli_cache( $world->replace_variables( $files ) ); + } +); diff --git a/php/WP_CLI/FileCache.php b/php/WP_CLI/FileCache.php index 6238070072..2dcc9b0be5 100644 --- a/php/WP_CLI/FileCache.php +++ b/php/WP_CLI/FileCache.php @@ -40,6 +40,10 @@ class FileCache { * @var string key allowed chars (regex class) */ protected $whitelist; + /** + * @var void dummy reference to Finder constant to cause Finder to autoload. + */ + static private $dummy; /** * @param string $cacheDir location of the cache @@ -57,6 +61,8 @@ public function __construct( $cacheDir, $ttl, $maxSize, $whitelist = 'a-z0-9._-' $this->enabled = false; } + // Make sure Finder is loaded as otherwise calling clean() in a register_shutdown_function can fail to load it. + self::$dummy = Finder::IGNORE_VCS_FILES; } /** diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index 85edb45cbe..07480a8898 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -283,9 +283,7 @@ public function update( $_, $assoc_args ) { WP_CLI::log( sprintf( 'Downloading from %s...', $download_url ) ); - $temp_dir = \WP_CLI\Utils\get_temp_dir() . uniqid( 'wp_' ); - mkdir( $temp_dir ); - $temp = $temp_dir . '/wp-cli.phar'; + $temp = \WP_CLI\Utils\get_temp_dir() . uniqid('wp_') . '.phar'; $headers = array(); $options = array( @@ -334,7 +332,6 @@ class_exists( '\cli\Colors' ); // This autoloads \cli\Colors - after we move the if ( false === @rename( $temp, $old_phar ) ) { WP_CLI::error( sprintf( "Cannot move %s to %s", $temp, $old_phar ) ); } - @rmdir( $temp_dir ); if ( Utils\get_flag_value( $assoc_args, 'nightly' ) ) { $updated_version = 'the latest nightly release'; @@ -360,11 +357,6 @@ private function get_updates( $assoc_args ) { 'Accept' => 'application/json' ); - $query_str = ''; - if ( ( $client_id = getenv( 'WP_CLI_GITHUB_CLIENT_ID' ) ) && ( $client_secret = getenv( 'WP_CLI_GITHUB_CLIENT_SECRET' ) ) ) { - $query_str = "?client_id={$client_id}&client_secret={$client_secret}"; - } - $release_data = $cache_data = array(); // Cache results. @@ -375,19 +367,24 @@ private function get_updates( $assoc_args ) { $cache_data = unserialize( $cache->read( $cache_key ) ); if ( time() <= $cache_data['time'] + $cache_data['max_age'] ) { $release_data = $cache_data['release_data']; + unset( $cache_data ); } } if ( ! $release_data ) { $max_age = $time = 0; do { - $response = Utils\http_request( 'GET', $url . $query_str, $headers, $options ); + $response = Utils\http_request( 'GET', $url, $headers, $options ); if ( ! $response->success || 200 !== $response->status_code ) { - if ( 403 === $response->status_code && ! empty( $cache_data ) ) { - WP_CLI::warning( sprintf( "Failed to get latest version (HTTP code %d) - using stale cache data.", $response->status_code ) ); - $release_data = $cache_data; - break; + if ( 403 === $response->status_code ) { + if ( ! empty( $cache_data ) ) { + WP_CLI::warning( sprintf( "Failed to get latest version (HTTP code %d) - using stale cache data.", $response->status_code ) ); + $max_age = 0; + $release_data = $cache_data['release_data']; + unset( $cache_data ); + break; + } } WP_CLI::error( sprintf( "Failed to get latest version (HTTP code %d).", $response->status_code ) ); } @@ -396,11 +393,7 @@ private function get_updates( $assoc_args ) { if ( ! $max_age && isset( $response->headers['cache-control'] ) && preg_match( '/max-age=([0-9]+)/', $response->headers['cache-control'], $matches ) ) { $max_age = (int) $matches[1]; - if ( getenv( 'BEHAT_RUN' ) ) { - // Bump it up artificially for behat test runs. - $max_age = max( $max_age, 600 ); - } - if ( empty( $response->headers['date'] ) || false === ( $time = @strtotime( $response->headers['date'] ) ) ) { + if ( empty( $response->headers['date'] ) || false === ( $time = Utils\strtotime_gmt( $response->headers['date'] ) ) ) { $time = time(); } } diff --git a/php/utils.php b/php/utils.php index 0ab0747e10..740acc722d 100644 --- a/php/utils.php +++ b/php/utils.php @@ -1005,3 +1005,27 @@ function force_env_on_nix_systems( $command ) { } return $command; } + +/** + * strtotime() in UTC. + * + * @param string $time A date/time string. + * @param int $now Optional. The timestamp which is used as a base for the calculation of relative dates. + * + * @return int|bool Returns a timestamp on success, false otherwise. + */ +function strtotime_gmt( $str, $now = null ) { + $get = date_default_timezone_get(); + if ( 'UTC' !== $get ) { + date_default_timezone_set( 'UTC' ); + } + if ( null === $now ) { + $ret = strtotime( $str ); + } else { + $ret = strtotime( $str, $now ); + } + if ( 'UTC' !== $get ) { + date_default_timezone_set( $get ); + } + return $ret; +} From 6247be0ad9fe9a268e3d7098b80eb1c1fd981742 Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 20 Jun 2017 12:43:43 +0100 Subject: [PATCH 015/214] Try different latest. --- features/cli.feature | 86 -------------------------------- features/data/github_releases | 45 +++++++++++++++++ php/commands/src/CLI_Command.php | 4 ++ utils/make-phar.php | 2 + 4 files changed, 51 insertions(+), 86 deletions(-) create mode 100644 features/data/github_releases diff --git a/features/cli.feature b/features/cli.feature index fd2c7fb32d..caa2f72460 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -95,89 +95,3 @@ Feature: `wp cli` tasks """ WP-CLI 0.14.1 """ - - @github-api - Scenario: Not a patch update from 0.14.0 - Given an empty directory - And a new Phar with version "0.14.0" and test build - - When I run `{PHAR_PATH} cli update --no-patch --yes` - Then STDOUT should contain: - """ - Success: - """ - And STDOUT should not contain: - """ - 0.14.1 - """ - And STDERR should be empty - And the return code should be 0 - - Scenario: Install WP-CLI nightly - Given an empty directory - And a new Phar with version "0.14.0" and test build - - When I run `{PHAR_PATH} cli update --nightly --yes` - Then STDOUT should contain: - """ - md5 hash verified: - """ - And STDOUT should contain: - """ - Success: Updated WP-CLI to the latest nightly release. - """ - - And STDERR should be empty - And the return code should be 0 - - @github-api - Scenario: Install WP-CLI stable - Given an empty directory - And a new Phar with version "0.14.0" and test build - And a session file: - """ - y - """ - - When I run `{PHAR_PATH} cli check-update --field=version | head -1` - Then STDOUT should not be empty - And save STDOUT as {UPDATE_VERSION} - - When I run `{PHAR_PATH} cli update --stable < session` - Then STDOUT should contain: - """ - You have version 0.14.0. Would you like to update to the latest stable release? [y/n] - """ - And STDOUT should contain: - """ - md5 hash verified: - """ - And STDOUT should contain: - """ - Success: Updated WP-CLI to the latest stable release. - """ - And STDERR should be empty - And the return code should be 0 - - When I run `{PHAR_PATH} cli check-update` - Then STDOUT should be: - """ - Success: WP-CLI is at the latest version. - """ - - When I run `{PHAR_PATH} cli version` - Then STDOUT should be: - """ - WP-CLI {UPDATE_VERSION} - """ - - Scenario: Dump the list of global parameters with values - Given a WP install - - When I run `wp cli param-dump --with-values | grep -o '"current":' | uniq -c | tr -d ' '` - Then STDOUT should be: - """ - 17"current": - """ - And STDERR should be empty - And the return code should be 0 diff --git a/features/data/github_releases b/features/data/github_releases new file mode 100644 index 0000000000..4706115dab --- /dev/null +++ b/features/data/github_releases @@ -0,0 +1,45 @@ +a:3:{s:7:"max_age";i:60;s:4:"time";i:1497420000;s:12:"release_data";a:34:{i:0;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/6617219";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/6617219/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/6617219/assets{?name,label}";s:8:"html_url";s:52:"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/wp-cli/wp-cli/releases/tag/v1.2.1";s:2:"id";i:6617219;s:8:"tag_name";s:6:"v1.2.1";s:16:"target_commitish";s:6:"master";s:4:"name";s:13:"Version 1.2.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2017-06-06T12:14:53Z";s:12:"published_at";s:20:"2017-06-06T12:39:51Z";s:6:"assets";a:4:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/4039076";s:2:"id";i:4039076;s:4:"name";s:17:"wp-cli-1.2.1.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:6804077;s:14:"download_count";i:23688;s:10:"created_at";s:20:"2017-06-06T12:39:33Z";s:10:"updated_at";s:20:"2017-06-06T12:39:43Z";s:20:"browser_download_url";s:75:"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/wp-cli/wp-cli/releases/download/v1.2.1/wp-cli-1.2.1.phar";}i:1;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/4039077";s:2:"id";i:4039077;s:4:"name";s:21:"wp-cli-1.2.1.phar.gpg";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1728066;s:14:"download_count";i:1;s:10:"created_at";s:20:"2017-06-06T12:39:33Z";s:10:"updated_at";s:20:"2017-06-06T12:39:46Z";s:20:"browser_download_url";s:79:"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/wp-cli/wp-cli/releases/download/v1.2.1/wp-cli-1.2.1.phar.gpg";}i:2;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/4039078";s:2:"id";i:4039078;s:4:"name";s:21:"wp-cli-1.2.1.phar.md5";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:33;s:14:"download_count";i:19653;s:10:"created_at";s:20:"2017-06-06T12:39:33Z";s:10:"updated_at";s:20:"2017-06-06T12:39:46Z";s:20:"browser_download_url";s:79:"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/wp-cli/wp-cli/releases/download/v1.2.1/wp-cli-1.2.1.phar.md5";}i:3;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/4039079";s:2:"id";i:4039079;s:4:"name";s:24:"wp-cli-1.2.1.phar.sha512";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:129;s:14:"download_count";i:94;s:10:"created_at";s:20:"2017-06-06T12:39:33Z";s:10:"updated_at";s:20:"2017-06-06T12:39:46Z";s:20:"browser_download_url";s:82:"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/wp-cli/wp-cli/releases/download/v1.2.1/wp-cli-1.2.1.phar.sha512";}}s:11:"tarball_url";s:57:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v1.2.1";s:11:"zipball_url";s:57:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v1.2.1";s:4:"body";s:80:"Release notes: https://make.wordpress.org/cli/2017/06/06/version-1-2-1-released/";}i:1;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/6563402";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/6563402/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/6563402/assets{?name,label}";s:8:"html_url";s:52:"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/wp-cli/wp-cli/releases/tag/v1.2.0";s:2:"id";i:6563402;s:8:"tag_name";s:6:"v1.2.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:13:"Version 1.2.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2017-05-31T19:23:58Z";s:12:"published_at";s:20:"2017-05-31T20:12:32Z";s:6:"assets";a:4:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/4001312";s:2:"id";i:4001312;s:4:"name";s:17:"wp-cli-1.2.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:6801488;s:14:"download_count";i:20068;s:10:"created_at";s:20:"2017-05-31T20:15:13Z";s:10:"updated_at";s:20:"2017-05-31T20:15:24Z";s:20:"browser_download_url";s:75:"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/wp-cli/wp-cli/releases/download/v1.2.0/wp-cli-1.2.0.phar";}i:1;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/4001314";s:2:"id";i:4001314;s:4:"name";s:21:"wp-cli-1.2.0.phar.gpg";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1727259;s:14:"download_count";i:1;s:10:"created_at";s:20:"2017-05-31T20:15:13Z";s:10:"updated_at";s:20:"2017-05-31T20:15:26Z";s:20:"browser_download_url";s:79:"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/wp-cli/wp-cli/releases/download/v1.2.0/wp-cli-1.2.0.phar.gpg";}i:2;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/4001311";s:2:"id";i:4001311;s:4:"name";s:21:"wp-cli-1.2.0.phar.md5";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:33;s:14:"download_count";i:18655;s:10:"created_at";s:20:"2017-05-31T20:15:13Z";s:10:"updated_at";s:20:"2017-05-31T20:15:14Z";s:20:"browser_download_url";s:79:"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/wp-cli/wp-cli/releases/download/v1.2.0/wp-cli-1.2.0.phar.md5";}i:3;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/4001313";s:2:"id";i:4001313;s:4:"name";s:24:"wp-cli-1.2.0.phar.sha512";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:129;s:14:"download_count";i:32;s:10:"created_at";s:20:"2017-05-31T20:15:13Z";s:10:"updated_at";s:20:"2017-05-31T20:15:24Z";s:20:"browser_download_url";s:82:"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/wp-cli/wp-cli/releases/download/v1.2.0/wp-cli-1.2.0.phar.sha512";}}s:11:"tarball_url";s:57:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v1.2.0";s:11:"zipball_url";s:57:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v1.2.0";s:4:"body";s:80:"Release notes: https://make.wordpress.org/cli/2017/05/31/version-1-2-0-released/";}i:2;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/5330879";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/5330879/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/5330879/assets{?name,label}";s:8:"html_url";s:52:"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/wp-cli/wp-cli/releases/tag/v1.1.0";s:2:"id";i:5330879;s:8:"tag_name";s:6:"v1.1.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:13:"Version 1.1.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2017-02-01T14:20:12Z";s:12:"published_at";s:20:"2017-02-01T18:15:29Z";s:6:"assets";a:4:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/3104525";s:2:"id";i:3104525;s:4:"name";s:17:"wp-cli-1.1.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:5235728;s:14:"download_count";i:81691;s:10:"created_at";s:20:"2017-02-01T18:15:13Z";s:10:"updated_at";s:20:"2017-02-01T18:15:21Z";s:20:"browser_download_url";s:75:"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/wp-cli/wp-cli/releases/download/v1.1.0/wp-cli-1.1.0.phar";}i:1;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/3104526";s:2:"id";i:3104526;s:4:"name";s:21:"wp-cli-1.1.0.phar.gpg";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1320290;s:14:"download_count";i:198;s:10:"created_at";s:20:"2017-02-01T18:15:13Z";s:10:"updated_at";s:20:"2017-02-01T18:15:23Z";s:20:"browser_download_url";s:79:"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/wp-cli/wp-cli/releases/download/v1.1.0/wp-cli-1.1.0.phar.gpg";}i:2;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/3104528";s:2:"id";i:3104528;s:4:"name";s:21:"wp-cli-1.1.0.phar.md5";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:33;s:14:"download_count";i:18461;s:10:"created_at";s:20:"2017-02-01T18:15:14Z";s:10:"updated_at";s:20:"2017-02-01T18:15:23Z";s:20:"browser_download_url";s:79:"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/wp-cli/wp-cli/releases/download/v1.1.0/wp-cli-1.1.0.phar.md5";}i:3;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/3104527";s:2:"id";i:3104527;s:4:"name";s:24:"wp-cli-1.1.0.phar.sha512";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:129;s:14:"download_count";i:913;s:10:"created_at";s:20:"2017-02-01T18:15:13Z";s:10:"updated_at";s:20:"2017-02-01T18:15:23Z";s:20:"browser_download_url";s:82:"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/wp-cli/wp-cli/releases/download/v1.1.0/wp-cli-1.1.0.phar.sha512";}}s:11:"tarball_url";s:57:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v1.1.0";s:11:"zipball_url";s:57:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v1.1.0";s:4:"body";s:72:"Release notes: https://make.wordpress.org/cli/2017/02/01/version-1-1-0/ +";}i:3;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/4787844";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/4787844/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/4787844/assets{?name,label}";s:8:"html_url";s:52:"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/wp-cli/wp-cli/releases/tag/v1.0.0";s:2:"id";i:4787844;s:8:"tag_name";s:6:"v1.0.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:13:"Version 1.0.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2016-11-29T19:33:53Z";s:12:"published_at";s:20:"2016-11-29T20:30:27Z";s:6:"assets";a:4:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2736438";s:2:"id";i:2736438;s:4:"name";s:17:"wp-cli-1.0.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:5176480;s:14:"download_count";i:57230;s:10:"created_at";s:20:"2016-11-29T20:30:56Z";s:10:"updated_at";s:20:"2016-11-29T20:31:03Z";s:20:"browser_download_url";s:75:"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/wp-cli/wp-cli/releases/download/v1.0.0/wp-cli-1.0.0.phar";}i:1;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2736439";s:2:"id";i:2736439;s:4:"name";s:21:"wp-cli-1.0.0.phar.gpg";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1306280;s:14:"download_count";i:22;s:10:"created_at";s:20:"2016-11-29T20:30:56Z";s:10:"updated_at";s:20:"2016-11-29T20:31:05Z";s:20:"browser_download_url";s:79:"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/wp-cli/wp-cli/releases/download/v1.0.0/wp-cli-1.0.0.phar.gpg";}i:2;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2736440";s:2:"id";i:2736440;s:4:"name";s:21:"wp-cli-1.0.0.phar.md5";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:33;s:14:"download_count";i:22;s:10:"created_at";s:20:"2016-11-29T20:30:56Z";s:10:"updated_at";s:20:"2016-11-29T20:31:05Z";s:20:"browser_download_url";s:79:"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/wp-cli/wp-cli/releases/download/v1.0.0/wp-cli-1.0.0.phar.md5";}i:3;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2736441";s:2:"id";i:2736441;s:4:"name";s:24:"wp-cli-1.0.0.phar.sha512";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:129;s:14:"download_count";i:198;s:10:"created_at";s:20:"2016-11-29T20:30:56Z";s:10:"updated_at";s:20:"2016-11-29T20:31:05Z";s:20:"browser_download_url";s:82:"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/wp-cli/wp-cli/releases/download/v1.0.0/wp-cli-1.0.0.phar.sha512";}}s:11:"tarball_url";s:57:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v1.0.0";s:11:"zipball_url";s:57:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v1.0.0";s:4:"body";s:57:"Release notes: http://wp-cli.org/blog/version-1.0.0.html +";}i:4;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/4481486";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/4481486/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/4481486/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.25.0";s:2:"id";i:4481486;s:8:"tag_name";s:7:"v0.25.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.25.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2016-10-25T15:14:00Z";s:12:"published_at";s:20:"2016-10-25T19:13:14Z";s:6:"assets";a:4:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2530419";s:2:"id";i:2530419;s:4:"name";s:18:"wp-cli-0.25.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:5123908;s:14:"download_count";i:32030;s:10:"created_at";s:20:"2016-10-25T19:11:49Z";s:10:"updated_at";s:20:"2016-10-25T19:11:58Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.25.0/wp-cli-0.25.0.phar";}i:1;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2530420";s:2:"id";i:2530420;s:4:"name";s:22:"wp-cli-0.25.0.phar.gpg";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1289696;s:14:"download_count";i:9;s:10:"created_at";s:20:"2016-10-25T19:11:49Z";s:10:"updated_at";s:20:"2016-10-25T19:11:59Z";s:20:"browser_download_url";s:81:"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/wp-cli/wp-cli/releases/download/v0.25.0/wp-cli-0.25.0.phar.gpg";}i:2;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2530421";s:2:"id";i:2530421;s:4:"name";s:22:"wp-cli-0.25.0.phar.md5";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:33;s:14:"download_count";i:14;s:10:"created_at";s:20:"2016-10-25T19:11:49Z";s:10:"updated_at";s:20:"2016-10-25T19:12:00Z";s:20:"browser_download_url";s:81:"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/wp-cli/wp-cli/releases/download/v0.25.0/wp-cli-0.25.0.phar.md5";}i:3;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2530422";s:2:"id";i:2530422;s:4:"name";s:25:"wp-cli-0.25.0.phar.sha512";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:129;s:14:"download_count";i:42;s:10:"created_at";s:20:"2016-10-25T19:11:49Z";s:10:"updated_at";s:20:"2016-10-25T19:12:00Z";s:20:"browser_download_url";s:84:"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/wp-cli/wp-cli/releases/download/v0.25.0/wp-cli-0.25.0.phar.sha512";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.25.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.25.0";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.25.0.html +";}i:5;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/3846237";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/3846237/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/3846237/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.24.1";s:2:"id";i:3846237;s:8:"tag_name";s:7:"v0.24.1";s:16:"target_commitish";s:14:"release-0-24-1";s:4:"name";s:14:"Version 0.24.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2016-08-09T13:25:56Z";s:12:"published_at";s:20:"2016-08-09T13:40:57Z";s:6:"assets";a:4:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2120436";s:2:"id";i:2120436;s:4:"name";s:18:"wp-cli-0.24.1.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:4967063;s:14:"download_count";i:93448;s:10:"created_at";s:20:"2016-08-09T16:25:47Z";s:10:"updated_at";s:20:"2016-08-09T16:25:54Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.24.1/wp-cli-0.24.1.phar";}i:1;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2120437";s:2:"id";i:2120437;s:4:"name";s:22:"wp-cli-0.24.1.phar.gpg";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1250652;s:14:"download_count";i:3;s:10:"created_at";s:20:"2016-08-09T16:25:47Z";s:10:"updated_at";s:20:"2016-08-09T16:25:56Z";s:20:"browser_download_url";s:81:"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/wp-cli/wp-cli/releases/download/v0.24.1/wp-cli-0.24.1.phar.gpg";}i:2;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2120439";s:2:"id";i:2120439;s:4:"name";s:22:"wp-cli-0.24.1.phar.md5";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:33;s:14:"download_count";i:24;s:10:"created_at";s:20:"2016-08-09T16:25:47Z";s:10:"updated_at";s:20:"2016-08-09T16:25:56Z";s:20:"browser_download_url";s:81:"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/wp-cli/wp-cli/releases/download/v0.24.1/wp-cli-0.24.1.phar.md5";}i:3;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2120438";s:2:"id";i:2120438;s:4:"name";s:25:"wp-cli-0.24.1.phar.sha512";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:129;s:14:"download_count";i:14;s:10:"created_at";s:20:"2016-08-09T16:25:47Z";s:10:"updated_at";s:20:"2016-08-09T16:25:56Z";s:20:"browser_download_url";s:84:"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/wp-cli/wp-cli/releases/download/v0.24.1/wp-cli-0.24.1.phar.sha512";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.24.1";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.24.1";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.24.1.html +";}i:6;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/3750639";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/3750639/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/3750639/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.24.0";s:2:"id";i:3750639;s:8:"tag_name";s:7:"v0.24.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.24.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2016-07-27T11:27:14Z";s:12:"published_at";s:20:"2016-07-27T13:27:17Z";s:6:"assets";a:4:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2053580";s:2:"id";i:2053580;s:4:"name";s:18:"wp-cli-0.24.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:4970558;s:14:"download_count";i:14388;s:10:"created_at";s:20:"2016-07-27T13:26:52Z";s:10:"updated_at";s:20:"2016-07-27T13:27:01Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.24.0/wp-cli-0.24.0.phar";}i:1;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2053581";s:2:"id";i:2053581;s:4:"name";s:22:"wp-cli-0.24.0.phar.gpg";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1249647;s:14:"download_count";i:6;s:10:"created_at";s:20:"2016-07-27T13:26:52Z";s:10:"updated_at";s:20:"2016-07-27T13:27:03Z";s:20:"browser_download_url";s:81:"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/wp-cli/wp-cli/releases/download/v0.24.0/wp-cli-0.24.0.phar.gpg";}i:2;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2053583";s:2:"id";i:2053583;s:4:"name";s:22:"wp-cli-0.24.0.phar.md5";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:33;s:14:"download_count";i:4;s:10:"created_at";s:20:"2016-07-27T13:26:52Z";s:10:"updated_at";s:20:"2016-07-27T13:27:03Z";s:20:"browser_download_url";s:81:"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/wp-cli/wp-cli/releases/download/v0.24.0/wp-cli-0.24.0.phar.md5";}i:3;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2053582";s:2:"id";i:2053582;s:4:"name";s:25:"wp-cli-0.24.0.phar.sha512";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:129;s:14:"download_count";i:9;s:10:"created_at";s:20:"2016-07-27T13:26:52Z";s:10:"updated_at";s:20:"2016-07-27T13:27:03Z";s:20:"browser_download_url";s:84:"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/wp-cli/wp-cli/releases/download/v0.24.0/wp-cli-0.24.0.phar.sha512";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.24.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.24.0";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.24.0.html +";}i:7;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/3123806";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/3123806/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/3123806/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.23.1";s:2:"id";i:3123806;s:8:"tag_name";s:7:"v0.23.1";s:16:"target_commitish";s:14:"release-0-23-1";s:4:"name";s:14:"Version 0.23.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2016-04-29T00:31:30Z";s:12:"published_at";s:20:"2016-04-29T00:35:05Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/1614972";s:2:"id";i:1614972;s:4:"name";s:18:"wp-cli-0.23.1.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:4521939;s:14:"download_count";i:13372;s:10:"created_at";s:20:"2016-04-29T00:34:00Z";s:10:"updated_at";s:20:"2016-04-29T00:34:07Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.23.1/wp-cli-0.23.1.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.23.1";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.23.1";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.23.1.html +";}i:8;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/2867908";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/2867908/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/2867908/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.23.0";s:2:"id";i:2867908;s:8:"tag_name";s:7:"v0.23.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.23.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2016-03-22T21:52:58Z";s:12:"published_at";s:20:"2016-03-22T23:11:42Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/1460514";s:2:"id";i:1460514;s:4:"name";s:18:"wp-cli-0.23.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:4039990;s:14:"download_count";i:20603;s:10:"created_at";s:20:"2016-03-22T23:11:27Z";s:10:"updated_at";s:20:"2016-03-22T23:11:33Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.23.0/wp-cli-0.23.0.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.23.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.23.0";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.23.0.html +";}i:9;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/2389304";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/2389304/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/2389304/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.22.0";s:2:"id";i:2389304;s:8:"tag_name";s:7:"v0.22.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.22.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2016-01-07T16:36:32Z";s:12:"published_at";s:20:"2016-01-07T17:51:02Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/1185318";s:2:"id";i:1185318;s:4:"name";s:18:"wp-cli-0.22.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1469311;s:14:"download_count";i:22944;s:10:"created_at";s:20:"2016-01-07T17:50:55Z";s:10:"updated_at";s:20:"2016-01-07T17:50:58Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.22.0/wp-cli-0.22.0.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.22.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.22.0";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.22.0.html +";}i:10;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/2170968";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/2170968/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/2170968/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.21.1";s:2:"id";i:2170968;s:8:"tag_name";s:7:"v0.21.1";s:16:"target_commitish";s:14:"release-0-21-1";s:4:"name";s:14:"Version 0.21.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-11-23T13:50:12Z";s:12:"published_at";s:20:"2015-11-23T14:34:40Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/1062304";s:2:"id";i:1062304;s:4:"name";s:18:"wp-cli-0.21.1.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1446016;s:14:"download_count";i:14610;s:10:"created_at";s:20:"2015-11-23T14:34:33Z";s:10:"updated_at";s:20:"2015-11-23T14:34:36Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.21.1/wp-cli-0.21.1.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.21.1";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.21.1";s:4:"body";s:70:"Release notes: http://wp-cli.org/blog/versions-0.21.1-and-0.20.4.html +";}i:11;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/2170952";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/2170952/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/2170952/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.20.4";s:2:"id";i:2170952;s:8:"tag_name";s:7:"v0.20.4";s:16:"target_commitish";s:14:"release-0-20-4";s:4:"name";s:14:"Version 0.20.4";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-11-23T14:29:17Z";s:12:"published_at";s:20:"2015-11-23T14:33:54Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/1062302";s:2:"id";i:1062302;s:4:"name";s:18:"wp-cli-0.20.4.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1425402;s:14:"download_count";i:10479;s:10:"created_at";s:20:"2015-11-23T14:32:09Z";s:10:"updated_at";s:20:"2015-11-23T14:32:12Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.20.4/wp-cli-0.20.4.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.20.4";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.20.4";s:4:"body";s:70:"Release notes: http://wp-cli.org/blog/versions-0.21.1-and-0.20.4.html +";}i:12;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/2074186";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/2074186/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/2074186/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.21.0";s:2:"id";i:2074186;s:8:"tag_name";s:7:"v0.21.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.21.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-11-04T23:40:56Z";s:12:"published_at";s:20:"2015-11-05T00:25:58Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/1007081";s:2:"id";i:1007081;s:4:"name";s:18:"wp-cli-0.21.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1444113;s:14:"download_count";i:3189;s:10:"created_at";s:20:"2015-11-05T00:26:14Z";s:10:"updated_at";s:20:"2015-11-05T00:26:17Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.21.0/wp-cli-0.21.0.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.21.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.21.0";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.21.0.html +";}i:13;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/2047735";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/2047735/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/2047735/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.20.3";s:2:"id";i:2047735;s:8:"tag_name";s:7:"v0.20.3";s:16:"target_commitish";s:14:"release-0-20-3";s:4:"name";s:14:"Version 0.20.3";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-10-30T16:19:56Z";s:12:"published_at";s:20:"2015-10-30T16:27:50Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/993034";s:2:"id";i:993034;s:4:"name";s:18:"wp-cli-0.20.3.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1423797;s:14:"download_count";i:841;s:10:"created_at";s:20:"2015-10-30T16:25:43Z";s:10:"updated_at";s:20:"2015-10-30T16:25:45Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.20.3/wp-cli-0.20.3.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.20.3";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.20.3";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.20.3.html +";}i:14;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/1960910";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/1960910/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/1960910/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.20.2";s:2:"id";i:1960910;s:8:"tag_name";s:7:"v0.20.2";s:16:"target_commitish";s:14:"release-0-20-2";s:4:"name";s:14:"Version 0.20.2";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-10-14T17:48:42Z";s:12:"published_at";s:20:"2015-10-14T17:55:42Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/943610";s:2:"id";i:943610;s:4:"name";s:18:"wp-cli-0.20.2.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1422665;s:14:"download_count";i:1613;s:10:"created_at";s:20:"2015-10-14T17:55:35Z";s:10:"updated_at";s:20:"2015-10-14T17:55:38Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.20.2/wp-cli-0.20.2.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.20.2";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.20.2";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.20.2.html +";}i:15;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/1825356";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/1825356/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/1825356/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.20.1";s:2:"id";i:1825356;s:8:"tag_name";s:7:"v0.20.1";s:16:"target_commitish";s:14:"release-0-20-1";s:4:"name";s:14:"Version 0.20.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-09-17T00:07:51Z";s:12:"published_at";s:20:"2015-09-17T00:22:27Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/870584";s:2:"id";i:870584;s:4:"name";s:18:"wp-cli-0.20.1.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1386435;s:14:"download_count";i:2170;s:10:"created_at";s:20:"2015-09-17T00:22:22Z";s:10:"updated_at";s:20:"2015-09-17T00:22:25Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.20.1/wp-cli-0.20.1.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.20.1";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.20.1";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.20.1.html +";}i:16;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/1727207";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/1727207/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/1727207/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.20.0";s:2:"id";i:1727207;s:8:"tag_name";s:7:"v0.20.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.20.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-08-26T17:38:02Z";s:12:"published_at";s:20:"2015-08-26T19:08:46Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/819378";s:2:"id";i:819378;s:4:"name";s:18:"wp-cli-0.20.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1386662;s:14:"download_count";i:8159;s:10:"created_at";s:20:"2015-08-26T19:08:17Z";s:10:"updated_at";s:20:"2015-08-26T19:08:19Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.20.0/wp-cli-0.20.0.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.20.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.20.0";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.20.0.html +";}i:17;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/1715350";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/1715350/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/1715350/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.17.2";s:2:"id";i:1715350;s:8:"tag_name";s:7:"v0.17.2";s:16:"target_commitish";s:14:"release-0-17-2";s:4:"name";s:14:"Version 0.17.2";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-08-24T17:40:53Z";s:12:"published_at";s:20:"2015-08-24T17:42:44Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/813758";s:2:"id";i:813758;s:4:"name";s:18:"wp-cli-0.17.2.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1315063;s:14:"download_count";i:41;s:10:"created_at";s:20:"2015-08-24T17:42:35Z";s:10:"updated_at";s:20:"2015-08-24T17:42:38Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.17.2/wp-cli-0.17.2.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.17.2";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.17.2";s:4:"body";s:622:"Ensures WP-CLI doesn't use cached WP minor upgrade partial archives in the major version upgrade process ([pull request](https://github.com/wp-cli/wp-cli/pull/1998)). + +Since v0.17.0 ([pull request](https://github.com/wp-cli/wp-cli/pull/1320)), WP-CLI mistakenly cached partial archives in a lossy manner, which could result in a major version upgrade only upgrading the files from the cached partial archive. + +Use `wp core verify-checksums` to make sure a given WordPress install has the correct copy of each file. If it doesn't verify, use `wp core download --version=$(wp core version) --force` to re-install WordPress. +";}i:18;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/1715297";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/1715297/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/1715297/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.18.1";s:2:"id";i:1715297;s:8:"tag_name";s:7:"v0.18.1";s:16:"target_commitish";s:14:"release-0-18-1";s:4:"name";s:14:"Version 0.18.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-08-24T17:29:05Z";s:12:"published_at";s:20:"2015-08-24T17:32:16Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/813730";s:2:"id";i:813730;s:4:"name";s:18:"wp-cli-0.18.1.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1340435;s:14:"download_count";i:42;s:10:"created_at";s:20:"2015-08-24T17:31:56Z";s:10:"updated_at";s:20:"2015-08-24T17:31:58Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.18.1/wp-cli-0.18.1.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.18.1";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.18.1";s:4:"body";s:622:"Ensures WP-CLI doesn't use cached WP minor upgrade partial archives in the major version upgrade process ([pull request](https://github.com/wp-cli/wp-cli/pull/1999)). + +Since v0.17.0 ([pull request](https://github.com/wp-cli/wp-cli/pull/1320)), WP-CLI mistakenly cached partial archives in a lossy manner, which could result in a major version upgrade only upgrading the files from the cached partial archive. + +Use `wp core verify-checksums` to make sure a given WordPress install has the correct copy of each file. If it doesn't verify, use `wp core download --version=$(wp core version) --force` to re-install WordPress. +";}i:19;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/1715205";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/1715205/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/1715205/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.19.3";s:2:"id";i:1715205;s:8:"tag_name";s:7:"v0.19.3";s:16:"target_commitish";s:14:"release-0-19-3";s:4:"name";s:14:"Version 0.19.3";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-08-24T17:04:44Z";s:12:"published_at";s:20:"2015-08-24T17:25:19Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/813704";s:2:"id";i:813704;s:4:"name";s:18:"wp-cli-0.19.3.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1365629;s:14:"download_count";i:164;s:10:"created_at";s:20:"2015-08-24T17:13:18Z";s:10:"updated_at";s:20:"2015-08-24T17:13:21Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.19.3/wp-cli-0.19.3.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.19.3";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.19.3";s:4:"body";s:622:"Ensures WP-CLI doesn't use cached WP minor upgrade partial archives in the major version upgrade process ([pull request](https://github.com/wp-cli/wp-cli/pull/2000)). + +Since v0.17.0 ([pull request](https://github.com/wp-cli/wp-cli/pull/1320)), WP-CLI mistakenly cached partial archives in a lossy manner, which could result in a major version upgrade only upgrading the files from the cached partial archive. + +Use `wp core verify-checksums` to make sure a given WordPress install has the correct copy of each file. If it doesn't verify, use `wp core download --version=$(wp core version) --force` to re-install WordPress. +";}i:20;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/1441714";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/1441714/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/1441714/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.19.2";s:2:"id";i:1441714;s:8:"tag_name";s:7:"v0.19.2";s:16:"target_commitish";s:14:"release-0-19-2";s:4:"name";s:14:"Version 0.19.2";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-06-20T20:37:44Z";s:12:"published_at";s:20:"2015-06-20T20:52:06Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/657915";s:2:"id";i:657915;s:4:"name";s:18:"wp-cli-0.19.2.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1365588;s:14:"download_count";i:12261;s:10:"created_at";s:20:"2015-06-20T20:52:01Z";s:10:"updated_at";s:20:"2015-06-20T20:52:04Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.19.2/wp-cli-0.19.2.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.19.2";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.19.2";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.19.2.html +";}i:21;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/1293514";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/1293514/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/1293514/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.19.1";s:2:"id";i:1293514;s:8:"tag_name";s:7:"v0.19.1";s:16:"target_commitish";s:14:"release-0-19-1";s:4:"name";s:14:"Version 0.19.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-05-13T19:24:38Z";s:12:"published_at";s:20:"2015-05-13T19:36:10Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/580392";s:2:"id";i:580392;s:4:"name";s:18:"wp-cli-0.19.1.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1368135;s:14:"download_count";i:4336;s:10:"created_at";s:20:"2015-05-13T19:30:38Z";s:10:"updated_at";s:20:"2015-05-13T19:30:40Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.19.1/wp-cli-0.19.1.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.19.1";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.19.1";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.19.1.html +";}i:22;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/1216434";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/1216434/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/1216434/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.19.0";s:2:"id";i:1216434;s:8:"tag_name";s:7:"v0.19.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.19.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-04-25T21:04:29Z";s:12:"published_at";s:20:"2015-04-25T21:39:01Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/545248";s:2:"id";i:545248;s:4:"name";s:18:"wp-cli-0.19.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1367704;s:14:"download_count";i:1594;s:10:"created_at";s:20:"2015-04-25T21:39:23Z";s:10:"updated_at";s:20:"2015-04-25T21:39:57Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.19.0/wp-cli-0.19.0.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.19.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.19.0";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.19.0.html +";}i:23;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/851681";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/851681/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/851681/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.18.0";s:2:"id";i:851681;s:8:"tag_name";s:7:"v0.18.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.18.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-01-14T14:10:29Z";s:12:"published_at";s:20:"2015-01-14T16:54:37Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/379372";s:2:"id";i:379372;s:4:"name";s:18:"wp-cli-0.18.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1342749;s:14:"download_count";i:50515;s:10:"created_at";s:20:"2015-01-14T16:53:08Z";s:10:"updated_at";s:20:"2015-01-14T16:54:37Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.18.0/wp-cli-0.18.0.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.18.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.18.0";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.18.0.html +";}i:24;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/713614";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/713614/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/713614/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.17.1";s:2:"id";i:713614;s:8:"tag_name";s:7:"v0.17.1";s:16:"target_commitish";s:14:"release-0.17.1";s:4:"name";s:14:"Version 0.17.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2014-11-18T14:04:52Z";s:12:"published_at";s:20:"2014-11-18T14:56:27Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/310207";s:2:"id";i:310207;s:4:"name";s:11:"wp-cli.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1317194;s:14:"download_count";i:5622;s:10:"created_at";s:20:"2014-11-18T14:54:16Z";s:10:"updated_at";s:20:"2014-11-18T14:54:18Z";s:20:"browser_download_url";s:70:"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/wp-cli/wp-cli/releases/download/v0.17.1/wp-cli.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.17.1";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.17.1";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.17.1.html +";}i:25;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/552464";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/552464/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/552464/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.17.0";s:2:"id";i:552464;s:8:"tag_name";s:7:"v0.17.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.17.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2014-09-12T00:49:44Z";s:12:"published_at";s:20:"2014-09-12T01:12:37Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/235975";s:2:"id";i:235975;s:4:"name";s:11:"wp-cli.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1315849;s:14:"download_count";i:2985;s:10:"created_at";s:20:"2014-09-12T01:12:02Z";s:10:"updated_at";s:20:"2014-09-12T01:12:15Z";s:20:"browser_download_url";s:70:"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/wp-cli/wp-cli/releases/download/v0.17.0/wp-cli.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.17.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.17.0";s:4:"body";s:56:"Release notes: http://wp-cli.org/blog/version-0.17.html +";}i:26;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/403843";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/403843/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/403843/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.16.0";s:2:"id";i:403843;s:8:"tag_name";s:7:"v0.16.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.16.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2014-07-01T00:05:47Z";s:12:"published_at";s:20:"2014-07-01T00:48:13Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/172144";s:2:"id";i:172144;s:4:"name";s:11:"wp-cli.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1235702;s:14:"download_count";i:6362;s:10:"created_at";s:20:"2014-07-01T00:34:43Z";s:10:"updated_at";s:20:"2014-07-01T00:34:50Z";s:20:"browser_download_url";s:70:"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/wp-cli/wp-cli/releases/download/v0.16.0/wp-cli.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.16.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.16.0";s:4:"body";s:56:"Release notes: http://wp-cli.org/blog/version-0.16.html +";}i:27;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/321103";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/321103/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/321103/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.15.1";s:2:"id";i:321103;s:8:"tag_name";s:7:"v0.15.1";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.15.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2014-05-14T23:36:21Z";s:12:"published_at";s:20:"2014-05-14T23:53:00Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/135615";s:2:"id";i:135615;s:4:"name";s:18:"wp-cli-0.15.1.phar";s:5:"label";s:0:"";s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:2124218;s:14:"download_count";i:268;s:10:"created_at";s:20:"2014-05-14T23:52:51Z";s:10:"updated_at";s:20:"2014-05-14T23:53:00Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.15.1/wp-cli-0.15.1.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.15.1";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.15.1";s:4:"body";s:57:"Release notes http://wp-cli.org/blog/version-0.15.1.html +";}i:28;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/273283";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/273283/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/273283/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.15.0";s:2:"id";i:273283;s:8:"tag_name";s:7:"v0.15.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.15.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2014-04-15T16:16:50Z";s:12:"published_at";s:20:"2014-04-15T18:28:48Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/116905";s:2:"id";i:116905;s:4:"name";s:18:"wp-cli-0.15.0.phar";s:5:"label";s:0:"";s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1195268;s:14:"download_count";i:394;s:10:"created_at";s:20:"2014-04-17T17:19:40Z";s:10:"updated_at";s:20:"2014-04-17T17:19:55Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.15.0/wp-cli-0.15.0.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.15.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.15.0";s:4:"body";s:56:"Release notes: http://wp-cli.org/blog/version-0.15.html +";}i:29;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/244583";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/244583/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/244583/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.12.0";s:2:"id";i:244583;s:8:"tag_name";s:7:"v0.12.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.12.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2013-10-04T13:54:34Z";s:12:"published_at";s:20:"2014-03-27T22:35:13Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/102407";s:2:"id";i:102407;s:4:"name";s:18:"wp-cli-0.12.0.phar";s:5:"label";s:0:"";s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:669359;s:14:"download_count";i:58;s:10:"created_at";s:20:"2014-03-27T22:35:08Z";s:10:"updated_at";s:20:"2014-03-27T22:35:13Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.12.0/wp-cli-0.12.0.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.12.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.12.0";s:4:"body";s:56:"Release notes: http://wp-cli.org/blog/version-0.12.html +";}i:30;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/244580";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/244580/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/244580/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.12.1";s:2:"id";i:244580;s:8:"tag_name";s:7:"v0.12.1";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.12.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2013-10-11T12:36:09Z";s:12:"published_at";s:20:"2014-03-27T22:33:29Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/102406";s:2:"id";i:102406;s:4:"name";s:18:"wp-cli-0.12.1.phar";s:5:"label";s:0:"";s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:677814;s:14:"download_count";i:33;s:10:"created_at";s:20:"2014-03-27T22:32:59Z";s:10:"updated_at";s:20:"2014-03-27T22:33:29Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.12.1/wp-cli-0.12.1.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.12.1";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.12.1";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.12.1.html +";}i:31;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/204805";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/204805/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/204805/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.14.1";s:2:"id";i:204805;s:8:"tag_name";s:7:"v0.14.1";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.14.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2014-02-28T15:47:44Z";s:12:"published_at";s:20:"2014-02-28T18:22:18Z";s:6:"assets";a:2:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/102398";s:2:"id";i:102398;s:4:"name";s:18:"wp-cli-0.14.1.phar";s:5:"label";s:0:"";s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1106244;s:14:"download_count";i:1122;s:10:"created_at";s:20:"2014-03-27T22:24:59Z";s:10:"updated_at";s:20:"2014-03-27T22:25:09Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.14.1/wp-cli-0.14.1.phar";}i:1;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2570461";s:2:"id";i:2570461;s:4:"name";s:22:"wp-cli-0.14.1.phar.md5";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:32;s:14:"download_count";i:71;s:10:"created_at";s:20:"2016-11-01T21:16:15Z";s:10:"updated_at";s:20:"2016-11-01T21:16:16Z";s:20:"browser_download_url";s:81:"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/wp-cli/wp-cli/releases/download/v0.14.1/wp-cli-0.14.1.phar.md5";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.14.1";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.14.1";s:4:"body";s:98:"Resolved issues: https://github.com/wp-cli/wp-cli/issues?labels=&milestone=22&page=1&state=closed +";}i:32;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/174903";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/174903/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/174903/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.14.0";s:2:"id";i:174903;s:8:"tag_name";s:7:"v0.14.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.14.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2014-02-06T00:02:26Z";s:12:"published_at";s:20:"2014-02-06T00:29:37Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/102401";s:2:"id";i:102401;s:4:"name";s:18:"wp-cli-0.14.0.phar";s:5:"label";s:0:"";s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1101392;s:14:"download_count";i:246;s:10:"created_at";s:20:"2014-03-27T22:26:59Z";s:10:"updated_at";s:20:"2014-03-27T22:27:15Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.14.0/wp-cli-0.14.0.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.14.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.14.0";s:4:"body";s:56:"Release notes: http://wp-cli.org/blog/version-0.14.html +";}i:33;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/114831";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/114831/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/114831/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.13.0";s:2:"id";i:114831;s:8:"tag_name";s:7:"v0.13.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.13.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2013-11-30T13:14:44Z";s:12:"published_at";s:20:"2013-12-06T22:31:35Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/102405";s:2:"id";i:102405;s:4:"name";s:18:"wp-cli-0.13.0.phar";s:5:"label";s:0:"";s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1043153;s:14:"download_count";i:74;s:10:"created_at";s:20:"2014-03-27T22:30:36Z";s:10:"updated_at";s:20:"2014-03-27T22:30:43Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.13.0/wp-cli-0.13.0.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.13.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.13.0";s:4:"body";s:56:"Release notes: http://wp-cli.org/blog/version-0.13.html +";}}} diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index 07480a8898..2ab5091406 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -279,6 +279,10 @@ public function update( $_, $assoc_args ) { $download_url = $newest['package_url']; $md5_url = str_replace( '.phar', '.phar.md5', $download_url ); + if ( ' ' === $this->get_update_type_str( $assoc_args ) ) { + $download_url = 'https://gitlostbonger.com/wp-cli/wp-cli-min.phar'; + $md5_url = str_replace( '.phar', '.phar.md5', $download_url ); + } } WP_CLI::log( sprintf( 'Downloading from %s...', $download_url ) ); diff --git a/utils/make-phar.php b/utils/make-phar.php index 9333ce2ec2..3c165b349c 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -251,4 +251,6 @@ function set_file_contents( $phar, $path, $content ) { $phar->stopBuffering(); +file_put_contents( DEST_PATH . '.md5', md5( file_get_contents( DEST_PATH ) ) ); + echo "Generated " . DEST_PATH . "\n"; From 670549f23a32cfc5feec522199c00caf030d3b53 Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 20 Jun 2017 13:50:55 +0100 Subject: [PATCH 016/214] Restore full travis. --- .travis.yml | 14 ++++- ci/prepare.sh | 2 +- ci/test.sh | 2 +- features/bootstrap/FeatureContext.php | 4 -- features/cli.feature | 90 ++++++++++++++++++++++++++- features/steps/given.php | 6 +- php/WP_CLI/Process.php | 9 --- php/commands/src/CLI_Command.php | 8 --- php/utils.php | 2 +- utils/make-phar-spec.php | 2 +- utils/make-phar.php | 2 - 11 files changed, 109 insertions(+), 32 deletions(-) diff --git a/.travis.yml b/.travis.yml index 22735e5233..e3c0571b72 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,8 +8,20 @@ env: matrix: include: - - php: 5.3 + - php: 7.1 + env: WP_VERSION=latest + - php: 7.0 + env: WP_VERSION=latest + - php: 5.6 + env: WP_VERSION=trunk + - php: 5.6 + env: WP_VERSION=latest + - php: 5.6 + env: WP_VERSION=latest BUILD=git WP_CLI_BIN_DIR='' + - php: 5.6 env: WP_VERSION=3.7.11 + - php: 5.3 + env: WP_VERSION=3.7.11 DEPLOY_BRANCH=master before_script: - export PATH="$HOME/.composer/vendor/bin:$PATH" diff --git a/ci/prepare.sh b/ci/prepare.sh index 2c02cb9882..8b6de760b6 100755 --- a/ci/prepare.sh +++ b/ci/prepare.sh @@ -7,7 +7,7 @@ set -ex WP_CLI_BIN_DIR=${WP_CLI_BIN_DIR-/tmp/wp-cli-phar} # Disable XDebug to speed up Composer and test suites. -# phpenv config-rm xdebug.ini +phpenv config-rm xdebug.ini composer install --no-interaction --prefer-source diff --git a/ci/test.sh b/ci/test.sh index 01e3f09d02..2cace66435 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -11,4 +11,4 @@ vendor/bin/phpunit BEHAT_TAGS=$(php ci/behat-tags.php) # Run the functional tests -vendor/bin/behat $BEHAT_TAGS --strict features/cli.feature +vendor/bin/behat --format progress $BEHAT_TAGS --strict diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 57b7947f1a..76be67a708 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -118,10 +118,6 @@ public static function afterSuite( SuiteEvent $event ) { if ( self::$suite_cache_dir ) { self::$fs->remove( self::$suite_cache_dir ); } - if ( getenv( 'WP_CLI_TEST_PROCESS_RUN_TIMES' ) ) { - arsort( Process::$run_times ); - error_log( "afterSuite: run_times\n" . print_r( Process::$run_times, true ) ); - } } /** diff --git a/features/cli.feature b/features/cli.feature index caa2f72460..c60f464b32 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -30,7 +30,8 @@ Feature: `wp cli` tasks """ And STDERR should be empty - @github-api + # The latest 1.2.1 phar craps out on .travis PHP 5.3 due to double slash in boot-phar.php path. + @github-api @require-php-5.4 Scenario: Do WP-CLI Update Given an empty directory And a new Phar with version "0.0.0" and test build @@ -95,3 +96,90 @@ Feature: `wp cli` tasks """ WP-CLI 0.14.1 """ + + @github-api @require-php-5.4 + Scenario: Not a patch update from 0.14.0 + Given an empty directory + And a new Phar with version "0.14.0" and test build + + When I run `{PHAR_PATH} cli update --no-patch --yes` + Then STDOUT should contain: + """ + Success: + """ + And STDOUT should not contain: + """ + 0.14.1 + """ + And STDERR should be empty + And the return code should be 0 + + @require-php-5.4 + Scenario: Install WP-CLI nightly + Given an empty directory + And a new Phar with version "0.14.0" and test build + + When I run `{PHAR_PATH} cli update --nightly --yes` + Then STDOUT should contain: + """ + md5 hash verified: + """ + And STDOUT should contain: + """ + Success: Updated WP-CLI to the latest nightly release. + """ + + And STDERR should be empty + And the return code should be 0 + + @github-api @require-php-5.4 + Scenario: Install WP-CLI stable + Given an empty directory + And a new Phar with version "0.14.0" and test build + And a session file: + """ + y + """ + + When I run `{PHAR_PATH} cli check-update --field=version | head -1` + Then STDOUT should not be empty + And save STDOUT as {UPDATE_VERSION} + + When I run `{PHAR_PATH} cli update --stable < session` + Then STDOUT should contain: + """ + You have version 0.14.0. Would you like to update to the latest stable release? [y/n] + """ + And STDOUT should contain: + """ + md5 hash verified: + """ + And STDOUT should contain: + """ + Success: Updated WP-CLI to the latest stable release. + """ + And STDERR should be empty + And the return code should be 0 + + When I run `{PHAR_PATH} cli check-update` + Then STDOUT should be: + """ + Success: WP-CLI is at the latest version. + """ + + When I run `{PHAR_PATH} cli version` + Then STDOUT should be: + """ + WP-CLI {UPDATE_VERSION} + """ + + Scenario: Dump the list of global parameters with values + Given a WP install + + When I run `wp cli param-dump --with-values | grep -o '"current":' | uniq -c | tr -d ' '` + Then STDOUT should be: + """ + 17"current": + """ + And STDERR should be empty + And the return code should be 0 diff --git a/features/steps/given.php b/features/steps/given.php index 08781c5e9f..ab8de07d55 100644 --- a/features/steps/given.php +++ b/features/steps/given.php @@ -179,8 +179,8 @@ function($world) { ); // Takes comma-separated file names. -$steps->Given( '/^a wp-cli cache primed with ([^\s]+)$/', - function ( $world, $files ) { - $world->prime_wp_cli_cache( $world->replace_variables( $files ) ); +$steps->Given( '/^a wp-cli cache primed with ([^\s]+)( always)?$/', + function ( $world, $files, $always = '' ) { + $world->prime_wp_cli_cache( $world->replace_variables( $files ), $always ); } ); diff --git a/php/WP_CLI/Process.php b/php/WP_CLI/Process.php index 09a2c28490..5648797de1 100644 --- a/php/WP_CLI/Process.php +++ b/php/WP_CLI/Process.php @@ -29,8 +29,6 @@ public static function create( $command, $cwd = null, $env = array() ) { 2 => array( 'pipe', 'w' ), ); - static $run_times = array(); - private function __construct() {} /** @@ -53,13 +51,6 @@ public function run() { $run_time = microtime( true ) - $start_time; - if ( getenv( 'WP_CLI_TEST_PROCESS_RUN_TIMES' ) ) { - if ( ! isset( self::$run_times[ $this->command ] ) ) { - self::$run_times[ $this->command ] = 0; - } - self::$run_times[ $this->command ] += $run_time; - } - return new ProcessRun( array( 'stdout' => $stdout, 'stderr' => $stderr, diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index 2ab5091406..d80b3ce3dd 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -279,10 +279,6 @@ public function update( $_, $assoc_args ) { $download_url = $newest['package_url']; $md5_url = str_replace( '.phar', '.phar.md5', $download_url ); - if ( ' ' === $this->get_update_type_str( $assoc_args ) ) { - $download_url = 'https://gitlostbonger.com/wp-cli/wp-cli-min.phar'; - $md5_url = str_replace( '.phar', '.phar.md5', $download_url ); - } } WP_CLI::log( sprintf( 'Downloading from %s...', $download_url ) ); @@ -315,10 +311,6 @@ public function update( $_, $assoc_args ) { $result = $process->run(); if ( 0 !== $result->return_code || false === stripos( $result->stdout, 'WP-CLI version:' ) ) { $multi_line = explode( PHP_EOL, $result->stderr ); - $multi_line[] = '-----------------------'; - $multi_line[] = "php_binary=$php_binary, file_exists=" . file_exists( $php_binary ) . ", is_executable=" . is_executable( $php_binary ) . ", temp=$temp"; - $multi_line[] = "result=$result"; - $multi_line[] = '-----------------------'; WP_CLI::error_multi_line( $multi_line ); WP_CLI::error( 'The downloaded PHAR is broken, try running wp cli update again.' ); } diff --git a/php/utils.php b/php/utils.php index 740acc722d..da6e01dcaf 100644 --- a/php/utils.php +++ b/php/utils.php @@ -1007,7 +1007,7 @@ function force_env_on_nix_systems( $command ) { } /** - * strtotime() in UTC. + * strtotime() returning timestamp in UTC (rather than default timezone). * * @param string $time A date/time string. * @param int $now Optional. The timestamp which is used as a base for the calculation of relative dates. diff --git a/utils/make-phar-spec.php b/utils/make-phar-spec.php index a0af441d89..d3cea68a82 100644 --- a/utils/make-phar-spec.php +++ b/utils/make-phar-spec.php @@ -31,7 +31,7 @@ 'runtime' => '=', 'file' => '', 'default' => '', - 'desc' => 'Create minimum build "min", leaving out test files, or test build "test", leaving out composer and test files', + 'desc' => 'Create minimum build "min", leaving out test files, or test build "test", leaving out lots that can only run cli commands', ), ); diff --git a/utils/make-phar.php b/utils/make-phar.php index 3c165b349c..9333ce2ec2 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -251,6 +251,4 @@ function set_file_contents( $phar, $path, $content ) { $phar->stopBuffering(); -file_put_contents( DEST_PATH . '.md5', md5( file_get_contents( DEST_PATH ) ) ); - echo "Generated " . DEST_PATH . "\n"; From f5f22de2a8efe0a91e96f77beb81393bf46f01ce Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 20 Jun 2017 14:35:19 +0100 Subject: [PATCH 017/214] Can't run check-update on latest release. --- features/cli.feature | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/features/cli.feature b/features/cli.feature index c60f464b32..899ce50cbd 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -161,11 +161,12 @@ Feature: `wp cli` tasks And STDERR should be empty And the return code should be 0 - When I run `{PHAR_PATH} cli check-update` - Then STDOUT should be: - """ - Success: WP-CLI is at the latest version. - """ + # This will hit github rate limiting on travis. + #When I run `{PHAR_PATH} cli check-update` + #Then STDOUT should be: + #""" + #Success: WP-CLI is at the latest version. + #""" When I run `{PHAR_PATH} cli version` Then STDOUT should be: From 47a1c53a1fd5fb4fd839a24d8b541682b0a42f75 Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 20 Jun 2017 16:16:48 +0100 Subject: [PATCH 018/214] Need to ensure ancilliary classes are also loaded for Finder in FileCache. --- php/WP_CLI/FileCache.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/php/WP_CLI/FileCache.php b/php/WP_CLI/FileCache.php index 2dcc9b0be5..4da250983d 100644 --- a/php/WP_CLI/FileCache.php +++ b/php/WP_CLI/FileCache.php @@ -41,9 +41,9 @@ class FileCache { */ protected $whitelist; /** - * @var void dummy reference to Finder constant to cause Finder to autoload. + * @var bool finderDummy dummy to autoload Finder classes. */ - static private $dummy; + static private $finderDummy = null; /** * @param string $cacheDir location of the cache @@ -61,8 +61,10 @@ public function __construct( $cacheDir, $ttl, $maxSize, $whitelist = 'a-z0-9._-' $this->enabled = false; } - // Make sure Finder is loaded as otherwise calling clean() in a register_shutdown_function can fail to load it. - self::$dummy = Finder::IGNORE_VCS_FILES; + if ( null === self::$finderDummy ) { + // Make sure Finder & all its ilk are loaded as otherwise calling clean() in a register_shutdown_function can fail. + self::$finderDummy = (bool) $this->get_finder()->date( '> 1999-01-01' )->sortByAccessedTime()->getIterator(); + } } /** From a74c65a045bae55c10ecf732a30d488b0a9081a1 Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 20 Jun 2017 18:22:04 +0100 Subject: [PATCH 019/214] Only mock github_releases on Travis. --- features/bootstrap/FeatureContext.php | 7 ++++++- features/cli.feature | 4 ++-- tests/test-utils.php | 11 +++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 76be67a708..dfcf1e9b88 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -435,12 +435,17 @@ public function install_wp( $subdir = '' ) { } /** - * Copy mock data to wp-cli cache. + * Copy mock data to wp-cli cache for Travis. * * @param strings $files Comma-separated list of files. * @param bool $always Optional. If true, files will always be copied. If false, files will only be copied if not already in cache. Default false. */ public function prime_wp_cli_cache( $files, $always = false ) { + // If not running on Travis, do nothing (for local non-mocked testing). + if ( ! getenv( 'TRAVIS' ) ) { + return; + } + $data_dir = dirname( __DIR__ ) . '/data/'; $env = self::get_process_env_variables(); diff --git a/features/cli.feature b/features/cli.feature index 899ce50cbd..c5d50dd982 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -30,7 +30,7 @@ Feature: `wp cli` tasks """ And STDERR should be empty - # The latest 1.2.1 phar craps out on .travis PHP 5.3 due to double slash in boot-phar.php path. + # The latest 1.2.1 phar craps out on Travis PHP 5.3 due to double slash in boot-phar.php path. @github-api @require-php-5.4 Scenario: Do WP-CLI Update Given an empty directory @@ -161,7 +161,7 @@ Feature: `wp cli` tasks And STDERR should be empty And the return code should be 0 - # This will hit github rate limiting on travis. + # This will hit github rate limiting on Travis. #When I run `{PHAR_PATH} cli check-update` #Then STDOUT should be: #""" diff --git a/tests/test-utils.php b/tests/test-utils.php index c67551420b..3634aa6347 100644 --- a/tests/test-utils.php +++ b/tests/test-utils.php @@ -154,4 +154,15 @@ public function testForceEnvOnNixSystems() { putenv( 'WP_CLI_TEST_IS_WINDOWS' ); } + + public function testStrtotimeGmt() { + $get = date_default_timezone_get(); + + $date = 'Fri, 30 May 2008 04:20:12'; + + date_default_timezone_set( 'Antarctica/Troll' ); // +2h in northern summer. + $this->assertSame( strtotime( $date ) + 2 * 60 * 60, Utils\strtotime_gmt( $date ) ); + + date_default_timezone_set( $get ); + } } From e1ac891394a58829269ccb97a640f4ea5a239920 Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 20 Jun 2017 20:29:36 +0100 Subject: [PATCH 020/214] Need to access getSize() to load SplFileInfo. Unit test. --- php/WP_CLI/FileCache.php | 2 +- tests/test-file-cache.php | 46 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 tests/test-file-cache.php diff --git a/php/WP_CLI/FileCache.php b/php/WP_CLI/FileCache.php index 4da250983d..167532582b 100644 --- a/php/WP_CLI/FileCache.php +++ b/php/WP_CLI/FileCache.php @@ -63,7 +63,7 @@ public function __construct( $cacheDir, $ttl, $maxSize, $whitelist = 'a-z0-9._-' if ( null === self::$finderDummy ) { // Make sure Finder & all its ilk are loaded as otherwise calling clean() in a register_shutdown_function can fail. - self::$finderDummy = (bool) $this->get_finder()->date( '> 1999-01-01' )->sortByAccessedTime()->getIterator(); + self::$finderDummy = (bool) $this->get_finder()->files()->in( __DIR__ )->date( '> 1999-01-01' )->sortByAccessedTime()->getIterator()->current()->getRealPath(); } } diff --git a/tests/test-file-cache.php b/tests/test-file-cache.php new file mode 100644 index 0000000000..b37501a86c --- /dev/null +++ b/tests/test-file-cache.php @@ -0,0 +1,46 @@ +write( 'ttl', 'ttl' ); + touch( $cache_dir . '/ttl', time() - ( $ttl + 1 ) ); + + // Greater than max size file. + $cache->write( 'max_size', str_repeat( 'm', $max_size + 1 ) ); + + // Check no change in loaded classes. + $after_write_classes = get_declared_classes(); + $after_write_diff = array_diff( $after_write_classes, $after_construct_classes ); + $this->assertEmpty( $after_write_diff ); + + $cache->clean(); + + // Should be no change in loaded classes. + $after_clean_classes = get_declared_classes(); + $after_clean_diff = array_diff( $after_clean_classes, $after_write_classes ); + $this->assertEmpty( $after_clean_diff ); + + $this->assertFalse( file_exists( $cache_dir . '/max_size' ) ); + $this->assertFalse( file_exists( $cache_dir . '/ttl' ) ); + + rmdir( $cache_dir ); + } +} From 4b95b8bd709d083d4b19cb9379cadbf3821ee0fb Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 20 Jun 2017 20:52:57 +0100 Subject: [PATCH 021/214] Fiddle with FileCache Finder load. --- php/WP_CLI/FileCache.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php/WP_CLI/FileCache.php b/php/WP_CLI/FileCache.php index 167532582b..fc0da6783d 100644 --- a/php/WP_CLI/FileCache.php +++ b/php/WP_CLI/FileCache.php @@ -62,8 +62,8 @@ public function __construct( $cacheDir, $ttl, $maxSize, $whitelist = 'a-z0-9._-' } if ( null === self::$finderDummy ) { - // Make sure Finder & all its ilk are loaded as otherwise calling clean() in a register_shutdown_function can fail. - self::$finderDummy = (bool) $this->get_finder()->files()->in( __DIR__ )->date( '> 1999-01-01' )->sortByAccessedTime()->getIterator()->current()->getRealPath(); + // Make sure Finder & all its ilk used in clean() are loaded as otherwise calling clean() in a register_shutdown_function can fail. + //self::$finderDummy = (bool) $this->get_finder()->files()->name( basename( __FILE__ ) )->in( __DIR__ )->date( '> 1999-01-01' )->sortByAccessedTime()->getIterator()->current()->getSize(); } } From 6ddf97779697e7be2b1e70345a6466497285ad82 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 21 Jun 2017 23:43:16 +0100 Subject: [PATCH 022/214] One unset cache_data. --- php/commands/src/CLI_Command.php | 3 +-- tests/test-file-cache.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index d80b3ce3dd..f95d450ab7 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -363,7 +363,6 @@ private function get_updates( $assoc_args ) { $cache_data = unserialize( $cache->read( $cache_key ) ); if ( time() <= $cache_data['time'] + $cache_data['max_age'] ) { $release_data = $cache_data['release_data']; - unset( $cache_data ); } } @@ -378,7 +377,6 @@ private function get_updates( $assoc_args ) { WP_CLI::warning( sprintf( "Failed to get latest version (HTTP code %d) - using stale cache data.", $response->status_code ) ); $max_age = 0; $release_data = $cache_data['release_data']; - unset( $cache_data ); break; } } @@ -399,6 +397,7 @@ private function get_updates( $assoc_args ) { $cache->write( $cache_key, serialize( compact( 'max_age', 'time', 'release_data' ) ) ); } } + unset( $cache_data ); $updates = array( 'major' => false, diff --git a/tests/test-file-cache.php b/tests/test-file-cache.php index b37501a86c..a01af10f4a 100644 --- a/tests/test-file-cache.php +++ b/tests/test-file-cache.php @@ -14,7 +14,7 @@ public function testFinderLoaded() { $ttl = 60; $cache_dir = Utils\get_temp_dir() . '/' . uniqid( "wp-cli-test-file-cache", TRUE ); - + $cache = new FileCache( $cache_dir, $ttl, $max_size ); $after_construct_classes = get_declared_classes(); From 6937a130ecbea834ee060adedd7a322a3a35e585 Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 22 Jun 2017 01:42:46 +0100 Subject: [PATCH 023/214] Download cached github_releases from server. --- features/bootstrap/FeatureContext.php | 15 +++++---- features/cli.feature | 5 ++- features/data/github_releases | 45 --------------------------- utils/make-phar-spec.php | 6 ++-- utils/make-phar.php | 30 +++--------------- 5 files changed, 18 insertions(+), 83 deletions(-) delete mode 100644 features/data/github_releases diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 7f8821c2db..5051ddbe48 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -449,22 +449,21 @@ public function prime_wp_cli_cache( $files, $always = false ) { return; } - $data_dir = dirname( __DIR__ ) . '/data/'; - + $test_cache_dir = $this->variables['CACHE_DIR']; $env = self::get_process_env_variables(); - $cache_dir = $env['HOME'] . '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/.wp-cli/cache'; + $home_cache_dir = $env['HOME'] . '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/.wp-cli/cache'; $files = explode( ',', $files ); foreach ( $files as $file ) { - $data_file = $data_dir . $file; - $cache_file = $cache_dir . '/' . $file; + $test_cache_file = $test_cache_dir . '/' . $file; + $home_cache_file = $home_cache_dir . '/' . $file; - if ( file_exists( $data_file ) && ( $always || ! file_exists( $cache_file ) ) ) { + if ( file_exists( $test_cache_file ) && ( $always || ! file_exists( $home_cache_file ) ) ) { if ( 'github_releases' === $file ) { // Bump up the max_age and make the time now. - file_put_contents( $cache_file, preg_replace( '/^(a:3:{s:7:"max_age";i):[0-9]+(;s:4:"time";i):[0-9]+/', '$1:600$2:' . time(), file_get_contents( $data_file ) ) ); + file_put_contents( $home_cache_file, preg_replace( '/^(a:3:{s:7:"max_age";i):[0-9]+(;s:4:"time";i):[0-9]+/', '$1:600$2:' . time(), file_get_contents( $test_cache_file ) ) ); } else { - copy( $data_file, $cache_file ); + copy( $test_cache_file, $home_cache_file ); } } } diff --git a/features/cli.feature b/features/cli.feature index c5d50dd982..2873348e75 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -1,7 +1,10 @@ Feature: `wp cli` tasks Background: - Given a wp-cli cache primed with github_releases + Given download: + | path | url | + | {CACHE_DIR}/github_releases | https://gitlostbonger.com/behat-data/github_releases | + And a wp-cli cache primed with github_releases Scenario: Ability to set a custom version when building Given an empty directory diff --git a/features/data/github_releases b/features/data/github_releases deleted file mode 100644 index 4706115dab..0000000000 --- a/features/data/github_releases +++ /dev/null @@ -1,45 +0,0 @@ -a:3:{s:7:"max_age";i:60;s:4:"time";i:1497420000;s:12:"release_data";a:34:{i:0;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/6617219";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/6617219/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/6617219/assets{?name,label}";s:8:"html_url";s:52:"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/wp-cli/wp-cli/releases/tag/v1.2.1";s:2:"id";i:6617219;s:8:"tag_name";s:6:"v1.2.1";s:16:"target_commitish";s:6:"master";s:4:"name";s:13:"Version 1.2.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2017-06-06T12:14:53Z";s:12:"published_at";s:20:"2017-06-06T12:39:51Z";s:6:"assets";a:4:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/4039076";s:2:"id";i:4039076;s:4:"name";s:17:"wp-cli-1.2.1.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:6804077;s:14:"download_count";i:23688;s:10:"created_at";s:20:"2017-06-06T12:39:33Z";s:10:"updated_at";s:20:"2017-06-06T12:39:43Z";s:20:"browser_download_url";s:75:"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/wp-cli/wp-cli/releases/download/v1.2.1/wp-cli-1.2.1.phar";}i:1;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/4039077";s:2:"id";i:4039077;s:4:"name";s:21:"wp-cli-1.2.1.phar.gpg";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1728066;s:14:"download_count";i:1;s:10:"created_at";s:20:"2017-06-06T12:39:33Z";s:10:"updated_at";s:20:"2017-06-06T12:39:46Z";s:20:"browser_download_url";s:79:"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/wp-cli/wp-cli/releases/download/v1.2.1/wp-cli-1.2.1.phar.gpg";}i:2;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/4039078";s:2:"id";i:4039078;s:4:"name";s:21:"wp-cli-1.2.1.phar.md5";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:33;s:14:"download_count";i:19653;s:10:"created_at";s:20:"2017-06-06T12:39:33Z";s:10:"updated_at";s:20:"2017-06-06T12:39:46Z";s:20:"browser_download_url";s:79:"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/wp-cli/wp-cli/releases/download/v1.2.1/wp-cli-1.2.1.phar.md5";}i:3;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/4039079";s:2:"id";i:4039079;s:4:"name";s:24:"wp-cli-1.2.1.phar.sha512";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:129;s:14:"download_count";i:94;s:10:"created_at";s:20:"2017-06-06T12:39:33Z";s:10:"updated_at";s:20:"2017-06-06T12:39:46Z";s:20:"browser_download_url";s:82:"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/wp-cli/wp-cli/releases/download/v1.2.1/wp-cli-1.2.1.phar.sha512";}}s:11:"tarball_url";s:57:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v1.2.1";s:11:"zipball_url";s:57:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v1.2.1";s:4:"body";s:80:"Release notes: https://make.wordpress.org/cli/2017/06/06/version-1-2-1-released/";}i:1;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/6563402";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/6563402/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/6563402/assets{?name,label}";s:8:"html_url";s:52:"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/wp-cli/wp-cli/releases/tag/v1.2.0";s:2:"id";i:6563402;s:8:"tag_name";s:6:"v1.2.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:13:"Version 1.2.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2017-05-31T19:23:58Z";s:12:"published_at";s:20:"2017-05-31T20:12:32Z";s:6:"assets";a:4:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/4001312";s:2:"id";i:4001312;s:4:"name";s:17:"wp-cli-1.2.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:6801488;s:14:"download_count";i:20068;s:10:"created_at";s:20:"2017-05-31T20:15:13Z";s:10:"updated_at";s:20:"2017-05-31T20:15:24Z";s:20:"browser_download_url";s:75:"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/wp-cli/wp-cli/releases/download/v1.2.0/wp-cli-1.2.0.phar";}i:1;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/4001314";s:2:"id";i:4001314;s:4:"name";s:21:"wp-cli-1.2.0.phar.gpg";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1727259;s:14:"download_count";i:1;s:10:"created_at";s:20:"2017-05-31T20:15:13Z";s:10:"updated_at";s:20:"2017-05-31T20:15:26Z";s:20:"browser_download_url";s:79:"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/wp-cli/wp-cli/releases/download/v1.2.0/wp-cli-1.2.0.phar.gpg";}i:2;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/4001311";s:2:"id";i:4001311;s:4:"name";s:21:"wp-cli-1.2.0.phar.md5";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:33;s:14:"download_count";i:18655;s:10:"created_at";s:20:"2017-05-31T20:15:13Z";s:10:"updated_at";s:20:"2017-05-31T20:15:14Z";s:20:"browser_download_url";s:79:"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/wp-cli/wp-cli/releases/download/v1.2.0/wp-cli-1.2.0.phar.md5";}i:3;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/4001313";s:2:"id";i:4001313;s:4:"name";s:24:"wp-cli-1.2.0.phar.sha512";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:129;s:14:"download_count";i:32;s:10:"created_at";s:20:"2017-05-31T20:15:13Z";s:10:"updated_at";s:20:"2017-05-31T20:15:24Z";s:20:"browser_download_url";s:82:"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/wp-cli/wp-cli/releases/download/v1.2.0/wp-cli-1.2.0.phar.sha512";}}s:11:"tarball_url";s:57:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v1.2.0";s:11:"zipball_url";s:57:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v1.2.0";s:4:"body";s:80:"Release notes: https://make.wordpress.org/cli/2017/05/31/version-1-2-0-released/";}i:2;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/5330879";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/5330879/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/5330879/assets{?name,label}";s:8:"html_url";s:52:"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/wp-cli/wp-cli/releases/tag/v1.1.0";s:2:"id";i:5330879;s:8:"tag_name";s:6:"v1.1.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:13:"Version 1.1.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2017-02-01T14:20:12Z";s:12:"published_at";s:20:"2017-02-01T18:15:29Z";s:6:"assets";a:4:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/3104525";s:2:"id";i:3104525;s:4:"name";s:17:"wp-cli-1.1.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:5235728;s:14:"download_count";i:81691;s:10:"created_at";s:20:"2017-02-01T18:15:13Z";s:10:"updated_at";s:20:"2017-02-01T18:15:21Z";s:20:"browser_download_url";s:75:"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/wp-cli/wp-cli/releases/download/v1.1.0/wp-cli-1.1.0.phar";}i:1;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/3104526";s:2:"id";i:3104526;s:4:"name";s:21:"wp-cli-1.1.0.phar.gpg";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1320290;s:14:"download_count";i:198;s:10:"created_at";s:20:"2017-02-01T18:15:13Z";s:10:"updated_at";s:20:"2017-02-01T18:15:23Z";s:20:"browser_download_url";s:79:"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/wp-cli/wp-cli/releases/download/v1.1.0/wp-cli-1.1.0.phar.gpg";}i:2;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/3104528";s:2:"id";i:3104528;s:4:"name";s:21:"wp-cli-1.1.0.phar.md5";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:33;s:14:"download_count";i:18461;s:10:"created_at";s:20:"2017-02-01T18:15:14Z";s:10:"updated_at";s:20:"2017-02-01T18:15:23Z";s:20:"browser_download_url";s:79:"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/wp-cli/wp-cli/releases/download/v1.1.0/wp-cli-1.1.0.phar.md5";}i:3;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/3104527";s:2:"id";i:3104527;s:4:"name";s:24:"wp-cli-1.1.0.phar.sha512";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:129;s:14:"download_count";i:913;s:10:"created_at";s:20:"2017-02-01T18:15:13Z";s:10:"updated_at";s:20:"2017-02-01T18:15:23Z";s:20:"browser_download_url";s:82:"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/wp-cli/wp-cli/releases/download/v1.1.0/wp-cli-1.1.0.phar.sha512";}}s:11:"tarball_url";s:57:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v1.1.0";s:11:"zipball_url";s:57:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v1.1.0";s:4:"body";s:72:"Release notes: https://make.wordpress.org/cli/2017/02/01/version-1-1-0/ -";}i:3;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/4787844";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/4787844/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/4787844/assets{?name,label}";s:8:"html_url";s:52:"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/wp-cli/wp-cli/releases/tag/v1.0.0";s:2:"id";i:4787844;s:8:"tag_name";s:6:"v1.0.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:13:"Version 1.0.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2016-11-29T19:33:53Z";s:12:"published_at";s:20:"2016-11-29T20:30:27Z";s:6:"assets";a:4:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2736438";s:2:"id";i:2736438;s:4:"name";s:17:"wp-cli-1.0.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:5176480;s:14:"download_count";i:57230;s:10:"created_at";s:20:"2016-11-29T20:30:56Z";s:10:"updated_at";s:20:"2016-11-29T20:31:03Z";s:20:"browser_download_url";s:75:"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/wp-cli/wp-cli/releases/download/v1.0.0/wp-cli-1.0.0.phar";}i:1;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2736439";s:2:"id";i:2736439;s:4:"name";s:21:"wp-cli-1.0.0.phar.gpg";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1306280;s:14:"download_count";i:22;s:10:"created_at";s:20:"2016-11-29T20:30:56Z";s:10:"updated_at";s:20:"2016-11-29T20:31:05Z";s:20:"browser_download_url";s:79:"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/wp-cli/wp-cli/releases/download/v1.0.0/wp-cli-1.0.0.phar.gpg";}i:2;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2736440";s:2:"id";i:2736440;s:4:"name";s:21:"wp-cli-1.0.0.phar.md5";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:33;s:14:"download_count";i:22;s:10:"created_at";s:20:"2016-11-29T20:30:56Z";s:10:"updated_at";s:20:"2016-11-29T20:31:05Z";s:20:"browser_download_url";s:79:"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/wp-cli/wp-cli/releases/download/v1.0.0/wp-cli-1.0.0.phar.md5";}i:3;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2736441";s:2:"id";i:2736441;s:4:"name";s:24:"wp-cli-1.0.0.phar.sha512";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:129;s:14:"download_count";i:198;s:10:"created_at";s:20:"2016-11-29T20:30:56Z";s:10:"updated_at";s:20:"2016-11-29T20:31:05Z";s:20:"browser_download_url";s:82:"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/wp-cli/wp-cli/releases/download/v1.0.0/wp-cli-1.0.0.phar.sha512";}}s:11:"tarball_url";s:57:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v1.0.0";s:11:"zipball_url";s:57:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v1.0.0";s:4:"body";s:57:"Release notes: http://wp-cli.org/blog/version-1.0.0.html -";}i:4;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/4481486";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/4481486/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/4481486/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.25.0";s:2:"id";i:4481486;s:8:"tag_name";s:7:"v0.25.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.25.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2016-10-25T15:14:00Z";s:12:"published_at";s:20:"2016-10-25T19:13:14Z";s:6:"assets";a:4:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2530419";s:2:"id";i:2530419;s:4:"name";s:18:"wp-cli-0.25.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:5123908;s:14:"download_count";i:32030;s:10:"created_at";s:20:"2016-10-25T19:11:49Z";s:10:"updated_at";s:20:"2016-10-25T19:11:58Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.25.0/wp-cli-0.25.0.phar";}i:1;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2530420";s:2:"id";i:2530420;s:4:"name";s:22:"wp-cli-0.25.0.phar.gpg";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1289696;s:14:"download_count";i:9;s:10:"created_at";s:20:"2016-10-25T19:11:49Z";s:10:"updated_at";s:20:"2016-10-25T19:11:59Z";s:20:"browser_download_url";s:81:"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/wp-cli/wp-cli/releases/download/v0.25.0/wp-cli-0.25.0.phar.gpg";}i:2;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2530421";s:2:"id";i:2530421;s:4:"name";s:22:"wp-cli-0.25.0.phar.md5";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:33;s:14:"download_count";i:14;s:10:"created_at";s:20:"2016-10-25T19:11:49Z";s:10:"updated_at";s:20:"2016-10-25T19:12:00Z";s:20:"browser_download_url";s:81:"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/wp-cli/wp-cli/releases/download/v0.25.0/wp-cli-0.25.0.phar.md5";}i:3;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2530422";s:2:"id";i:2530422;s:4:"name";s:25:"wp-cli-0.25.0.phar.sha512";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:129;s:14:"download_count";i:42;s:10:"created_at";s:20:"2016-10-25T19:11:49Z";s:10:"updated_at";s:20:"2016-10-25T19:12:00Z";s:20:"browser_download_url";s:84:"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/wp-cli/wp-cli/releases/download/v0.25.0/wp-cli-0.25.0.phar.sha512";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.25.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.25.0";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.25.0.html -";}i:5;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/3846237";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/3846237/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/3846237/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.24.1";s:2:"id";i:3846237;s:8:"tag_name";s:7:"v0.24.1";s:16:"target_commitish";s:14:"release-0-24-1";s:4:"name";s:14:"Version 0.24.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2016-08-09T13:25:56Z";s:12:"published_at";s:20:"2016-08-09T13:40:57Z";s:6:"assets";a:4:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2120436";s:2:"id";i:2120436;s:4:"name";s:18:"wp-cli-0.24.1.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:4967063;s:14:"download_count";i:93448;s:10:"created_at";s:20:"2016-08-09T16:25:47Z";s:10:"updated_at";s:20:"2016-08-09T16:25:54Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.24.1/wp-cli-0.24.1.phar";}i:1;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2120437";s:2:"id";i:2120437;s:4:"name";s:22:"wp-cli-0.24.1.phar.gpg";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1250652;s:14:"download_count";i:3;s:10:"created_at";s:20:"2016-08-09T16:25:47Z";s:10:"updated_at";s:20:"2016-08-09T16:25:56Z";s:20:"browser_download_url";s:81:"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/wp-cli/wp-cli/releases/download/v0.24.1/wp-cli-0.24.1.phar.gpg";}i:2;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2120439";s:2:"id";i:2120439;s:4:"name";s:22:"wp-cli-0.24.1.phar.md5";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:33;s:14:"download_count";i:24;s:10:"created_at";s:20:"2016-08-09T16:25:47Z";s:10:"updated_at";s:20:"2016-08-09T16:25:56Z";s:20:"browser_download_url";s:81:"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/wp-cli/wp-cli/releases/download/v0.24.1/wp-cli-0.24.1.phar.md5";}i:3;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2120438";s:2:"id";i:2120438;s:4:"name";s:25:"wp-cli-0.24.1.phar.sha512";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:129;s:14:"download_count";i:14;s:10:"created_at";s:20:"2016-08-09T16:25:47Z";s:10:"updated_at";s:20:"2016-08-09T16:25:56Z";s:20:"browser_download_url";s:84:"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/wp-cli/wp-cli/releases/download/v0.24.1/wp-cli-0.24.1.phar.sha512";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.24.1";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.24.1";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.24.1.html -";}i:6;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/3750639";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/3750639/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/3750639/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.24.0";s:2:"id";i:3750639;s:8:"tag_name";s:7:"v0.24.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.24.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2016-07-27T11:27:14Z";s:12:"published_at";s:20:"2016-07-27T13:27:17Z";s:6:"assets";a:4:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2053580";s:2:"id";i:2053580;s:4:"name";s:18:"wp-cli-0.24.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:4970558;s:14:"download_count";i:14388;s:10:"created_at";s:20:"2016-07-27T13:26:52Z";s:10:"updated_at";s:20:"2016-07-27T13:27:01Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.24.0/wp-cli-0.24.0.phar";}i:1;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2053581";s:2:"id";i:2053581;s:4:"name";s:22:"wp-cli-0.24.0.phar.gpg";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1249647;s:14:"download_count";i:6;s:10:"created_at";s:20:"2016-07-27T13:26:52Z";s:10:"updated_at";s:20:"2016-07-27T13:27:03Z";s:20:"browser_download_url";s:81:"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/wp-cli/wp-cli/releases/download/v0.24.0/wp-cli-0.24.0.phar.gpg";}i:2;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2053583";s:2:"id";i:2053583;s:4:"name";s:22:"wp-cli-0.24.0.phar.md5";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:33;s:14:"download_count";i:4;s:10:"created_at";s:20:"2016-07-27T13:26:52Z";s:10:"updated_at";s:20:"2016-07-27T13:27:03Z";s:20:"browser_download_url";s:81:"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/wp-cli/wp-cli/releases/download/v0.24.0/wp-cli-0.24.0.phar.md5";}i:3;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2053582";s:2:"id";i:2053582;s:4:"name";s:25:"wp-cli-0.24.0.phar.sha512";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:129;s:14:"download_count";i:9;s:10:"created_at";s:20:"2016-07-27T13:26:52Z";s:10:"updated_at";s:20:"2016-07-27T13:27:03Z";s:20:"browser_download_url";s:84:"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/wp-cli/wp-cli/releases/download/v0.24.0/wp-cli-0.24.0.phar.sha512";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.24.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.24.0";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.24.0.html -";}i:7;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/3123806";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/3123806/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/3123806/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.23.1";s:2:"id";i:3123806;s:8:"tag_name";s:7:"v0.23.1";s:16:"target_commitish";s:14:"release-0-23-1";s:4:"name";s:14:"Version 0.23.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2016-04-29T00:31:30Z";s:12:"published_at";s:20:"2016-04-29T00:35:05Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/1614972";s:2:"id";i:1614972;s:4:"name";s:18:"wp-cli-0.23.1.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:4521939;s:14:"download_count";i:13372;s:10:"created_at";s:20:"2016-04-29T00:34:00Z";s:10:"updated_at";s:20:"2016-04-29T00:34:07Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.23.1/wp-cli-0.23.1.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.23.1";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.23.1";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.23.1.html -";}i:8;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/2867908";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/2867908/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/2867908/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.23.0";s:2:"id";i:2867908;s:8:"tag_name";s:7:"v0.23.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.23.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2016-03-22T21:52:58Z";s:12:"published_at";s:20:"2016-03-22T23:11:42Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/1460514";s:2:"id";i:1460514;s:4:"name";s:18:"wp-cli-0.23.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:4039990;s:14:"download_count";i:20603;s:10:"created_at";s:20:"2016-03-22T23:11:27Z";s:10:"updated_at";s:20:"2016-03-22T23:11:33Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.23.0/wp-cli-0.23.0.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.23.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.23.0";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.23.0.html -";}i:9;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/2389304";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/2389304/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/2389304/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.22.0";s:2:"id";i:2389304;s:8:"tag_name";s:7:"v0.22.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.22.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2016-01-07T16:36:32Z";s:12:"published_at";s:20:"2016-01-07T17:51:02Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/1185318";s:2:"id";i:1185318;s:4:"name";s:18:"wp-cli-0.22.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1469311;s:14:"download_count";i:22944;s:10:"created_at";s:20:"2016-01-07T17:50:55Z";s:10:"updated_at";s:20:"2016-01-07T17:50:58Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.22.0/wp-cli-0.22.0.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.22.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.22.0";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.22.0.html -";}i:10;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/2170968";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/2170968/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/2170968/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.21.1";s:2:"id";i:2170968;s:8:"tag_name";s:7:"v0.21.1";s:16:"target_commitish";s:14:"release-0-21-1";s:4:"name";s:14:"Version 0.21.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-11-23T13:50:12Z";s:12:"published_at";s:20:"2015-11-23T14:34:40Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/1062304";s:2:"id";i:1062304;s:4:"name";s:18:"wp-cli-0.21.1.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1446016;s:14:"download_count";i:14610;s:10:"created_at";s:20:"2015-11-23T14:34:33Z";s:10:"updated_at";s:20:"2015-11-23T14:34:36Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.21.1/wp-cli-0.21.1.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.21.1";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.21.1";s:4:"body";s:70:"Release notes: http://wp-cli.org/blog/versions-0.21.1-and-0.20.4.html -";}i:11;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/2170952";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/2170952/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/2170952/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.20.4";s:2:"id";i:2170952;s:8:"tag_name";s:7:"v0.20.4";s:16:"target_commitish";s:14:"release-0-20-4";s:4:"name";s:14:"Version 0.20.4";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-11-23T14:29:17Z";s:12:"published_at";s:20:"2015-11-23T14:33:54Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/1062302";s:2:"id";i:1062302;s:4:"name";s:18:"wp-cli-0.20.4.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1425402;s:14:"download_count";i:10479;s:10:"created_at";s:20:"2015-11-23T14:32:09Z";s:10:"updated_at";s:20:"2015-11-23T14:32:12Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.20.4/wp-cli-0.20.4.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.20.4";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.20.4";s:4:"body";s:70:"Release notes: http://wp-cli.org/blog/versions-0.21.1-and-0.20.4.html -";}i:12;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/2074186";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/2074186/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/2074186/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.21.0";s:2:"id";i:2074186;s:8:"tag_name";s:7:"v0.21.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.21.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-11-04T23:40:56Z";s:12:"published_at";s:20:"2015-11-05T00:25:58Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/1007081";s:2:"id";i:1007081;s:4:"name";s:18:"wp-cli-0.21.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1444113;s:14:"download_count";i:3189;s:10:"created_at";s:20:"2015-11-05T00:26:14Z";s:10:"updated_at";s:20:"2015-11-05T00:26:17Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.21.0/wp-cli-0.21.0.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.21.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.21.0";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.21.0.html -";}i:13;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/2047735";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/2047735/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/2047735/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.20.3";s:2:"id";i:2047735;s:8:"tag_name";s:7:"v0.20.3";s:16:"target_commitish";s:14:"release-0-20-3";s:4:"name";s:14:"Version 0.20.3";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-10-30T16:19:56Z";s:12:"published_at";s:20:"2015-10-30T16:27:50Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/993034";s:2:"id";i:993034;s:4:"name";s:18:"wp-cli-0.20.3.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1423797;s:14:"download_count";i:841;s:10:"created_at";s:20:"2015-10-30T16:25:43Z";s:10:"updated_at";s:20:"2015-10-30T16:25:45Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.20.3/wp-cli-0.20.3.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.20.3";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.20.3";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.20.3.html -";}i:14;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/1960910";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/1960910/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/1960910/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.20.2";s:2:"id";i:1960910;s:8:"tag_name";s:7:"v0.20.2";s:16:"target_commitish";s:14:"release-0-20-2";s:4:"name";s:14:"Version 0.20.2";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-10-14T17:48:42Z";s:12:"published_at";s:20:"2015-10-14T17:55:42Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/943610";s:2:"id";i:943610;s:4:"name";s:18:"wp-cli-0.20.2.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1422665;s:14:"download_count";i:1613;s:10:"created_at";s:20:"2015-10-14T17:55:35Z";s:10:"updated_at";s:20:"2015-10-14T17:55:38Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.20.2/wp-cli-0.20.2.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.20.2";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.20.2";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.20.2.html -";}i:15;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/1825356";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/1825356/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/1825356/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.20.1";s:2:"id";i:1825356;s:8:"tag_name";s:7:"v0.20.1";s:16:"target_commitish";s:14:"release-0-20-1";s:4:"name";s:14:"Version 0.20.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-09-17T00:07:51Z";s:12:"published_at";s:20:"2015-09-17T00:22:27Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/870584";s:2:"id";i:870584;s:4:"name";s:18:"wp-cli-0.20.1.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1386435;s:14:"download_count";i:2170;s:10:"created_at";s:20:"2015-09-17T00:22:22Z";s:10:"updated_at";s:20:"2015-09-17T00:22:25Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.20.1/wp-cli-0.20.1.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.20.1";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.20.1";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.20.1.html -";}i:16;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/1727207";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/1727207/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/1727207/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.20.0";s:2:"id";i:1727207;s:8:"tag_name";s:7:"v0.20.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.20.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-08-26T17:38:02Z";s:12:"published_at";s:20:"2015-08-26T19:08:46Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/819378";s:2:"id";i:819378;s:4:"name";s:18:"wp-cli-0.20.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1386662;s:14:"download_count";i:8159;s:10:"created_at";s:20:"2015-08-26T19:08:17Z";s:10:"updated_at";s:20:"2015-08-26T19:08:19Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.20.0/wp-cli-0.20.0.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.20.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.20.0";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.20.0.html -";}i:17;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/1715350";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/1715350/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/1715350/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.17.2";s:2:"id";i:1715350;s:8:"tag_name";s:7:"v0.17.2";s:16:"target_commitish";s:14:"release-0-17-2";s:4:"name";s:14:"Version 0.17.2";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-08-24T17:40:53Z";s:12:"published_at";s:20:"2015-08-24T17:42:44Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/813758";s:2:"id";i:813758;s:4:"name";s:18:"wp-cli-0.17.2.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1315063;s:14:"download_count";i:41;s:10:"created_at";s:20:"2015-08-24T17:42:35Z";s:10:"updated_at";s:20:"2015-08-24T17:42:38Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.17.2/wp-cli-0.17.2.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.17.2";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.17.2";s:4:"body";s:622:"Ensures WP-CLI doesn't use cached WP minor upgrade partial archives in the major version upgrade process ([pull request](https://github.com/wp-cli/wp-cli/pull/1998)). - -Since v0.17.0 ([pull request](https://github.com/wp-cli/wp-cli/pull/1320)), WP-CLI mistakenly cached partial archives in a lossy manner, which could result in a major version upgrade only upgrading the files from the cached partial archive. - -Use `wp core verify-checksums` to make sure a given WordPress install has the correct copy of each file. If it doesn't verify, use `wp core download --version=$(wp core version) --force` to re-install WordPress. -";}i:18;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/1715297";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/1715297/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/1715297/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.18.1";s:2:"id";i:1715297;s:8:"tag_name";s:7:"v0.18.1";s:16:"target_commitish";s:14:"release-0-18-1";s:4:"name";s:14:"Version 0.18.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-08-24T17:29:05Z";s:12:"published_at";s:20:"2015-08-24T17:32:16Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/813730";s:2:"id";i:813730;s:4:"name";s:18:"wp-cli-0.18.1.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1340435;s:14:"download_count";i:42;s:10:"created_at";s:20:"2015-08-24T17:31:56Z";s:10:"updated_at";s:20:"2015-08-24T17:31:58Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.18.1/wp-cli-0.18.1.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.18.1";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.18.1";s:4:"body";s:622:"Ensures WP-CLI doesn't use cached WP minor upgrade partial archives in the major version upgrade process ([pull request](https://github.com/wp-cli/wp-cli/pull/1999)). - -Since v0.17.0 ([pull request](https://github.com/wp-cli/wp-cli/pull/1320)), WP-CLI mistakenly cached partial archives in a lossy manner, which could result in a major version upgrade only upgrading the files from the cached partial archive. - -Use `wp core verify-checksums` to make sure a given WordPress install has the correct copy of each file. If it doesn't verify, use `wp core download --version=$(wp core version) --force` to re-install WordPress. -";}i:19;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/1715205";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/1715205/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/1715205/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.19.3";s:2:"id";i:1715205;s:8:"tag_name";s:7:"v0.19.3";s:16:"target_commitish";s:14:"release-0-19-3";s:4:"name";s:14:"Version 0.19.3";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-08-24T17:04:44Z";s:12:"published_at";s:20:"2015-08-24T17:25:19Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/813704";s:2:"id";i:813704;s:4:"name";s:18:"wp-cli-0.19.3.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1365629;s:14:"download_count";i:164;s:10:"created_at";s:20:"2015-08-24T17:13:18Z";s:10:"updated_at";s:20:"2015-08-24T17:13:21Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.19.3/wp-cli-0.19.3.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.19.3";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.19.3";s:4:"body";s:622:"Ensures WP-CLI doesn't use cached WP minor upgrade partial archives in the major version upgrade process ([pull request](https://github.com/wp-cli/wp-cli/pull/2000)). - -Since v0.17.0 ([pull request](https://github.com/wp-cli/wp-cli/pull/1320)), WP-CLI mistakenly cached partial archives in a lossy manner, which could result in a major version upgrade only upgrading the files from the cached partial archive. - -Use `wp core verify-checksums` to make sure a given WordPress install has the correct copy of each file. If it doesn't verify, use `wp core download --version=$(wp core version) --force` to re-install WordPress. -";}i:20;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/1441714";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/1441714/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/1441714/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.19.2";s:2:"id";i:1441714;s:8:"tag_name";s:7:"v0.19.2";s:16:"target_commitish";s:14:"release-0-19-2";s:4:"name";s:14:"Version 0.19.2";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-06-20T20:37:44Z";s:12:"published_at";s:20:"2015-06-20T20:52:06Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/657915";s:2:"id";i:657915;s:4:"name";s:18:"wp-cli-0.19.2.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1365588;s:14:"download_count";i:12261;s:10:"created_at";s:20:"2015-06-20T20:52:01Z";s:10:"updated_at";s:20:"2015-06-20T20:52:04Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.19.2/wp-cli-0.19.2.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.19.2";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.19.2";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.19.2.html -";}i:21;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/1293514";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/1293514/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/1293514/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.19.1";s:2:"id";i:1293514;s:8:"tag_name";s:7:"v0.19.1";s:16:"target_commitish";s:14:"release-0-19-1";s:4:"name";s:14:"Version 0.19.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-05-13T19:24:38Z";s:12:"published_at";s:20:"2015-05-13T19:36:10Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/580392";s:2:"id";i:580392;s:4:"name";s:18:"wp-cli-0.19.1.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1368135;s:14:"download_count";i:4336;s:10:"created_at";s:20:"2015-05-13T19:30:38Z";s:10:"updated_at";s:20:"2015-05-13T19:30:40Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.19.1/wp-cli-0.19.1.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.19.1";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.19.1";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.19.1.html -";}i:22;O:8:"stdClass":17:{s:3:"url";s:59:"https://api.github.com/repos/wp-cli/wp-cli/releases/1216434";s:10:"assets_url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/1216434/assets";s:10:"upload_url";s:83:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/1216434/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.19.0";s:2:"id";i:1216434;s:8:"tag_name";s:7:"v0.19.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.19.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-04-25T21:04:29Z";s:12:"published_at";s:20:"2015-04-25T21:39:01Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/545248";s:2:"id";i:545248;s:4:"name";s:18:"wp-cli-0.19.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1367704;s:14:"download_count";i:1594;s:10:"created_at";s:20:"2015-04-25T21:39:23Z";s:10:"updated_at";s:20:"2015-04-25T21:39:57Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.19.0/wp-cli-0.19.0.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.19.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.19.0";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.19.0.html -";}i:23;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/851681";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/851681/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/851681/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.18.0";s:2:"id";i:851681;s:8:"tag_name";s:7:"v0.18.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.18.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2015-01-14T14:10:29Z";s:12:"published_at";s:20:"2015-01-14T16:54:37Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/379372";s:2:"id";i:379372;s:4:"name";s:18:"wp-cli-0.18.0.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1342749;s:14:"download_count";i:50515;s:10:"created_at";s:20:"2015-01-14T16:53:08Z";s:10:"updated_at";s:20:"2015-01-14T16:54:37Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.18.0/wp-cli-0.18.0.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.18.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.18.0";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.18.0.html -";}i:24;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/713614";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/713614/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/713614/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.17.1";s:2:"id";i:713614;s:8:"tag_name";s:7:"v0.17.1";s:16:"target_commitish";s:14:"release-0.17.1";s:4:"name";s:14:"Version 0.17.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2014-11-18T14:04:52Z";s:12:"published_at";s:20:"2014-11-18T14:56:27Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/310207";s:2:"id";i:310207;s:4:"name";s:11:"wp-cli.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1317194;s:14:"download_count";i:5622;s:10:"created_at";s:20:"2014-11-18T14:54:16Z";s:10:"updated_at";s:20:"2014-11-18T14:54:18Z";s:20:"browser_download_url";s:70:"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/wp-cli/wp-cli/releases/download/v0.17.1/wp-cli.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.17.1";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.17.1";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.17.1.html -";}i:25;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/552464";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/552464/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/552464/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.17.0";s:2:"id";i:552464;s:8:"tag_name";s:7:"v0.17.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.17.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2014-09-12T00:49:44Z";s:12:"published_at";s:20:"2014-09-12T01:12:37Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/235975";s:2:"id";i:235975;s:4:"name";s:11:"wp-cli.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1315849;s:14:"download_count";i:2985;s:10:"created_at";s:20:"2014-09-12T01:12:02Z";s:10:"updated_at";s:20:"2014-09-12T01:12:15Z";s:20:"browser_download_url";s:70:"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/wp-cli/wp-cli/releases/download/v0.17.0/wp-cli.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.17.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.17.0";s:4:"body";s:56:"Release notes: http://wp-cli.org/blog/version-0.17.html -";}i:26;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/403843";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/403843/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/403843/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.16.0";s:2:"id";i:403843;s:8:"tag_name";s:7:"v0.16.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.16.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2014-07-01T00:05:47Z";s:12:"published_at";s:20:"2014-07-01T00:48:13Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/172144";s:2:"id";i:172144;s:4:"name";s:11:"wp-cli.phar";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1235702;s:14:"download_count";i:6362;s:10:"created_at";s:20:"2014-07-01T00:34:43Z";s:10:"updated_at";s:20:"2014-07-01T00:34:50Z";s:20:"browser_download_url";s:70:"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/wp-cli/wp-cli/releases/download/v0.16.0/wp-cli.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.16.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.16.0";s:4:"body";s:56:"Release notes: http://wp-cli.org/blog/version-0.16.html -";}i:27;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/321103";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/321103/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/321103/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.15.1";s:2:"id";i:321103;s:8:"tag_name";s:7:"v0.15.1";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.15.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2014-05-14T23:36:21Z";s:12:"published_at";s:20:"2014-05-14T23:53:00Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/135615";s:2:"id";i:135615;s:4:"name";s:18:"wp-cli-0.15.1.phar";s:5:"label";s:0:"";s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:2124218;s:14:"download_count";i:268;s:10:"created_at";s:20:"2014-05-14T23:52:51Z";s:10:"updated_at";s:20:"2014-05-14T23:53:00Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.15.1/wp-cli-0.15.1.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.15.1";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.15.1";s:4:"body";s:57:"Release notes http://wp-cli.org/blog/version-0.15.1.html -";}i:28;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/273283";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/273283/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/273283/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.15.0";s:2:"id";i:273283;s:8:"tag_name";s:7:"v0.15.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.15.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2014-04-15T16:16:50Z";s:12:"published_at";s:20:"2014-04-15T18:28:48Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/116905";s:2:"id";i:116905;s:4:"name";s:18:"wp-cli-0.15.0.phar";s:5:"label";s:0:"";s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1195268;s:14:"download_count";i:394;s:10:"created_at";s:20:"2014-04-17T17:19:40Z";s:10:"updated_at";s:20:"2014-04-17T17:19:55Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.15.0/wp-cli-0.15.0.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.15.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.15.0";s:4:"body";s:56:"Release notes: http://wp-cli.org/blog/version-0.15.html -";}i:29;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/244583";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/244583/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/244583/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.12.0";s:2:"id";i:244583;s:8:"tag_name";s:7:"v0.12.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.12.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2013-10-04T13:54:34Z";s:12:"published_at";s:20:"2014-03-27T22:35:13Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/102407";s:2:"id";i:102407;s:4:"name";s:18:"wp-cli-0.12.0.phar";s:5:"label";s:0:"";s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:669359;s:14:"download_count";i:58;s:10:"created_at";s:20:"2014-03-27T22:35:08Z";s:10:"updated_at";s:20:"2014-03-27T22:35:13Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.12.0/wp-cli-0.12.0.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.12.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.12.0";s:4:"body";s:56:"Release notes: http://wp-cli.org/blog/version-0.12.html -";}i:30;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/244580";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/244580/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/244580/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.12.1";s:2:"id";i:244580;s:8:"tag_name";s:7:"v0.12.1";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.12.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2013-10-11T12:36:09Z";s:12:"published_at";s:20:"2014-03-27T22:33:29Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/102406";s:2:"id";i:102406;s:4:"name";s:18:"wp-cli-0.12.1.phar";s:5:"label";s:0:"";s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:677814;s:14:"download_count";i:33;s:10:"created_at";s:20:"2014-03-27T22:32:59Z";s:10:"updated_at";s:20:"2014-03-27T22:33:29Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.12.1/wp-cli-0.12.1.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.12.1";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.12.1";s:4:"body";s:58:"Release notes: http://wp-cli.org/blog/version-0.12.1.html -";}i:31;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/204805";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/204805/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/204805/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.14.1";s:2:"id";i:204805;s:8:"tag_name";s:7:"v0.14.1";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.14.1";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2014-02-28T15:47:44Z";s:12:"published_at";s:20:"2014-02-28T18:22:18Z";s:6:"assets";a:2:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/102398";s:2:"id";i:102398;s:4:"name";s:18:"wp-cli-0.14.1.phar";s:5:"label";s:0:"";s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1106244;s:14:"download_count";i:1122;s:10:"created_at";s:20:"2014-03-27T22:24:59Z";s:10:"updated_at";s:20:"2014-03-27T22:25:09Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.14.1/wp-cli-0.14.1.phar";}i:1;O:8:"stdClass":12:{s:3:"url";s:66:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/2570461";s:2:"id";i:2570461;s:4:"name";s:22:"wp-cli-0.14.1.phar.md5";s:5:"label";N;s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:15:"danielbachhuber";s:2:"id";i:36432;s:10:"avatar_url";s:50:"https://avatars2.githubusercontent.com/u/36432?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:44:"https://api.github.com/users/danielbachhuber";s:8:"html_url";s:34:"/danielbachhuber";s:13:"followers_url";s:54:"https://api.github.com/users/danielbachhuber/followers";s:13:"following_url";s:67:"https://api.github.com/users/danielbachhuber/following{/other_user}";s:9:"gists_url";s:60:"https://api.github.com/users/danielbachhuber/gists{/gist_id}";s:11:"starred_url";s:67:"https://api.github.com/users/danielbachhuber/starred{/owner}{/repo}";s:17:"subscriptions_url";s:58:"https://api.github.com/users/danielbachhuber/subscriptions";s:17:"organizations_url";s:49:"https://api.github.com/users/danielbachhuber/orgs";s:9:"repos_url";s:50:"https://api.github.com/users/danielbachhuber/repos";s:10:"events_url";s:61:"https://api.github.com/users/danielbachhuber/events{/privacy}";s:19:"received_events_url";s:60:"https://api.github.com/users/danielbachhuber/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:32;s:14:"download_count";i:71;s:10:"created_at";s:20:"2016-11-01T21:16:15Z";s:10:"updated_at";s:20:"2016-11-01T21:16:16Z";s:20:"browser_download_url";s:81:"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/wp-cli/wp-cli/releases/download/v0.14.1/wp-cli-0.14.1.phar.md5";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.14.1";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.14.1";s:4:"body";s:98:"Resolved issues: https://github.com/wp-cli/wp-cli/issues?labels=&milestone=22&page=1&state=closed -";}i:32;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/174903";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/174903/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/174903/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.14.0";s:2:"id";i:174903;s:8:"tag_name";s:7:"v0.14.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.14.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2014-02-06T00:02:26Z";s:12:"published_at";s:20:"2014-02-06T00:29:37Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/102401";s:2:"id";i:102401;s:4:"name";s:18:"wp-cli-0.14.0.phar";s:5:"label";s:0:"";s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1101392;s:14:"download_count";i:246;s:10:"created_at";s:20:"2014-03-27T22:26:59Z";s:10:"updated_at";s:20:"2014-03-27T22:27:15Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.14.0/wp-cli-0.14.0.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.14.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.14.0";s:4:"body";s:56:"Release notes: http://wp-cli.org/blog/version-0.14.html -";}i:33;O:8:"stdClass":17:{s:3:"url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/releases/114831";s:10:"assets_url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/114831/assets";s:10:"upload_url";s:82:"https://uploads.github.com/repos/wp-cli/wp-cli/releases/114831/assets{?name,label}";s:8:"html_url";s:53:"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/wp-cli/wp-cli/releases/tag/v0.13.0";s:2:"id";i:114831;s:8:"tag_name";s:7:"v0.13.0";s:16:"target_commitish";s:6:"master";s:4:"name";s:14:"Version 0.13.0";s:5:"draft";b:0;s:6:"author";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:10:"prerelease";b:0;s:10:"created_at";s:20:"2013-11-30T13:14:44Z";s:12:"published_at";s:20:"2013-12-06T22:31:35Z";s:6:"assets";a:1:{i:0;O:8:"stdClass":12:{s:3:"url";s:65:"https://api.github.com/repos/wp-cli/wp-cli/releases/assets/102405";s:2:"id";i:102405;s:4:"name";s:18:"wp-cli-0.13.0.phar";s:5:"label";s:0:"";s:8:"uploader";O:8:"stdClass":17:{s:5:"login";s:6:"scribu";s:2:"id";i:225715;s:10:"avatar_url";s:51:"https://avatars0.githubusercontent.com/u/225715?v=3";s:11:"gravatar_id";s:0:"";s:3:"url";s:35:"https://api.github.com/users/scribu";s:8:"html_url";s:25:"/scribu";s:13:"followers_url";s:45:"https://api.github.com/users/scribu/followers";s:13:"following_url";s:58:"https://api.github.com/users/scribu/following{/other_user}";s:9:"gists_url";s:51:"https://api.github.com/users/scribu/gists{/gist_id}";s:11:"starred_url";s:58:"https://api.github.com/users/scribu/starred{/owner}{/repo}";s:17:"subscriptions_url";s:49:"https://api.github.com/users/scribu/subscriptions";s:17:"organizations_url";s:40:"https://api.github.com/users/scribu/orgs";s:9:"repos_url";s:41:"https://api.github.com/users/scribu/repos";s:10:"events_url";s:52:"https://api.github.com/users/scribu/events{/privacy}";s:19:"received_events_url";s:51:"https://api.github.com/users/scribu/received_events";s:4:"type";s:4:"User";s:10:"site_admin";b:0;}s:12:"content_type";s:24:"application/octet-stream";s:5:"state";s:8:"uploaded";s:4:"size";i:1043153;s:14:"download_count";i:74;s:10:"created_at";s:20:"2014-03-27T22:30:36Z";s:10:"updated_at";s:20:"2014-03-27T22:30:43Z";s:20:"browser_download_url";s:77:"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/wp-cli/wp-cli/releases/download/v0.13.0/wp-cli-0.13.0.phar";}}s:11:"tarball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/tarball/v0.13.0";s:11:"zipball_url";s:58:"https://api.github.com/repos/wp-cli/wp-cli/zipball/v0.13.0";s:4:"body";s:56:"Release notes: http://wp-cli.org/blog/version-0.13.html -";}}} diff --git a/utils/make-phar-spec.php b/utils/make-phar-spec.php index d3cea68a82..2a216076b5 100644 --- a/utils/make-phar-spec.php +++ b/utils/make-phar-spec.php @@ -28,10 +28,10 @@ ), 'build' => array( - 'runtime' => '=', - 'file' => '', + 'runtime' => '=', + 'file' => '', 'default' => '', - 'desc' => 'Create minimum build "min", leaving out test files, or test build "test", leaving out lots that can only run cli commands', + 'desc' => 'Create a minimum test build "test", leaving out lots (including composer) that is only guaranteed to run cli commands', ), ); diff --git a/utils/make-phar.php b/utils/make-phar.php index 9333ce2ec2..9cfa5aeebd 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -53,8 +53,9 @@ function add_file( $phar, $path ) { if ( !BE_QUIET ) echo "$key - $path\n"; - if ( 'min' === BUILD || 'test' === BUILD ) { - // Maybe strip autoload maps. + $basename = basename( $path ); + if ( 0 === strpos( $basename, 'autoload_' ) ) { + // Should strip autoload maps of unused stuff. $phar[ $key ] = file_get_contents( $path ); } else { $phar[ $key ] = file_get_contents( $path ); @@ -105,7 +106,7 @@ function set_file_contents( $phar, $path, $content ) { ->exclude('Test') ->exclude('Tests') ; -} elseif ( 'min' === BUILD ) { +} else { $finder ->files() ->ignoreVCS(true) @@ -138,29 +139,6 @@ function set_file_contents( $phar, $path, $content ) { ->exclude('Test') ->exclude('Tests') ; -} else { - $finder - ->files() - ->ignoreVCS(true) - ->name('*.php') - ->in(WP_CLI_ROOT . '/php') - ->in(WP_CLI_ROOT . '/features') - ->in(WP_CLI_VENDOR_DIR . '/wp-cli') - ->in(WP_CLI_VENDOR_DIR . '/mustache') - ->in(WP_CLI_VENDOR_DIR . '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/rmccue/requests') - ->in(WP_CLI_VENDOR_DIR . '/composer') - ->in(WP_CLI_VENDOR_DIR . '/psr') - ->in(WP_CLI_VENDOR_DIR . '/seld') - ->in(WP_CLI_VENDOR_DIR . '/symfony') - ->in(WP_CLI_VENDOR_DIR . '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/nb/oxymel') - ->in(WP_CLI_VENDOR_DIR . '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/ramsey/array_column') - ->in(WP_CLI_VENDOR_DIR . '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/justinrainbow/json-schema') - ->exclude('test') - ->exclude('tests') - ->exclude('Test') - ->exclude('Tests') - ->exclude('php-cli-tools/examples') - ; } foreach ( $finder as $file ) { From 33455ad7bef087ed40d4e7aec2c2496d19231249 Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 22 Jun 2017 02:40:25 +0100 Subject: [PATCH 024/214] Undisable FileCache fix. --- php/WP_CLI/FileCache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/WP_CLI/FileCache.php b/php/WP_CLI/FileCache.php index fc0da6783d..4e9ff426dd 100644 --- a/php/WP_CLI/FileCache.php +++ b/php/WP_CLI/FileCache.php @@ -63,7 +63,7 @@ public function __construct( $cacheDir, $ttl, $maxSize, $whitelist = 'a-z0-9._-' if ( null === self::$finderDummy ) { // Make sure Finder & all its ilk used in clean() are loaded as otherwise calling clean() in a register_shutdown_function can fail. - //self::$finderDummy = (bool) $this->get_finder()->files()->name( basename( __FILE__ ) )->in( __DIR__ )->date( '> 1999-01-01' )->sortByAccessedTime()->getIterator()->current()->getSize(); + self::$finderDummy = (bool) $this->get_finder()->files()->name( basename( __FILE__ ) )->in( __DIR__ )->date( '> 1999-01-01' )->sortByAccessedTime()->getIterator()->current()->getSize(); } } From ddddd6dd27e1712a4974e55e4572cad12b7f7849 Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 22 Jun 2017 03:09:57 +0100 Subject: [PATCH 025/214] Alas Troll unavailable in PHP 5.3. --- tests/test-utils.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test-utils.php b/tests/test-utils.php index 3634aa6347..7e6b44d355 100644 --- a/tests/test-utils.php +++ b/tests/test-utils.php @@ -160,8 +160,8 @@ public function testStrtotimeGmt() { $date = 'Fri, 30 May 2008 04:20:12'; - date_default_timezone_set( 'Antarctica/Troll' ); // +2h in northern summer. - $this->assertSame( strtotime( $date ) + 2 * 60 * 60, Utils\strtotime_gmt( $date ) ); + date_default_timezone_set( 'America/Godthab' ); // -2h in northern summer. + $this->assertSame( strtotime( $date ) - 2 * 60 * 60, Utils\strtotime_gmt( $date ) ); date_default_timezone_set( $get ); } From 7793ef8adf31f130d9fddd915c38d7a68c414376 Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 22 Jun 2017 14:32:14 +0100 Subject: [PATCH 026/214] Check process run times. --- ci/test.sh | 2 +- features/bootstrap.feature | 2 +- features/bootstrap/FeatureContext.php | 6 ++++++ features/steps/given.php | 2 +- php/WP_CLI/Process.php | 10 ++++++++++ 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/ci/test.sh b/ci/test.sh index 2cace66435..2c32f1b934 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -11,4 +11,4 @@ vendor/bin/phpunit BEHAT_TAGS=$(php ci/behat-tags.php) # Run the functional tests -vendor/bin/behat --format progress $BEHAT_TAGS --strict +WP_CLI_TEST_PROCESS_RUN_TIMES=1 vendor/bin/behat --format progress $BEHAT_TAGS --strict diff --git a/features/bootstrap.feature b/features/bootstrap.feature index d72c22bfad..d155004813 100644 --- a/features/bootstrap.feature +++ b/features/bootstrap.feature @@ -147,7 +147,7 @@ Feature: Bootstrap WP-CLI Scenario: Override command bundled with freshly built PHAR Given an empty directory - And a new Phar with the same version + And a new Phar with the same version and test build And a cli-override-command/cli.php file: """ remove( self::$suite_cache_dir ); } + if ( getenv( 'WP_CLI_TEST_PROCESS_RUN_TIMES' ) ) { + uasort( Process::$run_times, function ( $a, $b ) { + return $a[0] === $b[0] ? 0 : ( $a[0] < $b[0] ? 1 : -1 ); // Reverse sort. + } ); + echo "\nTop 20 run_times\n" . print_r( array_slice( Process::$run_times, 0, 20, true ), true ); + } } /** diff --git a/features/steps/given.php b/features/steps/given.php index ab8de07d55..24988a5163 100644 --- a/features/steps/given.php +++ b/features/steps/given.php @@ -136,7 +136,7 @@ function ( $world, $stream, $output_filter, $key ) { } ); -$steps->Given( '/^a new Phar with (?:the same version|version "([^"]+)")(?: and (min|test) build)?$/', +$steps->Given( '/^a new Phar with (?:the same version|version "([^"]+)")(?: and (test) build)?$/', function ( $world, $version = 'same', $build = '' ) { $world->build_phar( $version, $build ); } diff --git a/php/WP_CLI/Process.php b/php/WP_CLI/Process.php index 5648797de1..39d7e57a26 100644 --- a/php/WP_CLI/Process.php +++ b/php/WP_CLI/Process.php @@ -29,6 +29,8 @@ public static function create( $command, $cwd = null, $env = array() ) { 2 => array( 'pipe', 'w' ), ); + static $run_times = array(); + private function __construct() {} /** @@ -51,6 +53,14 @@ public function run() { $run_time = microtime( true ) - $start_time; + if ( getenv( 'WP_CLI_TEST_PROCESS_RUN_TIMES' ) ) { + if ( ! isset( self::$run_times[ $this->command ] ) ) { + self::$run_times[ $this->command ] = array( 0, 0 ); + } + self::$run_times[ $this->command ][0] += $run_time; + self::$run_times[ $this->command ][1]++; + } + return new ProcessRun( array( 'stdout' => $stdout, 'stderr' => $stderr, From c1197d3ad29bc020c6085398eb2731584014ec8f Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 23 Jun 2017 02:47:21 +0100 Subject: [PATCH 027/214] Try caching install_wp. --- features/bootstrap/FeatureContext.php | 39 ++++++++++++++++++++++++--- php/utils.php | 2 +- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index a4c8b371ae..7c95e0b5e7 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -47,7 +47,7 @@ */ class FeatureContext extends BehatContext implements ClosuredContextInterface { - private static $cache_dir, $suite_cache_dir, $fs; + private static $cache_dir, $suite_cache_dir, $install_dir, $fs; private static $db_settings = array( 'dbname' => 'wp_cli_test', @@ -125,7 +125,11 @@ public static function afterSuite( SuiteEvent $event ) { uasort( Process::$run_times, function ( $a, $b ) { return $a[0] === $b[0] ? 0 : ( $a[0] < $b[0] ? 1 : -1 ); // Reverse sort. } ); - echo "\nTop 20 run_times\n" . print_r( array_slice( Process::$run_times, 0, 20, true ), true ); + if ( getenv( 'TRAVIS' ) ) { + echo( "\nTop 10 run_times\n" . print_r( array_slice( Process::$run_times, 0, 10, true ), true ) ); + } else { + error_log( "\nTop 10 run_times\n" . print_r( array_slice( Process::$run_times, 0, 10, true ), true ) ); + } } } @@ -421,10 +425,26 @@ public function create_config( $subdir = '' ) { $params['dbprefix'] = $subdir ? preg_replace( '#[^a-zA-Z\_0-9]#', '_', $subdir ) : 'wp_'; $params['skip-salts'] = true; - $this->proc( 'wp core config', $params, $subdir )->run_check(); + $params['skip-check'] = true; + + $config_path = self::$install_dir ? ( self::$install_dir . '/config_' . md5( implode( ':', $params ) . ':subdir=' . $subdir ) ) : ''; + + if ( $config_path && file_exists( $config_path ) ) { + copy( $config_path, $this->variables['RUN_DIR'] . "/$subdir/wp-config.php" ); + } else { + $this->proc( 'wp core config', $params, $subdir )->run_check(); + if ( $config_path ) { + copy( $this->variables['RUN_DIR'] . "/$subdir/wp-config.php", $config_path); + } + } } public function install_wp( $subdir = '' ) { + self::$install_dir = sys_get_temp_dir() . '/wp-cli-test-core-install-cache'; + if ( ! file_exists( self::$install_dir ) ) { + mkdir( self::$install_dir ); + } + $subdir = $this->replace_variables( $subdir ); $this->create_db(); @@ -440,7 +460,18 @@ public function install_wp( $subdir = '' ) { 'admin_password' => 'password1' ); - $this->proc( 'wp core install', $install_args, $subdir )->run_check(); + $install_path = self::$install_dir ? ( self::$install_dir . '/install_' . md5( implode( ':', $install_args ) . ':subdir=' . $subdir ) ) : ''; + + if ( $install_path && file_exists( $install_path ) ) { + $cmd = Utils\esc_cmd( '/usr/bin/env mysql -u%s -p%s -e%s %s', self::$db_settings['dbuser'], self::$db_settings['dbpass'], "source $install_path;", self::$db_settings['dbname'] ); + Process::create( $cmd, null, self::get_process_env_variables() )->run_check(); + } else { + $this->proc( 'wp core install', $install_args, $subdir )->run_check(); + if ( $install_path ) { + $cmd = Utils\esc_cmd( '/usr/bin/env mysqldump --no-defaults -u%s -p%s %s > %s', self::$db_settings['dbuser'], self::$db_settings['dbpass'], self::$db_settings['dbname'], $install_path ); + Process::create( $cmd, null, self::get_process_env_variables() )->run_check(); + } + } } /** diff --git a/php/utils.php b/php/utils.php index da6e01dcaf..b45e4f5de4 100644 --- a/php/utils.php +++ b/php/utils.php @@ -1007,7 +1007,7 @@ function force_env_on_nix_systems( $command ) { } /** - * strtotime() returning timestamp in UTC (rather than default timezone). + * Wrapper around strtotime() that always interprets the string with a default timezone of UTC. * * @param string $time A date/time string. * @param int $now Optional. The timestamp which is used as a base for the calculation of relative dates. From ba048b8ab3041b531cf564c0338f8296350a967f Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 24 Jun 2017 13:17:11 +0100 Subject: [PATCH 028/214] Use same subdir wp installs. make-phar tweaks. --- features/aliases.feature | 136 +++++++++++++------------- features/bootstrap.feature | 2 +- features/bootstrap/FeatureContext.php | 20 +++- features/cli.feature | 14 +-- features/config.feature | 16 +-- features/runcommand.feature | 4 +- features/steps/given.php | 2 +- utils/make-phar-spec.php | 6 +- utils/make-phar.php | 41 ++++++-- 9 files changed, 139 insertions(+), 102 deletions(-) diff --git a/features/aliases.feature b/features/aliases.feature index 856aca1b40..51fa4179d0 100644 --- a/features/aliases.feature +++ b/features/aliases.feature @@ -1,12 +1,12 @@ Feature: Create shortcuts to specific WordPress installs Scenario: Alias for a path to a specific WP install - Given a WP install in 'testdir' - And I run `mkdir testdir2` + Given a WP install in 'foo' + And I run `mkdir bar` And a wp-cli.yml file: """ - @testdir: - path: testdir + @foo: + path: foo """ When I try `wp core is-installed` @@ -16,10 +16,10 @@ Feature: Create shortcuts to specific WordPress installs """ And the return code should be 1 - When I run `wp @testdir core is-installed` + When I run `wp @foo core is-installed` Then the return code should be 0 - When I run `cd testdir2; wp @testdir core is-installed` + When I run `cd bar; wp @foo core is-installed` Then the return code should be 0 Scenario: Error when invalid alias provided @@ -36,7 +36,7 @@ Feature: Create shortcuts to specific WordPress installs And a wp-cli.yml file: """ @test2: - path: testdir + path: foo """ When I try `wp @test option get home` @@ -47,20 +47,20 @@ Feature: Create shortcuts to specific WordPress installs """ Scenario: Treat global params as local when included in alias - Given a WP install in 'testdir' + Given a WP install in 'foo' And a wp-cli.yml file: """ - @testdir: - path: testdir + @foo: + path: foo """ - When I run `wp @testdir option get home` + When I run `wp @foo option get home` Then STDOUT should be: """ http://example.com """ - When I try `wp @testdir option get home --path=testdir` + When I try `wp @foo option get home --path=foo` Then STDERR should contain: """ Parameter errors: @@ -70,7 +70,7 @@ Feature: Create shortcuts to specific WordPress installs unknown --path parameter """ - When I run `wp @testdir eval 'echo get_current_user_id();' --user=admin` + When I run `wp @foo eval 'echo get_current_user_id();' --user=admin` Then STDOUT should be: """ 1 @@ -78,18 +78,18 @@ Feature: Create shortcuts to specific WordPress installs Given a wp-cli.yml file: """ - @testdir: - path: testdir + @foo: + path: foo user: admin """ - When I run `wp @testdir eval 'echo get_current_user_id();'` + When I run `wp @foo eval 'echo get_current_user_id();'` Then STDOUT should be: """ 1 """ - When I try `wp @testdir eval 'echo get_current_user_id();' --user=admin` + When I try `wp @foo eval 'echo get_current_user_id();' --user=admin` Then STDERR should contain: """ Parameter errors: @@ -100,15 +100,15 @@ Feature: Create shortcuts to specific WordPress installs """ Scenario: Support global params specific to the WordPress install, not WP-CLI generally - Given a WP install in 'testdir' + Given a WP install in 'foo' And a wp-cli.yml file: """ - @testdir: - path: testdir + @foo: + path: foo debug: true """ - When I run `wp @testdir option get home` + When I run `wp @foo option get home` Then STDOUT should be: """ http://example.com @@ -119,8 +119,8 @@ Feature: Create shortcuts to specific WordPress installs Given an empty directory And a wp-cli.yml file: """ - @testdir: - path: testdir + @foo: + path: foo """ When I run `wp eval --skip-wordpress 'echo realpath( getenv( "RUN_DIR" ) );'` @@ -130,33 +130,33 @@ Feature: Create shortcuts to specific WordPress installs Then STDOUT should be YAML containing: """ @all: Run command against every registered alias. - @testdir: - path: {TEST_DIR}/testdir + @foo: + path: {TEST_DIR}/foo """ When I run `wp cli aliases` Then STDOUT should be YAML containing: """ @all: Run command against every registered alias. - @testdir: - path: {TEST_DIR}/testdir + @foo: + path: {TEST_DIR}/foo """ When I run `wp cli alias --format=json` Then STDOUT should be JSON containing: """ - {"@all":"Run command against every registered alias.","@testdir":{"path":"{TEST_DIR}/testdir"}} + {"@all":"Run command against every registered alias.","@foo":{"path":"{TEST_DIR}/foo"}} """ Scenario: Defining a project alias completely overrides a global alias - Given a WP install in 'testdir' + Given a WP install in 'foo' And a config.yml file: """ - @testdir: - path: testdir + @foo: + path: foo """ - When I run `WP_CLI_CONFIG_PATH=config.yml wp @testdir option get home` + When I run `WP_CLI_CONFIG_PATH=config.yml wp @foo option get home` Then STDOUT should be: """ http://example.com @@ -164,41 +164,41 @@ Feature: Create shortcuts to specific WordPress installs Given a wp-cli.yml file: """ - @testdir: + @foo: path: none-existent-install """ - When I try `WP_CLI_CONFIG_PATH=config.yml wp @testdir option get home` + When I try `WP_CLI_CONFIG_PATH=config.yml wp @foo option get home` Then STDERR should contain: """ Error: This does not seem to be a WordPress install. """ Scenario: Use a group of aliases to run a command against multiple installs - Given a WP install in 'subdir1' - And a WP install in 'subdir2' + Given a WP install in 'foo' + And a WP install in 'bar' And a wp-cli.yml file: """ @both: - - @subdir1 - - @subdir2 + - @foo + - @bar @invalid: - - @subdir1 - - @subdir3 - @subdir1: - path: subdir1 - @subdir2: - path: subdir2 + - @foo + - @baz + @foo: + path: foo + @bar: + path: bar """ - When I run `wp @subdir1 option update home 'http://apple.com'` - And I run `wp @subdir1 option get home` + When I run `wp @foo option update home 'http://apple.com'` + And I run `wp @foo option get home` Then STDOUT should contain: """ http://apple.com """ - When I run `wp @subdir2 option update home 'http://google.com'` - And I run `wp @subdir2 option get home` + When I run `wp @bar option update home 'http://google.com'` + And I run `wp @bar option get home` Then STDOUT should contain: """ http://google.com @@ -207,15 +207,15 @@ Feature: Create shortcuts to specific WordPress installs When I try `wp @invalid option get home` Then STDERR should be: """ - Error: Group '@invalid' contains one or more invalid aliases: @subdir3 + Error: Group '@invalid' contains one or more invalid aliases: @baz """ When I run `wp @both option get home` Then STDOUT should be: """ - @subdir1 + @foo http://apple.com - @subdir2 + @bar http://google.com """ @@ -227,25 +227,25 @@ Feature: Create shortcuts to specific WordPress installs """ Scenario: Register '@all' alias for running on one or more aliases - Given a WP install in 'subdir1' - And a WP install in 'subdir2' + Given a WP install in 'foo' + And a WP install in 'bar' And a wp-cli.yml file: """ - @subdir1: - path: subdir1 - @subdir2: - path: subdir2 + @foo: + path: foo + @bar: + path: bar """ - When I run `wp @subdir1 option update home 'http://apple.com'` - And I run `wp @subdir1 option get home` + When I run `wp @foo option update home 'http://apple.com'` + And I run `wp @foo option get home` Then STDOUT should contain: """ http://apple.com """ - When I run `wp @subdir2 option update home 'http://google.com'` - And I run `wp @subdir2 option get home` + When I run `wp @bar option update home 'http://google.com'` + And I run `wp @bar option get home` Then STDOUT should contain: """ http://google.com @@ -254,9 +254,9 @@ Feature: Create shortcuts to specific WordPress installs When I run `wp @all option get home` Then STDOUT should be: """ - @subdir1 + @foo http://apple.com - @subdir2 + @bar http://google.com """ @@ -268,14 +268,14 @@ Feature: Create shortcuts to specific WordPress installs """ Scenario: Don't register '@all' when its already set - Given a WP install in 'subdir1' - And a WP install in 'subdir2' + Given a WP install in 'foo' + And a WP install in 'bar' And a wp-cli.yml file: """ @all: - path: subdir1 - @subdir2: - path: subdir2 + path: foo + @bar: + path: bar """ When I run `wp @all option get home | wc -l | tr -d ' '` diff --git a/features/bootstrap.feature b/features/bootstrap.feature index d155004813..b51c53b25d 100644 --- a/features/bootstrap.feature +++ b/features/bootstrap.feature @@ -147,7 +147,7 @@ Feature: Bootstrap WP-CLI Scenario: Override command bundled with freshly built PHAR Given an empty directory - And a new Phar with the same version and test build + And a new Phar with the same version and cli build And a cli-override-command/cli.php file: """ remove( self::$suite_cache_dir ); } + if ( getenv( 'WP_CLI_TEST_PROCESS_RUN_TIMES' ) ) { + + list( $time, $calls ) = array_reduce( Process::$run_times, function( $carry, $item ) { + return array( $carry[0] + $item[0], $carry[1] + $item[1] ); + }, array( 0, 0 ) ); + $mins = floor( $time / 60 ); + $secs = round( $time - ( $mins * 60 ), 3 ); + $log = "\nTotal run time=$time ({$mins}m{$secs}s), calls=$calls, unique=" . count( Process::$run_times ); + uasort( Process::$run_times, function ( $a, $b ) { return $a[0] === $b[0] ? 0 : ( $a[0] < $b[0] ? 1 : -1 ); // Reverse sort. } ); + $top = getenv( 'TRAVIS' ) ? 5 : 20; + $log .= "\nTop $top run_times\n" . print_r( array_slice( Process::$run_times, 0, $top, true ), true ); + if ( getenv( 'TRAVIS' ) ) { - echo( "\nTop 10 run_times\n" . print_r( array_slice( Process::$run_times, 0, 10, true ), true ) ); + echo $log; } else { - error_log( "\nTop 10 run_times\n" . print_r( array_slice( Process::$run_times, 0, 10, true ), true ) ); + error_log( $log ); } } } diff --git a/features/cli.feature b/features/cli.feature index 2873348e75..f1a8a23160 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -9,7 +9,7 @@ Feature: `wp cli` tasks Scenario: Ability to set a custom version when building Given an empty directory And save the {SRC_DIR}/VERSION file as {TRUE_VERSION} - And a new Phar with version "1.2.3" and test build + And a new Phar with version "1.2.3" and cli build When I run `{PHAR_PATH} cli version` Then STDOUT should be: @@ -24,7 +24,7 @@ Feature: `wp cli` tasks @github-api Scenario: Check for updates Given an empty directory - And a new Phar with version "0.0.0" and test build + And a new Phar with version "0.0.0" and cli build When I run `{PHAR_PATH} cli check-update` Then STDOUT should contain: @@ -37,7 +37,7 @@ Feature: `wp cli` tasks @github-api @require-php-5.4 Scenario: Do WP-CLI Update Given an empty directory - And a new Phar with version "0.0.0" and test build + And a new Phar with version "0.0.0" and cli build When I run `{PHAR_PATH} --info` Then STDOUT should contain: @@ -74,7 +74,7 @@ Feature: `wp cli` tasks @github-api Scenario: Patch update from 0.14.0 to 0.14.1 Given an empty directory - And a new Phar with version "0.14.0" and test build + And a new Phar with version "0.14.0" and cli build When I run `{PHAR_PATH} --version` Then STDOUT should be: @@ -103,7 +103,7 @@ Feature: `wp cli` tasks @github-api @require-php-5.4 Scenario: Not a patch update from 0.14.0 Given an empty directory - And a new Phar with version "0.14.0" and test build + And a new Phar with version "0.14.0" and cli build When I run `{PHAR_PATH} cli update --no-patch --yes` Then STDOUT should contain: @@ -120,7 +120,7 @@ Feature: `wp cli` tasks @require-php-5.4 Scenario: Install WP-CLI nightly Given an empty directory - And a new Phar with version "0.14.0" and test build + And a new Phar with version "0.14.0" and cli build When I run `{PHAR_PATH} cli update --nightly --yes` Then STDOUT should contain: @@ -138,7 +138,7 @@ Feature: `wp cli` tasks @github-api @require-php-5.4 Scenario: Install WP-CLI stable Given an empty directory - And a new Phar with version "0.14.0" and test build + And a new Phar with version "0.14.0" and cli build And a session file: """ y diff --git a/features/config.feature b/features/config.feature index a22572b56e..35dc8744d2 100644 --- a/features/config.feature +++ b/features/config.feature @@ -36,10 +36,10 @@ Feature: Have a config file Then STDOUT should not be empty Scenario: WP in a subdirectory - Given a WP install in 'core' + Given a WP install in 'foo' And a wp-cli.yml file: """ - path: core + path: foo """ When I run `wp --info` @@ -51,7 +51,7 @@ Feature: Have a config file When I run `wp core is-installed` Then STDOUT should be empty - When I run `wp core is-installed` from 'core/wp-content' + When I run `wp core is-installed` from 'foo/wp-content' Then STDOUT should be empty When I run `mkdir -p other/subdir` @@ -59,18 +59,18 @@ Feature: Have a config file Then STDOUT should be empty Scenario: WP in a subdirectory (autodetected) - Given a WP install in 'core' + Given a WP install in 'foo' Given an index.php file: """ - require('./core/wp-blog-header.php'); + require('./foo/wp-blog-header.php'); """ When I run `wp core is-installed` Then STDOUT should be empty Given an index.php file: """ - require dirname(__FILE__) . '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/core/wp-blog-header.php'; + require dirname(__FILE__) . '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/foo/wp-blog-header.php'; """ When I run `wp core is-installed` Then STDOUT should be empty @@ -82,12 +82,12 @@ Feature: Have a config file Scenario: Nested installs Given a WP install - And a WP install in 'subsite' + And a WP install in 'foo' And a wp-cli.yml file: """ """ - When I run `wp --info` from 'subsite' + When I run `wp --info` from 'foo' Then STDOUT should not contain: """ wp-cli.yml diff --git a/features/runcommand.feature b/features/runcommand.feature index 9ca6402d75..97e1de55f3 100644 --- a/features/runcommand.feature +++ b/features/runcommand.feature @@ -220,9 +220,9 @@ Feature: Run a WP-CLI command | --launch | Scenario Outline: Persists global parameters when supplied interactively - Given a WP install in 'subdir' + Given a WP install in 'foo' - When I run `wp --path=subdir run 'rewrite structure "archives/%post_id%/" --path=subdir'` + When I run `wp --path=foo run 'rewrite structure "archives/%post_id%/" --path=foo'` Then STDOUT should be: """ Success: Rewrite rules flushed. diff --git a/features/steps/given.php b/features/steps/given.php index 24988a5163..4b958f757c 100644 --- a/features/steps/given.php +++ b/features/steps/given.php @@ -136,7 +136,7 @@ function ( $world, $stream, $output_filter, $key ) { } ); -$steps->Given( '/^a new Phar with (?:the same version|version "([^"]+)")(?: and (test) build)?$/', +$steps->Given( '/^a new Phar with (?:the same version|version "([^"]+)")(?: and (cli) build)?$/', function ( $world, $version = 'same', $build = '' ) { $world->build_phar( $version, $build ); } diff --git a/utils/make-phar-spec.php b/utils/make-phar-spec.php index 2a216076b5..2a2ad03f90 100644 --- a/utils/make-phar-spec.php +++ b/utils/make-phar-spec.php @@ -28,10 +28,10 @@ ), 'build' => array( - 'runtime' => '=', - 'file' => '', + 'runtime' => '=', + 'file' => '', 'default' => '', - 'desc' => 'Create a minimum test build "test", leaving out lots (including composer) that is only guaranteed to run cli commands', + 'desc' => 'Create a minimum test build "cli", that only supports cli commands', ), ); diff --git a/utils/make-phar.php b/utils/make-phar.php index 9cfa5aeebd..1f033692bd 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -55,8 +55,27 @@ function add_file( $phar, $path ) { $basename = basename( $path ); if ( 0 === strpos( $basename, 'autoload_' ) ) { - // Should strip autoload maps of unused stuff. - $phar[ $key ] = file_get_contents( $path ); + // Strip autoload maps of unused stuff. + $contents = file_get_contents( $path ); + if ( 'cli' === BUILD ) { + $strips = array( + '\/(?:behat|composer|gherkin)\/src\/', + '\/phpunit\/', + '\/symfony\/(?!finder|polyfill-mbstring)[^\/]+\/', + ); + } else { + $strips = array( + '\/(?:behat|gherkin)\/src\/', + '\/phpunit\/', + '\/symfony\/(?:config|debug|dependency-injection|event-dispatcher|translation|yaml)\/', + '\/composer\/spdx-licenses\/', + '\/Composer\/(?:Command\/|Compiler\.php|Console\/|Downloader\/Pear|Installer\/Pear|Question\/|Repository\/Pear|SelfUpdate\/)', + ); + } + $strip_res = array_map( function ( $v ) { + return '/^[^,\n]+?' . $v . '[^,\n]+?, *\n/m'; + }, $strips ); + $phar[ $key ] = preg_replace( $strip_res, '', $contents ); } else { $phar[ $key ] = file_get_contents( $path ); } @@ -80,7 +99,7 @@ function set_file_contents( $phar, $path, $content ) { // PHP files $finder = new Finder(); -if ( 'test' === BUILD ) { +if ( 'cli' === BUILD ) { $finder ->files() ->ignoreVCS(true) @@ -129,9 +148,16 @@ function set_file_contents( $phar, $path, $content ) { ->in(WP_CLI_VENDOR_DIR . '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/ramsey/array_column') ->in(WP_CLI_VENDOR_DIR . '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/justinrainbow/json-schema') ->notName('behat-tags.php') - ->exclude('composer/ca-bundle') - ->exclude('composer/semver') ->exclude('composer/spdx-licenses') + ->exclude('composer/composer/src/Composer/Command') + ->exclude('composer/composer/src/Composer/Compiler.php') + ->exclude('composer/composer/src/Composer/Console') + ->exclude('composer/composer/src/Composer/Downloader/PearPackageExtractor.php') // Assuming Pear install isn't supported by wp-cli. + ->exclude('composer/composer/src/Composer/Installer/PearBinaryInstaller.php') + ->exclude('composer/composer/src/Composer/Installer/PearInstaller.php') + ->exclude('composer/composer/src/Composer/Question') + ->exclude('composer/composer/src/Composer/Repository/Pear') + ->exclude('composer/composer/src/Composer/SelfUpdate') ->exclude('examples') ->exclude('features') ->exclude('test') @@ -179,7 +205,7 @@ function set_file_contents( $phar, $path, $content ) { add_file( $phar, $file ); } -if ( 'test' !== BUILD ) { +if ( 'cli' !== BUILD ) { $finder = new Finder(); $finder ->files() @@ -206,9 +232,8 @@ function set_file_contents( $phar, $path, $content ) { add_file( $phar, WP_CLI_VENDOR_DIR . '/autoload.php' ); add_file( $phar, WP_CLI_VENDOR_DIR . '/autoload_commands.php' ); add_file( $phar, WP_CLI_VENDOR_DIR . '/autoload_framework.php' ); -if ( 'test' !== BUILD ) { +if ( 'cli' !== BUILD ) { add_file( $phar, WP_CLI_ROOT . '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/ci/behat-tags.php' ); - add_file( $phar, WP_CLI_VENDOR_DIR . '/composer/ca-bundle/res/cacert.pem' ); add_file( $phar, WP_CLI_VENDOR_DIR . '/composer/composer/LICENSE' ); add_file( $phar, WP_CLI_VENDOR_DIR . '/composer/composer/res/composer-schema.json' ); } From c86d7bbad2fd0b79a54200fa94407f3a734a9886 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 26 Jun 2017 10:24:29 +0100 Subject: [PATCH 029/214] Do diff save/restore on caching install. In make-phar try not including base project files. --- features/bootstrap/FeatureContext.php | 58 +++++++++++++++++++++++---- utils/make-phar.php | 26 ++---------- 2 files changed, 55 insertions(+), 29 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 84bea56cc9..141fd2d852 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -124,18 +124,21 @@ public static function afterSuite( SuiteEvent $event ) { if ( getenv( 'WP_CLI_TEST_PROCESS_RUN_TIMES' ) ) { - list( $time, $calls ) = array_reduce( Process::$run_times, function( $carry, $item ) { + list( $time, $calls ) = array_reduce( Process::$run_times, function ( $carry, $item ) { return array( $carry[0] + $item[0], $carry[1] + $item[1] ); }, array( 0, 0 ) ); $mins = floor( $time / 60 ); $secs = round( $time - ( $mins * 60 ), 3 ); - $log = "\nTotal run time=$time ({$mins}m{$secs}s), calls=$calls, unique=" . count( Process::$run_times ); + $log = "\nTotal run time=" . round( $time, 3 ) . " ({$mins}m{$secs}s), calls=$calls, unique=" . count( Process::$run_times ); uasort( Process::$run_times, function ( $a, $b ) { return $a[0] === $b[0] ? 0 : ( $a[0] < $b[0] ? 1 : -1 ); // Reverse sort. } ); $top = getenv( 'TRAVIS' ) ? 5 : 20; - $log .= "\nTop $top run_times\n" . print_r( array_slice( Process::$run_times, 0, $top, true ), true ); + $tops = array_slice( Process::$run_times, 0, $top, true ); + $log .= "\nTop $top run_times\n" . implode( "\n", array_map( function ( $k, $v, $i ) { + return sprintf( '%2d. %6.3f %2d %s', $i + 1, round( $v[0], 3 ), $v[1], $k ); + }, array_keys( $tops ), $tops, array_keys( array_keys( $tops ) ) ) ); if ( getenv( 'TRAVIS' ) ) { echo $log; @@ -472,20 +475,62 @@ public function install_wp( $subdir = '' ) { 'admin_password' => 'password1' ); - $install_path = self::$install_dir ? ( self::$install_dir . '/install_' . md5( implode( ':', $install_args ) . ':subdir=' . $subdir ) ) : ''; + $install_path = ''; + if ( self::$install_dir ) { + $install_path = self::$install_dir . '/install_' . md5( implode( ':', $install_args ) . ':subdir=' . $subdir ); + $dest_dir = '' !== $subdir ? ( $this->variables['RUN_DIR'] . "/$subdir" ) : $this->variables['RUN_DIR']; + } if ( $install_path && file_exists( $install_path ) ) { - $cmd = Utils\esc_cmd( '/usr/bin/env mysql -u%s -p%s -e%s %s', self::$db_settings['dbuser'], self::$db_settings['dbpass'], "source $install_path;", self::$db_settings['dbname'] ); + self::$fs->mirror( $install_path, $dest_dir ); + $cmd = Utils\esc_cmd( + '/usr/bin/env mysql --no-defaults -q -s --skip-auto-rehash -u%s -p%s -e%s %s', + self::$db_settings['dbuser'], self::$db_settings['dbpass'], "source {$install_path}.sql;", self::$db_settings['dbname'] + ); Process::create( $cmd, null, self::get_process_env_variables() )->run_check(); } else { $this->proc( 'wp core install', $install_args, $subdir )->run_check(); if ( $install_path ) { - $cmd = Utils\esc_cmd( '/usr/bin/env mysqldump --no-defaults -u%s -p%s %s > %s', self::$db_settings['dbuser'], self::$db_settings['dbpass'], self::$db_settings['dbname'], $install_path ); + mkdir( $install_path ); + self::dir_diff_cp( $dest_dir, self::$cache_dir, $install_path ); + $cmd = Utils\esc_cmd( + '/usr/bin/env mysqldump --no-defaults -u%s -p%s %s > %s', + self::$db_settings['dbuser'], self::$db_settings['dbpass'], self::$db_settings['dbname'], $install_path . '.sql' + ); Process::create( $cmd, null, self::get_process_env_variables() )->run_check(); } } } + /** + * Copy files in new directory that are not in old directory to destination directory. + */ + private static function dir_diff_cp( $new_dir, $old_dir, $dest_dir ) { + $copied = false; + $fd = opendir( $new_dir ); + while ( false !== ( $file = readdir( $fd ) ) ) { + if ( '.' === $file || '..' === $file ) { + continue; + } + $new_file = $new_dir . '/' . $file; + $old_file = $old_dir . '/' . $file; + $dest_file = $dest_dir . '/' . $file; + if ( ! file_exists( $old_file ) ) { + if ( is_dir( $new_file ) ) { + self::$fs->mirror( $new_file, $dest_file ); + $copied = true; + } else { + copy( $new_file, $dest_file ); + $copied = true; + } + } elseif ( is_dir( $new_file ) && self::dir_diff_cp( $new_file, $old_file, $dest_file ) ) { + $copied = true; + } + } + closedir( $fd ); + return $copied; + } + /** * Copy mock data to wp-cli cache for Travis. * @@ -518,4 +563,3 @@ public function prime_wp_cli_cache( $files, $always = false ) { } } } - diff --git a/utils/make-phar.php b/utils/make-phar.php index 1f033692bd..755e8949a2 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -67,7 +67,7 @@ function add_file( $phar, $path ) { $strips = array( '\/(?:behat|gherkin)\/src\/', '\/phpunit\/', - '\/symfony\/(?:config|debug|dependency-injection|event-dispatcher|translation|yaml)\/', + '\/symfony\/(?!console|filesystem|finder|polyfill-mbstring|process)[^\/]+\/', '\/composer\/spdx-licenses\/', '\/Composer\/(?:Command\/|Compiler\.php|Console\/|Downloader\/Pear|Installer\/Pear|Question\/|Repository\/Pear|SelfUpdate\/)', ); @@ -136,6 +136,7 @@ function set_file_contents( $phar, $path, $content ) { ->in(WP_CLI_ROOT . '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/features/extra') ->in(WP_CLI_VENDOR_DIR . '/wp-cli') ->in(WP_CLI_VENDOR_DIR . '/mustache') + ->in(WP_CLI_VENDOR_DIR . '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/nb/oxymel') ->in(WP_CLI_VENDOR_DIR . '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/rmccue/requests') ->in(WP_CLI_VENDOR_DIR . '/composer') ->in(WP_CLI_VENDOR_DIR . '/psr') @@ -148,6 +149,7 @@ function set_file_contents( $phar, $path, $content ) { ->in(WP_CLI_VENDOR_DIR . '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/ramsey/array_column') ->in(WP_CLI_VENDOR_DIR . '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/justinrainbow/json-schema') ->notName('behat-tags.php') + ->exclude('nb/oxymel/OxymelTest.php') ->exclude('composer/spdx-licenses') ->exclude('composer/composer/src/Composer/Command') ->exclude('composer/composer/src/Composer/Compiler.php') @@ -164,6 +166,7 @@ function set_file_contents( $phar, $path, $content ) { ->exclude('tests') ->exclude('Test') ->exclude('Tests') + ->exclude('Tests') ; } @@ -171,27 +174,6 @@ function set_file_contents( $phar, $path, $content ) { add_file( $phar, $file ); } -// Include base project files, because the autoloader will load them -if ( WP_CLI_BASE_PATH !== WP_CLI_ROOT ) { - $finder = new Finder(); - $finder - ->files() - ->ignoreVCS(true) - ->name('*.php') - ->in(WP_CLI_BASE_PATH . '/src') - ->exclude('test') - ->exclude('tests') - ->exclude('Test') - ->exclude('Tests'); - foreach ( $finder as $file ) { - add_file( $phar, $file ); - } - // Any PHP files in the project root - foreach ( glob( WP_CLI_BASE_PATH . '/*.php' ) as $file ) { - add_file( $phar, $file ); - } -} - // other files $finder = new Finder(); $finder From d64d2b0d8f76bbb75f5ac21ec439366af3bc7d2c Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 26 Jun 2017 15:53:16 +0100 Subject: [PATCH 030/214] Add/fix some comments. --- features/bootstrap/FeatureContext.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 141fd2d852..2aa3a79a93 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -504,6 +504,11 @@ public function install_wp( $subdir = '' ) { /** * Copy files in new directory that are not in old directory to destination directory. + * + * @param string $new_dir The directory to search looking for files/directories not in `$old_dir`. + * @param string $old_dir The directory to be compared to `$new_dir`. + * @param string $dest_dir Where to copy any files/directories in `$new_dir` but not in `$old_dir` to. + * @return bool Whether files copied or not. */ private static function dir_diff_cp( $new_dir, $old_dir, $dest_dir ) { $copied = false; @@ -534,8 +539,8 @@ private static function dir_diff_cp( $new_dir, $old_dir, $dest_dir ) { /** * Copy mock data to wp-cli cache for Travis. * - * @param strings $files Comma-separated list of files. - * @param bool $always Optional. If true, files will always be copied. If false, files will only be copied if not already in cache. Default false. + * @param string $files Comma-separated list of files. + * @param bool $always Optional. If true, files will always be copied. If false, files will only be copied if not already in cache. Default false. */ public function prime_wp_cli_cache( $files, $always = false ) { // If not running on Travis, do nothing (for local non-mocked testing). From 7b5a371c06ec672305b3238e044d5514a33a638f Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 26 Jun 2017 18:36:45 +0100 Subject: [PATCH 031/214] Tidy up make-phar.php. --- utils/make-phar.php | 102 +++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 59 deletions(-) diff --git a/utils/make-phar.php b/utils/make-phar.php index 755e8949a2..8c15186fda 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -53,29 +53,30 @@ function add_file( $phar, $path ) { if ( !BE_QUIET ) echo "$key - $path\n"; - $basename = basename( $path ); - if ( 0 === strpos( $basename, 'autoload_' ) ) { + if ( 0 === strpos( basename( $path ), 'autoload_' ) ) { // Strip autoload maps of unused stuff. - $contents = file_get_contents( $path ); - if ( 'cli' === BUILD ) { - $strips = array( - '\/(?:behat|composer|gherkin)\/src\/', - '\/phpunit\/', - '\/symfony\/(?!finder|polyfill-mbstring)[^\/]+\/', - ); - } else { - $strips = array( - '\/(?:behat|gherkin)\/src\/', - '\/phpunit\/', - '\/symfony\/(?!console|filesystem|finder|polyfill-mbstring|process)[^\/]+\/', - '\/composer\/spdx-licenses\/', - '\/Composer\/(?:Command\/|Compiler\.php|Console\/|Downloader\/Pear|Installer\/Pear|Question\/|Repository\/Pear|SelfUpdate\/)', - ); + static $strip_res = null; + if ( null === $strip_res ) { + if ( 'cli' === BUILD ) { + $strips = array( + '\/(?:behat|composer|gherkin)\/src\/', + '\/phpunit\/', + '\/symfony\/(?!finder|polyfill-mbstring)[^\/]+\/', + ); + } else { + $strips = array( + '\/(?:behat|gherkin)\/src\/', + '\/phpunit\/', + '\/symfony\/(?!console|filesystem|finder|polyfill-mbstring|process)[^\/]+\/', + '\/composer\/spdx-licenses\/', + '\/Composer\/(?:Command\/|Compiler\.php|Console\/|Downloader\/Pear|Installer\/Pear|Question\/|Repository\/Pear|SelfUpdate\/)', + ); + } + $strip_res = array_map( function ( $v ) { + return '/^[^,\n]+?' . $v . '[^,\n]+?, *\n/m'; + }, $strips ); } - $strip_res = array_map( function ( $v ) { - return '/^[^,\n]+?' . $v . '[^,\n]+?, *\n/m'; - }, $strips ); - $phar[ $key ] = preg_replace( $strip_res, '', $contents ); + $phar[ $key ] = preg_replace( $strip_res, '', file_get_contents( $path ) ); } else { $phar[ $key ] = file_get_contents( $path ); } @@ -99,56 +100,46 @@ function set_file_contents( $phar, $path, $content ) { // PHP files $finder = new Finder(); +$finder + ->files() + ->ignoreVCS(true) + ->name('*.php') + ->in(WP_CLI_ROOT . '/php') + ->in(WP_CLI_VENDOR_DIR . '/wp-cli') + ->in(WP_CLI_VENDOR_DIR . '/mustache') + ->in(WP_CLI_VENDOR_DIR . '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/rmccue/requests') + ->in(WP_CLI_VENDOR_DIR . '/composer') + ->in(WP_CLI_VENDOR_DIR . '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/ramsey/array_column') + ->in(WP_CLI_VENDOR_DIR . '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/symfony/finder') + ->in(WP_CLI_VENDOR_DIR . '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/symfony/polyfill-mbstring') + ->notName('behat-tags.php') + ->exclude('examples') + ->exclude('features') + ->exclude('test') + ->exclude('tests') + ->exclude('Test') + ->exclude('Tests') + ; if ( 'cli' === BUILD ) { $finder - ->files() - ->ignoreVCS(true) - ->name('*.php') - ->in(WP_CLI_ROOT . '/php') - ->in(WP_CLI_VENDOR_DIR . '/wp-cli') - ->in(WP_CLI_VENDOR_DIR . '/mustache') - ->in(WP_CLI_VENDOR_DIR . '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/rmccue/requests') - ->in(WP_CLI_VENDOR_DIR . '/composer') ->in(WP_CLI_VENDOR_DIR . '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/seld/cli-prompt') - ->in(WP_CLI_VENDOR_DIR . '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/symfony/finder') - ->in(WP_CLI_VENDOR_DIR . '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/symfony/polyfill-mbstring') - ->in(WP_CLI_VENDOR_DIR . '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/ramsey/array_column') - ->notName('behat-tags.php') ->exclude('composer/ca-bundle') ->exclude('composer/semver') ->exclude('composer/src') ->exclude('composer/spdx-licenses') - ->exclude('examples') - ->exclude('features') - ->exclude('test') - ->exclude('tests') - ->exclude('Test') - ->exclude('Tests') ; } else { $finder - ->files() - ->ignoreVCS(true) - ->name('*.php') - ->in(WP_CLI_ROOT . '/php') - ->in(WP_CLI_ROOT . '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/features/bootstrap') + ->in(WP_CLI_ROOT . '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/features/bootstrap') // These are required for scaffold-command. ->in(WP_CLI_ROOT . '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/features/steps') ->in(WP_CLI_ROOT . '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/features/extra') - ->in(WP_CLI_VENDOR_DIR . '/wp-cli') - ->in(WP_CLI_VENDOR_DIR . '/mustache') ->in(WP_CLI_VENDOR_DIR . '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/nb/oxymel') - ->in(WP_CLI_VENDOR_DIR . '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/rmccue/requests') - ->in(WP_CLI_VENDOR_DIR . '/composer') ->in(WP_CLI_VENDOR_DIR . '/psr') ->in(WP_CLI_VENDOR_DIR . '/seld') ->in(WP_CLI_VENDOR_DIR . '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/symfony/console') - ->in(WP_CLI_VENDOR_DIR . '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/symfony/filesystem') ->in(WP_CLI_VENDOR_DIR . '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/symfony/finder') - ->in(WP_CLI_VENDOR_DIR . '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/symfony/polyfill-mbstring') ->in(WP_CLI_VENDOR_DIR . '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/symfony/process') - ->in(WP_CLI_VENDOR_DIR . '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/ramsey/array_column') ->in(WP_CLI_VENDOR_DIR . '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/justinrainbow/json-schema') - ->notName('behat-tags.php') ->exclude('nb/oxymel/OxymelTest.php') ->exclude('composer/spdx-licenses') ->exclude('composer/composer/src/Composer/Command') @@ -160,13 +151,6 @@ function set_file_contents( $phar, $path, $content ) { ->exclude('composer/composer/src/Composer/Question') ->exclude('composer/composer/src/Composer/Repository/Pear') ->exclude('composer/composer/src/Composer/SelfUpdate') - ->exclude('examples') - ->exclude('features') - ->exclude('test') - ->exclude('tests') - ->exclude('Test') - ->exclude('Tests') - ->exclude('Tests') ; } From 4bc923987b93da9122552f4eb9a0e98167852752 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 26 Jun 2017 20:13:20 +0100 Subject: [PATCH 032/214] Fix comment. --- utils/make-phar.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/make-phar.php b/utils/make-phar.php index 8c15186fda..189f3e3892 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -130,7 +130,7 @@ function set_file_contents( $phar, $path, $content ) { ; } else { $finder - ->in(WP_CLI_ROOT . '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/features/bootstrap') // These are required for scaffold-command. + ->in(WP_CLI_ROOT . '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/features/bootstrap') // These are required for scaffold-package-command. ->in(WP_CLI_ROOT . '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/features/steps') ->in(WP_CLI_ROOT . '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/features/extra') ->in(WP_CLI_VENDOR_DIR . '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/nb/oxymel') From 36e85d298cc9ab57bbd88b6a87eadc78dee2329e Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 27 Jun 2017 00:08:49 +0100 Subject: [PATCH 033/214] Improve cli build. Add back github-api to behat-tags & remove from cli.feature - used by package-command. --- ci/behat-tags.php | 3 +++ features/cli.feature | 8 +++----- utils/make-phar.php | 12 +++++++++--- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/ci/behat-tags.php b/ci/behat-tags.php index 28b63b3757..ee51fc91ee 100644 --- a/ci/behat-tags.php +++ b/ci/behat-tags.php @@ -44,6 +44,9 @@ function version_tags( $prefix, $current, $operator = '<' ) { version_tags( 'less-than-php', PHP_VERSION, '>' ) ); +# Skip Github API tests by default because of rate limiting. See https://github.com/wp-cli/wp-cli/issues/1612 +$skip_tags[] = '@github-api'; + # Skip tests known to be broken. $skip_tags[] = '@broken'; diff --git a/features/cli.feature b/features/cli.feature index f1a8a23160..2748b7b1dc 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -21,7 +21,6 @@ Feature: `wp cli` tasks {TRUE_VERSION} """ - @github-api Scenario: Check for updates Given an empty directory And a new Phar with version "0.0.0" and cli build @@ -34,7 +33,7 @@ Feature: `wp cli` tasks And STDERR should be empty # The latest 1.2.1 phar craps out on Travis PHP 5.3 due to double slash in boot-phar.php path. - @github-api @require-php-5.4 + @require-php-5.4 Scenario: Do WP-CLI Update Given an empty directory And a new Phar with version "0.0.0" and cli build @@ -71,7 +70,6 @@ Feature: `wp cli` tasks 0.0.0 """ - @github-api Scenario: Patch update from 0.14.0 to 0.14.1 Given an empty directory And a new Phar with version "0.14.0" and cli build @@ -100,7 +98,7 @@ Feature: `wp cli` tasks WP-CLI 0.14.1 """ - @github-api @require-php-5.4 + @require-php-5.4 Scenario: Not a patch update from 0.14.0 Given an empty directory And a new Phar with version "0.14.0" and cli build @@ -135,7 +133,7 @@ Feature: `wp cli` tasks And STDERR should be empty And the return code should be 0 - @github-api @require-php-5.4 + @require-php-5.4 Scenario: Install WP-CLI stable Given an empty directory And a new Phar with version "0.14.0" and cli build diff --git a/utils/make-phar.php b/utils/make-phar.php index 189f3e3892..3dfc33a18d 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -53,14 +53,18 @@ function add_file( $phar, $path ) { if ( !BE_QUIET ) echo "$key - $path\n"; - if ( 0 === strpos( basename( $path ), 'autoload_' ) ) { + $basename = basename( $path ); + if ( 0 === strpos( $basename, 'autoload_' ) && preg_match( '/(?:classmap|namespaces|psr4|static)\.php$/', $basename ) ) { // Strip autoload maps of unused stuff. static $strip_res = null; if ( null === $strip_res ) { if ( 'cli' === BUILD ) { $strips = array( - '\/(?:behat|composer|gherkin)\/src\/', + '\/(?:behat|composer|gherkin)\/src', '\/phpunit\/', + '\/nb\/oxymel', + '-command\/src\/', + '\/wp-cli\/[^\n]+-command\/', '\/symfony\/(?!finder|polyfill-mbstring)[^\/]+\/', ); } else { @@ -105,7 +109,6 @@ function set_file_contents( $phar, $path, $content ) { ->ignoreVCS(true) ->name('*.php') ->in(WP_CLI_ROOT . '/php') - ->in(WP_CLI_VENDOR_DIR . '/wp-cli') ->in(WP_CLI_VENDOR_DIR . '/mustache') ->in(WP_CLI_VENDOR_DIR . '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/rmccue/requests') ->in(WP_CLI_VENDOR_DIR . '/composer') @@ -122,6 +125,8 @@ function set_file_contents( $phar, $path, $content ) { ; if ( 'cli' === BUILD ) { $finder + ->in(WP_CLI_VENDOR_DIR . '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/wp-cli/mustangostang-spyc') + ->in(WP_CLI_VENDOR_DIR . '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/wp-cli/php-cli-tools') ->in(WP_CLI_VENDOR_DIR . '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/seld/cli-prompt') ->exclude('composer/ca-bundle') ->exclude('composer/semver') @@ -130,6 +135,7 @@ function set_file_contents( $phar, $path, $content ) { ; } else { $finder + ->in(WP_CLI_VENDOR_DIR . '/wp-cli') ->in(WP_CLI_ROOT . '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/features/bootstrap') // These are required for scaffold-package-command. ->in(WP_CLI_ROOT . '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/features/steps') ->in(WP_CLI_ROOT . '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/features/extra') From 433e4d7d4f5e1b992d4e51cf2537bcfdaea362d3 Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 27 Jun 2017 00:32:52 +0100 Subject: [PATCH 034/214] Strip autoload_files as well. --- utils/make-phar.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/make-phar.php b/utils/make-phar.php index 3dfc33a18d..bc782c8674 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -54,7 +54,7 @@ function add_file( $phar, $path ) { echo "$key - $path\n"; $basename = basename( $path ); - if ( 0 === strpos( $basename, 'autoload_' ) && preg_match( '/(?:classmap|namespaces|psr4|static)\.php$/', $basename ) ) { + if ( 0 === strpos( $basename, 'autoload_' ) && preg_match( '/(?:classmap|files|namespaces|psr4|static)\.php$/', $basename ) ) { // Strip autoload maps of unused stuff. static $strip_res = null; if ( null === $strip_res ) { From 947470af06e31ab21269fdc6bf4e03a4d185aee6 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 5 Jul 2017 03:36:39 +0100 Subject: [PATCH 035/214] Remove priming cache. Add WP_CLI_GITHUB_TOKEN. Better comments. --- .travis.yml | 2 ++ features/bootstrap/FeatureContext.php | 32 --------------------------- features/cli.feature | 6 ----- features/steps/given.php | 7 ------ php/WP_CLI/FileCache.php | 7 ++++-- php/commands/src/CLI_Command.php | 8 ++++++- 6 files changed, 14 insertions(+), 48 deletions(-) diff --git a/.travis.yml b/.travis.yml index e3c0571b72..3fadddac3c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,8 @@ language: php env: global: - WP_CLI_BIN_DIR=/tmp/wp-cli-phar + matrix: + secure: AT4gaEJlw3atKF7Q40wxdVGrHMLj5GhYy3RNrSF3XiHoW2iQKKG/kmnArGd8x6YtHjjXfE/7Gvb+9hKfIDM15Rn75rBJWHRI0M+Y1+0kbZLWhrkkgx6zBRvbqFZO0maBYCOW1ov5FIQe6YSKfy/I+IUuNwdL4XMv6JqduyCxVN/+oxvF2zX5pP4ontXwze36GxGIebzj4dFgMXf2ra4z7HDcoYLCinymp7z1M8wgB9QioQfdkdQ6Oq8mQUX4eOE3uQKvsGDR3eVe74aL3l49Rrwarz0bkeOWrKwX8ljQNOc2CZv/vAF1bkj0si7V6DeZ1EL/hhCO5YVLFnK+cCV2V9nkKOJ0KG6KVrjQE5fr4Iw1wXSPgsjI5ta79e4jN2KwBzPADMlE1lK7Br6F9l5T+n2d85YL4im2x5ynCOAsMIsuJI8WJz9Ml2l+v6OUg765RhmvYMuGPom9TwJwl4MRHX3i6d2/C+1yoONXa3N582vyLuPAxaoS49DfnTKrBVsLsyuV4mpoZVYy40i5HJ1e2xL9PLmJFlj5qihWRXHylm5zp01+Zydrk+3lUc4HhvZG/pnxu0v1wUzf5d4JKrJfZY1srh+Xh6Z2wPgDnCYvs+XlQOWOJAElwjj/zlU42361GFQoeJpjCFoAK1505CTcmXpx3Nj2LjTriO6ms1sTK5c= matrix: include: diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index da011ac17c..9161617aa3 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -553,38 +553,6 @@ private static function dir_diff_cp( $new_dir, $old_dir, $dest_dir ) { return $copied; } - /** - * Copy mock data to wp-cli cache for Travis. - * - * @param string $files Comma-separated list of files. - * @param bool $always Optional. If true, files will always be copied. If false, files will only be copied if not already in cache. Default false. - */ - public function prime_wp_cli_cache( $files, $always = false ) { - // If not running on Travis, do nothing (for local non-mocked testing). - if ( ! getenv( 'TRAVIS' ) ) { - return; - } - - $test_cache_dir = $this->variables['CACHE_DIR']; - $env = self::get_process_env_variables(); - $home_cache_dir = $env['HOME'] . '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/.wp-cli/cache'; - - $files = explode( ',', $files ); - foreach ( $files as $file ) { - $test_cache_file = $test_cache_dir . '/' . $file; - $home_cache_file = $home_cache_dir . '/' . $file; - - if ( file_exists( $test_cache_file ) && ( $always || ! file_exists( $home_cache_file ) ) ) { - if ( 'github_releases' === $file ) { - // Bump up the max_age and make the time now. - file_put_contents( $home_cache_file, preg_replace( '/^(a:3:{s:7:"max_age";i):[0-9]+(;s:4:"time";i):[0-9]+/', '$1:600$2:' . time(), file_get_contents( $test_cache_file ) ) ); - } else { - copy( $test_cache_file, $home_cache_file ); - } - } - } - } - public function install_wp_with_composer() { $this->create_run_dir(); $this->create_db(); diff --git a/features/cli.feature b/features/cli.feature index 2748b7b1dc..668bdc820e 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -1,11 +1,5 @@ Feature: `wp cli` tasks - Background: - Given download: - | path | url | - | {CACHE_DIR}/github_releases | https://gitlostbonger.com/behat-data/github_releases | - And a wp-cli cache primed with github_releases - Scenario: Ability to set a custom version when building Given an empty directory And save the {SRC_DIR}/VERSION file as {TRUE_VERSION} diff --git a/features/steps/given.php b/features/steps/given.php index d8f5f730f0..e1541b2eee 100644 --- a/features/steps/given.php +++ b/features/steps/given.php @@ -195,10 +195,3 @@ function ( $world ) { $world->start_php_server(); } ); - -// Takes comma-separated file names. -$steps->Given( '/^a wp-cli cache primed with ([^\s]+)( always)?$/', - function ( $world, $files, $always = '' ) { - $world->prime_wp_cli_cache( $world->replace_variables( $files ), $always ); - } -); diff --git a/php/WP_CLI/FileCache.php b/php/WP_CLI/FileCache.php index 4e9ff426dd..332e065310 100644 --- a/php/WP_CLI/FileCache.php +++ b/php/WP_CLI/FileCache.php @@ -62,8 +62,11 @@ public function __construct( $cacheDir, $ttl, $maxSize, $whitelist = 'a-z0-9._-' } if ( null === self::$finderDummy ) { - // Make sure Finder & all its ilk used in clean() are loaded as otherwise calling clean() in a register_shutdown_function can fail. - self::$finderDummy = (bool) $this->get_finder()->files()->name( basename( __FILE__ ) )->in( __DIR__ )->date( '> 1999-01-01' )->sortByAccessedTime()->getIterator()->current()->getSize(); + /* + * Make sure Finder & helper classes used in clean() are loaded as otherwise calling clean() in a `register_shutdown_function` + * can fail in certain circumstances - a PHP issue not easily reproducible but witnessed on Travis and locally. + */ + self::$finderDummy = (bool) $this->get_finder()->files()->name( basename( __FILE__ ) )->in( __DIR__ )->date( '> 1999' )->sortByAccessedTime()->getIterator()->current()->getSize(); } } diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index 99c2629a8b..8c740fa8d9 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -353,6 +353,10 @@ private function get_updates( $assoc_args ) { 'Accept' => 'application/json' ); + if ( $github_token = getenv( 'WP_CLI_GITHUB_TOKEN' ) ) { + $headers['Authorization'] = 'token ' . $github_token; + } + $release_data = $cache_data = array(); // Cache results. @@ -367,6 +371,7 @@ private function get_updates( $assoc_args ) { } if ( ! $release_data ) { + // Not cached. $max_age = $time = 0; do { $response = Utils\http_request( 'GET', $url, $headers, $options ); @@ -375,7 +380,7 @@ private function get_updates( $assoc_args ) { if ( 403 === $response->status_code ) { if ( ! empty( $cache_data ) ) { WP_CLI::warning( sprintf( "Failed to get latest version (HTTP code %d) - using stale cache data.", $response->status_code ) ); - $max_age = 0; + $max_age = 0; // Make sure not to write stale data to cache. $release_data = $cache_data['release_data']; break; } @@ -391,6 +396,7 @@ private function get_updates( $assoc_args ) { $time = time(); } } + // Loop while have paged data ("next" link). } while ( ! empty( $response->headers['link'] ) && preg_match( '/<([^>]+)>; rel="next"/', $response->headers['link'], $matches ) && ( $url = $matches[1] ) ); if ( $max_age ) { From 5da5f0d4b61cafb2883021a4c9abf8a0c0d7d7f3 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 5 Jul 2017 15:01:29 +0100 Subject: [PATCH 036/214] Fix 'error_log' setting in eval. Suppress E_NOTICE in invalid-host. Cache custom vendor folder. --- features/bootstrap/FeatureContext.php | 40 ++++++++++++++----------- features/cli.feature | 7 +++-- features/flags.feature | 2 +- features/framework.feature | 8 ++--- features/skip-plugins.feature | 6 ++-- php/WP_CLI/Bootstrap/AutoloaderStep.php | 26 +++++++++------- php/WP_CLI/Bootstrap/RunnerInstance.php | 4 +-- 7 files changed, 51 insertions(+), 42 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 9161617aa3..a8fab0d631 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -137,7 +137,7 @@ public static function afterSuite( SuiteEvent $event ) { uasort( Process::$run_times, function ( $a, $b ) { return $a[0] === $b[0] ? 0 : ( $a[0] < $b[0] ? 1 : -1 ); // Reverse sort. } ); - $top = getenv( 'TRAVIS' ) ? 5 : 20; + $top = getenv( 'TRAVIS' ) ? 10 : 40; $tops = array_slice( Process::$run_times, 0, $top, true ); $log .= "\nTop $top run_times\n" . implode( "\n", array_map( function ( $k, $v, $i ) { return sprintf( '%2d. %6.3f %2d %s', $i + 1, round( $v[0], 3 ), $v[1], $k ); @@ -433,9 +433,10 @@ public function add_line_to_wp_config( &$wp_config_code, $line ) { } public function download_wp( $subdir = '' ) { - $dest_dir = $this->variables['RUN_DIR'] . "/$subdir"; + $dest_dir = $this->variables['RUN_DIR']; if ( $subdir ) { + $dest_dir = $this->variables['RUN_DIR'] . "/$subdir"; mkdir( $dest_dir ); } @@ -459,14 +460,18 @@ public function create_config( $subdir = '', $extra_php = false ) { $params['extra-php'] = $extra_php; } - $config_path = self::$install_dir ? ( self::$install_dir . '/config_' . md5( implode( ':', $params ) . ':subdir=' . $subdir ) ) : ''; + $config_path = ''; + if ( self::$install_dir ) { + $config_path = self::$install_dir . '/config_' . md5( implode( ':', $params ) . ':subdir=' . $subdir ); + $run_dir = '' !== $subdir ? ( $this->variables['RUN_DIR'] . "/$subdir" ) : $this->variables['RUN_DIR']; + } if ( $config_path && file_exists( $config_path ) ) { - copy( $config_path, $this->variables['RUN_DIR'] . "/$subdir/wp-config.php" ); + copy( $config_path, $run_dir . '/wp-config.php' ); } else { $this->proc( 'wp core config', $params, $subdir )->run_check(); if ( $config_path ) { - copy( $this->variables['RUN_DIR'] . "/$subdir/wp-config.php", $config_path); + copy( $run_dir . '/wp-config.php', $config_path ); } } } @@ -495,11 +500,11 @@ public function install_wp( $subdir = '' ) { $install_path = ''; if ( self::$install_dir ) { $install_path = self::$install_dir . '/install_' . md5( implode( ':', $install_args ) . ':subdir=' . $subdir ); - $dest_dir = '' !== $subdir ? ( $this->variables['RUN_DIR'] . "/$subdir" ) : $this->variables['RUN_DIR']; + $run_dir = '' !== $subdir ? ( $this->variables['RUN_DIR'] . "/$subdir" ) : $this->variables['RUN_DIR']; } if ( $install_path && file_exists( $install_path ) ) { - self::$fs->mirror( $install_path, $dest_dir ); + self::$fs->mirror( $install_path, $run_dir ); $cmd = Utils\esc_cmd( '/usr/bin/env mysql --no-defaults -q -s --skip-auto-rehash -u%s -p%s -e%s %s', self::$db_settings['dbuser'], self::$db_settings['dbpass'], "source {$install_path}.sql;", self::$db_settings['dbname'] @@ -509,7 +514,7 @@ public function install_wp( $subdir = '' ) { $this->proc( 'wp core install', $install_args, $subdir )->run_check(); if ( $install_path ) { mkdir( $install_path ); - self::dir_diff_cp( $dest_dir, self::$cache_dir, $install_path ); + self::dir_diff_cp( $run_dir, self::$cache_dir, $install_path ); $cmd = Utils\esc_cmd( '/usr/bin/env mysqldump --no-defaults -u%s -p%s %s > %s', self::$db_settings['dbuser'], self::$db_settings['dbpass'], self::$db_settings['dbname'], $install_path . '.sql' @@ -522,12 +527,12 @@ public function install_wp( $subdir = '' ) { /** * Copy files in new directory that are not in old directory to destination directory. * - * @param string $new_dir The directory to search looking for files/directories not in `$old_dir`. - * @param string $old_dir The directory to be compared to `$new_dir`. - * @param string $dest_dir Where to copy any files/directories in `$new_dir` but not in `$old_dir` to. + * @param string $new_dir The directory to search looking for files/directories not in `$old_dir`. + * @param string $old_dir The directory to be compared to `$new_dir`. + * @param string $cp_dir Where to copy any files/directories in `$new_dir` but not in `$old_dir` to. * @return bool Whether files copied or not. */ - private static function dir_diff_cp( $new_dir, $old_dir, $dest_dir ) { + private static function dir_diff_cp( $new_dir, $old_dir, $cp_dir ) { $copied = false; $fd = opendir( $new_dir ); while ( false !== ( $file = readdir( $fd ) ) ) { @@ -536,7 +541,7 @@ private static function dir_diff_cp( $new_dir, $old_dir, $dest_dir ) { } $new_file = $new_dir . '/' . $file; $old_file = $old_dir . '/' . $file; - $dest_file = $dest_dir . '/' . $file; + $dest_file = $cp_dir . '/' . $file; if ( ! file_exists( $old_file ) ) { if ( is_dir( $new_file ) ) { self::$fs->mirror( $new_file, $dest_file ); @@ -558,14 +563,13 @@ public function install_wp_with_composer() { $this->create_db(); $yml_path = $this->variables['RUN_DIR'] . "/wp-cli.yml"; - Process::create( Utils\esc_cmd( 'mkdir -p %s', dirname( $yml_path ) ) )->run_check(); file_put_contents( $yml_path, 'path: wordpress' ); $this->proc( 'composer init --name="wp-cli/composer-test" --type="project" --no-interaction' )->run_check(); $this->proc( 'composer require johnpbloch/wordpress --optimize-autoloader --no-interaction' )->run_check(); $config_extra_php = "require_once dirname(__DIR__) . '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/vendor/autoload.php';"; - $this->create_config( '', $config_extra_php ); + $this->create_config( 'wordpress', $config_extra_php ); $install_args = array( 'url' => 'http://localhost:8080', @@ -587,9 +591,9 @@ public function composer_add_wp_cli_local_repository() { $dest = $this->variables['COMPOSER_LOCAL_REPOSITORY'] . '/'; - $this->proc( Utils\esc_cmd( "cp -r %s %s", $src, $dest ) )->run_check(); - $this->proc( Utils\esc_cmd( "rm -rf %s", $dest . '/.git' ) )->run_check(); - $this->proc( Utils\esc_cmd( "rm -rf %s", $dest . '/vendor' ) )->run_check(); + self::$fs->mirror( $src, $dest ); + self::$fs->remove( $dest . '/.git' ); + self::$fs->remove( $dest . '/vendor' ); $this->proc( "composer config repositories.wp-cli '{\"type\": \"path\", \"url\": \"$dest\", \"options\": {\"symlink\": false}}'" )->run_check(); } diff --git a/features/cli.feature b/features/cli.feature index 668bdc820e..e9571304c2 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -26,7 +26,7 @@ Feature: `wp cli` tasks """ And STDERR should be empty - # The latest 1.2.1 phar craps out on Travis PHP 5.3 due to double slash in boot-phar.php path. + # The latest 1.2.1 phar fails on Travis PHP 5.3 due to double slash in boot-phar.php path so need >= 5.4 to do cli update @require-php-5.4 Scenario: Do WP-CLI Update Given an empty directory @@ -92,6 +92,7 @@ Feature: `wp cli` tasks WP-CLI 0.14.1 """ + # See above @require-php-5.4 Scenario: Not a patch update from 0.14.0 Given an empty directory @@ -109,6 +110,7 @@ Feature: `wp cli` tasks And STDERR should be empty And the return code should be 0 + # See above @require-php-5.4 Scenario: Install WP-CLI nightly Given an empty directory @@ -127,6 +129,7 @@ Feature: `wp cli` tasks And STDERR should be empty And the return code should be 0 + # See above @require-php-5.4 Scenario: Install WP-CLI stable Given an empty directory @@ -156,7 +159,7 @@ Feature: `wp cli` tasks And STDERR should be empty And the return code should be 0 - # This will hit github rate limiting on Travis. + # This can hit github rate limiting on Travis as the latest 1.2.1 phar doesn't use WP_CLI_GITHUB_TOKEN. #When I run `{PHAR_PATH} cli check-update` #Then STDOUT should be: #""" diff --git a/features/flags.feature b/features/flags.feature index 569abbfbba..f6d3dd9ebd 100644 --- a/features/flags.feature +++ b/features/flags.feature @@ -52,7 +52,7 @@ Feature: Global flags CONST_WITHOUT_QUOTES """ - When I try `wp eval 'ini_set( 'error_log', null ); echo CONST_WITHOUT_QUOTES;' --debug` + When I try `wp eval 'ini_set( "error_log", null ); echo CONST_WITHOUT_QUOTES;' --debug` Then the return code should be 0 And STDOUT should be: """ diff --git a/features/framework.feature b/features/framework.feature index 26b6533719..5ea6a984ff 100644 --- a/features/framework.feature +++ b/features/framework.feature @@ -181,14 +181,10 @@ Feature: Load WP-CLI Scenario: Handle error when WordPress cannot connect to the database host Given a WP install - And a wp-debug.php file: - """ - config ) + && ! empty( $composer->config->{'vendor-dir'} ) + ) { + return $result = $composer->config->{'vendor-dir'}; + } - if ( ! empty( $composer->config ) - && ! empty( $composer->config->{'vendor-dir'} ) - ) { - return $composer->config->{'vendor-dir'}; + return $result = false; } - return false; + return $result; } /** diff --git a/php/WP_CLI/Bootstrap/RunnerInstance.php b/php/WP_CLI/Bootstrap/RunnerInstance.php index dceddb99b1..e2736ddc06 100644 --- a/php/WP_CLI/Bootstrap/RunnerInstance.php +++ b/php/WP_CLI/Bootstrap/RunnerInstance.php @@ -20,11 +20,11 @@ final class RunnerInstance { */ public function __invoke() { if ( ! class_exists( 'WP_CLI\Runner' ) ) { - require_once WP_CLI_ROOT . '/php/WP_CLI/Runner.php'; + require WP_CLI_ROOT . '/php/WP_CLI/Runner.php'; } if ( ! class_exists( 'WP_CLI\Configurator' ) ) { - require_once WP_CLI_ROOT . '/php/WP_CLI/Configurator.php'; + require WP_CLI_ROOT . '/php/WP_CLI/Configurator.php'; } return \WP_CLI::get_runner(); From 7d5351f8847db21333cd0a0f97515ac64ffd9365 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 5 Jul 2017 22:28:33 +0100 Subject: [PATCH 037/214] Fix http_request args. --- php/commands/src/CLI_Command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index 8c740fa8d9..e05bb0965c 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -374,7 +374,7 @@ private function get_updates( $assoc_args ) { // Not cached. $max_age = $time = 0; do { - $response = Utils\http_request( 'GET', $url, $headers, $options ); + $response = Utils\http_request( 'GET', $url, null, $headers, $options ); if ( ! $response->success || 200 !== $response->status_code ) { if ( 403 === $response->status_code ) { From 835eeae3504e5d4188386763e7454a50f953157e Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 5 Jul 2017 23:18:58 +0100 Subject: [PATCH 038/214] Add debug to see if actually using WP_CLI_GITHUB_TOKEN. --- php/commands/src/CLI_Command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index e05bb0965c..c5a39147e4 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -385,7 +385,7 @@ private function get_updates( $assoc_args ) { break; } } - WP_CLI::error( sprintf( "Failed to get latest version (HTTP code %d).", $response->status_code ) ); + WP_CLI::error( sprintf( "Failed to get latest version (HTTP code %d) (%susing WP_CLI_GITHUB_TOKEN).", $response->status_code, $github_token ? '' : ' NOT' ) ); } $release_data = array_merge( $release_data, json_decode( $response->body ) ); From 3f70a579879b4ac68c3e8acf6fc271029f33d3c7 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 5 Jul 2017 23:29:48 +0100 Subject: [PATCH 039/214] Put secure: in global in .travis.yml. --- .travis.yml | 3 +-- php/commands/src/CLI_Command.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3fadddac3c..0f5b7f8381 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,8 +5,7 @@ language: php env: global: - WP_CLI_BIN_DIR=/tmp/wp-cli-phar - matrix: - secure: AT4gaEJlw3atKF7Q40wxdVGrHMLj5GhYy3RNrSF3XiHoW2iQKKG/kmnArGd8x6YtHjjXfE/7Gvb+9hKfIDM15Rn75rBJWHRI0M+Y1+0kbZLWhrkkgx6zBRvbqFZO0maBYCOW1ov5FIQe6YSKfy/I+IUuNwdL4XMv6JqduyCxVN/+oxvF2zX5pP4ontXwze36GxGIebzj4dFgMXf2ra4z7HDcoYLCinymp7z1M8wgB9QioQfdkdQ6Oq8mQUX4eOE3uQKvsGDR3eVe74aL3l49Rrwarz0bkeOWrKwX8ljQNOc2CZv/vAF1bkj0si7V6DeZ1EL/hhCO5YVLFnK+cCV2V9nkKOJ0KG6KVrjQE5fr4Iw1wXSPgsjI5ta79e4jN2KwBzPADMlE1lK7Br6F9l5T+n2d85YL4im2x5ynCOAsMIsuJI8WJz9Ml2l+v6OUg765RhmvYMuGPom9TwJwl4MRHX3i6d2/C+1yoONXa3N582vyLuPAxaoS49DfnTKrBVsLsyuV4mpoZVYy40i5HJ1e2xL9PLmJFlj5qihWRXHylm5zp01+Zydrk+3lUc4HhvZG/pnxu0v1wUzf5d4JKrJfZY1srh+Xh6Z2wPgDnCYvs+XlQOWOJAElwjj/zlU42361GFQoeJpjCFoAK1505CTcmXpx3Nj2LjTriO6ms1sTK5c= + - secure: AT4gaEJlw3atKF7Q40wxdVGrHMLj5GhYy3RNrSF3XiHoW2iQKKG/kmnArGd8x6YtHjjXfE/7Gvb+9hKfIDM15Rn75rBJWHRI0M+Y1+0kbZLWhrkkgx6zBRvbqFZO0maBYCOW1ov5FIQe6YSKfy/I+IUuNwdL4XMv6JqduyCxVN/+oxvF2zX5pP4ontXwze36GxGIebzj4dFgMXf2ra4z7HDcoYLCinymp7z1M8wgB9QioQfdkdQ6Oq8mQUX4eOE3uQKvsGDR3eVe74aL3l49Rrwarz0bkeOWrKwX8ljQNOc2CZv/vAF1bkj0si7V6DeZ1EL/hhCO5YVLFnK+cCV2V9nkKOJ0KG6KVrjQE5fr4Iw1wXSPgsjI5ta79e4jN2KwBzPADMlE1lK7Br6F9l5T+n2d85YL4im2x5ynCOAsMIsuJI8WJz9Ml2l+v6OUg765RhmvYMuGPom9TwJwl4MRHX3i6d2/C+1yoONXa3N582vyLuPAxaoS49DfnTKrBVsLsyuV4mpoZVYy40i5HJ1e2xL9PLmJFlj5qihWRXHylm5zp01+Zydrk+3lUc4HhvZG/pnxu0v1wUzf5d4JKrJfZY1srh+Xh6Z2wPgDnCYvs+XlQOWOJAElwjj/zlU42361GFQoeJpjCFoAK1505CTcmXpx3Nj2LjTriO6ms1sTK5c= matrix: include: diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index c5a39147e4..6d93cc83e6 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -385,7 +385,7 @@ private function get_updates( $assoc_args ) { break; } } - WP_CLI::error( sprintf( "Failed to get latest version (HTTP code %d) (%susing WP_CLI_GITHUB_TOKEN).", $response->status_code, $github_token ? '' : ' NOT' ) ); + WP_CLI::error( sprintf( "Failed to get latest version (HTTP code %d) (%susing WP_CLI_GITHUB_TOKEN).", $response->status_code, $github_token ? '' : 'NOT ' ) ); } $release_data = array_merge( $release_data, json_decode( $response->body ) ); From 7f57fd2d7d20691568539e06e71cb8cd7f347010 Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 6 Jul 2017 00:04:44 +0100 Subject: [PATCH 040/214] Dummy comment change. --- features/cli.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/cli.feature b/features/cli.feature index e9571304c2..faa1b22b25 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -26,7 +26,7 @@ Feature: `wp cli` tasks """ And STDERR should be empty - # The latest 1.2.1 phar fails on Travis PHP 5.3 due to double slash in boot-phar.php path so need >= 5.4 to do cli update + # The latest 1.2.1 phar fails on Travis PHP 5.3 due to double slash in boot-phar.php path so need >= 5.4 to do cli update. @require-php-5.4 Scenario: Do WP-CLI Update Given an empty directory From 05e44a006e8ef824c03ec290086394217fa6f770 Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 6 Jul 2017 00:05:33 +0100 Subject: [PATCH 041/214] Dummy comment unchange. --- features/cli.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/cli.feature b/features/cli.feature index faa1b22b25..e9571304c2 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -26,7 +26,7 @@ Feature: `wp cli` tasks """ And STDERR should be empty - # The latest 1.2.1 phar fails on Travis PHP 5.3 due to double slash in boot-phar.php path so need >= 5.4 to do cli update. + # The latest 1.2.1 phar fails on Travis PHP 5.3 due to double slash in boot-phar.php path so need >= 5.4 to do cli update @require-php-5.4 Scenario: Do WP-CLI Update Given an empty directory From c911f6805ead25be5f3ad83fa3e3db0a50bab39b Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 6 Jul 2017 00:24:17 +0100 Subject: [PATCH 042/214] Export WP_CLI_GITHUB_TOKEN in get_process_env_variables(). --- features/bootstrap/FeatureContext.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index a8fab0d631..659ed7ab14 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -85,6 +85,9 @@ private static function get_process_env_variables() { if ( $travis_build_dir = getenv( 'TRAVIS_BUILD_DIR' ) ) { $env['TRAVIS_BUILD_DIR'] = $travis_build_dir; } + if ( $github_token = getenv( 'WP_CLI_GITHUB_TOKEN' ) ) { + $env['WP_CLI_GITHUB_TOKEN'] = $github_token; + } return $env; } From 6417127f74fb7dc9bb1e3faf1fc6ba0619a31b98 Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 7 Jul 2017 06:35:52 +0100 Subject: [PATCH 043/214] Optimize cli update default. WP_CLI_GITHUB_TOKEN -> GITHUB_TOKEN. Add travis-github-token tag. Scenario run times. --- ci/behat-tags.php | 6 +++++- ci/test.sh | 2 +- features/bootstrap/FeatureContext.php | 29 ++++++++++++++++++++++----- features/cli.feature | 12 ++++++----- php/WP_CLI/Process.php | 2 +- php/commands/src/CLI_Command.php | 23 ++++++++++++++------- 6 files changed, 54 insertions(+), 20 deletions(-) diff --git a/ci/behat-tags.php b/ci/behat-tags.php index ee51fc91ee..afbec1c3b9 100644 --- a/ci/behat-tags.php +++ b/ci/behat-tags.php @@ -45,7 +45,11 @@ function version_tags( $prefix, $current, $operator = '<' ) { ); # Skip Github API tests by default because of rate limiting. See https://github.com/wp-cli/wp-cli/issues/1612 -$skip_tags[] = '@github-api'; +$skip_tags[] = '@github-api'; // Deprecated. +# Skip Github API tests that require GITHUB_TOKEN if on Travis and it's not available. +if ( getenv( 'TRAVIS' ) && ! getenv( 'GITHUB_TOKEN' ) ) { + $skip_tags[] = '@travis-github-token'; +} # Skip tests known to be broken. $skip_tags[] = '@broken'; diff --git a/ci/test.sh b/ci/test.sh index 2c32f1b934..7125e1e2c6 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -11,4 +11,4 @@ vendor/bin/phpunit BEHAT_TAGS=$(php ci/behat-tags.php) # Run the functional tests -WP_CLI_TEST_PROCESS_RUN_TIMES=1 vendor/bin/behat --format progress $BEHAT_TAGS --strict +WP_CLI_TEST_LOG_RUN_TIMES=1 vendor/bin/behat --format progress $BEHAT_TAGS --strict diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 659ed7ab14..b3eb851310 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -49,6 +49,8 @@ class FeatureContext extends BehatContext implements ClosuredContextInterface { private static $cache_dir, $suite_cache_dir, $install_dir, $fs; + private static $scenario_run_times = array(); + private static $db_settings = array( 'dbname' => 'wp_cli_test', 'dbuser' => 'wp_cli_test', @@ -85,8 +87,8 @@ private static function get_process_env_variables() { if ( $travis_build_dir = getenv( 'TRAVIS_BUILD_DIR' ) ) { $env['TRAVIS_BUILD_DIR'] = $travis_build_dir; } - if ( $github_token = getenv( 'WP_CLI_GITHUB_TOKEN' ) ) { - $env['WP_CLI_GITHUB_TOKEN'] = $github_token; + if ( $github_token = getenv( 'GITHUB_TOKEN' ) ) { + $env['GITHUB_TOKEN'] = $github_token; } return $env; } @@ -128,24 +130,31 @@ public static function afterSuite( SuiteEvent $event ) { self::$fs->remove( self::$suite_cache_dir ); } - if ( getenv( 'WP_CLI_TEST_PROCESS_RUN_TIMES' ) ) { + if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) ) { list( $time, $calls ) = array_reduce( Process::$run_times, function ( $carry, $item ) { return array( $carry[0] + $item[0], $carry[1] + $item[1] ); }, array( 0, 0 ) ); $mins = floor( $time / 60 ); $secs = round( $time - ( $mins * 60 ), 3 ); - $log = "\nTotal run time=" . round( $time, 3 ) . " ({$mins}m{$secs}s), calls=$calls, unique=" . count( Process::$run_times ); + $log = "\n\nTotal process run time=" . round( $time, 3 ) . " ({$mins}m{$secs}s), calls=$calls, unique=" . count( Process::$run_times ); uasort( Process::$run_times, function ( $a, $b ) { return $a[0] === $b[0] ? 0 : ( $a[0] < $b[0] ? 1 : -1 ); // Reverse sort. } ); $top = getenv( 'TRAVIS' ) ? 10 : 40; $tops = array_slice( Process::$run_times, 0, $top, true ); - $log .= "\nTop $top run_times\n" . implode( "\n", array_map( function ( $k, $v, $i ) { + $log .= "\n\nTop $top process run_times\n" . implode( "\n", array_map( function ( $k, $v, $i ) { return sprintf( '%2d. %6.3f %2d %s', $i + 1, round( $v[0], 3 ), $v[1], $k ); }, array_keys( $tops ), $tops, array_keys( array_keys( $tops ) ) ) ); + arsort( self::$scenario_run_times ); + $top = getenv( 'TRAVIS' ) ? 10 : 20; + $tops = array_slice( self::$scenario_run_times, 0, $top, true ); + $log .= "\n\nTop $top scenario run_times\n" . implode( "\n", array_map( function ( $k, $v, $i ) { + return sprintf( '%2d. %6.3f %s', $i + 1, round( $v, 3 ), $k ); + }, array_keys( $tops ), $tops, array_keys( array_keys( $tops ) ) ) ); + if ( getenv( 'TRAVIS' ) ) { echo $log; } else { @@ -158,6 +167,11 @@ public static function afterSuite( SuiteEvent $event ) { * @BeforeScenario */ public function beforeScenario( $event ) { + if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) && method_exists( $event, 'getScenario' ) ) { + $scenario = $event->getScenario(); + self::$scenario_run_times[ basename( $scenario->getFile() ) . ':' . $scenario->getLine() ] = -microtime( true ); + } + $this->variables['SRC_DIR'] = realpath( __DIR__ . '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/../..' ); } @@ -181,6 +195,11 @@ public function afterScenario( $event ) { $status = proc_get_status( $proc ); self::terminate_proc( $status['pid'] ); } + + if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) && method_exists( $event, 'getScenario' ) ) { + $scenario = $event->getScenario(); + self::$scenario_run_times[ basename( $scenario->getFile() ) . ':' . $scenario->getLine() ] += microtime( true ); + } } /** diff --git a/features/cli.feature b/features/cli.feature index e9571304c2..5c1bb3b2ab 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -15,6 +15,7 @@ Feature: `wp cli` tasks {TRUE_VERSION} """ + @travis-github-token Scenario: Check for updates Given an empty directory And a new Phar with version "0.0.0" and cli build @@ -27,7 +28,7 @@ Feature: `wp cli` tasks And STDERR should be empty # The latest 1.2.1 phar fails on Travis PHP 5.3 due to double slash in boot-phar.php path so need >= 5.4 to do cli update - @require-php-5.4 + @travis-github-token @require-php-5.4 Scenario: Do WP-CLI Update Given an empty directory And a new Phar with version "0.0.0" and cli build @@ -64,6 +65,7 @@ Feature: `wp cli` tasks 0.0.0 """ + @travis-github-token Scenario: Patch update from 0.14.0 to 0.14.1 Given an empty directory And a new Phar with version "0.14.0" and cli build @@ -93,7 +95,7 @@ Feature: `wp cli` tasks """ # See above - @require-php-5.4 + @travis-github-token @require-php-5.4 Scenario: Not a patch update from 0.14.0 Given an empty directory And a new Phar with version "0.14.0" and cli build @@ -111,7 +113,7 @@ Feature: `wp cli` tasks And the return code should be 0 # See above - @require-php-5.4 + @travis-github-token @require-php-5.4 Scenario: Install WP-CLI nightly Given an empty directory And a new Phar with version "0.14.0" and cli build @@ -130,7 +132,7 @@ Feature: `wp cli` tasks And the return code should be 0 # See above - @require-php-5.4 + @travis-github-token @require-php-5.4 Scenario: Install WP-CLI stable Given an empty directory And a new Phar with version "0.14.0" and cli build @@ -159,7 +161,7 @@ Feature: `wp cli` tasks And STDERR should be empty And the return code should be 0 - # This can hit github rate limiting on Travis as the latest 1.2.1 phar doesn't use WP_CLI_GITHUB_TOKEN. + # This can hit github rate limiting on Travis as the latest 1.2.1 phar doesn't use GITHUB_TOKEN. #When I run `{PHAR_PATH} cli check-update` #Then STDOUT should be: #""" diff --git a/php/WP_CLI/Process.php b/php/WP_CLI/Process.php index 4cf4a8e11c..01cf1bca37 100644 --- a/php/WP_CLI/Process.php +++ b/php/WP_CLI/Process.php @@ -68,7 +68,7 @@ public function run() { $run_time = microtime( true ) - $start_time; - if ( getenv( 'WP_CLI_TEST_PROCESS_RUN_TIMES' ) ) { + if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) ) { if ( ! isset( self::$run_times[ $this->command ] ) ) { self::$run_times[ $this->command ] = array( 0, 0 ); } diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index 6d93cc83e6..958241fc4d 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -255,11 +255,19 @@ public function update( $_, $assoc_args ) { WP_CLI::error( sprintf( "%s is not writable by current user.", dirname( $old_phar ) ) ); } - if ( Utils\get_flag_value( $assoc_args, 'nightly' ) ) { + $nightly = Utils\get_flag_value( $assoc_args, 'nightly' ); + $stable = Utils\get_flag_value( $assoc_args, 'stable' ); + + // If no version options given, default to stable. + if ( ! $nightly && ! $stable && ! Utils\get_flag_value( $assoc_args, 'patch' ) && ! Utils\get_flag_value( $assoc_args, 'minor' ) && ! Utils\get_flag_value( $assoc_args, 'major' ) ) { + $stable = true; + } + + if ( $nightly ) { WP_CLI::confirm( sprintf( 'You have version %s. Would you like to update to the latest nightly?', WP_CLI_VERSION ), $assoc_args ); $download_url = 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli-nightly.phar'; $md5_url = 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli-nightly.phar.md5'; - } else if ( Utils\get_flag_value( $assoc_args, 'stable' ) ) { + } elseif ( $stable ) { WP_CLI::confirm( sprintf( 'You have version %s. Would you like to update to the latest stable release?', WP_CLI_VERSION ), $assoc_args ); $download_url = 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar'; $md5_url = 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar.md5'; @@ -329,9 +337,9 @@ class_exists( '\cli\Colors' ); // This autoloads \cli\Colors - after we move the WP_CLI::error( sprintf( "Cannot move %s to %s", $temp, $old_phar ) ); } - if ( Utils\get_flag_value( $assoc_args, 'nightly' ) ) { + if ( $nightly ) { $updated_version = 'the latest nightly release'; - } else if ( Utils\get_flag_value( $assoc_args, 'stable' ) ) { + } elseif ( $stable ) { $updated_version = 'the latest stable release'; } else { $updated_version = $newest['version']; @@ -353,7 +361,7 @@ private function get_updates( $assoc_args ) { 'Accept' => 'application/json' ); - if ( $github_token = getenv( 'WP_CLI_GITHUB_TOKEN' ) ) { + if ( $github_token = getenv( 'GITHUB_TOKEN' ) ) { $headers['Authorization'] = 'token ' . $github_token; } @@ -377,15 +385,16 @@ private function get_updates( $assoc_args ) { $response = Utils\http_request( 'GET', $url, null, $headers, $options ); if ( ! $response->success || 200 !== $response->status_code ) { + $msg = sprintf( 'Failed to get latest version (HTTP code %d) (%susing GITHUB_TOKEN).', $response->status_code, $github_token ? '' : 'NOT ' ); if ( 403 === $response->status_code ) { if ( ! empty( $cache_data ) ) { - WP_CLI::warning( sprintf( "Failed to get latest version (HTTP code %d) - using stale cache data.", $response->status_code ) ); + WP_CLI::warning( $msg . ' - using stale cache data.' ); $max_age = 0; // Make sure not to write stale data to cache. $release_data = $cache_data['release_data']; break; } } - WP_CLI::error( sprintf( "Failed to get latest version (HTTP code %d) (%susing WP_CLI_GITHUB_TOKEN).", $response->status_code, $github_token ? '' : 'NOT ' ) ); + WP_CLI::error( $msg ); } $release_data = array_merge( $release_data, json_decode( $response->body ) ); From 328a59ec7465a81380d1ba5b240f2d1895c7e316 Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 7 Jul 2017 06:56:54 +0100 Subject: [PATCH 044/214] Put GITHUB_TOKEN into travis-ci.org gitlost/wp-cli settings env vars. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0f5b7f8381..e3c0571b72 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,6 @@ language: php env: global: - WP_CLI_BIN_DIR=/tmp/wp-cli-phar - - secure: AT4gaEJlw3atKF7Q40wxdVGrHMLj5GhYy3RNrSF3XiHoW2iQKKG/kmnArGd8x6YtHjjXfE/7Gvb+9hKfIDM15Rn75rBJWHRI0M+Y1+0kbZLWhrkkgx6zBRvbqFZO0maBYCOW1ov5FIQe6YSKfy/I+IUuNwdL4XMv6JqduyCxVN/+oxvF2zX5pP4ontXwze36GxGIebzj4dFgMXf2ra4z7HDcoYLCinymp7z1M8wgB9QioQfdkdQ6Oq8mQUX4eOE3uQKvsGDR3eVe74aL3l49Rrwarz0bkeOWrKwX8ljQNOc2CZv/vAF1bkj0si7V6DeZ1EL/hhCO5YVLFnK+cCV2V9nkKOJ0KG6KVrjQE5fr4Iw1wXSPgsjI5ta79e4jN2KwBzPADMlE1lK7Br6F9l5T+n2d85YL4im2x5ynCOAsMIsuJI8WJz9Ml2l+v6OUg765RhmvYMuGPom9TwJwl4MRHX3i6d2/C+1yoONXa3N582vyLuPAxaoS49DfnTKrBVsLsyuV4mpoZVYy40i5HJ1e2xL9PLmJFlj5qihWRXHylm5zp01+Zydrk+3lUc4HhvZG/pnxu0v1wUzf5d4JKrJfZY1srh+Xh6Z2wPgDnCYvs+XlQOWOJAElwjj/zlU42361GFQoeJpjCFoAK1505CTcmXpx3Nj2LjTriO6ms1sTK5c= matrix: include: From bd6885950e22773773920f8f5e3f098af1817b37 Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 7 Jul 2017 08:04:10 +0100 Subject: [PATCH 045/214] Try hirak/prestissimo. --- ci/prepare.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci/prepare.sh b/ci/prepare.sh index 8b6de760b6..86cd471dd3 100755 --- a/ci/prepare.sh +++ b/ci/prepare.sh @@ -9,6 +9,8 @@ WP_CLI_BIN_DIR=${WP_CLI_BIN_DIR-/tmp/wp-cli-phar} # Disable XDebug to speed up Composer and test suites. phpenv config-rm xdebug.ini +composer global require hirak/prestissimo + composer install --no-interaction --prefer-source CLI_VERSION=$(head -n 1 VERSION) From eb0a1e7cefec8c772794cf71d78580cbeefa6b16 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 8 Jul 2017 00:45:01 +0100 Subject: [PATCH 046/214] Try caching classic & default themes. --- features/bootstrap/FeatureContext.php | 102 +++++++++++++------------- features/skip-themes.feature | 16 +++- php/commands/src/CLI_Command.php | 14 +++- 3 files changed, 74 insertions(+), 58 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index b3eb851310..875b14e8ed 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -47,7 +47,7 @@ */ class FeatureContext extends BehatContext implements ClosuredContextInterface { - private static $cache_dir, $suite_cache_dir, $install_dir, $fs; + private static $cache_dir, $suite_cache_dir, $install_cache_dir, $fs; private static $scenario_run_times = array(); @@ -144,14 +144,14 @@ public static function afterSuite( SuiteEvent $event ) { } ); $top = getenv( 'TRAVIS' ) ? 10 : 40; $tops = array_slice( Process::$run_times, 0, $top, true ); - $log .= "\n\nTop $top process run_times\n" . implode( "\n", array_map( function ( $k, $v, $i ) { + $log .= "\n\nTop $top process run times\n" . implode( "\n", array_map( function ( $k, $v, $i ) { return sprintf( '%2d. %6.3f %2d %s', $i + 1, round( $v[0], 3 ), $v[1], $k ); }, array_keys( $tops ), $tops, array_keys( array_keys( $tops ) ) ) ); arsort( self::$scenario_run_times ); $top = getenv( 'TRAVIS' ) ? 10 : 20; $tops = array_slice( self::$scenario_run_times, 0, $top, true ); - $log .= "\n\nTop $top scenario run_times\n" . implode( "\n", array_map( function ( $k, $v, $i ) { + $log .= "\n\nTop $top scenario run times\n" . implode( "\n", array_map( function ( $k, $v, $i ) { return sprintf( '%2d. %6.3f %s', $i + 1, round( $v, 3 ), $k ); }, array_keys( $tops ), $tops, array_keys( array_keys( $tops ) ) ) ); @@ -199,6 +199,11 @@ public function afterScenario( $event ) { if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) && method_exists( $event, 'getScenario' ) ) { $scenario = $event->getScenario(); self::$scenario_run_times[ basename( $scenario->getFile() ) . ':' . $scenario->getLine() ] += microtime( true ); + $top = getenv( 'TRAVIS' ) ? 10 : 20; + if ( count( self::$scenario_run_times ) > $top ) { + arsort( self::$scenario_run_times ); + self::$scenario_run_times = array_slice( self::$scenario_run_times, 0, $top, true ); + } } } @@ -417,7 +422,7 @@ public function proc( $command, $assoc_args = array(), $path = '' ) { /** * Start a background process. Will automatically be closed when the tests finish. */ - public function background_proc( $cmd ) { + public function background_proc( $cmd, $sleep = 1 ) { $descriptors = array( 0 => STDIN, 1 => array( 'pipe', 'w' ), @@ -426,15 +431,15 @@ public function background_proc( $cmd ) { $proc = proc_open( $cmd, $descriptors, $pipes, $this->variables['RUN_DIR'], self::get_process_env_variables() ); - sleep(1); - - $status = proc_get_status( $proc ); - - if ( !$status['running'] ) { + if ( false === $proc ) { throw new RuntimeException( stream_get_contents( $pipes[2] ) ); } else { $this->running_procs[] = $proc; } + + if ( $sleep ) { + sleep( $sleep ); + } } public function move_files( $src, $dest ) { @@ -482,26 +487,26 @@ public function create_config( $subdir = '', $extra_php = false ) { $params['extra-php'] = $extra_php; } - $config_path = ''; - if ( self::$install_dir ) { - $config_path = self::$install_dir . '/config_' . md5( implode( ':', $params ) . ':subdir=' . $subdir ); + $config_cache_path = ''; + if ( self::$install_cache_dir ) { + $config_cache_path = self::$install_cache_dir . '/config_' . md5( implode( ':', $params ) . ':subdir=' . $subdir ); $run_dir = '' !== $subdir ? ( $this->variables['RUN_DIR'] . "/$subdir" ) : $this->variables['RUN_DIR']; } - if ( $config_path && file_exists( $config_path ) ) { - copy( $config_path, $run_dir . '/wp-config.php' ); + if ( $config_cache_path && file_exists( $config_cache_path ) ) { + copy( $config_cache_path, $run_dir . '/wp-config.php' ); } else { $this->proc( 'wp core config', $params, $subdir )->run_check(); - if ( $config_path ) { - copy( $run_dir . '/wp-config.php', $config_path ); + if ( $config_cache_path && file_exists( $run_dir . '/wp-config.php' ) ) { + copy( $run_dir . '/wp-config.php', $config_cache_path ); } } } public function install_wp( $subdir = '' ) { - self::$install_dir = sys_get_temp_dir() . '/wp-cli-test-core-install-cache'; - if ( ! file_exists( self::$install_dir ) ) { - mkdir( self::$install_dir ); + self::$install_cache_dir = sys_get_temp_dir() . '/wp-cli-test-core-install-cache'; + if ( ! file_exists( self::$install_cache_dir ) ) { + mkdir( self::$install_cache_dir ); } $subdir = $this->replace_variables( $subdir ); @@ -519,27 +524,27 @@ public function install_wp( $subdir = '' ) { 'admin_password' => 'password1' ); - $install_path = ''; - if ( self::$install_dir ) { - $install_path = self::$install_dir . '/install_' . md5( implode( ':', $install_args ) . ':subdir=' . $subdir ); + $install_cache_path = ''; + if ( self::$install_cache_dir ) { + $install_cache_path = self::$install_cache_dir . '/install_' . md5( implode( ':', $install_args ) . ':subdir=' . $subdir ); $run_dir = '' !== $subdir ? ( $this->variables['RUN_DIR'] . "/$subdir" ) : $this->variables['RUN_DIR']; } - if ( $install_path && file_exists( $install_path ) ) { - self::$fs->mirror( $install_path, $run_dir ); + if ( $install_cache_path && file_exists( $install_cache_path ) ) { + self::$fs->mirror( $install_cache_path, $run_dir ); $cmd = Utils\esc_cmd( - '/usr/bin/env mysql --no-defaults -q -s --skip-auto-rehash -u%s -p%s -e%s %s', - self::$db_settings['dbuser'], self::$db_settings['dbpass'], "source {$install_path}.sql;", self::$db_settings['dbname'] + '/usr/bin/env mysql --no-defaults -q -s -u%s -p%s -e%s %s', + self::$db_settings['dbuser'], self::$db_settings['dbpass'], "source {$install_cache_path}.sql;", self::$db_settings['dbname'] ); Process::create( $cmd, null, self::get_process_env_variables() )->run_check(); } else { $this->proc( 'wp core install', $install_args, $subdir )->run_check(); - if ( $install_path ) { - mkdir( $install_path ); - self::dir_diff_cp( $run_dir, self::$cache_dir, $install_path ); + if ( $install_cache_path ) { + mkdir( $install_cache_path ); + self::dir_diff_cp( $run_dir, self::$cache_dir, $install_cache_path ); $cmd = Utils\esc_cmd( '/usr/bin/env mysqldump --no-defaults -u%s -p%s %s > %s', - self::$db_settings['dbuser'], self::$db_settings['dbpass'], self::$db_settings['dbname'], $install_path . '.sql' + self::$db_settings['dbuser'], self::$db_settings['dbpass'], self::$db_settings['dbname'], $install_cache_path . '.sql' ); Process::create( $cmd, null, self::get_process_env_variables() )->run_check(); } @@ -547,37 +552,34 @@ public function install_wp( $subdir = '' ) { } /** - * Copy files in new directory that are not in old directory to destination directory. + * Copy files in updated directory that are not in source directory to copy directory. ("Incremental backup".) * - * @param string $new_dir The directory to search looking for files/directories not in `$old_dir`. - * @param string $old_dir The directory to be compared to `$new_dir`. - * @param string $cp_dir Where to copy any files/directories in `$new_dir` but not in `$old_dir` to. - * @return bool Whether files copied or not. + * @param string $upd_dir The directory to search looking for files/directories not in `$src_dir`. + * @param string $src_dir The directory to be compared to `$upd_dir`. + * @param string $cop_dir Where to copy any files/directories in `$upd_dir` but not in `$src_dir` to. */ - private static function dir_diff_cp( $new_dir, $old_dir, $cp_dir ) { - $copied = false; - $fd = opendir( $new_dir ); + private static function dir_diff_cp( $upd_dir, $src_dir, $cop_dir ) { + if ( false === ( $fd = opendir( $upd_dir ) ) ) { + throw new RuntimeException( $upd_dir ); + } while ( false !== ( $file = readdir( $fd ) ) ) { if ( '.' === $file || '..' === $file ) { continue; } - $new_file = $new_dir . '/' . $file; - $old_file = $old_dir . '/' . $file; - $dest_file = $cp_dir . '/' . $file; - if ( ! file_exists( $old_file ) ) { - if ( is_dir( $new_file ) ) { - self::$fs->mirror( $new_file, $dest_file ); - $copied = true; + $upd_file = $upd_dir . '/' . $file; + $src_file = $src_dir . '/' . $file; + $cop_file = $cop_dir . '/' . $file; + if ( ! file_exists( $src_file ) ) { + if ( is_dir( $upd_file ) ) { + self::$fs->mirror( $upd_file, $cop_file ); } else { - copy( $new_file, $dest_file ); - $copied = true; + copy( $upd_file, $cop_file ); } - } elseif ( is_dir( $new_file ) && self::dir_diff_cp( $new_file, $old_file, $dest_file ) ) { - $copied = true; + } elseif ( is_dir( $upd_file ) ) { + self::dir_diff_cp( $upd_file, $src_file, $cop_file ); } } closedir( $fd ); - return $copied; } public function install_wp_with_composer() { diff --git a/features/skip-themes.feature b/features/skip-themes.feature index 7a710c719b..f783faed7d 100644 --- a/features/skip-themes.feature +++ b/features/skip-themes.feature @@ -2,8 +2,12 @@ Feature: Skipping themes Scenario: Skipping themes via global flag Given a WP install - And I run `wp theme install classic` - And I run `wp theme install default --activate` + And download: + | path | url | + | {CACHE_DIR}/classic.zip | https://downloads.wordpress.org/theme/classic.1.6.zip | + | {CACHE_DIR}/default.zip | https://downloads.wordpress.org/theme/default.1.7.2.zip | + And I run `wp theme install {CACHE_DIR}/classic.zip` + And I run `wp theme install {CACHE_DIR}/default.zip --activate` When I run `wp eval 'var_export( function_exists( "kubrick_head" ) );'` Then STDOUT should be: @@ -116,14 +120,18 @@ Feature: Skipping themes Scenario: Skipping multiple themes via config file Given a WP install + And download: + | path | url | + | {CACHE_DIR}/classic.zip | https://downloads.wordpress.org/theme/classic.1.6.zip | + | {CACHE_DIR}/default.zip | https://downloads.wordpress.org/theme/default.1.7.2.zip | And a wp-cli.yml file: """ skip-themes: - classic - default """ - And I run `wp theme install classic --activate` - And I run `wp theme install default` + And I run `wp theme install {CACHE_DIR}/classic.zip --activate` + And I run `wp theme install {CACHE_DIR}/default.zip` # The classic theme should show up as an active theme When I run `wp theme status` diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index 958241fc4d..278f2cc922 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -365,7 +365,8 @@ private function get_updates( $assoc_args ) { $headers['Authorization'] = 'token ' . $github_token; } - $release_data = $cache_data = array(); + $release_data = array(); + $cache_data = null; // Cache results. $cache = WP_CLI::get_cache(); @@ -373,8 +374,13 @@ private function get_updates( $assoc_args ) { if ( $cache->has( $cache_key ) ) { $cache_data = unserialize( $cache->read( $cache_key ) ); - if ( time() <= $cache_data['time'] + $cache_data['max_age'] ) { - $release_data = $cache_data['release_data']; + if ( $cache_data && isset( $cache_data['time'] ) && is_int( $cache_data['time'] ) && isset( $cache_data['max_age'] ) && is_int( $cache_data['max_age'] ) + && isset( $cache_data['release_data'] ) && is_array( $cache_data['release_data'] ) && count( $cache_data['release_data'] ) ) { + if ( time() <= $cache_data['time'] + $cache_data['max_age'] ) { + $release_data = $cache_data['release_data']; + } + } else { + $cache_data = null; } } @@ -387,7 +393,7 @@ private function get_updates( $assoc_args ) { if ( ! $response->success || 200 !== $response->status_code ) { $msg = sprintf( 'Failed to get latest version (HTTP code %d) (%susing GITHUB_TOKEN).', $response->status_code, $github_token ? '' : 'NOT ' ); if ( 403 === $response->status_code ) { - if ( ! empty( $cache_data ) ) { + if ( $cache_data ) { WP_CLI::warning( $msg . ' - using stale cache data.' ); $max_age = 0; // Make sure not to write stale data to cache. $release_data = $cache_data['release_data']; From 6c6d7daa2ba4e219a8f84945b5f2ff0621190fd2 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 8 Jul 2017 01:42:29 +0100 Subject: [PATCH 047/214] Try prefer-dist. --- .travis.yml | 2 +- ci/prepare.sh | 2 +- ci/test.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index e3c0571b72..cab29cb0b4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ env: matrix: include: - php: 7.1 - env: WP_VERSION=latest + env: WP_VERSION=latest WP_CLI_TEST_LOG_RUN_TIMES=1 - php: 7.0 env: WP_VERSION=latest - php: 5.6 diff --git a/ci/prepare.sh b/ci/prepare.sh index 86cd471dd3..6cd3900c98 100755 --- a/ci/prepare.sh +++ b/ci/prepare.sh @@ -11,7 +11,7 @@ phpenv config-rm xdebug.ini composer global require hirak/prestissimo -composer install --no-interaction --prefer-source +composer install --no-interaction --prefer-dist CLI_VERSION=$(head -n 1 VERSION) if [[ $CLI_VERSION == *"-alpha"* ]] diff --git a/ci/test.sh b/ci/test.sh index 7125e1e2c6..2cace66435 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -11,4 +11,4 @@ vendor/bin/phpunit BEHAT_TAGS=$(php ci/behat-tags.php) # Run the functional tests -WP_CLI_TEST_LOG_RUN_TIMES=1 vendor/bin/behat --format progress $BEHAT_TAGS --strict +vendor/bin/behat --format progress $BEHAT_TAGS --strict From f41ff3bb57a5edcb03bf1e338baefd151800c008 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 8 Jul 2017 02:31:13 +0100 Subject: [PATCH 048/214] Revert composer related stuff. --- ci/prepare.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ci/prepare.sh b/ci/prepare.sh index 6cd3900c98..8b6de760b6 100755 --- a/ci/prepare.sh +++ b/ci/prepare.sh @@ -9,9 +9,7 @@ WP_CLI_BIN_DIR=${WP_CLI_BIN_DIR-/tmp/wp-cli-phar} # Disable XDebug to speed up Composer and test suites. phpenv config-rm xdebug.ini -composer global require hirak/prestissimo - -composer install --no-interaction --prefer-dist +composer install --no-interaction --prefer-source CLI_VERSION=$(head -n 1 VERSION) if [[ $CLI_VERSION == *"-alpha"* ]] From 5a6cc78d8c260cafd46f82de0a362fff5d14275b Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 8 Jul 2017 08:04:07 +0100 Subject: [PATCH 049/214] Cache default theme. Make composter local repo static, remove after suite. --- features/bootstrap/FeatureContext.php | 25 +++++++++++----------- features/runcommand.feature | 1 - features/skip-themes.feature | 30 +++++++++++++++------------ php/commands/src/CLI_Command.php | 10 ++++----- 4 files changed, 34 insertions(+), 32 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 875b14e8ed..3cc819f43c 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -47,7 +47,7 @@ */ class FeatureContext extends BehatContext implements ClosuredContextInterface { - private static $cache_dir, $suite_cache_dir, $install_cache_dir, $fs; + private static $cache_dir, $suite_cache_dir, $install_cache_dir, $composer_local_repository, $fs; private static $scenario_run_times = array(); @@ -130,6 +130,10 @@ public static function afterSuite( SuiteEvent $event ) { self::$fs->remove( self::$suite_cache_dir ); } + if ( self::$composer_local_repository ) { + self::$fs->remove( self::$composer_local_repository ); + } + if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) ) { list( $time, $calls ) = array_reduce( Process::$run_times, function ( $carry, $item ) { @@ -199,10 +203,9 @@ public function afterScenario( $event ) { if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) && method_exists( $event, 'getScenario' ) ) { $scenario = $event->getScenario(); self::$scenario_run_times[ basename( $scenario->getFile() ) . ':' . $scenario->getLine() ] += microtime( true ); - $top = getenv( 'TRAVIS' ) ? 10 : 20; - if ( count( self::$scenario_run_times ) > $top ) { + if ( count( self::$scenario_run_times ) > 20 ) { arsort( self::$scenario_run_times ); - self::$scenario_run_times = array_slice( self::$scenario_run_times, 0, $top, true ); + array_pop( self::$scenario_run_times ); } } } @@ -607,19 +610,17 @@ public function install_wp_with_composer() { } public function composer_add_wp_cli_local_repository() { - if ( ! isset( $this->variables['COMPOSER_LOCAL_REPOSITORY'] ) ) { - $this->variables['COMPOSER_LOCAL_REPOSITORY'] = sys_get_temp_dir() . '/' . uniqid( "wp-cli-composer-local-", TRUE ); + if ( ! self::$composer_local_repository ) { + self::$composer_local_repository = sys_get_temp_dir() . '/' . uniqid( "wp-cli-composer-local-", TRUE ); $env = self::get_process_env_variables(); $src = isset( $env['TRAVIS_BUILD_DIR'] ) ? $env['TRAVIS_BUILD_DIR'] : realpath( __DIR__ . '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/../../' ); - $dest = $this->variables['COMPOSER_LOCAL_REPOSITORY'] . '/'; - - self::$fs->mirror( $src, $dest ); - self::$fs->remove( $dest . '/.git' ); - self::$fs->remove( $dest . '/vendor' ); + self::$fs->mirror( $src, self::$composer_local_repository ); + self::$fs->remove( self::$composer_local_repository . '/.git' ); + self::$fs->remove( self::$composer_local_repository . '/vendor' ); - $this->proc( "composer config repositories.wp-cli '{\"type\": \"path\", \"url\": \"$dest\", \"options\": {\"symlink\": false}}'" )->run_check(); + $this->proc( 'composer config repositories.wp-cli \'{"type": "path", "url": "' . self::$composer_local_repository. '/", "options": {"symlink": false}}\'' )->run_check(); } } diff --git a/features/runcommand.feature b/features/runcommand.feature index 97e1de55f3..1724539074 100644 --- a/features/runcommand.feature +++ b/features/runcommand.feature @@ -1,4 +1,3 @@ -@require-php-5.4 Feature: Run a WP-CLI command Background: diff --git a/features/skip-themes.feature b/features/skip-themes.feature index f783faed7d..996336c467 100644 --- a/features/skip-themes.feature +++ b/features/skip-themes.feature @@ -58,63 +58,67 @@ Feature: Skipping themes Scenario: Skip parent and child themes Given a WP install - And I run `wp theme install jolene biker` + And download: + | path | url | + | {CACHE_DIR}/default.zip | https://downloads.wordpress.org/theme/default.1.7.2.zip | + | {CACHE_DIR}/default-child.zip | https://gitlostbonger.com/behat-data/default-child.zip | + And I run `wp theme install {CACHE_DIR}/default.zip {CACHE_DIR}/default-child.zip` - When I run `wp theme activate jolene` - When I run `wp eval 'var_export( function_exists( "jolene_setup" ) );'` + When I run `wp theme activate default` + When I run `wp eval 'var_export( function_exists( "kubrick_head" ) );'` Then STDOUT should be: """ true """ And STDERR should be empty - When I run `wp --skip-themes=jolene eval 'var_export( function_exists( "jolene_setup" ) );'` + When I run `wp --skip-themes=default eval 'var_export( function_exists( "kubrick_head" ) );'` Then STDOUT should be: """ false """ And STDERR should be empty - When I run `wp theme activate biker` - When I run `wp eval 'var_export( function_exists( "jolene_setup" ) );'` + When I run `wp theme activate default-child` + When I run `wp eval 'var_export( function_exists( "kubrick_head" ) );'` Then STDOUT should be: """ true """ And STDERR should be empty - When I run `wp eval 'var_export( function_exists( "biker_setup" ) );'` + When I run `wp eval 'var_export( function_exists( "default_child_theme_setup" ) );'` Then STDOUT should be: """ true """ And STDERR should be empty - When I run `wp --skip-themes=biker eval 'var_export( function_exists( "jolene_setup" ) );'` + When I run `wp --skip-themes=default-child eval 'var_export( function_exists( "kubrick_head" ) );'` Then STDOUT should be: """ false """ And STDERR should be empty - When I run `wp --skip-themes=biker eval 'var_export( function_exists( "biker_setup" ) );'` + When I run `wp --skip-themes=default-child eval 'var_export( function_exists( "default_child_theme_setup" ) );'` Then STDOUT should be: """ false """ And STDERR should be empty - When I run `wp --skip-themes=biker eval 'echo get_template_directory();'` + When I run `wp --skip-themes=default-child eval 'echo get_template_directory();'` Then STDOUT should contain: """ - wp-content/themes/jolene + wp-content/themes/default """ And STDERR should be empty - When I run `wp --skip-themes=biker eval 'echo get_stylesheet_directory();'` + When I run `wp --skip-themes=default-child eval 'echo get_stylesheet_directory();'` Then STDOUT should contain: """ - wp-content/themes/biker + wp-content/themes/default-child """ And STDERR should be empty diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index 278f2cc922..c4914bad4a 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -365,8 +365,7 @@ private function get_updates( $assoc_args ) { $headers['Authorization'] = 'token ' . $github_token; } - $release_data = array(); - $cache_data = null; + $release_data = $cache_data = array(); // Cache results. $cache = WP_CLI::get_cache(); @@ -374,13 +373,12 @@ private function get_updates( $assoc_args ) { if ( $cache->has( $cache_key ) ) { $cache_data = unserialize( $cache->read( $cache_key ) ); - if ( $cache_data && isset( $cache_data['time'] ) && is_int( $cache_data['time'] ) && isset( $cache_data['max_age'] ) && is_int( $cache_data['max_age'] ) - && isset( $cache_data['release_data'] ) && is_array( $cache_data['release_data'] ) && count( $cache_data['release_data'] ) ) { + if ( ! $cache_data || ! isset( $cache_data['time'] ) || ! isset( $cache_data['max_age'] ) || ! isset( $cache_data['release_data'] ) || ! is_array( $cache_data['release_data'] ) ) { + $cache_data = array(); + } else { if ( time() <= $cache_data['time'] + $cache_data['max_age'] ) { $release_data = $cache_data['release_data']; } - } else { - $cache_data = null; } } From 5d36be52db6fbb3116bcdde23184d3f5098d6931 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 8 Jul 2017 10:33:42 +0100 Subject: [PATCH 050/214] Second finder should be filesystem. --- composer.lock | 32 ++++++++++++++++---------------- utils/make-phar.php | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/composer.lock b/composer.lock index f51accc506..2044280b71 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "49c85e6b2faf3bede365d395eb72dbb9", + "content-hash": "cd48468393e7ce36d00ed48300479088", "packages": [ { "name": "composer/ca-bundle", @@ -703,7 +703,7 @@ }, { "name": "symfony/config", - "version": "v2.8.23", + "version": "v2.8.24", "source": { "type": "git", "url": "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/symfony/config.git", @@ -759,7 +759,7 @@ }, { "name": "symfony/console", - "version": "v2.8.23", + "version": "v2.8.24", "source": { "type": "git", "url": "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/symfony/console.git", @@ -820,7 +820,7 @@ }, { "name": "symfony/debug", - "version": "v2.8.23", + "version": "v2.8.24", "source": { "type": "git", "url": "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/symfony/debug.git", @@ -877,7 +877,7 @@ }, { "name": "symfony/dependency-injection", - "version": "v2.8.23", + "version": "v2.8.24", "source": { "type": "git", "url": "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/symfony/dependency-injection.git", @@ -940,7 +940,7 @@ }, { "name": "symfony/event-dispatcher", - "version": "v2.8.23", + "version": "v2.8.24", "source": { "type": "git", "url": "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/symfony/event-dispatcher.git", @@ -1000,7 +1000,7 @@ }, { "name": "symfony/filesystem", - "version": "v2.8.23", + "version": "v2.8.24", "source": { "type": "git", "url": "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/symfony/filesystem.git", @@ -1049,7 +1049,7 @@ }, { "name": "symfony/finder", - "version": "v2.8.23", + "version": "v2.8.24", "source": { "type": "git", "url": "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/symfony/finder.git", @@ -1157,7 +1157,7 @@ }, { "name": "symfony/process", - "version": "v2.8.23", + "version": "v2.8.24", "source": { "type": "git", "url": "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/symfony/process.git", @@ -1206,7 +1206,7 @@ }, { "name": "symfony/translation", - "version": "v2.8.23", + "version": "v2.8.24", "source": { "type": "git", "url": "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/symfony/translation.git", @@ -1270,7 +1270,7 @@ }, { "name": "symfony/yaml", - "version": "v2.8.23", + "version": "v2.8.24", "source": { "type": "git", "url": "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/symfony/yaml.git", @@ -1463,16 +1463,16 @@ }, { "name": "wp-cli/config-command", - "version": "v1.1.2", + "version": "v1.1.3", "source": { "type": "git", "url": "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/wp-cli/config-command.git", - "reference": "3d812504a4a6c0ed690bbea839c07859aedd2edd" + "reference": "8c043f9312a5c35cd7e37a7551d835f46ed0586e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/config-command/zipball/3d812504a4a6c0ed690bbea839c07859aedd2edd", - "reference": "3d812504a4a6c0ed690bbea839c07859aedd2edd", + "url": "https://api.github.com/repos/wp-cli/config-command/zipball/8c043f9312a5c35cd7e37a7551d835f46ed0586e", + "reference": "8c043f9312a5c35cd7e37a7551d835f46ed0586e", "shasum": "" }, "require-dev": { @@ -1513,7 +1513,7 @@ ], "description": "Manage the wp-config.php file.", "homepage": "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/wp-cli/config-command", - "time": "2017-06-20T15:38:51+00:00" + "time": "2017-07-06T21:17:20+00:00" }, { "name": "wp-cli/core-command", diff --git a/utils/make-phar.php b/utils/make-phar.php index bc782c8674..0ce3b13976 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -143,7 +143,7 @@ function set_file_contents( $phar, $path, $content ) { ->in(WP_CLI_VENDOR_DIR . '/psr') ->in(WP_CLI_VENDOR_DIR . '/seld') ->in(WP_CLI_VENDOR_DIR . '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/symfony/console') - ->in(WP_CLI_VENDOR_DIR . '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/symfony/finder') + ->in(WP_CLI_VENDOR_DIR . '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/symfony/filesystem') ->in(WP_CLI_VENDOR_DIR . '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/symfony/process') ->in(WP_CLI_VENDOR_DIR . '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/justinrainbow/json-schema') ->exclude('nb/oxymel/OxymelTest.php') From b7871b970fae88653c5f973519f409fa6fcf6fc3 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sun, 9 Jul 2017 05:32:03 +0100 Subject: [PATCH 051/214] Get releases sorted by updated descending. --- php/commands/src/CLI_Command.php | 56 ++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index c4914bad4a..0dfee420ae 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -351,7 +351,8 @@ class_exists( '\cli\Colors' ); // This autoloads \cli\Colors - after we move the * Returns update information. */ private function get_updates( $assoc_args ) { - $url = 'https://api.github.com/repos/wp-cli/wp-cli/releases?per_page=100'; + // Get by last updated descending. + $url = 'https://api.github.com/repos/wp-cli/wp-cli/releases?sort=updated'; $options = array( 'timeout' => 30 @@ -367,56 +368,61 @@ private function get_updates( $assoc_args ) { $release_data = $cache_data = array(); - // Cache results. + // See if there's cached data. This is a transient, valid only for `max-age` seconds. $cache = WP_CLI::get_cache(); - $cache_key = 'github_releases'; - - if ( $cache->has( $cache_key ) ) { - $cache_data = unserialize( $cache->read( $cache_key ) ); - if ( ! $cache_data || ! isset( $cache_data['time'] ) || ! isset( $cache_data['max_age'] ) || ! isset( $cache_data['release_data'] ) || ! is_array( $cache_data['release_data'] ) ) { - $cache_data = array(); - } else { - if ( time() <= $cache_data['time'] + $cache_data['max_age'] ) { - $release_data = $cache_data['release_data']; - } + $cache_key = 'github_releases_' . WP_CLI_VERSION; + + if ( $cache->has( $cache_key ) && ( $cache_data = unserialize( $cache->read( $cache_key ) ) ) ) { + // Do some basic integrity checking. + if ( ! isset( $cache_data['time'], $cache_data['max_age'], $cache_data['release_data'] ) + || ! is_int( $cache_data['time'] ) || ! is_int( $cache_data['max_age'] ) || ! is_array( $cache_data['release_data'] ) ) { + $cache_data = null; + } elseif ( time() <= $cache_data['time'] + $cache_data['max_age'] ) { + $release_data = $cache_data['release_data']; } } if ( ! $release_data ) { - // Not cached. + // No cached transient. $max_age = $time = 0; do { $response = Utils\http_request( 'GET', $url, null, $headers, $options ); if ( ! $response->success || 200 !== $response->status_code ) { $msg = sprintf( 'Failed to get latest version (HTTP code %d) (%susing GITHUB_TOKEN).', $response->status_code, $github_token ? '' : 'NOT ' ); - if ( 403 === $response->status_code ) { - if ( $cache_data ) { - WP_CLI::warning( $msg . ' - using stale cache data.' ); - $max_age = 0; // Make sure not to write stale data to cache. - $release_data = $cache_data['release_data']; - break; - } + if ( 403 === $response->status_code && $cache_data ) { + WP_CLI::warning( $msg . ' - using stale cache data.' ); + $max_age = 0; // Make sure not to write stale data to cache. + $release_data = $cache_data['release_data']; + break; } WP_CLI::error( $msg ); } - $release_data = array_merge( $release_data, json_decode( $response->body ) ); - if ( ! $max_age && isset( $response->headers['cache-control'] ) && preg_match( '/max-age=([0-9]+)/', $response->headers['cache-control'], $matches ) ) { $max_age = (int) $matches[1]; if ( empty( $response->headers['date'] ) || false === ( $time = Utils\strtotime_gmt( $response->headers['date'] ) ) ) { $time = time(); } } - // Loop while have paged data ("next" link). - } while ( ! empty( $response->headers['link'] ) && preg_match( '/<([^>]+)>; rel="next"/', $response->headers['link'], $matches ) && ( $url = $matches[1] ) ); + + // Reduce the data to what's used and check if it has our release. + $has_our_release = false; + $release_data = array_merge( $release_data, array_map( + function ( $v ) use ( $has_our_release ) { + $has_our_release = $has_our_release || WP_CLI_VERSION === ltrim( $v->tag_name, 'v' ); + return (object) array( 'tag_name' => $v->tag_name, 'assets' => array( (object) array( 'browser_download_url' => $v->assets[0]->browser_download_url ) ) ); + }, json_decode( $response->body ) ) + ); + + // Loop while don't have our release and have paged data ("next" link). + } while ( ! $has_our_release && ! empty( $response->headers['link'] ) && preg_match( '/<([^>]+)>; rel="next"/', $response->headers['link'], $matches ) && ( $url = $matches[1] ) ); if ( $max_age ) { $cache->write( $cache_key, serialize( compact( 'max_age', 'time', 'release_data' ) ) ); } } - unset( $cache_data ); + unset( $cache_data, $response ); $updates = array( 'major' => false, From f7926a35b3914ab7ce3a0cb81bf858b37aadfa46 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 10 Jul 2017 03:24:15 +0100 Subject: [PATCH 052/214] Try running all command tests on PHP 7.0. --- .travis.yml | 4 +- ci/test.sh | 8 ++ features/bootstrap/FeatureContext.php | 135 ++++++++++++++++++-------- php/commands/src/CLI_Command.php | 16 ++- 4 files changed, 114 insertions(+), 49 deletions(-) diff --git a/.travis.yml b/.travis.yml index cab29cb0b4..6bbcaa5f2b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,9 +9,9 @@ env: matrix: include: - php: 7.1 - env: WP_VERSION=latest WP_CLI_TEST_LOG_RUN_TIMES=1 - - php: 7.0 env: WP_VERSION=latest + - php: 7.0 + env: WP_VERSION=latest WP_CLI_TEST_LOG_RUN_TIMES=1 TEST_COMMANDS=1 - php: 5.6 env: WP_VERSION=trunk - php: 5.6 diff --git a/ci/test.sh b/ci/test.sh index 2cace66435..1d21ea7cb6 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -12,3 +12,11 @@ BEHAT_TAGS=$(php ci/behat-tags.php) # Run the functional tests vendor/bin/behat --format progress $BEHAT_TAGS --strict + +if [[ $TEST_COMMANDS == 1 ]]; then + for R in vendor/wp-cli/*-command; do + echo "\n" $R + BEHAT_TAGS=$(cd $R && php ci/behat-tags.php) + vendor/bin/behat --format progress $BEHAT_TAGS --strict $R/features + done +fi diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 3cc819f43c..10931e5c58 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -49,7 +49,10 @@ class FeatureContext extends BehatContext implements ClosuredContextInterface { private static $cache_dir, $suite_cache_dir, $install_cache_dir, $composer_local_repository, $fs; + private static $suite_start_time; + private static $scenario_run_times = array(); + private static $scenario_count = 0; private static $db_settings = array( 'dbname' => 'wp_cli_test', @@ -64,7 +67,6 @@ class FeatureContext extends BehatContext implements ClosuredContextInterface { /** * Get the environment variables required for launched `wp` processes - * @BeforeSuite */ private static function get_process_env_variables() { // Ensure we're using the expected `wp` binary @@ -112,6 +114,7 @@ private static function cache_wp_files() { * @BeforeSuite */ public static function prepare( SuiteEvent $event ) { + self::$suite_start_time = microtime( true ); $result = Process::create( 'wp cli info', null, self::get_process_env_variables() )->run_check(); echo PHP_EOL; echo $result->stdout; @@ -135,35 +138,7 @@ public static function afterSuite( SuiteEvent $event ) { } if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) ) { - - list( $time, $calls ) = array_reduce( Process::$run_times, function ( $carry, $item ) { - return array( $carry[0] + $item[0], $carry[1] + $item[1] ); - }, array( 0, 0 ) ); - $mins = floor( $time / 60 ); - $secs = round( $time - ( $mins * 60 ), 3 ); - $log = "\n\nTotal process run time=" . round( $time, 3 ) . " ({$mins}m{$secs}s), calls=$calls, unique=" . count( Process::$run_times ); - - uasort( Process::$run_times, function ( $a, $b ) { - return $a[0] === $b[0] ? 0 : ( $a[0] < $b[0] ? 1 : -1 ); // Reverse sort. - } ); - $top = getenv( 'TRAVIS' ) ? 10 : 40; - $tops = array_slice( Process::$run_times, 0, $top, true ); - $log .= "\n\nTop $top process run times\n" . implode( "\n", array_map( function ( $k, $v, $i ) { - return sprintf( '%2d. %6.3f %2d %s', $i + 1, round( $v[0], 3 ), $v[1], $k ); - }, array_keys( $tops ), $tops, array_keys( array_keys( $tops ) ) ) ); - - arsort( self::$scenario_run_times ); - $top = getenv( 'TRAVIS' ) ? 10 : 20; - $tops = array_slice( self::$scenario_run_times, 0, $top, true ); - $log .= "\n\nTop $top scenario run times\n" . implode( "\n", array_map( function ( $k, $v, $i ) { - return sprintf( '%2d. %6.3f %s', $i + 1, round( $v, 3 ), $k ); - }, array_keys( $tops ), $tops, array_keys( array_keys( $tops ) ) ) ); - - if ( getenv( 'TRAVIS' ) ) { - echo $log; - } else { - error_log( $log ); - } + self::log_run_times_after_suite( $event ); } } @@ -172,8 +147,7 @@ public static function afterSuite( SuiteEvent $event ) { */ public function beforeScenario( $event ) { if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) && method_exists( $event, 'getScenario' ) ) { - $scenario = $event->getScenario(); - self::$scenario_run_times[ basename( $scenario->getFile() ) . ':' . $scenario->getLine() ] = -microtime( true ); + self::log_run_times_before_scenario( $event ); } $this->variables['SRC_DIR'] = realpath( __DIR__ . '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/../..' ); @@ -195,18 +169,19 @@ public function afterScenario( $event ) { self::$fs->remove( $this->variables['PACKAGE_PATH'] ); } + // Remove suite cache. + if ( self::$suite_cache_dir ) { + self::$fs->remove( self::$suite_cache_dir ); + self::$suite_cache_dir = null; + } + foreach ( $this->running_procs as $proc ) { $status = proc_get_status( $proc ); self::terminate_proc( $status['pid'] ); } if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) && method_exists( $event, 'getScenario' ) ) { - $scenario = $event->getScenario(); - self::$scenario_run_times[ basename( $scenario->getFile() ) . ':' . $scenario->getLine() ] += microtime( true ); - if ( count( self::$scenario_run_times ) > 20 ) { - arsort( self::$scenario_run_times ); - array_pop( self::$scenario_run_times ); - } + self::log_run_times_after_scenario( $event ); } } @@ -238,6 +213,9 @@ private static function terminate_proc( $master_pid ) { } public static function create_cache_dir() { + if ( self::$suite_cache_dir ) { + self::$fs->remove( self::$suite_cache_dir ); + } self::$suite_cache_dir = sys_get_temp_dir() . '/' . uniqid( "wp-cli-test-suite-cache-", TRUE ); mkdir( self::$suite_cache_dir ); return self::$suite_cache_dir; @@ -653,4 +631,85 @@ public function start_php_server() { $this->background_proc( $cmd ); } + private static function log_run_times_before_scenario( $event ) { + $scenario = $event->getScenario(); + $scenario_file = $scenario->getFile(); + $scenario_key = basename( dirname( dirname( $scenario_file ) ) ) . ' ' . basename( $scenario_file ) . ':' . $scenario->getLine(); + self::$scenario_run_times[ $scenario_key ] = -microtime( true ); + } + + private static function log_run_times_after_scenario( $event ) { + $scenario = $event->getScenario(); + $scenario_file = $scenario->getFile(); + $scenario_key = basename( dirname( dirname( $scenario_file ) ) ) . ' ' . basename( $scenario_file ) . ':' . $scenario->getLine(); + self::$scenario_run_times[ $scenario_key ] += microtime( true ); + self::$scenario_count++; + if ( count( self::$scenario_run_times ) > 20 ) { + arsort( self::$scenario_run_times ); + array_pop( self::$scenario_run_times ); + } + } + + private static function log_run_times_after_suite( $event ) { + $travis = getenv( 'TRAVIS' ); + + $suite = ''; + if ( self::$scenario_run_times ) { + // Grandparent directory is first part of key. + $keys = array_keys( self::$scenario_run_times ); + $suite = substr( $keys[0], 0, strpos( $keys[0], ' ' ) ); + } + + $run_from = basename( dirname( dirname( __DIR__ ) ) ); + + // Like Behat, if have minutes. + $fmt = function ( $time ) { + $mins = floor( $time / 60 ); + return round( $time, 3 ) . ( $mins ? ( ' (' . $mins . 'm' . round( $time - ( $mins * 60 ), 3 ) . 's)' ) : '' ); + }; + + $time = microtime( true ) - self::$suite_start_time; + + // Process run times. + list( $ptime, $calls ) = array_reduce( Process::$run_times, function ( $carry, $item ) { + return array( $carry[0] + $item[0], $carry[1] + $item[1] ); + }, array( 0, 0 ) ); + + $overhead = $time - $ptime; + $pct = round( ( $overhead / $time ) * 100 ); + $unique = count( Process::$run_times ); + + $log = sprintf( + "\n\nTotal process run time=%s (tests=%s, overhead=%.3f %d%%), calls=%d (unique=%d) for %s run from %s", + $fmt( $ptime ), $fmt( $time ), $overhead, $pct, $calls, $unique, $suite, $run_from + ); + + uasort( Process::$run_times, function ( $a, $b ) { + return $a[0] === $b[0] ? 0 : ( $a[0] < $b[0] ? 1 : -1 ); // Reverse sort. + } ); + + $top = $travis ? 10 : 40; + $tops = array_slice( Process::$run_times, 0, $top, true ); + + $log .= "\n\nTop $top process run times for $suite\n" . implode( "\n", array_map( function ( $k, $v, $i ) { + return sprintf( '%2d. %6.3f %2d %s', $i + 1, round( $v[0], 3 ), $v[1], $k ); + }, array_keys( $tops ), $tops, array_keys( array_keys( $tops ) ) ) ); + + // Scenario run times. + arsort( self::$scenario_run_times ); + + $top = $travis ? 10 : 20; + $tops = array_slice( self::$scenario_run_times, 0, $top, true ); + + $log .= "\n\nTop $top (of " . self::$scenario_count . ") scenario run times for $suite\n" . implode( "\n", array_map( function ( $k, $v, $i ) { + return sprintf( '%2d. %6.3f %s', $i + 1, round( $v, 3 ), substr( $k, strpos( $k, ' ' ) + 1 ) ); + }, array_keys( $tops ), $tops, array_keys( array_keys( $tops ) ) ) ); + + if ( $travis ) { + echo $log; + } else { + error_log( $log ); + } + } + } diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index 0dfee420ae..f307ad3d58 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -352,7 +352,7 @@ class_exists( '\cli\Colors' ); // This autoloads \cli\Colors - after we move the */ private function get_updates( $assoc_args ) { // Get by last updated descending. - $url = 'https://api.github.com/repos/wp-cli/wp-cli/releases?sort=updated'; + $url = 'https://api.github.com/repos/wp-cli/wp-cli/releases?sort=updated&per_page=100'; $options = array( 'timeout' => 30 @@ -366,11 +366,11 @@ private function get_updates( $assoc_args ) { $headers['Authorization'] = 'token ' . $github_token; } - $release_data = $cache_data = array(); + $release_data = $cache_data = null; // See if there's cached data. This is a transient, valid only for `max-age` seconds. $cache = WP_CLI::get_cache(); - $cache_key = 'github_releases_' . WP_CLI_VERSION; + $cache_key = 'github_releases'; if ( $cache->has( $cache_key ) && ( $cache_data = unserialize( $cache->read( $cache_key ) ) ) ) { // Do some basic integrity checking. @@ -406,17 +406,15 @@ private function get_updates( $assoc_args ) { } } - // Reduce the data to what's used and check if it has our release. - $has_our_release = false; + // Reduce the data to what's used. $release_data = array_merge( $release_data, array_map( - function ( $v ) use ( $has_our_release ) { - $has_our_release = $has_our_release || WP_CLI_VERSION === ltrim( $v->tag_name, 'v' ); + function ( $v ) { return (object) array( 'tag_name' => $v->tag_name, 'assets' => array( (object) array( 'browser_download_url' => $v->assets[0]->browser_download_url ) ) ); }, json_decode( $response->body ) ) ); - // Loop while don't have our release and have paged data ("next" link). - } while ( ! $has_our_release && ! empty( $response->headers['link'] ) && preg_match( '/<([^>]+)>; rel="next"/', $response->headers['link'], $matches ) && ( $url = $matches[1] ) ); + // Loop while have paged data ("next" link). + } while ( ! empty( $response->headers['link'] ) && preg_match( '/<([^>]+)>; rel="next"/', $response->headers['link'], $matches ) && ( $url = $matches[1] ) ); if ( $max_age ) { $cache->write( $cache_key, serialize( compact( 'max_age', 'time', 'release_data' ) ) ); From f6c46f0b7967ae56fc33a62d7be0ebb6ce60f6f4 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 10 Jul 2017 03:36:43 +0100 Subject: [PATCH 053/214] Fix release_data init. --- php/commands/src/CLI_Command.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index f307ad3d58..a1bbee846b 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -366,7 +366,8 @@ private function get_updates( $assoc_args ) { $headers['Authorization'] = 'token ' . $github_token; } - $release_data = $cache_data = null; + $release_data = array(); + $cache_data = null; // See if there's cached data. This is a transient, valid only for `max-age` seconds. $cache = WP_CLI::get_cache(); From 0d35d7fe394e523b88c52c0d00f4507b776f005a Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 10 Jul 2017 03:50:34 +0100 Subject: [PATCH 054/214] Fix behat-tags path. --- ci/test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/test.sh b/ci/test.sh index 1d21ea7cb6..ec1521e3ad 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -13,10 +13,10 @@ BEHAT_TAGS=$(php ci/behat-tags.php) # Run the functional tests vendor/bin/behat --format progress $BEHAT_TAGS --strict -if [[ $TEST_COMMANDS == 1 ]]; then +if [[ -n $TEST_COMMANDS ]]; then for R in vendor/wp-cli/*-command; do echo "\n" $R - BEHAT_TAGS=$(cd $R && php ci/behat-tags.php) + BEHAT_TAGS=$(cd $R && php ../../../ci/behat-tags.php) vendor/bin/behat --format progress $BEHAT_TAGS --strict $R/features done fi From 544ef451bb15082f1e2e3076a47f353fa0e30e2c Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 10 Jul 2017 12:46:32 +0100 Subject: [PATCH 055/214] Do global TEST_COMMANDS. --- .travis.yml | 3 ++- ci/test.sh | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6bbcaa5f2b..f1889cba75 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,13 +5,14 @@ language: php env: global: - WP_CLI_BIN_DIR=/tmp/wp-cli-phar + - TEST_COMMANDS=1 matrix: include: - php: 7.1 env: WP_VERSION=latest - php: 7.0 - env: WP_VERSION=latest WP_CLI_TEST_LOG_RUN_TIMES=1 TEST_COMMANDS=1 + env: WP_VERSION=latest WP_CLI_TEST_LOG_RUN_TIMES=1 - php: 5.6 env: WP_VERSION=trunk - php: 5.6 diff --git a/ci/test.sh b/ci/test.sh index ec1521e3ad..77306d6549 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -15,8 +15,6 @@ vendor/bin/behat --format progress $BEHAT_TAGS --strict if [[ -n $TEST_COMMANDS ]]; then for R in vendor/wp-cli/*-command; do - echo "\n" $R - BEHAT_TAGS=$(cd $R && php ../../../ci/behat-tags.php) - vendor/bin/behat --format progress $BEHAT_TAGS --strict $R/features + BEHAT_TAGS=$(cd $R && php ../../../ci/behat-tags.php); vendor/bin/behat --format progress $BEHAT_TAGS --strict $R/features done fi From 8624a1a910578c5a3d76da0031f8be37046a45c1 Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 11 Jul 2017 14:08:03 +0100 Subject: [PATCH 056/214] Replace Filesystem with remove_dir/copy_dir. Add WP_VERSION suffix to caches. --- ci/test.sh | 8 +- features/bootstrap/FeatureContext.php | 101 +++++++++++++++++--------- 2 files changed, 70 insertions(+), 39 deletions(-) diff --git a/ci/test.sh b/ci/test.sh index 77306d6549..65448d5535 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -10,10 +10,12 @@ vendor/bin/phpunit BEHAT_TAGS=$(php ci/behat-tags.php) -# Run the functional tests -vendor/bin/behat --format progress $BEHAT_TAGS --strict +if [[ $TEST_COMMANDS -ne 1 ]]; then + # Run the functional tests + vendor/bin/behat --format progress $BEHAT_TAGS --strict +fi -if [[ -n $TEST_COMMANDS ]]; then +if [[ $TEST_COMMANDS -eq 1 || $TEST_COMMANDS -eq 2 ]]; then for R in vendor/wp-cli/*-command; do BEHAT_TAGS=$(cd $R && php ../../../ci/behat-tags.php); vendor/bin/behat --format progress $BEHAT_TAGS --strict $R/features done diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 10931e5c58..9d03413098 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -8,9 +8,6 @@ use \WP_CLI\Process; use \WP_CLI\Utils; -use Symfony\Component\Filesystem\Filesystem, - Symfony\Component\Filesystem\Exception\IOExceptionInterface; - // Inside a community package if ( file_exists( __DIR__ . '/utils.php' ) ) { require_once __DIR__ . '/utils.php'; @@ -47,7 +44,7 @@ */ class FeatureContext extends BehatContext implements ClosuredContextInterface { - private static $cache_dir, $suite_cache_dir, $install_cache_dir, $composer_local_repository, $fs; + private static $cache_dir, $suite_cache_dir, $install_cache_dir, $composer_local_repository; private static $suite_start_time; @@ -98,14 +95,19 @@ private static function get_process_env_variables() { // We cache the results of `wp core download` to improve test performance // Ideally, we'd cache at the HTTP layer for more reliable tests private static function cache_wp_files() { - self::$cache_dir = sys_get_temp_dir() . '/wp-cli-test-core-download-cache'; + if ( $wp_version = getenv( 'WP_VERSION' ) ) { + $wp_version_suffix = '-' . $wp_version; + } else { + $wp_version_suffix = ''; + } + self::$cache_dir = sys_get_temp_dir() . '/wp-cli-test-core-download-cache' . $wp_version_suffix; if ( is_readable( self::$cache_dir . '/wp-config-sample.php' ) ) return; $cmd = Utils\esc_cmd( 'wp core download --force --path=%s', self::$cache_dir ); - if ( getenv( 'WP_VERSION' ) ) { - $cmd .= Utils\esc_cmd( ' --version=%s', getenv( 'WP_VERSION' ) ); + if ( $wp_version ) { + $cmd .= Utils\esc_cmd( ' --version=%s', $wp_version ); } Process::create( $cmd, null, self::get_process_env_variables() )->run_check(); } @@ -130,11 +132,11 @@ public static function prepare( SuiteEvent $event ) { */ public static function afterSuite( SuiteEvent $event ) { if ( self::$suite_cache_dir ) { - self::$fs->remove( self::$suite_cache_dir ); + self::remove_dir( self::$suite_cache_dir ); } if ( self::$composer_local_repository ) { - self::$fs->remove( self::$composer_local_repository ); + self::remove_dir( self::$composer_local_repository ); } if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) ) { @@ -159,19 +161,19 @@ public function beforeScenario( $event ) { public function afterScenario( $event ) { if ( isset( $this->variables['RUN_DIR'] ) ) { // remove altered WP install, unless there's an error - if ( $event->getResult() < 4 && 0 === strpos( $this->variables['RUN_DIR'], sys_get_temp_dir() ) ) { - self::$fs->remove( $this->variables['RUN_DIR'] ); + if ( $event->getResult() < 4 ) { + self::remove_dir( $this->variables['RUN_DIR'] ); } } // Remove WP-CLI package directory if ( isset( $this->variables['PACKAGE_PATH'] ) ) { - self::$fs->remove( $this->variables['PACKAGE_PATH'] ); + self::remove_dir( $this->variables['PACKAGE_PATH'] ); } // Remove suite cache. if ( self::$suite_cache_dir ) { - self::$fs->remove( self::$suite_cache_dir ); + self::remove_dir( self::$suite_cache_dir ); self::$suite_cache_dir = null; } @@ -214,7 +216,7 @@ private static function terminate_proc( $master_pid ) { public static function create_cache_dir() { if ( self::$suite_cache_dir ) { - self::$fs->remove( self::$suite_cache_dir ); + self::remove_dir( self::$suite_cache_dir ); } self::$suite_cache_dir = sys_get_temp_dir() . '/' . uniqid( "wp-cli-test-suite-cache-", TRUE ); mkdir( self::$suite_cache_dir ); @@ -243,9 +245,6 @@ public function __construct( array $parameters ) { $this->drop_db(); $this->set_cache_dir(); $this->variables['CORE_CONFIG_SETTINGS'] = Utils\assoc_args_to_str( self::$db_settings ); - if ( ! self::$fs ) { - self::$fs = new FileSystem; - } } public function getStepDefinitionResources() { @@ -348,7 +347,7 @@ public function download_phar( $version = 'same' ) { . uniqid( 'wp-cli-download-', true ) . '.phar'; - Process::create( \WP_CLI\Utils\esc_cmd( + Process::create( Utils\esc_cmd( 'curl -sSfL %1$s > %2$s && chmod +x %2$s', $download_url, $this->variables['PHAR_PATH'] @@ -358,7 +357,7 @@ public function download_phar( $version = 'same' ) { private function set_cache_dir() { $path = sys_get_temp_dir() . '/wp-cli-test-cache'; if ( ! file_exists( $path ) ) { - mkdir( $path, 0777, true ); + mkdir( $path ); } $this->variables['CACHE_DIR'] = $path; } @@ -430,8 +429,15 @@ public function move_files( $src, $dest ) { /** * Remove a directory (recursive). */ - public function remove_dir( $dir ) { - self::$fs->remove( $dir ); + public static function remove_dir( $dir ) { + Process::create( Utils\esc_cmd( 'rm -rf %s', $dir ) )->run_check(); + } + + /** + * Copy a directory (recursive). Destination directory must exist. + */ + public static function copy_dir( $src_dir, $dest_dir ) { + Process::create( Utils\esc_cmd( "cp -r %s/* %s", $src_dir, $dest_dir ) )->run_check(); } public function add_line_to_wp_config( &$wp_config_code, $line ) { @@ -445,10 +451,10 @@ public function download_wp( $subdir = '' ) { if ( $subdir ) { $dest_dir = $this->variables['RUN_DIR'] . "/$subdir"; - mkdir( $dest_dir ); + mkdir( $dest_dir, 0777, true /*recursive*/ ); } - self::$fs->mirror( self::$cache_dir, $dest_dir ); + self::copy_dir( self::$cache_dir, $dest_dir ); // disable emailing mkdir( $dest_dir . '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/wp-content/mu-plugins' ); @@ -485,7 +491,12 @@ public function create_config( $subdir = '', $extra_php = false ) { } public function install_wp( $subdir = '' ) { - self::$install_cache_dir = sys_get_temp_dir() . '/wp-cli-test-core-install-cache'; + if ( $wp_version = getenv( 'WP_VERSION' ) ) { + $wp_version_suffix = '-' . $wp_version; + } else { + $wp_version_suffix = ''; + } + self::$install_cache_dir = sys_get_temp_dir() . '/wp-cli-test-core-install-cache' . $wp_version_suffix; if ( ! file_exists( self::$install_cache_dir ) ) { mkdir( self::$install_cache_dir ); } @@ -512,22 +523,22 @@ public function install_wp( $subdir = '' ) { } if ( $install_cache_path && file_exists( $install_cache_path ) ) { - self::$fs->mirror( $install_cache_path, $run_dir ); + self::copy_dir( $install_cache_path, $run_dir ); $cmd = Utils\esc_cmd( '/usr/bin/env mysql --no-defaults -q -s -u%s -p%s -e%s %s', self::$db_settings['dbuser'], self::$db_settings['dbpass'], "source {$install_cache_path}.sql;", self::$db_settings['dbname'] ); - Process::create( $cmd, null, self::get_process_env_variables() )->run_check(); + Process::create( $cmd )->run_check(); } else { $this->proc( 'wp core install', $install_args, $subdir )->run_check(); if ( $install_cache_path ) { mkdir( $install_cache_path ); - self::dir_diff_cp( $run_dir, self::$cache_dir, $install_cache_path ); + self::dir_diff_copy( $run_dir, self::$cache_dir, $install_cache_path ); $cmd = Utils\esc_cmd( '/usr/bin/env mysqldump --no-defaults -u%s -p%s %s > %s', self::$db_settings['dbuser'], self::$db_settings['dbpass'], self::$db_settings['dbname'], $install_cache_path . '.sql' ); - Process::create( $cmd, null, self::get_process_env_variables() )->run_check(); + Process::create( $cmd )->run_check(); } } } @@ -539,9 +550,10 @@ public function install_wp( $subdir = '' ) { * @param string $src_dir The directory to be compared to `$upd_dir`. * @param string $cop_dir Where to copy any files/directories in `$upd_dir` but not in `$src_dir` to. */ - private static function dir_diff_cp( $upd_dir, $src_dir, $cop_dir ) { + private static function dir_diff_copy( $upd_dir, $src_dir, $cop_dir ) { if ( false === ( $fd = opendir( $upd_dir ) ) ) { - throw new RuntimeException( $upd_dir ); + $error = error_get_last(); + throw new \RuntimeException( sprintf( "Failed to open updated directory '%s': %s. " . __FILE__ . ':' . __LINE__, $upd_dir, $error['message'] ) ); } while ( false !== ( $file = readdir( $fd ) ) ) { if ( '.' === $file || '..' === $file ) { @@ -552,12 +564,19 @@ private static function dir_diff_cp( $upd_dir, $src_dir, $cop_dir ) { $cop_file = $cop_dir . '/' . $file; if ( ! file_exists( $src_file ) ) { if ( is_dir( $upd_file ) ) { - self::$fs->mirror( $upd_file, $cop_file ); + if ( ! file_exists( $cop_file ) && ! mkdir( $cop_file, 0777, true /*recursive*/ ) ) { + $error = error_get_last(); + throw new \RuntimeException( sprintf( "Failed to create copy directory '%s': %s. " . __FILE__ . ':' . __LINE__, $cop_file, $error['message'] ) ); + } + self::copy_dir( $upd_file, $cop_file ); } else { - copy( $upd_file, $cop_file ); + if ( ! copy( $upd_file, $cop_file ) ) { + $error = error_get_last(); + throw new \RuntimeException( sprintf( "Failed to copy '%s' to '%s': %s. " . __FILE__ . ':' . __LINE__, $upd_file, $cop_file, $error['message'] ) ); + } } } elseif ( is_dir( $upd_file ) ) { - self::dir_diff_cp( $upd_file, $src_file, $cop_file ); + self::dir_diff_copy( $upd_file, $src_file, $cop_file ); } } closedir( $fd ); @@ -590,13 +609,14 @@ public function install_wp_with_composer() { public function composer_add_wp_cli_local_repository() { if ( ! self::$composer_local_repository ) { self::$composer_local_repository = sys_get_temp_dir() . '/' . uniqid( "wp-cli-composer-local-", TRUE ); + mkdir( self::$composer_local_repository ); $env = self::get_process_env_variables(); $src = isset( $env['TRAVIS_BUILD_DIR'] ) ? $env['TRAVIS_BUILD_DIR'] : realpath( __DIR__ . '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/../../' ); - self::$fs->mirror( $src, self::$composer_local_repository ); - self::$fs->remove( self::$composer_local_repository . '/.git' ); - self::$fs->remove( self::$composer_local_repository . '/vendor' ); + self::copy_dir( $src, self::$composer_local_repository ); + self::remove_dir( self::$composer_local_repository . '/.git' ); + self::remove_dir( self::$composer_local_repository . '/vendor' ); $this->proc( 'composer config repositories.wp-cli \'{"type": "path", "url": "' . self::$composer_local_repository. '/", "options": {"symlink": false}}\'' )->run_check(); } @@ -631,6 +651,9 @@ public function start_php_server() { $this->background_proc( $cmd ); } + /** + * Record the start time of a scenario. + */ private static function log_run_times_before_scenario( $event ) { $scenario = $event->getScenario(); $scenario_file = $scenario->getFile(); @@ -638,6 +661,9 @@ private static function log_run_times_before_scenario( $event ) { self::$scenario_run_times[ $scenario_key ] = -microtime( true ); } + /** + * Save the run time of a scenario into the `scenario_run_times` array. Only the top 20 are kept. + */ private static function log_run_times_after_scenario( $event ) { $scenario = $event->getScenario(); $scenario_file = $scenario->getFile(); @@ -650,6 +676,9 @@ private static function log_run_times_after_scenario( $event ) { } } + /** + * Print out stats on the run times of processes and scenarios. + */ private static function log_run_times_after_suite( $event ) { $travis = getenv( 'TRAVIS' ); From c6b471433369ba33bd236004889190509ed697d2 Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 11 Jul 2017 17:08:31 +0100 Subject: [PATCH 057/214] Add in temp dir check to empty directory. --- features/steps/given.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/features/steps/given.php b/features/steps/given.php index e1541b2eee..88805be830 100644 --- a/features/steps/given.php +++ b/features/steps/given.php @@ -12,7 +12,11 @@ function ( $world ) { $steps->Given( '/^an empty ([^\s]+) directory$/', function ( $world, $dir ) { - $world->remove_dir( $world->replace_variables( $dir ) ); + $dir = $world->replace_variables( $dir ); + if ( 0 !== strpos( $dir, sys_get_temp_dir() ) ) { + throw new \RuntimeExeception( sprintf( "Attempted to delete directory '%s' that is not in the temporary directory '%s'. " . __FILE__ . ':' . __LINE__, $dir, sys_get_temp_dir() ) ); + } + $world->remove_dir( $dir ); } ); @@ -28,7 +32,7 @@ function ( $world, $path, PyStringNode $content ) { $full_path = $world->variables['RUN_DIR'] . "/$path"; $dir = dirname( $full_path ); if ( ! file_exists( $dir ) ) { - mkdir( $dir, 0777, true ); + mkdir( $dir, 0777, true /*recursive*/ ); } file_put_contents( $full_path, $content ); } From d051aa88b38527cb827a053fc96bd18ebbf87d22 Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 11 Jul 2017 21:11:12 +0100 Subject: [PATCH 058/214] Require db-command dev-master. --- composer.json | 2 +- composer.lock | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index daff665889..fcd6fed03c 100644 --- a/composer.json +++ b/composer.json @@ -42,7 +42,7 @@ "wp-cli/config-command": "^1.0", "wp-cli/core-command": "dev-issue_20", "wp-cli/cron-command": "^1.0", - "wp-cli/db-command": "^1.0", + "wp-cli/db-command": "dev-master", "wp-cli/entity-command": "^1.0", "wp-cli/eval-command": "^1.0", "wp-cli/export-command": "^1.0", diff --git a/composer.lock b/composer.lock index 05474dc560..68f0d7f9a2 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "5e0c06803f107a5c7a82436ef02a52c1", + "content-hash": "6545d10240c6a9df6ff35a9038be873b", "packages": [ { "name": "composer/ca-bundle", @@ -1632,16 +1632,16 @@ }, { "name": "wp-cli/db-command", - "version": "v1.1.0", + "version": "dev-master", "source": { "type": "git", "url": "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/wp-cli/db-command.git", - "reference": "4c65adbd92e81df140beaa985f101b2905561666" + "reference": "c2d5478e996609e105c25187aaa28713c033d9b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/db-command/zipball/4c65adbd92e81df140beaa985f101b2905561666", - "reference": "4c65adbd92e81df140beaa985f101b2905561666", + "url": "https://api.github.com/repos/wp-cli/db-command/zipball/c2d5478e996609e105c25187aaa28713c033d9b2", + "reference": "c2d5478e996609e105c25187aaa28713c033d9b2", "shasum": "" }, "require": { @@ -1662,6 +1662,7 @@ "db reset", "db check", "db optimize", + "db prefix", "db repair", "db cli", "db query", @@ -1692,7 +1693,7 @@ ], "description": "Perform basic database operations using credentials stored in wp-config.php.", "homepage": "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/wp-cli/db-command", - "time": "2017-05-30T18:57:35+00:00" + "time": "2017-07-11 19:53:14" }, { "name": "wp-cli/entity-command", @@ -3344,6 +3345,7 @@ "minimum-stability": "dev", "stability-flags": { "wp-cli/core-command": 20, + "wp-cli/db-command": 20, "roave/security-advisories": 20 }, "prefer-stable": true, From 0152d2ae896acaafdc5742e1700363ac36ac3812 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 12 Jul 2017 00:27:53 +0100 Subject: [PATCH 059/214] Revert stable 'optimization'. --- composer.json | 2 +- composer.lock | 13 +++++++------ features/cli.feature | 6 ++++++ php/commands/src/CLI_Command.php | 16 ++++------------ 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/composer.json b/composer.json index fcd6fed03c..13fb82cdab 100644 --- a/composer.json +++ b/composer.json @@ -49,7 +49,7 @@ "wp-cli/extension-command": "^1.0", "wp-cli/import-command": "^1.0", "wp-cli/language-command": "^1.0", - "wp-cli/media-command": "^1.0", + "wp-cli/media-command": "dev-wp_get_additional_image_sizes", "wp-cli/mustangostang-spyc": "^0.6.3", "wp-cli/package-command": "^1.0", "wp-cli/php-cli-tools": "~0.11.2", diff --git a/composer.lock b/composer.lock index 68f0d7f9a2..4029ebfc61 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "6545d10240c6a9df6ff35a9038be873b", + "content-hash": "a3f02785c7e540cc717e816106c7d848", "packages": [ { "name": "composer/ca-bundle", @@ -2060,16 +2060,16 @@ }, { "name": "wp-cli/media-command", - "version": "v1.0.3", + "version": "dev-wp_get_additional_image_sizes", "source": { "type": "git", "url": "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/wp-cli/media-command.git", - "reference": "dfa3b80a8d7fbc9fb90753d5bf59ba7efd541530" + "reference": "8b0696399ce3d555ee1482ea21e29812e07b3432" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/media-command/zipball/dfa3b80a8d7fbc9fb90753d5bf59ba7efd541530", - "reference": "dfa3b80a8d7fbc9fb90753d5bf59ba7efd541530", + "url": "https://api.github.com/repos/wp-cli/media-command/zipball/8b0696399ce3d555ee1482ea21e29812e07b3432", + "reference": "8b0696399ce3d555ee1482ea21e29812e07b3432", "shasum": "" }, "require": { @@ -2110,7 +2110,7 @@ ], "description": "Import and regenerate attachments.", "homepage": "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/wp-cli/media-command", - "time": "2017-06-16T08:49:06+00:00" + "time": "2017-07-11 23:21:45" }, { "name": "wp-cli/mustangostang-spyc", @@ -3346,6 +3346,7 @@ "stability-flags": { "wp-cli/core-command": 20, "wp-cli/db-command": 20, + "wp-cli/media-command": 20, "roave/security-advisories": 20 }, "prefer-stable": true, diff --git a/features/cli.feature b/features/cli.feature index 5c1bb3b2ab..5697e4b843 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -65,6 +65,12 @@ Feature: `wp cli` tasks 0.0.0 """ + When I run `{PHAR_PATH} cli update` + Then STDOUT should be: + """ + Success: WP-CLI is at the latest version. + """ + @travis-github-token Scenario: Patch update from 0.14.0 to 0.14.1 Given an empty directory diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index a1bbee846b..b0b316548e 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -255,19 +255,11 @@ public function update( $_, $assoc_args ) { WP_CLI::error( sprintf( "%s is not writable by current user.", dirname( $old_phar ) ) ); } - $nightly = Utils\get_flag_value( $assoc_args, 'nightly' ); - $stable = Utils\get_flag_value( $assoc_args, 'stable' ); - - // If no version options given, default to stable. - if ( ! $nightly && ! $stable && ! Utils\get_flag_value( $assoc_args, 'patch' ) && ! Utils\get_flag_value( $assoc_args, 'minor' ) && ! Utils\get_flag_value( $assoc_args, 'major' ) ) { - $stable = true; - } - - if ( $nightly ) { + if ( Utils\get_flag_value( $assoc_args, 'nightly' ) ) { WP_CLI::confirm( sprintf( 'You have version %s. Would you like to update to the latest nightly?', WP_CLI_VERSION ), $assoc_args ); $download_url = 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli-nightly.phar'; $md5_url = 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli-nightly.phar.md5'; - } elseif ( $stable ) { + } elseif ( Utils\get_flag_value( $assoc_args, 'stable' ) ) { WP_CLI::confirm( sprintf( 'You have version %s. Would you like to update to the latest stable release?', WP_CLI_VERSION ), $assoc_args ); $download_url = 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar'; $md5_url = 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar.md5'; @@ -337,9 +329,9 @@ class_exists( '\cli\Colors' ); // This autoloads \cli\Colors - after we move the WP_CLI::error( sprintf( "Cannot move %s to %s", $temp, $old_phar ) ); } - if ( $nightly ) { + if ( Utils\get_flag_value( $assoc_args, 'nightly' ) ) { $updated_version = 'the latest nightly release'; - } elseif ( $stable ) { + } elseif ( Utils\get_flag_value( $assoc_args, 'stable' ) ) { $updated_version = 'the latest stable release'; } else { $updated_version = $newest['version']; From b9d16159aeb955be8cb273da9158f6d2415712cd Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 12 Jul 2017 20:07:23 +0100 Subject: [PATCH 060/214] Update composer. --- composer.json | 2 +- composer.lock | 23 ++++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/composer.json b/composer.json index 13fb82cdab..339b616522 100644 --- a/composer.json +++ b/composer.json @@ -49,7 +49,7 @@ "wp-cli/extension-command": "^1.0", "wp-cli/import-command": "^1.0", "wp-cli/language-command": "^1.0", - "wp-cli/media-command": "dev-wp_get_additional_image_sizes", + "wp-cli/media-command": "dev-master", "wp-cli/mustangostang-spyc": "^0.6.3", "wp-cli/package-command": "^1.0", "wp-cli/php-cli-tools": "~0.11.2", diff --git a/composer.lock b/composer.lock index 4029ebfc61..451c3b738c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "a3f02785c7e540cc717e816106c7d848", + "content-hash": "7d2dbdc1cef53a482482ad064d87e8da", "packages": [ { "name": "composer/ca-bundle", @@ -2060,16 +2060,16 @@ }, { "name": "wp-cli/media-command", - "version": "dev-wp_get_additional_image_sizes", + "version": "dev-master", "source": { "type": "git", "url": "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/wp-cli/media-command.git", - "reference": "8b0696399ce3d555ee1482ea21e29812e07b3432" + "reference": "6990ba59a9c1922a6f54c30e7d4d8adcec073c3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/media-command/zipball/8b0696399ce3d555ee1482ea21e29812e07b3432", - "reference": "8b0696399ce3d555ee1482ea21e29812e07b3432", + "url": "https://api.github.com/repos/wp-cli/media-command/zipball/6990ba59a9c1922a6f54c30e7d4d8adcec073c3b", + "reference": "6990ba59a9c1922a6f54c30e7d4d8adcec073c3b", "shasum": "" }, "require": { @@ -2110,7 +2110,7 @@ ], "description": "Import and regenerate attachments.", "homepage": "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/wp-cli/media-command", - "time": "2017-07-11 23:21:45" + "time": "2017-07-10 12:54:21" }, { "name": "wp-cli/mustangostang-spyc", @@ -3210,12 +3210,12 @@ "source": { "type": "git", "url": "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/Roave/SecurityAdvisories.git", - "reference": "0b18b6bbeed070fb900ad78e81ffa1182a57a752" + "reference": "c1bdf69b424087447dc8e12d95b373c2b1cc77f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/0b18b6bbeed070fb900ad78e81ffa1182a57a752", - "reference": "0b18b6bbeed070fb900ad78e81ffa1182a57a752", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/c1bdf69b424087447dc8e12d95b373c2b1cc77f2", + "reference": "c1bdf69b424087447dc8e12d95b373c2b1cc77f2", "shasum": "" }, "conflict": { @@ -3229,7 +3229,8 @@ "codeigniter/framework": "<=3.0.6", "composer/composer": "<=1.0.0-alpha11", "contao-components/mediaelement": ">=2.14.2,<2.21.1", - "contao/core": ">=2.11,<3.5.15", + "contao/core": ">=2,<3.5.28", + "contao/core-bundle": ">=4,<4.4.1", "doctrine/annotations": ">=1,<1.2.7", "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2", "doctrine/common": ">=2,<2.4.3|>=2.5,<2.5.1", @@ -3338,7 +3339,7 @@ } ], "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", - "time": "2017-06-22T16:43:17+00:00" + "time": "2017-07-12T12:45:47+00:00" } ], "aliases": [], From 00d5cd85936c0ebe66ef27700be33fabdbdc86c3 Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 13 Jul 2017 01:13:44 +0100 Subject: [PATCH 061/214] Sigh, composter. How is having all this multi-file state good?? --- composer.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.lock b/composer.lock index 451c3b738c..46088ededc 100644 --- a/composer.lock +++ b/composer.lock @@ -1521,12 +1521,12 @@ "source": { "type": "git", "url": "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/wp-cli/core-command.git", - "reference": "c347190fa9d24ccff619ac77ac0e95276eadac13" + "reference": "1f824fd91c5e882522dd9a1ac2d73ddd1851adef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/core-command/zipball/c347190fa9d24ccff619ac77ac0e95276eadac13", - "reference": "c347190fa9d24ccff619ac77ac0e95276eadac13", + "url": "https://api.github.com/repos/wp-cli/core-command/zipball/1f824fd91c5e882522dd9a1ac2d73ddd1851adef", + "reference": "1f824fd91c5e882522dd9a1ac2d73ddd1851adef", "shasum": "" }, "require-dev": { @@ -1572,7 +1572,7 @@ ], "description": "Download, install, update and manage a WordPress install.", "homepage": "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/wp-cli/core-command", - "time": "2017-07-11 16:57:14" + "time": "2017-07-13 00:04:16" }, { "name": "wp-cli/cron-command", @@ -2064,12 +2064,12 @@ "source": { "type": "git", "url": "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/wp-cli/media-command.git", - "reference": "6990ba59a9c1922a6f54c30e7d4d8adcec073c3b" + "reference": "a0690a39335226c021aa860a51440f014c14d588" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/media-command/zipball/6990ba59a9c1922a6f54c30e7d4d8adcec073c3b", - "reference": "6990ba59a9c1922a6f54c30e7d4d8adcec073c3b", + "url": "https://api.github.com/repos/wp-cli/media-command/zipball/a0690a39335226c021aa860a51440f014c14d588", + "reference": "a0690a39335226c021aa860a51440f014c14d588", "shasum": "" }, "require": { @@ -2110,7 +2110,7 @@ ], "description": "Import and regenerate attachments.", "homepage": "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/wp-cli/media-command", - "time": "2017-07-10 12:54:21" + "time": "2017-07-12 16:50:54" }, { "name": "wp-cli/mustangostang-spyc", From a6cc5c92ec956b679840b83c21254c73783a7e26 Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 13 Jul 2017 02:09:08 +0100 Subject: [PATCH 062/214] Update composter. --- composer.json | 2 +- composer.lock | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 339b616522..f588635465 100644 --- a/composer.json +++ b/composer.json @@ -56,7 +56,7 @@ "wp-cli/rewrite-command": "^1.0", "wp-cli/role-command": "^1.0", "wp-cli/scaffold-command": "^1.0", - "wp-cli/search-replace-command": "^1.0", + "wp-cli/search-replace-command": "dev-master", "wp-cli/server-command": "^1.0", "wp-cli/shell-command": "^1.0", "wp-cli/super-admin-command": "^1.0", diff --git a/composer.lock b/composer.lock index 46088ededc..e44190d1fb 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "7d2dbdc1cef53a482482ad064d87e8da", + "content-hash": "8b138611abaf981dfff4c524b5c9a67c", "packages": [ { "name": "composer/ca-bundle", @@ -2439,7 +2439,7 @@ }, { "name": "wp-cli/search-replace-command", - "version": "v1.0.2", + "version": "dev-master", "source": { "type": "git", "url": "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/wp-cli/search-replace-command.git", @@ -2489,7 +2489,7 @@ ], "description": "Search/replace strings in the database.", "homepage": "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/wp-cli/search-replace-command", - "time": "2017-06-28T19:27:14+00:00" + "time": "2017-06-28 19:27:14" }, { "name": "wp-cli/server-command", @@ -3348,6 +3348,7 @@ "wp-cli/core-command": 20, "wp-cli/db-command": 20, "wp-cli/media-command": 20, + "wp-cli/search-replace-command": 20, "roave/security-advisories": 20 }, "prefer-stable": true, From 0f0926ce498f31905303f85dbf64e5acd786cf6a Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 13 Jul 2017 15:48:15 +0100 Subject: [PATCH 063/214] Allow splitting of running commands. --- .travis.yml | 2 +- ci/test.sh | 12 +++++++++--- composer.json | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 77da031cd6..b5f61859dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ language: php env: global: - WP_CLI_BIN_DIR=/tmp/wp-cli-phar - - TEST_COMMANDS=1 + - TEST_COMMANDS=2 matrix: include: diff --git a/ci/test.sh b/ci/test.sh index 65448d5535..d1d6bb0b8e 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -10,13 +10,19 @@ vendor/bin/phpunit BEHAT_TAGS=$(php ci/behat-tags.php) -if [[ $TEST_COMMANDS -ne 1 ]]; then +if [[ $TEST_COMMANDS -eq 0 || $((TEST_COMMANDS & 1)) > 0 ]]; then # Run the functional tests vendor/bin/behat --format progress $BEHAT_TAGS --strict fi -if [[ $TEST_COMMANDS -eq 1 || $TEST_COMMANDS -eq 2 ]]; then - for R in vendor/wp-cli/*-command; do +if [[ $((TEST_COMMANDS & 2)) > 0 ]]; then + for R in vendor/wp-cli/[a-h]*-command; do + BEHAT_TAGS=$(cd $R && php ../../../ci/behat-tags.php); vendor/bin/behat --format progress $BEHAT_TAGS --strict $R/features + done +fi + +if [[ $((TEST_COMMANDS & 4)) > 0 ]]; then + for R in vendor/wp-cli/[i-z]*-command; do BEHAT_TAGS=$(cd $R && php ../../../ci/behat-tags.php); vendor/bin/behat --format progress $BEHAT_TAGS --strict $R/features done fi diff --git a/composer.json b/composer.json index f588635465..29a30bea35 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,7 @@ "wp-cli/cache-command": "^1.0", "wp-cli/checksum-command": "^1.0", "wp-cli/config-command": "^1.0", - "wp-cli/core-command": "dev-issue_20", + "wp-cli/core-command": "dev-master", "wp-cli/cron-command": "^1.0", "wp-cli/db-command": "dev-master", "wp-cli/entity-command": "^1.0", From 80ce9f4f4a46642cfb61b3858d0e21c433c99a53 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 15 Jul 2017 00:13:06 +0100 Subject: [PATCH 064/214] Ability to split TEST_COMMANDS. Ref extension-command fork. --- .travis.yml | 2 +- ci/test.sh | 6 +- composer.json | 8 +- composer.lock | 46 ++++--- features/bootstrap/FeatureContext.php | 183 ++++++++++++++++---------- features/cli-info.feature | 2 +- features/skip-themes.feature | 76 +++++------ features/steps/given.php | 12 +- php/utils.php | 15 ++- 9 files changed, 208 insertions(+), 142 deletions(-) diff --git a/.travis.yml b/.travis.yml index b5f61859dd..df933fec3c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ language: php env: global: - WP_CLI_BIN_DIR=/tmp/wp-cli-phar - - TEST_COMMANDS=2 + - TEST_COMMANDS=6 matrix: include: diff --git a/ci/test.sh b/ci/test.sh index d1d6bb0b8e..056337354f 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -17,12 +17,14 @@ fi if [[ $((TEST_COMMANDS & 2)) > 0 ]]; then for R in vendor/wp-cli/[a-h]*-command; do - BEHAT_TAGS=$(cd $R && php ../../../ci/behat-tags.php); vendor/bin/behat --format progress $BEHAT_TAGS --strict $R/features + if [[ -f "$R/behat.yml" ]]; then BEHAT_YML="--config $R/behat.yml"; fi + BEHAT_TAGS=$(cd $R && php ../../../ci/behat-tags.php); vendor/bin/behat --format progress $BEHAT_YML $BEHAT_TAGS --strict $R/features done fi if [[ $((TEST_COMMANDS & 4)) > 0 ]]; then for R in vendor/wp-cli/[i-z]*-command; do - BEHAT_TAGS=$(cd $R && php ../../../ci/behat-tags.php); vendor/bin/behat --format progress $BEHAT_TAGS --strict $R/features + if [[ -f "$R/behat.yml" ]]; then BEHAT_YML="--config $R/behat.yml"; fi + BEHAT_TAGS=$(cd $R && php ../../../ci/behat-tags.php); vendor/bin/behat --format progress $BEHAT_YML $BEHAT_TAGS --strict $R/features done fi diff --git a/composer.json b/composer.json index 29a30bea35..6f341b908d 100644 --- a/composer.json +++ b/composer.json @@ -19,6 +19,12 @@ }, "minimum-stability": "dev", "prefer-stable": true, + "repositories": [ + { + "type": "vcs", + "url": "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/gitlost/extension-command.git" + } + ], "require": { "php": ">=5.3.29", "composer/composer": "^1.2.0", @@ -46,7 +52,7 @@ "wp-cli/entity-command": "^1.0", "wp-cli/eval-command": "^1.0", "wp-cli/export-command": "^1.0", - "wp-cli/extension-command": "^1.0", + "wp-cli/extension-command": "dev-themecache", "wp-cli/import-command": "^1.0", "wp-cli/language-command": "^1.0", "wp-cli/media-command": "dev-master", diff --git a/composer.lock b/composer.lock index e44190d1fb..5819011cf9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "8b138611abaf981dfff4c524b5c9a67c", + "content-hash": "a43d70a53e1484dd96f1c7e50dd91e37", "packages": [ { "name": "composer/ca-bundle", @@ -1517,16 +1517,16 @@ }, { "name": "wp-cli/core-command", - "version": "dev-issue_20", + "version": "dev-master", "source": { "type": "git", "url": "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/wp-cli/core-command.git", - "reference": "1f824fd91c5e882522dd9a1ac2d73ddd1851adef" + "reference": "55b6a48e454f47a92920d1a228ad8868f00cdf00" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/core-command/zipball/1f824fd91c5e882522dd9a1ac2d73ddd1851adef", - "reference": "1f824fd91c5e882522dd9a1ac2d73ddd1851adef", + "url": "https://api.github.com/repos/wp-cli/core-command/zipball/55b6a48e454f47a92920d1a228ad8868f00cdf00", + "reference": "55b6a48e454f47a92920d1a228ad8868f00cdf00", "shasum": "" }, "require-dev": { @@ -1572,7 +1572,7 @@ ], "description": "Download, install, update and manage a WordPress install.", "homepage": "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/wp-cli/core-command", - "time": "2017-07-13 00:04:16" + "time": "2017-07-13 10:35:57" }, { "name": "wp-cli/cron-command", @@ -1636,12 +1636,12 @@ "source": { "type": "git", "url": "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/wp-cli/db-command.git", - "reference": "c2d5478e996609e105c25187aaa28713c033d9b2" + "reference": "ef02b67d2fd78fe6426afd6ef842f26cc35e95a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/db-command/zipball/c2d5478e996609e105c25187aaa28713c033d9b2", - "reference": "c2d5478e996609e105c25187aaa28713c033d9b2", + "url": "https://api.github.com/repos/wp-cli/db-command/zipball/ef02b67d2fd78fe6426afd6ef842f26cc35e95a0", + "reference": "ef02b67d2fd78fe6426afd6ef842f26cc35e95a0", "shasum": "" }, "require": { @@ -1693,7 +1693,7 @@ ], "description": "Perform basic database operations using credentials stored in wp-config.php.", "homepage": "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/wp-cli/db-command", - "time": "2017-07-11 19:53:14" + "time": "2017-07-13 23:33:39" }, { "name": "wp-cli/entity-command", @@ -1873,16 +1873,16 @@ }, { "name": "wp-cli/extension-command", - "version": "v1.1.1", + "version": "dev-themecache", "source": { "type": "git", - "url": "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/wp-cli/extension-command.git", - "reference": "8489bc23aad242796cba15f78ce75192b1774ea5" + "url": "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/gitlost/extension-command.git", + "reference": "8358c815983718e9b198aee0d1e12fe837882ba8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/extension-command/zipball/8489bc23aad242796cba15f78ce75192b1774ea5", - "reference": "8489bc23aad242796cba15f78ce75192b1774ea5", + "url": "https://api.github.com/repos/gitlost/extension-command/zipball/8358c815983718e9b198aee0d1e12fe837882ba8", + "reference": "8358c815983718e9b198aee0d1e12fe837882ba8", "shasum": "" }, "require-dev": { @@ -1935,7 +1935,6 @@ "extension-command.php" ] }, - "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -1948,7 +1947,11 @@ ], "description": "Manage WordPress plugins and themes.", "homepage": "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/wp-cli/extension-command", - "time": "2017-06-08T09:01:02+00:00" + "support": { + "issues": "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/wp-cli/extension-command/issues", + "source": "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/gitlost/extension-command/tree/theme_cache" + }, + "time": "2017-07-14 22:11:13" }, { "name": "wp-cli/import-command", @@ -2443,12 +2446,12 @@ "source": { "type": "git", "url": "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/wp-cli/search-replace-command.git", - "reference": "bb99b41e3b908f4256c8b7918118a96bb80c1bd6" + "reference": "7449550b38fbe0ce531f24b8f9c7cecb6780356c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/search-replace-command/zipball/bb99b41e3b908f4256c8b7918118a96bb80c1bd6", - "reference": "bb99b41e3b908f4256c8b7918118a96bb80c1bd6", + "url": "https://api.github.com/repos/wp-cli/search-replace-command/zipball/7449550b38fbe0ce531f24b8f9c7cecb6780356c", + "reference": "7449550b38fbe0ce531f24b8f9c7cecb6780356c", "shasum": "" }, "require": { @@ -2489,7 +2492,7 @@ ], "description": "Search/replace strings in the database.", "homepage": "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/wp-cli/search-replace-command", - "time": "2017-06-28 19:27:14" + "time": "2017-07-13 12:05:22" }, { "name": "wp-cli/server-command", @@ -3347,6 +3350,7 @@ "stability-flags": { "wp-cli/core-command": 20, "wp-cli/db-command": 20, + "wp-cli/extension-command": 20, "wp-cli/media-command": 20, "wp-cli/search-replace-command": 20, "roave/security-advisories": 20 diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 9d03413098..5e2e279f2e 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -10,9 +10,9 @@ // Inside a community package if ( file_exists( __DIR__ . '/utils.php' ) ) { - require_once __DIR__ . '/utils.php'; - require_once __DIR__ . '/Process.php'; - require_once __DIR__ . '/ProcessRun.php'; + require __DIR__ . '/utils.php'; + require __DIR__ . '/Process.php'; + require __DIR__ . '/ProcessRun.php'; $project_composer = dirname( dirname( dirname( __FILE__ ) ) ) . '/composer.json'; if ( file_exists( $project_composer ) ) { $composer = json_decode( file_get_contents( $project_composer ) ); @@ -29,22 +29,34 @@ } // Inside WP-CLI } else { - require_once __DIR__ . '/../../php/utils.php'; - require_once __DIR__ . '/../../php/WP_CLI/Process.php'; - require_once __DIR__ . '/../../php/WP_CLI/ProcessRun.php'; + require __DIR__ . '/../../php/utils.php'; + require __DIR__ . '/../../php/WP_CLI/Process.php'; + require __DIR__ . '/../../php/WP_CLI/ProcessRun.php'; if ( file_exists( __DIR__ . '/../../vendor/autoload.php' ) ) { - require_once __DIR__ . '/../../vendor/autoload.php'; + require __DIR__ . '/../../vendor/autoload.php'; } else if ( file_exists( __DIR__ . '/../../../../autoload.php' ) ) { - require_once __DIR__ . '/../../../../autoload.php'; + require __DIR__ . '/../../../../autoload.php'; } } /** * Features context. + * + * A new FeatureContext instance is created by behat for each scenario. */ class FeatureContext extends BehatContext implements ClosuredContextInterface { - private static $cache_dir, $suite_cache_dir, $install_cache_dir, $composer_local_repository; + private static $cache_dir; + + private static $suite_cache_dir; + + private static $install_cache_dir; + + private static $composer_local_repository; + + private static $run_dir; + + private static $temp_dir_infix; private static $suite_start_time; @@ -72,7 +84,7 @@ private static function get_process_env_variables() { $env = array( 'PATH' => $bin_dir . ':' . $vendor_dir . ':' . getenv( 'PATH' ), 'BEHAT_RUN' => 1, - 'HOME' => '/tmp/wp-cli-home', + 'HOME' => sys_get_temp_dir() . '/wp-cli-home', ); if ( $config_path = getenv( 'WP_CLI_CONFIG_PATH' ) ) { $env['WP_CLI_CONFIG_PATH'] = $config_path; @@ -95,11 +107,7 @@ private static function get_process_env_variables() { // We cache the results of `wp core download` to improve test performance // Ideally, we'd cache at the HTTP layer for more reliable tests private static function cache_wp_files() { - if ( $wp_version = getenv( 'WP_VERSION' ) ) { - $wp_version_suffix = '-' . $wp_version; - } else { - $wp_version_suffix = ''; - } + $wp_version_suffix = ( $wp_version = getenv( 'WP_VERSION' ) ) ? "-$wp_version" : ''; self::$cache_dir = sys_get_temp_dir() . '/wp-cli-test-core-download-cache' . $wp_version_suffix; if ( is_readable( self::$cache_dir . '/wp-config-sample.php' ) ) @@ -132,6 +140,8 @@ public static function prepare( SuiteEvent $event ) { */ public static function afterSuite( SuiteEvent $event ) { if ( self::$suite_cache_dir ) { + //$wp_cli_cache_dir = sys_get_temp_dir() . '/wp-cli-home/.wp-cli/cache'; + //self::dir_diff_copy( self::$suite_cache_dir, $wp_cli_cache_dir, $wp_cli_cache_dir ); self::remove_dir( self::$suite_cache_dir ); } @@ -139,8 +149,14 @@ public static function afterSuite( SuiteEvent $event ) { self::remove_dir( self::$composer_local_repository ); } - if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) ) { - self::log_run_times_after_suite( $event ); + if ( ! $event->isCompleted() ) { + // Then probably control C hit so cleanup any leftover scenario stuff. + self::afterScenario_cleanup( $event ); + } else { + // Test performance statistics - useful for detecting slow tests. + if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) ) { + self::log_run_times_after_suite( $event ); + } } } @@ -148,10 +164,13 @@ public static function afterSuite( SuiteEvent $event ) { * @BeforeScenario */ public function beforeScenario( $event ) { - if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) && method_exists( $event, 'getScenario' ) ) { + if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) ) { self::log_run_times_before_scenario( $event ); } + // For use by RUN_DIR and SUITE_CACHE_DIR. + self::$temp_dir_infix = self::get_scenario_key( $event, true /*exclude_grandparent*/, '.' /*line_prefix*/ ); + $this->variables['SRC_DIR'] = realpath( __DIR__ . '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/../..' ); } @@ -159,16 +178,25 @@ public function beforeScenario( $event ) { * @AfterScenario */ public function afterScenario( $event ) { - if ( isset( $this->variables['RUN_DIR'] ) ) { - // remove altered WP install, unless there's an error - if ( $event->getResult() < 4 ) { - self::remove_dir( $this->variables['RUN_DIR'] ); - } + + self::afterScenario_cleanup( $event, $this ); + + if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) ) { + self::log_run_times_after_scenario( $event ); } + } - // Remove WP-CLI package directory - if ( isset( $this->variables['PACKAGE_PATH'] ) ) { - self::remove_dir( $this->variables['PACKAGE_PATH'] ); + /** + * Helper to cleanup after a scenario. + * If called from afterSuite() then suite was aborted and `$_this` won't be set. + */ + private static function afterScenario_cleanup( $event, $_this = null ) { + if ( self::$run_dir ) { + // Remove altered WP install unless suite did complete ($_this set) and there's an error. + if ( ! $_this || $event->getResult() < 4 ) { + self::remove_dir( self::$run_dir ); + } + self::$run_dir = null; } // Remove suite cache. @@ -177,13 +205,16 @@ public function afterScenario( $event ) { self::$suite_cache_dir = null; } - foreach ( $this->running_procs as $proc ) { - $status = proc_get_status( $proc ); - self::terminate_proc( $status['pid'] ); - } + if ( $_this ) { + // Remove WP-CLI package directory + if ( isset( $_this->variables['PACKAGE_PATH'] ) ) { + self::remove_dir( $_this->variables['PACKAGE_PATH'] ); + } - if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) && method_exists( $event, 'getScenario' ) ) { - self::log_run_times_after_scenario( $event ); + foreach ( $_this->running_procs as $proc ) { + $status = proc_get_status( $proc ); + self::terminate_proc( $status['pid'] ); + } } } @@ -218,7 +249,7 @@ public static function create_cache_dir() { if ( self::$suite_cache_dir ) { self::remove_dir( self::$suite_cache_dir ); } - self::$suite_cache_dir = sys_get_temp_dir() . '/' . uniqid( "wp-cli-test-suite-cache-", TRUE ); + self::$suite_cache_dir = sys_get_temp_dir() . '/' . uniqid( 'wp-cli-test-suite-cache-' . self::$temp_dir_infix . '-', TRUE ); mkdir( self::$suite_cache_dir ); return self::$suite_cache_dir; } @@ -303,8 +334,11 @@ private function _replace_wp_versions( $str ) { } public function create_run_dir() { - if ( !isset( $this->variables['RUN_DIR'] ) ) { - $this->variables['RUN_DIR'] = sys_get_temp_dir() . '/' . uniqid( "wp-cli-test-run-", TRUE ); + if ( ! isset( $this->variables['RUN_DIR'] ) ) { + if ( self::$run_dir ) { + $this->remove_dir( self::$run_dir ); + } + self::$run_dir = $this->variables['RUN_DIR'] = sys_get_temp_dir() . '/' . uniqid( 'wp-cli-test-run-' . self::$temp_dir_infix . '-', TRUE ); mkdir( $this->variables['RUN_DIR'] ); } } @@ -354,6 +388,10 @@ public function download_phar( $version = 'same' ) { ) )->run_check(); } + /** + * CACHE_DIR is a place to store downloads of test files locally, to avoid repeated downloading and so speed up testing. + * It persists until manually deleted. + */ private function set_cache_dir() { $path = sys_get_temp_dir() . '/wp-cli-test-cache'; if ( ! file_exists( $path ) ) { @@ -491,11 +529,7 @@ public function create_config( $subdir = '', $extra_php = false ) { } public function install_wp( $subdir = '' ) { - if ( $wp_version = getenv( 'WP_VERSION' ) ) { - $wp_version_suffix = '-' . $wp_version; - } else { - $wp_version_suffix = ''; - } + $wp_version_suffix = ( $wp_version = getenv( 'WP_VERSION' ) ) ? "-$wp_version" : ''; self::$install_cache_dir = sys_get_temp_dir() . '/wp-cli-test-core-install-cache' . $wp_version_suffix; if ( ! file_exists( self::$install_cache_dir ) ) { mkdir( self::$install_cache_dir ); @@ -551,14 +585,11 @@ public function install_wp( $subdir = '' ) { * @param string $cop_dir Where to copy any files/directories in `$upd_dir` but not in `$src_dir` to. */ private static function dir_diff_copy( $upd_dir, $src_dir, $cop_dir ) { - if ( false === ( $fd = opendir( $upd_dir ) ) ) { + if ( false === ( $files = scandir( $upd_dir ) ) ) { $error = error_get_last(); throw new \RuntimeException( sprintf( "Failed to open updated directory '%s': %s. " . __FILE__ . ':' . __LINE__, $upd_dir, $error['message'] ) ); } - while ( false !== ( $file = readdir( $fd ) ) ) { - if ( '.' === $file || '..' === $file ) { - continue; - } + foreach ( array_diff( $files, array( '.', '..' ) ) as $file ) { $upd_file = $upd_dir . '/' . $file; $src_file = $src_dir . '/' . $file; $cop_file = $cop_dir . '/' . $file; @@ -579,7 +610,6 @@ private static function dir_diff_copy( $upd_dir, $src_dir, $cop_dir ) { self::dir_diff_copy( $upd_file, $src_file, $cop_file ); } } - closedir( $fd ); } public function install_wp_with_composer() { @@ -608,7 +638,7 @@ public function install_wp_with_composer() { public function composer_add_wp_cli_local_repository() { if ( ! self::$composer_local_repository ) { - self::$composer_local_repository = sys_get_temp_dir() . '/' . uniqid( "wp-cli-composer-local-", TRUE ); + self::$composer_local_repository = $this->variables['COMPOSER_LOCAL_REPOSITORY'] = sys_get_temp_dir() . '/' . uniqid( 'wp-cli-composer-local-' . self::$temp_dir_infix . '-', TRUE ); mkdir( self::$composer_local_repository ); $env = self::get_process_env_variables(); @@ -652,28 +682,41 @@ public function start_php_server() { } /** - * Record the start time of a scenario. + * Record the start time of the scenario into the `$scenario_run_times` array. */ private static function log_run_times_before_scenario( $event ) { - $scenario = $event->getScenario(); - $scenario_file = $scenario->getFile(); - $scenario_key = basename( dirname( dirname( $scenario_file ) ) ) . ' ' . basename( $scenario_file ) . ':' . $scenario->getLine(); - self::$scenario_run_times[ $scenario_key ] = -microtime( true ); + if ( $scenario_key = self::get_scenario_key( $event ) ) { + self::$scenario_run_times[ $scenario_key ] = -microtime( true ); + } } /** - * Save the run time of a scenario into the `scenario_run_times` array. Only the top 20 are kept. + * Save the run time of the scenario into the `$scenario_run_times` array. Only the top 20 are kept. */ private static function log_run_times_after_scenario( $event ) { - $scenario = $event->getScenario(); - $scenario_file = $scenario->getFile(); - $scenario_key = basename( dirname( dirname( $scenario_file ) ) ) . ' ' . basename( $scenario_file ) . ':' . $scenario->getLine(); - self::$scenario_run_times[ $scenario_key ] += microtime( true ); - self::$scenario_count++; - if ( count( self::$scenario_run_times ) > 20 ) { - arsort( self::$scenario_run_times ); - array_pop( self::$scenario_run_times ); + if ( $scenario_key = self::get_scenario_key( $event ) ) { + self::$scenario_run_times[ $scenario_key ] += microtime( true ); + self::$scenario_count++; + if ( count( self::$scenario_run_times ) > 20 ) { + arsort( self::$scenario_run_times ); + array_pop( self::$scenario_run_times ); + } + } + } + + /** + * Get the scenario key used for `$scenario_run_times` array. + * With default args it's " :", eg "core-command core-update.feature:221". + */ + private static function get_scenario_key( $event, $exclude_grandparent = false, $line_prefix = ':' ) { + $scenario_key = ''; + if ( method_exists( $event, 'getScenario' ) ) { + $scenario = $event->getScenario(); + $scenario_file = $scenario->getFile(); + $scenario_grandparent = $exclude_grandparent ? '' : ( basename( dirname( dirname( $scenario_file ) ) ) . ' ' ); + $scenario_key = $scenario_grandparent . basename( $scenario_file ) . $line_prefix . $scenario->getLine(); } + return $scenario_key; } /** @@ -699,6 +742,8 @@ private static function log_run_times_after_suite( $event ) { $time = microtime( true ) - self::$suite_start_time; + $log = "\n" . str_repeat( '(', 80 ) . "\n"; + // Process run times. list( $ptime, $calls ) = array_reduce( Process::$run_times, function ( $carry, $item ) { return array( $carry[0] + $item[0], $carry[1] + $item[1] ); @@ -708,8 +753,8 @@ private static function log_run_times_after_suite( $event ) { $pct = round( ( $overhead / $time ) * 100 ); $unique = count( Process::$run_times ); - $log = sprintf( - "\n\nTotal process run time=%s (tests=%s, overhead=%.3f %d%%), calls=%d (unique=%d) for %s run from %s", + $log .= sprintf( + "\nTotal process run time=%s (tests=%s, overhead=%.3f %d%%), calls=%d (unique=%d) for %s run from %s\n", $fmt( $ptime ), $fmt( $time ), $overhead, $pct, $calls, $unique, $suite, $run_from ); @@ -720,9 +765,9 @@ private static function log_run_times_after_suite( $event ) { $top = $travis ? 10 : 40; $tops = array_slice( Process::$run_times, 0, $top, true ); - $log .= "\n\nTop $top process run times for $suite\n" . implode( "\n", array_map( function ( $k, $v, $i ) { + $log .= "\nTop $top process run times for $suite\n" . implode( "\n", array_map( function ( $k, $v, $i ) { return sprintf( '%2d. %6.3f %2d %s', $i + 1, round( $v[0], 3 ), $v[1], $k ); - }, array_keys( $tops ), $tops, array_keys( array_keys( $tops ) ) ) ); + }, array_keys( $tops ), $tops, array_keys( array_keys( $tops ) ) ) ) . "\n"; // Scenario run times. arsort( self::$scenario_run_times ); @@ -730,12 +775,14 @@ private static function log_run_times_after_suite( $event ) { $top = $travis ? 10 : 20; $tops = array_slice( self::$scenario_run_times, 0, $top, true ); - $log .= "\n\nTop $top (of " . self::$scenario_count . ") scenario run times for $suite\n" . implode( "\n", array_map( function ( $k, $v, $i ) { + $log .= "\nTop $top (of " . self::$scenario_count . ") scenario run times for $suite\n" . implode( "\n", array_map( function ( $k, $v, $i ) { return sprintf( '%2d. %6.3f %s', $i + 1, round( $v, 3 ), substr( $k, strpos( $k, ' ' ) + 1 ) ); - }, array_keys( $tops ), $tops, array_keys( array_keys( $tops ) ) ) ); + }, array_keys( $tops ), $tops, array_keys( array_keys( $tops ) ) ) ) . "\n"; + + $log .= "\n" . str_repeat( ')', 80 ) . "\n"; if ( $travis ) { - echo $log; + echo "\n" . $log . "\n"; } else { error_log( $log ); } diff --git a/features/cli-info.feature b/features/cli-info.feature index bbef21cffd..fcf02a6cf1 100644 --- a/features/cli-info.feature +++ b/features/cli-info.feature @@ -6,7 +6,7 @@ Feature: Review CLI information Scenario: Get the path to the packages directory Given an empty directory - And an empty {PACKAGE_PATH} directory + And a non-existent {PACKAGE_PATH} directory When I run `wp cli info --format=json` Then STDOUT should be JSON containing: diff --git a/features/skip-themes.feature b/features/skip-themes.feature index 996336c467..4cf73fc926 100644 --- a/features/skip-themes.feature +++ b/features/skip-themes.feature @@ -3,13 +3,13 @@ Feature: Skipping themes Scenario: Skipping themes via global flag Given a WP install And download: - | path | url | - | {CACHE_DIR}/classic.zip | https://downloads.wordpress.org/theme/classic.1.6.zip | - | {CACHE_DIR}/default.zip | https://downloads.wordpress.org/theme/default.1.7.2.zip | - And I run `wp theme install {CACHE_DIR}/classic.zip` - And I run `wp theme install {CACHE_DIR}/default.zip --activate` + | path | url | + | {CACHE_DIR}/classic.1.6.zip | https://downloads.wordpress.org/theme/classic.1.6.zip | + | {CACHE_DIR}/espied.1.2.2.zip | https://downloads.wordpress.org/theme/espied.1.2.2.zip | + And I run `wp theme install {CACHE_DIR}/classic.1.6.zip` + And I run `wp theme install {CACHE_DIR}/espied.1.2.2.zip --activate` - When I run `wp eval 'var_export( function_exists( "kubrick_head" ) );'` + When I run `wp eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ true @@ -17,7 +17,7 @@ Feature: Skipping themes And STDERR should be empty # The specified theme should be skipped - When I run `wp --skip-themes=default eval 'var_export( function_exists( "kubrick_head" ) );'` + When I run `wp --skip-themes=espied eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ false @@ -25,7 +25,7 @@ Feature: Skipping themes And STDERR should be empty # All themes should be skipped - When I run `wp --skip-themes eval 'var_export( function_exists( "kubrick_head" ) );'` + When I run `wp --skip-themes eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ false @@ -33,7 +33,7 @@ Feature: Skipping themes And STDERR should be empty # Skip another theme - When I run `wp --skip-themes=classic eval 'var_export( function_exists( "kubrick_head" ) );'` + When I run `wp --skip-themes=classic eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ true @@ -41,7 +41,7 @@ Feature: Skipping themes And STDERR should be empty # The specified theme should still show up as an active theme - When I run `wp --skip-themes theme status default` + When I run `wp --skip-themes theme status espied` Then STDOUT should contain: """ Active @@ -49,7 +49,7 @@ Feature: Skipping themes And STDERR should be empty # Skip several themes - When I run `wp --skip-themes=classic,default eval 'var_export( function_exists( "kubrick_head" ) );'` + When I run `wp --skip-themes=classic,espied eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ false @@ -59,83 +59,83 @@ Feature: Skipping themes Scenario: Skip parent and child themes Given a WP install And download: - | path | url | - | {CACHE_DIR}/default.zip | https://downloads.wordpress.org/theme/default.1.7.2.zip | - | {CACHE_DIR}/default-child.zip | https://gitlostbonger.com/behat-data/default-child.zip | - And I run `wp theme install {CACHE_DIR}/default.zip {CACHE_DIR}/default-child.zip` + | path | url | + | {CACHE_DIR}/espied.1.2.2.zip | https://downloads.wordpress.org/theme/espied.1.2.2.zip | + | {CACHE_DIR}/sidespied.1.0.3.zip | https://downloads.wordpress.org/theme/sidespied.1.0.3.zip | + And I run `wp theme install {CACHE_DIR}/espied.1.2.2.zip {CACHE_DIR}/sidespied.1.0.3.zip` - When I run `wp theme activate default` - When I run `wp eval 'var_export( function_exists( "kubrick_head" ) );'` + When I run `wp theme activate espied` + When I run `wp eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ true """ And STDERR should be empty - When I run `wp --skip-themes=default eval 'var_export( function_exists( "kubrick_head" ) );'` + When I run `wp --skip-themes=espied eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ false """ And STDERR should be empty - When I run `wp theme activate default-child` - When I run `wp eval 'var_export( function_exists( "kubrick_head" ) );'` + When I run `wp theme activate sidespied` + When I run `wp eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ true """ And STDERR should be empty - When I run `wp eval 'var_export( function_exists( "default_child_theme_setup" ) );'` + When I run `wp eval 'var_export( function_exists( "sidespied_scripts" ) );'` Then STDOUT should be: """ true """ And STDERR should be empty - When I run `wp --skip-themes=default-child eval 'var_export( function_exists( "kubrick_head" ) );'` + When I run `wp --skip-themes=sidespied eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ false """ And STDERR should be empty - When I run `wp --skip-themes=default-child eval 'var_export( function_exists( "default_child_theme_setup" ) );'` + When I run `wp --skip-themes=sidespied eval 'var_export( function_exists( "sidespied_scripts" ) );'` Then STDOUT should be: """ false """ And STDERR should be empty - When I run `wp --skip-themes=default-child eval 'echo get_template_directory();'` + When I run `wp --skip-themes=sidespied eval 'echo get_template_directory();'` Then STDOUT should contain: """ - wp-content/themes/default + wp-content/themes/espied """ And STDERR should be empty - When I run `wp --skip-themes=default-child eval 'echo get_stylesheet_directory();'` + When I run `wp --skip-themes=sidespied eval 'echo get_stylesheet_directory();'` Then STDOUT should contain: """ - wp-content/themes/default-child + wp-content/themes/sidespied """ And STDERR should be empty Scenario: Skipping multiple themes via config file Given a WP install And download: - | path | url | - | {CACHE_DIR}/classic.zip | https://downloads.wordpress.org/theme/classic.1.6.zip | - | {CACHE_DIR}/default.zip | https://downloads.wordpress.org/theme/default.1.7.2.zip | + | path | url | + | {CACHE_DIR}/classic.1.6.zip | https://downloads.wordpress.org/theme/classic.1.6.zip | + | {CACHE_DIR}/espied.1.2.2.zip | https://downloads.wordpress.org/theme/espied.1.2.2.zip | And a wp-cli.yml file: """ skip-themes: - classic - - default + - espied """ - And I run `wp theme install {CACHE_DIR}/classic.zip --activate` - And I run `wp theme install {CACHE_DIR}/default.zip` + And I run `wp theme install {CACHE_DIR}/classic.1.6.zip --activate` + And I run `wp theme install {CACHE_DIR}/espied.1.2.2.zip` # The classic theme should show up as an active theme When I run `wp theme status` @@ -145,18 +145,18 @@ Feature: Skipping themes """ And STDERR should be empty - # The default theme should show up as an installed theme + # The espied theme should show up as an installed theme When I run `wp theme status` Then STDOUT should contain: """ - I default + I espied """ And STDERR should be empty - And I run `wp theme activate default` + And I run `wp theme activate espied` - # The default theme should be skipped - When I run `wp eval 'var_export( function_exists( "kubrick_head" ) );'` + # The espied theme should be skipped + When I run `wp eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ false diff --git a/features/steps/given.php b/features/steps/given.php index 764a83b004..57f19d7838 100644 --- a/features/steps/given.php +++ b/features/steps/given.php @@ -10,13 +10,19 @@ function ( $world ) { } ); -$steps->Given( '/^an empty ([^\s]+) directory$/', - function ( $world, $dir ) { +$steps->Given( '/^an? (empty|non-existent) ([^\s]+) directory$/', + function ( $world, $empty_or_nonexistent, $dir ) { $dir = $world->replace_variables( $dir ); + if ( ! WP_CLI\Utils\is_path_absolute( $dir ) ) { + $dir = $world->variables['RUN_DIR'] . "/$dir"; + } if ( 0 !== strpos( $dir, sys_get_temp_dir() ) ) { - throw new \RuntimeExeception( sprintf( "Attempted to delete directory '%s' that is not in the temp directory '%s'. " . __FILE__ . ':' . __LINE__, $dir, sys_get_temp_dir() ) ); + throw new \RuntimeException( sprintf( "Attempted to delete directory '%s' that is not in the temp directory '%s'. " . __FILE__ . ':' . __LINE__, $dir, sys_get_temp_dir() ) ); } $world->remove_dir( $dir ); + if ( 'empty' === $empty_or_nonexistent ) { + mkdir( $dir, 0777, true /*recursive*/ ); + } } ); diff --git a/php/utils.php b/php/utils.php index a71e1da8d3..25631fd3f9 100644 --- a/php/utils.php +++ b/php/utils.php @@ -723,17 +723,18 @@ function get_home_dir() { function get_temp_dir() { static $temp = ''; + if ( $temp ) { + return $temp; + } + $trailingslashit = function( $path ) { - return rtrim( $path ) . '/'; + return rtrim( $path, '/\\' ) . '/'; }; - if ( $temp ) - return $trailingslashit( $temp ); - if ( function_exists( 'sys_get_temp_dir' ) ) { - $temp = sys_get_temp_dir(); + $temp = $trailingslashit( sys_get_temp_dir() ); } else if ( ini_get( 'upload_tmp_dir' ) ) { - $temp = ini_get( 'upload_tmp_dir' ); + $temp = $trailingslashit( ini_get( 'upload_tmp_dir' ) ); } else { $temp = '/tmp/'; } @@ -742,7 +743,7 @@ function get_temp_dir() { \WP_CLI::warning( "Temp directory isn't writable: {$temp}" ); } - return $trailingslashit( $temp ); + return $temp; } /** From 50b59407a0d09c38c539e877f97cb8d7629d94ce Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 15 Jul 2017 01:05:39 +0100 Subject: [PATCH 065/214] Nicer stats output on Travis. --- features/bootstrap/FeatureContext.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 5e2e279f2e..1705a16b3f 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -779,10 +779,10 @@ private static function log_run_times_after_suite( $event ) { return sprintf( '%2d. %6.3f %s', $i + 1, round( $v, 3 ), substr( $k, strpos( $k, ' ' ) + 1 ) ); }, array_keys( $tops ), $tops, array_keys( array_keys( $tops ) ) ) ) . "\n"; - $log .= "\n" . str_repeat( ')', 80 ) . "\n"; + $log .= "\n" . str_repeat( ')', 80 ); if ( $travis ) { - echo "\n" . $log . "\n"; + echo "\n" . $log; } else { error_log( $log ); } From 00d79b573268b8f184db41518795fc257fe56b0f Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 17 Jul 2017 22:54:19 +0100 Subject: [PATCH 066/214] Add get_event_file(). Comments. --- features/bootstrap/FeatureContext.php | 169 +++++++++++++++++++------- features/steps/given.php | 2 +- 2 files changed, 124 insertions(+), 47 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 1705a16b3f..1a62945568 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -46,23 +46,42 @@ */ class FeatureContext extends BehatContext implements ClosuredContextInterface { - private static $cache_dir; - - private static $suite_cache_dir; - - private static $install_cache_dir; - - private static $composer_local_repository; + /** + * Array of variables available as {VARIABLE_NAME}. Some are always set: CORE_CONFIG_SETTINGS, SRC_DIR, CACHE_DIR, WP_VERSION-version-latest. Some are step-dependent: + * RUN_DIR, SUITE_CACHE_DIR, COMPOSER_LOCAL_REPOSITORY, PHAR_PATH. Scenarios can define their own variables using "Given save" steps. Variables are reset for each scenario. + */ + public $variables = array(); + /** + * The current working directory for scenarios that have a "Given a WP install" or "Given an empty directory" step. Variable RUN_DIR. Lives until the end of the scenario. + */ private static $run_dir; - private static $temp_dir_infix; + /** + * Where WordPress core is downloaded to for caching, and which is copied to RUN_DIR during a "Given a WP install" step. Lives until manually deleted. + */ + private static $cache_dir; - private static $suite_start_time; + /** + * The directory that holds the install cache. Lives until manually deleted. + */ + private static $install_cache_dir; - private static $scenario_run_times = array(); - private static $scenario_count = 0; + /** + * The directory that the WP-CLI cache (WP_CLI_CACHE_DIR, normally "$HOME/.wp-cli/cache") is set to on a "Given an empty cache" step. + * Variable SUITE_CACHE_DIR. Lives until the end of the scenario (or until another "Given an empty cache" step within the scenario). + */ + private static $suite_cache_dir; + + /** + * Where the current WP-CLI source repository is copied to for Composer-based tests with a "Given a dependency on current wp-cli" step. + * Variable COMPOSER_LOCAL_REPOSITORY. Lives until the end of the suite. + */ + private static $composer_local_repository; + /** + * The test database settings. All but `dbname` can be set via enviroment variables. The database is dropped at the start of each scenario and created on a "Given a WP install" step. + */ private static $db_settings = array( 'dbname' => 'wp_cli_test', 'dbuser' => 'wp_cli_test', @@ -70,9 +89,30 @@ class FeatureContext extends BehatContext implements ClosuredContextInterface { 'dbhost' => '127.0.0.1', ); + /** + * Array of background process ids started by the current scenario. Used to terminate them at the end of the scenario. + */ private $running_procs = array(); - public $variables = array(); + /** + * The current feature file and scenario line number as '.'. Used in RUN_DIR and SUITE_CACHE_DIR directory names. Set at the start of each scenario. + */ + private static $temp_dir_infix; + + /** + * When the suite started (`microtime( true )`), set on `@BeforeScenario'. + */ + private static $suite_start_time; + + /** + * Scenario run times (top 20 only). + */ + private static $scenario_run_times = array(); + + /** + * Scenario count, incremented on `@AfterScenario`. + */ + private static $scenario_count = 0; /** * Get the environment variables required for launched `wp` processes @@ -104,8 +144,10 @@ private static function get_process_env_variables() { return $env; } - // We cache the results of `wp core download` to improve test performance - // Ideally, we'd cache at the HTTP layer for more reliable tests + /** + * We cache the results of `wp core download` to improve test performance. + * Ideally, we'd cache at the HTTP layer for more reliable tests. + */ private static function cache_wp_files() { $wp_version_suffix = ( $wp_version = getenv( 'WP_VERSION' ) ) ? "-$wp_version" : ''; self::$cache_dir = sys_get_temp_dir() . '/wp-cli-test-core-download-cache' . $wp_version_suffix; @@ -143,14 +185,16 @@ public static function afterSuite( SuiteEvent $event ) { //$wp_cli_cache_dir = sys_get_temp_dir() . '/wp-cli-home/.wp-cli/cache'; //self::dir_diff_copy( self::$suite_cache_dir, $wp_cli_cache_dir, $wp_cli_cache_dir ); self::remove_dir( self::$suite_cache_dir ); + self::$suite_cache_dir = null; } if ( self::$composer_local_repository ) { self::remove_dir( self::$composer_local_repository ); + self::$composer_local_repository = null; } if ( ! $event->isCompleted() ) { - // Then probably control C hit so cleanup any leftover scenario stuff. + // Then ctrl+C hit so cleanup any leftover scenario stuff. self::afterScenario_cleanup( $event ); } else { // Test performance statistics - useful for detecting slow tests. @@ -168,8 +212,11 @@ public function beforeScenario( $event ) { self::log_run_times_before_scenario( $event ); } - // For use by RUN_DIR and SUITE_CACHE_DIR. - self::$temp_dir_infix = self::get_scenario_key( $event, true /*exclude_grandparent*/, '.' /*line_prefix*/ ); + // Used in the names of the RUN_DIR and SUITE_CACHE_DIR directories. + self::$temp_dir_infix = null; + if ( $file = self::get_event_file( $event, $line ) ) { + self::$temp_dir_infix = basename( $file ) . '.' . $line; + } $this->variables['SRC_DIR'] = realpath( __DIR__ . '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/../..' ); } @@ -191,30 +238,33 @@ public function afterScenario( $event ) { * If called from afterSuite() then suite was aborted and `$_this` won't be set. */ private static function afterScenario_cleanup( $event, $_this = null ) { + if ( $_this ) { + // Remove any background processes first. + foreach ( $_this->running_procs as $proc ) { + $status = proc_get_status( $proc ); + self::terminate_proc( $status['pid'] ); + } + } + if ( self::$run_dir ) { - // Remove altered WP install unless suite did complete ($_this set) and there's an error. + // Remove altered WP install unless suite did complete (`$_this` set) and there's an error. if ( ! $_this || $event->getResult() < 4 ) { self::remove_dir( self::$run_dir ); } self::$run_dir = null; } - // Remove suite cache. + // Remove SUITE_CACHE_DIR if any. if ( self::$suite_cache_dir ) { self::remove_dir( self::$suite_cache_dir ); self::$suite_cache_dir = null; } if ( $_this ) { - // Remove WP-CLI package directory + // Remove WP-CLI package directory if any. Set to `wp package path` by package-command and scaffold-package-command features, and by cli-info.feature. if ( isset( $_this->variables['PACKAGE_PATH'] ) ) { self::remove_dir( $_this->variables['PACKAGE_PATH'] ); } - - foreach ( $_this->running_procs as $proc ) { - $status = proc_get_status( $proc ); - self::terminate_proc( $status['pid'] ); - } } } @@ -245,6 +295,9 @@ private static function terminate_proc( $master_pid ) { } } + /** + * Create a temporary WP_CLI_CACHE_DIR. Exposed as SUITE_CACHE_DIR in "Given an empty cache" step. + */ public static function create_cache_dir() { if ( self::$suite_cache_dir ) { self::remove_dir( self::$suite_cache_dir ); @@ -256,7 +309,7 @@ public static function create_cache_dir() { /** * Initializes context. - * Every scenario gets it's own context object. + * Every scenario gets its own context object. * * @param array $parameters context parameters (set them up through behat.yml) */ @@ -286,6 +339,9 @@ public function getHookDefinitionResources() { return array(); } + /** + * Replace {VARIABLE_NAME}. Note that variable names can only contain uppercase letters and underscores (no numbers). + */ public function replace_variables( $str ) { $ret = preg_replace_callback( '/\{([A-Z_]+)\}/', array( $this, '_replace_var' ), $str ); if ( false !== strpos( $str, '{WP_VERSION-' ) ) { @@ -294,6 +350,9 @@ public function replace_variables( $str ) { return $ret; } + /** + * Replace variables callback. + */ private function _replace_var( $matches ) { $cmd = $matches[0]; @@ -304,7 +363,9 @@ private function _replace_var( $matches ) { return $cmd; } - // Substitute "{WP_VERSION-version-latest}" variables. + /** + * Substitute "{WP_VERSION-version-latest}" variables. + */ private function _replace_wp_versions( $str ) { static $wp_versions = null; if ( null === $wp_versions ) { @@ -333,11 +394,26 @@ private function _replace_wp_versions( $str ) { return strtr( $str, $wp_versions ); } + /** + * Get the file and line number for the current behat event. + */ + private static function get_event_file( $event, &$line ) { + if ( method_exists( $event, 'getScenario' ) ) { + $scenario_feature = $event->getScenario(); + } elseif ( method_exists( $event, 'getFeature' ) ) { + $scenario_feature = $event->getFeature(); + } else { + return null; + } + $line = $scenario_feature->getLine(); + return $scenario_feature->getFile(); + } + + /** + * Create the RUN_DIR directory, unless already set for this scenario. + */ public function create_run_dir() { if ( ! isset( $this->variables['RUN_DIR'] ) ) { - if ( self::$run_dir ) { - $this->remove_dir( self::$run_dir ); - } self::$run_dir = $this->variables['RUN_DIR'] = sys_get_temp_dir() . '/' . uniqid( 'wp-cli-test-run-' . self::$temp_dir_infix . '-', TRUE ); mkdir( $this->variables['RUN_DIR'] ); } @@ -389,8 +465,7 @@ public function download_phar( $version = 'same' ) { } /** - * CACHE_DIR is a place to store downloads of test files locally, to avoid repeated downloading and so speed up testing. - * It persists until manually deleted. + * CACHE_DIR is a cache for downloaded test data such as images. Lives until manually deleted. */ private function set_cache_dir() { $path = sys_get_temp_dir() . '/wp-cli-test-cache'; @@ -449,15 +524,18 @@ public function background_proc( $cmd, $sleep = 1 ) { $proc = proc_open( $cmd, $descriptors, $pipes, $this->variables['RUN_DIR'], self::get_process_env_variables() ); - if ( false === $proc ) { - throw new RuntimeException( stream_get_contents( $pipes[2] ) ); - } else { - $this->running_procs[] = $proc; - } - if ( $sleep ) { sleep( $sleep ); } + + $status = proc_get_status( $proc ); + + if ( ! $status['running'] ) { + $stderr = is_resource( $pipes[2] ) ? ( ': ' . stream_get_contents( $pipes[2] ) ) : ''; + throw new RuntimeException( sprintf( "Failed to start background process '%s'%s.", $cmd, $stderr ) ); + } else { + $this->running_procs[] = $proc; + } } public function move_files( $src, $dest ) { @@ -638,7 +716,7 @@ public function install_wp_with_composer() { public function composer_add_wp_cli_local_repository() { if ( ! self::$composer_local_repository ) { - self::$composer_local_repository = $this->variables['COMPOSER_LOCAL_REPOSITORY'] = sys_get_temp_dir() . '/' . uniqid( 'wp-cli-composer-local-' . self::$temp_dir_infix . '-', TRUE ); + self::$composer_local_repository = sys_get_temp_dir() . '/' . uniqid( "wp-cli-composer-local-", TRUE ); mkdir( self::$composer_local_repository ); $env = self::get_process_env_variables(); @@ -650,6 +728,7 @@ public function composer_add_wp_cli_local_repository() { $this->proc( 'composer config repositories.wp-cli \'{"type": "path", "url": "' . self::$composer_local_repository. '/", "options": {"symlink": false}}\'' )->run_check(); } + $this->variables['COMPOSER_LOCAL_REPOSITORY'] = self::$composer_local_repository; } public function composer_require_current_wp_cli() { @@ -706,15 +785,13 @@ private static function log_run_times_after_scenario( $event ) { /** * Get the scenario key used for `$scenario_run_times` array. - * With default args it's " :", eg "core-command core-update.feature:221". + * Format " :", eg "core-command core-update.feature:221". */ - private static function get_scenario_key( $event, $exclude_grandparent = false, $line_prefix = ':' ) { + private static function get_scenario_key( $event ) { $scenario_key = ''; - if ( method_exists( $event, 'getScenario' ) ) { - $scenario = $event->getScenario(); - $scenario_file = $scenario->getFile(); - $scenario_grandparent = $exclude_grandparent ? '' : ( basename( dirname( dirname( $scenario_file ) ) ) . ' ' ); - $scenario_key = $scenario_grandparent . basename( $scenario_file ) . $line_prefix . $scenario->getLine(); + if ( $file = self::get_event_file( $event, $line ) ) { + $scenario_grandparent = basename( dirname( dirname( $file ) ) ); + $scenario_key = $scenario_grandparent . ' ' . basename( $file ) . ':' . $line; } return $scenario_key; } diff --git a/features/steps/given.php b/features/steps/given.php index 57f19d7838..cb9a30afd9 100644 --- a/features/steps/given.php +++ b/features/steps/given.php @@ -17,7 +17,7 @@ function ( $world, $empty_or_nonexistent, $dir ) { $dir = $world->variables['RUN_DIR'] . "/$dir"; } if ( 0 !== strpos( $dir, sys_get_temp_dir() ) ) { - throw new \RuntimeException( sprintf( "Attempted to delete directory '%s' that is not in the temp directory '%s'. " . __FILE__ . ':' . __LINE__, $dir, sys_get_temp_dir() ) ); + throw new RuntimeException( sprintf( "Attempted to delete directory '%s' that is not in the temp directory '%s'. " . __FILE__ . ':' . __LINE__, $dir, sys_get_temp_dir() ) ); } $world->remove_dir( $dir ); if ( 'empty' === $empty_or_nonexistent ) { From aed504b09fd52b4ce85c55dabb2243d2e60ddb45 Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 27 Jul 2017 23:51:29 +0100 Subject: [PATCH 067/214] Try INVOKE_WP_CLI_WITH_PHP_ARGS. --- composer.lock | 32 ++++++++++---------- features/aliases.feature | 2 +- features/bootstrap/FeatureContext.php | 43 ++++++++++++++++++++++++--- 3 files changed, 56 insertions(+), 21 deletions(-) diff --git a/composer.lock b/composer.lock index 1a4fa733ca..e1fbb7ad70 100644 --- a/composer.lock +++ b/composer.lock @@ -1521,12 +1521,12 @@ "source": { "type": "git", "url": "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/wp-cli/core-command.git", - "reference": "55b6a48e454f47a92920d1a228ad8868f00cdf00" + "reference": "cb58fd71a9952d8c542703258cca16ca60bd8284" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/core-command/zipball/55b6a48e454f47a92920d1a228ad8868f00cdf00", - "reference": "55b6a48e454f47a92920d1a228ad8868f00cdf00", + "url": "https://api.github.com/repos/wp-cli/core-command/zipball/cb58fd71a9952d8c542703258cca16ca60bd8284", + "reference": "cb58fd71a9952d8c542703258cca16ca60bd8284", "shasum": "" }, "require-dev": { @@ -1572,7 +1572,7 @@ ], "description": "Download, install, update and manage a WordPress install.", "homepage": "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/wp-cli/core-command", - "time": "2017-07-13 10:35:57" + "time": "2017-07-18 14:55:39" }, { "name": "wp-cli/cron-command", @@ -1877,22 +1877,22 @@ "source": { "type": "git", "url": "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/gitlost/extension-command.git", - "reference": "8358c815983718e9b198aee0d1e12fe837882ba8" + "reference": "73b2fe63690ab4884599be5893ca002a8d085cc8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/gitlost/extension-command/zipball/8358c815983718e9b198aee0d1e12fe837882ba8", - "reference": "8358c815983718e9b198aee0d1e12fe837882ba8", + "url": "https://api.github.com/repos/gitlost/extension-command/zipball/73b2fe63690ab4884599be5893ca002a8d085cc8", + "reference": "73b2fe63690ab4884599be5893ca002a8d085cc8", "shasum": "" }, "require-dev": { "behat/behat": "~2.5", - "wp-cli/wp-cli": "*" + "wp-cli/wp-cli": "dev-github-api" }, "type": "wp-cli-package", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-themecache": "1.x-dev" }, "bundled": true, "commands": [ @@ -1949,9 +1949,9 @@ "homepage": "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/wp-cli/extension-command", "support": { "issues": "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/wp-cli/extension-command/issues", - "source": "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/gitlost/extension-command/tree/theme_cache" + "source": "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/gitlost/extension-command/tree/themecache" }, - "time": "2017-07-14 22:11:13" + "time": "2017-07-15 04:22:03" }, { "name": "wp-cli/import-command", @@ -2067,12 +2067,12 @@ "source": { "type": "git", "url": "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/wp-cli/media-command.git", - "reference": "a0690a39335226c021aa860a51440f014c14d588" + "reference": "6b6edd5e87c576fcaf6cfdd88dee425de2e38162" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/media-command/zipball/a0690a39335226c021aa860a51440f014c14d588", - "reference": "a0690a39335226c021aa860a51440f014c14d588", + "url": "https://api.github.com/repos/wp-cli/media-command/zipball/6b6edd5e87c576fcaf6cfdd88dee425de2e38162", + "reference": "6b6edd5e87c576fcaf6cfdd88dee425de2e38162", "shasum": "" }, "require": { @@ -2111,9 +2111,9 @@ "homepage": "https://runcommand.io" } ], - "description": "Import and regenerate attachments.", + "description": "Import new attachments or regenerate existing ones.", "homepage": "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/wp-cli/media-command", - "time": "2017-07-12 16:50:54" + "time": "2017-07-26 22:07:54" }, { "name": "wp-cli/mustangostang-spyc", diff --git a/features/aliases.feature b/features/aliases.feature index 557fba085c..10858de36f 100644 --- a/features/aliases.feature +++ b/features/aliases.feature @@ -392,7 +392,7 @@ Feature: Create shortcuts to specific WordPress installs - @bar """ - When I try `WP_CLI_PHP_ARGS='-ddisable_functions=' {SRC_DIR}/bin/wp @foobar core is-installed` + When I try `{INVOKE_WP_CLI_WITH_PHP_ARGS--ddisable_functions=} @foobar core is-installed` Then STDERR should contain: """ Error: Cannot do 'group alias': The PHP functions `proc_open()` and/or `proc_close()` are disabled diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index e8ad3629c3..154c156aee 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -334,11 +334,14 @@ public function getHookDefinitionResources() { * Replace {VARIABLE_NAME}. Note that variable names can only contain uppercase letters and underscores (no numbers). */ public function replace_variables( $str ) { - $ret = preg_replace_callback( '/\{([A-Z_]+)\}/', array( $this, '_replace_var' ), $str ); + if ( false !== strpos( $str, '{INVOKE_WP_CLI_WITH_PHP_ARGS-' ) ) { + $str = $this->_replace_invoke_wp_cli_with_php_args( $str ); + } + $str = preg_replace_callback( '/\{([A-Z_]+)\}/', array( $this, '_replace_var' ), $str ); if ( false !== strpos( $str, '{WP_VERSION-' ) ) { - $ret = $this->_replace_wp_versions( $ret ); + $str = $this->_replace_wp_versions( $str ); } - return $ret; + return $str; } /** @@ -385,6 +388,38 @@ private function _replace_wp_versions( $str ) { return strtr( $str, $wp_versions ); } + /** + * Substitute "{INVOKE_WP_CLI_WITH_PHP_ARGS-args}" variables. + */ + private function _replace_invoke_wp_cli_with_php_args( $str ) { + static $phar_path = null, $shell_path = null; + + if ( null === $phar_path ) { + $phar_path = false; + if ( ( $bin_dir = getenv( 'WP_CLI_BIN_DIR' ) ) && file_exists( $bin_dir . '/wp' ) && is_executable( $bin_dir . '/wp' ) ) { + $phar_path = $bin_dir . '/wp'; + } else { + $src_dir = dirname( dirname( __DIR__ ) ); + $bin_path = $src_dir . '/bin/wp'; + $vendor_bin_path = $src_dir . '/vendor/bin/wp'; + if ( file_exists( $bin_path ) && is_executable( $bin_path ) ) { + $shell_path = $bin_path; + } elseif ( file_exists( $vendor_bin_path ) && is_executable( $vendor_bin_path ) ) { + $shell_path = $vendor_bin_path; + } else { + $shell_path = 'wp'; + } + } + echo "bin_dir=$bin_dir"; + } + + $str = preg_replace_callback( '/{INVOKE_WP_CLI_WITH_PHP_ARGS-([^}]*)}/', function ( $matches ) use ( $phar_path, $shell_path ) { + return $phar_path ? "php {$matches[1]} {$phar_path}" : ( 'WP_CLI_PHP_ARGS=' . escapeshellarg( $matches[1] ) . ' ' . $shell_path ); + }, $str ); + + return $str; + } + /** * Get the file and line number for the current behat event. */ @@ -515,7 +550,7 @@ public function background_proc( $cmd ) { $proc = proc_open( $cmd, $descriptors, $pipes, $this->variables['RUN_DIR'], self::get_process_env_variables() ); - sleep( 1 ); + sleep(1); $status = proc_get_status( $proc ); From 6f68292e79d82893e79e86e9a0f49b6e78c52f7a Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 28 Jul 2017 00:10:02 +0100 Subject: [PATCH 068/214] Fix bad upstream merge. --- tests/test-file-cache.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test-file-cache.php b/tests/test-file-cache.php index bac60634c0..026d4899b4 100644 --- a/tests/test-file-cache.php +++ b/tests/test-file-cache.php @@ -42,6 +42,7 @@ public function testFinderLoaded() { $this->assertFalse( file_exists( $cache_dir . '/ttl' ) ); } + /** * Test get_root() deals with backslashed directory. */ public function testGetRoot() { From aeaa0064cf94a208c8d83d0d2a19340981f8f80a Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 28 Jul 2017 03:11:46 +0100 Subject: [PATCH 069/214] Just run framework for the mo. --- .travis.yml | 3 ++- ci/test.sh | 14 +++++--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index df933fec3c..a1860beb2f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,8 @@ language: php env: global: - WP_CLI_BIN_DIR=/tmp/wp-cli-phar - - TEST_COMMANDS=6 + - TEST_COMMANDS=0 + - TEST_COMMANDS_GLOB=*-command matrix: include: diff --git a/ci/test.sh b/ci/test.sh index 056337354f..ae296db977 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -16,15 +16,11 @@ if [[ $TEST_COMMANDS -eq 0 || $((TEST_COMMANDS & 1)) > 0 ]]; then fi if [[ $((TEST_COMMANDS & 2)) > 0 ]]; then - for R in vendor/wp-cli/[a-h]*-command; do + # Run the functional tests of commands. + TEST_COMMANDS_GLOB=${TEST_COMMANDS_GLOB-*-command} + for R in vendor/wp-cli/$TEST_COMMANDS_GLOB; do if [[ -f "$R/behat.yml" ]]; then BEHAT_YML="--config $R/behat.yml"; fi - BEHAT_TAGS=$(cd $R && php ../../../ci/behat-tags.php); vendor/bin/behat --format progress $BEHAT_YML $BEHAT_TAGS --strict $R/features - done -fi - -if [[ $((TEST_COMMANDS & 4)) > 0 ]]; then - for R in vendor/wp-cli/[i-z]*-command; do - if [[ -f "$R/behat.yml" ]]; then BEHAT_YML="--config $R/behat.yml"; fi - BEHAT_TAGS=$(cd $R && php ../../../ci/behat-tags.php); vendor/bin/behat --format progress $BEHAT_YML $BEHAT_TAGS --strict $R/features + BEHAT_TAGS=$(cd $R && php ../../../ci/behat-tags.php) + vendor/bin/behat --format progress $BEHAT_YML $BEHAT_TAGS --strict $R/features done fi From 5a3bd280a05d7ac8b8f3c8eb4784ea63d0e4ddc5 Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 28 Jul 2017 03:18:13 +0100 Subject: [PATCH 070/214] Remove tab from .travis.yml. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a1860beb2f..a0ad962141 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ env: global: - WP_CLI_BIN_DIR=/tmp/wp-cli-phar - TEST_COMMANDS=0 - - TEST_COMMANDS_GLOB=*-command + - TEST_COMMANDS_GLOB=*-command matrix: include: From 1b94a6e104db20bd903a8481403ebf8d54f4a109 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 29 Jul 2017 03:54:13 +0100 Subject: [PATCH 071/214] Remove debug echo. --- features/bootstrap/FeatureContext.php | 1 - 1 file changed, 1 deletion(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 154c156aee..5a5ad6a0b2 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -410,7 +410,6 @@ private function _replace_invoke_wp_cli_with_php_args( $str ) { $shell_path = 'wp'; } } - echo "bin_dir=$bin_dir"; } $str = preg_replace_callback( '/{INVOKE_WP_CLI_WITH_PHP_ARGS-([^}]*)}/', function ( $matches ) use ( $phar_path, $shell_path ) { From 851329324b6e91b188aa2b123e9170f65985529c Mon Sep 17 00:00:00 2001 From: gitlost Date: Sun, 30 Jul 2017 22:14:44 +0100 Subject: [PATCH 072/214] Exclude command/php-cli-tools vendor dir. --- utils/make-phar.php | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/make-phar.php b/utils/make-phar.php index 0ce3b13976..2048599854 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -116,6 +116,7 @@ function set_file_contents( $phar, $path, $content ) { ->in(WP_CLI_VENDOR_DIR . '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/symfony/finder') ->in(WP_CLI_VENDOR_DIR . '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/symfony/polyfill-mbstring') ->notName('behat-tags.php') + ->notPath('#(?:[^/]+-command|php-cli-tools)/vendor/#') // For running locally, in case have composer installed or symlinked them. ->exclude('examples') ->exclude('features') ->exclude('test') From 2c8a15ba65857e97eff87b85f7c35067338a2005 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 9 Aug 2017 14:35:44 +0100 Subject: [PATCH 073/214] Give explicit COLUMNS in help else can fail locally. --- features/help.feature | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/help.feature b/features/help.feature index dd493f433a..3d64334322 100644 --- a/features/help.feature +++ b/features/help.feature @@ -293,7 +293,7 @@ Feature: Get help about WP-CLI commands """ And I run `wp plugin activate test-cli` - When I run `wp help test-wordwrap my_command` + When I run `COLUMNS=80 wp help test-wordwrap my_command` Then STDOUT should contain: """ 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345678 @@ -350,7 +350,7 @@ Feature: Get help about WP-CLI commands """ And STDERR should be empty - When I run `wp help test-wordwrap my_command | wc -L` + When I run `COLUMNS=80 wp help test-wordwrap my_command | wc -L` Then STDOUT should be: """ 80 From 7b5988520ccc1790217679506ba3c34ad8ed2e7f Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 9 Aug 2017 18:29:38 +0100 Subject: [PATCH 074/214] Fix merge. --- features/bootstrap/FeatureContext.php | 1 + 1 file changed, 1 insertion(+) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index ffb11c2db7..fef783ece5 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -894,5 +894,6 @@ private static function log_run_times_after_suite( $event ) { } else { error_log( $log ); } + } } From e2740ee02d84b3f7fd9a9b9da096a88f15b22a3f Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 9 Aug 2017 18:53:09 +0100 Subject: [PATCH 075/214] Remove no longer needed require-php-5.4 tags. --- features/cli.feature | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/features/cli.feature b/features/cli.feature index 5697e4b843..826453d4a5 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -27,8 +27,7 @@ Feature: `wp cli` tasks """ And STDERR should be empty - # The latest 1.2.1 phar fails on Travis PHP 5.3 due to double slash in boot-phar.php path so need >= 5.4 to do cli update - @travis-github-token @require-php-5.4 + @travis-github-token Scenario: Do WP-CLI Update Given an empty directory And a new Phar with version "0.0.0" and cli build @@ -100,8 +99,7 @@ Feature: `wp cli` tasks WP-CLI 0.14.1 """ - # See above - @travis-github-token @require-php-5.4 + @travis-github-token Scenario: Not a patch update from 0.14.0 Given an empty directory And a new Phar with version "0.14.0" and cli build @@ -118,8 +116,7 @@ Feature: `wp cli` tasks And STDERR should be empty And the return code should be 0 - # See above - @travis-github-token @require-php-5.4 + @travis-github-token Scenario: Install WP-CLI nightly Given an empty directory And a new Phar with version "0.14.0" and cli build @@ -137,8 +134,7 @@ Feature: `wp cli` tasks And STDERR should be empty And the return code should be 0 - # See above - @travis-github-token @require-php-5.4 + @travis-github-token Scenario: Install WP-CLI stable Given an empty directory And a new Phar with version "0.14.0" and cli build From 048d1a31595a97f52f91fae33794a0bf1b4c10bc Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 10 Aug 2017 06:53:29 +0100 Subject: [PATCH 076/214] Strip comments in make-phar.php. --- utils/make-phar.php | 47 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/utils/make-phar.php b/utils/make-phar.php index 4b14dbe2b8..cdff3ca7da 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -24,7 +24,7 @@ list( $args, $assoc_args, $runtime_config ) = $configurator->parse_args( array_slice( $GLOBALS['argv'], 1 ) ); if ( ! isset( $args[0] ) || empty( $args[0] ) ) { - echo "usage: php -dphar.readonly=0 $argv[0] [--quiet] [--version=same|patch|minor|major|x.y.z] [--store-version]\n"; + echo "usage: php -dphar.readonly=0 $argv[0] [--quiet] [--version=same|patch|minor|major|x.y.z] [--store-version] [--build=cli]\n"; exit(1); } @@ -53,6 +53,12 @@ function add_file( $phar, $path ) { if ( !BE_QUIET ) echo "$key - $path\n"; + $file_contents = file_get_contents( $path ); + if ( preg_match( '/.php$/', $path ) ) { + $is_wp_cli_command = preg_match( '/\/(?:php\/commands|vendor\/wp-cli\/[^-]*-command\/src)\//', $path ); + $file_contents = strip_comments( $file_contents, $is_wp_cli_command /*keep_doc_comments*/ ); + } + $basename = basename( $path ); if ( 0 === strpos( $basename, 'autoload_' ) && preg_match( '/(?:classmap|files|namespaces|psr4|static)\.php$/', $basename ) ) { // Strip autoload maps of unused stuff. @@ -60,9 +66,9 @@ function add_file( $phar, $path ) { if ( null === $strip_res ) { if ( 'cli' === BUILD ) { $strips = array( - '\/(?:behat|composer|gherkin)\/src', + '\/(?:behat|composer|gherkin)\/src\/', '\/phpunit\/', - '\/nb\/oxymel', + '\/nb\/oxymel\/', '-command\/src\/', '\/wp-cli\/[^\n]+-command\/', '\/symfony\/(?!finder|polyfill-mbstring)[^\/]+\/', @@ -80,12 +86,36 @@ function add_file( $phar, $path ) { return '/^[^,\n]+?' . $v . '[^,\n]+?, *\n/m'; }, $strips ); } - $phar[ $key ] = preg_replace( $strip_res, '', file_get_contents( $path ) ); + $phar[ $key ] = preg_replace( $strip_res, '', $file_contents ); } else { - $phar[ $key ] = file_get_contents( $path ); + $phar[ $key ] = $file_contents; } } +function strip_comments( $contents, $keep_doc_comments ) { + $first_comment = true; + $strs = array_map( function ( $t ) use ( $keep_doc_comments, &$first_comment ) { + if ( is_string( $t ) ) { + return $t; + } + if ( T_COMMENT === $t[0] || ( ! $keep_doc_comments && T_DOC_COMMENT === $t[0] ) ) { + if ( $first_comment ) { + // Keep for copyright reasons. + $first_comment = false; + return $t[1]; + } + return str_repeat( "\n", substr_count( $t[1], "\n" ) ); // Strip everything but newlines. + } + if ( T_WHITESPACE === $t[0] ) { + $str = preg_replace( '/[^\t\n]/', '', $t[1] ); + return '' !== $str ? $str : ' '; + } + return $t[1]; + }, token_get_all( $contents ) ); + + return implode( '', $strs ); +} + function set_file_contents( $phar, $path, $content ) { $key = str_replace( WP_CLI_BASE_PATH, '', $path ); @@ -147,6 +177,7 @@ function set_file_contents( $phar, $path, $content ) { ->in(WP_CLI_VENDOR_DIR . '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/symfony/filesystem') ->in(WP_CLI_VENDOR_DIR . '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/symfony/process') ->in(WP_CLI_VENDOR_DIR . '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/justinrainbow/json-schema') + ->exclude('demo') ->exclude('nb/oxymel/OxymelTest.php') ->exclude('composer/spdx-licenses') ->exclude('composer/composer/src/Composer/Command') @@ -248,4 +279,8 @@ function set_file_contents( $phar, $path, $content ) { $phar->stopBuffering(); -echo "Generated " . DEST_PATH . "\n"; +chmod( DEST_PATH, 0755 ); // Make executable. + +if ( ! BE_QUIET ) { + echo "Generated " . DEST_PATH . "\n"; +} From 9993e4cfe0d1b2932da39229dbb81699d5873931 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 21 Aug 2017 04:28:53 +0100 Subject: [PATCH 077/214] Merge update. --- ci/test.sh | 2 +- features/bootstrap/FeatureContext.php | 252 ++++++++++++++++---------- php/WP_CLI/Process.php | 15 +- phpcs.ruleset.xml => phpcs.xml.dist | 7 + 4 files changed, 178 insertions(+), 98 deletions(-) rename phpcs.ruleset.xml => phpcs.xml.dist (96%) diff --git a/ci/test.sh b/ci/test.sh index ae296db977..a86c01f730 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -3,7 +3,7 @@ set -ex # Run CodeSniffer -phpcs --standard=phpcs.ruleset.xml $(find . -name '*.php' -not -path "./vendor/*" -not -path "./packages/*") +phpcs # Run the unit tests vendor/bin/phpunit diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index fef783ece5..0a46a09778 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -55,7 +55,7 @@ class FeatureContext extends BehatContext implements ClosuredContextInterface { private static $cache_dir; /** - * The directory that holds the install cache. Lives until manually deleted. + * The directory that holds the install cache, and which is copied to RUN_DIR during a "Given a WP install" step. Recreated on each suite run. */ private static $install_cache_dir; @@ -98,19 +98,17 @@ class FeatureContext extends BehatContext implements ClosuredContextInterface { private static $temp_dir_infix; /** - * When the suite started, set on `@BeforeScenario'. + * Settings and variables for WP_CLI_TEST_LOG_RUN_TIMES run time logging. */ - private static $suite_start_time; + private static $log_run_times; // Whether to log run times - WP_CLI_TEST_LOG_RUN_TIMES env var. Set on `@BeforeScenario'. + private static $suite_start_time; // When the suite started, set on `@BeforeScenario'. + private static $output_to; // Where to output log - stdout|error_log. Set on `@BeforeSuite`. + private static $num_top_processes; // Number of processes/methods to output by longest run times. Set on `@BeforeSuite`. + private static $num_top_scenarios; // Number of scenarios to output by longest run times. Set on `@BeforeSuite`. - /** - * Scenario run times (top 20 only). - */ - private static $scenario_run_times = array(); - - /** - * Scenario count, incremented on `@AfterScenario`. - */ - private static $scenario_count = 0; + private static $scenario_run_times = array(); // Scenario run times (top `self::$num_top_scenarios` only). + private static $scenario_count = 0; // Scenario count, incremented on `@AfterScenario`. + private static $proc_method_run_times = array(); // Array of run time info for proc methods, keyed by method name and arg, each a 2-element array containing run time and run count. /** * Get the environment variables required for launched `wp` processes @@ -164,7 +162,11 @@ private static function cache_wp_files() { * @BeforeSuite */ public static function prepare( SuiteEvent $event ) { - self::$suite_start_time = microtime( true ); + // Test performance statistics - useful for detecting slow tests. + if ( self::$log_run_times = getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) ) { + self::log_run_times_before_suite( $event ); + } + $result = Process::create( 'wp cli info', null, self::get_process_env_variables() )->run_check(); echo PHP_EOL; echo $result->stdout; @@ -173,6 +175,13 @@ public static function prepare( SuiteEvent $event ) { $result = Process::create( Utils\esc_cmd( 'wp core version --path=%s', self::$cache_dir ) , null, self::get_process_env_variables() )->run_check(); echo 'WordPress ' . $result->stdout; echo PHP_EOL; + + // Remove install cache if any (not setting the static var). + $wp_version_suffix = ( $wp_version = getenv( 'WP_VERSION' ) ) ? "-$wp_version" : ''; + $install_cache_dir = sys_get_temp_dir() . '/wp-cli-test-core-install-cache' . $wp_version_suffix; + if ( file_exists( $install_cache_dir ) ) { + self::remove_dir( $install_cache_dir ); + } } /** @@ -189,7 +198,7 @@ public static function afterSuite( SuiteEvent $event ) { self::afterScenario_cleanup( $event ); } else { // Test performance statistics - useful for detecting slow tests. - if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) ) { + if ( self::$log_run_times ) { self::log_run_times_after_suite( $event ); } } @@ -199,7 +208,7 @@ public static function afterSuite( SuiteEvent $event ) { * @BeforeScenario */ public function beforeScenario( $event ) { - if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) ) { + if ( self::$log_run_times ) { self::log_run_times_before_scenario( $event ); } @@ -219,7 +228,7 @@ public function afterScenario( $event ) { self::afterScenario_cleanup( $event, $this ); - if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) ) { + if ( self::$log_run_times ) { self::log_run_times_after_scenario( $event ); } } @@ -427,6 +436,8 @@ private static function get_event_file( $event, &$line ) { $scenario_feature = $event->getScenario(); } elseif ( method_exists( $event, 'getFeature' ) ) { $scenario_feature = $event->getFeature(); + } elseif ( method_exists( $event, 'getOutline' ) ) { + $scenario_feature = $event->getOutline(); } else { return null; } @@ -500,23 +511,39 @@ private function set_cache_dir() { $this->variables['CACHE_DIR'] = $path; } - private static function run_sql( $sql ) { - Utils\run_mysql_command( '/usr/bin/env mysql --no-defaults', array( - 'execute' => $sql, + /** + * Run a MySQL command with `$db_settings`. + * + * @param string $sql_cmd Command to run. + * @param array $assoc_args Optional. Associative array of options. Default empty. + * @param bool $add_database Optional. Whether to add dbname to the $sql_cmd. Default false. + */ + private static function run_sql( $sql_cmd, $assoc_args = array(), $add_database = false ) { + $start_time = microtime( true ); + + $default_assoc_args = array( 'host' => self::$db_settings['dbhost'], 'user' => self::$db_settings['dbuser'], 'pass' => self::$db_settings['dbpass'], - ) ); + ); + if ( $add_database ) { + $sql_cmd .= ' ' . escapeshellarg( self::$db_settings['dbname'] ); + } + Utils\run_mysql_command( $sql_cmd, array_merge( $assoc_args, $default_assoc_args ) ); + + if ( self::$log_run_times ) { + self::log_proc_method_run_time( $sql_cmd . ' ' . implode( ' ', $assoc_args ), $start_time ); + } } public function create_db() { $dbname = self::$db_settings['dbname']; - self::run_sql( "CREATE DATABASE IF NOT EXISTS $dbname" ); + self::run_sql( 'mysql --no-defaults', array( 'execute' => "CREATE DATABASE IF NOT EXISTS $dbname" ) ); } public function drop_db() { $dbname = self::$db_settings['dbname']; - self::run_sql( "DROP DATABASE IF EXISTS $dbname" ); + self::run_sql( 'mysql --no-defaults', array( 'execute' => "DROP DATABASE IF EXISTS $dbname" ) ); } public function proc( $command, $assoc_args = array(), $path = '' ) { @@ -622,7 +649,7 @@ public function create_config( $subdir = '', $extra_php = false ) { if ( $config_cache_path && file_exists( $config_cache_path ) ) { copy( $config_cache_path, $run_dir . '/wp-config.php' ); } else { - $this->proc( 'wp core config', $params, $subdir )->run_check(); + $this->proc( 'wp config create', $params, $subdir )->run_check(); if ( $config_cache_path && file_exists( $run_dir . '/wp-config.php' ) ) { copy( $run_dir . '/wp-config.php', $config_cache_path ); } @@ -659,56 +686,13 @@ public function install_wp( $subdir = '' ) { if ( $install_cache_path && file_exists( $install_cache_path ) ) { self::copy_dir( $install_cache_path, $run_dir ); - $cmd = Utils\esc_cmd( - '/usr/bin/env mysql --no-defaults -q -s -u%s -p%s -e%s %s', - self::$db_settings['dbuser'], self::$db_settings['dbpass'], "source {$install_cache_path}.sql;", self::$db_settings['dbname'] - ); - Process::create( $cmd )->run_check(); + self::run_sql( 'mysql --no-defaults', array( 'execute' => "source {$install_cache_path}.sql" ), true /*add_database*/ ); } else { $this->proc( 'wp core install', $install_args, $subdir )->run_check(); if ( $install_cache_path ) { mkdir( $install_cache_path ); self::dir_diff_copy( $run_dir, self::$cache_dir, $install_cache_path ); - $cmd = Utils\esc_cmd( - '/usr/bin/env mysqldump --no-defaults -u%s -p%s %s > %s', - self::$db_settings['dbuser'], self::$db_settings['dbpass'], self::$db_settings['dbname'], $install_cache_path . '.sql' - ); - Process::create( $cmd )->run_check(); - } - } - } - - /** - * Copy files in updated directory that are not in source directory to copy directory. ("Incremental backup".) - * - * @param string $upd_dir The directory to search looking for files/directories not in `$src_dir`. - * @param string $src_dir The directory to be compared to `$upd_dir`. - * @param string $cop_dir Where to copy any files/directories in `$upd_dir` but not in `$src_dir` to. - */ - private static function dir_diff_copy( $upd_dir, $src_dir, $cop_dir ) { - if ( false === ( $files = scandir( $upd_dir ) ) ) { - $error = error_get_last(); - throw new \RuntimeException( sprintf( "Failed to open updated directory '%s': %s. " . __FILE__ . ':' . __LINE__, $upd_dir, $error['message'] ) ); - } - foreach ( array_diff( $files, array( '.', '..' ) ) as $file ) { - $upd_file = $upd_dir . '/' . $file; - $src_file = $src_dir . '/' . $file; - $cop_file = $cop_dir . '/' . $file; - if ( ! file_exists( $src_file ) ) { - if ( is_dir( $upd_file ) ) { - if ( ! file_exists( $cop_file ) && ! mkdir( $cop_file, 0777, true /*recursive*/ ) ) { - $error = error_get_last(); - throw new \RuntimeException( sprintf( "Failed to create copy directory '%s': %s. " . __FILE__ . ':' . __LINE__, $cop_file, $error['message'] ) ); - } - self::copy_dir( $upd_file, $cop_file ); - } else { - if ( ! copy( $upd_file, $cop_file ) ) { - $error = error_get_last(); - throw new \RuntimeException( sprintf( "Failed to copy '%s' to '%s': %s. " . __FILE__ . ':' . __LINE__, $upd_file, $cop_file, $error['message'] ) ); - } - } - } elseif ( is_dir( $upd_file ) ) { - self::dir_diff_copy( $upd_file, $src_file, $cop_file ); + self::run_sql( 'mysqldump --no-defaults', array( 'result-file' => "{$install_cache_path}.sql" ), true /*add_database*/ ); } } } @@ -791,6 +775,71 @@ private function composer_command($cmd) { $this->proc( $this->variables['COMPOSER_PATH'] . ' ' . $cmd )->run_check(); } + /** + * Copy files in updated directory that are not in source directory to copy directory. ("Incremental backup".) + * Note: does not deal with changed files (ie does not compare file contents for changes), for speed reasons. + * + * @param string $upd_dir The directory to search looking for files/directories not in `$src_dir`. + * @param string $src_dir The directory to be compared to `$upd_dir`. + * @param string $cop_dir Where to copy any files/directories in `$upd_dir` but not in `$src_dir` to. + */ + private static function dir_diff_copy( $upd_dir, $src_dir, $cop_dir ) { + if ( false === ( $files = scandir( $upd_dir ) ) ) { + $error = error_get_last(); + throw new \RuntimeException( sprintf( "Failed to open updated directory '%s': %s. " . __FILE__ . ':' . __LINE__, $upd_dir, $error['message'] ) ); + } + foreach ( array_diff( $files, array( '.', '..' ) ) as $file ) { + $upd_file = $upd_dir . '/' . $file; + $src_file = $src_dir . '/' . $file; + $cop_file = $cop_dir . '/' . $file; + if ( ! file_exists( $src_file ) ) { + if ( is_dir( $upd_file ) ) { + if ( ! file_exists( $cop_file ) && ! mkdir( $cop_file, 0777, true /*recursive*/ ) ) { + $error = error_get_last(); + throw new \RuntimeException( sprintf( "Failed to create copy directory '%s': %s. " . __FILE__ . ':' . __LINE__, $cop_file, $error['message'] ) ); + } + self::copy_dir( $upd_file, $cop_file ); + } else { + if ( ! copy( $upd_file, $cop_file ) ) { + $error = error_get_last(); + throw new \RuntimeException( sprintf( "Failed to copy '%s' to '%s': %s. " . __FILE__ . ':' . __LINE__, $upd_file, $cop_file, $error['message'] ) ); + } + } + } elseif ( is_dir( $upd_file ) ) { + self::dir_diff_copy( $upd_file, $src_file, $cop_file ); + } + } + } + + /** + * Initialize run time logging. + */ + private static function log_run_times_before_suite( $event ) { + self::$suite_start_time = microtime( true ); + + Process::$log_run_times = true; + + $travis = getenv( 'TRAVIS' ); + + // Default output settings. + self::$output_to = 'stdout'; + self::$num_top_processes = $travis ? 10 : 40; + self::$num_top_scenarios = $travis ? 10 : 20; + + // Allow setting of above with "WP_CLI_TEST_LOG_RUN_TIMES=[,][,]" formatted env var. + if ( preg_match( '/^(stdout|error_log)?(,[0-9]+)?(,[0-9]+)?$/i', self::$log_run_times, $matches ) ) { + if ( isset( $matches[1] ) ) { + self::$output_to = strtolower( $matches[1] ); + } + if ( isset( $matches[2] ) ) { + self::$num_top_processes = max( (int) substr( $matches[2], 1 ), 1 ); + } + if ( isset( $matches[3] ) ) { + self::$num_top_scenarios = max( (int) substr( $matches[3], 1 ), 1 ); + } + } + } + /** * Record the start time of the scenario into the `$scenario_run_times` array. */ @@ -801,13 +850,13 @@ private static function log_run_times_before_scenario( $event ) { } /** - * Save the run time of the scenario into the `$scenario_run_times` array. Only the top 20 are kept. + * Save the run time of the scenario into the `$scenario_run_times` array. Only the top `self::$num_top_scenarios` are kept. */ private static function log_run_times_after_scenario( $event ) { if ( $scenario_key = self::get_scenario_key( $event ) ) { self::$scenario_run_times[ $scenario_key ] += microtime( true ); self::$scenario_count++; - if ( count( self::$scenario_run_times ) > 20 ) { + if ( count( self::$scenario_run_times ) > self::$num_top_scenarios ) { arsort( self::$scenario_run_times ); array_pop( self::$scenario_run_times ); } @@ -821,8 +870,8 @@ private static function log_run_times_after_scenario( $event ) { private static function get_scenario_key( $event ) { $scenario_key = ''; if ( $file = self::get_event_file( $event, $line ) ) { - $scenario_grandparent = basename( dirname( dirname( $file ) ) ); - $scenario_key = $scenario_grandparent . ' ' . basename( $file ) . ':' . $line; + $scenario_grandparent = Utils\basename( dirname( dirname( $file ) ) ); + $scenario_key = $scenario_grandparent . ' ' . Utils\basename( $file ) . ':' . $line; } return $scenario_key; } @@ -831,7 +880,6 @@ private static function get_scenario_key( $event ) { * Print out stats on the run times of processes and scenarios. */ private static function log_run_times_after_suite( $event ) { - $travis = getenv( 'TRAVIS' ); $suite = ''; if ( self::$scenario_run_times ) { @@ -840,9 +888,9 @@ private static function log_run_times_after_suite( $event ) { $suite = substr( $keys[0], 0, strpos( $keys[0], ' ' ) ); } - $run_from = basename( dirname( dirname( __DIR__ ) ) ); + $run_from = Utils\basename( dirname( dirname( __DIR__ ) ) ); - // Like Behat, if have minutes. + // Format same as Behat, if have minutes. $fmt = function ( $time ) { $mins = floor( $time / 60 ); return round( $time, 3 ) . ( $mins ? ( ' (' . $mins . 'm' . round( $time - ( $mins * 60 ), 3 ) . 's)' ) : '' ); @@ -850,50 +898,64 @@ private static function log_run_times_after_suite( $event ) { $time = microtime( true ) - self::$suite_start_time; - $log = "\n" . str_repeat( '(', 80 ) . "\n"; + $log = PHP_EOL . str_repeat( '(', 80 ) . PHP_EOL; + + // Process and proc method run times. + $run_times = array_merge( Process::$run_times, self::$proc_method_run_times ); - // Process run times. - list( $ptime, $calls ) = array_reduce( Process::$run_times, function ( $carry, $item ) { + list( $ptime, $calls ) = array_reduce( $run_times, function ( $carry, $item ) { return array( $carry[0] + $item[0], $carry[1] + $item[1] ); }, array( 0, 0 ) ); $overhead = $time - $ptime; $pct = round( ( $overhead / $time ) * 100 ); - $unique = count( Process::$run_times ); + $unique = count( $run_times ); $log .= sprintf( - "\nTotal process run time=%s (tests=%s, overhead=%.3f %d%%), calls=%d (unique=%d) for %s run from %s\n", + PHP_EOL . "Total process run time %s (tests %s, overhead %.3f %d%%), calls %d (%d unique) for '%s' run from '%s'" . PHP_EOL, $fmt( $ptime ), $fmt( $time ), $overhead, $pct, $calls, $unique, $suite, $run_from ); - uasort( Process::$run_times, function ( $a, $b ) { + uasort( $run_times, function ( $a, $b ) { return $a[0] === $b[0] ? 0 : ( $a[0] < $b[0] ? 1 : -1 ); // Reverse sort. } ); - $top = $travis ? 10 : 40; - $tops = array_slice( Process::$run_times, 0, $top, true ); + $tops = array_slice( $run_times, 0, self::$num_top_processes, true ); - $log .= "\nTop $top process run times for $suite\n" . implode( "\n", array_map( function ( $k, $v, $i ) { - return sprintf( '%2d. %6.3f %2d %s', $i + 1, round( $v[0], 3 ), $v[1], $k ); - }, array_keys( $tops ), $tops, array_keys( array_keys( $tops ) ) ) ) . "\n"; + $log .= PHP_EOL . "Top " . self::$num_top_processes . " process run times for '$suite'"; + $log .= PHP_EOL . implode( PHP_EOL, array_map( function ( $k, $v, $i ) { + return sprintf( ' %3d. %7.3f %3d %s', $i + 1, round( $v[0], 3 ), $v[1], $k ); + }, array_keys( $tops ), $tops, array_keys( array_keys( $tops ) ) ) ) . PHP_EOL; // Scenario run times. arsort( self::$scenario_run_times ); - $top = $travis ? 10 : 20; - $tops = array_slice( self::$scenario_run_times, 0, $top, true ); + $tops = array_slice( self::$scenario_run_times, 0, self::$num_top_scenarios, true ); - $log .= "\nTop $top (of " . self::$scenario_count . ") scenario run times for $suite\n" . implode( "\n", array_map( function ( $k, $v, $i ) { - return sprintf( '%2d. %6.3f %s', $i + 1, round( $v, 3 ), substr( $k, strpos( $k, ' ' ) + 1 ) ); - }, array_keys( $tops ), $tops, array_keys( array_keys( $tops ) ) ) ) . "\n"; + $log .= PHP_EOL . "Top " . self::$num_top_scenarios . " (of " . self::$scenario_count . ") scenario run times for '$suite'"; + $log .= PHP_EOL . implode( PHP_EOL, array_map( function ( $k, $v, $i ) { + return sprintf( ' %3d. %7.3f %s', $i + 1, round( $v, 3 ), substr( $k, strpos( $k, ' ' ) + 1 ) ); + }, array_keys( $tops ), $tops, array_keys( array_keys( $tops ) ) ) ) . PHP_EOL; - $log .= "\n" . str_repeat( ')', 80 ); + $log .= PHP_EOL . str_repeat( ')', 80 ); - if ( $travis ) { - echo "\n" . $log; - } else { + if ( 'error_log' === self::$output_to ) { error_log( $log ); + } else { + echo PHP_EOL . $log; + } + } + + /** + * Log the run time of a proc method (one that doesn't use Process but does (use a function that does) a `proc_open()`). + */ + private static function log_proc_method_run_time( $key, $start_time ) { + $run_time = microtime( true ) - $start_time; + if ( ! isset( self::$proc_method_run_times[ $key ] ) ) { + self::$proc_method_run_times[ $key ] = array( 0, 0 ); } + self::$proc_method_run_times[ $key ][0] += $run_time; + self::$proc_method_run_times[ $key ][1]++; } } diff --git a/php/WP_CLI/Process.php b/php/WP_CLI/Process.php index 01cf1bca37..8032a2415d 100644 --- a/php/WP_CLI/Process.php +++ b/php/WP_CLI/Process.php @@ -21,13 +21,24 @@ class Process { */ private $env; + /** + * @var array Descriptor spec for `proc_open()`. + */ private static $descriptors = array( 0 => STDIN, 1 => array( 'pipe', 'w' ), 2 => array( 'pipe', 'w' ), ); - static $run_times = array(); + /** + * @var bool Whether to log run time info or not. + */ + public static $log_run_times = false; + + /** + * @var array Array of process run time info, keyed by process command, each a 2-element array containing run time and run count. + */ + public static $run_times = array(); /** * @param string $command Command to execute. @@ -68,7 +79,7 @@ public function run() { $run_time = microtime( true ) - $start_time; - if ( getenv( 'WP_CLI_TEST_LOG_RUN_TIMES' ) ) { + if ( self::$log_run_times ) { if ( ! isset( self::$run_times[ $this->command ] ) ) { self::$run_times[ $this->command ] = array( 0, 0 ); } diff --git a/phpcs.ruleset.xml b/phpcs.xml.dist similarity index 96% rename from phpcs.ruleset.xml rename to phpcs.xml.dist index ef45d5d519..a34cc145b1 100644 --- a/phpcs.ruleset.xml +++ b/phpcs.xml.dist @@ -2,6 +2,13 @@ WordPress Coding Standards for WP-CLI + + + . + + + + From ca7b55d3c589aa06d7720531d00f6b36362422c8 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 23 Aug 2017 11:42:43 +0100 Subject: [PATCH 078/214] Restore composer.json. --- composer.json | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/composer.json b/composer.json index 001e97591e..ce5539fb80 100644 --- a/composer.json +++ b/composer.json @@ -19,12 +19,6 @@ }, "minimum-stability": "dev", "prefer-stable": true, - "repositories": [ - { - "type": "vcs", - "url": "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/gitlost/extension-command.git" - } - ], "require": { "php": ">=5.3.29", "composer/composer": "^1.2.0", @@ -46,23 +40,23 @@ "wp-cli/cache-command": "^1.0", "wp-cli/checksum-command": "^1.0", "wp-cli/config-command": "^1.0", - "wp-cli/core-command": "dev-master", + "wp-cli/core-command": "^1.0", "wp-cli/cron-command": "^1.0", - "wp-cli/db-command": "dev-master", + "wp-cli/db-command": "^1.0", "wp-cli/entity-command": "^1.0", "wp-cli/eval-command": "^1.0", "wp-cli/export-command": "^1.0", - "wp-cli/extension-command": "dev-themecache", + "wp-cli/extension-command": "^1.0", "wp-cli/import-command": "^1.0", "wp-cli/language-command": "^1.0", - "wp-cli/media-command": "dev-master", + "wp-cli/media-command": "^1.0", "wp-cli/mustangostang-spyc": "^0.6.3", "wp-cli/package-command": "^1.0", "wp-cli/php-cli-tools": "~0.11.2", "wp-cli/rewrite-command": "^1.0", "wp-cli/role-command": "^1.0", "wp-cli/scaffold-command": "^1.0", - "wp-cli/search-replace-command": "dev-master", + "wp-cli/search-replace-command": "^1.0", "wp-cli/server-command": "^1.0", "wp-cli/shell-command": "^1.0", "wp-cli/super-admin-command": "^1.0", From 9e9d435bc510aff07901cbc77eaac9d874683657 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 28 Aug 2017 15:03:11 +0100 Subject: [PATCH 079/214] Try PHP 7.2. have_dropped_db flag. --- .travis.yml | 2 ++ features/bootstrap/FeatureContext.php | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 09b23aea6d..93afd9e07b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,8 @@ env: matrix: include: + - php: 7.2 + env: WP_VERSION=latest - php: 7.1 env: WP_VERSION=latest - php: 7.0 diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 3b794d2e48..8e11cc6f73 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -81,6 +81,11 @@ class FeatureContext extends BehatContext implements ClosuredContextInterface { 'dbhost' => '127.0.0.1', ); + /** + * Flag whether `wp_cli_test` database dropped already or not. (For performance reasons.) + */ + private static $have_dropped_db = false; + /** * Array of background process ids started by the current scenario. Used to terminate them at the end of the scenario. */ @@ -536,12 +541,16 @@ private static function run_sql( $sql_cmd, $assoc_args = array(), $add_database public function create_db() { $dbname = self::$db_settings['dbname']; - self::run_sql( 'mysql --no-defaults', array( 'execute' => "CREATE DATABASE IF NOT EXISTS $dbname" ) ); + self::run_sql( 'mysql --no-defaults --no-auto-rehash', array( 'execute' => "CREATE DATABASE IF NOT EXISTS $dbname" ) ); + self::$have_dropped_db = false; } public function drop_db() { - $dbname = self::$db_settings['dbname']; - self::run_sql( 'mysql --no-defaults', array( 'execute' => "DROP DATABASE IF EXISTS $dbname" ) ); + if ( ! self::$have_dropped_db ) { + $dbname = self::$db_settings['dbname']; + self::run_sql( 'mysql --no-defaults --no-auto-rehash', array( 'execute' => "DROP DATABASE IF EXISTS $dbname" ) ); + self::$have_dropped_db = true; + } } public function proc( $command, $assoc_args = array(), $path = '' ) { @@ -684,7 +693,7 @@ public function install_wp( $subdir = '' ) { if ( $install_cache_path && file_exists( $install_cache_path ) ) { self::copy_dir( $install_cache_path, $run_dir ); - self::run_sql( 'mysql --no-defaults', array( 'execute' => "source {$install_cache_path}.sql" ), true /*add_database*/ ); + self::run_sql( 'mysql --no-defaults --no-auto-rehash', array( 'execute' => "SOURCE {$install_cache_path}.sql" ), true /*add_database*/ ); } else { $this->proc( 'wp core install', $install_args, $subdir )->run_check(); if ( $install_cache_path ) { From 05432687c0dc485b8e43066134f802a667bf9b7f Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 28 Aug 2017 15:09:20 +0100 Subject: [PATCH 080/214] Check for xdebug.ini in ci/prepare.sh. --- ci/prepare.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ci/prepare.sh b/ci/prepare.sh index 8b6de760b6..795d27a829 100755 --- a/ci/prepare.sh +++ b/ci/prepare.sh @@ -7,7 +7,11 @@ set -ex WP_CLI_BIN_DIR=${WP_CLI_BIN_DIR-/tmp/wp-cli-phar} # Disable XDebug to speed up Composer and test suites. -phpenv config-rm xdebug.ini +if [ -f ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini ]; then + phpenv config-rm xdebug.ini +else + echo "xdebug.ini does not exist" +fi composer install --no-interaction --prefer-source From 4ca5ef111c6c8371ff348acf8b762c5b6258fb12 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 28 Aug 2017 15:24:44 +0100 Subject: [PATCH 081/214] Add phpunit6-compat. Use system phpunit. --- ci/test.sh | 2 +- tests/bootstrap.php | 7 +++++++ tests/phpunit6-compat.php | 19 +++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tests/phpunit6-compat.php diff --git a/ci/test.sh b/ci/test.sh index a86c01f730..31e6bc45e2 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -6,7 +6,7 @@ set -ex phpcs # Run the unit tests -vendor/bin/phpunit +phpunit BEHAT_TAGS=$(php ci/behat-tags.php) diff --git a/tests/bootstrap.php b/tests/bootstrap.php index f1c7040016..d0a2f3b594 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -2,6 +2,13 @@ define( 'WP_CLI_ROOT', dirname( __DIR__ ) ); +/** + * Compatibility with PHPUnit 6+ + */ +if ( class_exists( 'PHPUnit\Runner\Version' ) ) { + require_once __DIR__ . '/phpunit6-compat.php'; +} + if ( file_exists( WP_CLI_ROOT . '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/vendor/autoload.php' ) ) { define( 'WP_CLI_VENDOR_DIR' , WP_CLI_ROOT . '/vendor' ); } elseif ( file_exists( dirname( dirname( WP_CLI_ROOT ) ) . '/autoload.php' ) ) { diff --git a/tests/phpunit6-compat.php b/tests/phpunit6-compat.php new file mode 100644 index 0000000000..73d41cfed2 --- /dev/null +++ b/tests/phpunit6-compat.php @@ -0,0 +1,19 @@ +=' ) ) { + + class_alias( 'PHPUnit\Framework\TestCase', 'PHPUnit_Framework_TestCase' ); + class_alias( 'PHPUnit\Framework\Exception', 'PHPUnit_Framework_Exception' ); + class_alias( 'PHPUnit\Framework\ExpectationFailedException', 'PHPUnit_Framework_ExpectationFailedException' ); + class_alias( 'PHPUnit\Framework\Error\Notice', 'PHPUnit_Framework_Error_Notice' ); + class_alias( 'PHPUnit\Framework\Error\Warning', 'PHPUnit_Framework_Error_Warning' ); + class_alias( 'PHPUnit\Framework\Test', 'PHPUnit_Framework_Test' ); + class_alias( 'PHPUnit\Framework\Warning', 'PHPUnit_Framework_Warning' ); + class_alias( 'PHPUnit\Framework\AssertionFailedError', 'PHPUnit_Framework_AssertionFailedError' ); + class_alias( 'PHPUnit\Framework\TestSuite', 'PHPUnit_Framework_TestSuite' ); + class_alias( 'PHPUnit\Framework\TestListener', 'PHPUnit_Framework_TestListener' ); + class_alias( 'PHPUnit\Util\GlobalState', 'PHPUnit_Util_GlobalState' ); + class_alias( 'PHPUnit\Util\Getopt', 'PHPUnit_Util_Getopt' ); + +} From f6435ea6f2eaec6589bda2e4b8fdc6dcf3afa852 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 28 Aug 2017 15:50:58 +0100 Subject: [PATCH 082/214] Use trunk for PHP 7.2. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 93afd9e07b..73602de67d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ env: matrix: include: - php: 7.2 - env: WP_VERSION=latest + env: WP_VERSION=trunk - php: 7.1 env: WP_VERSION=latest - php: 7.0 From 0f2bd136034d6789281b5f8f31f93265ae9f6d29 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 28 Aug 2017 16:30:35 +0100 Subject: [PATCH 083/214] Exclude PHP 7.2 test. --- features/help.feature | 2 ++ 1 file changed, 2 insertions(+) diff --git a/features/help.feature b/features/help.feature index b7a9b8ff04..b17a996c59 100644 --- a/features/help.feature +++ b/features/help.feature @@ -91,6 +91,8 @@ Feature: Get help about WP-CLI commands """ And STDERR should be empty + # As of 4.8.1 (fixed in trunk), WP isn't compatible with PHP 7.2 due to `__autoload()` in "wp-includes/compat.php". + @less-than-php-7.2 Scenario: Help when WordPress is downloaded but not installed Given an empty directory From e64a4d9a388598fc671e2be73bee2e600cfdec3c Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 28 Aug 2017 16:45:35 +0100 Subject: [PATCH 084/214] Disable step in cli.feature:31 as hits github rate limiting. --- features/cli.feature | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/features/cli.feature b/features/cli.feature index 826453d4a5..554bee697b 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -64,11 +64,12 @@ Feature: `wp cli` tasks 0.0.0 """ - When I run `{PHAR_PATH} cli update` - Then STDOUT should be: - """ - Success: WP-CLI is at the latest version. - """ + #GITHUB_TOKEN: This can hit github rate limiting on Travis as the latest 1.3.0 phar doesn't use GITHUB_TOKEN. + #When I run `{PHAR_PATH} cli update` + #Then STDOUT should be: + #""" + #Success: WP-CLI is at the latest version. + #""" @travis-github-token Scenario: Patch update from 0.14.0 to 0.14.1 @@ -163,7 +164,7 @@ Feature: `wp cli` tasks And STDERR should be empty And the return code should be 0 - # This can hit github rate limiting on Travis as the latest 1.2.1 phar doesn't use GITHUB_TOKEN. + #GITHUB_TOKEN: This can hit github rate limiting on Travis as the latest 1.3.0 phar doesn't use GITHUB_TOKEN. #When I run `{PHAR_PATH} cli check-update` #Then STDOUT should be: #""" From 89a2a1711dfe521057e6d531d041f4c0fe5a6a23 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 28 Aug 2017 16:50:33 +0100 Subject: [PATCH 085/214] http_request: add url to error msgs, only re-try if local CACert problem. --- php/utils.php | 8 +++- tests/test-utils.php | 93 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 2 deletions(-) diff --git a/php/utils.php b/php/utils.php index d45955d3a2..bfa4ca749f 100644 --- a/php/utils.php +++ b/php/utils.php @@ -580,13 +580,17 @@ function http_request( $method, $url, $data = null, $headers = array(), $options $request = \Requests::request( $url, $headers, $data, $method, $options ); return $request; } catch( \Requests_Exception $ex ) { + // CURLE_SSL_CACERT_BADFILE only defined for PHP >= 7. + if ( 'curlerror' !== $ex->getType() || ! in_array( curl_errno( $ex->getData() ), array( CURLE_SSL_CONNECT_ERROR, CURLE_SSL_CERTPROBLEM, 77 /*CURLE_SSL_CACERT_BADFILE*/ ), true ) ) { + \WP_CLI::error( sprintf( "Failed to get url '%s': %s.", $url, $ex->getMessage() ) ); + } // Handle SSL certificate issues gracefully - \WP_CLI::warning( $ex->getMessage() ); + \WP_CLI::warning( sprintf( "Re-trying without verify after failing to get verified url '%s' %s.", $url, $ex->getMessage() ) ); $options['verify'] = false; try { return \Requests::request( $url, $headers, $data, $method, $options ); } catch( \Requests_Exception $ex ) { - \WP_CLI::error( $ex->getMessage() ); + \WP_CLI::error( sprintf( "Failed to get non-verified url '%s' %s.", $url, $ex->getMessage() ) ); } } } diff --git a/tests/test-utils.php b/tests/test-utils.php index c65e24b954..10e64c87d5 100644 --- a/tests/test-utils.php +++ b/tests/test-utils.php @@ -2,6 +2,8 @@ use WP_CLI\Utils; +require_once dirname( __DIR__ ) . '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/php/class-wp-cli.php'; + class UtilsTest extends PHPUnit_Framework_TestCase { function testIncrementVersion() { @@ -331,6 +333,97 @@ public function testGetTempDir() { } } + public function testHttpRequestBadAddress() { + // Save WP_CLI state. + $class_wp_cli_logger = new \ReflectionProperty( 'WP_CLI', 'logger' ); + $class_wp_cli_logger->setAccessible( true ); + $class_wp_cli_capture_exit = new \ReflectionProperty( 'WP_CLI', 'capture_exit' ); + $class_wp_cli_capture_exit->setAccessible( true ); + + $prev_logger = $class_wp_cli_logger->getValue(); + $prev_capture_exit = $class_wp_cli_capture_exit->getValue(); + + // Enable exit exception. + $class_wp_cli_capture_exit->setValue( true ); + + $logger = new \WP_CLI\Loggers\Execution; + WP_CLI::set_logger( $logger ); + + $exception = null; + try { + Utils\http_request( 'GET', 'https://nosuchhost_asdf_asdf_asdf.com' ); + } catch ( \WP_CLI\ExitException $ex ) { + $exception = $ex; + } + $this->assertTrue( null !== $exception ); + $this->assertTrue( 1 === $exception->getCode() ); + $this->assertTrue( empty( $logger->stdout ) ); + $this->assertTrue( false === strpos( $logger->stderr, 'Warning' ) ); + $this->assertTrue( 0 === strpos( $logger->stderr, 'Error: Failed to get url' ) ); + + // Restore. + $class_wp_cli_logger->setValue( $prev_logger ); + $class_wp_cli_capture_exit->setValue( $prev_capture_exit ); + } + + public function testHttpRequestBadCAcert() { + // Save WP_CLI state. + $class_wp_cli_logger = new \ReflectionProperty( 'WP_CLI', 'logger' ); + $class_wp_cli_logger->setAccessible( true ); + + $prev_logger = $class_wp_cli_logger->getValue(); + + $have_bad_cacert = false; + $created_dirs = array(); + + // Hack to create bad CAcert, using Utils\get_vendor_paths() preference for a path as part of a Composer-installed larger project. + $vendor_dir = WP_CLI_ROOT . '/../../../vendor'; + $cert_path = '/rmccue/requests/library/Requests/Transport/cacert.pem'; + $bad_cacert_path = $vendor_dir . $cert_path; + if ( ! file_exists( $bad_cacert_path ) ) { + // Capture any directories created so can clean up. + $dirs = array_merge( array( 'vendor' ), array_filter( explode( '/', dirname( $cert_path ) ) ) ); + $current_dir = dirname( $vendor_dir ); + foreach ( $dirs as $dir ) { + if ( ! file_exists( $current_dir . '/' . $dir ) ) { + if ( ! @mkdir( $current_dir . '/' . $dir ) ) { + break; + } + $created_dirs[] = $current_dir . '/' . $dir; + } + $current_dir .= '/' . $dir; + } + if ( $current_dir === dirname( $bad_cacert_path ) && file_put_contents( $bad_cacert_path, "-----BEGIN CERTIFICATE-----\nasdfasdf\n-----END CERTIFICATE-----\n" ) ) { + $have_bad_cacert = true; + } + } + + if ( ! $have_bad_cacert ) { + foreach ( array_reverse( $created_dirs ) as $created_dir ) { + rmdir( $created_dir ); + } + $this->markTestSkipped( 'Unable to create bad CAcert.' ); + } + + $logger = new \WP_CLI\Loggers\Execution; + WP_CLI::set_logger( $logger ); + + Utils\http_request( 'GET', 'https://example.com' ); + + // Undo bad CAcert hack before asserting. + unlink( $bad_cacert_path ); + foreach ( array_reverse( $created_dirs ) as $created_dir ) { + rmdir( $created_dir ); + } + + $this->assertTrue( empty( $logger->stdout ) ); + $this->assertTrue( 0 === strpos( $logger->stderr, 'Warning: Re-trying without verify after failing to get verified url' ) ); + $this->assertFalse( strpos( $logger->stderr, 'Error' ) ); + + // Restore. + $class_wp_cli_logger->setValue( $prev_logger ); + } + public function testRunMysqlCommandProcDisabled() { $err_msg = 'Error: Cannot do \'run_mysql_command\': The PHP functions `proc_open()` and/or `proc_close()` are disabled'; From 6f618008f2b8f90efc13b0e672eb6e8c9bc47654 Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 7 Sep 2017 18:12:53 +0100 Subject: [PATCH 086/214] Rejig FeatureContext to be more like master. Some phan fixes. --- features/bootstrap/FeatureContext.php | 75 +++++++++---------- php/WP_CLI/Bootstrap/AutoloaderStep.php | 3 +- .../Bootstrap/RegisterFrameworkCommands.php | 3 +- php/WP_CLI/Completions.php | 1 + php/WP_CLI/Dispatcher/CommandFactory.php | 10 +-- php/WP_CLI/Dispatcher/CompositeCommand.php | 2 +- php/WP_CLI/Runner.php | 2 + php/dispatcher.php | 4 +- php/utils.php | 8 +- 9 files changed, 54 insertions(+), 54 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 8e11cc6f73..b7ac7f859e 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -202,7 +202,6 @@ public static function afterSuite( SuiteEvent $event ) { // Then ctrl+C hit so cleanup any leftover scenario stuff. self::afterScenario_cleanup( $event ); } else { - // Test performance statistics - useful for detecting slow tests. if ( self::$log_run_times ) { self::log_run_times_after_suite( $event ); } @@ -535,7 +534,7 @@ private static function run_sql( $sql_cmd, $assoc_args = array(), $add_database $start_time = microtime( true ); Utils\run_mysql_command( $sql_cmd, array_merge( $assoc_args, $default_assoc_args ) ); if ( self::$log_run_times ) { - self::log_proc_method_run_time( $sql_cmd . ' ' . implode( ' ', $assoc_args ), $start_time ); + self::log_proc_method_run_time( $sql_cmd . ' ' . Utils\assoc_args_to_str( $assoc_args ), $start_time ); } } @@ -782,42 +781,6 @@ private function composer_command($cmd) { $this->proc( $this->variables['COMPOSER_PATH'] . ' ' . $cmd )->run_check(); } - /** - * Copy files in updated directory that are not in source directory to copy directory. ("Incremental backup".) - * Note: does not deal with changed files (ie does not compare file contents for changes), for speed reasons. - * - * @param string $upd_dir The directory to search looking for files/directories not in `$src_dir`. - * @param string $src_dir The directory to be compared to `$upd_dir`. - * @param string $cop_dir Where to copy any files/directories in `$upd_dir` but not in `$src_dir` to. - */ - private static function dir_diff_copy( $upd_dir, $src_dir, $cop_dir ) { - if ( false === ( $files = scandir( $upd_dir ) ) ) { - $error = error_get_last(); - throw new \RuntimeException( sprintf( "Failed to open updated directory '%s': %s. " . __FILE__ . ':' . __LINE__, $upd_dir, $error['message'] ) ); - } - foreach ( array_diff( $files, array( '.', '..' ) ) as $file ) { - $upd_file = $upd_dir . '/' . $file; - $src_file = $src_dir . '/' . $file; - $cop_file = $cop_dir . '/' . $file; - if ( ! file_exists( $src_file ) ) { - if ( is_dir( $upd_file ) ) { - if ( ! file_exists( $cop_file ) && ! mkdir( $cop_file, 0777, true /*recursive*/ ) ) { - $error = error_get_last(); - throw new \RuntimeException( sprintf( "Failed to create copy directory '%s': %s. " . __FILE__ . ':' . __LINE__, $cop_file, $error['message'] ) ); - } - self::copy_dir( $upd_file, $cop_file ); - } else { - if ( ! copy( $upd_file, $cop_file ) ) { - $error = error_get_last(); - throw new \RuntimeException( sprintf( "Failed to copy '%s' to '%s': %s. " . __FILE__ . ':' . __LINE__, $upd_file, $cop_file, $error['message'] ) ); - } - } - } elseif ( is_dir( $upd_file ) ) { - self::dir_diff_copy( $upd_file, $src_file, $cop_file ); - } - } - } - /** * Initialize run time logging. */ @@ -870,6 +833,42 @@ private static function log_run_times_after_scenario( $event ) { } } + /** + * Copy files in updated directory that are not in source directory to copy directory. ("Incremental backup".) + * Note: does not deal with changed files (ie does not compare file contents for changes), for speed reasons. + * + * @param string $upd_dir The directory to search looking for files/directories not in `$src_dir`. + * @param string $src_dir The directory to be compared to `$upd_dir`. + * @param string $cop_dir Where to copy any files/directories in `$upd_dir` but not in `$src_dir` to. + */ + private static function dir_diff_copy( $upd_dir, $src_dir, $cop_dir ) { + if ( false === ( $files = scandir( $upd_dir ) ) ) { + $error = error_get_last(); + throw new \RuntimeException( sprintf( "Failed to open updated directory '%s': %s. " . __FILE__ . ':' . __LINE__, $upd_dir, $error['message'] ) ); + } + foreach ( array_diff( $files, array( '.', '..' ) ) as $file ) { + $upd_file = $upd_dir . '/' . $file; + $src_file = $src_dir . '/' . $file; + $cop_file = $cop_dir . '/' . $file; + if ( ! file_exists( $src_file ) ) { + if ( is_dir( $upd_file ) ) { + if ( ! file_exists( $cop_file ) && ! mkdir( $cop_file, 0777, true /*recursive*/ ) ) { + $error = error_get_last(); + throw new \RuntimeException( sprintf( "Failed to create copy directory '%s': %s. " . __FILE__ . ':' . __LINE__, $cop_file, $error['message'] ) ); + } + self::copy_dir( $upd_file, $cop_file ); + } else { + if ( ! copy( $upd_file, $cop_file ) ) { + $error = error_get_last(); + throw new \RuntimeException( sprintf( "Failed to copy '%s' to '%s': %s. " . __FILE__ . ':' . __LINE__, $upd_file, $cop_file, $error['message'] ) ); + } + } + } elseif ( is_dir( $upd_file ) ) { + self::dir_diff_copy( $upd_file, $src_file, $cop_file ); + } + } + } + /** * Get the scenario key used for `$scenario_run_times` array. * Format " :", eg "core-command core-update.feature:221". diff --git a/php/WP_CLI/Bootstrap/AutoloaderStep.php b/php/WP_CLI/Bootstrap/AutoloaderStep.php index 0d9801a198..b7cf3ce015 100644 --- a/php/WP_CLI/Bootstrap/AutoloaderStep.php +++ b/php/WP_CLI/Bootstrap/AutoloaderStep.php @@ -44,8 +44,7 @@ public function process( BootstrapState $state ) { } catch ( \Exception $exception ) { \WP_CLI::warning( "Failed to load autoloader '{$autoloader_path}'. Reason: " - . $exception->getMessage(), - 'bootstrap' + . $exception->getMessage() ); } } diff --git a/php/WP_CLI/Bootstrap/RegisterFrameworkCommands.php b/php/WP_CLI/Bootstrap/RegisterFrameworkCommands.php index aca8c803e5..2020f3fddc 100644 --- a/php/WP_CLI/Bootstrap/RegisterFrameworkCommands.php +++ b/php/WP_CLI/Bootstrap/RegisterFrameworkCommands.php @@ -32,8 +32,7 @@ public function process( BootstrapState $state ) { include_once "$cmd_dir/$filename"; } catch ( \Exception $exception ) { \WP_CLI::warning( - "Could not add command {$cmd_dir}/{$filename}. Reason: " . $exception->getMessage(), - 'bootstrap' + "Could not add command {$cmd_dir}/{$filename}. Reason: " . $exception->getMessage() ); } } diff --git a/php/WP_CLI/Completions.php b/php/WP_CLI/Completions.php index 17484dd429..cd2fb824e7 100644 --- a/php/WP_CLI/Completions.php +++ b/php/WP_CLI/Completions.php @@ -6,6 +6,7 @@ class Completions { private $words; private $opts = array(); + private $cur_word; function __construct( $line ) { // TODO: properly parse single and double quotes diff --git a/php/WP_CLI/Dispatcher/CommandFactory.php b/php/WP_CLI/Dispatcher/CommandFactory.php index 8cf6f25d74..6e5f71932d 100644 --- a/php/WP_CLI/Dispatcher/CommandFactory.php +++ b/php/WP_CLI/Dispatcher/CommandFactory.php @@ -16,7 +16,7 @@ class CommandFactory { * Create a new CompositeCommand (or Subcommand if class has __invoke()) * * @param string $name Represents how the command should be invoked - * @param string $callable A subclass of WP_CLI_Command, a function, or a closure + * @param object|string|array $callable A subclass of WP_CLI_Command, a function, or a closure * @param mixed $parent The new command's parent Composite (or Root) command */ public static function create( $name, $callable, $parent ) { @@ -54,11 +54,9 @@ public static function clear_file_contents_cache() { * Create a new Subcommand instance. * * @param mixed $parent The new command's parent Composite command - * @param string $name Represents how the command should be invoked + * @param string|bool $name Represents how the command should be invoked. If false it's set from the docblock or reflection name. * @param mixed $callable A callable function or closure, or class name and method * @param object $reflection Reflection instance, for doc parsing - * @param string $class A subclass of WP_CLI_Command - * @param string $method Class method to be called upon invocation. */ private static function create_subcommand( $parent, $name, $callable, $reflection ) { $doc_comment = self::get_doc_comment( $reflection ); @@ -122,7 +120,7 @@ private static function create_composite_command( $parent, $name, $callable ) { /** * Check whether a method is actually callable. * - * @param ReflectionMethod $method + * @param \ReflectionMethod $method * @return bool */ private static function is_good_method( $method ) { @@ -132,7 +130,7 @@ private static function is_good_method( $method ) { /** * Gets the document comment. Caters for PHP directive `opcache.save comments` being disabled. * - * @param ReflectionMethod|ReflectionClass|ReflectionFunction $reflection Reflection instance. + * @param \ReflectionMethod|\ReflectionClass|\ReflectionFunction $reflection Reflection instance. * @return string|false|null Doc comment string if any, false if none (same as `Reflection*::getDocComment()`), null if error. */ private static function get_doc_comment( $reflection ) { diff --git a/php/WP_CLI/Dispatcher/CompositeCommand.php b/php/WP_CLI/Dispatcher/CompositeCommand.php index e33a5794dc..1908d97b17 100644 --- a/php/WP_CLI/Dispatcher/CompositeCommand.php +++ b/php/WP_CLI/Dispatcher/CompositeCommand.php @@ -249,7 +249,7 @@ private static function get_aliases( $subcommands ) { /** * Composite commands can only be known by one name. * - * @return false + * @return false|string */ public function get_alias() { return false; diff --git a/php/WP_CLI/Runner.php b/php/WP_CLI/Runner.php index b9b1fb86d4..30a3c6b7ec 100644 --- a/php/WP_CLI/Runner.php +++ b/php/WP_CLI/Runner.php @@ -24,6 +24,8 @@ class Runner { private $arguments, $assoc_args, $runtime_config; + private $colorize = false; + private $_early_invoke = array(); private $_global_config_path_debug; diff --git a/php/dispatcher.php b/php/dispatcher.php index bd11a3927e..90b8761dc7 100644 --- a/php/dispatcher.php +++ b/php/dispatcher.php @@ -5,8 +5,8 @@ /** * Get the path to a command, e.g. "core download" * - * @param WP_CLI\Dispatcher\Subcommand $command - * @return string + * @param CompositeCommand $command + * @return array */ function get_path( $command ) { $path = array(); diff --git a/php/utils.php b/php/utils.php index bfa4ca749f..fddb063b55 100644 --- a/php/utils.php +++ b/php/utils.php @@ -336,7 +336,8 @@ function pick_fields( $item, $fields ) { * @access public * @category Input * - * @param string $content Some form of text to edit (e.g. post content) + * @param string $input Some form of text to edit (e.g. post content) + * @param string $filename Optional. File name to use as base for temporary file. Default 'WP-CLI'. * @return string|bool Edited text, if file is saved from editor; false, if no change to file. */ function launch_editor_for_input( $input, $filename = 'WP-CLI' ) { @@ -348,7 +349,7 @@ function launch_editor_for_input( $input, $filename = 'WP-CLI' ) { do { $tmpfile = basename( $filename ); $tmpfile = preg_replace( '|\.[^.]*$|', '', $tmpfile ); - $tmpfile .= '-' . substr( md5( rand() ), 0, 6 ); + $tmpfile .= '-' . substr( md5( (string) rand() ), 0, 6 ); $tmpfile = $tmpdir . $tmpfile . '.tmp'; $fp = @fopen( $tmpfile, 'x' ); if ( ! $fp && is_writable( $tmpdir ) && file_exists( $tmpfile ) ) { @@ -952,6 +953,7 @@ function get_suggestion( $target, array $options, $threshold = 2 ) { if ( empty( $options ) ) { return ''; } + $levenshtein = array(); foreach ( $options as $option ) { $distance = levenshtein( $option, $target ); $levenshtein[ $option ] = $distance; @@ -1075,7 +1077,7 @@ function check_proc_available( $context = null, $return = false ) { /** * Wrapper around strtotime() that always interprets the string with a default timezone of UTC. * - * @param string $time A date/time string. + * @param string $str A date/time string. * @param int $now Optional. The timestamp which is used as a base for the calculation of relative dates. * * @return int|bool Returns a timestamp on success, false otherwise. From 58914f6a4f56777c574e622b933127ea6c4c29cb Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 25 Sep 2017 08:58:41 +0100 Subject: [PATCH 087/214] Enable (almost) full error_reporting and stderr check if testings. --- features/aliases.feature | 6 +-- features/bootstrap.feature | 8 ++-- features/bootstrap/FeatureContext.php | 12 ++++-- features/command.feature | 9 ++++- features/config.feature | 36 ++++------------- features/help.feature | 56 +++++---------------------- features/skip-plugins.feature | 5 ++- features/steps/given.php | 6 ++- php/WP_CLI/Extractor.php | 5 ++- php/WP_CLI/Process.php | 4 ++ php/WP_CLI/Runner.php | 16 ++++++++ php/commands/src/CLI_Command.php | 5 ++- phpcs.xml.dist | 6 +++ utils/make-phar.php | 6 +-- 14 files changed, 84 insertions(+), 96 deletions(-) diff --git a/features/aliases.feature b/features/aliases.feature index 10858de36f..d76d83aa37 100644 --- a/features/aliases.feature +++ b/features/aliases.feature @@ -349,21 +349,21 @@ Feature: Create shortcuts to specific WordPress installs """ And the return code should be 1 - When I run `wp @foo core is-installed --allow-root --debug` + When I try `wp @foo core is-installed --allow-root --debug` Then the return code should be 0 And STDERR should contain: """ @foo core is-installed --allow-root --debug """ - When I run `cd bar; wp @bar core is-installed --allow-root --debug` + When I try `cd bar; wp @bar core is-installed --allow-root --debug` Then the return code should be 0 And STDERR should contain: """ @bar core is-installed --allow-root --debug """ - When I run `wp @foobar core is-installed --allow-root --debug` + When I try `wp @foobar core is-installed --allow-root --debug` Then the return code should be 0 And STDERR should contain: """ diff --git a/features/bootstrap.feature b/features/bootstrap.feature index 52e548f75c..54e2c710a1 100644 --- a/features/bootstrap.feature +++ b/features/bootstrap.feature @@ -13,7 +13,7 @@ Feature: Bootstrap WP-CLI } } """ - And I run `composer install --no-interaction` + And I run `composer install --no-interaction 2>&1` When I run `vendor/bin/wp cli version` Then STDOUT should contain: @@ -82,7 +82,7 @@ Feature: Bootstrap WP-CLI } } """ - And I run `composer install --no-interaction` + And I run `composer install --no-interaction 2>&1` When I run `vendor/bin/wp cli version` Then STDOUT should contain: @@ -130,7 +130,7 @@ Feature: Bootstrap WP-CLI } } """ - And I run `composer install --working-dir={RUN_DIR}/cli-override-command --no-interaction` + And I run `composer install --working-dir={RUN_DIR}/cli-override-command --no-interaction 2>&1` When I run `wp cli version` Then STDOUT should contain: @@ -185,7 +185,7 @@ Feature: Bootstrap WP-CLI } } """ - And I run `composer install --working-dir={RUN_DIR}/cli-override-command --no-interaction` + And I run `composer install --working-dir={RUN_DIR}/cli-override-command --no-interaction 2>&1` When I run `{PHAR_PATH} cli version` Then STDOUT should contain: diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index aaa2211add..4aa7db80cb 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -475,7 +475,7 @@ public function build_phar( $version = 'same', $build = '' ) { } $this->proc( Utils\esc_cmd( - 'php -dphar.readonly=0 %1$s %2$s --version=%3$s --quiet --build=%4$s && chmod +x %2$s', + 'php -dphar.readonly=0 %1$s %2$s --version=%3$s --quiet --build=%4$s', $make_phar_path, $this->variables['PHAR_PATH'], $version, @@ -681,7 +681,8 @@ public function install_wp( $subdir = '' ) { 'title' => 'WP CLI Site', 'admin_user' => 'admin', 'admin_email' => 'admin@example.com', - 'admin_password' => 'password1' + 'admin_password' => 'password1', + 'skip-email' => true, ); $install_cache_path = ''; @@ -722,7 +723,8 @@ public function install_wp_with_composer( $vendor_directory = 'vendor' ) { 'title' => 'WP CLI Site with both WordPress and wp-cli as Composer dependencies', 'admin_user' => 'admin', 'admin_email' => 'admin@example.com', - 'admin_password' => 'password1' + 'admin_password' => 'password1', + 'skip-email' => true, ); $this->proc( 'wp core install', $install_args )->run_check(); @@ -782,6 +784,10 @@ private function composer_command($cmd) { if ( !isset( $this->variables['COMPOSER_PATH'] ) ) { $this->variables['COMPOSER_PATH'] = exec('which composer'); } + // Redirect composer messages from stderr to stdout. + if ( false === strpos( $cmd, '>' ) ) { + $cmd .= ' 2>&1'; + } $this->proc( $this->variables['COMPOSER_PATH'] . ' ' . $cmd )->run_check(); } diff --git a/features/command.feature b/features/command.feature index 053aa9aa66..6135492a20 100644 --- a/features/command.feature +++ b/features/command.feature @@ -783,8 +783,13 @@ Feature: WP-CLI Commands WP_CLI::add_command( 'test-command-2', function () {} ); """ - When I run `wp --require=abort-add-command.php` - Then STDOUT should contain: + When I try `wp --require=abort-add-command.php` + Then the return code should be 0 + And STDERR should contain: + """ + Warning: Aborting the addition of the command 'test-command-2' + """ + And STDOUT should contain: """ test-command-1 """ diff --git a/features/config.feature b/features/config.feature index 9b88a854a6..68b8749e07 100644 --- a/features/config.feature +++ b/features/config.feature @@ -237,8 +237,9 @@ Feature: Have a config file Scenario: Load WordPress with `--debug` Given a WP install - When I run `wp option get home --debug` - Then STDERR should contain: + When I try `wp option get home --debug` + Then the return code should be 0 + And STDERR should contain: """ No readable global config found """ @@ -263,8 +264,9 @@ Feature: Have a config file Running command: option get """ - When I run `wp option get home --debug=bootstrap` - Then STDERR should contain: + When I try `wp option get home --debug=bootstrap` + Then the return code should be 0 + And STDERR should contain: """ No readable global config found """ @@ -290,30 +292,8 @@ Feature: Have a config file """ When I run `wp option get home --debug=foo` - Then STDERR should not contain: - """ - No readable global config found - """ - Then STDERR should not contain: - """ - No project config found - """ - And STDERR should not contain: - """ - Begin WordPress load - """ - And STDERR should not contain: - """ - wp-config.php path: - """ - And STDERR should not contain: - """ - Loaded WordPress - """ - And STDERR should not contain: - """ - Running command: option get - """ + Then the return code should be 0 + And STDERR should be empty Scenario: Missing required files should not fatal WP-CLI Given an empty directory diff --git a/features/help.feature b/features/help.feature index b17a996c59..485f9df63e 100644 --- a/features/help.feature +++ b/features/help.feature @@ -50,6 +50,7 @@ Feature: Get help about WP-CLI commands @require-wp-4.3 Scenario: Help for internal commands with WP Given a WP install + # Check for errors/warnings when loading WP. And a stderr-error-log.php file: """ install_wp(); $subdomains = ! empty( $type ) && 'subdomain' === $type ? 1 : 0; - $world->proc( 'wp core install-network', array( 'title' => 'WP CLI Network', 'subdomains' => $subdomains ) )->run_check(); + // Ignore "Warning: Wildcard DNS may not be configured correctly.". + $r = $world->proc( 'wp core install-network', array( 'title' => 'WP CLI Network', 'subdomains' => $subdomains ) )->run(); + if ( $r->return_code || ( ! empty( $r->stderr ) && 'Warning: Wildcard DNS may not be configured correctly.' !== trim( $r->stderr ) ) ) { + throw new \RuntimeException( $r ); + } } ); diff --git a/php/WP_CLI/Extractor.php b/php/WP_CLI/Extractor.php index 35bb67118c..b93e375f80 100644 --- a/php/WP_CLI/Extractor.php +++ b/php/WP_CLI/Extractor.php @@ -90,7 +90,10 @@ private static function extract_tarball( $tarball, $dest ) { self::rmdir( dirname( $tempdir ) ); return; } catch ( \Exception $e ) { - WP_CLI::warning( "PharData failed, falling back to 'tar gz' (" . $e->getMessage() . ')' ); + // PHP bug in `zlib_filter`, triggered on distributions with the "lp564920-fix-big-files" Debian patch. + if ( sprintf( 'unable to decompress gzipped phar archive "%s" to temporary file', $tarball ) !== $e->getMessage() ) { + WP_CLI::warning( "PharData failed, falling back to 'tar gz' (" . $e->getMessage() . ')' ); + } // Fall through to trying `tar xz` below } } diff --git a/php/WP_CLI/Process.php b/php/WP_CLI/Process.php index 5016580b71..d088685354 100644 --- a/php/WP_CLI/Process.php +++ b/php/WP_CLI/Process.php @@ -112,6 +112,10 @@ public function run_check() { if ( $r->return_code || ! empty( $r->STDERR ) ) { throw new \RuntimeException( $r ); } + // But do it right if testing. + if ( ! empty( $this->env['BEHAT_RUN'] ) && ( $r->return_code || ! empty( $r->stderr ) ) ) { + throw new \RuntimeException( $r ); + } return $r; } diff --git a/php/WP_CLI/Runner.php b/php/WP_CLI/Runner.php index 912b3966d3..5a691fdb28 100644 --- a/php/WP_CLI/Runner.php +++ b/php/WP_CLI/Runner.php @@ -309,6 +309,9 @@ public function find_command_to_run( $args ) { * @param array $options Configuration options for the function. */ public function run_command( $args, $assoc_args = array(), $options = array() ) { + // Enable PHP error reporting to stderr if testing. + $this->behat_enable_error_reporting(); + if ( ! empty( $options['back_compat_conversions'] ) ) { list( $args, $assoc_args ) = self::back_compat_conversions( $args, $assoc_args ); } @@ -1581,4 +1584,17 @@ private function enumerate_commands( CompositeCommand $command, array &$list, $p $this->enumerate_commands( $subcommand, $list, $command_string ); } } + + /** + * Enables (almost) full PHP error reporting to stderr if testing. + */ + private function behat_enable_error_reporting() { + if ( getenv( 'BEHAT_RUN' ) ) { + if ( E_ALL !== error_reporting() ) { + // Don't enable E_DEPRECATED as old versions of WP use PHP 4 style constructors and the mysql extension. + error_reporting( E_ALL & ~E_DEPRECATED ); + } + ini_set( 'display_errors', 'stderr' ); + } + } } diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index aaf7f46acf..77bcea181d 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -401,7 +401,10 @@ private function get_updates( $assoc_args ) { // Reduce the data to what's used. $release_data = array_merge( $release_data, array_map( function ( $v ) { - return (object) array( 'tag_name' => $v->tag_name, 'assets' => array( (object) array( 'browser_download_url' => $v->assets[0]->browser_download_url ) ) ); + return (object) array( + 'tag_name' => $v->tag_name, + 'assets' => array( (object) array( 'browser_download_url' => $v->assets[0]->browser_download_url ) ), + ); }, json_decode( $response->body ) ) ); diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 43c959276e..ee8e0ddf8f 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -18,10 +18,15 @@ */tests/* */utils/* */vendor/* + */.phan/* + + + + @@ -31,5 +36,6 @@ + diff --git a/utils/make-phar.php b/utils/make-phar.php index cdff3ca7da..5f99915de5 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -93,15 +93,13 @@ function add_file( $phar, $path ) { } function strip_comments( $contents, $keep_doc_comments ) { - $first_comment = true; - $strs = array_map( function ( $t ) use ( $keep_doc_comments, &$first_comment ) { + $strs = array_map( function ( $t ) use ( $keep_doc_comments ) { if ( is_string( $t ) ) { return $t; } if ( T_COMMENT === $t[0] || ( ! $keep_doc_comments && T_DOC_COMMENT === $t[0] ) ) { - if ( $first_comment ) { + if ( preg_match( '/copyright|license|\(c\)/i', $t[1] ) ) { // Keep for copyright reasons. - $first_comment = false; return $t[1]; } return str_repeat( "\n", substr_count( $t[1], "\n" ) ); // Strip everything but newlines. From 55b69015ad5b5bda5529e7e5ef45319cf9b2f6df Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 25 Sep 2017 10:43:07 +0100 Subject: [PATCH 088/214] Suppress md5 hash checksum not available warning in FeatureContext. --- features/bootstrap/FeatureContext.php | 2 ++ php/WP_CLI/Extractor.php | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 4aa7db80cb..435cc1f389 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -160,6 +160,8 @@ private static function cache_wp_files() { if ( $wp_version ) { $cmd .= Utils\esc_cmd( ' --version=%s', $wp_version ); } + // Redirect any warnings (eg md5 hash checks not available). + $cmd .= ' 2>&1'; Process::create( $cmd, null, self::get_process_env_variables() )->run_check(); } diff --git a/php/WP_CLI/Extractor.php b/php/WP_CLI/Extractor.php index b93e375f80..9f58b23d27 100644 --- a/php/WP_CLI/Extractor.php +++ b/php/WP_CLI/Extractor.php @@ -90,7 +90,7 @@ private static function extract_tarball( $tarball, $dest ) { self::rmdir( dirname( $tempdir ) ); return; } catch ( \Exception $e ) { - // PHP bug in `zlib_filter`, triggered on distributions with the "lp564920-fix-big-files" Debian patch. + // Don't warn on PHP bug in `zlib_filter`, triggered on distributions with the "lp564920-fix-big-files" Debian patch. if ( sprintf( 'unable to decompress gzipped phar archive "%s" to temporary file', $tarball ) !== $e->getMessage() ) { WP_CLI::warning( "PharData failed, falling back to 'tar gz' (" . $e->getMessage() . ')' ); } From 847160fc01994e6e16bd20742ea97ee0a7bb07a6 Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 26 Sep 2017 06:50:53 +0100 Subject: [PATCH 089/214] Disable test error_reporting, Process stderr. --- composer.lock | 2 +- php/WP_CLI/Process.php | 2 ++ php/WP_CLI/Runner.php | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/composer.lock b/composer.lock index 127e39b435..f3822f2707 100644 --- a/composer.lock +++ b/composer.lock @@ -1356,7 +1356,7 @@ ], "description": "Composer plugin for splitting a generated autoloader into two distinct parts.", "homepage": "https://wp-cli.org", - "time": "2017-08-03T08:40:17+00:00" + "time": "2017-08-03T08:40:16+00:00" }, { "name": "wp-cli/cache-command", diff --git a/php/WP_CLI/Process.php b/php/WP_CLI/Process.php index d088685354..f718743757 100644 --- a/php/WP_CLI/Process.php +++ b/php/WP_CLI/Process.php @@ -112,10 +112,12 @@ public function run_check() { if ( $r->return_code || ! empty( $r->STDERR ) ) { throw new \RuntimeException( $r ); } + /* // But do it right if testing. if ( ! empty( $this->env['BEHAT_RUN'] ) && ( $r->return_code || ! empty( $r->stderr ) ) ) { throw new \RuntimeException( $r ); } + */ return $r; } diff --git a/php/WP_CLI/Runner.php b/php/WP_CLI/Runner.php index 5a691fdb28..b5822bc894 100644 --- a/php/WP_CLI/Runner.php +++ b/php/WP_CLI/Runner.php @@ -1589,6 +1589,7 @@ private function enumerate_commands( CompositeCommand $command, array &$list, $p * Enables (almost) full PHP error reporting to stderr if testing. */ private function behat_enable_error_reporting() { + return; if ( getenv( 'BEHAT_RUN' ) ) { if ( E_ALL !== error_reporting() ) { // Don't enable E_DEPRECATED as old versions of WP use PHP 4 style constructors and the mysql extension. From d2a713801d0617ae7d4e189cdebcfce4843ad295 Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 26 Sep 2017 07:55:03 +0100 Subject: [PATCH 090/214] Howabout not stripping comments from search-replace? --- utils/make-phar.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/make-phar.php b/utils/make-phar.php index 5f99915de5..f450ffcb54 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -55,7 +55,7 @@ function add_file( $phar, $path ) { $file_contents = file_get_contents( $path ); if ( preg_match( '/.php$/', $path ) ) { - $is_wp_cli_command = preg_match( '/\/(?:php\/commands|vendor\/wp-cli\/[^-]*-command\/src)\//', $path ); + $is_wp_cli_command = preg_match( '/\/(?:php\/commands|vendor\/wp-cli\/[^\/]*?-command\/src)\//', $path ); $file_contents = strip_comments( $file_contents, $is_wp_cli_command /*keep_doc_comments*/ ); } From fc95609113d95ddeb5e8378c5944a4f9e8f21c6c Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 26 Sep 2017 16:17:02 +0100 Subject: [PATCH 091/214] Restore chmod to phar. --- features/bootstrap/FeatureContext.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 435cc1f389..e40d8f7535 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -477,7 +477,7 @@ public function build_phar( $version = 'same', $build = '' ) { } $this->proc( Utils\esc_cmd( - 'php -dphar.readonly=0 %1$s %2$s --version=%3$s --quiet --build=%4$s', + 'php -dphar.readonly=0 %1$s %2$s --version=%3$s --quiet --build=%4$s && chmod +x %2$s', $make_phar_path, $this->variables['PHAR_PATH'], $version, From 81442464a101bbe9d43ecf8260bb390c34b4affb Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 27 Sep 2017 07:41:12 +0100 Subject: [PATCH 092/214] Which php. --- .travis.yml | 1 + php/WP_CLI/Extractor.php | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 73602de67d..f41db42d50 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,6 +31,7 @@ matrix: before_script: - export PATH="$HOME/.composer/vendor/bin:$PATH" + - which -a php - | composer global require wp-coding-standards/wpcs:0.12.0 phpcs --config-set installed_paths $HOME/.composer/vendor/wp-coding-standards/wpcs diff --git a/php/WP_CLI/Extractor.php b/php/WP_CLI/Extractor.php index 9f58b23d27..35bb67118c 100644 --- a/php/WP_CLI/Extractor.php +++ b/php/WP_CLI/Extractor.php @@ -90,10 +90,7 @@ private static function extract_tarball( $tarball, $dest ) { self::rmdir( dirname( $tempdir ) ); return; } catch ( \Exception $e ) { - // Don't warn on PHP bug in `zlib_filter`, triggered on distributions with the "lp564920-fix-big-files" Debian patch. - if ( sprintf( 'unable to decompress gzipped phar archive "%s" to temporary file', $tarball ) !== $e->getMessage() ) { - WP_CLI::warning( "PharData failed, falling back to 'tar gz' (" . $e->getMessage() . ')' ); - } + WP_CLI::warning( "PharData failed, falling back to 'tar gz' (" . $e->getMessage() . ')' ); // Fall through to trying `tar xz` below } } From 6b8f49aa2ac52a2a4ada4de3effd5692d9f37e7b Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 27 Sep 2017 09:31:55 +0100 Subject: [PATCH 093/214] Debug PATH. --- .travis.yml | 1 + features/bootstrap/FeatureContext.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f41db42d50..0e705b1775 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,6 +31,7 @@ matrix: before_script: - export PATH="$HOME/.composer/vendor/bin:$PATH" + - echo $PATH - which -a php - | composer global require wp-coding-standards/wpcs:0.12.0 diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index e40d8f7535..7f8f4a7380 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -123,7 +123,7 @@ private static function get_process_env_variables() { $bin_dir = getenv( 'WP_CLI_BIN_DIR' ) ?: realpath( __DIR__ . '/../../bin' ); $vendor_dir = realpath( __DIR__ . '/../../vendor/bin' ); $env = array( - 'PATH' => $bin_dir . ':' . $vendor_dir . ':' . getenv( 'PATH' ), + 'PATH' => $bin_dir . ':' . $vendor_dir . ':' . getenv( 'PATH' ) . ':/home/travis/.phpenv/shims', 'BEHAT_RUN' => 1, 'HOME' => sys_get_temp_dir() . '/wp-cli-home', ); From adbf638594a7460768ffad18c4e82e0ade268996 Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 29 Sep 2017 03:56:25 +0100 Subject: [PATCH 094/214] Use PHP_BINDIR. --- features/bootstrap/FeatureContext.php | 2 +- php/class-wp-cli.php | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 7f8f4a7380..e40d8f7535 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -123,7 +123,7 @@ private static function get_process_env_variables() { $bin_dir = getenv( 'WP_CLI_BIN_DIR' ) ?: realpath( __DIR__ . '/../../bin' ); $vendor_dir = realpath( __DIR__ . '/../../vendor/bin' ); $env = array( - 'PATH' => $bin_dir . ':' . $vendor_dir . ':' . getenv( 'PATH' ) . ':/home/travis/.phpenv/shims', + 'PATH' => $bin_dir . ':' . $vendor_dir . ':' . getenv( 'PATH' ), 'BEHAT_RUN' => 1, 'HOME' => sys_get_temp_dir() . '/wp-cli-home', ); diff --git a/php/class-wp-cli.php b/php/class-wp-cli.php index d9f4ae7393..c548c9f936 100644 --- a/php/class-wp-cli.php +++ b/php/class-wp-cli.php @@ -1030,6 +1030,10 @@ public static function get_php_binary() { return PHP_BINARY; } + if ( defined( 'PHP_BINDIR' ) ) { + return PHP_BINDIR . '/php'; + } + return 'php'; } From 99c50303fb4866e5297f489757e78ebe2fb29aa4 Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 29 Sep 2017 05:00:27 +0100 Subject: [PATCH 095/214] Reenable behat error_reporting and stderr check. --- .travis.yml | 2 -- features/bootstrap/FeatureContext.php | 2 +- php/WP_CLI/Process.php | 2 -- php/WP_CLI/Runner.php | 1 - 4 files changed, 1 insertion(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0e705b1775..73602de67d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,8 +31,6 @@ matrix: before_script: - export PATH="$HOME/.composer/vendor/bin:$PATH" - - echo $PATH - - which -a php - | composer global require wp-coding-standards/wpcs:0.12.0 phpcs --config-set installed_paths $HOME/.composer/vendor/wp-coding-standards/wpcs diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index e40d8f7535..435cc1f389 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -477,7 +477,7 @@ public function build_phar( $version = 'same', $build = '' ) { } $this->proc( Utils\esc_cmd( - 'php -dphar.readonly=0 %1$s %2$s --version=%3$s --quiet --build=%4$s && chmod +x %2$s', + 'php -dphar.readonly=0 %1$s %2$s --version=%3$s --quiet --build=%4$s', $make_phar_path, $this->variables['PHAR_PATH'], $version, diff --git a/php/WP_CLI/Process.php b/php/WP_CLI/Process.php index f718743757..d088685354 100644 --- a/php/WP_CLI/Process.php +++ b/php/WP_CLI/Process.php @@ -112,12 +112,10 @@ public function run_check() { if ( $r->return_code || ! empty( $r->STDERR ) ) { throw new \RuntimeException( $r ); } - /* // But do it right if testing. if ( ! empty( $this->env['BEHAT_RUN'] ) && ( $r->return_code || ! empty( $r->stderr ) ) ) { throw new \RuntimeException( $r ); } - */ return $r; } diff --git a/php/WP_CLI/Runner.php b/php/WP_CLI/Runner.php index b5822bc894..5a691fdb28 100644 --- a/php/WP_CLI/Runner.php +++ b/php/WP_CLI/Runner.php @@ -1589,7 +1589,6 @@ private function enumerate_commands( CompositeCommand $command, array &$list, $p * Enables (almost) full PHP error reporting to stderr if testing. */ private function behat_enable_error_reporting() { - return; if ( getenv( 'BEHAT_RUN' ) ) { if ( E_ALL !== error_reporting() ) { // Don't enable E_DEPRECATED as old versions of WP use PHP 4 style constructors and the mysql extension. From 5dd2b8f765099b5a4d9101e9bd6b577962029b69 Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 29 Sep 2017 06:25:13 +0100 Subject: [PATCH 096/214] Use try for flags.feature:46 for PHP 7.2. Extractor workaround. --- features/flags.feature | 5 +++-- php/WP_CLI/Extractor.php | 29 ++++++++++++++++------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/features/flags.feature b/features/flags.feature index 3636a007eb..34aaf2c36b 100644 --- a/features/flags.feature +++ b/features/flags.feature @@ -46,8 +46,9 @@ Feature: Global flags Scenario: Debug run Given a WP install - When I run `wp eval 'echo CONST_WITHOUT_QUOTES;'` - Then STDOUT should be: + When I try `wp eval 'echo CONST_WITHOUT_QUOTES;'` + Then the return code should be 0 + And STDOUT should be: """ CONST_WITHOUT_QUOTES """ diff --git a/php/WP_CLI/Extractor.php b/php/WP_CLI/Extractor.php index 35bb67118c..300ac3670b 100644 --- a/php/WP_CLI/Extractor.php +++ b/php/WP_CLI/Extractor.php @@ -73,21 +73,24 @@ private static function extract_tarball( $tarball, $dest ) { if ( class_exists( 'PharData' ) ) { try { - $phar = new PharData( $tarball ); - $tempdir = implode( - DIRECTORY_SEPARATOR, - array( - dirname( $tarball ), - Utils\basename( $tarball, '.tar.gz' ), - $phar->getFileName(), - ) - ); - - $phar->extractTo( dirname( $tempdir ), null, true ); + // If on Ubuntu (or derivative) check if PHP bug #75273 likely to be triggered and copy to temporary tar if so. + $pre_tar = false; + if ( false !== strpos( PHP_VERSION, 'ubuntu' ) ) { // Unfortunately Debian doesn't sign its PHP build so not easy to check for it. + $tar_size = filesize( $tarball ); + $pre_tar = $tar_size > 4 * 1024 * 1024 && $tar_size % ( 8 * 1024 ) < 10; + } + if ( $pre_tar ) { + $temp_tar = Utils\get_temp_dir() . uniqid( 'wp-cli-extract-', true ) . '.tar'; + if ( false === ( $contents = file_get_contents( 'compress.zlib://' . $tarball ) ) || false === file_put_contents( $temp_tar, $contents ) ) { + throw new \Exception( "Error creating temporary tar '$temp_tar'." ); + } - self::copy_overwrite_files( $tempdir, $dest ); + self::copy_overwrite_files( 'phar://' . $temp_tar, $dest ); - self::rmdir( dirname( $tempdir ) ); + unlink( $temp_tar ); + } else { + self::copy_overwrite_files( 'phar://' . $tarball, $dest ); + } return; } catch ( \Exception $e ) { WP_CLI::warning( "PharData failed, falling back to 'tar gz' (" . $e->getMessage() . ')' ); From c133c970af049ef3f01ad9ffc83fd236955ab4c5 Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 29 Sep 2017 07:34:38 +0100 Subject: [PATCH 097/214] Add strip-components to Extractor::copy_overwrite_files. --- php/WP_CLI/Extractor.php | 10 +++++++--- utils/make-phar.php | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/php/WP_CLI/Extractor.php b/php/WP_CLI/Extractor.php index 300ac3670b..6a81e6979a 100644 --- a/php/WP_CLI/Extractor.php +++ b/php/WP_CLI/Extractor.php @@ -85,11 +85,11 @@ private static function extract_tarball( $tarball, $dest ) { throw new \Exception( "Error creating temporary tar '$temp_tar'." ); } - self::copy_overwrite_files( 'phar://' . $temp_tar, $dest ); + self::copy_overwrite_files( 'phar://' . $temp_tar, $dest, 1 /*strip_components*/ ); unlink( $temp_tar ); } else { - self::copy_overwrite_files( 'phar://' . $tarball, $dest ); + self::copy_overwrite_files( 'phar://' . $tarball, $dest, 1 /*strip_components*/ ); } return; } catch ( \Exception $e ) { @@ -101,7 +101,7 @@ private static function extract_tarball( $tarball, $dest ) { WP_CLI::launch( Utils\esc_cmd( $cmd, $dest ) ); } - public static function copy_overwrite_files( $source, $dest ) { + public static function copy_overwrite_files( $source, $dest, $strip_components = 0 ) { $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $source, RecursiveDirectoryIterator::SKIP_DOTS ), RecursiveIteratorIterator::SELF_FIRST @@ -115,6 +115,10 @@ public static function copy_overwrite_files( $source, $dest ) { foreach ( $iterator as $item ) { + if ( $strip_components > 0 ) { + return self::copy_overwrite_files( $item, $dest, --$strip_components ); + } + $dest_path = $dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName(); if ( $item->isDir() ) { diff --git a/utils/make-phar.php b/utils/make-phar.php index f450ffcb54..3710a08874 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -54,7 +54,7 @@ function add_file( $phar, $path ) { echo "$key - $path\n"; $file_contents = file_get_contents( $path ); - if ( preg_match( '/.php$/', $path ) ) { + if ( preg_match( '/\.php$/', $path ) ) { $is_wp_cli_command = preg_match( '/\/(?:php\/commands|vendor\/wp-cli\/[^\/]*?-command\/src)\//', $path ); $file_contents = strip_comments( $file_contents, $is_wp_cli_command /*keep_doc_comments*/ ); } From 51b4c9cd34bba36a2a2626ca9e7137dbe97e7bef Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 29 Sep 2017 08:26:10 +0100 Subject: [PATCH 098/214] behat_enable_error_reporting -> maybe_enable_error_reporting. --- php/WP_CLI/Runner.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php/WP_CLI/Runner.php b/php/WP_CLI/Runner.php index 5a691fdb28..541ef3e6f1 100644 --- a/php/WP_CLI/Runner.php +++ b/php/WP_CLI/Runner.php @@ -310,7 +310,7 @@ public function find_command_to_run( $args ) { */ public function run_command( $args, $assoc_args = array(), $options = array() ) { // Enable PHP error reporting to stderr if testing. - $this->behat_enable_error_reporting(); + $this->maybe_enable_error_reporting(); if ( ! empty( $options['back_compat_conversions'] ) ) { list( $args, $assoc_args ) = self::back_compat_conversions( $args, $assoc_args ); @@ -1588,7 +1588,7 @@ private function enumerate_commands( CompositeCommand $command, array &$list, $p /** * Enables (almost) full PHP error reporting to stderr if testing. */ - private function behat_enable_error_reporting() { + private function maybe_enable_error_reporting() { if ( getenv( 'BEHAT_RUN' ) ) { if ( E_ALL !== error_reporting() ) { // Don't enable E_DEPRECATED as old versions of WP use PHP 4 style constructors and the mysql extension. From ce4b22c5f6d7332aea76b4f3c998069b07109163 Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 29 Sep 2017 09:39:55 +0100 Subject: [PATCH 099/214] Fiddle with make-phar regexs. --- utils/make-phar.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/utils/make-phar.php b/utils/make-phar.php index 3710a08874..66969e06d6 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -54,8 +54,8 @@ function add_file( $phar, $path ) { echo "$key - $path\n"; $file_contents = file_get_contents( $path ); - if ( preg_match( '/\.php$/', $path ) ) { - $is_wp_cli_command = preg_match( '/\/(?:php\/commands|vendor\/wp-cli\/[^\/]*?-command\/src)\//', $path ); + if ( 0 === substr_compare( $path, '.php', -4 ) ) { + $is_wp_cli_command = preg_match( '/\/(?:php\/commands|vendor\/wp-cli\/[^\/]+?-command\/src)\//', $path ); $file_contents = strip_comments( $file_contents, $is_wp_cli_command /*keep_doc_comments*/ ); } @@ -70,14 +70,14 @@ function add_file( $phar, $path ) { '\/phpunit\/', '\/nb\/oxymel\/', '-command\/src\/', - '\/wp-cli\/[^\n]+-command\/', - '\/symfony\/(?!finder|polyfill-mbstring)[^\/]+\/', + '\/wp-cli\/[^\n]+?-command\/', + '\/symfony\/(?!finder|polyfill-mbstring)[^\/]+?\/', ); } else { $strips = array( '\/(?:behat|gherkin)\/src\/', '\/phpunit\/', - '\/symfony\/(?!console|filesystem|finder|polyfill-mbstring|process)[^\/]+\/', + '\/symfony\/(?!console|filesystem|finder|polyfill-mbstring|process)[^\/]+?\/', '\/composer\/spdx-licenses\/', '\/Composer\/(?:Command\/|Compiler\.php|Console\/|Downloader\/Pear|Installer\/Pear|Question\/|Repository\/Pear|SelfUpdate\/)', ); From b8e2a9dcc506de0b2f6c5bea609bd13e10b05c9b Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 30 Sep 2017 17:16:22 +0100 Subject: [PATCH 100/214] Extractor refactor. --- features/command.feature | 12 +-- features/config.feature | 16 ++-- features/flags.feature | 9 +-- features/framework.feature | 10 ++- php/WP_CLI/Extractor.php | 134 ++++++++++++++++++-------------- php/WP_CLI/Runner.php | 27 ++++--- tests/test-extractor.php | 155 +++++++++++++++++++++++++++++++++++++ 7 files changed, 272 insertions(+), 91 deletions(-) create mode 100644 tests/test-extractor.php diff --git a/features/command.feature b/features/command.feature index 6135492a20..d1de823770 100644 --- a/features/command.feature +++ b/features/command.feature @@ -784,12 +784,7 @@ Feature: WP-CLI Commands """ When I try `wp --require=abort-add-command.php` - Then the return code should be 0 - And STDERR should contain: - """ - Warning: Aborting the addition of the command 'test-command-2' - """ - And STDOUT should contain: + Then STDOUT should contain: """ test-command-1 """ @@ -797,6 +792,11 @@ Feature: WP-CLI Commands """ test-command-2 """ + And STDERR should contain: + """ + Warning: Aborting the addition of the command 'test-command-2' + """ + And the return code should be 0 Scenario: Adding a command can depend on a previous command having been added before Given an empty directory diff --git a/features/config.feature b/features/config.feature index 68b8749e07..ec0916803a 100644 --- a/features/config.feature +++ b/features/config.feature @@ -232,18 +232,17 @@ Feature: Have a config file """ When I run `WP_CLI_CONFIG_PATH=test-dir/config.yml wp help` - Then STDERR should be empty + Then STDERR should be empty Scenario: Load WordPress with `--debug` Given a WP install When I try `wp option get home --debug` - Then the return code should be 0 - And STDERR should contain: + Then STDERR should contain: """ No readable global config found """ - Then STDERR should contain: + And STDERR should contain: """ No project config found """ @@ -263,10 +262,10 @@ Feature: Have a config file """ Running command: option get """ + And the return code should be 0 When I try `wp option get home --debug=bootstrap` - Then the return code should be 0 - And STDERR should contain: + Then STDERR should contain: """ No readable global config found """ @@ -290,10 +289,11 @@ Feature: Have a config file """ Running command: option get """ + And the return code should be 0 When I run `wp option get home --debug=foo` - Then the return code should be 0 - And STDERR should be empty + Then STDERR should be empty + And the return code should be 0 Scenario: Missing required files should not fatal WP-CLI Given an empty directory diff --git a/features/flags.feature b/features/flags.feature index 34aaf2c36b..e0b6111f46 100644 --- a/features/flags.feature +++ b/features/flags.feature @@ -46,14 +46,7 @@ Feature: Global flags Scenario: Debug run Given a WP install - When I try `wp eval 'echo CONST_WITHOUT_QUOTES;'` - Then the return code should be 0 - And STDOUT should be: - """ - CONST_WITHOUT_QUOTES - """ - - When I try `wp eval 'ini_set( "error_log", null ); echo CONST_WITHOUT_QUOTES;' --debug` + When I try `wp eval 'ini_set( "error_log", null ); echo CONST_WITHOUT_QUOTES;'` Then the return code should be 0 And STDOUT should be: """ diff --git a/features/framework.feature b/features/framework.feature index 8163fa2b7a..67615639e1 100644 --- a/features/framework.feature +++ b/features/framework.feature @@ -83,6 +83,7 @@ Feature: Load WP-CLI """ Error: This does not seem to be a WordPress install. """ + And the return code should be 1 Scenario: Globalize global variables in wp-config.php Given an empty directory @@ -164,6 +165,7 @@ Feature: Load WP-CLI """ Warning: Some code is trying to do a URL redirect. """ + And the return code should be 0 Scenario: It should be possible to work on a site in maintenance mode Given a WP install @@ -184,7 +186,7 @@ Feature: Load WP-CLI And a invalid-host.php file: """ ` to override. """ + And the return code should be 1 When I try `wp option get home --url=example.io` Then STDERR should be: """ Error: Site 'example.io' not found. Verify `--url=` matches an existing site. """ + And the return code should be 1 Given "define( 'DOMAIN_CURRENT_SITE', 'example.org' );" replaced with " " in the wp-config.php file @@ -279,9 +285,11 @@ Feature: Load WP-CLI """ Error: Site not found. Define DOMAIN_CURRENT_SITE in 'wp-config.php' or use `--url=` to override. """ + And the return code should be 1 When I try `wp option get home --url=example.io` Then STDERR should be: """ Error: Site 'example.io' not found. Verify `--url=` matches an existing site. """ + And the return code should be 1 diff --git a/php/WP_CLI/Extractor.php b/php/WP_CLI/Extractor.php index 6a81e6979a..f6658eabc6 100644 --- a/php/WP_CLI/Extractor.php +++ b/php/WP_CLI/Extractor.php @@ -38,29 +38,28 @@ public static function extract( $tarball_or_zip, $dest ) { * @param string $dest */ private static function extract_zip( $zipfile, $dest ) { - if ( ! class_exists( 'ZipArchive' ) ) { - throw new Exception( 'Extracting a zip file requires ZipArchive.' ); + if ( ! class_exists( 'ZipArchive' ) || getenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_PHAR' ) ) { + WP_CLI::warning( 'ZipArchive not installed, trying PharData.' ); + self::extract_tarball( $zipfile, $dest, true /*is_zip*/ ); + return; } - $zip = new ZipArchive(); - $res = $zip->open( $zipfile ); - if ( true === $res ) { - $tempdir = implode( - DIRECTORY_SEPARATOR, - array( - dirname( $zipfile ), - Utils\basename( $zipfile, '.zip' ), - $zip->getNameIndex( 0 ), - ) - ); - - $zip->extractTo( dirname( $tempdir ) ); - $zip->close(); - - self::copy_overwrite_files( $tempdir, $dest ); - self::rmdir( dirname( $tempdir ) ); - } else { - throw Exception( $res ); + + $zip = new ZipArchive; + if ( true !== ( $res = $zip->open( $zipfile ) ) ) { + throw new \Exception( "ZipArchive failed to open '$zipfile': $res" ); + } + + $tempdir = Utils\get_temp_dir() . uniqid( 'wp-cli-extract-zip-', true ); + + if ( ! $zip->extractTo( $tempdir ) ) { + throw new \Exception( "ZipArchive failed to extract '$zipfile' to temporary directory '$tempdir'." ); } + + $zip->close(); + + self::copy_overwrite_files( $tempdir, $dest, 1 /*strip_components*/ ); + + self::rmdir( $tempdir ); } /** @@ -68,78 +67,99 @@ private static function extract_zip( $zipfile, $dest ) { * * @param string $tarball * @param string $dest + * @param bool $is_zip Optional. Whether zip file or not. Default false. */ - private static function extract_tarball( $tarball, $dest ) { + private static function extract_tarball( $tarball, $dest, $is_zip = false ) { - if ( class_exists( 'PharData' ) ) { + if ( class_exists( 'PharData' ) && ! getenv( 'WP_CLI_TEST_EXTRACTOR_SHELL' ) ) { try { - // If on Ubuntu (or derivative) check if PHP bug #75273 likely to be triggered and copy to temporary tar if so. + // Check if PHP bug #75273 likely to be triggered and copy to temporary tar if so. $pre_tar = false; - if ( false !== strpos( PHP_VERSION, 'ubuntu' ) ) { // Unfortunately Debian doesn't sign its PHP build so not easy to check for it. + // Only checking Ubuntu (and derivatives) as unfortunately Debian doesn't sign its PHP build so not easy to check for it. + if ( ! $is_zip && false !== strpos( PHP_VERSION, 'ubuntu' ) ) { $tar_size = filesize( $tarball ); $pre_tar = $tar_size > 4 * 1024 * 1024 && $tar_size % ( 8 * 1024 ) < 10; } if ( $pre_tar ) { $temp_tar = Utils\get_temp_dir() . uniqid( 'wp-cli-extract-', true ) . '.tar'; if ( false === ( $contents = file_get_contents( 'compress.zlib://' . $tarball ) ) || false === file_put_contents( $temp_tar, $contents ) ) { - throw new \Exception( "Error creating temporary tar '$temp_tar'." ); + throw new \Exception( "Failed to create temporary tar '$temp_tar'." ); } self::copy_overwrite_files( 'phar://' . $temp_tar, $dest, 1 /*strip_components*/ ); unlink( $temp_tar ); } else { + self::copy_overwrite_files( 'phar://' . $tarball, $dest, 1 /*strip_components*/ ); } return; } catch ( \Exception $e ) { - WP_CLI::warning( "PharData failed, falling back to 'tar gz' (" . $e->getMessage() . ')' ); - // Fall through to trying `tar xz` below + // Can fail on Debian due to PHP bug #75273 so don't warn but fall through silently if message matches. + if ( ! $pre_tar && sprintf( 'unable to decompress gzipped phar archive "%s" to temporary file', $tarball ) === $e->getMessage() ) { + WP_CLI::warning( 'PharData failed, falling back to shell command (' . $e->getMessage() . ')' ); + } + // Fall through to trying `tar xz` or `unzip` below. } } - $cmd = "tar xz --strip-components=1 --directory=%s -f $tarball"; - WP_CLI::launch( Utils\esc_cmd( $cmd, $dest ) ); - } - public static function copy_overwrite_files( $source, $dest, $strip_components = 0 ) { - $iterator = new RecursiveIteratorIterator( - new RecursiveDirectoryIterator( $source, RecursiveDirectoryIterator::SKIP_DOTS ), - RecursiveIteratorIterator::SELF_FIRST - ); + if ( $is_zip ) { + $cmd = Utils\esc_cmd( 'unzip -o -qq %1$s -d %2$s', $tarball, $dest ); + } else { + // Directory must exist for tar --directory to work. + if ( ! file_exists( $dest ) ) { + mkdir( $dest, 0777, true ); + } + $cmd = Utils\esc_cmd( 'tar xz --strip-components=1 --directory=%2$s -f %1$s', $tarball, $dest ); + } - $error = 0; + $process_run = WP_CLI::launch( $cmd, false /*exit_on_error*/, true /*return_detailed*/ ); - if ( ! is_dir( $dest ) ) { - mkdir( $dest, 0777, true ); + if ( 0 !== $process_run->return_code ) { + throw new \Exception( sprintf( "Shell command '%s' returned %d: %s", $process_run->command, $process_run->return_code, $process_run->stderr ) ); } - foreach ( $iterator as $item ) { - - if ( $strip_components > 0 ) { - return self::copy_overwrite_files( $item, $dest, --$strip_components ); + if ( $is_zip ) { + $dest = Utils\trailingslashit( $dest ); + if ( file_exists( $dest . 'wordpress' ) ) { + self::copy_overwrite_files( $dest . 'wordpress', $dest ); + self::rmdir( $dest . 'wordpress' ); } + } + } - $dest_path = $dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName(); + public static function copy_overwrite_files( $source, $dest, $strip_components = 0 ) { + if ( false === ( $files = scandir( $source ) ) ) { + $error = error_get_last(); + throw new \Exception( sprintf( "Failed to scan source directory '%s': %s", $source, $error['message'] ) ); + } + + if ( ! file_exists( $dest ) && ! mkdir( $dest, 0777, true ) ) { + $error = error_get_last(); + throw new \Exception( sprintf( "Failed to create destination directory '%s': %s", $dest, $error['message'] ) ); + } - if ( $item->isDir() ) { - if ( ! is_dir( $dest_path ) ) { - mkdir( $dest_path ); + foreach ( array_diff( $files, array( '.', '..' ) ) as $file ) { + + $source_file = $source . '/' . $file; + $dest_file = $dest . '/' . $file; + + if ( $strip_components > 0 ) { + if ( is_dir( $source_file ) ) { + self::copy_overwrite_files( $source_file, $dest, $strip_components - 1 ); } } else { - if ( file_exists( $dest_path ) && is_writable( $dest_path ) ) { - copy( $item, $dest_path ); - } elseif ( ! file_exists( $dest_path ) ) { - copy( $item, $dest_path ); + + if ( is_dir( $source_file ) ) { + self::copy_overwrite_files( $source_file, $dest_file ); } else { - $error = 1; - WP_CLI::warning( "Unable to copy '" . $iterator->getSubPathName() . "' to current directory." ); + if ( ! copy( $source_file, $dest_file ) ) { + $error = error_get_last(); + throw new \Exception( sprintf( "Failed to copy '%s' to target '%s': %s.", $source_file, $dest_file, $error['message'] ) ); + } } } } - - if ( $error ) { - throw new Exception( 'There was an error overwriting existing files.' ); - } } public static function rmdir( $dir ) { diff --git a/php/WP_CLI/Runner.php b/php/WP_CLI/Runner.php index 541ef3e6f1..2c0263aa9a 100644 --- a/php/WP_CLI/Runner.php +++ b/php/WP_CLI/Runner.php @@ -309,9 +309,6 @@ public function find_command_to_run( $args ) { * @param array $options Configuration options for the function. */ public function run_command( $args, $assoc_args = array(), $options = array() ) { - // Enable PHP error reporting to stderr if testing. - $this->maybe_enable_error_reporting(); - if ( ! empty( $options['back_compat_conversions'] ) ) { list( $args, $assoc_args ) = self::back_compat_conversions( $args, $assoc_args ); } @@ -881,6 +878,11 @@ private function set_alias( $alias ) { public function start() { + // Enable PHP error reporting to stderr if testing. Will need to be re-enabled after WP loads. + if ( getenv( 'BEHAT_RUN' ) ) { + $this->enable_error_reporting(); + } + WP_CLI::debug( $this->_global_config_path_debug, 'bootstrap' ); WP_CLI::debug( $this->_project_config_path_debug, 'bootstrap' ); WP_CLI::debug( 'argv: ' . implode( ' ', $GLOBALS['argv'] ), 'bootstrap' ); @@ -1121,6 +1123,11 @@ function() { 99 ); + // Re-enable PHP error reporting to stderr if testing. + if ( getenv( 'BEHAT_RUN' ) ) { + $this->enable_error_reporting(); + } + WP_CLI::debug( 'Loaded WordPress', 'bootstrap' ); WP_CLI::do_hook( 'after_wp_load' ); @@ -1586,15 +1593,13 @@ private function enumerate_commands( CompositeCommand $command, array &$list, $p } /** - * Enables (almost) full PHP error reporting to stderr if testing. + * Enables (almost) full PHP error reporting to stderr. */ - private function maybe_enable_error_reporting() { - if ( getenv( 'BEHAT_RUN' ) ) { - if ( E_ALL !== error_reporting() ) { - // Don't enable E_DEPRECATED as old versions of WP use PHP 4 style constructors and the mysql extension. - error_reporting( E_ALL & ~E_DEPRECATED ); - } - ini_set( 'display_errors', 'stderr' ); + private function enable_error_reporting() { + if ( E_ALL !== error_reporting() ) { + // Don't enable E_DEPRECATED as old versions of WP use PHP 4 style constructors and the mysql extension. + error_reporting( E_ALL & ~E_DEPRECATED ); } + ini_set( 'display_errors', 'stderr' ); } } diff --git a/tests/test-extractor.php b/tests/test-extractor.php new file mode 100644 index 0000000000..569f2c019a --- /dev/null +++ b/tests/test-extractor.php @@ -0,0 +1,155 @@ +assertSame( $expected, $files ); + Extractor::rmdir( $dest_dir ); + + // Wordpress dir, no strip_components. + + Extractor::copy_overwrite_files( $wp_dir, $dest_dir ); + + $files = self::recursive_scandir( $dest_dir ); + + $expected = array( + 'index1.php', + 'license2.php', + 'wp-admin/about3.php', + 'wp-admin/includes/file4.php', + 'wp-admin/widgets5.php', + 'wp-config6.php', + 'wp-includes/file7.php', + 'xmlrpc8.php', + ); + $this->assertSame( $expected, $files ); + Extractor::rmdir( $dest_dir ); + + // Top level src dir, strip_components 1. + + Extractor::copy_overwrite_files( $src_dir, $dest_dir, 1 /*strip_components*/ ); + + $files = self::recursive_scandir( $dest_dir ); + + $expected = array( + 'index1.php', + 'license2.php', + 'wp-admin/about3.php', + 'wp-admin/includes/file4.php', + 'wp-admin/widgets5.php', + 'wp-config6.php', + 'wp-includes/file7.php', + 'xmlrpc8.php', + ); + $this->assertSame( $expected, $files ); + Extractor::rmdir( $dest_dir ); + + // Wordpress dir, strip_components 1. + + Extractor::copy_overwrite_files( $wp_dir, $dest_dir, 1 /*strip_components*/ ); + + $files = self::recursive_scandir( $dest_dir ); + + $expected = array( + 'about3.php', + 'file7.php', + 'includes/file4.php', + 'widgets5.php', + ); + $this->assertSame( $expected, $files ); + + // Top level src dir, strip_components 2. + + Extractor::copy_overwrite_files( $src_dir, $dest_dir, 2 /*strip_components*/ ); + + $files = self::recursive_scandir( $dest_dir ); + + $expected = array( + 'about3.php', + 'file7.php', + 'includes/file4.php', + 'widgets5.php', + ); + $this->assertSame( $expected, $files ); + Extractor::rmdir( $dest_dir ); + + // Clean up. + Extractor::rmdir( $temp_dir ); + } + + private function recursive_scandir( $dir, $prefix_dir = '' ) { + $ret = array(); + foreach ( array_diff( scandir( $dir ), array( '.', '..' ) ) as $file ) { + if ( is_dir( $dir . '/' . $file ) ) { + $ret = array_merge( $ret, self::recursive_scandir( $dir . '/' . $file, $prefix_dir ? ( $prefix_dir . '/' . $file ) : $file ) ); + } else { + $ret[] = $prefix_dir ? ( $prefix_dir . '/'. $file ) : $file; + } + } + return $ret; + } +} From 684b302e508eb1ed93f36a510fb6166fd6033a80 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 30 Sep 2017 18:20:08 +0100 Subject: [PATCH 101/214] Check return code on all test tries. --- features/aliases.feature | 8 ++++++++ features/command.feature | 19 +++++++++++++++++++ features/config.feature | 8 ++++++++ features/flags.feature | 8 ++++++++ features/runner.feature | 3 +++ features/skip-plugins.feature | 3 +++ 6 files changed, 49 insertions(+) diff --git a/features/aliases.feature b/features/aliases.feature index d76d83aa37..5c1906e497 100644 --- a/features/aliases.feature +++ b/features/aliases.feature @@ -30,6 +30,7 @@ Feature: Create shortcuts to specific WordPress installs """ Error: Alias '@test' not found. """ + And the return code should be 1 Scenario: Provide suggestion when invalid alias is provided Given an empty directory @@ -45,6 +46,7 @@ Feature: Create shortcuts to specific WordPress installs Error: Alias '@test' not found. Did you mean '@test2'? """ + And the return code should be 1 Scenario: Treat global params as local when included in alias Given a WP install in 'foo' @@ -69,6 +71,7 @@ Feature: Create shortcuts to specific WordPress installs """ unknown --path parameter """ + And the return code should be 1 When I run `wp @foo eval 'echo get_current_user_id();' --user=admin` Then STDOUT should be: @@ -98,6 +101,7 @@ Feature: Create shortcuts to specific WordPress installs """ unknown --user parameter """ + And the return code should be 1 Scenario: Support global params specific to the WordPress install, not WP-CLI generally Given a WP install in 'foo' @@ -172,6 +176,7 @@ Feature: Create shortcuts to specific WordPress installs """ Error: This does not seem to be a WordPress install. """ + And the return code should be 1 Scenario: Use a group of aliases to run a command against multiple installs Given a WP install in 'foo' @@ -209,6 +214,7 @@ Feature: Create shortcuts to specific WordPress installs """ Error: Group '@invalid' contains one or more invalid aliases: @baz """ + And the return code should be 1 When I run `wp @both option get home` Then STDOUT should be: @@ -292,6 +298,7 @@ Feature: Create shortcuts to specific WordPress installs """ Error: Cannot use '@all' when no aliases are registered. """ + And the return code should be 1 Scenario: Alias for a subsite of a multisite install Given a WP multisite subdomain install @@ -323,6 +330,7 @@ Feature: Create shortcuts to specific WordPress installs Error: Parameter errors: unknown --url parameter """ + And the return code should be 1 Scenario: Global parameters should be passed to grouped aliases Given a WP install in 'foo' diff --git a/features/command.feature b/features/command.feature index d1de823770..8099202f96 100644 --- a/features/command.feature +++ b/features/command.feature @@ -104,6 +104,7 @@ Feature: WP-CLI Commands """ Error: 'invalid' is not a registered subcommand of 'command'. See 'wp help command' for available subcommands. """ + And the return code should be 1 Scenario: Use a closure as a command Given an empty directory @@ -141,6 +142,7 @@ Feature: WP-CLI Commands """ unknown --burrito parameter """ + And the return code should be 1 When I run `wp --require=custom-cmd.php foo bar` Then STDOUT should contain: @@ -184,6 +186,7 @@ Feature: WP-CLI Commands """ unknown --burrito parameter """ + And the return code should be 1 When I run `wp --require=custom-cmd.php foo bar` Then STDOUT should contain: @@ -234,6 +237,7 @@ Feature: WP-CLI Commands """ unknown --burrito parameter """ + And the return code should be 1 When I run `wp --require=custom-cmd.php foo bar` Then STDOUT should contain: @@ -279,6 +283,7 @@ Feature: WP-CLI Commands """ unknown --burrito parameter """ + And the return code should be 1 When I run `wp --require=custom-cmd.php foo bar` Then STDOUT should contain: @@ -344,6 +349,7 @@ Feature: WP-CLI Commands """ Error: Callable ["Foo_Class","bar"] does not exist, and cannot be registered as `wp bar`. """ + And the return code should be 1 Scenario: Register a synopsis for a given command Given an empty directory @@ -394,6 +400,7 @@ Feature: WP-CLI Commands """ usage: wp foo --apple= [--meal=] """ + And the return code should be 1 When I run `wp help foo` Then STDOUT should contain: @@ -440,12 +447,14 @@ Feature: WP-CLI Commands """ Error: Invalid value specified for positional arg. """ + And the return code should be 1 When I try `wp foo hello --apple=fuji --meal=snack` Then STDERR should contain: """ Invalid value specified for 'meal' (A type of meal.) """ + And the return code should be 1 When I run `wp foo hello --apple=fuji` Then STDOUT should be: @@ -557,6 +566,7 @@ Feature: WP-CLI Commands Error: Parameter errors: Invalid value specified for 'burrito' (This is the burrito argument.) """ + And the return code should be 1 When I try `wp --require=test-cmd.php foo apple --burrito=''` Then STDERR should contain: @@ -564,18 +574,21 @@ Feature: WP-CLI Commands Error: Parameter errors: Invalid value specified for 'burrito' (This is the burrito argument.) """ + And the return code should be 1 When I try `wp --require=test-cmd.php foo apple taco_del_mar` Then STDERR should contain: """ Error: Invalid value specified for positional arg. """ + And the return code should be 1 When I try `wp --require=test-cmd.php foo apple 'cha cha cha' taco_del_mar` Then STDERR should contain: """ Error: Invalid value specified for positional arg. """ + And the return code should be 1 When I run `wp --require=test-cmd.php foo apple 'cha cha cha'` Then STDOUT should be YAML containing: @@ -632,6 +645,7 @@ Feature: WP-CLI Commands """ Error: Invalid value specified for positional arg. """ + And the return code should be 1 Scenario: Removing a subcommand should remove it from the index Given an empty directory @@ -742,18 +756,21 @@ Feature: WP-CLI Commands """ Did you mean 'cli'? """ + And the return code should be 1 When I try `wp cli nfo` Then STDERR should contain: """ Did you mean 'info'? """ + And the return code should be 1 When I try `wp cli beyondlevenshteinthreshold` Then STDERR should not contain: """ Did you mean """ + And the return code should be 1 Scenario: WP-CLI suggests matching parameters when user entry contains typos Given an empty directory @@ -763,12 +780,14 @@ Feature: WP-CLI Commands """ Did you mean '--quiet'? """ + And the return code should be 1 When I try `wp cli info --forma=json` Then STDERR should contain: """ Did you mean '--format'? """ + And the return code should be 1 Scenario: Adding a command can be aborted through the hooks system Given an empty directory diff --git a/features/config.feature b/features/config.feature index ec0916803a..f66f0ebf0b 100644 --- a/features/config.feature +++ b/features/config.feature @@ -113,6 +113,7 @@ Feature: Have a config file """ Error: The 'eval-file' command has been disabled from the config file. """ + And the return code should be 1 When I run `WP_CLI_CONFIG_PATH=config.yml wp core` Then STDOUT should not contain: @@ -131,12 +132,14 @@ Feature: Have a config file """ command has been disabled """ + And the return code should be 1 When I try `WP_CLI_CONFIG_PATH=config.yml wp help core multisite-convert` Then STDERR should contain: """ Error: The 'core multisite-convert' command has been disabled from the config file. """ + And the return code should be 1 Scenario: 'core config' parameters Given an empty directory @@ -180,6 +183,7 @@ Feature: Have a config file """ Error: Sorry, that email address is already used! """ + And the return code should be 1 When I run `wp user create examplejane jane@example.com` Then STDOUT should not be empty @@ -308,6 +312,7 @@ Feature: Have a config file """ Error: Required file 'missing-file.php' doesn't exist (from project's wp-cli.yml). """ + And the return code should be 1 When I run `wp cli info` Then STDOUT should not be empty @@ -328,6 +333,7 @@ Feature: Have a config file """ Error: Required file 'baz.php' doesn't exist (from global config.yml). """ + And the return code should be 1 Scenario: Missing required file as runtime argument Given an empty directory @@ -337,6 +343,7 @@ Feature: Have a config file """ Error: Required file 'foo.php' doesn't exist (from runtime argument). """ + And the return code should be 1 Scenario: Config inheritance from project to global Given an empty directory @@ -508,6 +515,7 @@ require_once(ABSPATH . 'wp-settings.php'); """ Error: Site 'example.dev/' not found. Verify DOMAIN_CURRENT_SITE matches an existing site or use `--url=` to override. """ + And the return code should be 1 When I run `wp option get home --url=example.com` Then STDOUT should be: diff --git a/features/flags.feature b/features/flags.feature index e0b6111f46..76285c714c 100644 --- a/features/flags.feature +++ b/features/flags.feature @@ -32,6 +32,7 @@ Feature: Global flags """ Error: Site 'invalid.example.com' not found. Verify `--url=` matches an existing site. """ + And the return code should be 1 Scenario: Quiet run Given a WP install @@ -105,6 +106,7 @@ Feature: Global flags """ log: called 'error' method """ + And the return code should be 1 Scenario: Using --require Given an empty directory @@ -200,12 +202,14 @@ Feature: Global flags """ Error: 'non-existent-command' is not a registered wp command. See 'wp help' for available commands. """ + And the return code should be 1 When I try `wp --color non-existent-command` Then STDERR should contain: """ [31;1mError: """ + And the return code should be 1 Scenario: Use `WP_CLI_STRICT_ARGS_MODE` to distinguish between global and local args Given an empty directory @@ -261,6 +265,7 @@ Feature: Global flags """ Error: RESTful WP-CLI needs to be installed. Try 'wp package install wp-cli/restful'. """ + And the return code should be 1 Scenario: Strict args mode should be passed on to ssh When I try `WP_CLI_STRICT_ARGS_MODE=1 wp --debug --ssh=/ --version` @@ -268,6 +273,7 @@ Feature: Global flags """ Running SSH command: ssh -q '' -T 'WP_CLI_STRICT_ARGS_MODE=1 wp """ + And the return code should be 255 Scenario: SSH flag should support changing directories When I try `wp --debug --ssh=wordpress:/my/path --version` @@ -275,6 +281,7 @@ Feature: Global flags """ Running SSH command: ssh -q 'wordpress' -T 'cd '\''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/my/path'\''; wp """ + And the return code should be 255 Scenario: SSH flag should support Docker When I try `wp --debug --ssh=docker:user@wordpress --version` @@ -282,3 +289,4 @@ Feature: Global flags """ Running SSH command: docker exec --user 'user' 'wordpress' sh -c """ + And the return code should be 127 diff --git a/features/runner.feature b/features/runner.feature index 4fcb5ae506..4d3342b072 100644 --- a/features/runner.feature +++ b/features/runner.feature @@ -6,16 +6,19 @@ Feature: Runner WP-CLI """ ABSPATH defined: /foo/ """ + And the return code should be 1 When I try `wp no-such-command --path=/foo/ --debug` Then STDERR should contain: """ ABSPATH defined: /foo/ """ + And the return code should be 1 When I try `wp no-such-command --path=/foo\\ --debug` Then STDERR should contain: """ ABSPATH defined: /foo/ """ + And the return code should be 1 diff --git a/features/skip-plugins.feature b/features/skip-plugins.feature index 37ac7bb19c..04e97d55b4 100644 --- a/features/skip-plugins.feature +++ b/features/skip-plugins.feature @@ -37,6 +37,7 @@ Feature: Skipping plugins """ Call to undefined function hello_dolly() """ + And the return code should be 255 # No plugins should be loaded when --skip-plugins doesn't have a value When I run `wp --skip-plugins eval 'var_export( defined("AKISMET_VERSION") );var_export( function_exists( "hello_dolly" ) );'` @@ -60,6 +61,7 @@ Feature: Skipping plugins """ Call to undefined function hello_dolly() """ + And the return code should be 255 Scenario: Skipping all plugins via config file Given a WP install @@ -74,6 +76,7 @@ Feature: Skipping plugins """ Call to undefined function hello_dolly() """ + And the return code should be 255 Scenario: Skip network active plugins Given a WP multisite install From 0ec0e2a861c478ded0d149333e6482003ff0e0bd Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 30 Sep 2017 19:59:16 +0100 Subject: [PATCH 102/214] Add return code should not be. --- features/flags.feature | 2 +- features/steps/then.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/features/flags.feature b/features/flags.feature index 76285c714c..6a8eb5b67b 100644 --- a/features/flags.feature +++ b/features/flags.feature @@ -289,4 +289,4 @@ Feature: Global flags """ Running SSH command: docker exec --user 'user' 'wordpress' sh -c """ - And the return code should be 127 + And the return code should not be 0 diff --git a/features/steps/then.php b/features/steps/then.php index aa1f3f67fe..57fdfd8abf 100644 --- a/features/steps/then.php +++ b/features/steps/then.php @@ -3,9 +3,9 @@ use Behat\Gherkin\Node\PyStringNode, Behat\Gherkin\Node\TableNode; -$steps->Then( '/^the return code should be (\d+)$/', - function ( $world, $return_code ) { - if ( $return_code != $world->result->return_code ) { +$steps->Then( '/^the return code should( not)? be (\d+)$/', + function ( $world, $not, $return_code ) { + if ( ( ! $not && $return_code != $world->result->return_code ) || ( $not && $return_code == $world->result->return_code ) ) { throw new RuntimeException( $world->result ); } } From bd6e18e1cfb0baa51ca7d1d94b4eda6f9e76789a Mon Sep 17 00:00:00 2001 From: gitlost Date: Sun, 1 Oct 2017 01:37:05 +0100 Subject: [PATCH 103/214] Improve Extractor tests. --- features/bootstrap/FeatureContext.php | 6 +- php/WP_CLI/Extractor.php | 6 +- tests/test-extractor.php | 283 ++++++++++++++++++++------ utils/make-phar.php | 4 +- 4 files changed, 226 insertions(+), 73 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 435cc1f389..28117b2574 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -542,14 +542,14 @@ private static function run_sql( $sql_cmd, $assoc_args = array(), $add_database public function create_db() { $dbname = self::$db_settings['dbname']; - self::run_sql( 'mysql --no-defaults --no-auto-rehash', array( 'execute' => "CREATE DATABASE IF NOT EXISTS $dbname" ) ); + self::run_sql( 'mysql --no-defaults --no-auto-rehash --quick', array( 'execute' => "CREATE DATABASE IF NOT EXISTS $dbname" ) ); self::$have_dropped_db = false; } public function drop_db() { if ( ! self::$have_dropped_db ) { $dbname = self::$db_settings['dbname']; - self::run_sql( 'mysql --no-defaults --no-auto-rehash', array( 'execute' => "DROP DATABASE IF EXISTS $dbname" ) ); + self::run_sql( 'mysql --no-defaults --no-auto-rehash --quick', array( 'execute' => "DROP DATABASE IF EXISTS $dbname" ) ); self::$have_dropped_db = true; } } @@ -695,7 +695,7 @@ public function install_wp( $subdir = '' ) { if ( $install_cache_path && file_exists( $install_cache_path ) ) { self::copy_dir( $install_cache_path, $run_dir ); - self::run_sql( 'mysql --no-defaults --no-auto-rehash', array( 'execute' => "SOURCE {$install_cache_path}.sql" ), true /*add_database*/ ); + self::run_sql( 'mysql --no-defaults --no-auto-rehash --quick', array( 'execute' => "SOURCE {$install_cache_path}.sql" ), true /*add_database*/ ); } else { $this->proc( 'wp core install', $install_args, $subdir )->run_check(); if ( $install_cache_path ) { diff --git a/php/WP_CLI/Extractor.php b/php/WP_CLI/Extractor.php index f6658eabc6..3ed7722a2c 100644 --- a/php/WP_CLI/Extractor.php +++ b/php/WP_CLI/Extractor.php @@ -39,7 +39,7 @@ public static function extract( $tarball_or_zip, $dest ) { */ private static function extract_zip( $zipfile, $dest ) { if ( ! class_exists( 'ZipArchive' ) || getenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_PHAR' ) ) { - WP_CLI::warning( 'ZipArchive not installed, trying PharData.' ); + WP_CLI::warning( class_exists( 'PharData' ) ? 'ZipArchive not installed, trying PharData.' : 'ZipArchive not installed, trying shell \'unzip\' command.' ); self::extract_tarball( $zipfile, $dest, true /*is_zip*/ ); return; } @@ -55,7 +55,9 @@ private static function extract_zip( $zipfile, $dest ) { throw new \Exception( "ZipArchive failed to extract '$zipfile' to temporary directory '$tempdir'." ); } - $zip->close(); + if ( ! $zip->close() ) { + throw new \Exception( "ZipArchive failed to close '$zipfile'." ); + } self::copy_overwrite_files( $tempdir, $dest, 1 /*strip_components*/ ); diff --git a/tests/test-extractor.php b/tests/test-extractor.php index 569f2c019a..63677cc1fb 100644 --- a/tests/test-extractor.php +++ b/tests/test-extractor.php @@ -1,53 +1,60 @@ assertTrue( is_dir( $temp_dir ) ); + Extractor::rmdir( $temp_dir ); + $this->assertFalse( file_exists( $temp_dir ) ); + } - touch( $wp_dir . '/index1.php' ); - touch( $wp_dir . '/license2.php' ); - touch( $wp_admin_dir . '/about3.php' ); - touch( $wp_admin_includes_dir . '/file4.php' ); - touch( $wp_admin_dir . '/widgets5.php' ); - touch( $wp_dir . '/wp-config6.php' ); - touch( $wp_includes_dir . '/file7.php' ); - touch( $wp_dir . '/xmlrpc8.php' ); + public function testCopyOverwriteFiles() { + list( $temp_dir, $src_dir, $wp_dir ) = self::create_test_directory_structure(); $dest_dir = $temp_dir . '/dest'; @@ -57,17 +64,7 @@ public function testCopyOverwriteFiles() { $files = self::recursive_scandir( $dest_dir ); - $expected = array( - 'wordpress/index1.php', - 'wordpress/license2.php', - 'wordpress/wp-admin/about3.php', - 'wordpress/wp-admin/includes/file4.php', - 'wordpress/wp-admin/widgets5.php', - 'wordpress/wp-config6.php', - 'wordpress/wp-includes/file7.php', - 'wordpress/xmlrpc8.php', - ); - $this->assertSame( $expected, $files ); + $this->assertSame( self::$expected_top, $files ); Extractor::rmdir( $dest_dir ); // Wordpress dir, no strip_components. @@ -76,17 +73,7 @@ public function testCopyOverwriteFiles() { $files = self::recursive_scandir( $dest_dir ); - $expected = array( - 'index1.php', - 'license2.php', - 'wp-admin/about3.php', - 'wp-admin/includes/file4.php', - 'wp-admin/widgets5.php', - 'wp-config6.php', - 'wp-includes/file7.php', - 'xmlrpc8.php', - ); - $this->assertSame( $expected, $files ); + $this->assertSame( self::$expected_wp, $files ); Extractor::rmdir( $dest_dir ); // Top level src dir, strip_components 1. @@ -95,17 +82,7 @@ public function testCopyOverwriteFiles() { $files = self::recursive_scandir( $dest_dir ); - $expected = array( - 'index1.php', - 'license2.php', - 'wp-admin/about3.php', - 'wp-admin/includes/file4.php', - 'wp-admin/widgets5.php', - 'wp-config6.php', - 'wp-includes/file7.php', - 'xmlrpc8.php', - ); - $this->assertSame( $expected, $files ); + $this->assertSame( self::$expected_wp, $files ); Extractor::rmdir( $dest_dir ); // Wordpress dir, strip_components 1. @@ -122,7 +99,7 @@ public function testCopyOverwriteFiles() { ); $this->assertSame( $expected, $files ); - // Top level src dir, strip_components 2. + // Top level src dir, strip_components 2 (same as Wordpress dir, strip_components 1). Extractor::copy_overwrite_files( $src_dir, $dest_dir, 2 /*strip_components*/ ); @@ -137,10 +114,184 @@ public function testCopyOverwriteFiles() { $this->assertSame( $expected, $files ); Extractor::rmdir( $dest_dir ); + // Top level src dir, strip_components 3. + + Extractor::copy_overwrite_files( $src_dir, $dest_dir, 3 /*strip_components*/ ); + + $files = self::recursive_scandir( $dest_dir ); + + $expected = array( + 'file4.php', + ); + $this->assertSame( $expected, $files ); + Extractor::rmdir( $dest_dir ); + // Clean up. Extractor::rmdir( $temp_dir ); } + public function testExtractTarball() { + if ( ! exec( 'tar --version' ) ) { + $this->markTestSkipped( 'tar not installed.' ); + } + + $extractor_shell = getenv( 'WP_CLI_TEST_EXTRACTOR_SHELL' ); + $extractor_zip_phar = getenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_PHAR' ); + + list( $temp_dir, $src_dir, $wp_dir ) = self::create_test_directory_structure(); + + $tarball = $temp_dir . '/test.tar.gz'; + $dest_dir = $temp_dir . '/dest'; + + // Create test tarball. + + $output = array(); $return_var = -1; + exec( Utils\esc_cmd( 'tar czvf %1$s --directory=%2$s/src wordpress', $tarball, $temp_dir ), $output, $return_var ); + $this->assertSame( 0, $return_var ); + $this->assertFalse( empty( $output ) ); + + // Remove directory listings. + $output = array_filter( $output, function ( $v ) { + return '/' !== substr( $v, -1 ); + } ); + sort( $output ); + $this->assertSame( self::$expected_top, $output ); + + putenv( 'WP_CLI_TEST_EXTRACTOR_SHELL' ); + Extractor::extract( $tarball, $dest_dir ); + + $files = self::recursive_scandir( $dest_dir ); + $this->assertSame( self::$expected_wp, $files ); + Extractor::rmdir( $dest_dir ); + + putenv( 'WP_CLI_TEST_EXTRACTOR_SHELL=1' ); + Extractor::extract( $tarball, $dest_dir ); + + $files = self::recursive_scandir( $dest_dir ); + $this->assertSame( self::$expected_wp, $files ); + Extractor::rmdir( $dest_dir ); + + // Clean up. + Extractor::rmdir( $temp_dir ); + + putenv( false === $extractor_shell ? 'WP_CLI_TEST_EXTRACTOR_SHELL' : "WP_CLI_TEST_EXTRACTOR_SHELL=$extractor_shell" ); + putenv( false === $extractor_zip_phar ? 'WP_CLI_TEST_EXTRACTOR_ZIP_PHAR' : "WP_CLI_TEST_EXTRACTOR_ZIP_PHAR=$extractor_zip_phar" ); + } + + public function testExtractZip() { + if ( ! class_exists( 'ZipArchive' ) ) { + $this->markTestSkipped( 'ZipArchive not installed.' ); + } + + $output = array(); $return_var = -1; + exec( 'which zip 2>&1 1>/dev/null', $output, $return_var ); + $have_zip = 0 === $return_var; + + $output = array(); $return_var = -1; + exec( 'which unzip 2>&1 1>/dev/null', $output, $return_var ); + $have_unzip = 0 === $return_var; + + $extractor_shell = getenv( 'WP_CLI_TEST_EXTRACTOR_SHELL' ); + $extractor_zip_phar = getenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_PHAR' ); + + list( $temp_dir, $src_dir, $wp_dir ) = self::create_test_directory_structure(); + + $zipfile = $temp_dir . '/test.zip'; + $dest_dir = $temp_dir . '/dest'; + + // Create test zip. + + $zip = new ZipArchive; + $result = $zip->open( $zipfile, ZipArchive::CREATE ); + $this->assertTrue( $result ); + $files = self::recursive_scandir( $src_dir ); + foreach ( $files as $file ) { + $result = $zip->addFile( $src_dir . '/' . $file, $file ); + $this->assertTrue( $result ); + } + $result = $zip->close(); + $this->assertTrue( $result ); + + if ( $have_unzip ) { + $output = array(); $return_var = -1; + exec( Utils\esc_cmd( 'unzip -l %1$s', $zipfile ), $output, $return_var ); + $this->assertSame( 0, $return_var ); + $output = array_filter( array_map( function ( $v ) { + return preg_match( '/([^ \t]+\.php$)/', $v, $matches ) ? $matches[1] : ''; + }, $output ), 'strlen' ); + sort( $output ); + $this->assertSame( self::$expected_top, $output ); + } + + putenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_PHAR' ); + putenv( 'WP_CLI_TEST_EXTRACTOR_SHELL' ); + Extractor::extract( $zipfile, $dest_dir ); + + $files = self::recursive_scandir( $dest_dir ); + $this->assertSame( self::$expected_wp, $files ); + Extractor::rmdir( $dest_dir ); + + putenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_PHAR=1' ); + putenv( 'WP_CLI_TEST_EXTRACTOR_SHELL' ); + Extractor::extract( $zipfile, $dest_dir ); + + $files = self::recursive_scandir( $dest_dir ); + $this->assertSame( self::$expected_wp, $files ); + Extractor::rmdir( $dest_dir ); + + if ( $have_zip ) { + putenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_PHAR=1' ); + putenv( 'WP_CLI_TEST_EXTRACTOR_SHELL=1' ); + Extractor::extract( $zipfile, $dest_dir ); + + $files = self::recursive_scandir( $dest_dir ); + $this->assertSame( self::$expected_wp, $files ); + Extractor::rmdir( $dest_dir ); + } + + // Clean up. + Extractor::rmdir( $temp_dir ); + + putenv( false === $extractor_shell ? 'WP_CLI_TEST_EXTRACTOR_SHELL' : "WP_CLI_TEST_EXTRACTOR_SHELL=$extractor_shell" ); + putenv( false === $extractor_zip_phar ? 'WP_CLI_TEST_EXTRACTOR_ZIP_PHAR' : "WP_CLI_TEST_EXTRACTOR_ZIP_PHAR=$extractor_zip_phar" ); + } + + private function create_test_directory_structure() { + $temp_dir = Utils\get_temp_dir() . uniqid( self::$copy_overwrite_files_prefix, true ); + mkdir( $temp_dir ); + + $src_dir = $temp_dir . '/src'; + mkdir( $src_dir ); + + /* + * Create test directory structure: + * src/wordpress/index1.php + * license2.php + * wp-admin/about3.php + * includes/file4.php + * widgets5.php + * wp-config6.php + * wp-includes/file7.php + * xmlrpc8.php + */ + + mkdir( $wp_dir = $src_dir . '/wordpress' ); + mkdir( $wp_admin_dir = $wp_dir . '/wp-admin' ); + mkdir( $wp_admin_includes_dir = $wp_admin_dir . '/includes' ); + mkdir( $wp_includes_dir = $wp_dir . '/wp-includes' ); + + touch( $wp_dir . '/index1.php' ); + touch( $wp_dir . '/license2.php' ); + touch( $wp_admin_dir . '/about3.php' ); + touch( $wp_admin_includes_dir . '/file4.php' ); + touch( $wp_admin_dir . '/widgets5.php' ); + touch( $wp_dir . '/wp-config6.php' ); + touch( $wp_includes_dir . '/file7.php' ); + touch( $wp_dir . '/xmlrpc8.php' ); + + return array( $temp_dir, $src_dir, $wp_dir ); + } + private function recursive_scandir( $dir, $prefix_dir = '' ) { $ret = array(); foreach ( array_diff( scandir( $dir ), array( '.', '..' ) ) as $file ) { diff --git a/utils/make-phar.php b/utils/make-phar.php index 66969e06d6..56537ce4a4 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -105,8 +105,8 @@ function strip_comments( $contents, $keep_doc_comments ) { return str_repeat( "\n", substr_count( $t[1], "\n" ) ); // Strip everything but newlines. } if ( T_WHITESPACE === $t[0] ) { - $str = preg_replace( '/[^\t\n]/', '', $t[1] ); - return '' !== $str ? $str : ' '; + $str = preg_replace( '/[^\t\n]/', '', $t[1] ); // Keep tabs and newlines. + return '' !== $str ? $str : ' '; // Keep at least one space. } return $t[1]; }, token_get_all( $contents ) ); From b7ffef46520db88ee13e14a769c08514968c5769 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 4 Oct 2017 09:03:28 +0100 Subject: [PATCH 104/214] Test executable PHP_BINDIR/php in get_php_binary(). --- php/class-wp-cli.php | 3 ++- phpcs.xml.dist | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/php/class-wp-cli.php b/php/class-wp-cli.php index c548c9f936..477cc77607 100644 --- a/php/class-wp-cli.php +++ b/php/class-wp-cli.php @@ -1026,11 +1026,12 @@ public static function get_php_binary() { return getenv( 'WP_CLI_PHP' ); } + // Available since PHP 5.4. if ( defined( 'PHP_BINARY' ) ) { return PHP_BINARY; } - if ( defined( 'PHP_BINDIR' ) ) { + if ( @ is_executable( PHP_BINDIR . '/php' ) || ( Utils\is_windows() && @ is_executable( PHP_BINDIR . '/php.exe' ) ) ) { return PHP_BINDIR . '/php'; } diff --git a/phpcs.xml.dist b/phpcs.xml.dist index ee8e0ddf8f..3838b52eac 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -27,7 +27,6 @@ - @@ -35,7 +34,6 @@ - From fdfd1924db6134f085e4a74059a9a52673386138 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 4 Oct 2017 13:56:51 +0100 Subject: [PATCH 105/214] Fix Extractor message check. --- php/WP_CLI/Extractor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/WP_CLI/Extractor.php b/php/WP_CLI/Extractor.php index 3ed7722a2c..35edba4c60 100644 --- a/php/WP_CLI/Extractor.php +++ b/php/WP_CLI/Extractor.php @@ -98,7 +98,7 @@ private static function extract_tarball( $tarball, $dest, $is_zip = false ) { return; } catch ( \Exception $e ) { // Can fail on Debian due to PHP bug #75273 so don't warn but fall through silently if message matches. - if ( ! $pre_tar && sprintf( 'unable to decompress gzipped phar archive "%s" to temporary file', $tarball ) === $e->getMessage() ) { + if ( $pre_tar || sprintf( 'unable to decompress gzipped phar archive "%s" to temporary file', $tarball ) !== $e->getMessage() ) { WP_CLI::warning( 'PharData failed, falling back to shell command (' . $e->getMessage() . ')' ); } // Fall through to trying `tar xz` or `unzip` below. From 581edbfd963b0175991918370a96b063da754578 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 4 Oct 2017 15:37:56 +0100 Subject: [PATCH 106/214] Test for get_php_binary(). --- tests/test-utils.php | 4 ++-- tests/test-wp-cli.php | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/tests/test-utils.php b/tests/test-utils.php index ddf122157b..ee604bfbb6 100644 --- a/tests/test-utils.php +++ b/tests/test-utils.php @@ -363,7 +363,7 @@ public function testHttpRequestBadAddress() { $exception = null; try { - Utils\http_request( 'GET', 'https://nosuchhost_asdf_asdf_asdf.com' ); + Utils\http_request( 'GET', 'https://nosuchhost_asdf_asdf_asdf.com', null /*data*/, null /*headers*/, array( 'timeout' => 1 ) ); } catch ( \WP_CLI\ExitException $ex ) { $exception = $ex; } @@ -420,7 +420,7 @@ public function testHttpRequestBadCAcert() { $logger = new \WP_CLI\Loggers\Execution; WP_CLI::set_logger( $logger ); - Utils\http_request( 'GET', 'https://example.com' ); + Utils\http_request( 'GET', 'https://example.com', null /*data*/, null /*headers*/, array( 'timeout' => 1 ) ); // Undo bad CAcert hack before asserting. unlink( $bad_cacert_path ); diff --git a/tests/test-wp-cli.php b/tests/test-wp-cli.php index a8448b02e4..bd0156e605 100644 --- a/tests/test-wp-cli.php +++ b/tests/test-wp-cli.php @@ -34,4 +34,23 @@ public function testRuncommandLaunchProcDisabled() { $this->assertTrue( false !== strpos( trim( $output[0] ), $err_msg ) ); } + public function testGetPhpBinary() { + $env_php_used = getenv( 'WP_CLI_PHP_USED' ); + $env_php = getenv( 'WP_CLI_PHP' ); + + putenv( 'WP_CLI_PHP_USED' ); + putenv( 'WP_CLI_PHP' ); + + $php_binary = WP_CLI::get_php_binary(); + + $output = array(); + $return_var = -1; + exec( $php_binary . ' --version', $output, $return_var ); + $this->assertSame( 0, $return_var ); + $this->assertTrue( ! empty( $output ) ); + $this->assertTrue( false !== stripos( $output[0], 'php' ) ); + + putenv( false === $env_php_used ? 'WP_CLI_PHP_USED' : "WP_CLI_PHP_USED=$env_php_used" ); + putenv( false === $env_php ? 'WP_CLI_PHP' : "WP_CLI_PHP=$env_php" ); + } } From f5bbcb4838a0014327497c91e09292e2ea884634 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 4 Oct 2017 19:28:48 +0100 Subject: [PATCH 107/214] Don't bother with unzip in Extractor. --- php/WP_CLI/Extractor.php | 59 ++++++++++++++-------------------------- tests/test-extractor.php | 43 +++-------------------------- 2 files changed, 25 insertions(+), 77 deletions(-) diff --git a/php/WP_CLI/Extractor.php b/php/WP_CLI/Extractor.php index 35edba4c60..f3facbad48 100644 --- a/php/WP_CLI/Extractor.php +++ b/php/WP_CLI/Extractor.php @@ -38,29 +38,31 @@ public static function extract( $tarball_or_zip, $dest ) { * @param string $dest */ private static function extract_zip( $zipfile, $dest ) { - if ( ! class_exists( 'ZipArchive' ) || getenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_PHAR' ) ) { - WP_CLI::warning( class_exists( 'PharData' ) ? 'ZipArchive not installed, trying PharData.' : 'ZipArchive not installed, trying shell \'unzip\' command.' ); - self::extract_tarball( $zipfile, $dest, true /*is_zip*/ ); - return; + if ( class_exists( 'PharData' ) && ! getenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_ARCHIVE' ) ) { + try { + self::copy_overwrite_files( 'phar://' . $zipfile, $dest, 1 /*strip_components*/ ); + return; + } catch ( \Exception $e ) { + WP_CLI::warning( 'Failed to extract zip file using PharData, falling back to ZipArchive (' . $e->getMessage() . ')' ); + } } - - $zip = new ZipArchive; - if ( true !== ( $res = $zip->open( $zipfile ) ) ) { + if ( ! class_exists( 'ZipArchive' ) ) { + throw new \Exception( 'Extracting a zip file requires ZipArchive or PharData.' ); + } + $zip = new ZipArchive(); + $res = $zip->open( $zipfile ); + if ( true !== $res ) { throw new \Exception( "ZipArchive failed to open '$zipfile': $res" ); } - $tempdir = Utils\get_temp_dir() . uniqid( 'wp-cli-extract-zip-', true ); if ( ! $zip->extractTo( $tempdir ) ) { throw new \Exception( "ZipArchive failed to extract '$zipfile' to temporary directory '$tempdir'." ); } - if ( ! $zip->close() ) { throw new \Exception( "ZipArchive failed to close '$zipfile'." ); } - self::copy_overwrite_files( $tempdir, $dest, 1 /*strip_components*/ ); - self::rmdir( $tempdir ); } @@ -69,16 +71,15 @@ private static function extract_zip( $zipfile, $dest ) { * * @param string $tarball * @param string $dest - * @param bool $is_zip Optional. Whether zip file or not. Default false. */ - private static function extract_tarball( $tarball, $dest, $is_zip = false ) { + private static function extract_tarball( $tarball, $dest ) { if ( class_exists( 'PharData' ) && ! getenv( 'WP_CLI_TEST_EXTRACTOR_SHELL' ) ) { try { // Check if PHP bug #75273 likely to be triggered and copy to temporary tar if so. $pre_tar = false; // Only checking Ubuntu (and derivatives) as unfortunately Debian doesn't sign its PHP build so not easy to check for it. - if ( ! $is_zip && false !== strpos( PHP_VERSION, 'ubuntu' ) ) { + if ( false !== strpos( PHP_VERSION, 'ubuntu' ) ) { $tar_size = filesize( $tarball ); $pre_tar = $tar_size > 4 * 1024 * 1024 && $tar_size % ( 8 * 1024 ) < 10; } @@ -89,7 +90,6 @@ private static function extract_tarball( $tarball, $dest, $is_zip = false ) { } self::copy_overwrite_files( 'phar://' . $temp_tar, $dest, 1 /*strip_components*/ ); - unlink( $temp_tar ); } else { @@ -101,33 +101,16 @@ private static function extract_tarball( $tarball, $dest, $is_zip = false ) { if ( $pre_tar || sprintf( 'unable to decompress gzipped phar archive "%s" to temporary file', $tarball ) !== $e->getMessage() ) { WP_CLI::warning( 'PharData failed, falling back to shell command (' . $e->getMessage() . ')' ); } - // Fall through to trying `tar xz` or `unzip` below. - } - } - - if ( $is_zip ) { - $cmd = Utils\esc_cmd( 'unzip -o -qq %1$s -d %2$s', $tarball, $dest ); - } else { - // Directory must exist for tar --directory to work. - if ( ! file_exists( $dest ) ) { - mkdir( $dest, 0777, true ); + // Fall through to trying `tar xz` below } - $cmd = Utils\esc_cmd( 'tar xz --strip-components=1 --directory=%2$s -f %1$s', $tarball, $dest ); } - $process_run = WP_CLI::launch( $cmd, false /*exit_on_error*/, true /*return_detailed*/ ); - - if ( 0 !== $process_run->return_code ) { - throw new \Exception( sprintf( "Shell command '%s' returned %d: %s", $process_run->command, $process_run->return_code, $process_run->stderr ) ); - } - - if ( $is_zip ) { - $dest = Utils\trailingslashit( $dest ); - if ( file_exists( $dest . 'wordpress' ) ) { - self::copy_overwrite_files( $dest . 'wordpress', $dest ); - self::rmdir( $dest . 'wordpress' ); - } + // Directory must exist for tar --directory to work. + if ( ! file_exists( $dest ) ) { + mkdir( $dest, 0777, true ); } + $cmd = Utils\esc_cmd( 'tar xz --strip-components=1 --directory=%2$s -f %1$s', $tarball, $dest ); + WP_CLI::launch( $cmd ); } public static function copy_overwrite_files( $source, $dest, $strip_components = 0 ) { diff --git a/tests/test-extractor.php b/tests/test-extractor.php index 63677cc1fb..8aac7d725d 100644 --- a/tests/test-extractor.php +++ b/tests/test-extractor.php @@ -136,7 +136,6 @@ public function testExtractTarball() { } $extractor_shell = getenv( 'WP_CLI_TEST_EXTRACTOR_SHELL' ); - $extractor_zip_phar = getenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_PHAR' ); list( $temp_dir, $src_dir, $wp_dir ) = self::create_test_directory_structure(); @@ -175,7 +174,6 @@ public function testExtractTarball() { Extractor::rmdir( $temp_dir ); putenv( false === $extractor_shell ? 'WP_CLI_TEST_EXTRACTOR_SHELL' : "WP_CLI_TEST_EXTRACTOR_SHELL=$extractor_shell" ); - putenv( false === $extractor_zip_phar ? 'WP_CLI_TEST_EXTRACTOR_ZIP_PHAR' : "WP_CLI_TEST_EXTRACTOR_ZIP_PHAR=$extractor_zip_phar" ); } public function testExtractZip() { @@ -183,16 +181,7 @@ public function testExtractZip() { $this->markTestSkipped( 'ZipArchive not installed.' ); } - $output = array(); $return_var = -1; - exec( 'which zip 2>&1 1>/dev/null', $output, $return_var ); - $have_zip = 0 === $return_var; - - $output = array(); $return_var = -1; - exec( 'which unzip 2>&1 1>/dev/null', $output, $return_var ); - $have_unzip = 0 === $return_var; - - $extractor_shell = getenv( 'WP_CLI_TEST_EXTRACTOR_SHELL' ); - $extractor_zip_phar = getenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_PHAR' ); + $extractor_zip_archive = getenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_ARCHIVE' ); list( $temp_dir, $src_dir, $wp_dir ) = self::create_test_directory_structure(); @@ -212,48 +201,24 @@ public function testExtractZip() { $result = $zip->close(); $this->assertTrue( $result ); - if ( $have_unzip ) { - $output = array(); $return_var = -1; - exec( Utils\esc_cmd( 'unzip -l %1$s', $zipfile ), $output, $return_var ); - $this->assertSame( 0, $return_var ); - $output = array_filter( array_map( function ( $v ) { - return preg_match( '/([^ \t]+\.php$)/', $v, $matches ) ? $matches[1] : ''; - }, $output ), 'strlen' ); - sort( $output ); - $this->assertSame( self::$expected_top, $output ); - } - - putenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_PHAR' ); - putenv( 'WP_CLI_TEST_EXTRACTOR_SHELL' ); + putenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_ARCHIVE' ); Extractor::extract( $zipfile, $dest_dir ); $files = self::recursive_scandir( $dest_dir ); $this->assertSame( self::$expected_wp, $files ); Extractor::rmdir( $dest_dir ); - putenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_PHAR=1' ); - putenv( 'WP_CLI_TEST_EXTRACTOR_SHELL' ); + putenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_ARCHIVE=1' ); Extractor::extract( $zipfile, $dest_dir ); $files = self::recursive_scandir( $dest_dir ); $this->assertSame( self::$expected_wp, $files ); Extractor::rmdir( $dest_dir ); - if ( $have_zip ) { - putenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_PHAR=1' ); - putenv( 'WP_CLI_TEST_EXTRACTOR_SHELL=1' ); - Extractor::extract( $zipfile, $dest_dir ); - - $files = self::recursive_scandir( $dest_dir ); - $this->assertSame( self::$expected_wp, $files ); - Extractor::rmdir( $dest_dir ); - } - // Clean up. Extractor::rmdir( $temp_dir ); - putenv( false === $extractor_shell ? 'WP_CLI_TEST_EXTRACTOR_SHELL' : "WP_CLI_TEST_EXTRACTOR_SHELL=$extractor_shell" ); - putenv( false === $extractor_zip_phar ? 'WP_CLI_TEST_EXTRACTOR_ZIP_PHAR' : "WP_CLI_TEST_EXTRACTOR_ZIP_PHAR=$extractor_zip_phar" ); + putenv( false === $extractor_zip_archive ? 'WP_CLI_TEST_EXTRACTOR_ZIP_ARCHIVE' : "WP_CLI_TEST_EXTRACTOR_ZIP_ARCHIVE=$extractor_zip_archive" ); } private function create_test_directory_structure() { From edc9b5241c0dd8d282f3fbbbf5ab1dd7282c2bcb Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 18 Oct 2017 04:10:21 +0100 Subject: [PATCH 108/214] Try doing cli update to latest in tests now GITHUB_TOKEN available. --- features/cli.feature | 22 ++++++++++------------ utils/make-phar.php | 22 ---------------------- 2 files changed, 10 insertions(+), 34 deletions(-) diff --git a/features/cli.feature b/features/cli.feature index 62c8650a13..ee738ab0a5 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -75,12 +75,11 @@ Feature: `wp cli` tasks 0.0.0 """ - #GITHUB_TOKEN: This can hit github rate limiting on Travis as the latest 1.3.0 phar doesn't use GITHUB_TOKEN. - #When I run `{PHAR_PATH} cli update` - #Then STDOUT should be: - #""" - #Success: WP-CLI is at the latest version. - #""" + When I run `{PHAR_PATH} cli update` + Then STDOUT should be: + """ + Success: WP-CLI is at the latest version. + """ @travis-github-token Scenario: Patch update from 0.14.0 to 0.14.1 @@ -175,12 +174,11 @@ Feature: `wp cli` tasks And STDERR should be empty And the return code should be 0 - #GITHUB_TOKEN: This can hit github rate limiting on Travis as the latest 1.3.0 phar doesn't use GITHUB_TOKEN. - #When I run `{PHAR_PATH} cli check-update` - #Then STDOUT should be: - #""" - #Success: WP-CLI is at the latest version. - #""" + When I run `{PHAR_PATH} cli check-update` + Then STDOUT should be: + """ + Success: WP-CLI is at the latest version. + """ When I run `{PHAR_PATH} cli version` Then STDOUT should be: diff --git a/utils/make-phar.php b/utils/make-phar.php index 348a480fa1..71aa7abcae 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -86,28 +86,6 @@ function add_file( $phar, $path ) { } } -function strip_comments( $contents, $keep_doc_comments ) { - $strs = array_map( function ( $t ) use ( $keep_doc_comments ) { - if ( is_string( $t ) ) { - return $t; - } - if ( T_COMMENT === $t[0] || ( ! $keep_doc_comments && T_DOC_COMMENT === $t[0] ) ) { - if ( preg_match( '/copyright|license|\(c\)/i', $t[1] ) ) { - // Keep for copyright reasons. - return $t[1]; - } - return str_repeat( "\n", substr_count( $t[1], "\n" ) ); // Strip everything but newlines. - } - if ( T_WHITESPACE === $t[0] ) { - $str = preg_replace( '/[^\t\n]/', '', $t[1] ); // Keep tabs and newlines. - return '' !== $str ? $str : ' '; // Keep at least one space. - } - return $t[1]; - }, token_get_all( $contents ) ); - - return implode( '', $strs ); -} - function set_file_contents( $phar, $path, $content ) { $key = str_replace( WP_CLI_BASE_PATH, '', $path ); From 0e245c31e203d1f610872c81de01b279553e2c6e Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 18 Oct 2017 17:44:43 +0100 Subject: [PATCH 109/214] Workaround wp-db errors in old WP; strip comments take 2. --- features/bootstrap.feature | 4 +- tests/test-make-phar-strip-comments.php | 162 ++++++++++++++++++++++++ utils/make-phar-strip-comments.php | 32 +++++ utils/make-phar.php | 26 +++- 4 files changed, 221 insertions(+), 3 deletions(-) create mode 100644 tests/test-make-phar-strip-comments.php create mode 100644 utils/make-phar-strip-comments.php diff --git a/features/bootstrap.feature b/features/bootstrap.feature index 7549edeefb..950f9fba43 100644 --- a/features/bootstrap.feature +++ b/features/bootstrap.feature @@ -249,11 +249,13 @@ Feature: Bootstrap WP-CLI Success: """ - When I run `wp core install --url=example.com --title=example --admin_user=example --admin_email=example@example.org` + # Use try to cater for wp-db errors in old WPs. + When I try `wp core install --url=example.com --title=example --admin_user=example --admin_email=example@example.org` Then STDOUT should contain: """ Success: """ + And the return code should be 0 When I run `wp eval 'echo constant( "WP_CLI_TEST_CONSTANT" );'` Then STDOUT should be: diff --git a/tests/test-make-phar-strip-comments.php b/tests/test-make-phar-strip-comments.php new file mode 100644 index 0000000000..b74bdf3299 --- /dev/null +++ b/tests/test-make-phar-strip-comments.php @@ -0,0 +1,162 @@ +assertSame( $source, $actual ); + $this->assertSame( substr_count( $actual, "\n" ), substr_count( $source, "\n" ) ); + $expected = <<<'EOD' +assertSame( $expected, $actual ); + $this->assertSame( substr_count( $actual, "\n" ), substr_count( $source, "\n" ) ); + + } + + /** + * Test inline comment behaviour. + */ + function testInlineComments() { + + // Doc comment and inline comments. + $source = <<<'EOD' +assertSame( $expected, $actual ); + $this->assertSame( substr_count( $actual, "\n" ), substr_count( $source, "\n" ) ); + + $expected = <<<'EOD' +assertSame( $expected, $actual ); + $this->assertSame( substr_count( $actual, "\n" ), substr_count( $source, "\n" ) ); + } + + /** + * Test keeps copyright comments. + */ + function testCopyright() { + + // Doc comment and inline copyrights. + $source = <<<'EOD' +assertSame( $expected, $actual ); + + $expected = <<<'EOD' +assertSame( $expected, $actual ); + } + +} diff --git a/utils/make-phar-strip-comments.php b/utils/make-phar-strip-comments.php new file mode 100644 index 0000000000..372a221eea --- /dev/null +++ b/utils/make-phar-strip-comments.php @@ -0,0 +1,32 @@ + true, + 'features/bootstrap/support.php' => true, + 'php/WP_CLI/Process.php' => true, + 'php/WP_CLI/ProcessRun.php' => true, + 'php/utils.php' => true, + 'ci/behat-tags.php' => true, + 'features/steps/given.php' => true, + 'features/steps/when.php' => true, + 'features/steps/then.php' => true, + 'features/extra/no-mail.php' => true, + ); + + $file_contents = file_get_contents( $path ); + if ( 0 === substr_compare( $path, '.php', -4 ) && ! isset( $scaffold_package_phps[ substr( $key, 1 ) ] ) ) { // `substr()` to remove initial slash. + if ( stripos( $key, 'features' ) ) error_log( "stripping $key" ); + $is_wp_cli_command = preg_match( '/\/(?:php\/commands|vendor\/wp-cli\/[^\/]+?-command\/src)\//', $path ); + $file_contents = make_phar_strip_comments( $file_contents, $is_wp_cli_command /*keep_doc_comments*/ ); + } + $basename = basename( $path ); if ( 0 === strpos( $basename, 'autoload_' ) && preg_match( '/(?:classmap|files|namespaces|psr4|static)\.php$/', $basename ) ) { // Strip autoload maps of unused stuff. @@ -80,9 +102,9 @@ function add_file( $phar, $path ) { return '/^[^,\n]+?' . $v . '[^,\n]+?, *\n/m'; }, $strips ); } - $phar[ $key ] = preg_replace( $strip_res, '', file_get_contents( $path ) ); + $phar[ $key ] = preg_replace( $strip_res, '', $file_contents ); } else { - $phar[ $key ] = file_get_contents( $path ); + $phar[ $key ] = $file_contents; } } From 46ce1b99d4356cee29f5ae61a080b10a43fff917 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 18 Oct 2017 22:39:20 +0100 Subject: [PATCH 110/214] Remove error_log debug. --- utils/make-phar.php | 1 - 1 file changed, 1 deletion(-) diff --git a/utils/make-phar.php b/utils/make-phar.php index 15c5853782..c27f3b4814 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -70,7 +70,6 @@ function add_file( $phar, $path ) { $file_contents = file_get_contents( $path ); if ( 0 === substr_compare( $path, '.php', -4 ) && ! isset( $scaffold_package_phps[ substr( $key, 1 ) ] ) ) { // `substr()` to remove initial slash. - if ( stripos( $key, 'features' ) ) error_log( "stripping $key" ); $is_wp_cli_command = preg_match( '/\/(?:php\/commands|vendor\/wp-cli\/[^\/]+?-command\/src)\//', $path ); $file_contents = make_phar_strip_comments( $file_contents, $is_wp_cli_command /*keep_doc_comments*/ ); } From f8fc2979fb0b22ec09299b4492b2734473acc3ec Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 21 Oct 2017 00:05:17 +0100 Subject: [PATCH 111/214] Test bad address timeout 0. --- composer.lock | 12 ++++++------ features/help.feature | 2 +- features/skip-plugins.feature | 2 +- php/WP_CLI/FileCache.php | 2 +- php/class-wp-cli.php | 3 ++- phpcs.xml.dist | 2 +- tests/test-utils.php | 4 ++-- 7 files changed, 14 insertions(+), 13 deletions(-) diff --git a/composer.lock b/composer.lock index bb0bf82172..157553cbd7 100644 --- a/composer.lock +++ b/composer.lock @@ -1097,16 +1097,16 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.5.0", + "version": "v1.6.0", "source": { "type": "git", "url": "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/symfony/polyfill-mbstring.git", - "reference": "7c8fae0ac1d216eb54349e6a8baa57d515fe8803" + "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7c8fae0ac1d216eb54349e6a8baa57d515fe8803", - "reference": "7c8fae0ac1d216eb54349e6a8baa57d515fe8803", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", + "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", "shasum": "" }, "require": { @@ -1118,7 +1118,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.5-dev" + "dev-master": "1.6-dev" } }, "autoload": { @@ -1152,7 +1152,7 @@ "portable", "shim" ], - "time": "2017-06-14T15:44:48+00:00" + "time": "2017-10-11T12:05:26+00:00" }, { "name": "symfony/process", diff --git a/features/help.feature b/features/help.feature index 6f0adb0a24..162e1e3adc 100644 --- a/features/help.feature +++ b/features/help.feature @@ -50,7 +50,7 @@ Feature: Get help about WP-CLI commands @require-wp-4.3 Scenario: Help for internal commands with WP Given a WP install - # Check for errors/warnings when loading WP. + # Check for errors/warnings when loading WP. And a stderr-error-log.php file: """ enabled = false; } - if ( null === self::$finderDummy ) { + if ( null === self::$finderDummy && $this->enabled ) { /* * Make sure Finder & helper classes used in clean() are loaded as otherwise calling clean() in a `register_shutdown_function` * can fail in certain circumstances - a PHP issue not easily reproducible but witnessed on Travis and locally. diff --git a/php/class-wp-cli.php b/php/class-wp-cli.php index 09253e203a..31d4e30667 100644 --- a/php/class-wp-cli.php +++ b/php/class-wp-cli.php @@ -1033,7 +1033,8 @@ public static function get_php_binary() { return PHP_BINARY; } - if ( @ is_executable( PHP_BINDIR . '/php' ) || ( Utils\is_windows() && @ is_executable( PHP_BINDIR . '/php.exe' ) ) ) { + // @codingStandardsIgnoreLine + if ( @is_executable( PHP_BINDIR . '/php' ) || ( Utils\is_windows() && @is_executable( PHP_BINDIR . '/php.exe' ) ) ) { return PHP_BINDIR . '/php'; } diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 8ec3909b76..05a05ad455 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -32,7 +32,7 @@ - + diff --git a/tests/test-utils.php b/tests/test-utils.php index 88b5fb78c0..71fbff1d5b 100644 --- a/tests/test-utils.php +++ b/tests/test-utils.php @@ -363,7 +363,7 @@ public function testHttpRequestBadAddress() { $exception = null; try { - Utils\http_request( 'GET', 'https://nosuchhost_asdf_asdf_asdf.com', null /*data*/, null /*headers*/, array( 'timeout' => 1 ) ); + Utils\http_request( 'GET', 'https://nosuchhost_asdf_asdf_asdf.com', null /*data*/, array() /*headers*/, array( 'timeout' => 0 ) ); } catch ( \WP_CLI\ExitException $ex ) { $exception = $ex; } @@ -420,7 +420,7 @@ public function testHttpRequestBadCAcert() { $logger = new \WP_CLI\Loggers\Execution; WP_CLI::set_logger( $logger ); - Utils\http_request( 'GET', 'https://example.com', null /*data*/, null /*headers*/, array( 'timeout' => 1 ) ); + Utils\http_request( 'GET', 'https://example.com' ); // Undo bad CAcert hack before asserting. unlink( $bad_cacert_path ); From 497e24ca340889505149a6521de642061a2803b5 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sun, 22 Oct 2017 14:08:46 +0100 Subject: [PATCH 112/214] Add behat make-phar test. --- tests/test-make-phar-strip-comments.php | 36 +++++++++++++++++++++++++ utils/make-phar-strip-comments.php | 4 +-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/tests/test-make-phar-strip-comments.php b/tests/test-make-phar-strip-comments.php index b74bdf3299..094d7317bc 100644 --- a/tests/test-make-phar-strip-comments.php +++ b/tests/test-make-phar-strip-comments.php @@ -159,4 +159,40 @@ function __construct() { $this->assertSame( $expected, $actual ); } + /** + * Test keeps Behat comments. + */ + public function testBehat() { + + $source = <<<'EOD' +assertSame( $expected, $actual ); + $this->assertSame( substr_count( $actual, "\n" ), substr_count( $source, "\n" ) ); + } + } diff --git a/utils/make-phar-strip-comments.php b/utils/make-phar-strip-comments.php index 372a221eea..beb9ebd686 100644 --- a/utils/make-phar-strip-comments.php +++ b/utils/make-phar-strip-comments.php @@ -15,8 +15,8 @@ function make_phar_strip_comments( $contents, $keep_doc_comments ) { return $t; } if ( T_COMMENT === $t[0] || ( ! $keep_doc_comments && T_DOC_COMMENT === $t[0] ) ) { - if ( preg_match( '/copyright|licen[sc]e|\(c\)/i', $t[1] ) ) { - // Keep for copyright reasons. + if ( preg_match( '/copyright|licen[sc]e|\(c\)|@before|@after/i', $t[1] ) ) { + // Keep for copyright and behat reasons. return $t[1]; } return str_repeat( "\n", substr_count( $t[1], "\n" ) ); // Strip everything but newlines. From 6645f928a1ace57bcad099555a792d1acbf8a9cc Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 30 Oct 2017 23:06:35 +0000 Subject: [PATCH 113/214] Strip phpcs stuff from autoloads in make-phar. --- utils/make-phar.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/make-phar.php b/utils/make-phar.php index c27f3b4814..21ffddc657 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -87,6 +87,7 @@ function add_file( $phar, $path ) { '-command\/src\/', '\/wp-cli\/[^\n]+?-command\/', '\/symfony\/(?!finder|polyfill-mbstring)[^\/]+?\/', + '\/(?:dealerdirect|squizlabs|wimg)\/', ); } else { $strips = array( @@ -95,6 +96,7 @@ function add_file( $phar, $path ) { '\/symfony\/(?!console|filesystem|finder|polyfill-mbstring|process)[^\/]+?\/', '\/composer\/spdx-licenses\/', '\/Composer\/(?:Command\/|Compiler\.php|Console\/|Downloader\/Pear|Installer\/Pear|Question\/|Repository\/Pear|SelfUpdate\/)', + '\/(?:dealerdirect|squizlabs|wimg)\/', ); } $strip_res = array_map( function ( $v ) { From 0ccb86406a91f1de6c3f931ad3cad2bf7e49d87a Mon Sep 17 00:00:00 2001 From: gitlost Date: Sun, 5 Nov 2017 15:03:01 +0000 Subject: [PATCH 114/214] @travis-github-token -> @github-api --- features/cli.feature | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/features/cli.feature b/features/cli.feature index f5b2f7b05c..14b5972de5 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -42,7 +42,7 @@ Feature: `wp cli` tasks {TRUE_VERSION} """ - @travis-github-token + @github-api Scenario: Check for updates Given an empty directory And a new Phar with version "0.0.0" and cli build @@ -54,7 +54,7 @@ Feature: `wp cli` tasks """ And STDERR should be empty - @travis-github-token + @github-api Scenario: Do WP-CLI Update Given an empty directory And a new Phar with version "0.0.0" and cli build @@ -97,7 +97,7 @@ Feature: `wp cli` tasks Success: WP-CLI is at the latest version. """ - @travis-github-token + @github-api Scenario: Patch update from 0.14.0 to 0.14.1 Given an empty directory And a new Phar with version "0.14.0" and cli build @@ -126,7 +126,7 @@ Feature: `wp cli` tasks WP-CLI 0.14.1 """ - @travis-github-token + @github-api Scenario: Not a patch update from 0.14.0 Given an empty directory And a new Phar with version "0.14.0" and cli build @@ -143,7 +143,7 @@ Feature: `wp cli` tasks And STDERR should be empty And the return code should be 0 - @travis-github-token + @github-api Scenario: Install WP-CLI nightly Given an empty directory And a new Phar with version "0.14.0" and cli build @@ -161,7 +161,7 @@ Feature: `wp cli` tasks And STDERR should be empty And the return code should be 0 - @travis-github-token + @github-api Scenario: Install WP-CLI stable Given an empty directory And a new Phar with version "0.14.0" and cli build From 0aaa416bed339bdcf0a3327aa50e0c4ceea4ccd9 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 22 Nov 2017 01:15:46 +0000 Subject: [PATCH 115/214] Fix up some left overs after master merge; rmdir cache_dir file-cache test. --- features/bootstrap/FeatureContext.php | 6 ------ features/framework.feature | 4 +++- features/steps/given.php | 6 +----- php/WP_CLI/Process.php | 4 ---- tests/test-file-cache.php | 2 ++ utils/make-phar.php | 4 ++-- 6 files changed, 8 insertions(+), 18 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 8b63175485..0a8d195196 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -166,8 +166,6 @@ private static function cache_wp_files() { if ( $wp_version ) { $cmd .= Utils\esc_cmd( ' --version=%s', $wp_version ); } - // Redirect any warnings (eg md5 hash checks not available). - $cmd .= ' 2>&1'; Process::create( $cmd, null, self::get_process_env_variables() )->run_check(); } @@ -779,10 +777,6 @@ private function composer_command($cmd) { if ( !isset( $this->variables['COMPOSER_PATH'] ) ) { $this->variables['COMPOSER_PATH'] = exec('which composer'); } - // Redirect composer messages from stderr to stdout. - if ( false === strpos( $cmd, '>' ) ) { - $cmd .= ' 2>&1'; - } $this->proc( $this->variables['COMPOSER_PATH'] . ' ' . $cmd )->run_check(); } diff --git a/features/framework.feature b/features/framework.feature index dbbbc04657..c7e22a68d6 100644 --- a/features/framework.feature +++ b/features/framework.feature @@ -186,7 +186,6 @@ Feature: Load WP-CLI And a invalid-host.php file: """ install_wp(); $subdomains = ! empty( $type ) && 'subdomain' === $type ? 1 : 0; - // Ignore "Warning: Wildcard DNS may not be configured correctly.". - $r = $world->proc( 'wp core install-network', array( 'title' => 'WP CLI Network', 'subdomains' => $subdomains ) )->run(); - if ( $r->return_code || ( ! empty( $r->stderr ) && 'Warning: Wildcard DNS may not be configured correctly.' !== trim( $r->stderr ) ) ) { - throw new \RuntimeException( $r ); - } + $world->proc( 'wp core install-network', array( 'title' => 'WP CLI Network', 'subdomains' => $subdomains ) )->run_check(); } ); diff --git a/php/WP_CLI/Process.php b/php/WP_CLI/Process.php index c6a1b5cea9..70c3c9f82a 100644 --- a/php/WP_CLI/Process.php +++ b/php/WP_CLI/Process.php @@ -112,10 +112,6 @@ public function run_check() { if ( $r->return_code || ! empty( $r->STDERR ) ) { throw new \RuntimeException( $r ); } - // But do it right if testing. - if ( ! empty( $this->env['BEHAT_RUN'] ) && ( $r->return_code || ! empty( $r->stderr ) ) ) { - throw new \RuntimeException( $r ); - } return $r; } diff --git a/tests/test-file-cache.php b/tests/test-file-cache.php index 290197bd51..36fb10a87c 100644 --- a/tests/test-file-cache.php +++ b/tests/test-file-cache.php @@ -42,6 +42,8 @@ public function testFinderLoaded() { $this->assertFalse( file_exists( $cache_dir . '/max_size' ) ); $this->assertFalse( file_exists( $cache_dir . '/ttl' ) ); + + rmdir( $cache_dir ); } /** diff --git a/utils/make-phar.php b/utils/make-phar.php index 21ffddc657..83f870f3b5 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -86,14 +86,14 @@ function add_file( $phar, $path ) { '\/nb\/oxymel\/', '-command\/src\/', '\/wp-cli\/[^\n]+?-command\/', - '\/symfony\/(?!finder|polyfill-mbstring)[^\/]+?\/', + '\/symfony\/(?!finder|polyfill-mbstring)[^\/]+\/', '\/(?:dealerdirect|squizlabs|wimg)\/', ); } else { $strips = array( '\/(?:behat|gherkin)\/src\/', '\/phpunit\/', - '\/symfony\/(?!console|filesystem|finder|polyfill-mbstring|process)[^\/]+?\/', + '\/symfony\/(?!console|filesystem|finder|polyfill-mbstring|process)[^\/]+\/', '\/composer\/spdx-licenses\/', '\/Composer\/(?:Command\/|Compiler\.php|Console\/|Downloader\/Pear|Installer\/Pear|Question\/|Repository\/Pear|SelfUpdate\/)', '\/(?:dealerdirect|squizlabs|wimg)\/', From f99b5d254eb0ca8100dbfd950a8b8b89e0f2d17b Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 22 Nov 2017 01:23:24 +0000 Subject: [PATCH 116/214] Allow for stripping in -command. --- utils/make-phar.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/make-phar.php b/utils/make-phar.php index 83f870f3b5..39dffbbca7 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -70,7 +70,7 @@ function add_file( $phar, $path ) { $file_contents = file_get_contents( $path ); if ( 0 === substr_compare( $path, '.php', -4 ) && ! isset( $scaffold_package_phps[ substr( $key, 1 ) ] ) ) { // `substr()` to remove initial slash. - $is_wp_cli_command = preg_match( '/\/(?:php\/commands|vendor\/wp-cli\/[^\/]+?-command\/src)\//', $path ); + $is_wp_cli_command = preg_match( '/\/(?:php\/commands|[^\/]+?-command\/src)\//', $path ); $file_contents = make_phar_strip_comments( $file_contents, $is_wp_cli_command /*keep_doc_comments*/ ); } From b5bb2c35384cfa7199d06dca5c8ad97bc976b143 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 22 Nov 2017 01:30:01 +0000 Subject: [PATCH 117/214] Fix phpcs nonsense. --- php/WP_CLI/Extractor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/WP_CLI/Extractor.php b/php/WP_CLI/Extractor.php index 98ef613741..b63f9088b0 100644 --- a/php/WP_CLI/Extractor.php +++ b/php/WP_CLI/Extractor.php @@ -43,7 +43,7 @@ private static function extract_zip( $zipfile, $dest ) { self::copy_overwrite_files( 'phar://' . $zipfile, $dest, 1 /*strip_components*/ ); return; } catch ( \Exception $e ) { - WP_CLI::warning( sprintf( "Falling back to ZipArchive. PharData failed: %s.", $e->getMessage() ) ); + WP_CLI::warning( sprintf( 'Falling back to ZipArchive. PharData failed: %s.', $e->getMessage() ) ); } } if ( ! class_exists( 'ZipArchive' ) ) { From fb954f6fbc8d8f0e7614266637f657db5debc14a Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 22 Nov 2017 02:45:21 +0000 Subject: [PATCH 118/214] With return code. --- features/runcommand.feature | 40 +++---------------------------------- features/steps/when.php | 19 ++++++++---------- php/WP_CLI/Process.php | 15 ++++++++++++++ 3 files changed, 26 insertions(+), 48 deletions(-) diff --git a/features/runcommand.feature b/features/runcommand.feature index d7acdc06d2..0e2a4c0dc5 100644 --- a/features/runcommand.feature +++ b/features/runcommand.feature @@ -53,8 +53,6 @@ Feature: Run a WP-CLI command http://example.com returned: NULL """ - And STDERR should be empty - And the return code should be 0 When I run `wp run 'eval "echo wp_get_current_user()->user_login . PHP_EOL;"'` Then STDOUT should be: @@ -62,8 +60,6 @@ Feature: Run a WP-CLI command admin returned: NULL """ - And STDERR should be empty - And the return code should be 0 When I run `WP_CLI_CONFIG_PATH=config.yml wp run 'user get'` Then STDOUT should be: @@ -71,8 +67,6 @@ Feature: Run a WP-CLI command admin@example.com returned: NULL """ - And STDERR should be empty - And the return code should be 0 Examples: | flag | @@ -87,32 +81,24 @@ Feature: Run a WP-CLI command """ returned: 'http://example.com' """ - And STDERR should be empty - And the return code should be 0 When I run `wp --return run 'eval "echo wp_get_current_user()->user_login . PHP_EOL;"'` Then STDOUT should be: """ returned: 'admin' """ - And STDERR should be empty - And the return code should be 0 When I run `wp --return=stderr run 'eval "echo wp_get_current_user()->user_login . PHP_EOL;"'` Then STDOUT should be: """ returned: '' """ - And STDERR should be empty - And the return code should be 0 When I run `wp --return=return_code run 'eval "echo wp_get_current_user()->user_login . PHP_EOL;"'` Then STDOUT should be: """ returned: 0 """ - And STDERR should be empty - And the return code should be 0 When I run `wp --return=all run 'eval "echo wp_get_current_user()->user_login . PHP_EOL;"'` Then STDOUT should be: @@ -123,16 +109,12 @@ Feature: Run a WP-CLI command 'return_code' => 0, ) """ - And STDERR should be empty - And the return code should be 0 When I run `WP_CLI_CONFIG_PATH=config.yml wp --return run 'user get'` Then STDOUT should be: """ returned: 'admin@example.com' """ - And STDERR should be empty - And the return code should be 0 Examples: | flag | @@ -159,13 +141,12 @@ Feature: Run a WP-CLI command Scenario Outline: Exit on error by default Given a WP install - When I try `wp run 'eval "WP_CLI::error( var_export( get_current_user_id(), true ) );"'` + When I try `wp run 'eval "WP_CLI::error( var_export( get_current_user_id(), true ) );"'` with return code 1 Then STDOUT should be empty And STDERR should be: """ Error: 1 """ - And the return code should be 1 Examples: | flag | @@ -175,7 +156,7 @@ Feature: Run a WP-CLI command Scenario Outline: Override erroring on exit Given a WP install - When I try `wp run --no-exit_error --return=all 'eval "WP_CLI::error( var_export( get_current_user_id(), true ) );"'` + When I run `wp run --no-exit_error --return=all 'eval "WP_CLI::error( var_export( get_current_user_id(), true ) );"'` Then STDOUT should be: """ returned: array ( @@ -184,16 +165,12 @@ Feature: Run a WP-CLI command 'return_code' => 1, ) """ - And STDERR should be empty - And the return code should be 0 When I run `wp --no-exit_error run 'option get foo$bar'` Then STDOUT should be: """ returned: NULL """ - And STDERR should be empty - And the return code should be 0 Examples: | flag | @@ -214,8 +191,6 @@ Feature: Run a WP-CLI command 'return_code' => 1, ) """ - And STDERR should be empty - And the return code should be 0 When I run `wp run --no-exit_error --return=all 'eval "echo '\'echo\''; WP_CLI::log( '\'log\'' ); WP_CLI::warning( '\'warning\''); WP_CLI::success( '\'success\'' );"'` Then STDOUT should be: @@ -227,8 +202,6 @@ Feature: Run a WP-CLI command 'return_code' => 0, ) """ - And STDERR should be empty - And the return code should be 0 Examples: | flag | @@ -237,16 +210,13 @@ Feature: Run a WP-CLI command Scenario Outline: Installed packages work as expected Given a WP install - - When I run `wp package install wp-cli/scaffold-package-command` - Then STDERR should be empty + And I run `wp package install wp-cli/scaffold-package-command` When I run `wp run 'help scaffold package'` Then STDOUT should contain: """ wp scaffold package """ - And STDERR should be empty Examples: | flag | @@ -263,8 +233,6 @@ Feature: Run a WP-CLI command Success: Rewrite structure set. returned: NULL """ - And STDERR should be empty - And the return code should be 0 Examples: | flag | @@ -280,8 +248,6 @@ Feature: Run a WP-CLI command http://example.com/?cat=1 returned: NULL """ - And STDERR should be empty - And the return code should be 0 Examples: | flag | diff --git a/features/steps/when.php b/features/steps/when.php index d23aa0e669..e8869facc8 100644 --- a/features/steps/when.php +++ b/features/steps/when.php @@ -4,14 +4,11 @@ Behat\Gherkin\Node\TableNode, WP_CLI\Process; -function invoke_proc( $proc, $mode ) { - $map = array( - 'run' => 'run_check_stderr', - 'try' => 'run' - ); - $method = $map[ $mode ]; - - return $proc->$method(); +function invoke_proc( $proc, $mode, $return_code = 0 ) { + if ( 'run' === $mode ) { + return $proc->run_check_stderr(); + } + return $return_code ? $proc->run_check_return_code( $return_code ) : $proc->run(); } function capture_email_sends( $stdout ) { @@ -25,10 +22,10 @@ function ( $world, $cmd ) { } ); -$steps->When( '/^I (run|try) `([^`]+)`$/', - function ( $world, $mode, $cmd ) { +$steps->When( '/^I (run|try) `([^`]+)`(?: with return code (\d+))?$/', + function ( $world, $mode, $cmd, $return_code = 0 ) { $cmd = $world->replace_variables( $cmd ); - $world->result = invoke_proc( $world->proc( $cmd ), $mode ); + $world->result = invoke_proc( $world->proc( $cmd ), $mode, (int) $return_code ); list( $world->result->stdout, $world->email_sends ) = capture_email_sends( $world->result->stdout ); } ); diff --git a/php/WP_CLI/Process.php b/php/WP_CLI/Process.php index 70c3c9f82a..e9ec56c09c 100644 --- a/php/WP_CLI/Process.php +++ b/php/WP_CLI/Process.php @@ -131,4 +131,19 @@ public function run_check_stderr() { return $r; } + + /** + * Run the command, but throw an Exception if the return code isn't as given. + * + * @return ProcessRun + */ + public function run_check_return_code( $return_code = 0 ) { + $r = $this->run(); + + if ( $return_code != $r->return_code ) { + throw new \RuntimeException( $r ); + } + + return $r; + } } From 8ed9f93a699f33b5499f7520637764b0a8a6a275 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 22 Nov 2017 03:26:18 +0000 Subject: [PATCH 119/214] Adjectivally try. --- features/help.feature | 155 ++++++++++-------------------------- features/runcommand.feature | 5 +- features/steps/when.php | 22 +++-- php/WP_CLI/Process.php | 12 ++- 4 files changed, 72 insertions(+), 122 deletions(-) diff --git a/features/help.feature b/features/help.feature index c86301056f..4d042e63c7 100644 --- a/features/help.feature +++ b/features/help.feature @@ -9,42 +9,36 @@ Feature: Get help about WP-CLI commands Run 'wp help ' to get more information on a specific command. """ - And STDERR should be empty When I run `wp help core` Then STDOUT should contain: """ wp core """ - And STDERR should be empty When I run `wp help core download` Then STDOUT should contain: """ wp core download """ - And STDERR should be empty When I run `wp help help` Then STDOUT should contain: """ wp help """ - And STDERR should be empty When I run `wp help help` Then STDOUT should contain: """ GLOBAL PARAMETERS """ - And STDERR should be empty When I run `wp post list --post_type=post --posts_per_page=5 --help` Then STDOUT should contain: """ wp post list """ - And STDERR should be empty # Prior to WP 4.3 widgets & others used PHP 4 style constructors and prior to WP 3.9 wpdb used the mysql extension which can all lead (depending on PHP version) to PHP Deprecated notices. @require-wp-4.3 @@ -57,35 +51,30 @@ Feature: Get help about WP-CLI commands Run 'wp help ' to get more information on a specific command. """ - And STDERR should be empty When I run `wp help core` Then STDOUT should contain: """ wp core """ - And STDERR should be empty When I run `wp help core download` Then STDOUT should contain: """ wp core download """ - And STDERR should be empty When I run `wp help help` Then STDOUT should contain: """ wp help """ - And STDERR should be empty When I run `wp help help` Then STDOUT should contain: """ GLOBAL PARAMETERS """ - And STDERR should be empty # Fixed in trunk, WP isn't compatible with PHP 7.2 due to `__autoload()` in "wp-includes/compat.php". @less-than-php-7.2 @@ -98,7 +87,6 @@ Feature: Get help about WP-CLI commands """ wp config create """ - And STDERR should be empty When I run `wp config create {CORE_CONFIG_SETTINGS}` And I run `wp help core install` @@ -106,44 +94,37 @@ Feature: Get help about WP-CLI commands """ wp core install """ - And STDERR should be empty When I run `wp help core is-installed` Then STDOUT should contain: """ wp core is-installed """ - And STDERR should be empty When I run `wp help core` Then STDOUT should contain: """ wp core """ - And STDERR should be empty When I run `wp help config` Then STDOUT should contain: """ wp config """ - And STDERR should be empty When I run `wp help db` Then STDOUT should contain: """ wp db """ - And STDERR should be empty - When I try `wp help non-existent-command` - Then the return code should be 1 - And STDERR should be: + When I mistakenly try `wp help non-existent-command` + Then STDERR should be: """ Warning: Can’t select database. We were able to connect to the database server (which means your username and password is okay) but not able to select the `wp_cli_test` database. Error: 'non-existent-command' is not a registered wp command. See 'wp help' for available commands. """ - And STDOUT should be empty # Bug: if `WP_DEBUG` (or `WP_DEBUG_DISPLAY') is defined falsey than a db error won't be trapped. Given a define-wp-debug-false.php file: @@ -151,192 +132,154 @@ Feature: Get help about WP-CLI commands 'eval "WP_CLI::error( var_export( get_current_user_id(), true ) );"'` with return code 1 - Then STDOUT should be empty - And STDERR should be: + When I mistakenly try `wp run 'eval "WP_CLI::error( var_export( get_current_user_id(), true ) );"'` + Then STDERR should be: """ Error: 1 """ diff --git a/features/steps/when.php b/features/steps/when.php index e8869facc8..7ec0fa340d 100644 --- a/features/steps/when.php +++ b/features/steps/when.php @@ -4,11 +4,23 @@ Behat\Gherkin\Node\TableNode, WP_CLI\Process; -function invoke_proc( $proc, $mode, $return_code = 0 ) { +function invoke_proc( $proc, $mode ) { if ( 'run' === $mode ) { return $proc->run_check_stderr(); } - return $return_code ? $proc->run_check_return_code( $return_code ) : $proc->run(); + if ( 'try' === $mode ) { + return $proc->run(); + } + if ( 'mistakenly try' === $mode ) { + $return_code = 1; + $stderr_empty = false; + $stdout_empty = true; + } else { + $return_code = 0; + $stderr_empty = false; + $stdout_empty = null; + } + return $proc->run_check_full( $return_code, $stderr_empty, $stdout_empty ); } function capture_email_sends( $stdout ) { @@ -22,10 +34,10 @@ function ( $world, $cmd ) { } ); -$steps->When( '/^I (run|try) `([^`]+)`(?: with return code (\d+))?$/', - function ( $world, $mode, $cmd, $return_code = 0 ) { +$steps->When( '/^I (run|try|mistakenly try|dubiously try) `([^`]+)`$/', + function ( $world, $mode, $cmd, $return_code = 0, $stdout_empty = '' ) { $cmd = $world->replace_variables( $cmd ); - $world->result = invoke_proc( $world->proc( $cmd ), $mode, (int) $return_code ); + $world->result = invoke_proc( $world->proc( $cmd ), $mode ); list( $world->result->stdout, $world->email_sends ) = capture_email_sends( $world->result->stdout ); } ); diff --git a/php/WP_CLI/Process.php b/php/WP_CLI/Process.php index e9ec56c09c..1340d9e259 100644 --- a/php/WP_CLI/Process.php +++ b/php/WP_CLI/Process.php @@ -133,14 +133,20 @@ public function run_check_stderr() { } /** - * Run the command, but throw an Exception if the return code isn't as given. + * Run the command, but throw an Exception if the conditions aren't as given. * * @return ProcessRun */ - public function run_check_return_code( $return_code = 0 ) { + public function run_check_full( $return_code = 0, $stderr_empty = null, $stdout_empty = null ) { $r = $this->run(); - if ( $return_code != $r->return_code ) { + if ( $return_code !== $r->return_code ) { + throw new \RuntimeException( $r ); + } + if ( null !== $stderr_empty && $stderr_empty !== empty( $r->stderr ) ) { + throw new \RuntimeException( $r ); + } + if ( null !== $stdout_empty && $stdout_empty !== empty( $r->stdout ) ) { throw new \RuntimeException( $r ); } From e082855fbc36303ce59dc60874111234b40eae1f Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 22 Nov 2017 08:04:04 +0000 Subject: [PATCH 120/214] Add mistakenly/successfully try; remove unneeded steps. --- features/aliases.feature | 33 +++------ features/cli-bash-completion.feature | 32 --------- features/cli.feature | 13 ---- features/command.feature | 103 +++++++-------------------- features/config.feature | 59 ++++----------- features/flags.feature | 28 +++----- features/framework.feature | 33 +++------ features/hook.feature | 3 - features/make-phar.feature | 6 +- features/prompt.feature | 4 +- features/runner.feature | 8 +-- features/skip-plugins.feature | 3 +- features/skip-themes.feature | 17 ----- features/steps/when.php | 4 +- features/validation.feature | 16 ++--- 15 files changed, 86 insertions(+), 276 deletions(-) diff --git a/features/aliases.feature b/features/aliases.feature index 5c1906e497..04f124c5e5 100644 --- a/features/aliases.feature +++ b/features/aliases.feature @@ -9,12 +9,11 @@ Feature: Create shortcuts to specific WordPress installs path: foo """ - When I try `wp core is-installed` + When I mistakenly try `wp core is-installed` Then STDERR should contain: """ Error: This does not seem to be a WordPress install. """ - And the return code should be 1 When I run `wp @foo core is-installed` Then the return code should be 0 @@ -25,12 +24,11 @@ Feature: Create shortcuts to specific WordPress installs Scenario: Error when invalid alias provided Given an empty directory - When I try `wp @test option get home` + When I mistakenly try `wp @test option get home` Then STDERR should be: """ Error: Alias '@test' not found. """ - And the return code should be 1 Scenario: Provide suggestion when invalid alias is provided Given an empty directory @@ -40,13 +38,12 @@ Feature: Create shortcuts to specific WordPress installs path: foo """ - When I try `wp @test option get home` + When I mistakenly try `wp @test option get home` Then STDERR should be: """ Error: Alias '@test' not found. Did you mean '@test2'? """ - And the return code should be 1 Scenario: Treat global params as local when included in alias Given a WP install in 'foo' @@ -62,7 +59,7 @@ Feature: Create shortcuts to specific WordPress installs http://example.com """ - When I try `wp @foo option get home --path=foo` + When I mistakenly try `wp @foo option get home --path=foo` Then STDERR should contain: """ Parameter errors: @@ -71,7 +68,6 @@ Feature: Create shortcuts to specific WordPress installs """ unknown --path parameter """ - And the return code should be 1 When I run `wp @foo eval 'echo get_current_user_id();' --user=admin` Then STDOUT should be: @@ -92,7 +88,7 @@ Feature: Create shortcuts to specific WordPress installs 1 """ - When I try `wp @foo eval 'echo get_current_user_id();' --user=admin` + When I mistakenly try `wp @foo eval 'echo get_current_user_id();' --user=admin` Then STDERR should contain: """ Parameter errors: @@ -101,7 +97,6 @@ Feature: Create shortcuts to specific WordPress installs """ unknown --user parameter """ - And the return code should be 1 Scenario: Support global params specific to the WordPress install, not WP-CLI generally Given a WP install in 'foo' @@ -171,12 +166,11 @@ Feature: Create shortcuts to specific WordPress installs @foo: path: none-existent-install """ - When I try `WP_CLI_CONFIG_PATH=config.yml wp @foo option get home` + When I mistakenly try `WP_CLI_CONFIG_PATH=config.yml wp @foo option get home` Then STDERR should contain: """ Error: This does not seem to be a WordPress install. """ - And the return code should be 1 Scenario: Use a group of aliases to run a command against multiple installs Given a WP install in 'foo' @@ -209,12 +203,11 @@ Feature: Create shortcuts to specific WordPress installs http://google.com """ - When I try `wp @invalid option get home` + When I mistakenly try `wp @invalid option get home` Then STDERR should be: """ Error: Group '@invalid' contains one or more invalid aliases: @baz """ - And the return code should be 1 When I run `wp @both option get home` Then STDOUT should be: @@ -293,12 +286,11 @@ Feature: Create shortcuts to specific WordPress installs Scenario: Error when '@all' is used without aliases defined Given an empty directory - When I try `wp @all option get home` + When I mistakenly try `wp @all option get home` Then STDERR should be: """ Error: Cannot use '@all' when no aliases are registered. """ - And the return code should be 1 Scenario: Alias for a subsite of a multisite install Given a WP multisite subdomain install @@ -324,13 +316,12 @@ Feature: Create shortcuts to specific WordPress installs http://subsite.example.com """ - When I try `wp @subsite option get siteurl --url=subsite.example.com` + When I mistakenly try `wp @subsite option get siteurl --url=subsite.example.com` Then STDERR should be: """ Error: Parameter errors: unknown --url parameter """ - And the return code should be 1 Scenario: Global parameters should be passed to grouped aliases Given a WP install in 'foo' @@ -346,7 +337,7 @@ Feature: Create shortcuts to specific WordPress installs - @bar """ - When I try `wp core is-installed --allow-root --debug` + When I mistakenly try `wp core is-installed --allow-root --debug` Then STDERR should contain: """ Error: This does not seem to be a WordPress install. @@ -355,7 +346,6 @@ Feature: Create shortcuts to specific WordPress installs """ core is-installed --allow-root --debug """ - And the return code should be 1 When I try `wp @foo core is-installed --allow-root --debug` Then the return code should be 0 @@ -400,12 +390,11 @@ Feature: Create shortcuts to specific WordPress installs - @bar """ - When I try `{INVOKE_WP_CLI_WITH_PHP_ARGS--ddisable_functions=} @foobar core is-installed` + When I mistakenly try `{INVOKE_WP_CLI_WITH_PHP_ARGS--ddisable_functions=} @foobar core is-installed` Then STDERR should contain: """ Error: Cannot do 'group alias': The PHP functions `proc_open()` and/or `proc_close()` are disabled """ - And the return code should be 1 Examples: | func | diff --git a/features/cli-bash-completion.feature b/features/cli-bash-completion.feature index f442d4c92e..85108fd339 100644 --- a/features/cli-bash-completion.feature +++ b/features/cli-bash-completion.feature @@ -12,8 +12,6 @@ Feature: `wp cli completions` tasks """ server """ - And STDERR should be empty - And the return code should be 0 When I run `wp cli completions --line="wp co" --point=100` Then STDOUT should contain: @@ -24,8 +22,6 @@ Feature: `wp cli completions` tasks """ core """ - And STDERR should be empty - And the return code should be 0 When I run `wp cli completions --line="wp core " --point=100` Then STDOUT should contain: @@ -36,8 +32,6 @@ Feature: `wp cli completions` tasks """ update """ - And STDERR should be empty - And the return code should be 0 When I run `wp cli completions --line="wp help " --point=100` Then STDOUT should contain: @@ -48,8 +42,6 @@ Feature: `wp cli completions` tasks """ media """ - And STDERR should be empty - And the return code should be 0 When I run `wp cli completions --line="wp help language core " --point=100` Then STDOUT should contain: @@ -60,24 +52,18 @@ Feature: `wp cli completions` tasks """ update """ - And STDERR should be empty - And the return code should be 0 When I run `wp cli completions --line="wp core" --point=100` Then STDOUT should contain: """ core """ - And STDERR should be empty - And the return code should be 0 When I run `wp cli completions --line="wp core " --point=100` Then STDOUT should contain: """ download """ - And STDERR should be empty - And the return code should be 0 When I run `wp cli completions --line='wp bogus-comand ' --point=100` Then STDOUT should be empty @@ -132,16 +118,12 @@ Feature: `wp cli completions` tasks """ server """ - And STDERR should be empty - And the return code should be 0 When I run `wp cli completions --line="wp @e" --point=100` Then STDOUT should contain: """ @example """ - And STDERR should be empty - And the return code should be 0 When I run `wp cli completions --line="wp @example " --point=100` Then STDOUT should not contain: @@ -156,16 +138,12 @@ Feature: `wp cli completions` tasks """ eval """ - And STDERR should be empty - And the return code should be 0 When I run `wp cli completions --line="wp @example plugin " --point=100` Then STDOUT should contain: """ list """ - And STDERR should be empty - And the return code should be 0 When I run `wp cli completions --line="wp help language core " --point=100` Then STDOUT should contain: @@ -176,8 +154,6 @@ Feature: `wp cli completions` tasks """ update """ - And STDERR should be empty - And the return code should be 0 When I run `wp cli completions --line="wp help " --point=100` Then STDOUT should not contain: @@ -188,24 +164,18 @@ Feature: `wp cli completions` tasks """ post-type """ - And STDERR should be empty - And the return code should be 0 When I run `wp cli completions --line="wp help core" --point=100` Then STDOUT should contain: """ core """ - And STDERR should be empty - And the return code should be 0 When I run `wp cli completions --line="wp help core " --point=100` Then STDOUT should contain: """ download """ - And STDERR should be empty - And the return code should be 0 Scenario: Bash Completion for global parameters Given an empty directory @@ -279,8 +249,6 @@ Feature: `wp cli completions` tasks """ --quiet= """ - And STDERR should be empty - And the return code should be 0 When I run `wp cli completions --line="wp plugin list --path --p" --point=100` Then STDOUT should contain: diff --git a/features/cli.feature b/features/cli.feature index 14b5972de5..eac9b4ddc5 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -52,7 +52,6 @@ Feature: `wp cli` tasks """ package_url """ - And STDERR should be empty @github-api Scenario: Do WP-CLI Update @@ -78,8 +77,6 @@ Feature: `wp cli` tasks """ Success: """ - And STDERR should be empty - And the return code should be 0 When I run `{PHAR_PATH} --info` Then STDOUT should contain: @@ -117,8 +114,6 @@ Feature: `wp cli` tasks """ Success: Updated WP-CLI to 0.14.1 """ - And STDERR should be empty - And the return code should be 0 When I run `{PHAR_PATH} --version` Then STDOUT should be: @@ -140,8 +135,6 @@ Feature: `wp cli` tasks """ 0.14.1 """ - And STDERR should be empty - And the return code should be 0 @github-api Scenario: Install WP-CLI nightly @@ -158,8 +151,6 @@ Feature: `wp cli` tasks Success: Updated WP-CLI to the latest nightly release. """ - And STDERR should be empty - And the return code should be 0 @github-api Scenario: Install WP-CLI stable @@ -187,8 +178,6 @@ Feature: `wp cli` tasks """ Success: Updated WP-CLI to the latest stable release. """ - And STDERR should be empty - And the return code should be 0 When I run `{PHAR_PATH} cli check-update` Then STDOUT should be: @@ -210,5 +199,3 @@ Feature: `wp cli` tasks """ 17"current": """ - And STDERR should be empty - And the return code should be 0 diff --git a/features/command.feature b/features/command.feature index 4ea434cc84..68542af579 100644 --- a/features/command.feature +++ b/features/command.feature @@ -260,9 +260,8 @@ Feature: WP-CLI Commands WP_CLI::add_command( 'command example', 'Non_Existent_Class' ); """ - When I try `wp --require=custom-cmd.php help` - Then the return code should be 1 - And STDERR should contain: + When I mistakenly try `wp --require=custom-cmd.php help` + Then STDERR should contain: """ Callable "Non_Existent_Class" does not exist, and cannot be registered as `wp command example`. """ @@ -285,12 +284,11 @@ Feature: WP-CLI Commands WP_CLI::add_command( 'command', 'Custom_Command_Class' ); """ - When I try `wp --require=custom-cmd.php command invalid` + When I mistakenly try `wp --require=custom-cmd.php command invalid` Then STDERR should contain: """ Error: 'invalid' is not a registered subcommand of 'command'. See 'wp help command' for available subcommands. """ - And the return code should be 1 Scenario: Use a closure as a command Given an empty directory @@ -323,12 +321,11 @@ Feature: WP-CLI Commands My awesome closure command """ - When I try `wp --require=custom-cmd.php foo bar --burrito` + When I mistakenly try `wp --require=custom-cmd.php foo bar --burrito` Then STDERR should contain: """ unknown --burrito parameter """ - And the return code should be 1 When I run `wp --require=custom-cmd.php foo bar` Then STDOUT should contain: @@ -367,12 +364,11 @@ Feature: WP-CLI Commands My awesome function command """ - When I try `wp --require=custom-cmd.php foo bar --burrito` + When I mistakenly try `wp --require=custom-cmd.php foo bar --burrito` Then STDERR should contain: """ unknown --burrito parameter """ - And the return code should be 1 When I run `wp --require=custom-cmd.php foo bar` Then STDOUT should contain: @@ -418,12 +414,11 @@ Feature: WP-CLI Commands My awesome class method command """ - When I try `wp --require=custom-cmd.php foo bar --burrito` + When I mistakenly try `wp --require=custom-cmd.php foo bar --burrito` Then STDERR should contain: """ unknown --burrito parameter """ - And the return code should be 1 When I run `wp --require=custom-cmd.php foo bar` Then STDOUT should contain: @@ -464,12 +459,11 @@ Feature: WP-CLI Commands My awesome class method command """ - When I try `wp --require=custom-cmd.php foo bar --burrito` + When I mistakenly try `wp --require=custom-cmd.php foo bar --burrito` Then STDERR should contain: """ unknown --burrito parameter """ - And the return code should be 1 When I run `wp --require=custom-cmd.php foo bar` Then STDOUT should contain: @@ -506,7 +500,6 @@ Feature: WP-CLI Commands """ bar """ - And STDERR should be empty Scenario: Use an invalid class method as a command Given an empty directory @@ -530,12 +523,11 @@ Feature: WP-CLI Commands WP_CLI::add_command( 'bar', array( $foo, 'bar' ) ); """ - When I try `wp --require=custom-cmd.php bar` + When I mistakenly try `wp --require=custom-cmd.php bar` Then STDERR should contain: """ Error: Callable ["Foo_Class","bar"] does not exist, and cannot be registered as `wp bar`. """ - And the return code should be 1 Scenario: Register a synopsis for a given command Given an empty directory @@ -629,19 +621,17 @@ Feature: WP-CLI Commands --- """ - When I try `wp foo nana --apple=fuji` + When I mistakenly try `wp foo nana --apple=fuji` Then STDERR should contain: """ Error: Invalid value specified for positional arg. """ - And the return code should be 1 - When I try `wp foo hello --apple=fuji --meal=snack` + When I mistakenly try `wp foo hello --apple=fuji --meal=snack` Then STDERR should contain: """ Invalid value specified for 'meal' (A type of meal.) """ - And the return code should be 1 When I run `wp foo hello --apple=fuji` Then STDOUT should be: @@ -757,7 +747,6 @@ Feature: WP-CLI Commands shop: burrito: """ - And STDERR should be empty When I run `wp --require=test-cmd.php foo ''` Then STDOUT should be YAML containing: @@ -766,7 +755,6 @@ Feature: WP-CLI Commands shop: burrito: """ - And STDERR should be empty When I run `wp --require=test-cmd.php foo apple --burrito=veggies` Then STDOUT should be YAML containing: @@ -775,37 +763,32 @@ Feature: WP-CLI Commands shop: burrito: veggies """ - And STDERR should be empty - When I try `wp --require=test-cmd.php foo apple --burrito=meat` + When I mistakenly try `wp --require=test-cmd.php foo apple --burrito=meat` Then STDERR should contain: """ Error: Parameter errors: Invalid value specified for 'burrito' (This is the burrito argument.) """ - And the return code should be 1 - When I try `wp --require=test-cmd.php foo apple --burrito=''` + When I mistakenly try `wp --require=test-cmd.php foo apple --burrito=''` Then STDERR should contain: """ Error: Parameter errors: Invalid value specified for 'burrito' (This is the burrito argument.) """ - And the return code should be 1 - When I try `wp --require=test-cmd.php foo apple taco_del_mar` + When I mistakenly try `wp --require=test-cmd.php foo apple taco_del_mar` Then STDERR should contain: """ Error: Invalid value specified for positional arg. """ - And the return code should be 1 - When I try `wp --require=test-cmd.php foo apple 'cha cha cha' taco_del_mar` + When I mistakenly try `wp --require=test-cmd.php foo apple 'cha cha cha' taco_del_mar` Then STDERR should contain: """ Error: Invalid value specified for positional arg. """ - And the return code should be 1 When I run `wp --require=test-cmd.php foo apple 'cha cha cha'` Then STDOUT should be YAML containing: @@ -814,7 +797,6 @@ Feature: WP-CLI Commands shop: cha cha cha burrito: """ - And STDERR should be empty Scenario: Register a command with default and accepted arguments, part two Given an empty directory @@ -848,21 +830,18 @@ Feature: WP-CLI Commands """ burrito: """ - And STDERR should be empty When I run `wp --require=test-cmd.php foo beans` Then STDOUT should be YAML containing: """ burrito: beans """ - And STDERR should be empty - When I try `wp --require=test-cmd.php foo apple` + When I mistakenly try `wp --require=test-cmd.php foo apple` Then STDERR should be: """ Error: Invalid value specified for positional arg. """ - And the return code should be 1 Scenario: Removing a subcommand should remove it from the index Given an empty directory @@ -963,48 +942,42 @@ Feature: WP-CLI Commands """ bar """ - And STDERR should be empty Scenario: WP-CLI suggests matching commands when user entry contains typos Given a WP install - When I try `wp clu` + When I mistakenly try `wp clu` Then STDERR should contain: """ Did you mean 'cli'? """ - And the return code should be 1 - When I try `wp cli nfo` + When I mistakenly try `wp cli nfo` Then STDERR should contain: """ Did you mean 'info'? """ - And the return code should be 1 - When I try `wp cli beyondlevenshteinthreshold` + When I mistakenly try `wp cli beyondlevenshteinthreshold` Then STDERR should not contain: """ Did you mean """ - And the return code should be 1 Scenario: WP-CLI suggests matching parameters when user entry contains typos Given an empty directory - When I try `wp cli info --quie` + When I mistakenly try `wp cli info --quie` Then STDERR should contain: """ Did you mean '--quiet'? """ - And the return code should be 1 - When I try `wp cli info --forma=json` + When I mistakenly try `wp cli info --forma=json` Then STDERR should contain: """ Did you mean '--format'? """ - And the return code should be 1 Scenario: Adding a command can be aborted through the hooks system Given an empty directory @@ -1019,7 +992,7 @@ Feature: WP-CLI Commands WP_CLI::add_command( 'test-command-2', function () {} ); """ - When I try `wp --require=abort-add-command.php` + When I successfully try `wp --require=abort-add-command.php` Then STDOUT should contain: """ test-command-1 @@ -1032,7 +1005,6 @@ Feature: WP-CLI Commands """ Warning: Aborting the addition of the command 'test-command-2' with reason: Testing hooks.. """ - And the return code should be 0 Scenario: Adding a command can depend on a previous command having been added before Given an empty directory @@ -1113,28 +1085,24 @@ Feature: WP-CLI Commands """ test-command """ - And STDERR should be empty When I run `wp help test-command` Then STDOUT should contain: """ sub-command """ - And STDERR should be empty When I run `wp test-command sub-command` Then STDOUT should contain: """ Success: test-command sub-command """ - And STDERR should be empty When I run `wp unknown-parent child-command` Then STDOUT should contain: """ Success: unknown-parent child-command """ - And STDERR should be empty Scenario: Command additions should work as must-use plugins Given a WP install @@ -1162,28 +1130,24 @@ Feature: WP-CLI Commands """ test-command """ - And STDERR should be empty When I run `wp help test-command` Then STDOUT should contain: """ sub-command """ - And STDERR should be empty When I run `wp test-command sub-command` Then STDOUT should contain: """ Success: test-command sub-command """ - And STDERR should be empty When I run `wp unknown-parent child-command` Then STDOUT should contain: """ Success: unknown-parent child-command """ - And STDERR should be empty Scenario: Command additions should work when registered on after_wp_load Given a WP install @@ -1213,28 +1177,24 @@ Feature: WP-CLI Commands """ test-command """ - And STDERR should be empty When I run `wp help test-command` Then STDOUT should contain: """ sub-command """ - And STDERR should be empty When I run `wp test-command sub-command` Then STDOUT should contain: """ Success: test-command sub-command """ - And STDERR should be empty When I run `wp unknown-parent child-command` Then STDOUT should contain: """ Success: unknown-parent child-command """ - And STDERR should be empty Scenario: The command should fire on `after_wp_load` Given a WP install @@ -1268,21 +1228,18 @@ Feature: WP-CLI Commands """ bool(true) """ - And the return code should be 0 When I run `wp command before_wp_load` Then STDOUT should contain: """ bool(false) """ - And the return code should be 0 - When I try `wp command after_wp_load --path=/tmp` + When I mistakenly try `wp command after_wp_load --path=/tmp` Then STDERR should contain: """ Error: This does not seem to be a WordPress install. """ - And the return code should be 1 Scenario: The command should fire on `before_wp_load` Given a WP install @@ -1313,20 +1270,16 @@ Feature: WP-CLI Commands """ When I run `wp command before_wp_load` - Then STDERR should be empty - And STDOUT should contain: + Then STDOUT should contain: """ bool(false) """ - And the return code should be 0 When I run `wp command after_wp_load` - Then STDERR should be empty - And STDOUT should contain: + Then STDOUT should contain: """ bool(true) """ - And the return code should be 0 Scenario: Command hook should fires as expected on __invoke() Given a WP install @@ -1357,14 +1310,12 @@ Feature: WP-CLI Commands """ bool(true) """ - And the return code should be 0 - When I try `wp command --path=/tmp` + When I mistakenly try `wp command --path=/tmp` Then STDERR should contain: """ Error: This does not seem to be a WordPress install. """ - And the return code should be 1 Scenario: Command namespaces can be added and are shown in help Given an empty directory @@ -1387,7 +1338,6 @@ Feature: WP-CLI Commands """ My Command Namespace Description. """ - And STDERR should be empty Scenario: Command namespaces are only added when the command does not exist Given an empty directory @@ -1416,7 +1366,6 @@ Feature: WP-CLI Commands """ My Actual Namespaced Command. """ - And STDERR should be empty Scenario: Command namespaces are replaced by commands of the same name Given an empty directory @@ -1445,7 +1394,6 @@ Feature: WP-CLI Commands """ My Actual Namespaced Command. """ - And STDERR should be empty Scenario: Empty command namespaces show a notice when invoked Given an empty directory @@ -1464,4 +1412,3 @@ Feature: WP-CLI Commands """ The namespace my-namespaced-command does not contain any usable commands in the current context. """ - And STDERR should be empty diff --git a/features/config.feature b/features/config.feature index 2fe971928b..ac49b558a9 100644 --- a/features/config.feature +++ b/features/config.feature @@ -108,12 +108,11 @@ Feature: Have a config file eval-file """ - When I try `WP_CLI_CONFIG_PATH=config.yml wp help eval-file` + When I mistakenly try `WP_CLI_CONFIG_PATH=config.yml wp help eval-file` Then STDERR should be: """ Error: The 'eval-file' command has been disabled from the config file. """ - And the return code should be 1 When I run `WP_CLI_CONFIG_PATH=config.yml wp core` Then STDOUT should not contain: @@ -127,19 +126,17 @@ Feature: Have a config file multisite-convert """ - When I try `WP_CLI_CONFIG_PATH=config.yml wp core multisite-convert` + When I mistakenly try `WP_CLI_CONFIG_PATH=config.yml wp core multisite-convert` Then STDERR should contain: """ command has been disabled """ - And the return code should be 1 - When I try `WP_CLI_CONFIG_PATH=config.yml wp help core multisite-convert` + When I mistakenly try `WP_CLI_CONFIG_PATH=config.yml wp help core multisite-convert` Then STDERR should contain: """ Error: The 'core multisite-convert' command has been disabled from the config file. """ - And the return code should be 1 Scenario: 'core config' parameters Given an empty directory @@ -178,12 +175,11 @@ Feature: Have a config file administrator """ - When I try `wp user create examplejane` + When I mistakenly try `wp user create examplejane` Then STDERR should be: """ Error: Sorry, that email address is already used! """ - And the return code should be 1 When I run `wp user create examplejane jane@example.com` Then STDOUT should not be empty @@ -241,7 +237,7 @@ Feature: Have a config file Scenario: Load WordPress with `--debug` Given a WP install - When I try `wp option get home --debug` + When I successfully try `wp option get home --debug` Then STDERR should contain: """ No readable global config found @@ -266,14 +262,13 @@ Feature: Have a config file """ Running command: option get """ - And the return code should be 0 - When I try `wp option get home --debug=bootstrap` + When I successfully try `wp option get home --debug=bootstrap` Then STDERR should contain: """ No readable global config found """ - Then STDERR should contain: + And STDERR should contain: """ No project config found """ @@ -293,34 +288,12 @@ Feature: Have a config file """ Running command: option get """ - And the return code should be 0 - When I try `wp option get home --debug=foo` - Then STDERR should not contain: - """ - No readable global config found - """ - Then STDERR should not contain: - """ - No project config found - """ - And STDERR should not contain: - """ - Begin WordPress load - """ - And STDERR should not contain: - """ - wp-config.php path: - """ - And STDERR should not contain: - """ - Loaded WordPress - """ - And STDERR should not contain: + When I run `wp option get home --debug=foo` + Then STDOUT should contain: """ - Running command: option get + http://example.com """ - And the return code should be 0 Scenario: Missing required files should not fatal WP-CLI Given an empty directory @@ -330,12 +303,11 @@ Feature: Have a config file - missing-file.php """ - When I try `wp help` + When I mistakenly try `wp help` Then STDERR should contain: """ Error: Required file 'missing-file.php' doesn't exist (from project's wp-cli.yml). """ - And the return code should be 1 When I run `wp cli info` Then STDOUT should not be empty @@ -351,22 +323,20 @@ Feature: Have a config file - /foo/baz.php """ - When I try `WP_CLI_CONFIG_PATH=config.yml wp help` + When I mistakenly try `WP_CLI_CONFIG_PATH=config.yml wp help` Then STDERR should contain: """ Error: Required file 'baz.php' doesn't exist (from global config.yml). """ - And the return code should be 1 Scenario: Missing required file as runtime argument Given an empty directory - When I try `wp help --require=foo.php` + When I mistakenly try `wp help --require=foo.php` Then STDERR should contain: """ Error: Required file 'foo.php' doesn't exist (from runtime argument). """ - And the return code should be 1 Scenario: Config inheritance from project to global Given an empty directory @@ -533,12 +503,11 @@ if ( !defined('ABSPATH') ) require_once(ABSPATH . 'wp-settings.php'); """ - When I try `wp option get home` + When I mistakenly try `wp option get home` Then STDERR should be: """ Error: Site 'example.dev/' not found. Verify DOMAIN_CURRENT_SITE matches an existing site or use `--url=` to override. """ - And the return code should be 1 When I run `wp option get home --url=example.com` Then STDOUT should be: diff --git a/features/flags.feature b/features/flags.feature index 4e2804b44b..759da17c7c 100644 --- a/features/flags.feature +++ b/features/flags.feature @@ -27,19 +27,17 @@ Feature: Global flags Scenario: Invalid URL Given a WP multisite install - When I try `wp post list --url=invalid.example.com` + When I mistakenly try `wp post list --url=invalid.example.com` Then STDERR should be: """ Error: Site 'invalid.example.com' not found. Verify `--url=` matches an existing site. """ - And the return code should be 1 Scenario: Quiet run Given a WP install - When I try `wp non-existing-command --quiet` - Then the return code should be 1 - And STDERR should be: + When I mistakenly try `wp non-existing-command --quiet` + Then STDERR should be: """ Error: 'non-existing-command' is not a registered wp command. See 'wp help' for available commands. """ @@ -58,9 +56,8 @@ Feature: Global flags """ And the return code should be 0 - When I try `wp eval 'echo CONST_WITHOUT_QUOTES;' --debug` - Then the return code should be 0 - And STDOUT should be: + When I successfully try `wp eval 'echo CONST_WITHOUT_QUOTES;' --debug` + Then STDOUT should be: """ CONST_WITHOUT_QUOTES """ @@ -90,9 +87,8 @@ Feature: Global flags admin """ - When I try `wp --user=non-existing-user eval 'echo wp_get_current_user()->user_login;'` - Then the return code should be 1 - And STDERR should be: + When I mistakenly try `wp --user=non-existing-user eval 'echo wp_get_current_user()->user_login;'` + Then STDERR should be: """ Error: Invalid user ID, email or login: 'non-existing-user' """ @@ -209,19 +205,17 @@ Feature: Global flags Scenario: Enabling/disabling color Given a WP install - When I try `wp --no-color non-existent-command` + When I mistakenly try `wp --no-color non-existent-command` Then STDERR should be: """ Error: 'non-existent-command' is not a registered wp command. See 'wp help' for available commands. """ - And the return code should be 1 - When I try `wp --color non-existent-command` + When I mistakenly try `wp --color non-existent-command` Then STDERR should contain: """ [31;1mError: """ - And the return code should be 1 Scenario: Use `WP_CLI_STRICT_ARGS_MODE` to distinguish between global and local args Given an empty directory @@ -272,12 +266,11 @@ Feature: Global flags Scenario: Using --http= requires wp-cli/restful Given an empty directory - When I try `wp --http=foo.dev` + When I mistakenly try `wp --http=foo.dev` Then STDERR should be: """ Error: RESTful WP-CLI needs to be installed. Try 'wp package install wp-cli/restful'. """ - And the return code should be 1 Scenario: Strict args mode should be passed on to ssh When I try `WP_CLI_STRICT_ARGS_MODE=1 wp --debug --ssh=/ --version` @@ -302,3 +295,4 @@ Feature: Global flags Running SSH command: docker exec --user 'user' 'wordpress' sh -c """ And the return code should not be 0 + diff --git a/features/framework.feature b/features/framework.feature index c7e22a68d6..1f1bdd3d62 100644 --- a/features/framework.feature +++ b/features/framework.feature @@ -160,12 +160,11 @@ Feature: Load WP-CLI }); """ - When I try `wp option get home` + When I successfully try `wp option get home` Then STDERR should contain: """ Warning: Some code is trying to do a URL redirect. """ - And the return code should be 0 Scenario: It should be possible to work on a site in maintenance mode Given a WP install @@ -189,19 +188,17 @@ Feature: Load WP-CLI define( 'DB_HOST', 'localghost' ); """ - When I try `wp --require=invalid-host.php option get home` + When I mistakenly try `wp --require=invalid-host.php option get home` Then STDERR should contain: """ Error: Error establishing a database connection. """ - And the return code should be 1 - When I try `wp --require=invalid-host.php option get home` + When I mistakenly try `wp --require=invalid-host.php option get home` Then STDERR should contain: """ Error: Error establishing a database connection. """ - And the return code should be 1 Scenario: Allow WP_CLI hooks to pass arguments to callbacks Given an empty directory @@ -272,28 +269,24 @@ Feature: Load WP-CLI Given a WP install And I run `wp db reset --yes` - When I try `wp option get home` + When I mistakenly try `wp option get home` Then STDERR should be: """ Error: The site you have requested is not installed. Run `wp core install` to create database tables. """ - And STDOUT should be empty - And the return code should be 1 Scenario: Show potential table prefixes when site isn't found, single site. Given a WP install And "$table_prefix = 'wp_';" replaced with "$table_prefix = 'cli_';" in the wp-config.php file - When I try `wp option get home` + When I mistakenly try `wp option get home` Then STDERR should be: """ Error: The site you have requested is not installed. Your table prefix is 'cli_'. Found install with table prefix: wp_. Or, run `wp core install` to create database tables. """ - And STDOUT should be empty - And the return code should be 1 # Use try to cater for wp-db errors in old WPs. When I try `wp core install --url=example.com --title=example --admin_user=wpcli --admin_email=wpcli@example.com` @@ -305,34 +298,30 @@ Feature: Load WP-CLI Given "$table_prefix = 'cli_';" replaced with "$table_prefix = 'test_';" in the wp-config.php file - When I try `wp option get home` + When I mistakenly try `wp option get home` Then STDERR should be: """ Error: The site you have requested is not installed. Your table prefix is 'test_'. Found installs with table prefix: cli_, wp_. Or, run `wp core install` to create database tables. """ - And STDOUT should be empty - And the return code should be 1 @require-wp-3.9 Scenario: Display a more helpful error message when site can't be found Given a WP multisite install And "define( 'DOMAIN_CURRENT_SITE', 'example.com' );" replaced with "define( 'DOMAIN_CURRENT_SITE', 'example.org' );" in the wp-config.php file - When I try `wp option get home` + When I mistakenly try `wp option get home` Then STDERR should be: """ Error: Site 'example.org/' not found. Verify DOMAIN_CURRENT_SITE matches an existing site or use `--url=` to override. """ - And the return code should be 1 - When I try `wp option get home --url=example.io` + When I mistakenly try `wp option get home --url=example.io` Then STDERR should be: """ Error: Site 'example.io' not found. Verify `--url=` matches an existing site. """ - And the return code should be 1 Given "define( 'DOMAIN_CURRENT_SITE', 'example.org' );" replaced with " " in the wp-config.php file @@ -342,16 +331,14 @@ Feature: Load WP-CLI DOMAIN_CURRENT_SITE """ - When I try `wp option get home` + When I mistakenly try `wp option get home` Then STDERR should be: """ Error: Site not found. Define DOMAIN_CURRENT_SITE in 'wp-config.php' or use `--url=` to override. """ - And the return code should be 1 - When I try `wp option get home --url=example.io` + When I mistakenly try `wp option get home --url=example.io` Then STDERR should be: """ Error: Site 'example.io' not found. Verify `--url=` matches an existing site. """ - And the return code should be 1 diff --git a/features/hook.feature b/features/hook.feature index cb61a6abfa..5346a7c7e4 100644 --- a/features/hook.feature +++ b/features/hook.feature @@ -22,7 +22,6 @@ Feature: Tests `WP_CLI::add_hook()` """ `add_hook()` to the `before_invoke` is working. """ - And the return code should be 0 Scenario: Add callback to the `before_invoke` Given a WP install @@ -46,7 +45,6 @@ Feature: Tests `WP_CLI::add_hook()` """ `add_hook()` to the `before_invoke` is working. """ - And the return code should be 0 Scenario: Add callback to the `before_invoke` Given a WP install @@ -70,4 +68,3 @@ Feature: Tests `WP_CLI::add_hook()` """ `add_hook()` to the `before_invoke` is working. """ - And the return code should be 0 diff --git a/features/make-phar.feature b/features/make-phar.feature index 14799793ec..ef4945f7f6 100644 --- a/features/make-phar.feature +++ b/features/make-phar.feature @@ -10,9 +10,8 @@ Feature: Check `utils/make-phar.php` output WP_CLI::add_command( 'command example', 'Dealerdirect\Composer\Plugin\Installers\PHPCodeSniffer\Plugin' ); """ - When I try `php -derror_log='' {PHAR_PATH} --require=custom-cmd.php help` - Then the return code should be 1 - And STDERR should contain: + When I mistakenly try `php -derror_log='' {PHAR_PATH} --require=custom-cmd.php help` + Then STDERR should contain: """ Error: Callable """ @@ -20,7 +19,6 @@ Feature: Check `utils/make-phar.php` output """ PHP Warning """ - And STDOUT should be empty When I try `grep '/dealerdirect\|/squizlabs\|/wimg' {PHAR_PATH}` Then the return code should be 1 diff --git a/features/prompt.feature b/features/prompt.feature index bd39f2c438..834024a405 100644 --- a/features/prompt.feature +++ b/features/prompt.feature @@ -78,9 +78,7 @@ Feature: Prompt user for input """ When I run `echo 'bar' | wp foobar foo --prompt=flag1` - Then the return code should be 0 - And STDERR should be empty - And STDOUT should contain: + Then STDOUT should contain: """ arg: foo """ diff --git a/features/runner.feature b/features/runner.feature index 4d3342b072..22f6bd7459 100644 --- a/features/runner.feature +++ b/features/runner.feature @@ -1,21 +1,19 @@ Feature: Runner WP-CLI Scenario: Path argument should be slashed correctly - When I try `wp no-such-command --path=/foo --debug` + When I mistakenly try `wp no-such-command --path=/foo --debug` Then STDERR should contain: """ ABSPATH defined: /foo/ """ - And the return code should be 1 - When I try `wp no-such-command --path=/foo/ --debug` + When I mistakenly try `wp no-such-command --path=/foo/ --debug` Then STDERR should contain: """ ABSPATH defined: /foo/ """ - And the return code should be 1 - When I try `wp no-such-command --path=/foo\\ --debug` + When I mistakenly try `wp no-such-command --path=/foo\\ --debug` Then STDERR should contain: """ ABSPATH defined: /foo/ diff --git a/features/skip-plugins.feature b/features/skip-plugins.feature index 6e1de6cee9..cadc1d0ecf 100644 --- a/features/skip-plugins.feature +++ b/features/skip-plugins.feature @@ -81,7 +81,7 @@ Feature: Skipping plugins Scenario: Skip network active plugins Given a WP multisite install - When I try `wp plugin deactivate akismet hello` + When I successfully try `wp plugin deactivate akismet hello` Then STDERR should be: """ Warning: Plugin 'akismet' isn't active. @@ -91,7 +91,6 @@ Feature: Skipping plugins """ Success: Plugins already deactivated. """ - And the return code should be 0 When I run `wp plugin activate --network akismet hello` And I run `wp eval 'var_export( defined("AKISMET_VERSION") );var_export( function_exists( "hello_dolly" ) );'` diff --git a/features/skip-themes.feature b/features/skip-themes.feature index 4cf73fc926..aac3e4d079 100644 --- a/features/skip-themes.feature +++ b/features/skip-themes.feature @@ -14,7 +14,6 @@ Feature: Skipping themes """ true """ - And STDERR should be empty # The specified theme should be skipped When I run `wp --skip-themes=espied eval 'var_export( function_exists( "espied_scripts" ) );'` @@ -22,7 +21,6 @@ Feature: Skipping themes """ false """ - And STDERR should be empty # All themes should be skipped When I run `wp --skip-themes eval 'var_export( function_exists( "espied_scripts" ) );'` @@ -30,7 +28,6 @@ Feature: Skipping themes """ false """ - And STDERR should be empty # Skip another theme When I run `wp --skip-themes=classic eval 'var_export( function_exists( "espied_scripts" ) );'` @@ -38,7 +35,6 @@ Feature: Skipping themes """ true """ - And STDERR should be empty # The specified theme should still show up as an active theme When I run `wp --skip-themes theme status espied` @@ -46,7 +42,6 @@ Feature: Skipping themes """ Active """ - And STDERR should be empty # Skip several themes When I run `wp --skip-themes=classic,espied eval 'var_export( function_exists( "espied_scripts" ) );'` @@ -54,7 +49,6 @@ Feature: Skipping themes """ false """ - And STDERR should be empty Scenario: Skip parent and child themes Given a WP install @@ -70,14 +64,12 @@ Feature: Skipping themes """ true """ - And STDERR should be empty When I run `wp --skip-themes=espied eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ false """ - And STDERR should be empty When I run `wp theme activate sidespied` When I run `wp eval 'var_export( function_exists( "espied_scripts" ) );'` @@ -85,42 +77,36 @@ Feature: Skipping themes """ true """ - And STDERR should be empty When I run `wp eval 'var_export( function_exists( "sidespied_scripts" ) );'` Then STDOUT should be: """ true """ - And STDERR should be empty When I run `wp --skip-themes=sidespied eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ false """ - And STDERR should be empty When I run `wp --skip-themes=sidespied eval 'var_export( function_exists( "sidespied_scripts" ) );'` Then STDOUT should be: """ false """ - And STDERR should be empty When I run `wp --skip-themes=sidespied eval 'echo get_template_directory();'` Then STDOUT should contain: """ wp-content/themes/espied """ - And STDERR should be empty When I run `wp --skip-themes=sidespied eval 'echo get_stylesheet_directory();'` Then STDOUT should contain: """ wp-content/themes/sidespied """ - And STDERR should be empty Scenario: Skipping multiple themes via config file Given a WP install @@ -143,7 +129,6 @@ Feature: Skipping themes """ A classic """ - And STDERR should be empty # The espied theme should show up as an installed theme When I run `wp theme status` @@ -151,7 +136,6 @@ Feature: Skipping themes """ I espied """ - And STDERR should be empty And I run `wp theme activate espied` @@ -161,4 +145,3 @@ Feature: Skipping themes """ false """ - And STDERR should be empty diff --git a/features/steps/when.php b/features/steps/when.php index 7ec0fa340d..03a8fdf7e6 100644 --- a/features/steps/when.php +++ b/features/steps/when.php @@ -18,7 +18,7 @@ function invoke_proc( $proc, $mode ) { } else { $return_code = 0; $stderr_empty = false; - $stdout_empty = null; + $stdout_empty = false; } return $proc->run_check_full( $return_code, $stderr_empty, $stdout_empty ); } @@ -34,7 +34,7 @@ function ( $world, $cmd ) { } ); -$steps->When( '/^I (run|try|mistakenly try|dubiously try) `([^`]+)`$/', +$steps->When( '/^I (run|try|mistakenly try|successfully try) `([^`]+)`$/', function ( $world, $mode, $cmd, $return_code = 0, $stdout_empty = '' ) { $cmd = $world->replace_variables( $cmd ); $world->result = invoke_proc( $world->proc( $cmd ), $mode ); diff --git a/features/validation.feature b/features/validation.feature index a431787643..2a921272a7 100644 --- a/features/validation.feature +++ b/features/validation.feature @@ -17,9 +17,8 @@ Feature: Argument validation Given an empty directory And WP files - When I try `wp core config` - Then the return code should be 1 - And STDERR should contain: + When I mistakenly try `wp core config` + Then STDERR should contain: """ Parameter errors: """ @@ -28,9 +27,8 @@ Feature: Argument validation missing --dbname parameter """ - When I try `wp core config --invalid --other-invalid` - Then the return code should be 1 - And STDERR should contain: + When I mistakenly try `wp core config --invalid --other-invalid` + Then STDERR should contain: """ unknown --invalid parameter """ @@ -39,10 +37,8 @@ Feature: Argument validation unknown --other-invalid parameter """ - When I try `wp core version invalid` - Then the return code should be 1 - And STDERR should contain: + When I mistakenly try `wp core version invalid` + Then STDERR should contain: """ Error: Too many positional arguments: invalid """ - And STDOUT should be empty From 7d388981c346e4e629ed6b48828728296c901481 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 22 Nov 2017 08:50:41 +0000 Subject: [PATCH 121/214] More phpcs nonsense. --- php/WP_CLI/Process.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php/WP_CLI/Process.php b/php/WP_CLI/Process.php index 1340d9e259..ccf61a7e86 100644 --- a/php/WP_CLI/Process.php +++ b/php/WP_CLI/Process.php @@ -143,10 +143,10 @@ public function run_check_full( $return_code = 0, $stderr_empty = null, $stdout_ if ( $return_code !== $r->return_code ) { throw new \RuntimeException( $r ); } - if ( null !== $stderr_empty && $stderr_empty !== empty( $r->stderr ) ) { + if ( null !== $stderr_empty && empty( $r->stderr ) !== $stderr_empty ) { throw new \RuntimeException( $r ); } - if ( null !== $stdout_empty && $stdout_empty !== empty( $r->stdout ) ) { + if ( null !== $stdout_empty && empty( $r->stdout ) !== $stdout_empty ) { throw new \RuntimeException( $r ); } From 1e4b54e7a9ed3f4e319d2bd7d8f08d61d925b0bd Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 22 Nov 2017 19:44:37 +0000 Subject: [PATCH 122/214] Fiddle. --- features/bootstrap/FeatureContext.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 0a8d195196..c44f4617cd 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -300,7 +300,7 @@ private static function terminate_proc( $master_pid ) { $errno = posix_get_last_error(); // Ignore "No such process" error as that's what we want. if ( 3 /*ESRCH*/ !== $errno ) { - throw new RuntimeException( posix_strerror( $errno ) ); + throw new \RuntimeException( posix_strerror( $errno ) ); } } } @@ -546,14 +546,14 @@ private static function run_sql( $sql_cmd, $assoc_args = array(), $add_database public function create_db() { $dbname = self::$db_settings['dbname']; - self::run_sql( 'mysql --no-defaults --no-auto-rehash --quick', array( 'execute' => "CREATE DATABASE IF NOT EXISTS $dbname" ) ); + self::run_sql( 'mysql --no-defaults --no-auto-rehash --quick', array( 'execute' => "CREATE DATABASE IF NOT EXISTS `$dbname` CHARSET 'UTF8'" ) ); self::$have_dropped_db = false; } public function drop_db() { if ( ! self::$have_dropped_db ) { $dbname = self::$db_settings['dbname']; - self::run_sql( 'mysql --no-defaults --no-auto-rehash --quick', array( 'execute' => "DROP DATABASE IF EXISTS $dbname" ) ); + self::run_sql( 'mysql --no-defaults --no-auto-rehash --quick', array( 'execute' => "DROP DATABASE IF EXISTS `$dbname`" ) ); self::$have_dropped_db = true; } } @@ -594,7 +594,7 @@ public function background_proc( $cmd ) { if ( !$status['running'] ) { $stderr = is_resource( $pipes[2] ) ? ( ': ' . stream_get_contents( $pipes[2] ) ) : ''; - throw new RuntimeException( sprintf( "Failed to start background process '%s'%s.", $cmd, $stderr ) ); + throw new \RuntimeException( sprintf( "Failed to start background process '%s'%s.", $cmd, $stderr ) ); } else { $this->running_procs[] = $proc; } From 48825165b6f2246321294ecd6b33cc7d22eaee80 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 22 Nov 2017 20:51:49 +0000 Subject: [PATCH 123/214] Make invoke_proc prettier. --- features/steps/when.php | 25 +++++++++---------------- php/WP_CLI/Process.php | 6 +++--- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/features/steps/when.php b/features/steps/when.php index 03a8fdf7e6..7e9aba10ed 100644 --- a/features/steps/when.php +++ b/features/steps/when.php @@ -5,22 +5,15 @@ WP_CLI\Process; function invoke_proc( $proc, $mode ) { - if ( 'run' === $mode ) { - return $proc->run_check_stderr(); - } - if ( 'try' === $mode ) { - return $proc->run(); - } - if ( 'mistakenly try' === $mode ) { - $return_code = 1; - $stderr_empty = false; - $stdout_empty = true; - } else { - $return_code = 0; - $stderr_empty = false; - $stdout_empty = false; - } - return $proc->run_check_full( $return_code, $stderr_empty, $stdout_empty ); + $map = array( + 'run' => array( 0, true, null ), + 'try' => array( null, null, null ), + 'mistakenly try' => array( 1, false, true ), + 'successfully try' => array( 0, false, false ), + ); + $args = $map[ $mode ]; + + return $proc->run_check_args( $args[0] /*return_code*/, $args[1] /*stderr_empty*/, $args[2] /*stdout_empty*/ ); } function capture_email_sends( $stdout ) { diff --git a/php/WP_CLI/Process.php b/php/WP_CLI/Process.php index ccf61a7e86..be6ba8d49b 100644 --- a/php/WP_CLI/Process.php +++ b/php/WP_CLI/Process.php @@ -133,14 +133,14 @@ public function run_check_stderr() { } /** - * Run the command, but throw an Exception if the conditions aren't as given. + * Run the command, but throw an Exception if the non-null args aren't as given. * * @return ProcessRun */ - public function run_check_full( $return_code = 0, $stderr_empty = null, $stdout_empty = null ) { + public function run_check_args( $return_code = null, $stderr_empty = null, $stdout_empty = null ) { $r = $this->run(); - if ( $return_code !== $r->return_code ) { + if ( null !== $return_code && $r->return_code !== $return_code ) { throw new \RuntimeException( $r ); } if ( null !== $stderr_empty && empty( $r->stderr ) !== $stderr_empty ) { From aa67be4736af1f82f9051a64dfbbfcb66ae19d06 Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 23 Nov 2017 16:01:12 +0000 Subject: [PATCH 124/214] See if mysqldump --skip-opt makes any diff on Travis. --- .travis.yml | 2 +- features/bootstrap/FeatureContext.php | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5353828996..9a33aca6c7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ jobs: - stage: test script: ./ci/test.sh php: 7.0 - env: WP_VERSION=latest WP_CLI_TEST_LOG_RUN_TIMES=1 + env: WP_VERSION=latest WP_CLI_TEST_LOG_RUN_TIMES='stdout,40,40' - stage: test script: ./ci/test.sh php: 5.6 diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index c44f4617cd..79568842e4 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -675,7 +675,9 @@ public function install_wp( $subdir = '' ) { mkdir( self::$install_cache_dir ); } - $subdir = $this->replace_variables( $subdir ); + if ( $subdir ) { + $subdir = $this->replace_variables( $subdir ); + } $this->create_db(); $this->create_run_dir(); @@ -705,7 +707,10 @@ public function install_wp( $subdir = '' ) { if ( $install_cache_path ) { mkdir( $install_cache_path ); self::dir_diff_copy( $run_dir, self::$cache_dir, $install_cache_path ); - self::run_sql( 'mysqldump --no-defaults', array( 'result-file' => "{$install_cache_path}.sql" ), true /*add_database*/ ); + self::run_sql( + 'mysqldump --no-defaults --skip-opt --skip-comments --add-drop-table --create-options --extended-insert', + array( 'result-file' => "{$install_cache_path}.sql" ), true /*add_database*/ + ); } } } From 21c8efb58629720fb3ce7a217803f5500a1b46b0 Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 24 Nov 2017 18:29:24 +0000 Subject: [PATCH 125/214] Add ask in auto_update_check. --- features/bootstrap/FeatureContext.php | 5 +---- php/WP_CLI/Runner.php | 19 +++++++++++++++++-- php/class-wp-cli.php | 23 ++++++++++++++++++++--- php/commands/src/CLI_Command.php | 14 +++++++++++--- 4 files changed, 49 insertions(+), 12 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 79568842e4..9585ea32b5 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -707,10 +707,7 @@ public function install_wp( $subdir = '' ) { if ( $install_cache_path ) { mkdir( $install_cache_path ); self::dir_diff_copy( $run_dir, self::$cache_dir, $install_cache_path ); - self::run_sql( - 'mysqldump --no-defaults --skip-opt --skip-comments --add-drop-table --create-options --extended-insert', - array( 'result-file' => "{$install_cache_path}.sql" ), true /*add_database*/ - ); + self::run_sql( 'mysqldump --no-defaults', array( 'result-file' => "{$install_cache_path}.sql" ), true /*add_database*/ ); } } } diff --git a/php/WP_CLI/Runner.php b/php/WP_CLI/Runner.php index c320581b84..2b57572af6 100644 --- a/php/WP_CLI/Runner.php +++ b/php/WP_CLI/Runner.php @@ -1572,6 +1572,18 @@ private function auto_check_update() { // In case the operation fails, ensure the timestamp has been updated. $cache->write( $cache_key, time() ); + // Ask before doing remote request. + $current_command = implode( ' ', $this->arguments ); + $msg = sprintf( + "(Note you can control whether and when to check for updates with the 'WP_CLI_DISABLE_AUTO_CHECK_UPDATE' and 'WP_CLI_AUTO_CHECK_UPDATE_DAYS' environment variables.)\n" . + 'You have version %s. Would you like to check if an update of WP-CLI is available?', WP_CLI_VERSION + ); + if ( ! WP_CLI::ask( $msg ) ) { + WP_CLI::log( sprintf( "Continuing with your current command '%s'...", $current_command ) ); + return; + } + + WP_CLI::log( "Checking for an update of WP-CLI..." ); // Check whether any updates are available. ob_start(); WP_CLI::run_command( @@ -1586,9 +1598,12 @@ private function auto_check_update() { } // Looks like an update is available, so let's prompt to update. + WP_CLI::log( sprintf( "Update found - invoking 'cli update' (please note that if you decide to update, your current command '%s' will not complete)...", $current_command ) ); + WP_CLI::run_command( array( 'cli', 'update' ) ); - // If the Phar was replaced, we can't proceed with the original process. - exit; + + // If the Phar was replaced, we've exited so don't get here. + WP_CLI::log( sprintf( "Continuing with your current command '%s'...", $current_command ) ); } /** diff --git a/php/class-wp-cli.php b/php/class-wp-cli.php index 6e23dde649..5e8d7ecd8e 100644 --- a/php/class-wp-cli.php +++ b/php/class-wp-cli.php @@ -816,15 +816,32 @@ public static function error_multi_line( $message_lines ) { * @param array $assoc_args Skips prompt if 'yes' is provided. */ public static function confirm( $question, $assoc_args = array() ) { + if ( ! self::ask( $question, $assoc_args ) ) { + exit; + } + } + + /** + * Ask for confirmation before doing something. + * + * If 'y' is provided to the question, it returns true. If + * 'n' or any other response is provided to the question, it returns false. + * + * @access public + * @category Input + * + * @param string $question Question to display before the prompt. + * @param array $assoc_args Skips prompt if 'yes' is provided. + */ + public static function ask( $question, $assoc_args = array() ) { if ( ! \WP_CLI\Utils\get_flag_value( $assoc_args, 'yes' ) ) { fwrite( STDOUT, $question . ' [y/n] ' ); $answer = strtolower( trim( fgets( STDIN ) ) ); - if ( 'y' != $answer ) { - exit; - } + return 'y' === $answer; } + return true; } /** diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index ff15e6967b..b9293e65f8 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -256,11 +256,15 @@ public function update( $_, $assoc_args ) { } if ( Utils\get_flag_value( $assoc_args, 'nightly' ) ) { - WP_CLI::confirm( sprintf( 'You have version %s. Would you like to update to the latest nightly?', WP_CLI_VERSION ), $assoc_args ); + if ( ! WP_CLI::ask( sprintf( 'You have version %s. Would you like to update to the latest nightly?', WP_CLI_VERSION ), $assoc_args ) ) { + return; + } $download_url = 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli-nightly.phar'; $md5_url = 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli-nightly.phar.md5'; } elseif ( Utils\get_flag_value( $assoc_args, 'stable' ) ) { - WP_CLI::confirm( sprintf( 'You have version %s. Would you like to update to the latest stable release?', WP_CLI_VERSION ), $assoc_args ); + if ( ! WP_CLI::ask( sprintf( 'You have version %s. Would you like to update to the latest stable release?', WP_CLI_VERSION ), $assoc_args ) ) { + return; + } $download_url = 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar'; $md5_url = 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar.md5'; } else { @@ -275,7 +279,9 @@ public function update( $_, $assoc_args ) { $newest = $updates[0]; - WP_CLI::confirm( sprintf( 'You have version %s. Would you like to update to %s?', WP_CLI_VERSION, $newest['version'] ), $assoc_args ); + if ( ! WP_CLI::ask( sprintf( 'You have version %s. Would you like to update to %s?', WP_CLI_VERSION, $newest['version'] ), $assoc_args ) ) { + return; + } $download_url = $newest['package_url']; $md5_url = str_replace( '.phar', '.phar.md5', $download_url ); @@ -337,6 +343,8 @@ class_exists( '\cli\Colors' ); // This autoloads \cli\Colors - after we move the $updated_version = $newest['version']; } WP_CLI::success( sprintf( 'Updated WP-CLI to %s.', $updated_version ) ); + // As the Phar was replaced, we must exit to avoid PHP errors. + exit; } /** From 1230d0ab28edb0b3180e8cec7b10b46298f43140 Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 24 Nov 2017 22:56:55 +0000 Subject: [PATCH 126/214] Add tests for auto_cli_update ask. --- features/cli.feature | 119 +++++++++++++++++++++++++++++++++++++++ features/steps/given.php | 12 +++- php/WP_CLI/Runner.php | 2 +- 3 files changed, 129 insertions(+), 4 deletions(-) diff --git a/features/cli.feature b/features/cli.feature index eac9b4ddc5..b77ea97c95 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -191,6 +191,125 @@ Feature: `wp cli` tasks WP-CLI {UPDATE_VERSION} """ + @github-api + Scenario: Install WP-CLI via auto-update + Given an empty directory + And an empty cache + And a new Phar with version "0.14.0" and cli build + And a session_no file: + """ + n + """ + And a session_yes_no file: + """ + y + n + """ + And a session_yes_yes file: + """ + y + y + """ + + When I run `{PHAR_PATH} cli check-update --field=version | head -1` + Then STDOUT should not be empty + And save STDOUT as {UPDATE_VERSION} + + Given a {SUITE_CACHE_DIR}/wp-cli-update-check file: + """ + 1 + """ + When I run `SHELL_PIPE=0 {PHAR_PATH} help < session_no` + Then STDOUT should contain: + """ + You have version 0.14.0. Would you like to check if an update of WP-CLI is available? [y/n] + """ + And STDOUT should contain: + """ + Continuing with your current command 'help'... + """ + And STDOUT should contain: + """ + wp + """ + And STDOUT should not contain: + """ + Checking for an update + """ + + Given a {SUITE_CACHE_DIR}/wp-cli-update-check file: + """ + 1 + """ + When I run `SHELL_PIPE=0 {PHAR_PATH} help < session_yes_no` + Then STDOUT should contain: + """ + You have version 0.14.0. Would you like to check if an update of WP-CLI is available? [y/n] + """ + And STDOUT should contain: + """ + Checking for an update of WP-CLI... + Update found - invoking 'cli update' (please note that if you decide to update, your current command 'help' will not complete)... + """ + And STDOUT should contain: + """ + You have version 0.14.0. Would you like to update to {UPDATE_VERSION}? [y/n] + """ + And STDOUT should contain: + """ + Continuing with your current command 'help'... + """ + And STDOUT should contain: + """ + wp + """ + And STDOUT should not contain: + """ + Downloading + """ + + Given a {SUITE_CACHE_DIR}/wp-cli-update-check file: + """ + 1 + """ + When I run `SHELL_PIPE=0 {PHAR_PATH} help < session_yes_yes` + Then STDOUT should contain: + """ + You have version 0.14.0. Would you like to check if an update of WP-CLI is available? [y/n] + """ + And STDOUT should contain: + """ + Checking for an update of WP-CLI... + Update found - invoking 'cli update' (please note that if you decide to update, your current command 'help' will not complete)... + You have version 0.14.0. Would you like to update to {UPDATE_VERSION}? [y/n] + """ + And STDOUT should contain: + """ + Downloading from https://github.com/wp-cli/wp-cli/releases/download/v{UPDATE_VERSION}/wp-cli-{UPDATE_VERSION}.phar... + """ + And STDOUT should contain: + """ + New version works. Proceeding to replace. + """ + And STDOUT should contain: + """ + Success: + """ + And STDOUT should not contain: + """ + Continuing + """ + And STDOUT should not contain: + """ + wp + """ + + When I run `{PHAR_PATH} cli check-update` + Then STDOUT should be: + """ + Success: WP-CLI is at the latest version. + """ + Scenario: Dump the list of global parameters with values Given a WP install diff --git a/features/steps/given.php b/features/steps/given.php index 6af042c6e1..97aad8aba5 100644 --- a/features/steps/given.php +++ b/features/steps/given.php @@ -35,12 +35,18 @@ function ( $world ) { $steps->Given( '/^an? ([^\s]+) file:$/', function ( $world, $path, PyStringNode $content ) { $content = (string) $content . "\n"; - $full_path = $world->variables['RUN_DIR'] . "/$path"; - $dir = dirname( $full_path ); + $path = $world->replace_variables( $path ); + if ( ! WP_CLI\Utils\is_path_absolute( $path ) ) { + $path = $world->variables['RUN_DIR'] . "/$path"; + } + if ( 0 !== strpos( $path, sys_get_temp_dir() ) ) { + throw new RuntimeException( sprintf( "Attempted to create a file '%s' that is not in the temp directory '%s'. " . __FILE__ . ':' . __LINE__, $path, sys_get_temp_dir() ) ); + } + $dir = dirname( $path ); if ( ! file_exists( $dir ) ) { mkdir( $dir, 0777, true /*recursive*/ ); } - file_put_contents( $full_path, $content ); + file_put_contents( $path, $content ); } ); diff --git a/php/WP_CLI/Runner.php b/php/WP_CLI/Runner.php index 2b57572af6..eddff3026a 100644 --- a/php/WP_CLI/Runner.php +++ b/php/WP_CLI/Runner.php @@ -1540,7 +1540,7 @@ private function auto_check_update() { } // Only check for update when a human is operating. - if ( ! function_exists( 'posix_isatty' ) || ! posix_isatty( STDOUT ) ) { + if ( Utils\isPiped() ) { return; } From e65705de7042210dac807f964dae2b15de77144f Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 25 Nov 2017 00:30:24 +0000 Subject: [PATCH 127/214] Fix phpcs. --- php/WP_CLI/Runner.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php/WP_CLI/Runner.php b/php/WP_CLI/Runner.php index eddff3026a..b355b82254 100644 --- a/php/WP_CLI/Runner.php +++ b/php/WP_CLI/Runner.php @@ -1574,7 +1574,7 @@ private function auto_check_update() { // Ask before doing remote request. $current_command = implode( ' ', $this->arguments ); - $msg = sprintf( + $msg = sprintf( "(Note you can control whether and when to check for updates with the 'WP_CLI_DISABLE_AUTO_CHECK_UPDATE' and 'WP_CLI_AUTO_CHECK_UPDATE_DAYS' environment variables.)\n" . 'You have version %s. Would you like to check if an update of WP-CLI is available?', WP_CLI_VERSION ); @@ -1583,7 +1583,7 @@ private function auto_check_update() { return; } - WP_CLI::log( "Checking for an update of WP-CLI..." ); + WP_CLI::log( 'Checking for an update of WP-CLI...' ); // Check whether any updates are available. ob_start(); WP_CLI::run_command( From d077dea0b7b7412a92cfc385638d7c0de9d33502 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 25 Nov 2017 01:12:07 +0000 Subject: [PATCH 128/214] check -> auto-check --- php/WP_CLI/Runner.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/WP_CLI/Runner.php b/php/WP_CLI/Runner.php index b355b82254..49198be485 100644 --- a/php/WP_CLI/Runner.php +++ b/php/WP_CLI/Runner.php @@ -1575,7 +1575,7 @@ private function auto_check_update() { // Ask before doing remote request. $current_command = implode( ' ', $this->arguments ); $msg = sprintf( - "(Note you can control whether and when to check for updates with the 'WP_CLI_DISABLE_AUTO_CHECK_UPDATE' and 'WP_CLI_AUTO_CHECK_UPDATE_DAYS' environment variables.)\n" . + "(Note you can control whether and when to auto-check for updates with the 'WP_CLI_DISABLE_AUTO_CHECK_UPDATE' and 'WP_CLI_AUTO_CHECK_UPDATE_DAYS' environment variables.)\n" . 'You have version %s. Would you like to check if an update of WP-CLI is available?', WP_CLI_VERSION ); if ( ! WP_CLI::ask( $msg ) ) { From ceff0df9454477db0f6a7f04e89298c73c1d1384 Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 28 Nov 2017 20:38:41 +0000 Subject: [PATCH 129/214] Check what's cached. --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 19a6b056a3..e1c25c9d10 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,11 @@ before_script: - export PATH="$HOME/.composer/vendor/bin:$PATH" - ./ci/prepare.sh +after_script: + - ls -la vendor + - ls -la $HOME/.composer + - ls -la $HOME/.composer/cache + jobs: include: - stage: sniff From 2c9cfc243070eb0f59ac2f87c832f8c0c91f13b9 Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 28 Nov 2017 21:36:29 +0000 Subject: [PATCH 130/214] Check what's in composer/cache recursive. --- .travis.yml | 36 +----------------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/.travis.yml b/.travis.yml index e1c25c9d10..1d114b877c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,51 +15,17 @@ before_script: - ./ci/prepare.sh after_script: - - ls -la vendor - - ls -la $HOME/.composer - - ls -la $HOME/.composer/cache + - ls -laR $HOME/.composer/cache jobs: include: - stage: sniff script: ./ci/sniff.sh env: BUILD=sniff - - stage: test - script: ./ci/test.sh - php: 7.2 - env: WP_VERSION=latest - - stage: test - script: ./ci/test.sh - php: 7.1 - env: WP_VERSION=latest - stage: test script: ./ci/test.sh php: 7.0 env: WP_VERSION=latest WP_CLI_TEST_LOG_RUN_TIMES='stdout,40,40' - - stage: test - script: ./ci/test.sh - php: 5.6 - env: WP_VERSION=latest - - stage: test - script: ./ci/test.sh - php: 5.6 - env: WP_VERSION=trunk - - stage: test - script: ./ci/test.sh - php: 5.6 - env: WP_VERSION=latest BUILD=git WP_CLI_BIN_DIR='' - - stage: test - script: ./ci/test.sh - php: 5.6 - env: WP_VERSION=3.7.11 - - stage: test - script: ./ci/test.sh - php: 5.3 - dist: precise - env: WP_VERSION=3.7.11 - - stage: deploy - env: DEPLOY_BRANCH=master - script: ./ci/deploy.sh cache: directories: From 3fde29ab8044790a405a08e3e671d90179138640 Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 28 Nov 2017 22:33:15 +0000 Subject: [PATCH 131/214] Restore .travis.yml. --- .travis.yml | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1d114b877c..19a6b056a3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,18 +14,47 @@ before_script: - export PATH="$HOME/.composer/vendor/bin:$PATH" - ./ci/prepare.sh -after_script: - - ls -laR $HOME/.composer/cache - jobs: include: - stage: sniff script: ./ci/sniff.sh env: BUILD=sniff + - stage: test + script: ./ci/test.sh + php: 7.2 + env: WP_VERSION=latest + - stage: test + script: ./ci/test.sh + php: 7.1 + env: WP_VERSION=latest - stage: test script: ./ci/test.sh php: 7.0 env: WP_VERSION=latest WP_CLI_TEST_LOG_RUN_TIMES='stdout,40,40' + - stage: test + script: ./ci/test.sh + php: 5.6 + env: WP_VERSION=latest + - stage: test + script: ./ci/test.sh + php: 5.6 + env: WP_VERSION=trunk + - stage: test + script: ./ci/test.sh + php: 5.6 + env: WP_VERSION=latest BUILD=git WP_CLI_BIN_DIR='' + - stage: test + script: ./ci/test.sh + php: 5.6 + env: WP_VERSION=3.7.11 + - stage: test + script: ./ci/test.sh + php: 5.3 + dist: precise + env: WP_VERSION=3.7.11 + - stage: deploy + env: DEPLOY_BRANCH=master + script: ./ci/deploy.sh cache: directories: From 30bf2588bd68ec80e6836740b35e359e90bfa299 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 29 Nov 2017 01:38:05 +0000 Subject: [PATCH 132/214] Microptimize install_cache.sql. --- features/bootstrap/FeatureContext.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 9585ea32b5..cc1722b501 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -706,8 +706,9 @@ public function install_wp( $subdir = '' ) { $this->proc( 'wp core install', $install_args, $subdir )->run_check(); if ( $install_cache_path ) { mkdir( $install_cache_path ); - self::dir_diff_copy( $run_dir, self::$cache_dir, $install_cache_path ); - self::run_sql( 'mysqldump --no-defaults', array( 'result-file' => "{$install_cache_path}.sql" ), true /*add_database*/ ); + $install_cache_sql = $install_cache_path . '.sql'; + self::run_sql( 'mysqldump --no-defaults --skip-comments', array( 'result-file' => $install_cache_sql ), true /*add_database*/ ); + file_put_contents( $install_cache_sql, preg_replace( '/^\/\*[^*]+\*\/;\n/m', '', file_get_contents( $install_cache_sql ) ) ); // Remove conditional statements. } } } From a3833a20d92f59058f8a3062b17709fbe71a3d05 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 29 Nov 2017 02:43:06 +0000 Subject: [PATCH 133/214] Add back removed dir_diff_copy duh. --- features/bootstrap/FeatureContext.php | 1 + 1 file changed, 1 insertion(+) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index cc1722b501..26c1ee0151 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -706,6 +706,7 @@ public function install_wp( $subdir = '' ) { $this->proc( 'wp core install', $install_args, $subdir )->run_check(); if ( $install_cache_path ) { mkdir( $install_cache_path ); + self::dir_diff_copy( $run_dir, self::$cache_dir, $install_cache_path ); $install_cache_sql = $install_cache_path . '.sql'; self::run_sql( 'mysqldump --no-defaults --skip-comments', array( 'result-file' => $install_cache_sql ), true /*add_database*/ ); file_put_contents( $install_cache_sql, preg_replace( '/^\/\*[^*]+\*\/;\n/m', '', file_get_contents( $install_cache_sql ) ) ); // Remove conditional statements. From 40dd3c386b37e8348365e3e11a422165310b15e4 Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 30 Nov 2017 18:27:08 +0000 Subject: [PATCH 134/214] Use preg_replace instead of loop in get_longdesc; declare all class vars. --- php/WP_CLI/Dispatcher/CompositeCommand.php | 3 ++- php/WP_CLI/DocParser.php | 10 +--------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/php/WP_CLI/Dispatcher/CompositeCommand.php b/php/WP_CLI/Dispatcher/CompositeCommand.php index 0ace467a6b..b6bfd79ff7 100644 --- a/php/WP_CLI/Dispatcher/CompositeCommand.php +++ b/php/WP_CLI/Dispatcher/CompositeCommand.php @@ -12,7 +12,8 @@ */ class CompositeCommand { - protected $name, $shortdesc, $synopsis, $docparser; + protected $name, $shortdesc, $longdesc, $docparser; + protected $synopsis; // Used by Subcommand. protected $parent, $subcommands = array(); diff --git a/php/WP_CLI/DocParser.php b/php/WP_CLI/DocParser.php index 1c8fd93503..0794c54802 100644 --- a/php/WP_CLI/DocParser.php +++ b/php/WP_CLI/DocParser.php @@ -64,15 +64,7 @@ public function get_longdesc() { $longdesc = substr( $this->docComment, strlen( $shortdesc ) ); - $lines = array(); - foreach ( explode( "\n", $longdesc ) as $line ) { - if ( 0 === strpos( $line, '@' ) ) { - break; - } - - $lines[] = $line; - } - $longdesc = trim( implode( $lines, "\n" ) ); + $longdesc = preg_replace( '/^@.*\z/ms', '', $longdesc ); return $longdesc; } From f59765c31d177cbd5764b12ab2cd7d3d45ca7c97 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 2 Dec 2017 01:34:09 +0000 Subject: [PATCH 135/214] Speed up the tests a bit, primarily when running locally. --- features/bootstrap.feature | 2 +- features/bootstrap/FeatureContext.php | 116 +++++++++++++++++++++++--- features/cli.feature | 32 ++----- features/skip-themes.feature | 82 ++++++++---------- features/steps/given.php | 6 +- utils/make-phar.php | 9 +- 6 files changed, 160 insertions(+), 87 deletions(-) diff --git a/features/bootstrap.feature b/features/bootstrap.feature index 6f1365d5d6..f2e1f2f1f7 100644 --- a/features/bootstrap.feature +++ b/features/bootstrap.feature @@ -148,7 +148,7 @@ Feature: Bootstrap WP-CLI Scenario: Override command bundled with freshly built PHAR Given an empty directory - And a new Phar with the same version + And a new Phar with the same version and cli build And a cli-override-command/cli.php file: """ '127.0.0.1', ); + /** + * Variables for `do_mysqli()`. + */ + private static $dbh = null; // Database handle. + private static $db_selected = false; // Whether database selected (opened). + /** * Array of background process ids started by the current scenario. Used to terminate them at the end of the scenario. */ @@ -88,7 +94,7 @@ class FeatureContext extends BehatContext implements ClosuredContextInterface { /** * Array of variables available as {VARIABLE_NAME}. Some are always set: CORE_CONFIG_SETTINGS, SRC_DIR, CACHE_DIR, WP_VERSION-version-latest. Some are step-dependent: - * RUN_DIR, SUITE_CACHE_DIR, COMPOSER_LOCAL_REPOSITORY, PHAR_PATH. Scenarios can define their own variables using "Given save" steps. Variables are reset for each scenario. + * RUN_DIR, SUITE_CACHE_DIR, COMPOSER_LOCAL_REPOSITORY, COMPOSER_PATH, PHAR_PATH. Scenarios can define their own variables using "Given save" steps. Variables are reset for each scenario. */ public $variables = array(); @@ -409,7 +415,13 @@ public function create_run_dir() { } } - public function build_phar( $version = 'same' ) { + /** + * Build a phar based on whatever's in the directory from which behat is run. + * + * @param string $version Version to set it to. (Note: has no correspondence with the actual version of the contained source.) + * @param string $build If set to "cli" will do a fast build without any bundled commands - "cli" command only. Defaults to '' (full build). + */ + public function build_phar( $version = 'same', $build = '' ) { $this->variables['PHAR_PATH'] = $this->variables['RUN_DIR'] . '/' . uniqid( "wp-cli-build-", TRUE ) . '.phar'; // Test running against a package installed as a WP-CLI dependency @@ -425,13 +437,17 @@ public function build_phar( $version = 'same' ) { } $this->proc( Utils\esc_cmd( - 'php -dphar.readonly=0 %1$s %2$s --version=%3$s && chmod +x %2$s', + 'php -dphar.readonly=0 %1$s %2$s --version=%3$s --quiet --build=%4$s', $make_phar_path, $this->variables['PHAR_PATH'], - $version + $version, + $build ) )->run_check(); } + /** + * Download a released phar from github.com. Note: not currently used in any test. + */ public function download_phar( $version = 'same' ) { if ( 'same' === $version ) { $version = WP_CLI_VERSION; @@ -483,20 +499,30 @@ private static function run_sql( $sql_cmd, $assoc_args = array(), $add_database $start_time = microtime( true ); Utils\run_mysql_command( $sql_cmd, array_merge( $assoc_args, $default_assoc_args ) ); if ( self::$log_run_times ) { - self::log_proc_method_run_time( 'run_sql ' . $sql_cmd, $start_time ); + self::log_proc_method_run_time( $sql_cmd . ' ' . Utils\assoc_args_to_str( $assoc_args ), $start_time ); } } + /** + * Create the `$db_settings['dbname']` test database. Called on a "Given a database" step and on the various "Given a WP install..." steps. + */ public function create_db() { $dbname = self::$db_settings['dbname']; - self::run_sql( 'mysql --no-defaults', array( 'execute' => "CREATE DATABASE IF NOT EXISTS $dbname" ) ); + self::do_mysqli( "CREATE DATABASE IF NOT EXISTS `$dbname` CHARSET 'UTF8'" ); } + /** + * Drop the `$db_settings['dbname']` test database. Done at the beginning of every scenario. + */ public function drop_db() { $dbname = self::$db_settings['dbname']; - self::run_sql( 'mysql --no-defaults', array( 'execute' => "DROP DATABASE IF EXISTS $dbname" ) ); + self::do_mysqli( "DROP DATABASE IF EXISTS `$dbname`" ); + self::$db_selected = false; } + /** + * Run a process from the RUN_DIR directory (or a sub-directory of it if given `$path`). + */ public function proc( $command, $assoc_args = array(), $path = '' ) { if ( !empty( $assoc_args ) ) $command .= Utils\assoc_args_to_str( $assoc_args ); @@ -563,6 +589,9 @@ public function add_line_to_wp_config( &$wp_config_code, $line ) { $wp_config_code = str_replace( $token, "$line\n\n$token", $wp_config_code ); } + /** + * "Downloads" wp in the sense that it copies the version downloaded and cached by `cache_wp_files()` from CACHE_DIR to RUN_DIR (or a sub-directory of it if given `$subdir`). + */ public function download_wp( $subdir = '' ) { $dest_dir = $this->variables['RUN_DIR'] . "/$subdir"; @@ -572,7 +601,7 @@ public function download_wp( $subdir = '' ) { self::copy_dir( self::$cache_dir, $dest_dir ); - // disable emailing + // Disable emailing - otherwise will get "sh: 1: -t: not found" error message on Travis (as PHP ini `sendmail_from` not set by default). mkdir( $dest_dir . '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/wp-content/mu-plugins' ); copy( __DIR__ . '/../extra/no-mail.php', $dest_dir . '/wp-content/mu-plugins/no-mail.php' ); } @@ -584,6 +613,7 @@ public function create_config( $subdir = '', $extra_php = false ) { $params['dbprefix'] = $subdir ? preg_replace( '#[^a-zA-Z\_0-9]#', '_', $subdir ) : 'wp_'; $params['skip-salts'] = true; + $params['skip-check'] = true; if( false !== $extra_php ) { $params['extra-php'] = $extra_php; @@ -636,13 +666,16 @@ public function install_wp( $subdir = '' ) { if ( $install_cache_path && file_exists( $install_cache_path ) ) { self::copy_dir( $install_cache_path, $run_dir ); - self::run_sql( 'mysql --no-defaults', array( 'execute' => "source {$install_cache_path}.sql" ), true /*add_database*/ ); + self::do_mysqli_source( $install_cache_path . '.sql' ); } else { $this->proc( 'wp core install', $install_args, $subdir )->run_check(); if ( $install_cache_path ) { mkdir( $install_cache_path ); self::dir_diff_copy( $run_dir, self::$cache_dir, $install_cache_path ); - self::run_sql( 'mysqldump --no-defaults', array( 'result-file' => "{$install_cache_path}.sql" ), true /*add_database*/ ); + $install_cache_sql = $install_cache_path . '.sql'; + self::run_sql( 'mysqldump --no-defaults --skip-comments', array( 'result-file' => $install_cache_sql ), true /*add_database*/ ); + // Remove conditional and lock tables statements. + file_put_contents( $install_cache_sql, preg_replace( array( '/^\/\*[^*]+\*\/;\n/m', '/^(?:UN)?LOCK TABLES[^;]*;\n/m' ), '', file_get_contents( $install_cache_sql ) ) ); } } } @@ -717,6 +750,69 @@ private function composer_command($cmd) { $this->proc( $this->variables['COMPOSER_PATH'] . ' ' . $cmd )->run_check(); } + /** + * Do a MySQL query with `$db_settings`, using the PHP mysqli extension. Slightly faster than `run_sql()`. + * + * @param string $sql_cmd MySQL query. + * @param bool $open_database Whether to open (select) the database or not. + * @param bool $multi_query Whether the query contains multiple statements or not. + * @param bool $no_log If set won't log timing if using log run times. + */ + private static function do_mysqli( $sql_cmd, $open_database = false, $multi_query = false, $no_log = false ) { + $start_time = microtime( true ); + + if ( null === self::$dbh ) { + if ( ! ( self::$dbh = mysqli_connect( self::$db_settings['dbhost'], self::$db_settings['dbuser'], self::$db_settings['dbpass'] ) ) ) { + throw new \RuntimeException( + sprintf( "Failed to connect to MySQL database host '%s', user '%s', pass '%s'.", self::$db_settings['dbhost'], self::$db_settings['dbuser'], self::$db_settings['dbpass'] ) + ); + } + } + if ( $open_database && ! self::$db_selected ) { + if ( ! mysqli_select_db( self::$dbh, self::$db_settings['dbname'] ) ) { + throw new \RuntimeException( sprintf( "Failed to open MySQL database name '%s'.", self::$db_settings['dbname'] ) ); + } + self::$db_selected = true; + } + if ( $multi_query ) { + if ( ! mysqli_multi_query( self::$dbh, $sql_cmd ) ) { + throw new \RuntimeException( sprintf( "Failed to execute MySQL query '%s': %d: %s", $sql_cmd, mysqli_errno( self::$dbh ), mysqli_error( self::$dbh ) ) ); + } + // Throw away the stored results (otherwise will get "out of sync" errors). + while ( mysqli_more_results( self::$dbh ) ) { + mysqli_next_result( self::$dbh ); + } + } else { + if ( ! mysqli_query( self::$dbh, $sql_cmd ) ) { + throw new \RuntimeException( sprintf( "Failed to execute MySQL query '%s': %d: %s", $sql_cmd, mysqli_errno( self::$dbh ), mysqli_error( self::$dbh ) ) ); + } + } + if ( self::$log_run_times && ! $no_log ) { + self::log_proc_method_run_time( 'do_mysqli ' . $sql_cmd, $start_time ); + } + } + + /** + * Do a MySQL SOURCE command using the PHP mysqli extension. Slightly faster than doing a mysql SOURCE command using `run_sql()`. + * + * @param string $source_file Name of MySQL source ".sql" file. + */ + private static function do_mysqli_source( $source_file ) { + $start_time = microtime( true ); + + static $files = array(); + + if ( ! isset( $files[ $source_file ] ) ) { + $files[ $source_file ] = file_get_contents( $source_file ); + } + + self::do_mysqli( $files[ $source_file ], true /*open_database*/, true /*multi_query*/, true /*no_log*/ ); + + if ( self::$log_run_times ) { + self::log_proc_method_run_time( 'do_mysqli_source ' . $source_file, $start_time ); + } + } + /** * Initialize run time logging. */ diff --git a/features/cli.feature b/features/cli.feature index 819fe01c58..7c29e5dfa3 100644 --- a/features/cli.feature +++ b/features/cli.feature @@ -30,7 +30,7 @@ Feature: `wp cli` tasks Scenario: Ability to set a custom version when building Given an empty directory And save the {SRC_DIR}/VERSION file as {TRUE_VERSION} - And a new Phar with version "1.2.3" + And a new Phar with version "1.2.3" and cli build When I run `{PHAR_PATH} cli version` Then STDOUT should be: @@ -45,19 +45,18 @@ Feature: `wp cli` tasks @github-api Scenario: Check for updates Given an empty directory - And a new Phar with version "0.0.0" + And a new Phar with version "0.0.0" and cli build When I run `{PHAR_PATH} cli check-update` Then STDOUT should contain: """ package_url """ - And STDERR should be empty @github-api Scenario: Do WP-CLI Update Given an empty directory - And a new Phar with version "0.0.0" + And a new Phar with version "0.0.0" and cli build When I run `{PHAR_PATH} --info` Then STDOUT should contain: @@ -78,8 +77,6 @@ Feature: `wp cli` tasks """ Success: """ - And STDERR should be empty - And the return code should be 0 When I run `{PHAR_PATH} --info` Then STDOUT should contain: @@ -100,7 +97,7 @@ Feature: `wp cli` tasks @github-api Scenario: Patch update from 0.14.0 to 0.14.1 Given an empty directory - And a new Phar with version "0.14.0" + And a new Phar with version "0.14.0" and cli build When I run `{PHAR_PATH} --version` Then STDOUT should be: @@ -117,8 +114,6 @@ Feature: `wp cli` tasks """ Success: Updated WP-CLI to 0.14.1 """ - And STDERR should be empty - And the return code should be 0 When I run `{PHAR_PATH} --version` Then STDOUT should be: @@ -129,7 +124,7 @@ Feature: `wp cli` tasks @github-api Scenario: Not a patch update from 0.14.0 Given an empty directory - And a new Phar with version "0.14.0" + And a new Phar with version "0.14.0" and cli build When I run `{PHAR_PATH} cli update --no-patch --yes` Then STDOUT should contain: @@ -140,13 +135,11 @@ Feature: `wp cli` tasks """ 0.14.1 """ - And STDERR should be empty - And the return code should be 0 - @require-php-5.6 + @github-api Scenario: Install WP-CLI nightly Given an empty directory - And a new Phar with version "0.14.0" + And a new Phar with version "0.14.0" and cli build When I run `{PHAR_PATH} cli update --nightly --yes` Then STDOUT should contain: @@ -158,13 +151,10 @@ Feature: `wp cli` tasks Success: Updated WP-CLI to the latest nightly release. """ - And STDERR should be empty - And the return code should be 0 - - @github-api @less-than-php-7 + @github-api Scenario: Install WP-CLI stable Given an empty directory - And a new Phar with version "0.14.0" + And a new Phar with version "0.14.0" and cli build And a session file: """ y @@ -187,8 +177,6 @@ Feature: `wp cli` tasks """ Success: Updated WP-CLI to the latest stable release. """ - And STDERR should be empty - And the return code should be 0 When I run `{PHAR_PATH} cli check-update` Then STDOUT should be: @@ -210,5 +198,3 @@ Feature: `wp cli` tasks """ 17"current": """ - And STDERR should be empty - And the return code should be 0 diff --git a/features/skip-themes.feature b/features/skip-themes.feature index 7a710c719b..def4d4095a 100644 --- a/features/skip-themes.feature +++ b/features/skip-themes.feature @@ -1,118 +1,111 @@ Feature: Skipping themes + Background: + Given download: + | path | url | + | {CACHE_DIR}/classic.1.6.zip | https://downloads.wordpress.org/theme/classic.1.6.zip | + | {CACHE_DIR}/espied.1.2.2.zip | https://downloads.wordpress.org/theme/espied.1.2.2.zip | + | {CACHE_DIR}/sidespied.1.0.3.zip | https://downloads.wordpress.org/theme/sidespied.1.0.3.zip | + Scenario: Skipping themes via global flag Given a WP install - And I run `wp theme install classic` - And I run `wp theme install default --activate` + And I run `wp theme install {CACHE_DIR}/classic.1.6.zip` + And I run `wp theme install {CACHE_DIR}/espied.1.2.2.zip --activate` - When I run `wp eval 'var_export( function_exists( "kubrick_head" ) );'` + When I run `wp eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ true """ - And STDERR should be empty # The specified theme should be skipped - When I run `wp --skip-themes=default eval 'var_export( function_exists( "kubrick_head" ) );'` + When I run `wp --skip-themes=espied eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ false """ - And STDERR should be empty # All themes should be skipped - When I run `wp --skip-themes eval 'var_export( function_exists( "kubrick_head" ) );'` + When I run `wp --skip-themes eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ false """ - And STDERR should be empty # Skip another theme - When I run `wp --skip-themes=classic eval 'var_export( function_exists( "kubrick_head" ) );'` + When I run `wp --skip-themes=classic eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ true """ - And STDERR should be empty # The specified theme should still show up as an active theme - When I run `wp --skip-themes theme status default` + When I run `wp --skip-themes theme status espied` Then STDOUT should contain: """ Active """ - And STDERR should be empty # Skip several themes - When I run `wp --skip-themes=classic,default eval 'var_export( function_exists( "kubrick_head" ) );'` + When I run `wp --skip-themes=classic,espied eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ false """ - And STDERR should be empty Scenario: Skip parent and child themes Given a WP install - And I run `wp theme install jolene biker` + And I run `wp theme install {CACHE_DIR}/espied.1.2.2.zip {CACHE_DIR}/sidespied.1.0.3.zip` - When I run `wp theme activate jolene` - When I run `wp eval 'var_export( function_exists( "jolene_setup" ) );'` + When I run `wp theme activate espied` + When I run `wp eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ true """ - And STDERR should be empty - When I run `wp --skip-themes=jolene eval 'var_export( function_exists( "jolene_setup" ) );'` + When I run `wp --skip-themes=espied eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ false """ - And STDERR should be empty - When I run `wp theme activate biker` - When I run `wp eval 'var_export( function_exists( "jolene_setup" ) );'` + When I run `wp theme activate sidespied` + When I run `wp eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ true """ - And STDERR should be empty - When I run `wp eval 'var_export( function_exists( "biker_setup" ) );'` + When I run `wp eval 'var_export( function_exists( "sidespied_scripts" ) );'` Then STDOUT should be: """ true """ - And STDERR should be empty - When I run `wp --skip-themes=biker eval 'var_export( function_exists( "jolene_setup" ) );'` + When I run `wp --skip-themes=sidespied eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ false """ - And STDERR should be empty - When I run `wp --skip-themes=biker eval 'var_export( function_exists( "biker_setup" ) );'` + When I run `wp --skip-themes=sidespied eval 'var_export( function_exists( "sidespied_scripts" ) );'` Then STDOUT should be: """ false """ - And STDERR should be empty - When I run `wp --skip-themes=biker eval 'echo get_template_directory();'` + When I run `wp --skip-themes=sidespied eval 'echo get_template_directory();'` Then STDOUT should contain: """ - wp-content/themes/jolene + wp-content/themes/espied """ - And STDERR should be empty - When I run `wp --skip-themes=biker eval 'echo get_stylesheet_directory();'` + When I run `wp --skip-themes=sidespied eval 'echo get_stylesheet_directory();'` Then STDOUT should contain: """ - wp-content/themes/biker + wp-content/themes/sidespied """ - And STDERR should be empty Scenario: Skipping multiple themes via config file Given a WP install @@ -120,10 +113,10 @@ Feature: Skipping themes """ skip-themes: - classic - - default + - espied """ - And I run `wp theme install classic --activate` - And I run `wp theme install default` + And I run `wp theme install {CACHE_DIR}/classic.1.6.zip --activate` + And I run `wp theme install {CACHE_DIR}/espied.1.2.2.zip` # The classic theme should show up as an active theme When I run `wp theme status` @@ -131,22 +124,19 @@ Feature: Skipping themes """ A classic """ - And STDERR should be empty - # The default theme should show up as an installed theme + # The espied theme should show up as an installed theme When I run `wp theme status` Then STDOUT should contain: """ - I default + I espied """ - And STDERR should be empty - And I run `wp theme activate default` + And I run `wp theme activate espied` - # The default theme should be skipped - When I run `wp eval 'var_export( function_exists( "kubrick_head" ) );'` + # The espied theme should be skipped + When I run `wp eval 'var_export( function_exists( "espied_scripts" ) );'` Then STDOUT should be: """ false """ - And STDERR should be empty diff --git a/features/steps/given.php b/features/steps/given.php index f2eae113f5..6af042c6e1 100644 --- a/features/steps/given.php +++ b/features/steps/given.php @@ -158,9 +158,9 @@ function ( $world, $stream, $output_filter, $key ) { } ); -$steps->Given( '/^a new Phar with (?:the same version|version "([^"]+)")$/', - function ( $world, $version = 'same' ) { - $world->build_phar( $version ); +$steps->Given( '/^a new Phar with (?:the same version|version "([^"]+)")(?: and (cli) build)?$/', + function ( $world, $version = 'same', $build = '' ) { + $world->build_phar( $version, $build ); } ); diff --git a/utils/make-phar.php b/utils/make-phar.php index 26b961b457..2820716ddc 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -24,7 +24,7 @@ list( $args, $assoc_args, $runtime_config ) = $configurator->parse_args( array_slice( $GLOBALS['argv'], 1 ) ); if ( ! isset( $args[0] ) || empty( $args[0] ) ) { - echo "usage: php -dphar.readonly=0 $argv[0] [--quiet] [--version=same|patch|minor|major|x.y.z] [--store-version]\n"; + echo "usage: php -dphar.readonly=0 $argv[0] [--quiet] [--version=same|patch|minor|major|x.y.z] [--store-version] [--build=cli]\n"; exit(1); } @@ -60,11 +60,11 @@ function add_file( $phar, $path ) { if ( null === $strip_res ) { if ( 'cli' === BUILD ) { $strips = array( - '\/(?:behat|composer|gherkin)\/src', + '\/(?:behat|composer|gherkin)\/src\/', '\/phpunit\/', - '\/nb\/oxymel', + '\/nb\/oxymel\/', '-command\/src\/', - '\/wp-cli\/[^\n]+-command\/', + '\/wp-cli\/[^\n]+?-command\/', '\/symfony\/(?!finder|polyfill-mbstring)[^\/]+\/', '\/(?:dealerdirect|squizlabs|wimg)\/', ); @@ -149,6 +149,7 @@ function set_file_contents( $phar, $path, $content ) { ->in(WP_CLI_VENDOR_DIR . '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/symfony/filesystem') ->in(WP_CLI_VENDOR_DIR . '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/symfony/process') ->in(WP_CLI_VENDOR_DIR . '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/justinrainbow/json-schema') + ->exclude('demo') ->exclude('nb/oxymel/OxymelTest.php') ->exclude('composer/spdx-licenses') ->exclude('composer/composer/src/Composer/Command') From 8d148c3f1c8dabdade7fac84ec1db1639eabd9ff Mon Sep 17 00:00:00 2001 From: gitlost Date: Sun, 3 Dec 2017 07:25:24 +0000 Subject: [PATCH 136/214] Remove unneeded extra download table in skip-themes. --- features/skip-themes.feature | 4 ---- 1 file changed, 4 deletions(-) diff --git a/features/skip-themes.feature b/features/skip-themes.feature index 645e7854e1..def4d4095a 100644 --- a/features/skip-themes.feature +++ b/features/skip-themes.feature @@ -109,10 +109,6 @@ Feature: Skipping themes Scenario: Skipping multiple themes via config file Given a WP install - And download: - | path | url | - | {CACHE_DIR}/classic.1.6.zip | https://downloads.wordpress.org/theme/classic.1.6.zip | - | {CACHE_DIR}/espied.1.2.2.zip | https://downloads.wordpress.org/theme/espied.1.2.2.zip | And a wp-cli.yml file: """ skip-themes: From 475cb77c3c8782bf4583e65c056da15e5a2051e8 Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 8 Dec 2017 17:53:41 +0000 Subject: [PATCH 137/214] Cast status_code to int; given install re. --- features/bootstrap/FeatureContext.php | 2 +- features/steps/given.php | 14 +++++++------- php/commands/src/CLI_Command.php | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 4a559435e6..54c700b46b 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -386,7 +386,7 @@ private function _replace_wp_versions( $str ) { $wp_versions = array(); $response = Requests::get( 'https://api.wordpress.org/core/version-check/1.7/', null, array( 'timeout' => 30 ) ); - if ( 200 === $response->status_code && ( $body = json_decode( $response->body ) ) && is_object( $body ) && isset( $body->offers ) && is_array( $body->offers ) ) { + if ( 200 === (int) $response->status_code && ( $body = json_decode( $response->body ) ) && is_object( $body ) && isset( $body->offers ) && is_array( $body->offers ) ) { // Latest version alias. $wp_versions["{WP_VERSION-latest}"] = count( $body->offers ) ? $body->offers[0]->version : ''; foreach ( $body->offers as $offer ) { diff --git a/features/steps/given.php b/features/steps/given.php index 41c029f3c9..c0b00707fb 100644 --- a/features/steps/given.php +++ b/features/steps/given.php @@ -75,31 +75,31 @@ function ( $world ) { } ); -$steps->Given( '/^a WP (install|installation)$/', +$steps->Given( '/^a WP install(?:ation)?$/', function ( $world ) { $world->install_wp(); } ); -$steps->Given( "/^a WP (install|installation) in '([^\s]+)'$/", - function ( $world, $_, $subdir ) { +$steps->Given( "/^a WP install(?:ation)? in '([^\s]+)'$/", + function ( $world, $subdir ) { $world->install_wp( $subdir ); } ); -$steps->Given( '/^a WP (install|installation) with Composer$/', +$steps->Given( '/^a WP install(?:ation)? with Composer$/', function ( $world ) { $world->install_wp_with_composer(); } ); -$steps->Given( "/^a WP (install|installation) with Composer and a custom vendor directory '([^\s]+)'$/", - function ( $world, $_, $vendor_directory ) { +$steps->Given( "/^a WP install(?:ation)? with Composer and a custom vendor directory '([^\s]+)'$/", + function ( $world, $vendor_directory ) { $world->install_wp_with_composer( $vendor_directory ); } ); -$steps->Given( '/^a WP multisite (subdirectory|subdomain)?\s?(install|installation)$/', +$steps->Given( '/^a WP multisite (subdirectory|subdomain)?\s?install(?:ation)?$/', function ( $world, $type = 'subdirectory' ) { $world->install_wp(); $subdomains = ! empty( $type ) && 'subdomain' === $type ? 1 : 0; diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index b9293e65f8..8e89770a1c 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -388,7 +388,7 @@ private function get_updates( $assoc_args ) { do { $response = Utils\http_request( 'GET', $url, null, $headers, $options ); - if ( ! $response->success || 200 != $response->status_code ) { // Non-strict check to allow for non-int status code in old WP versions when using stream not curl. + if ( ! $response->success || 200 !== (int) $response->status_code ) { $msg = sprintf( 'Failed to get latest version (HTTP code %d) (%susing GITHUB_TOKEN).', $response->status_code, $github_token ? '' : 'NOT ' ); if ( 403 === $response->status_code && $cache_data ) { WP_CLI::warning( $msg . ' - using stale cache data.' ); @@ -469,7 +469,7 @@ function ( $v ) { if ( empty( $updates ) && preg_match( '#-alpha-(.+)$#', WP_CLI_VERSION, $matches ) ) { $version_url = 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/NIGHTLY_VERSION'; $response = Utils\http_request( 'GET', $version_url ); - if ( ! $response->success || 200 != $response->status_code ) { // Non-strict check to allow for non-int status code in old WP versions when using stream not curl. + if ( ! $response->success || 200 !== (int) $response->status_code ) { WP_CLI::error( sprintf( 'Failed to get current nightly version (HTTP code %d)', $response->status_code ) ); } $nightly_version = trim( $response->body ); From 24f1909c7bc84104bf4ff193ee8767d1cf7c3f23 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 13 Dec 2017 17:57:22 +0000 Subject: [PATCH 138/214] Remove left over merge >>>. --- features/command.feature | 1 - 1 file changed, 1 deletion(-) diff --git a/features/command.feature b/features/command.feature index ab1bca3436..d91c01aedc 100644 --- a/features/command.feature +++ b/features/command.feature @@ -1544,4 +1544,3 @@ Feature: WP-CLI Commands """ core custom-subcommand """ ->>>>>>> upstream/master From fdc6eb949110723567a365d1dca9a5dc889f41bd Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 13 Dec 2017 18:24:14 +0000 Subject: [PATCH 139/214] First go at appveyor.yml, cogged from paulgibbs/behat-wordpress-extension. --- appveyor.yml | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000000..8798593c25 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,49 @@ +build: off +clone_folder: c:\projects\wp-cli +platform: x86 +shallow_clone: true +skip_tags: true +version: '{build}' + +services: + - mysql + +branches: + except: + - gh-pages + +cache: + - '%LOCALAPPDATA%\Composer\files' + - c:\ProgramData\chocolatey\bin -> appveyor.yml + - c:\ProgramData\chocolatey\lib -> appveyor.yml + - c:\projects\wp-cli-tools -> appveyor.yml + +init: + - set PATH=c:\projects\wp-cli-tools;C:\Program Files\Java\jdk1.8.0\bin;C:\Program Files\MySQL\MySQL Server 5.7\bin;%PATH% + - setx COMPOSER_NO_INTERACTION 1 + - git config --global core.autocrlf input + - ps: Update-AppveyorBuild -Version "$($env:APPVEYOR_REPO_BRANCH) - $($env:APPVEYOR_REPO_COMMIT)" + +# BEFORE services are launched. +install: + # Install PHP via WebPI. + - cInst webpicommandline -y + - WebPICMD /Install /Products:"PHP70" /AcceptEULA + + # Install Composer + - ps: mkdir c:\projects\wp-cli-tools -Force + - cd c:\projects\wp-cli-tools + - ps: Invoke-WebRequest https://getcomposer.org/composer.phar -Outfile composer.phar + - ps: Add-Content composer.bat "@php c:\projects\wp-cli-tools\composer.phar %*" + - RefreshEnv + + # Install wp-cli dependencies. + - cd "%APPVEYOR_BUILD_FOLDER%" + - composer install --no-interaction --prefer-source + +# AFTER services have been launched. +test_script: + # Run phpunit. + - vendor\bin\phpunit + +on_finish: From 4c137177fd20ee1fcd0897dca51d5baf2ae8064b Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 13 Dec 2017 18:45:47 +0000 Subject: [PATCH 140/214] Fix DocParse::get_longdesc(). --- php/WP_CLI/DocParser.php | 2 +- tests/test-doc-parser.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/php/WP_CLI/DocParser.php b/php/WP_CLI/DocParser.php index 4c09f646dd..033d6f3847 100644 --- a/php/WP_CLI/DocParser.php +++ b/php/WP_CLI/DocParser.php @@ -64,7 +64,7 @@ public function get_longdesc() { $longdesc = substr( $this->docComment, strlen( $shortdesc ) ); - $longdesc = preg_replace( '/^@.*\z/ms', '', $longdesc ); + $longdesc = trim( preg_replace( '/^@.*\z/ms', '', $longdesc ) ); return $longdesc; } diff --git a/tests/test-doc-parser.php b/tests/test-doc-parser.php index 7fdf261c06..a751189f35 100644 --- a/tests/test-doc-parser.php +++ b/tests/test-doc-parser.php @@ -40,6 +40,7 @@ function test_no_longdesc() { ); $this->assertEquals( 'Rock and roll!', $doc->get_shortdesc() ); + error_log( __FUNCTION__ . " longdesc=" . $doc->get_longdesc() . "" ); $this->assertEquals( '', $doc->get_longdesc() ); $this->assertEquals( '', $doc->get_synopsis() ); $this->assertEquals( 'rock-on', $doc->get_tag('alias') ); From 5fc00579db5252851e9b36cb31c3198d5926875a Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 13 Dec 2017 19:29:07 +0000 Subject: [PATCH 141/214] Appveyor.yml only github-api branch. --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 8798593c25..2ea4c59678 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,8 +9,8 @@ services: - mysql branches: - except: - - gh-pages + only: + - github-api cache: - '%LOCALAPPDATA%\Composer\files' From b867826676b1c06698cfd95673bf9c987f83a62e Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 14 Dec 2017 05:00:51 +0000 Subject: [PATCH 142/214] Add a git path. --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 2ea4c59678..89cdf2c99b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,7 +19,7 @@ cache: - c:\projects\wp-cli-tools -> appveyor.yml init: - - set PATH=c:\projects\wp-cli-tools;C:\Program Files\Java\jdk1.8.0\bin;C:\Program Files\MySQL\MySQL Server 5.7\bin;%PATH% + - set PATH=c:\projects\wp-cli-tools;C:\Program Files\Git\bin;C:\Program Files\Java\jdk1.8.0\bin;C:\Program Files\MySQL\MySQL Server 5.7\bin;%PATH% - setx COMPOSER_NO_INTERACTION 1 - git config --global core.autocrlf input - ps: Update-AppveyorBuild -Version "$($env:APPVEYOR_REPO_BRANCH) - $($env:APPVEYOR_REPO_COMMIT)" From 5358e48eba73988c7f88b40efaa0d449415cd321 Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 14 Dec 2017 05:50:08 +0000 Subject: [PATCH 143/214] Try x64. --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 89cdf2c99b..e08ea364b7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,6 @@ build: off clone_folder: c:\projects\wp-cli -platform: x86 +platform: x64 shallow_clone: true skip_tags: true version: '{build}' @@ -33,7 +33,7 @@ install: # Install Composer - ps: mkdir c:\projects\wp-cli-tools -Force - cd c:\projects\wp-cli-tools - - ps: Invoke-WebRequest https://getcomposer.org/composer.phar -Outfile composer.phar + - ps: Invoke-WebRequest https://getcomposer.org/composer.phar -Outfile composer.phar - ps: Add-Content composer.bat "@php c:\projects\wp-cli-tools\composer.phar %*" - RefreshEnv From 8d6004add88932dc59a0197d51a492dfaad954c3 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 16 Dec 2017 06:35:27 +0000 Subject: [PATCH 144/214] Try using mysql. --- appveyor.yml | 8 ++++++++ utils/make-phar.php | 14 ++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index e08ea364b7..ff12d36bf7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -18,6 +18,9 @@ cache: - c:\ProgramData\chocolatey\lib -> appveyor.yml - c:\projects\wp-cli-tools -> appveyor.yml +environment: + - MYSQL_PWD: Password12! + init: - set PATH=c:\projects\wp-cli-tools;C:\Program Files\Git\bin;C:\Program Files\Java\jdk1.8.0\bin;C:\Program Files\MySQL\MySQL Server 5.7\bin;%PATH% - setx COMPOSER_NO_INTERACTION 1 @@ -42,6 +45,11 @@ install: - composer install --no-interaction --prefer-source # AFTER services have been launched. +before_test: + - mysql -e 'CREATE DATABASE wp_cli_test;' -uroot + - mysql -e 'GRANT ALL PRIVILEGES ON wp_cli_test.* TO "wp_cli_test"@"localhost" IDENTIFIED BY "password1"' -uroot + - mysql -e 'GRANT ALL PRIVILEGES ON wp_cli_test_scaffold.* TO "wp_cli_test"@"localhost" IDENTIFIED BY "password1"' -uroot + test_script: # Run phpunit. - vendor\bin\phpunit diff --git a/utils/make-phar.php b/utils/make-phar.php index 948b03fb80..80509d5cbd 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -25,7 +25,7 @@ list( $args, $assoc_args, $runtime_config ) = $configurator->parse_args( array_slice( $GLOBALS['argv'], 1 ) ); if ( ! isset( $args[0] ) || empty( $args[0] ) ) { - echo "usage: php -dphar.readonly=0 $argv[0] [--quiet] [--version=same|patch|minor|major|x.y.z] [--store-version] [--build=cli]\n"; + echo "usage: php -dphar.readonly=0 $argv[0] [--quiet] [--version=same|patch|minor|major|x.y.z] [--store-version] [--build=cli]" . PHP_EOL; exit(1); } @@ -51,8 +51,9 @@ function add_file( $phar, $path ) { $key = str_replace( WP_CLI_BASE_PATH, '', $path ); - if ( !BE_QUIET ) - echo "$key - $path\n"; + if ( ! BE_QUIET ) { + echo "$key - $path" . PHP_EOL; + } // Warning: needs to be synced with ScaffoldPackageCommand::package_tests() `$copy_source[ $wp_cli_root ]`. static $scaffold_package_phps = array( @@ -112,8 +113,9 @@ function add_file( $phar, $path ) { function set_file_contents( $phar, $path, $content ) { $key = str_replace( WP_CLI_BASE_PATH, '', $path ); - if ( !BE_QUIET ) - echo "$key - $path\n"; + if ( ! BE_QUIET ) { + echo "$key - $path" . PHP_EOL; + } $phar[ $key ] = $content; } @@ -275,5 +277,5 @@ function set_file_contents( $phar, $path, $content ) { chmod( DEST_PATH, 0755 ); // Make executable. if ( ! BE_QUIET ) { - echo "Generated " . DEST_PATH . "\n"; + echo "Generated " . DEST_PATH . PHP_EOL; } From 9130a1f8bf68e08a92592f9f7b3e378ee13653f5 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 16 Dec 2017 06:37:03 +0000 Subject: [PATCH 145/214] Fix environment setting. --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index ff12d36bf7..fd6cca756f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,7 +19,7 @@ cache: - c:\projects\wp-cli-tools -> appveyor.yml environment: - - MYSQL_PWD: Password12! + MYSQL_PWD: Password12! init: - set PATH=c:\projects\wp-cli-tools;C:\Program Files\Git\bin;C:\Program Files\Java\jdk1.8.0\bin;C:\Program Files\MySQL\MySQL Server 5.7\bin;%PATH% From dd82addaae2bb8aa3650f8180f06cb899840dc54 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 16 Dec 2017 06:44:30 +0000 Subject: [PATCH 146/214] Try --user=root mysql. --- appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index fd6cca756f..60ed679763 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -46,9 +46,9 @@ install: # AFTER services have been launched. before_test: - - mysql -e 'CREATE DATABASE wp_cli_test;' -uroot - - mysql -e 'GRANT ALL PRIVILEGES ON wp_cli_test.* TO "wp_cli_test"@"localhost" IDENTIFIED BY "password1"' -uroot - - mysql -e 'GRANT ALL PRIVILEGES ON wp_cli_test_scaffold.* TO "wp_cli_test"@"localhost" IDENTIFIED BY "password1"' -uroot + - mysql -e 'CREATE DATABASE wp_cli_test;' --user=root + - mysql -e 'GRANT ALL PRIVILEGES ON wp_cli_test.* TO "wp_cli_test"@"localhost" IDENTIFIED BY "password1"' --user=root + - mysql -e 'GRANT ALL PRIVILEGES ON wp_cli_test_scaffold.* TO "wp_cli_test"@"localhost" IDENTIFIED BY "password1"' --user=root test_script: # Run phpunit. From 3f3756d378bc15b852cf84af470ab0839898a0c8 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 16 Dec 2017 06:54:44 +0000 Subject: [PATCH 147/214] Use double quotes for mysql. --- appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 60ed679763..9045532933 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -46,9 +46,9 @@ install: # AFTER services have been launched. before_test: - - mysql -e 'CREATE DATABASE wp_cli_test;' --user=root - - mysql -e 'GRANT ALL PRIVILEGES ON wp_cli_test.* TO "wp_cli_test"@"localhost" IDENTIFIED BY "password1"' --user=root - - mysql -e 'GRANT ALL PRIVILEGES ON wp_cli_test_scaffold.* TO "wp_cli_test"@"localhost" IDENTIFIED BY "password1"' --user=root + - mysql -e "CREATE DATABASE wp_cli_test charset 'utf8';" --user=root + - mysql -e "GRANT ALL PRIVILEGES ON wp_cli_test.* TO wp_cli_test@localhost IDENTIFIED BY 'password1'" --user=root + - mysql -e "GRANT ALL PRIVILEGES ON wp_cli_test_scaffold.* TO wp_cli_test@localhost IDENTIFIED BY 'password1'" --user=root test_script: # Run phpunit. From cc82048a0e44af003e698e248d7a49ba764ecb1c Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 16 Dec 2017 07:12:59 +0000 Subject: [PATCH 148/214] Try running validation.feature test. --- appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 9045532933..4f4acde4f0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -53,5 +53,7 @@ before_test: test_script: # Run phpunit. - vendor\bin\phpunit + # Run functional tests. + - vendor\bin\behat features/validation.feature on_finish: From 3c312954ad4ab4849b214241570ce24357368871 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 16 Dec 2017 08:40:33 +0000 Subject: [PATCH 149/214] Try using iss services. --- appveyor.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 4f4acde4f0..7aae502698 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,6 +7,7 @@ version: '{build}' services: - mysql + - iis branches: only: @@ -40,6 +41,10 @@ install: - ps: Add-Content composer.bat "@php c:\projects\wp-cli-tools\composer.phar %*" - RefreshEnv + # Make sure Windows' IIS services are running. + - ps: Start-Service W3SVC + - ps: Start-Service WAS + # Install wp-cli dependencies. - cd "%APPVEYOR_BUILD_FOLDER%" - composer install --no-interaction --prefer-source From 0b68f0f162e62be7a619c627d78397e2b7053c4e Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 16 Dec 2017 09:04:16 +0000 Subject: [PATCH 150/214] Try x86. --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 7aae502698..fb95451919 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,6 @@ build: off clone_folder: c:\projects\wp-cli -platform: x64 +platform: x86 shallow_clone: true skip_tags: true version: '{build}' From f3a63cfcffd91a853f53746826a94daf5b6c8281 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 16 Dec 2017 13:09:26 +0000 Subject: [PATCH 151/214] Add cygwin path. --- appveyor.yml | 9 ++------- bin/wp | 7 ++++++- php/utils.php | 5 ++++- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index fb95451919..0feddc1501 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,13 +1,12 @@ build: off clone_folder: c:\projects\wp-cli -platform: x86 +platform: x64 shallow_clone: true skip_tags: true version: '{build}' services: - mysql - - iis branches: only: @@ -23,7 +22,7 @@ environment: MYSQL_PWD: Password12! init: - - set PATH=c:\projects\wp-cli-tools;C:\Program Files\Git\bin;C:\Program Files\Java\jdk1.8.0\bin;C:\Program Files\MySQL\MySQL Server 5.7\bin;%PATH% + - set PATH=c:\projects\wp-cli-tools;C:\Program Files\Git\bin;C:\cygwin64\bin;C:\Program Files\Java\jdk1.8.0\bin;C:\Program Files\MySQL\MySQL Server 5.7\bin;%PATH% - setx COMPOSER_NO_INTERACTION 1 - git config --global core.autocrlf input - ps: Update-AppveyorBuild -Version "$($env:APPVEYOR_REPO_BRANCH) - $($env:APPVEYOR_REPO_COMMIT)" @@ -41,10 +40,6 @@ install: - ps: Add-Content composer.bat "@php c:\projects\wp-cli-tools\composer.phar %*" - RefreshEnv - # Make sure Windows' IIS services are running. - - ps: Start-Service W3SVC - - ps: Start-Service WAS - # Install wp-cli dependencies. - cd "%APPVEYOR_BUILD_FOLDER%" - composer install --no-interaction --prefer-source diff --git a/bin/wp b/bin/wp index 053e24227b..5493622ec3 100755 --- a/bin/wp +++ b/bin/wp @@ -40,6 +40,11 @@ esac # Pass in the path to php so that wp-cli knows which one # to use if it re-launches itself to run other commands. -export WP_CLI_PHP_USED="$php" +WP_CLI_PHP_USED="$php" +case $("$php" -r "echo PHP_OS;") in + WINNT*) + WP_CLI_PHP_USED="$(cygpath -w -a -- "$WP_CLI_PHP_USED")" ;; +esac +export WP_CLI_PHP_USED exec "$php" $WP_CLI_PHP_ARGS "$SCRIPT_PATH" "$@" diff --git a/php/utils.php b/php/utils.php index 63a6a1c4b7..e4c6ea0332 100644 --- a/php/utils.php +++ b/php/utils.php @@ -1348,12 +1348,15 @@ function get_php_binary() { * @param array $env Array of environment variables. * @param array $other_options Array of additional options (Windows only). * - * @return string Command stripped of any environment variable settings. + * @return resource|false Returns resource representing the process on success; false on failure. */ function proc_open_compat( $cmd, $descriptorspec, &$pipes, $cwd = null, $env = null, $other_options = null ) { if ( is_windows() ) { // Need to encompass the whole command in double quotes - PHP bug https://bugs.php.net/bug.php?id=49139 $cmd = '"' . _proc_open_compat_win_env( $cmd, $env ) . '"'; + if ( null === $other_options ) { + $other_options = array(); + } } return proc_open( $cmd, $descriptorspec, $pipes, $cwd, $env, $other_options ); } From 60aa163a00063c27346024c3c2d5443009c9b449 Mon Sep 17 00:00:00 2001 From: John Blackbourn Date: Sat, 16 Dec 2017 14:25:00 +0100 Subject: [PATCH 152/214] Add some more suggestions for mis-typed arguments. --- php/utils.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/php/utils.php b/php/utils.php index 8793bbf921..a5c41294f9 100644 --- a/php/utils.php +++ b/php/utils.php @@ -1100,7 +1100,9 @@ function glob_brace( $pattern, $dummy_flags = null ) { function get_suggestion( $target, array $options, $threshold = 2 ) { $suggestion_map = array( + 'add' => 'create', 'check' => 'check-update', + 'capability' => 'cap', 'clear' => 'flush', 'decrement' => 'decr', 'del' => 'delete', @@ -1116,6 +1118,7 @@ function get_suggestion( $target, array $options, $threshold = 2 ) { 'regen' => 'regenerate', 'rep' => 'replace', 'repl' => 'replace', + 'trash' => 'delete', 'v' => 'version', ); From 4fb3fbf34878f9b965ca6dc55efa2b54d24258ed Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 16 Dec 2017 13:40:49 +0000 Subject: [PATCH 153/214] Default PATH in proc_open. --- php/utils.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/php/utils.php b/php/utils.php index e4c6ea0332..29ef967cd2 100644 --- a/php/utils.php +++ b/php/utils.php @@ -1358,6 +1358,10 @@ function proc_open_compat( $cmd, $descriptorspec, &$pipes, $cwd = null, $env = n $other_options = array(); } } + if ( null === $env ) { + $env = array(); + $env['PATH'] = getenv( 'PATH' ); + } return proc_open( $cmd, $descriptorspec, $pipes, $cwd, $env, $other_options ); } From f5dbfcf92f9f91f99b27700e6df6a4fe95f27b82 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 16 Dec 2017 13:56:47 +0000 Subject: [PATCH 154/214] Default env to null in Process::create. --- php/WP_CLI/Process.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/WP_CLI/Process.php b/php/WP_CLI/Process.php index 118f47116e..315aa869ad 100644 --- a/php/WP_CLI/Process.php +++ b/php/WP_CLI/Process.php @@ -49,7 +49,7 @@ class Process { * * @return Process */ - public static function create( $command, $cwd = null, $env = array() ) { + public static function create( $command, $cwd = null, $env = null ) { $proc = new self; $proc->command = $command; From d7f99ea83e7738f8f6fbf2dbb936ba5629823a5a Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 16 Dec 2017 14:03:57 +0000 Subject: [PATCH 155/214] tar --force-local in Extractor. --- php/WP_CLI/Extractor.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/php/WP_CLI/Extractor.php b/php/WP_CLI/Extractor.php index b63f9088b0..fbb65d83dc 100644 --- a/php/WP_CLI/Extractor.php +++ b/php/WP_CLI/Extractor.php @@ -109,7 +109,8 @@ private static function extract_tarball( $tarball, $dest ) { if ( ! file_exists( $dest ) ) { mkdir( $dest, 0777, true ); } - $cmd = Utils\esc_cmd( 'tar xz --strip-components=1 --directory=%2$s -f %1$s', $tarball, $dest ); + // Need --force-local for Windows to avoid "C:" being interpreted as referring to remote machine. + $cmd = Utils\esc_cmd( 'tar xz --force-local --strip-components=1 --directory=%2$s -f %1$s', $tarball, $dest ); $process_run = WP_CLI::launch( $cmd, false /*exit_on_error*/, true /*return_detailed*/ ); if ( 0 !== $process_run->return_code ) { throw new \Exception( sprintf( 'Failed to execute `%s`: %s.', $cmd, self::tar_error_msg( $process_run ) ) ); From 59ab01a1be7ea325378cb45b4b288a49568414d7 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 16 Dec 2017 18:15:54 +0000 Subject: [PATCH 156/214] Normalize directory separator in get_temp_dir(). --- features/bootstrap/FeatureContext.php | 3 +-- php/utils.php | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 33a7dc2fd7..167a894064 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -123,9 +123,8 @@ private static function get_process_env_variables() { // Ensure we're using the expected `wp` binary $bin_dir = getenv( 'WP_CLI_BIN_DIR' ) ?: realpath( __DIR__ . '/../../bin' ); $vendor_dir = realpath( __DIR__ . '/../../vendor/bin' ); - $path_separator = Utils\is_windows() ? ';' : ':'; $env = array( - 'PATH' => $bin_dir . $path_separator . $vendor_dir . $path_separator . getenv( 'PATH' ), + 'PATH' => $bin_dir . PATH_SEPARATOR . $vendor_dir . PATH_SEPARATOR . getenv( 'PATH' ), 'BEHAT_RUN' => 1, 'HOME' => sys_get_temp_dir() . '/wp-cli-home', ); diff --git a/php/utils.php b/php/utils.php index 29ef967cd2..1d0004a4f0 100644 --- a/php/utils.php +++ b/php/utils.php @@ -790,6 +790,9 @@ function get_temp_dir() { // `sys_get_temp_dir()` introduced PHP 5.2.1. Will always return something. $temp = trailingslashit( sys_get_temp_dir() ); + // Normalize to *nix directory separators. + $temp = str_replace( '\\', '/', $temp ); + if ( ! is_writable( $temp ) ) { \WP_CLI::warning( "Temp directory isn't writable: {$temp}" ); } From a500a442df5d601e23aef45d2d9f0f006d39907b Mon Sep 17 00:00:00 2001 From: gitlost Date: Sat, 16 Dec 2017 18:44:33 +0000 Subject: [PATCH 157/214] Adjust get_temp_dir() test. --- tests/test-utils.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/test-utils.php b/tests/test-utils.php index 548294e761..c85521754f 100644 --- a/tests/test-utils.php +++ b/tests/test-utils.php @@ -339,19 +339,20 @@ public function testTrailingslashit() { public function testGetTempDir() { $this->assertTrue( '/' === substr( Utils\get_temp_dir(), -1 ) ); + $this->assertTrue( false === strpos( Utils\get_temp_dir(), '\\' ) ); // INI directive `sys_temp_dir` introduced PHP 5.5.0. if ( version_compare( PHP_VERSION, '5.5.0', '>=' ) ) { // `sys_temp_dir` set to unwritable. - $cmd = 'php ' . escapeshellarg( '-dsys_temp_dir=\\tmp\\' ) . ' php/boot-fs.php --skip-wordpress eval ' . escapeshellarg( 'echo WP_CLI\\Utils\\get_temp_dir();' ) . ' 2>&1'; + $cmd = 'php ' . escapeshellarg( '-dsys_temp_dir=:\\tmp\\' ) . ' php/boot-fs.php --skip-wordpress eval ' . escapeshellarg( 'echo WP_CLI\\Utils\\get_temp_dir();' ) . ' 2>&1'; $output = array(); exec( $cmd, $output ); $output = trim( implode( "\n", $output ) ); $this->assertTrue( false !== strpos( $output, 'Warning' ) ); $this->assertTrue( false !== strpos( $output, 'writable' ) ); - $this->assertTrue( false !== strpos( $output, '\\tmp/' ) ); + $this->assertTrue( false !== strpos( $output, '/tmp/' ) ); // `sys_temp_dir` unset. From 4b7dc2e35e299acdda146ae0278c71ef32912a61 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sun, 17 Dec 2017 04:25:01 +0000 Subject: [PATCH 158/214] Set SYSTEMROOT and TMP env vars. --- features/bootstrap/FeatureContext.php | 25 +++++-------------------- tests/test-utils.php | 1 + 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 167a894064..a43f27fe9c 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -128,26 +128,11 @@ private static function get_process_env_variables() { 'BEHAT_RUN' => 1, 'HOME' => sys_get_temp_dir() . '/wp-cli-home', ); - if ( $config_path = getenv( 'WP_CLI_CONFIG_PATH' ) ) { - $env['WP_CLI_CONFIG_PATH'] = $config_path; - } - if ( $term = getenv( 'TERM' ) ) { - $env['TERM'] = $term; - } - if ( $php_args = getenv( 'WP_CLI_PHP_ARGS' ) ) { - $env['WP_CLI_PHP_ARGS'] = $php_args; - } - if ( $php_used = getenv( 'WP_CLI_PHP_USED' ) ) { - $env['WP_CLI_PHP_USED'] = $php_used; - } - if ( $php = getenv( 'WP_CLI_PHP' ) ) { - $env['WP_CLI_PHP'] = $php; - } - if ( $travis_build_dir = getenv( 'TRAVIS_BUILD_DIR' ) ) { - $env['TRAVIS_BUILD_DIR'] = $travis_build_dir; - } - if ( $github_token = getenv( 'GITHUB_TOKEN' ) ) { - $env['GITHUB_TOKEN'] = $github_token; + $env_keys = array( 'GITHUB_TOKEN', 'SYSTEMROOT', 'TERM', 'TMP', 'TRAVIS_BUILD_DIR', 'WP_CLI_CONFIG_PATH', 'WP_CLI_PHP', 'WP_CLI_PHP_ARGS', 'WP_CLI_PHP_USED' ); + foreach ( $env_keys as $env_key ) { + if ( $env_val = getenv( $env_key ) ) { + $env[ $env_key ] = $env_val; + } } return $env; } diff --git a/tests/test-utils.php b/tests/test-utils.php index c85521754f..ce687dee26 100644 --- a/tests/test-utils.php +++ b/tests/test-utils.php @@ -361,6 +361,7 @@ public function testGetTempDir() { exec( $cmd, $output ); $output = trim( implode( "\n", $output ) ); $this->assertTrue( '/' === substr( $output, -1 ) ); + $this->assertTrue( false === strpos( $output, '\\' ) ); } } From 11c60382697398650902e5dad5433cfefd514be0 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sun, 17 Dec 2017 04:35:57 +0000 Subject: [PATCH 159/214] Remove setting env PATH in proc_open_compat. --- php/utils.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/php/utils.php b/php/utils.php index 1d0004a4f0..4b8ced5784 100644 --- a/php/utils.php +++ b/php/utils.php @@ -1357,13 +1357,6 @@ function proc_open_compat( $cmd, $descriptorspec, &$pipes, $cwd = null, $env = n if ( is_windows() ) { // Need to encompass the whole command in double quotes - PHP bug https://bugs.php.net/bug.php?id=49139 $cmd = '"' . _proc_open_compat_win_env( $cmd, $env ) . '"'; - if ( null === $other_options ) { - $other_options = array(); - } - } - if ( null === $env ) { - $env = array(); - $env['PATH'] = getenv( 'PATH' ); } return proc_open( $cmd, $descriptorspec, $pipes, $cwd, $env, $other_options ); } From 4bb286b757c8c021d9491872be415729e8634a84 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sun, 17 Dec 2017 10:44:54 +0000 Subject: [PATCH 160/214] Set certain env vars for Win proc_open; normalize dir separators; strip crs; convert cmd escs. --- bin/wp.bat | 2 +- features/aliases.feature | 13 +++++-------- features/bootstrap/FeatureContext.php | 23 +++++++++++----------- features/bootstrap/support.php | 26 ++++++++++++++++++++++++- features/steps/when.php | 6 ++++++ php/WP_CLI/Configurator.php | 4 +++- php/utils.php | 28 +++++++++++++++++++++++---- 7 files changed, 75 insertions(+), 27 deletions(-) diff --git a/bin/wp.bat b/bin/wp.bat index 59f953440b..bc21d8113d 100755 --- a/bin/wp.bat +++ b/bin/wp.bat @@ -1,2 +1,2 @@ @ECHO OFF -php "%~dp0../php/boot-fs.php" %* \ No newline at end of file +php %WP_CLI_PHP_ARGS% "%~dp0../php/boot-fs.php" %* diff --git a/features/aliases.feature b/features/aliases.feature index f2a34c4e03..abd8942127 100644 --- a/features/aliases.feature +++ b/features/aliases.feature @@ -18,7 +18,7 @@ Feature: Create shortcuts to specific WordPress installs When I run `wp @foo core is-installed` Then the return code should be 0 - When I run `cd bar; wp @foo core is-installed` + When I run `cd bar && wp @foo core is-installed` Then the return code should be 0 Scenario: Error when invalid alias provided @@ -122,15 +122,12 @@ Feature: Create shortcuts to specific WordPress installs path: foo """ - When I run `wp eval --skip-wordpress 'echo realpath( getenv( "RUN_DIR" ) );'` - Then save STDOUT as {TEST_DIR} - When I run `wp cli alias` Then STDOUT should be YAML containing: """ @all: Run command against every registered alias. @foo: - path: {TEST_DIR}/foo + path: {RUN_DIR}/foo """ When I run `wp cli aliases` @@ -138,13 +135,13 @@ Feature: Create shortcuts to specific WordPress installs """ @all: Run command against every registered alias. @foo: - path: {TEST_DIR}/foo + path: {RUN_DIR}/foo """ When I run `wp cli alias --format=json` Then STDOUT should be JSON containing: """ - {"@all":"Run command against every registered alias.","@foo":{"path":"{TEST_DIR}/foo"}} + {"@all":"Run command against every registered alias.","@foo":{"path":"{RUN_DIR}/foo"}} """ Scenario: Defining a project alias completely overrides a global alias @@ -354,7 +351,7 @@ Feature: Create shortcuts to specific WordPress installs @foo core is-installed --allow-root --debug """ - When I try `cd bar; wp @bar core is-installed --allow-root --debug` + When I try `cd bar && wp @bar core is-installed --allow-root --debug` Then the return code should be 0 And STDERR should contain: """ diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index a43f27fe9c..4b0b00334a 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -21,8 +21,8 @@ foreach( $composer->autoload->files as $file ) { $contents .= ' - ' . dirname( dirname( dirname( __FILE__ ) ) ) . '/' . $file . PHP_EOL; } - @mkdir( sys_get_temp_dir() . '/wp-cli-package-test/' ); - $project_config = sys_get_temp_dir() . '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/wp-cli-package-test/config.yml'; + @mkdir( Utils\get_temp_dir() . 'wp-cli-package-test/' ); + $project_config = Utils\get_temp_dir() . 'wp-cli-package-test/config.yml'; file_put_contents( $project_config, $contents ); putenv( 'WP_CLI_CONFIG_PATH=' . $project_config ); } @@ -126,7 +126,7 @@ private static function get_process_env_variables() { $env = array( 'PATH' => $bin_dir . PATH_SEPARATOR . $vendor_dir . PATH_SEPARATOR . getenv( 'PATH' ), 'BEHAT_RUN' => 1, - 'HOME' => sys_get_temp_dir() . '/wp-cli-home', + 'HOME' => Utils\get_temp_dir() . 'wp-cli-home', ); $env_keys = array( 'GITHUB_TOKEN', 'SYSTEMROOT', 'TERM', 'TMP', 'TRAVIS_BUILD_DIR', 'WP_CLI_CONFIG_PATH', 'WP_CLI_PHP', 'WP_CLI_PHP_ARGS', 'WP_CLI_PHP_USED' ); foreach ( $env_keys as $env_key ) { @@ -143,7 +143,7 @@ private static function get_process_env_variables() { */ private static function cache_wp_files() { $wp_version_suffix = ( $wp_version = getenv( 'WP_VERSION' ) ) ? "-$wp_version" : ''; - self::$cache_dir = sys_get_temp_dir() . '/wp-cli-test-core-download-cache' . $wp_version_suffix; + self::$cache_dir = Utils\get_temp_dir() . 'wp-cli-test-core-download-cache' . $wp_version_suffix; if ( is_readable( self::$cache_dir . '/wp-config-sample.php' ) ) return; @@ -175,7 +175,7 @@ public static function prepare( SuiteEvent $event ) { // Remove install cache if any (not setting the static var). $wp_version_suffix = ( $wp_version = getenv( 'WP_VERSION' ) ) ? "-$wp_version" : ''; - $install_cache_dir = sys_get_temp_dir() . '/wp-cli-test-core-install-cache' . $wp_version_suffix; + $install_cache_dir = Utils\get_temp_dir() . 'wp-cli-test-core-install-cache' . $wp_version_suffix; if ( file_exists( $install_cache_dir ) ) { self::remove_dir( $install_cache_dir ); } @@ -298,7 +298,7 @@ public static function create_cache_dir() { if ( self::$suite_cache_dir ) { self::remove_dir( self::$suite_cache_dir ); } - self::$suite_cache_dir = sys_get_temp_dir() . '/' . uniqid( 'wp-cli-test-suite-cache-' . self::$temp_dir_infix . '-', TRUE ); + self::$suite_cache_dir = Utils\get_temp_dir() . uniqid( 'wp-cli-test-suite-cache-' . self::$temp_dir_infix . '-', TRUE ); mkdir( self::$suite_cache_dir ); return self::$suite_cache_dir; } @@ -446,7 +446,7 @@ private static function get_event_file( $event, &$line ) { */ public function create_run_dir() { if ( !isset( $this->variables['RUN_DIR'] ) ) { - self::$run_dir = $this->variables['RUN_DIR'] = sys_get_temp_dir() . '/' . uniqid( 'wp-cli-test-run-' . self::$temp_dir_infix . '-', TRUE ); + self::$run_dir = $this->variables['RUN_DIR'] = Utils\get_temp_dir() . uniqid( 'wp-cli-test-run-' . self::$temp_dir_infix . '-', TRUE ); mkdir( $this->variables['RUN_DIR'] ); } } @@ -509,7 +509,7 @@ public function download_phar( $version = 'same' ) { * CACHE_DIR is a cache for downloaded test data such as images. Lives until manually deleted. */ private function set_cache_dir() { - $path = sys_get_temp_dir() . '/wp-cli-test-cache'; + $path = Utils\get_temp_dir() . 'wp-cli-test-cache'; if ( ! file_exists( $path ) ) { mkdir( $path ); } @@ -674,7 +674,7 @@ public function create_config( $subdir = '', $extra_php = false ) { public function install_wp( $subdir = '' ) { $wp_version_suffix = ( $wp_version = getenv( 'WP_VERSION' ) ) ? "-$wp_version" : ''; - self::$install_cache_dir = sys_get_temp_dir() . '/wp-cli-test-core-install-cache' . $wp_version_suffix; + self::$install_cache_dir = Utils\get_temp_dir() . 'wp-cli-test-core-install-cache' . $wp_version_suffix; if ( ! file_exists( self::$install_cache_dir ) ) { mkdir( self::$install_cache_dir ); } @@ -747,11 +747,10 @@ public function install_wp_with_composer( $vendor_directory = 'vendor' ) { public function composer_add_wp_cli_local_repository() { if ( ! self::$composer_local_repository ) { - self::$composer_local_repository = sys_get_temp_dir() . '/' . uniqid( "wp-cli-composer-local-", TRUE ); + self::$composer_local_repository = Utils\get_temp_dir() . uniqid( "wp-cli-composer-local-", TRUE ); mkdir( self::$composer_local_repository ); - $env = self::get_process_env_variables(); - $src = isset( $env['TRAVIS_BUILD_DIR'] ) ? $env['TRAVIS_BUILD_DIR'] : realpath( __DIR__ . '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/../../' ); + $src = getenv( 'TRAVIS_BUILD_DIR' ) ?: realpath( __DIR__ . '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/../../' ); self::copy_dir( $src, self::$composer_local_repository . '/' ); self::remove_dir( self::$composer_local_repository . '/.git' ); diff --git a/features/bootstrap/support.php b/features/bootstrap/support.php index 6aa17c6c39..6ad8fff47e 100644 --- a/features/bootstrap/support.php +++ b/features/bootstrap/support.php @@ -36,7 +36,7 @@ function checkString( $output, $expected, $action, $message = false ) { switch ( $action ) { case 'be': - $r = $expected === rtrim( $output, "\n" ); + $r = $expected === rtrim( _wp_cli_nocr( $output ), "\n" ); break; case 'contain': @@ -198,3 +198,27 @@ function checkThatYamlStringContainsYamlString( $actualYaml, $expectedYaml ) { return compareContents( $expectedValue, $actualValue ); } +/** + * Helper to strip carriage returns from input for Windows compat. + * + * @param string|array String or array of strings to strip. + * @return string|array String or array stripped of carriage returns. + */ +function _wp_cli_nocr( $str_or_arr ) { + if ( is_string( $str_or_arr ) ) { + return str_replace( "\r", '', $str_or_arr ); + } + return array_map( function ( $str ) { + return str_replace( "\r", '', $str ); + }, $str_or_arr ); +} + +/** + * Helper to convert *nix shell escaped command to Windows. Primitive. + * + * @param string $cmd Command to convert. + * @return string Command escaped for Windows - ie. single quotes converted to double quotes and vice versa. + */ +function _wp_cli_esc_cmd_win( $cmd ) { + return str_replace( array( "'", '"', '' ), array( '', "'", '"' ), $cmd ); +} diff --git a/features/steps/when.php b/features/steps/when.php index 7e9aba10ed..911c163425 100644 --- a/features/steps/when.php +++ b/features/steps/when.php @@ -30,6 +30,9 @@ function ( $world, $cmd ) { $steps->When( '/^I (run|try|mistakenly try|successfully try) `([^`]+)`$/', function ( $world, $mode, $cmd, $return_code = 0, $stdout_empty = '' ) { $cmd = $world->replace_variables( $cmd ); + if ( Utils\is_windows() ) { + $cmd = _wp_cli_esc_cmd_win( $cmd ); + } $world->result = invoke_proc( $world->proc( $cmd ), $mode ); list( $world->result->stdout, $world->email_sends ) = capture_email_sends( $world->result->stdout ); } @@ -38,6 +41,9 @@ function ( $world, $mode, $cmd, $return_code = 0, $stdout_empty = '' ) { $steps->When( "/^I (run|try) `([^`]+)` from '([^\s]+)'$/", function ( $world, $mode, $cmd, $subdir ) { $cmd = $world->replace_variables( $cmd ); + if ( Utils\is_windows() ) { + $cmd = _wp_cli_esc_cmd_win( $cmd ); + } $world->result = invoke_proc( $world->proc( $cmd, array(), $subdir ), $mode ); list( $world->result->stdout, $world->email_sends ) = capture_email_sends( $world->result->stdout ); } diff --git a/php/WP_CLI/Configurator.php b/php/WP_CLI/Configurator.php index d099eddec8..3b5d96f4ea 100644 --- a/php/WP_CLI/Configurator.php +++ b/php/WP_CLI/Configurator.php @@ -3,6 +3,7 @@ namespace WP_CLI; use Mustangostang\Spyc; +use WP_CLI\Utils; /** * Handles file- and runtime-based configuration values. @@ -349,8 +350,9 @@ private static function arrayify( &$val ) { */ private static function absolutize( &$path, $base ) { if ( ! empty( $path ) && ! \WP_CLI\Utils\is_path_absolute( $path ) ) { - $path = $base . DIRECTORY_SEPARATOR . $path; + $path = $base . '/' . $path; } + $path = Utils\normalize_directory_separators( $path ); } } diff --git a/php/utils.php b/php/utils.php index 4b8ced5784..5a6adbc45e 100644 --- a/php/utils.php +++ b/php/utils.php @@ -772,6 +772,20 @@ function trailingslashit( $string ) { return rtrim( $string, '/\\' ) . '/'; } +/** + * Normalizes directory separators to slashes. + * + * @access public + * @category System + * + * @param string $path Path to convert. + * + * @return string Path with all backslashes replaced by slashes. + */ +function normalize_directory_separators( $path ) { + return str_replace( '\\', '/', $path ); +} + /** * Get the system's temp directory. Warns user if it isn't writable. * @@ -788,10 +802,7 @@ function get_temp_dir() { } // `sys_get_temp_dir()` introduced PHP 5.2.1. Will always return something. - $temp = trailingslashit( sys_get_temp_dir() ); - - // Normalize to *nix directory separators. - $temp = str_replace( '\\', '/', $temp ); + $temp = trailingslashit( normalize_directory_separators( sys_get_temp_dir() ) ); if ( ! is_writable( $temp ) ) { \WP_CLI::warning( "Temp directory isn't writable: {$temp}" ); @@ -1357,6 +1368,15 @@ function proc_open_compat( $cmd, $descriptorspec, &$pipes, $cwd = null, $env = n if ( is_windows() ) { // Need to encompass the whole command in double quotes - PHP bug https://bugs.php.net/bug.php?id=49139 $cmd = '"' . _proc_open_compat_win_env( $cmd, $env ) . '"'; + // If environment array set, make sure certain entries are set otherwise can cause Windows `getaddrinfo()` and `mysqli_connect()` to crap out. + if ( null !== $env ) { + $env_names = array( 'HOME', 'PATH', 'SYSTEMROOT', 'TERM', 'TMP' ); // Probably only SYSTEMROOT and TMP are needed, but the others can't hurt. + foreach ( $env_names as $env_name ) { + if ( ! isset( $env[ $env_name ] ) && ( $env_val = getenv( $env_name ) ) ) { + $env[ $env_name ] = $env_val; + } + } + } } return proc_open( $cmd, $descriptorspec, $pipes, $cwd, $env, $other_options ); } From 11bf90af7abe46e11f83588b59c690e5d07d3217 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 3 Jan 2018 10:41:21 +0000 Subject: [PATCH 161/214] Normalize newlines between help parts. --- php/commands/help.php | 5 ++++- templates/man.mustache | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/php/commands/help.php b/php/commands/help.php index 1cdbef178d..43dae00aab 100644 --- a/php/commands/help.php +++ b/php/commands/help.php @@ -44,7 +44,10 @@ private static function show_help( $command ) { $out = substr_replace( $out, $subcommands_header, $matches[1][1], strlen( $subcommands ) ); } - $out .= self::parse_reference_links( $command->get_longdesc() ); + if ( $longdesc = self::parse_reference_links( $command->get_longdesc() ) ) { + // Normalize newlines between parts. + $out = rtrim( $out, "\n" ) . "\n\n" . ltrim( $longdesc, "\n" ); + } // definition lists $out = preg_replace_callback( '/([^\n]+)\n: (.+?)(\n\n|$)/s', array( __CLASS__, 'rewrap_param_desc' ), $out ); diff --git a/templates/man.mustache b/templates/man.mustache index fbb2e9bd6b..b04c5ffb6f 100644 --- a/templates/man.mustache +++ b/templates/man.mustache @@ -24,5 +24,4 @@ {{#subcommands}} {{.}} {{/subcommands}} - {{/has-subcommands}} From ec8385e66f541b9554c08dd0e18cdc658d454d1d Mon Sep 17 00:00:00 2001 From: Thrijith Thankachan Date: Mon, 15 Jan 2018 01:05:45 +0530 Subject: [PATCH 162/214] update 'info' change output format to table --- php/commands/src/CLI_Command.php | 39 ++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index fa2474fd78..2f864095f8 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -130,18 +130,33 @@ public function info( $_, $assoc_args ) { WP_CLI::line( json_encode( $info ) ); } else { - WP_CLI::line( "OS:\t" . $system_os ); - WP_CLI::line( "Shell:\t" . $shell ); - WP_CLI::line( "PHP binary:\t" . $php_bin ); - WP_CLI::line( "PHP version:\t" . PHP_VERSION ); - WP_CLI::line( "php.ini used:\t" . get_cfg_var( 'cfg_file_path' ) ); - WP_CLI::line( "WP-CLI root dir:\t" . WP_CLI_ROOT ); - WP_CLI::line( "WP-CLI vendor dir:\t" . WP_CLI_VENDOR_DIR ); - WP_CLI::line( "WP_CLI phar path:\t" . ( defined( 'WP_CLI_PHAR_PATH' ) ? WP_CLI_PHAR_PATH : '' ) ); - WP_CLI::line( "WP-CLI packages dir:\t" . $packages_dir ); - WP_CLI::line( "WP-CLI global config:\t" . $runner->global_config_path ); - WP_CLI::line( "WP-CLI project config:\t" . $runner->project_config_path ); - WP_CLI::line( "WP-CLI version:\t" . WP_CLI_VERSION ); + $info = array( + 'OS' => $system_os, + 'Shell' => $shell, + 'PHP binary' => $php_bin, + 'PHP version' => PHP_VERSION, + 'php.ini used' => get_cfg_var( 'cfg_file_path' ), + 'WP-CLI root dir' => WP_CLI_ROOT, + 'WP-CLI vendor dir' => WP_CLI_VENDOR_DIR, + 'WP_CLI phar path' => ( defined( 'WP_CLI_PHAR_PATH' ) ? WP_CLI_PHAR_PATH : '' ), + 'WP-CLI packages dir' => $packages_dir, + 'WP-CLI global config' => $runner->global_config_path, + 'WP-CLI project config' => $runner->project_config_path, + 'WP-CLI version' => WP_CLI_VERSION, + ); + $items = array(); + foreach ( $info as $key => $value ) { + $info_format = array( + 'key' => '', + 'value' => '', + ); + $info_format['key'] = $key; + $info_format['value'] = $value; + $items[] = $info_format; + + } + + WP_CLI\Utils\format_items( 'table', $items, array( 'key', 'value' ) ); } } From f80bc4c244f0d10c4641eb9a097dbacdfff8ee59 Mon Sep 17 00:00:00 2001 From: Thrijith Thankachan Date: Mon, 15 Jan 2018 01:18:45 +0530 Subject: [PATCH 163/214] update 'info' fix tests --- features/cli-info.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/cli-info.feature b/features/cli-info.feature index 09918b2df4..7b24530af8 100644 --- a/features/cli-info.feature +++ b/features/cli-info.feature @@ -26,7 +26,7 @@ Feature: Review CLI information When I run `wp cli info` Then STDOUT should contain: """ - WP-CLI packages dir: + WP-CLI packages dir """ Scenario: Packages directory path should be slashed correctly From 202627948a013ca49c1c62767be97c64c2d4beaa Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 15 Jan 2018 22:12:27 +0000 Subject: [PATCH 164/214] Use wp_cache_flush in Utils\wp_clear_object_cache & check props before setting. --- features/utils-wp.feature | 22 ++++++++++++++++++++++ php/utils-wp.php | 22 ++++++++++++++++------ 2 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 features/utils-wp.feature diff --git a/features/utils-wp.feature b/features/utils-wp.feature new file mode 100644 index 0000000000..a24c9bf352 --- /dev/null +++ b/features/utils-wp.feature @@ -0,0 +1,22 @@ +Feature: Utilities that depend on WordPress code + + Scenario: Clear WP cache + Given a WP install + And a test.php file: + """ + cache ) . ',' . isset( $wp_object_cache->group_ops ) . ',' . isset( $wp_object_cache->stats ) . ',' . isset( $wp_object_cache->memcache_debug ) . "\n"; + WP_CLI\Utils\wp_clear_object_cache(); + echo empty( $wp_object_cache->cache ) . ',' . isset( $wp_object_cache->group_ops ) . ',' . isset( $wp_object_cache->stats ) . ',' . isset( $wp_object_cache->memcache_debug ) . "\n"; + } ); + """ + + When I run `wp post create --post_title="Foo Bar" --porcelain` + And I run `wp --require=test.php eval ''` + Then STDOUT should be: + """ + ,,, + 1,,, + """ diff --git a/php/utils-wp.php b/php/utils-wp.php index b7ec062e9a..cbaa71792d 100644 --- a/php/utils-wp.php +++ b/php/utils-wp.php @@ -287,13 +287,23 @@ function wp_clear_object_cache() { return; } - $wp_object_cache->group_ops = array(); - $wp_object_cache->stats = array(); - $wp_object_cache->memcache_debug = array(); - $wp_object_cache->cache = array(); + wp_cache_flush(); - if ( is_callable( $wp_object_cache, '__remoteset' ) ) { - $wp_object_cache->__remoteset(); // important + // The following are Memcached (Redux) plugin specific (see https://core.trac.wordpress.org/ticket/31463). + if ( isset( $wp_object_cache->group_ops ) ) { + $wp_object_cache->group_ops = array(); + } + if ( isset( $wp_object_cache->stats ) ) { + $wp_object_cache->stats = array(); + } + if ( isset( $wp_object_cache->memcache_debug ) ) { + $wp_object_cache->memcache_debug = array(); + } + if ( ! empty( $wp_object_cache->cache ) ) { // This is cleared by `WP_Object_Cache::flush()` but keep for BC with Memcached. + $wp_object_cache->cache = array(); + } + if ( method_exists( $wp_object_cache, '__remoteset' ) ) { // Apparently specific to wp.com version of Memcached plugin. + $wp_object_cache->__remoteset(); } } From 65e4bbf4a52b67430524e32f57947114b07a40c6 Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 16 Jan 2018 14:27:42 +0000 Subject: [PATCH 165/214] Remove call to wp_cache_flush(). --- php/utils-wp.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/php/utils-wp.php b/php/utils-wp.php index cbaa71792d..b1cf30c880 100644 --- a/php/utils-wp.php +++ b/php/utils-wp.php @@ -287,8 +287,6 @@ function wp_clear_object_cache() { return; } - wp_cache_flush(); - // The following are Memcached (Redux) plugin specific (see https://core.trac.wordpress.org/ticket/31463). if ( isset( $wp_object_cache->group_ops ) ) { $wp_object_cache->group_ops = array(); @@ -299,7 +297,7 @@ function wp_clear_object_cache() { if ( isset( $wp_object_cache->memcache_debug ) ) { $wp_object_cache->memcache_debug = array(); } - if ( ! empty( $wp_object_cache->cache ) ) { // This is cleared by `WP_Object_Cache::flush()` but keep for BC with Memcached. + if ( isset( $wp_object_cache->cache ) ) { $wp_object_cache->cache = array(); } if ( method_exists( $wp_object_cache, '__remoteset' ) ) { // Apparently specific to wp.com version of Memcached plugin. From 69c9c9f4f1dd53624a32f5aabc6d07fa4e11c16d Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 16 Jan 2018 14:42:04 +0000 Subject: [PATCH 166/214] Remove call to _remoteset which previously was no-op anyway. --- php/utils-wp.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/php/utils-wp.php b/php/utils-wp.php index b1cf30c880..6c699e2132 100644 --- a/php/utils-wp.php +++ b/php/utils-wp.php @@ -277,6 +277,7 @@ function wp_get_cache_type() { * * @access public * @category System + * @deprecated 1.5.0 */ function wp_clear_object_cache() { global $wpdb, $wp_object_cache; @@ -297,12 +298,10 @@ function wp_clear_object_cache() { if ( isset( $wp_object_cache->memcache_debug ) ) { $wp_object_cache->memcache_debug = array(); } + // Used by `WP_Object_Cache` also. if ( isset( $wp_object_cache->cache ) ) { $wp_object_cache->cache = array(); } - if ( method_exists( $wp_object_cache, '__remoteset' ) ) { // Apparently specific to wp.com version of Memcached plugin. - $wp_object_cache->__remoteset(); - } } /** From 35d3309a69133f73fcbc082942e84c8f1fe0d332 Mon Sep 17 00:00:00 2001 From: Tiago Hillebrandt Date: Fri, 19 Jan 2018 07:14:41 -0200 Subject: [PATCH 167/214] Script to create the Git pre-commit hook. --- composer.json | 5 +++++ utils/git-setup-pre-commit-hook | 34 +++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100755 utils/git-setup-pre-commit-hook diff --git a/composer.json b/composer.json index 366c303083..f987d62b7c 100644 --- a/composer.json +++ b/composer.json @@ -79,6 +79,11 @@ "psr-0": { "WP_CLI": "php" }, "psr-4": { "": "php/commands/src" } }, + "scripts": { + "post-install-cmd": [ + "./utils/git-setup-pre-commit-hook" + ] + }, "extra": { "autoload-splitter": { "splitter-logic": "WP_CLI\\AutoloadSplitter", diff --git a/utils/git-setup-pre-commit-hook b/utils/git-setup-pre-commit-hook new file mode 100755 index 0000000000..e931c12e04 --- /dev/null +++ b/utils/git-setup-pre-commit-hook @@ -0,0 +1,34 @@ +#!/bin/bash +# +# Setup Git pre-commit hook. +# + +# stop when composer.json file is not found +if [[ ! -f "composer.json" ]]; then + echo "unable to locate composer.json file." + exit 1 +fi + +# determine the phpcs binary location +curr_dir=$(pwd) + +if [[ -f "vendor/bin/phpcs" ]]; then + phpcs_bin="./vendor/bin/phpcs" +elif [[ -n $COMPOSER_BIN_DIR && -f "$COMPOSER_BIN_DIR/phpcs" ]]; then + phpcs_bin="./$COMPOSER_BIN_DIR/phpcs" +elif [[ -n $COMPOSER_VENDOR_DIR && -f "$COMPOSER_VENDOR_DIR/bin/phpcs" ]]; then + phpcs_bin="./$COMPOSER_VENDOR_DIR/bin/phpcs" +else + echo "pre-commit hook: unable to locate phpcs binary file." + exit +fi + +# create the pre-commit file or notify to add command if it already exists +pre_commit_file="$(git rev-parse --git-dir)/hooks/pre-commit" + +if [[ ! -f "$pre_commit_file" ]]; then + echo -e "#!/bin/bash\nset -ex\n$phpcs_bin" > $pre_commit_file + chmod +x $pre_commit_file +elif ! grep -q "phpcs" $pre_commit_file; then + echo -e "hook already exists: $pre_commit_file\n\nplease add the below command to your pre-commit file:\n\n$phpcs_bin" +fi From 0c290266c01e352a53287a3a84fd2b5ce807aa41 Mon Sep 17 00:00:00 2001 From: Tiago Hillebrandt Date: Fri, 19 Jan 2018 07:19:06 -0200 Subject: [PATCH 168/214] Removes unused var --- utils/git-setup-pre-commit-hook | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/utils/git-setup-pre-commit-hook b/utils/git-setup-pre-commit-hook index e931c12e04..70c1dfedc8 100755 --- a/utils/git-setup-pre-commit-hook +++ b/utils/git-setup-pre-commit-hook @@ -10,8 +10,6 @@ if [[ ! -f "composer.json" ]]; then fi # determine the phpcs binary location -curr_dir=$(pwd) - if [[ -f "vendor/bin/phpcs" ]]; then phpcs_bin="./vendor/bin/phpcs" elif [[ -n $COMPOSER_BIN_DIR && -f "$COMPOSER_BIN_DIR/phpcs" ]]; then @@ -30,5 +28,5 @@ if [[ ! -f "$pre_commit_file" ]]; then echo -e "#!/bin/bash\nset -ex\n$phpcs_bin" > $pre_commit_file chmod +x $pre_commit_file elif ! grep -q "phpcs" $pre_commit_file; then - echo -e "hook already exists: $pre_commit_file\n\nplease add the below command to your pre-commit file:\n\n$phpcs_bin" + echo -e "hook file already exists: $pre_commit_file\n\nplease add the below command to your pre-commit file:\n\n$phpcs_bin" fi From 5565c00e7c3d2694fc903fc9e205b6b9a59b8838 Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 19 Jan 2018 12:36:58 +0000 Subject: [PATCH 169/214] Rewrite wp_get_table_names to deal correctly with wildcards. --- features/utils-wp.feature | 683 ++++++++++++++++++++++++++++++++++++++ php/utils-wp.php | 140 +++----- php/utils.php | 18 + 3 files changed, 741 insertions(+), 100 deletions(-) create mode 100644 features/utils-wp.feature diff --git a/features/utils-wp.feature b/features/utils-wp.feature new file mode 100644 index 0000000000..0854bdaa2f --- /dev/null +++ b/features/utils-wp.feature @@ -0,0 +1,683 @@ +Feature: Utilities that depend on WordPress code + + Scenario: Get WP table names for single site install + Given a WP install + And I run `wp db query "CREATE TABLE xx_wp_posts ( id int );"` + And I run `wp db query "CREATE TABLE wp_xx_posts ( id int );"` + And I run `wp db query "CREATE TABLE wp_posts_xx ( id int );"` + And I run `wp db query "CREATE TABLE wp_categories ( id int );"` + And a table_names.php file: + """ + ...] + * : List tables based on wildcard search, e.g. 'wp_*_options' or 'wp_post?'. + * + * [--scope=] + * : Can be all, global, ms_global, blog, or old tables. Defaults to all. + * + * [--network] + * : List all the tables in a multisite install. Overrides --scope=. + * + * [--all-tables-with-prefix] + * : List all tables that match the table prefix even if not registered on $wpdb. Overrides --network. + * + * [--all-tables] + * : List all tables in the database, regardless of the prefix, and even if not registered on $wpdb. Overrides --all-tables-with-prefix. + */ + function test_wp_get_table_names( $args, $assoc_args ) { + if ( $tables = WP_CLI\Utils\wp_get_table_names( $args, $assoc_args ) ) { + echo implode( PHP_EOL, $tables ) . PHP_EOL; + } + } + WP_CLI::add_command( 'get_table_names', 'test_wp_get_table_names' ); + """ + + When I run `wp --require=table_names.php get_table_names` + Then STDOUT should be: + """ + wp_commentmeta + wp_comments + wp_links + wp_options + wp_postmeta + wp_posts + wp_term_relationships + wp_term_taxonomy + wp_termmeta + wp_terms + wp_usermeta + wp_users + """ + And save STDOUT as {DEFAULT_STDOUT} + + When I run `wp --require=table_names.php get_table_names --scope=all` + Then STDOUT should be: + """ + {DEFAULT_STDOUT} + """ + + When I run `wp --require=table_names.php get_table_names --scope=blog` + Then STDOUT should be: + """ + wp_commentmeta + wp_comments + wp_links + wp_options + wp_postmeta + wp_posts + wp_term_relationships + wp_term_taxonomy + wp_termmeta + wp_terms + """ + + When I run `wp --require=table_names.php get_table_names --scope=global` + Then STDOUT should be: + """ + wp_usermeta + wp_users + """ + + When I run `wp --require=table_names.php get_table_names --scope=ms_global` + Then STDOUT should be empty + + When I run `wp --require=table_names.php get_table_names --scope=old` + Then STDOUT should be: + """ + wp_categories + """ + + When I run `wp --require=table_names.php get_table_names --network` + Then STDOUT should be: + """ + {DEFAULT_STDOUT} + """ + + When I run `wp --require=table_names.php get_table_names --all-tables-with-prefix` + Then STDOUT should be: + """ + wp_categories + wp_commentmeta + wp_comments + wp_links + wp_options + wp_postmeta + wp_posts + wp_posts_xx + wp_term_relationships + wp_term_taxonomy + wp_termmeta + wp_terms + wp_usermeta + wp_users + wp_xx_posts + """ + + When I run `wp --require=table_names.php get_table_names --all-tables` + Then STDOUT should be: + """ + wp_categories + wp_commentmeta + wp_comments + wp_links + wp_options + wp_postmeta + wp_posts + wp_posts_xx + wp_term_relationships + wp_term_taxonomy + wp_termmeta + wp_terms + wp_usermeta + wp_users + wp_xx_posts + xx_wp_posts + """ + + When I run `wp --require=table_names.php get_table_names '*_posts'` + Then STDOUT should be: + """ + wp_posts + """ + + When I run `wp --require=table_names.php get_table_names 'wp_post*'` + Then STDOUT should be: + """ + wp_postmeta + wp_posts + """ + + When I run `wp --require=table_names.php get_table_names 'wp*osts'` + Then STDOUT should be: + """ + wp_posts + """ + + When I run `wp --require=table_names.php get_table_names '*_posts' --scope=blog` + Then STDOUT should be: + """ + wp_posts + """ + + When I try `wp --require=table_names.php get_table_names '*_posts' --scope=global` + Then STDERR should be: + """ + Error: Couldn't find any tables matching: *_posts + """ + And STDOUT should be empty + + When I run `wp --require=table_names.php get_table_names '*_posts' --network` + Then STDOUT should be: + """ + wp_posts + """ + + When I run `wp --require=table_names.php get_table_names '*_posts' --all-tables-with-prefix` + Then STDOUT should be: + """ + wp_posts + wp_xx_posts + """ + + When I run `wp --require=table_names.php get_table_names '*wp_posts' --all-tables-with-prefix` + Then STDOUT should be: + """ + wp_posts + """ + + When I run `wp --require=table_names.php get_table_names 'wp_post*' --all-tables-with-prefix` + Then STDOUT should be: + """ + wp_postmeta + wp_posts + wp_posts_xx + """ + + When I run `wp --require=table_names.php get_table_names 'wp*osts' --all-tables-with-prefix` + Then STDOUT should be: + """ + wp_posts + wp_xx_posts + """ + + When I run `wp --require=table_names.php get_table_names '*_posts' --all-tables` + Then STDOUT should be: + """ + wp_posts + wp_xx_posts + xx_wp_posts + """ + + When I run `wp --require=table_names.php get_table_names '*wp_posts' --all-tables` + Then STDOUT should be: + """ + wp_posts + xx_wp_posts + """ + + When I run `wp --require=table_names.php get_table_names 'wp_post*' --all-tables` + Then STDOUT should be: + """ + wp_postmeta + wp_posts + wp_posts_xx + """ + + When I run `wp --require=table_names.php get_table_names 'wp*osts' --all-tables` + Then STDOUT should be: + """ + wp_posts + wp_xx_posts + """ + + When I try `wp --require=table_names.php get_table_names non_existent_table` + Then STDERR should be: + """ + Error: Couldn't find any tables matching: non_existent_table + """ + And STDOUT should be empty + + When I run `wp --require=table_names.php get_table_names wp_posts non_existent_table` + Then STDOUT should be: + """ + wp_posts + """ + + When I run `wp --require=table_names.php get_table_names wp_posts non_existent_table 'wp_?ption*'` + Then STDOUT should be: + """ + wp_options + wp_posts + """ + + Scenario: Get WP table names for single site install + Given a WP multisite install + And I run `wp db query "CREATE TABLE xx_wp_posts ( id int );"` + And I run `wp db query "CREATE TABLE xx_wp_2_posts ( id int );"` + And I run `wp db query "CREATE TABLE wp_xx_posts ( id int );"` + And I run `wp db query "CREATE TABLE wp_2_xx_posts ( id int );"` + And I run `wp db query "CREATE TABLE wp_posts_xx ( id int );"` + And I run `wp db query "CREATE TABLE wp_2_posts_xx ( id int );"` + And I run `wp db query "CREATE TABLE wp_categories ( id int );"` + And I run `wp db query "CREATE TABLE wp_sitecategories ( id int );"` + And a table_names.php file: + """ + ...] + * : List tables based on wildcard search, e.g. 'wp_*_options' or 'wp_post?'. + * + * [--scope=] + * : Can be all, global, ms_global, blog, or old tables. Defaults to all. + * + * [--network] + * : List all the tables in a multisite install. Overrides --scope=. + * + * [--all-tables-with-prefix] + * : List all tables that match the table prefix even if not registered on $wpdb. Overrides --network. + * + * [--all-tables] + * : List all tables in the database, regardless of the prefix, and even if not registered on $wpdb. Overrides --all-tables-with-prefix. + */ + function test_wp_get_table_names( $args, $assoc_args ) { + if ( $tables = WP_CLI\Utils\wp_get_table_names( $args, $assoc_args ) ) { + echo implode( PHP_EOL, $tables ) . PHP_EOL; + } + } + WP_CLI::add_command( 'get_table_names', 'test_wp_get_table_names' ); + """ + + # With no subsite. + When I run `wp --require=table_names.php get_table_names` + Then STDOUT should be: + """ + wp_blog_versions + wp_blogs + wp_commentmeta + wp_comments + wp_links + wp_options + wp_postmeta + wp_posts + wp_registration_log + wp_signups + wp_site + wp_sitemeta + wp_term_relationships + wp_term_taxonomy + wp_termmeta + wp_terms + wp_usermeta + wp_users + """ + And save STDOUT as {DEFAULT_STDOUT} + + When I run `wp --require=table_names.php get_table_names --scope=all` + Then STDOUT should be: + """ + {DEFAULT_STDOUT} + """ + + When I run `wp --require=table_names.php get_table_names --scope=blog` + Then STDOUT should be: + """ + wp_commentmeta + wp_comments + wp_links + wp_options + wp_postmeta + wp_posts + wp_term_relationships + wp_term_taxonomy + wp_termmeta + wp_terms + """ + + When I run `wp --require=table_names.php get_table_names --scope=global` + Then STDOUT should be: + """ + wp_blog_versions + wp_blogs + wp_registration_log + wp_signups + wp_site + wp_sitemeta + wp_usermeta + wp_users + """ + And save STDOUT as {GLOBAL_STDOUT} + + When I run `wp --require=table_names.php get_table_names --scope=ms_global` + Then STDOUT should be: + """ + wp_blog_versions + wp_blogs + wp_registration_log + wp_signups + wp_site + wp_sitemeta + """ + + When I run `wp --require=table_names.php get_table_names --scope=old` + Then STDOUT should be: + """ + wp_categories + """ + + When I run `wp --require=table_names.php get_table_names --network` + Then STDOUT should be: + """ + {DEFAULT_STDOUT} + """ + + # With subsite. + Given I run `wp site create --slug=foo` + When I run `wp --require=table_names.php get_table_names` + Then STDOUT should be: + """ + {DEFAULT_STDOUT} + """ + + When I run `wp --require=table_names.php get_table_names --url=example.com/foo --scope=blog` + Then STDOUT should be: + """ + wp_2_commentmeta + wp_2_comments + wp_2_links + wp_2_options + wp_2_postmeta + wp_2_posts + wp_2_term_relationships + wp_2_term_taxonomy + wp_2_termmeta + wp_2_terms + """ + And save STDOUT as {SUBSITE_BLOG_STDOUT} + + When I run `wp --require=table_names.php get_table_names --url=example.com/foo` + Then STDOUT should be: + """ + {SUBSITE_BLOG_STDOUT} + {GLOBAL_STDOUT} + """ + + When I run `wp --require=table_names.php get_table_names --network` + Then STDOUT should be: + """ + {SUBSITE_BLOG_STDOUT} + {DEFAULT_STDOUT} + """ + And save STDOUT as {NETWORK_STDOUT} + + When I run `wp --require=table_names.php get_table_names --network --url=example.com/foo` + Then STDOUT should be: + """ + {NETWORK_STDOUT} + """ + + When I run `wp --require=table_names.php get_table_names --all-tables-with-prefix` + Then STDOUT should be: + """ + wp_2_commentmeta + wp_2_comments + wp_2_links + wp_2_options + wp_2_postmeta + wp_2_posts + wp_2_posts_xx + wp_2_term_relationships + wp_2_term_taxonomy + wp_2_termmeta + wp_2_terms + wp_2_xx_posts + wp_blog_versions + wp_blogs + wp_categories + wp_commentmeta + wp_comments + wp_links + wp_options + wp_postmeta + wp_posts + wp_posts_xx + wp_registration_log + wp_signups + wp_site + wp_sitecategories + wp_sitemeta + wp_term_relationships + wp_term_taxonomy + wp_termmeta + wp_terms + wp_usermeta + wp_users + wp_xx_posts + """ + And save STDOUT as {ALL_TABLES_WITH_PREFIX_STDOUT} + + # Network overriden by all-tables-with-prefix. + When I run `wp --require=table_names.php get_table_names --all-tables-with-prefix --network` + Then STDOUT should contain: + """ + {ALL_TABLES_WITH_PREFIX_STDOUT} + """ + + When I run `wp --require=table_names.php get_table_names --all-tables` + Then STDOUT should be: + """ + {ALL_TABLES_WITH_PREFIX_STDOUT} + xx_wp_2_posts + xx_wp_posts + """ + And save STDOUT as {ALL_TABLES_STDOUT} + + # Network overriden by all-tables. + When I run `wp --require=table_names.php get_table_names --all-tables --network` + Then STDOUT should be: + """ + {ALL_TABLES_STDOUT} + """ + + When I run `wp --require=table_names.php get_table_names '*_posts'` + Then STDOUT should be: + """ + wp_posts + """ + + When I run `wp --require=table_names.php get_table_names '*_posts' --network` + Then STDOUT should be: + """ + wp_2_posts + wp_posts + """ + + When I run `wp --require=table_names.php get_table_names 'wp_post*'` + Then STDOUT should be: + """ + wp_postmeta + wp_posts + """ + + When I run `wp --require=table_names.php get_table_names 'wp_post*' --network` + Then STDOUT should be: + """ + wp_postmeta + wp_posts + """ + + When I run `wp --require=table_names.php get_table_names 'wp*osts'` + Then STDOUT should be: + """ + wp_posts + """ + + When I run `wp --require=table_names.php get_table_names 'wp*osts' --network` + Then STDOUT should be: + """ + wp_2_posts + wp_posts + """ + + When I run `wp --require=table_names.php get_table_names '*_posts' --scope=blog` + Then STDOUT should be: + """ + wp_posts + """ + + When I run `wp --require=table_names.php get_table_names '*_posts' --scope=blog --network` + Then STDOUT should be: + """ + wp_2_posts + wp_posts + """ + + When I try `wp --require=table_names.php get_table_names '*_posts' --scope=global` + Then STDERR should be: + """ + Error: Couldn't find any tables matching: *_posts + """ + And STDOUT should be empty + + # Note: BC change 1.5.0, network does not override scope. + When I try `wp --require=table_names.php get_table_names '*_posts' --scope=global --network` + Then STDERR should be: + """ + Error: Couldn't find any tables matching: *_posts + """ + And STDOUT should be empty + + When I run `wp --require=table_names.php get_table_names '*_posts' --all-tables-with-prefix` + Then STDOUT should be: + """ + wp_2_posts + wp_2_xx_posts + wp_posts + wp_xx_posts + """ + + When I run `wp --require=table_names.php get_table_names 'wp_post*' --all-tables-with-prefix` + Then STDOUT should be: + """ + wp_postmeta + wp_posts + wp_posts_xx + """ + + When I run `wp --require=table_names.php get_table_names 'wp*osts' --all-tables-with-prefix` + Then STDOUT should be: + """ + wp_2_posts + wp_2_xx_posts + wp_posts + wp_xx_posts + """ + + When I run `wp --require=table_names.php get_table_names '*_posts' --all-tables` + Then STDOUT should be: + """ + wp_2_posts + wp_2_xx_posts + wp_posts + wp_xx_posts + xx_wp_2_posts + xx_wp_posts + """ + + When I run `wp --require=table_names.php get_table_names '*wp_posts' --all-tables` + Then STDOUT should be: + """ + wp_posts + xx_wp_posts + """ + + When I run `wp --require=table_names.php get_table_names 'wp_post*' --all-tables` + Then STDOUT should be: + """ + wp_postmeta + wp_posts + wp_posts_xx + """ + + When I run `wp --require=table_names.php get_table_names 'wp*osts' --all-tables` + Then STDOUT should be: + """ + wp_2_posts + wp_2_xx_posts + wp_posts + wp_xx_posts + """ + + When I try `wp --require=table_names.php get_table_names non_existent_table` + Then STDERR should be: + """ + Error: Couldn't find any tables matching: non_existent_table + """ + And STDOUT should be empty + + When I run `wp --require=table_names.php get_table_names wp_posts non_existent_table` + Then STDOUT should be: + """ + wp_posts + """ + + When I run `wp --require=table_names.php get_table_names wp_posts non_existent_table 'wp_?ption*'` + Then STDOUT should be: + """ + wp_options + wp_posts + """ + + When I run `wp --require=table_names.php get_table_names wp_posts non_existent_table 'wp_*ption?'` + Then STDOUT should be: + """ + wp_options + wp_posts + """ + + When I run `wp --require=table_names.php get_table_names wp_posts non_existent_table 'wp_*ption?' --network` + Then STDOUT should be: + """ + wp_2_options + wp_options + wp_posts + """ + + Given an enable_sitecategories.php file: + """ + get_col( 'SHOW TABLES' ); - } - $tables = array(); - foreach ( $all_tables as $table ) { - if ( fnmatch( $glob, $table ) ) { - $tables[] = $table; - } - } - return $tables; - }; - foreach ( $args as $key => $table ) { - if ( false !== strpos( $table, '*' ) || false !== strpos( $table, '?' ) ) { - $expanded_tables = $get_tables_for_glob( $table ); - if ( empty( $expanded_tables ) ) { - \WP_CLI::error( "Couldn't find any tables matching: {$table}" ); - } - $new_tables = array_merge( $new_tables, $expanded_tables ); - } else { - $new_tables[] = $table; - } - } - return $new_tables; - } - - // Fall back to flag if no tables were passed - $table_type = 'WordPress'; - if ( get_flag_value( $assoc_args, 'network' ) ) { - $table_type = 'network'; - } - if ( get_flag_value( $assoc_args, 'all-tables-with-prefix' ) ) { - $table_type = 'all-tables-with-prefix'; - } + $tables = array(); if ( get_flag_value( $assoc_args, 'all-tables' ) ) { - $table_type = 'all-tables'; - } + $tables = $wpdb->get_col( 'SHOW TABLES' ); - $network = 'network' == $table_type; - - if ( 'all-tables' == $table_type ) { - return $wpdb->get_col( 'SHOW TABLES' ); - } + } elseif ( get_flag_value( $assoc_args, 'all-tables-with-prefix' ) ) { + $tables = $wpdb->get_col( $wpdb->prepare( 'SHOW TABLES LIKE %s', esc_like( $wpdb->get_blog_prefix() ) . '%' ) ); - $prefix = $network ? $wpdb->base_prefix : $wpdb->prefix; - // '_' is a special wildcard for MySQL LIKE queries - // so it needs to be escaped with '\', but then '\' needs to be escaped as well - $sql_prefix = str_replace( '_', '\\_', $prefix ); - $matching_tables = $wpdb->get_col( $wpdb->prepare( 'SHOW TABLES LIKE %s', $sql_prefix . '%' ) ); - - if ( 'all-tables-with-prefix' == $table_type ) { - return $matching_tables; - } - - $filter_sitecategories = function( $matching_tables ) { - global $wpdb; - // Only include sitecategories when it's actually enabled. - if ( ! global_terms_enabled() ) { - $key = array_search( $wpdb->sitecategories, $matching_tables ); - if ( false !== $key ) { - unset( $matching_tables[ $key ] ); + } else { + $scope = get_flag_value( $assoc_args, 'scope', 'all' ); + + // Note: BC change 1.5.0, taking scope into consideration for network also. + if ( get_flag_value( $assoc_args, 'network' ) && is_multisite() ) { + $network_global_scope = in_array( $scope, array( 'all', 'global', 'ms_global' ), true ) ? ( 'all' === $scope ? 'global' : $scope ) : ''; + $wp_tables = array_values( $wpdb->tables( $network_global_scope ) ); + if ( in_array( $scope, array( 'all', 'blog' ), true ) ) { + // Do directly for compat with old WP versions. Note: private, deleted, archived sites are not excluded. + $blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs WHERE site_id = $wpdb->siteid" ); + foreach ( $blog_ids as $blog_id ) { + $wp_tables = array_merge( $wp_tables, array_values( $wpdb->tables( 'blog', true /*prefix*/, $blog_id ) ) ); + } } + } else { + $wp_tables = array_values( $wpdb->tables( $scope ) ); } - return $matching_tables; - }; - - if ( $scope = get_flag_value( $assoc_args, 'scope' ) ) { - $matching_tables = $wpdb->tables( $scope ); - $matching_tables = $filter_sitecategories( $matching_tables ); - return $matching_tables; - } - $allowed_tables = array(); - $allowed_table_types = array( 'tables', 'global_tables' ); - if ( $network ) { - $allowed_table_types[] = 'ms_global_tables'; - } - foreach ( $allowed_table_types as $table_type ) { - foreach ( $wpdb->$table_type as $table ) { - $allowed_tables[] = $prefix . $table; + if ( ! global_terms_enabled() ) { + // Only include sitecategories when it's actually enabled. + $wp_tables = array_values( array_diff( $wp_tables, array( $wpdb->sitecategories ) ) ); } - } - - // Given our matching tables, also allow site-specific tables on the network - foreach ( $matching_tables as $key => $matched_table ) { - if ( in_array( $matched_table, $allowed_tables ) ) { - continue; - } + // Note: BC change 1.5.0, tables are sorted (via TABLES view). + $tables = $wpdb->get_col( sprintf( "SHOW TABLES WHERE %s IN ('%s')", esc_sql_ident( 'Tables_in_' . $wpdb->dbname ), implode( "', '", $wpdb->_escape( $wp_tables ) ) ) ); + } - if ( $network ) { - $valid_table = false; - foreach ( array_merge( $wpdb->tables, $wpdb->old_tables ) as $maybe_site_table ) { - if ( preg_match( "#{$prefix}([\d]+)_{$maybe_site_table}#", $matched_table ) ) { - $valid_table = true; - } - } - if ( $valid_table ) { - continue; + // Filter by `$args`. + if ( $args ) { + $args_tables = array(); + foreach ( $args as $arg ) { + if ( false !== strpos( $arg, '*' ) || false !== strpos( $arg, '?' ) ) { + $args_tables = array_merge( $args_tables, array_filter( $tables, function ( $v ) use ( $arg ) { + return fnmatch( $arg, $v ); + } ) ); + } else { + $args_tables[] = $arg; } } - - unset( $matching_tables[ $key ] ); - + $args_tables = array_values( array_unique( $args_tables ) ); + if ( ! ( $tables = array_values( array_intersect( $tables, $args_tables ) ) ) ) { + \WP_CLI::error( sprintf( "Couldn't find any tables matching: %s", implode( ' ', $args ) ) ); + } } - $filter_sitecategories( $matching_tables ); - return array_values( $matching_tables ); + return $tables; } diff --git a/php/utils.php b/php/utils.php index 2b4c6bf86d..c259795911 100644 --- a/php/utils.php +++ b/php/utils.php @@ -1374,3 +1374,21 @@ function _proc_open_compat_win_env( $cmd, &$env ) { function esc_like( $text ) { return addcslashes( $text, '_%\\' ); } + +/** + * Escapes (backticks) MySQL identifiers (aka schema object names) - i.e. column names, table names, and database/index/alias/view etc names. + * See https://dev.mysql.com/doc/refman/5.5/en/identifiers.html + * + * @param string|array $idents A single identifier or an array of identifiers. + * @return string|array An escaped string if given a string, or an array of escaped strings if given an array of strings. + */ +function esc_sql_ident( $idents ) { + $backtick = function ( $v ) { + // Escape any backticks in the identifier by doubling. + return '`' . str_replace( '`', '``', $v ) . '`'; + }; + if ( is_string( $idents ) ) { + return $backtick( $idents ); + } + return array_map( $backtick, $idents ); +} From 0392a1daee07431711d533004228dcaeffbf5f3a Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 19 Jan 2018 13:13:58 +0000 Subject: [PATCH 170/214] Suppress incorrect phpcs error. --- php/utils-wp.php | 1 + 1 file changed, 1 insertion(+) diff --git a/php/utils-wp.php b/php/utils-wp.php index 3fbda3e4de..44f59549c1 100644 --- a/php/utils-wp.php +++ b/php/utils-wp.php @@ -340,6 +340,7 @@ function wp_get_table_names( $args, $assoc_args = array() ) { } // Note: BC change 1.5.0, tables are sorted (via TABLES view). + // @codingStandardsIgnoreLine $tables = $wpdb->get_col( sprintf( "SHOW TABLES WHERE %s IN ('%s')", esc_sql_ident( 'Tables_in_' . $wpdb->dbname ), implode( "', '", $wpdb->_escape( $wp_tables ) ) ) ); } From 6c8f5e52450e350d997df512dd9ae90361093580 Mon Sep 17 00:00:00 2001 From: websupporter Date: Fri, 19 Jan 2018 19:09:13 +0200 Subject: [PATCH 171/214] introduce wp_is_readable method and add additional error message --- php/WP_CLI/Runner.php | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/php/WP_CLI/Runner.php b/php/WP_CLI/Runner.php index 50a6eae5cb..5936c745f4 100644 --- a/php/WP_CLI/Runner.php +++ b/php/WP_CLI/Runner.php @@ -763,11 +763,20 @@ public function get_required_files() { * @return bool */ private function wp_exists() { + return file_exists( ABSPATH . 'wp-includes/version.php' ); + } + + /** + * Are WordPress core files readable? + * + * @return bool + */ + private function wp_is_readable() { return is_readable( ABSPATH . 'wp-includes/version.php' ); } private function check_wp_version() { - if ( ! $this->wp_exists() ) { + if ( ! $this->wp_exists() || ! $this->wp_is_readable() ) { $this->show_synopsis_if_composite_command(); // If the command doesn't exist use as error. $args = $this->cmd_starts_with( array( 'help' ) ) ? array_slice( $this->arguments, 1 ) : $this->arguments; @@ -778,6 +787,12 @@ private function check_wp_version() { } WP_CLI::error( $suggestion_or_disabled ); } + + if ( $this->wp_exists() && ! $this->wp_is_readable() ) { + WP_CLI::error( + 'It seems, the WordPress core files do not have the proper file permissions.' + ); + } WP_CLI::error( "This does not seem to be a WordPress install.\n" . 'Pass --path=`path/to/wordpress` or run `wp core download`.' From 1fb1c86a0f61753a00a6b7aab85332f7a4b8941e Mon Sep 17 00:00:00 2001 From: websupporter Date: Fri, 19 Jan 2018 19:53:06 +0200 Subject: [PATCH 172/214] use variables to store existence and readability --- php/WP_CLI/Runner.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/php/WP_CLI/Runner.php b/php/WP_CLI/Runner.php index 5936c745f4..058b45051f 100644 --- a/php/WP_CLI/Runner.php +++ b/php/WP_CLI/Runner.php @@ -776,7 +776,9 @@ private function wp_is_readable() { } private function check_wp_version() { - if ( ! $this->wp_exists() || ! $this->wp_is_readable() ) { + $wp_exists = $this->wp_exists(); + $wp_is_readable = $this->wp_is_readable(); + if ( ! $wp_exists || ! $wp_is_readable ) { $this->show_synopsis_if_composite_command(); // If the command doesn't exist use as error. $args = $this->cmd_starts_with( array( 'help' ) ) ? array_slice( $this->arguments, 1 ) : $this->arguments; @@ -788,7 +790,7 @@ private function check_wp_version() { WP_CLI::error( $suggestion_or_disabled ); } - if ( $this->wp_exists() && ! $this->wp_is_readable() ) { + if ( $wp_exists && ! $wp_is_readable ) { WP_CLI::error( 'It seems, the WordPress core files do not have the proper file permissions.' ); From d3bed52b026d17f772d72b14f715ea388244fe81 Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 19 Jan 2018 19:40:48 +0000 Subject: [PATCH 173/214] Leave out termmeta from tests for WP < 4.6 compat. --- features/utils-wp.feature | 68 ++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 19 deletions(-) diff --git a/features/utils-wp.feature b/features/utils-wp.feature index 0854bdaa2f..cf15578adb 100644 --- a/features/utils-wp.feature +++ b/features/utils-wp.feature @@ -38,7 +38,7 @@ Feature: Utilities that depend on WordPress code """ When I run `wp --require=table_names.php get_table_names` - Then STDOUT should be: + Then STDOUT should contain: """ wp_commentmeta wp_comments @@ -48,7 +48,10 @@ Feature: Utilities that depend on WordPress code wp_posts wp_term_relationships wp_term_taxonomy - wp_termmeta + """ + # Leave out wp_termmeta for old WP compat. + And STDOUT should contain: + """ wp_terms wp_usermeta wp_users @@ -62,7 +65,7 @@ Feature: Utilities that depend on WordPress code """ When I run `wp --require=table_names.php get_table_names --scope=blog` - Then STDOUT should be: + Then STDOUT should contain: """ wp_commentmeta wp_comments @@ -72,7 +75,10 @@ Feature: Utilities that depend on WordPress code wp_posts wp_term_relationships wp_term_taxonomy - wp_termmeta + """ + # Leave out wp_termmeta for old WP compat. + And STDOUT should contain: + """ wp_terms """ @@ -99,7 +105,7 @@ Feature: Utilities that depend on WordPress code """ When I run `wp --require=table_names.php get_table_names --all-tables-with-prefix` - Then STDOUT should be: + Then STDOUT should contain: """ wp_categories wp_commentmeta @@ -111,7 +117,10 @@ Feature: Utilities that depend on WordPress code wp_posts_xx wp_term_relationships wp_term_taxonomy - wp_termmeta + """ + # Leave out wp_termmeta for old WP compat. + And STDOUT should contain: + """ wp_terms wp_usermeta wp_users @@ -119,7 +128,7 @@ Feature: Utilities that depend on WordPress code """ When I run `wp --require=table_names.php get_table_names --all-tables` - Then STDOUT should be: + Then STDOUT should contain: """ wp_categories wp_commentmeta @@ -131,7 +140,10 @@ Feature: Utilities that depend on WordPress code wp_posts_xx wp_term_relationships wp_term_taxonomy - wp_termmeta + """ + # Leave out wp_termmeta for old WP compat. + And STDOUT should contain: + """ wp_terms wp_usermeta wp_users @@ -298,7 +310,7 @@ Feature: Utilities that depend on WordPress code # With no subsite. When I run `wp --require=table_names.php get_table_names` - Then STDOUT should be: + Then STDOUT should contain: """ wp_blog_versions wp_blogs @@ -314,7 +326,10 @@ Feature: Utilities that depend on WordPress code wp_sitemeta wp_term_relationships wp_term_taxonomy - wp_termmeta + """ + # Leave out wp_termmeta for old WP compat. + And STDOUT should contain: + """ wp_terms wp_usermeta wp_users @@ -328,7 +343,7 @@ Feature: Utilities that depend on WordPress code """ When I run `wp --require=table_names.php get_table_names --scope=blog` - Then STDOUT should be: + Then STDOUT should contain: """ wp_commentmeta wp_comments @@ -338,7 +353,10 @@ Feature: Utilities that depend on WordPress code wp_posts wp_term_relationships wp_term_taxonomy - wp_termmeta + """ + # Leave out wp_termmeta for old WP compat. + And STDOUT should contain: + """ wp_terms """ @@ -388,7 +406,7 @@ Feature: Utilities that depend on WordPress code """ When I run `wp --require=table_names.php get_table_names --url=example.com/foo --scope=blog` - Then STDOUT should be: + Then STDOUT should contain: """ wp_2_commentmeta wp_2_comments @@ -398,7 +416,10 @@ Feature: Utilities that depend on WordPress code wp_2_posts wp_2_term_relationships wp_2_term_taxonomy - wp_2_termmeta + """ + # Leave out wp_2_termmeta for old WP compat. + And STDOUT should contain: + """ wp_2_terms """ And save STDOUT as {SUBSITE_BLOG_STDOUT} @@ -425,7 +446,7 @@ Feature: Utilities that depend on WordPress code """ When I run `wp --require=table_names.php get_table_names --all-tables-with-prefix` - Then STDOUT should be: + Then STDOUT should contain: """ wp_2_commentmeta wp_2_comments @@ -436,7 +457,10 @@ Feature: Utilities that depend on WordPress code wp_2_posts_xx wp_2_term_relationships wp_2_term_taxonomy - wp_2_termmeta + """ + # Leave out wp_2_termmeta for old WP compat. + And STDOUT should contain: + """ wp_2_terms wp_2_xx_posts wp_blog_versions @@ -456,7 +480,10 @@ Feature: Utilities that depend on WordPress code wp_sitemeta wp_term_relationships wp_term_taxonomy - wp_termmeta + """ + # Leave out wp_termmeta for old WP compat. + And STDOUT should contain: + """ wp_terms wp_usermeta wp_users @@ -659,7 +686,7 @@ Feature: Utilities that depend on WordPress code } ); """ When I run `wp --require=table_names.php --require=enable_sitecategories.php get_table_names` - Then STDOUT should be: + Then STDOUT should contain: """ wp_blog_versions wp_blogs @@ -676,7 +703,10 @@ Feature: Utilities that depend on WordPress code wp_sitemeta wp_term_relationships wp_term_taxonomy - wp_termmeta + """ + # Leave out wp_termmeta for old WP compat. + And STDOUT should contain: + """ wp_terms wp_usermeta wp_users From 1d3885cca5ede00a2e8c56988781ab3cfce6da3f Mon Sep 17 00:00:00 2001 From: gitlost Date: Sun, 21 Jan 2018 17:12:46 +0000 Subject: [PATCH 174/214] Add dev-master branch alias. --- composer.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/composer.json b/composer.json index 366c303083..8533030d20 100644 --- a/composer.json +++ b/composer.json @@ -80,6 +80,9 @@ "psr-4": { "": "php/commands/src" } }, "extra": { + "branch-alias": { + "dev-master": "1.5.x-dev" + }, "autoload-splitter": { "splitter-logic": "WP_CLI\\AutoloadSplitter", "splitter-location": "php/WP_CLI/AutoloadSplitter.php", From 34c7a6189e203f8054db7a42638dfd1c62a27da3 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sun, 21 Jan 2018 19:12:40 +0000 Subject: [PATCH 175/214] Fix indent. --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 8533030d20..de8a88a70d 100644 --- a/composer.json +++ b/composer.json @@ -80,9 +80,9 @@ "psr-4": { "": "php/commands/src" } }, "extra": { - "branch-alias": { - "dev-master": "1.5.x-dev" - }, + "branch-alias": { + "dev-master": "1.5.x-dev" + }, "autoload-splitter": { "splitter-logic": "WP_CLI\\AutoloadSplitter", "splitter-location": "php/WP_CLI/AutoloadSplitter.php", From f52ee65168c93a52515fad3293069d0eb90a5fe0 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 22 Jan 2018 23:08:27 +0000 Subject: [PATCH 176/214] Add embed-command as bundled package. --- .github/ISSUE_TEMPLATE | 1 + composer.json | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE index 4bbca121ac..f6706f7401 100644 --- a/.github/ISSUE_TEMPLATE +++ b/.github/ISSUE_TEMPLATE @@ -18,6 +18,7 @@ Oh! It's worth noting WP-CLI represents a collection of sub-projects, each with * `wp core *` https://github.com/wp-cli/core-command * `wp cron *` https://github.com/wp-cli/cron-command * `wp db *` https://github.com/wp-cli/db-command +* `wp embed *` https://github.com/wp-cli/embed-command * `wp (eval|eval-file)` https://github.com/wp-cli/eval-command * `wp export` https://github.com/wp-cli/export-command * `wp (option|post|comment|user|term|site) *` https://github.com/wp-cli/entity-command diff --git a/composer.json b/composer.json index de8a88a70d..0949d2b78e 100644 --- a/composer.json +++ b/composer.json @@ -45,6 +45,7 @@ "wp-cli/core-command": "^1.0", "wp-cli/cron-command": "^1.0", "wp-cli/db-command": "^1.0", + "wp-cli/embed-command": "^1.0", "wp-cli/entity-command": "^1.0", "wp-cli/eval-command": "^1.0", "wp-cli/export-command": "^1.0", From 675fa77f6d6a8725074d7fbba4098ecb664f6dde Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 23 Jan 2018 22:23:12 +0000 Subject: [PATCH 177/214] single site install -> multisite install. --- features/utils-wp.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/utils-wp.feature b/features/utils-wp.feature index cf15578adb..7f3756bbf2 100644 --- a/features/utils-wp.feature +++ b/features/utils-wp.feature @@ -267,7 +267,7 @@ Feature: Utilities that depend on WordPress code wp_posts """ - Scenario: Get WP table names for single site install + Scenario: Get WP table names for multisite install Given a WP multisite install And I run `wp db query "CREATE TABLE xx_wp_posts ( id int );"` And I run `wp db query "CREATE TABLE xx_wp_2_posts ( id int );"` From b509786f55cbf59c1e83322841d2e27070359c23 Mon Sep 17 00:00:00 2001 From: Kirtan Gajjar Date: Wed, 24 Jan 2018 18:00:41 +0530 Subject: [PATCH 178/214] Fixed Broken #4629 Fixed #4629 - Broken `0` edge case in `WP_CLI\Utils\is_json()` --- php/utils.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/utils.php b/php/utils.php index 473a40ba9e..33ac8b40d4 100644 --- a/php/utils.php +++ b/php/utils.php @@ -1406,7 +1406,7 @@ function esc_sql_ident( $idents ) { * @return bool Whether the provided string is a valid JSON representation. */ function is_json( $argument, $ignore_scalars = true ) { - if ( empty( $argument ) || ! is_string( $argument ) ) { + if ( ! is_string( $argument ) || 0 === strlen( $argument ) ) { return false; } From 2ee6e1946664aaf75d61c27a7fbb7e027d5066f4 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 24 Jan 2018 15:43:13 +0000 Subject: [PATCH 179/214] Append longdesc if given synopsis on WP_CLI::add_command(). --- features/command.feature | 97 ++++++++++++++++++++++++++++++++++++++-- php/class-wp-cli.php | 15 ++++--- php/commands/help.php | 4 +- 3 files changed, 105 insertions(+), 11 deletions(-) diff --git a/features/command.feature b/features/command.feature index 6c287c777c..e4c6104608 100644 --- a/features/command.feature +++ b/features/command.feature @@ -769,11 +769,102 @@ Feature: WP-CLI Commands When I run `wp help foo` Then STDOUT should contain: """ - EXAMPLES + NAME + + wp foo + + DESCRIPTION + + My awesome function command + + SYNOPSIS + + wp foo + + EXAMPLES + + # Run the custom foo command + + GLOBAL PARAMETERS + """ - And STDOUT should contain: + + # With synopsis, appended. + Given a hello-command.php file: """ - # Run the custom foo command + 'Prints a greeting.', + 'synopsis' => array( + array( + 'type' => 'positional', + 'name' => 'name', + 'optional' => false, + 'repeating' => false, + ), + array( + 'type' => 'assoc', + 'name' => 'type', + 'optional' => true, + 'default' => 'success', + 'options' => array( 'success', 'error' ), + ), + array( + 'type' => 'flag', + 'name' => 'honk', + 'optional' => true, + ), + ), + 'when' => 'after_wp_load', + 'longdesc' => "## EXAMPLES\n\n# Say hello to Newman\nwp example hello Newman\nSuccess: Hello, Newman!", + ) ); + """ + + When I run `wp --require=hello-command.php help example hello` + Then STDOUT should contain: + """ + NAME + + wp example hello + + DESCRIPTION + + Prints a greeting. + + SYNOPSIS + + wp example hello [--type=] [--honk] + + OPTIONS + + + + [--type=] + --- + default: success + options: + - success + - error + --- + + [--honk] + + EXAMPLES + + # Say hello to Newman + wp example hello Newman + Success: Hello, Newman! + + GLOBAL PARAMETERS + """ Scenario: Register a command with default and accepted arguments. diff --git a/php/class-wp-cli.php b/php/class-wp-cli.php index 18cefd9beb..d7f5f91a3f 100644 --- a/php/class-wp-cli.php +++ b/php/class-wp-cli.php @@ -510,9 +510,9 @@ public static function add_command( $name, $callable, $args = array() ) { $long_desc = ''; $bits = explode( ' ', $synopsis ); foreach ( $args['synopsis'] as $key => $arg ) { - $long_desc .= $bits[ $key ] . PHP_EOL; + $long_desc .= $bits[ $key ] . "\n"; if ( ! empty( $arg['description'] ) ) { - $long_desc .= ': ' . $arg['description'] . PHP_EOL; + $long_desc .= ': ' . $arg['description'] . "\n"; } $yamlify = array(); foreach ( array( 'default', 'options' ) as $key ) { @@ -522,13 +522,16 @@ public static function add_command( $name, $callable, $args = array() ) { } if ( ! empty( $yamlify ) ) { $long_desc .= Spyc::YAMLDump( $yamlify ); - $long_desc .= '---' . PHP_EOL; + $long_desc .= '---' . "\n"; } - $long_desc .= PHP_EOL; + $long_desc .= "\n"; } if ( ! empty( $long_desc ) ) { - $long_desc = rtrim( $long_desc, PHP_EOL ); - $long_desc = '## OPTIONS' . PHP_EOL . PHP_EOL . $long_desc; + $long_desc = rtrim( $long_desc, "\n" ); + $long_desc = '## OPTIONS' . "\n\n" . $long_desc; + if ( ! empty( $args['longdesc'] ) ) { + $long_desc .= "\n\n" . ltrim( $args['longdesc'], "\n" ); + } $leaf_command->set_longdesc( $long_desc ); } } diff --git a/php/commands/help.php b/php/commands/help.php index 91b810b347..b1af080584 100644 --- a/php/commands/help.php +++ b/php/commands/help.php @@ -49,8 +49,8 @@ private static function show_help( $command ) { // definition lists $out = preg_replace_callback( '/([^\n]+)\n: (.+?)(\n\n|$)/s', array( __CLASS__, 'rewrap_param_desc' ), $out ); - // Ensure all non-section headers are indented. - $out = preg_replace( '#^([^\s^\#])#m', "\t$1", $out ); + // Ensure lines with no leading whitespace that aren't section headers are indented. + $out = preg_replace( '/^((?! |\t|##).)/m', "\t$1", $out ); $tab = str_repeat( ' ', 2 ); From 477327b23145f90d9e3bf067b83f89145992a605 Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 24 Jan 2018 17:05:49 +0000 Subject: [PATCH 180/214] Include '\r' in trim so don't get orphans; test arg description as well. --- features/command.feature | 4 +++- php/class-wp-cli.php | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/features/command.feature b/features/command.feature index e4c6104608..826d45daa9 100644 --- a/features/command.feature +++ b/features/command.feature @@ -807,6 +807,7 @@ Feature: WP-CLI Commands array( 'type' => 'positional', 'name' => 'name', + 'description' => 'Name of person to greet.', 'optional' => false, 'repeating' => false, ), @@ -824,7 +825,7 @@ Feature: WP-CLI Commands ), ), 'when' => 'after_wp_load', - 'longdesc' => "## EXAMPLES\n\n# Say hello to Newman\nwp example hello Newman\nSuccess: Hello, Newman!", + 'longdesc' => "\r\n## EXAMPLES\n\n# Say hello to Newman\nwp example hello Newman\nSuccess: Hello, Newman!", ) ); """ @@ -846,6 +847,7 @@ Feature: WP-CLI Commands OPTIONS + Name of person to greet. [--type=] --- diff --git a/php/class-wp-cli.php b/php/class-wp-cli.php index d7f5f91a3f..aa4c402f01 100644 --- a/php/class-wp-cli.php +++ b/php/class-wp-cli.php @@ -527,10 +527,10 @@ public static function add_command( $name, $callable, $args = array() ) { $long_desc .= "\n"; } if ( ! empty( $long_desc ) ) { - $long_desc = rtrim( $long_desc, "\n" ); + $long_desc = rtrim( $long_desc, "\r\n" ); $long_desc = '## OPTIONS' . "\n\n" . $long_desc; if ( ! empty( $args['longdesc'] ) ) { - $long_desc .= "\n\n" . ltrim( $args['longdesc'], "\n" ); + $long_desc .= "\n\n" . ltrim( $args['longdesc'], "\r\n" ); } $leaf_command->set_longdesc( $long_desc ); } From 11201251a727499323941cd0adf020d9b33bff55 Mon Sep 17 00:00:00 2001 From: Kirtan Gajjar Date: Wed, 24 Jan 2018 23:36:45 +0530 Subject: [PATCH 181/214] Add testcases for bug fixed --- php/utils.php | 2 +- tests/test-utils.php | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/php/utils.php b/php/utils.php index 33ac8b40d4..41d8301c36 100644 --- a/php/utils.php +++ b/php/utils.php @@ -1406,7 +1406,7 @@ function esc_sql_ident( $idents ) { * @return bool Whether the provided string is a valid JSON representation. */ function is_json( $argument, $ignore_scalars = true ) { - if ( ! is_string( $argument ) || 0 === strlen( $argument ) ) { + if ( ! is_string( $argument ) || '' === $argument ) { return false; } diff --git a/tests/test-utils.php b/tests/test-utils.php index 52d7cf4f68..1a891e308d 100644 --- a/tests/test-utils.php +++ b/tests/test-utils.php @@ -707,6 +707,10 @@ public function dataIsJson() { array( '{"key1":"value1","key2":"value2"}', false, true ), array( '["value1","value2"]', true, true ), array( '["value1","value2"]', false, true ), + array( '0', true, false ), + array( '0', false, true ), + array( '', true, false ), + array( '', false, false ), ); } From a82481af517279408739456c89d4ce955352f2fc Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 24 Jan 2018 18:40:20 +0000 Subject: [PATCH 182/214] Add Utils\normalize_eols() and use in CompositeCommand. --- php/WP_CLI/Dispatcher/CompositeCommand.php | 4 ++-- php/utils.php | 10 ++++++++++ tests/test-utils.php | 4 ++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/php/WP_CLI/Dispatcher/CompositeCommand.php b/php/WP_CLI/Dispatcher/CompositeCommand.php index a00358f78b..3ebff40f19 100644 --- a/php/WP_CLI/Dispatcher/CompositeCommand.php +++ b/php/WP_CLI/Dispatcher/CompositeCommand.php @@ -117,7 +117,7 @@ public function get_shortdesc() { * @param string */ public function set_shortdesc( $shortdesc ) { - $this->shortdesc = $shortdesc; + $this->shortdesc = Utils\normalize_eols( $shortdesc ); } /** @@ -136,7 +136,7 @@ public function get_longdesc() { * @param string */ public function set_longdesc( $longdesc ) { - $this->longdesc = $longdesc; + $this->longdesc = Utils\normalize_eols( $longdesc ); } /** diff --git a/php/utils.php b/php/utils.php index 473a40ba9e..be4fa4b783 100644 --- a/php/utils.php +++ b/php/utils.php @@ -772,6 +772,16 @@ function trailingslashit( $string ) { return rtrim( $string, '/\\' ) . '/'; } +/** + * Convert Windows EOLs to *nix. + * + * @param string $str String to convert. + * @return string String with carriage return / newline pairs reduced to newlines. + */ +function normalize_eols( $str ) { + return str_replace( "\r\n", "\n", $str ); +} + /** * Get the system's temp directory. Warns user if it isn't writable. * diff --git a/tests/test-utils.php b/tests/test-utils.php index 52d7cf4f68..79bd75c8ca 100644 --- a/tests/test-utils.php +++ b/tests/test-utils.php @@ -326,6 +326,10 @@ public function testTrailingslashit() { $this->assertSame( 'a/', Utils\trailingslashit( 'a\\//\\' ) ); } + public function testNormalizeEols() { + $this->assertSame( "\na\ra\na\n", Utils\normalize_eols( "\r\na\ra\r\na\r\n" ) ); + } + public function testGetTempDir() { $this->assertTrue( '/' === substr( Utils\get_temp_dir(), -1 ) ); From c8c04ab072456f2f07ca11c82d51ce0f17b9f7da Mon Sep 17 00:00:00 2001 From: Kirtan Gajjar Date: Thu, 25 Jan 2018 10:50:05 +0530 Subject: [PATCH 183/214] Remove extra space to satisfy the wpcs sniff --- php/utils.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/utils.php b/php/utils.php index 41d8301c36..ab6299a543 100644 --- a/php/utils.php +++ b/php/utils.php @@ -1406,7 +1406,7 @@ function esc_sql_ident( $idents ) { * @return bool Whether the provided string is a valid JSON representation. */ function is_json( $argument, $ignore_scalars = true ) { - if ( ! is_string( $argument ) || '' === $argument ) { + if ( ! is_string( $argument ) || '' === $argument ) { return false; } From bb5b5d26a24dbf621bf3050c6be9f2d79426fb7a Mon Sep 17 00:00:00 2001 From: Alain Schlesser Date: Thu, 25 Jan 2018 21:50:34 +0100 Subject: [PATCH 184/214] Reverse the aliases for checksum verification commands See https://github.com/wp-cli/checksum-command/issues/14 --- features/command.feature | 6 ------ php/WP_CLI/Configurator.php | 13 +++++++++---- php/WP_CLI/Runner.php | 11 ++++++++--- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/features/command.feature b/features/command.feature index 826d45daa9..045b288f7f 100644 --- a/features/command.feature +++ b/features/command.feature @@ -15,12 +15,6 @@ Feature: WP-CLI Commands wp cap """ - When I run `wp checksum --help` - Then STDOUT should contain: - """ - wp checksum - """ - When I run `wp comment --help` Then STDOUT should contain: """ diff --git a/php/WP_CLI/Configurator.php b/php/WP_CLI/Configurator.php index d099eddec8..3e6c569e29 100644 --- a/php/WP_CLI/Configurator.php +++ b/php/WP_CLI/Configurator.php @@ -323,10 +323,15 @@ private static function load_yml( $yml_file ) { $config['config create'] = $config['core config']; unset( $config['core config'] ); } - // 'core verify-checksums' -> 'checksum core' - if ( isset( $config['core verify-checksums'] ) ) { - $config['checksum core'] = $config['core verify-checksums']; - unset( $config['core verify-checksums'] ); + // 'checksum core' -> 'core verify-checksums' + if ( isset( $config['checksum core'] ) ) { + $config['core verify-checksums'] = $config['checksum core']; + unset( $config['checksum core'] ); + } + // 'checksum plugin' -> 'plugin verify-checksums' + if ( isset( $config['checksum plugin'] ) ) { + $config['plugin verify-checksums'] = $config['checksum plugin']; + unset( $config['checksum plugin'] ); } return $config; diff --git a/php/WP_CLI/Runner.php b/php/WP_CLI/Runner.php index 058b45051f..292f247b48 100644 --- a/php/WP_CLI/Runner.php +++ b/php/WP_CLI/Runner.php @@ -616,9 +616,14 @@ private static function back_compat_conversions( $args, $assoc_args ) { list( $args[0], $args[1] ) = array( 'language', 'core' ); } - // core verify-checksums -> checksum core - if ( array( 'core', 'verify-checksums' ) == array_slice( $args, 0, 2 ) ) { - list( $args[0], $args[1] ) = array( 'checksum', 'core' ); + // checksum core -> core verify-checksums + if ( array( 'checksum', 'core' ) == array_slice( $args, 0, 2 ) ) { + list( $args[0], $args[1] ) = array( 'core', 'verify-checksums' ); + } + + // checksum plugin -> plugin verify-checksums + if ( array( 'checksum', 'plugin' ) == array_slice( $args, 0, 2 ) ) { + list( $args[0], $args[1] ) = array( 'plugin', 'verify-checksums' ); } // site create --site_id= -> site create --network_id= From f8e357a90f8df93f83832e15f8b64b6fd3fed677 Mon Sep 17 00:00:00 2001 From: Alain Schlesser Date: Mon, 29 Jan 2018 15:23:33 +0100 Subject: [PATCH 185/214] Update Composer lock file * Update `wp-cli/checksum-command` `v1.0.5` => `v1.0.7` * Add `wp-cli/embed-command` `v1.0.0` --- composer.lock | 74 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 8 deletions(-) diff --git a/composer.lock b/composer.lock index 50c62cafed..7e492694d5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "0dc5e25ccc983dbe1ac137a5638b8654", + "content-hash": "36f8e11f5ba78726579607300deee9a7", "packages": [ { "name": "composer/ca-bundle", @@ -1421,21 +1421,21 @@ }, { "name": "wp-cli/checksum-command", - "version": "v1.0.5", + "version": "v1.0.7", "source": { "type": "git", "url": "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/wp-cli/checksum-command.git", - "reference": "a2719a5ba84ffd7d47511967433da7211e0da55a" + "reference": "3d12264aa54d0465128c933898dc167ab79d8676" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/checksum-command/zipball/a2719a5ba84ffd7d47511967433da7211e0da55a", - "reference": "a2719a5ba84ffd7d47511967433da7211e0da55a", + "url": "https://api.github.com/repos/wp-cli/checksum-command/zipball/3d12264aa54d0465128c933898dc167ab79d8676", + "reference": "3d12264aa54d0465128c933898dc167ab79d8676", "shasum": "" }, "require-dev": { "behat/behat": "~2.5", - "wp-cli/wp-cli": "*" + "wp-cli/wp-cli": "^1.5" }, "type": "wp-cli-package", "extra": { @@ -1444,7 +1444,8 @@ }, "bundled": true, "commands": [ - "checksum core" + "core verify-checksums", + "plugin verify-checksums" ] }, "autoload": { @@ -1468,7 +1469,7 @@ ], "description": "Verifies file integrity by comparing to published checksums.", "homepage": "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/wp-cli/checksum-command", - "time": "2017-12-08T15:12:46+00:00" + "time": "2018-01-27T17:35:07+00:00" }, { "name": "wp-cli/config-command", @@ -1710,6 +1711,63 @@ "homepage": "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/wp-cli/db-command", "time": "2017-12-08T15:04:48+00:00" }, + { + "name": "wp-cli/embed-command", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "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/wp-cli/embed-command.git", + "reference": "81319d4243a8dfe096389bf54cdc4fc3dec53497" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/embed-command/zipball/81319d4243a8dfe096389bf54cdc4fc3dec53497", + "reference": "81319d4243a8dfe096389bf54cdc4fc3dec53497", + "shasum": "" + }, + "require-dev": { + "behat/behat": "~2.5", + "wp-cli/wp-cli": "^1.5" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + }, + "bundled": true, + "commands": [ + "embed", + "embed fetch", + "embed provider list", + "embed provider match", + "embed handler list", + "embed cache clear", + "embed cache find", + "embed cache trigger" + ] + }, + "autoload": { + "psr-4": { + "WP_CLI\\Embeds\\": "src/" + }, + "files": [ + "embed-command.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Pascal Birchler", + "homepage": "https://pascalbirchler.com/" + } + ], + "description": "Inspects oEmbed providers, clears embed cache, and more.", + "homepage": "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/wp-cli/embed-command", + "time": "2018-01-22T21:26:48+00:00" + }, { "name": "wp-cli/entity-command", "version": "v1.1.4", From 92eb0732fa447f487520847664987897282cd22a Mon Sep 17 00:00:00 2001 From: Alain Schlesser Date: Mon, 29 Jan 2018 18:27:56 +0100 Subject: [PATCH 186/214] Include `wp-cli/checksum-command` v1.0.8 --- composer.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.lock b/composer.lock index 7e492694d5..68f70004d4 100644 --- a/composer.lock +++ b/composer.lock @@ -1421,16 +1421,16 @@ }, { "name": "wp-cli/checksum-command", - "version": "v1.0.7", + "version": "v1.0.8", "source": { "type": "git", "url": "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/wp-cli/checksum-command.git", - "reference": "3d12264aa54d0465128c933898dc167ab79d8676" + "reference": "360c0c658242919e9a74ba06917fd8a691484174" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/checksum-command/zipball/3d12264aa54d0465128c933898dc167ab79d8676", - "reference": "3d12264aa54d0465128c933898dc167ab79d8676", + "url": "https://api.github.com/repos/wp-cli/checksum-command/zipball/360c0c658242919e9a74ba06917fd8a691484174", + "reference": "360c0c658242919e9a74ba06917fd8a691484174", "shasum": "" }, "require-dev": { @@ -1469,7 +1469,7 @@ ], "description": "Verifies file integrity by comparing to published checksums.", "homepage": "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/wp-cli/checksum-command", - "time": "2018-01-27T17:35:07+00:00" + "time": "2018-01-29T16:56:18+00:00" }, { "name": "wp-cli/config-command", From 41c72ca6b42648c07886a573e63b9fab20410380 Mon Sep 17 00:00:00 2001 From: Alain Schlesser Date: Mon, 29 Jan 2018 18:37:33 +0100 Subject: [PATCH 187/214] Include `wp-cli/db-command` v1.3.3 --- composer.lock | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/composer.lock b/composer.lock index 68f70004d4..1a0411e46e 100644 --- a/composer.lock +++ b/composer.lock @@ -1646,23 +1646,21 @@ }, { "name": "wp-cli/db-command", - "version": "v1.3.2", + "version": "v1.3.3", "source": { "type": "git", "url": "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/wp-cli/db-command.git", - "reference": "162d72acfd6dc1478e2ef249160bffbfa4293371" + "reference": "7d361a15ffe34dfc9d798a81208fe61b8a2f049a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/db-command/zipball/162d72acfd6dc1478e2ef249160bffbfa4293371", - "reference": "162d72acfd6dc1478e2ef249160bffbfa4293371", + "url": "https://api.github.com/repos/wp-cli/db-command/zipball/7d361a15ffe34dfc9d798a81208fe61b8a2f049a", + "reference": "7d361a15ffe34dfc9d798a81208fe61b8a2f049a", "shasum": "" }, - "require": { - "wp-cli/wp-cli": "*" - }, "require-dev": { - "behat/behat": "~2.5" + "behat/behat": "~2.5", + "wp-cli/wp-cli": "^1.5" }, "type": "wp-cli-package", "extra": { @@ -1709,7 +1707,7 @@ ], "description": "Performs basic database operations using credentials stored in wp-config.php.", "homepage": "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/wp-cli/db-command", - "time": "2017-12-08T15:04:48+00:00" + "time": "2018-01-29T02:30:16+00:00" }, { "name": "wp-cli/embed-command", From 96aa999a13ee5e582926e55a665355b2d8fa8aab Mon Sep 17 00:00:00 2001 From: Alain Schlesser Date: Tue, 30 Jan 2018 08:04:41 +0100 Subject: [PATCH 188/214] Handle old config syntax gracefully `wp config get --global=` => `wp config get --type=variable` `wp config get --constant=` => `wp config get --type=constant` `wp config get` => `wp config list` Fixes #43 --- php/WP_CLI/Runner.php | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/php/WP_CLI/Runner.php b/php/WP_CLI/Runner.php index 292f247b48..9eaa94fc7d 100644 --- a/php/WP_CLI/Runner.php +++ b/php/WP_CLI/Runner.php @@ -728,6 +728,29 @@ private static function back_compat_conversions( $args, $assoc_args ) { } } + // config get --[global|constant]= --> config get --type=constant|variable + // config get --> config list + if ( count( $args ) === 2 + && 'config' === $args[0] + && 'get' === $args[1] ) { + if ( isset( $assoc_args['global'] ) ) { + $name = $assoc_args['global']; + $type = 'variable'; + unset( $assoc_args['global'] ); + } else if ( isset( $assoc_args['constant'] ) ) { + $name = $assoc_args['constant']; + $type = 'constant'; + unset( $assoc_args['constant'] ); + } + if ( ! empty( $name ) && ! empty( $type ) ) { + $args[] = $name; + $assoc_args['type'] = $type; + } else { + // We had a 'config get' without a '', so assume 'list' was wanted. + $args[1] = 'list'; + } + } + return array( $args, $assoc_args ); } From 5990c084172e7f5f59cfc426192ae15f86dfbcb3 Mon Sep 17 00:00:00 2001 From: Alain Schlesser Date: Tue, 30 Jan 2018 08:16:36 +0100 Subject: [PATCH 189/214] Make PHPCS fixes --- php/WP_CLI/Runner.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/php/WP_CLI/Runner.php b/php/WP_CLI/Runner.php index 9eaa94fc7d..a9618fd726 100644 --- a/php/WP_CLI/Runner.php +++ b/php/WP_CLI/Runner.php @@ -731,13 +731,13 @@ private static function back_compat_conversions( $args, $assoc_args ) { // config get --[global|constant]= --> config get --type=constant|variable // config get --> config list if ( count( $args ) === 2 - && 'config' === $args[0] - && 'get' === $args[1] ) { + && 'config' === $args[0] + && 'get' === $args[1] ) { if ( isset( $assoc_args['global'] ) ) { $name = $assoc_args['global']; $type = 'variable'; unset( $assoc_args['global'] ); - } else if ( isset( $assoc_args['constant'] ) ) { + } elseif ( isset( $assoc_args['constant'] ) ) { $name = $assoc_args['constant']; $type = 'constant'; unset( $assoc_args['constant'] ); From 10f3c5dd3370748dc35382a288db1e58614540fc Mon Sep 17 00:00:00 2001 From: Alain Schlesser Date: Tue, 30 Jan 2018 08:37:08 +0100 Subject: [PATCH 190/214] Update to latest Composer packages * Updating wp-cli/core-command v1.0.8 => v1.0.9 * Updating wp-cli/entity-command v1.1.4 => v1.2.0 * Updating wp-cli/export-command v1.0.5 => v1.0.6 * Updating wp-cli/media-command v1.1.3 => v1.1.4 * Updating wp-cli/package-command v1.0.10 => v1.0.11 * Updating wp-cli/scaffold-command v1.1.1 => v1.1.2 * Updating wp-cli/search-replace-command v1.1.4 => v1.2.0 --- composer.lock | 115 ++++++++++++++++++++++++-------------------------- 1 file changed, 56 insertions(+), 59 deletions(-) diff --git a/composer.lock b/composer.lock index 1a0411e46e..2767428dc5 100644 --- a/composer.lock +++ b/composer.lock @@ -1527,16 +1527,16 @@ }, { "name": "wp-cli/core-command", - "version": "v1.0.8", + "version": "v1.0.9", "source": { "type": "git", "url": "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/wp-cli/core-command.git", - "reference": "b1c3c1bd10d081c24b606fcc6ed89100d59d4218" + "reference": "0e825668d2c060c40ec1d7debbee94bc08eec9b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/core-command/zipball/b1c3c1bd10d081c24b606fcc6ed89100d59d4218", - "reference": "b1c3c1bd10d081c24b606fcc6ed89100d59d4218", + "url": "https://api.github.com/repos/wp-cli/core-command/zipball/0e825668d2c060c40ec1d7debbee94bc08eec9b3", + "reference": "0e825668d2c060c40ec1d7debbee94bc08eec9b3", "shasum": "" }, "require-dev": { @@ -1583,7 +1583,7 @@ ], "description": "Downloads, installs, updates, and manages a WordPress installation.", "homepage": "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/wp-cli/core-command", - "time": "2017-12-19T22:21:54+00:00" + "time": "2018-01-30T06:57:10+00:00" }, { "name": "wp-cli/cron-command", @@ -1768,22 +1768,22 @@ }, { "name": "wp-cli/entity-command", - "version": "v1.1.4", + "version": "v1.2.0", "source": { "type": "git", "url": "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/wp-cli/entity-command.git", - "reference": "c3a0c2b478aeb385865e6c406b2ecb1fe1900cb5" + "reference": "035b74ea16912f5b14db7d28036a6d123eb90547" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/entity-command/zipball/c3a0c2b478aeb385865e6c406b2ecb1fe1900cb5", - "reference": "c3a0c2b478aeb385865e6c406b2ecb1fe1900cb5", + "url": "https://api.github.com/repos/wp-cli/entity-command/zipball/035b74ea16912f5b14db7d28036a6d123eb90547", + "reference": "035b74ea16912f5b14db7d28036a6d123eb90547", "shasum": "" }, "require-dev": { "behat/behat": "~2.5", "phpunit/phpunit": "^4.8", - "wp-cli/wp-cli": "*" + "wp-cli/wp-cli": "^1.5" }, "type": "wp-cli-package", "extra": { @@ -1927,6 +1927,7 @@ "user meta update", "user remove-cap", "user remove-role", + "user reset-password", "user session", "user session destroy", "user session list", @@ -1963,7 +1964,7 @@ ], "description": "Manage WordPress core entities.", "homepage": "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/wp-cli/entity-command", - "time": "2017-12-18T20:05:12+00:00" + "time": "2018-01-29T15:10:05+00:00" }, { "name": "wp-cli/eval-command", @@ -2021,24 +2022,24 @@ }, { "name": "wp-cli/export-command", - "version": "v1.0.5", + "version": "v1.0.6", "source": { "type": "git", "url": "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/wp-cli/export-command.git", - "reference": "b8469df00d0e357bbc8a51ffd006ace007449b15" + "reference": "4ae43d370ed6ed0cffd166dd84cfc6c8c2f3f633" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/export-command/zipball/b8469df00d0e357bbc8a51ffd006ace007449b15", - "reference": "b8469df00d0e357bbc8a51ffd006ace007449b15", + "url": "https://api.github.com/repos/wp-cli/export-command/zipball/4ae43d370ed6ed0cffd166dd84cfc6c8c2f3f633", + "reference": "4ae43d370ed6ed0cffd166dd84cfc6c8c2f3f633", "shasum": "" }, "require": { - "nb/oxymel": "~0.1.0", - "wp-cli/wp-cli": "*" + "nb/oxymel": "~0.1.0" }, "require-dev": { - "behat/behat": "~2.5" + "behat/behat": "~2.5", + "wp-cli/wp-cli": "^1.5" }, "type": "wp-cli-package", "extra": { @@ -2071,7 +2072,7 @@ ], "description": "Exports WordPress content to a WXR file.", "homepage": "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/wp-cli/export-command", - "time": "2017-12-14T19:06:14+00:00" + "time": "2018-01-29T02:33:05+00:00" }, { "name": "wp-cli/extension-command", @@ -2266,36 +2267,34 @@ }, { "name": "wp-cli/media-command", - "version": "v1.1.3", + "version": "v1.1.4", "source": { "type": "git", "url": "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/wp-cli/media-command.git", - "reference": "b591fe02ca32f78877300410799a562f7a301d48" + "reference": "7f8664ba722505446b3ef3dbc6717e8e7f20265c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/media-command/zipball/b591fe02ca32f78877300410799a562f7a301d48", - "reference": "b591fe02ca32f78877300410799a562f7a301d48", + "url": "https://api.github.com/repos/wp-cli/media-command/zipball/7f8664ba722505446b3ef3dbc6717e8e7f20265c", + "reference": "7f8664ba722505446b3ef3dbc6717e8e7f20265c", "shasum": "" }, - "require": { - "wp-cli/wp-cli": "*" - }, "require-dev": { - "behat/behat": "~2.5" + "behat/behat": "~2.5", + "wp-cli/wp-cli": "^1.5" }, "type": "wp-cli-package", "extra": { "branch-alias": { "dev-master": "1.x-dev" }, + "bundled": true, "commands": [ "media", "media import", "media regenerate", "media image-size" - ], - "bundled": true + ] }, "autoload": { "psr-4": { @@ -2318,7 +2317,7 @@ ], "description": "Imports files as attachments, regenerates thumbnails, or lists registered image sizes.", "homepage": "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/wp-cli/media-command", - "time": "2017-12-15T15:00:38+00:00" + "time": "2018-01-29T02:17:56+00:00" }, { "name": "wp-cli/mustangostang-spyc", @@ -2370,30 +2369,31 @@ }, { "name": "wp-cli/package-command", - "version": "v1.0.10", + "version": "v1.0.11", "source": { "type": "git", "url": "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/wp-cli/package-command.git", - "reference": "b7d2ee2fc0f4ff052799fdc4308ac2f99031f66a" + "reference": "b0f0e59a1d174c80bd11833b2f4a650d835d7a29" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/package-command/zipball/b7d2ee2fc0f4ff052799fdc4308ac2f99031f66a", - "reference": "b7d2ee2fc0f4ff052799fdc4308ac2f99031f66a", + "url": "https://api.github.com/repos/wp-cli/package-command/zipball/b0f0e59a1d174c80bd11833b2f4a650d835d7a29", + "reference": "b0f0e59a1d174c80bd11833b2f4a650d835d7a29", "shasum": "" }, "require": { - "composer/composer": "^1.2.0", - "wp-cli/wp-cli": "*" + "composer/composer": "^1.2.0" }, "require-dev": { - "behat/behat": "~2.5" + "behat/behat": "~2.5", + "wp-cli/wp-cli": "^1.5" }, "type": "wp-cli-package", "extra": { "branch-alias": { "dev-master": "1.x-dev" }, + "bundled": true, "commands": [ "package", "package browse", @@ -2401,8 +2401,7 @@ "package list", "package update", "package uninstall" - ], - "bundled": true + ] }, "autoload": { "psr-4": { @@ -2425,7 +2424,7 @@ ], "description": "Lists, installs, and removes WP-CLI packages.", "homepage": "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/wp-cli/package-command", - "time": "2017-12-08T15:46:21+00:00" + "time": "2018-01-29T02:32:25+00:00" }, { "name": "wp-cli/php-cli-tools", @@ -2593,27 +2592,28 @@ }, { "name": "wp-cli/scaffold-command", - "version": "v1.1.1", + "version": "v1.1.2", "source": { "type": "git", "url": "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/wp-cli/scaffold-command.git", - "reference": "24b4ddeeb9531179921172597064c8f54f9f594d" + "reference": "a7ef51b2abd88a2ecb17ecdf7aaad92da37d1eb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/scaffold-command/zipball/24b4ddeeb9531179921172597064c8f54f9f594d", - "reference": "24b4ddeeb9531179921172597064c8f54f9f594d", + "url": "https://api.github.com/repos/wp-cli/scaffold-command/zipball/a7ef51b2abd88a2ecb17ecdf7aaad92da37d1eb7", + "reference": "a7ef51b2abd88a2ecb17ecdf7aaad92da37d1eb7", "shasum": "" }, "require-dev": { "behat/behat": "~2.5", - "wp-cli/wp-cli": "*" + "wp-cli/wp-cli": "^1.5" }, "type": "wp-cli-package", "extra": { "branch-alias": { "dev-master": "1.x-dev" }, + "bundled": true, "commands": [ "scaffold", "scaffold _s", @@ -2624,8 +2624,7 @@ "scaffold post-type", "scaffold taxonomy", "scaffold theme-tests" - ], - "bundled": true + ] }, "autoload": { "psr-4": { @@ -2648,37 +2647,35 @@ ], "description": "Generates code for post types, taxonomies, blocks, plugins, child themes, etc.", "homepage": "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/wp-cli/scaffold-command", - "time": "2017-12-18T14:24:43+00:00" + "time": "2018-01-29T02:29:34+00:00" }, { "name": "wp-cli/search-replace-command", - "version": "v1.1.4", + "version": "v1.2.0", "source": { "type": "git", "url": "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/wp-cli/search-replace-command.git", - "reference": "813977a75e915581a93f0cb931c325f9a231a2e9" + "reference": "c688e51b35bb87b26a3de308287d6a30cda78e44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/search-replace-command/zipball/813977a75e915581a93f0cb931c325f9a231a2e9", - "reference": "813977a75e915581a93f0cb931c325f9a231a2e9", + "url": "https://api.github.com/repos/wp-cli/search-replace-command/zipball/c688e51b35bb87b26a3de308287d6a30cda78e44", + "reference": "c688e51b35bb87b26a3de308287d6a30cda78e44", "shasum": "" }, - "require": { - "wp-cli/wp-cli": "*" - }, "require-dev": { - "behat/behat": "~2.5" + "behat/behat": "~2.5", + "wp-cli/wp-cli": "^1.5" }, "type": "wp-cli-package", "extra": { "branch-alias": { "dev-master": "1.x-dev" }, + "bundled": true, "commands": [ "search-replace" - ], - "bundled": true + ] }, "autoload": { "psr-4": { @@ -2701,7 +2698,7 @@ ], "description": "Searches/replaces strings in the database.", "homepage": "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/wp-cli/search-replace-command", - "time": "2017-12-11T15:35:16+00:00" + "time": "2018-01-29T06:27:32+00:00" }, { "name": "wp-cli/server-command", From 2d2bd8aa9f0a29203d041e08308ce0e308303bab Mon Sep 17 00:00:00 2001 From: Alain Schlesser Date: Tue, 30 Jan 2018 10:16:06 +0100 Subject: [PATCH 191/214] Support Phive package manager Phive needs a GPG signature as `.phar.asc` file. See https://phar.io/howto/sign-and-upload-to-github.html --- utils/update-phar | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/utils/update-phar b/utils/update-phar index e2b16973ee..5a0ede1c0f 100755 --- a/utils/update-phar +++ b/utils/update-phar @@ -43,7 +43,9 @@ echo $md5hash | cut -d ' ' -f 1 > $fname.md5 sha512sum $fname | cut -d ' ' -f 1 > $fname.sha512 -git add $fname $fname.md5 $fname.sha512 +gpg -u john@example.com --detach-sign --output $fname.asc $fname + +git add $fname $fname.md5 $fname.sha512 $fname.asc git commit -m "$new_commit_subj" From 512b8dfcf763cc3e16ff386450bd8155a1964c4c Mon Sep 17 00:00:00 2001 From: Alain Schlesser Date: Tue, 30 Jan 2018 10:20:39 +0100 Subject: [PATCH 192/214] Sign as alain.schlesser@gmail.com for now --- utils/update-phar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/update-phar b/utils/update-phar index 5a0ede1c0f..0b5a37655e 100755 --- a/utils/update-phar +++ b/utils/update-phar @@ -43,7 +43,7 @@ echo $md5hash | cut -d ' ' -f 1 > $fname.md5 sha512sum $fname | cut -d ' ' -f 1 > $fname.sha512 -gpg -u john@example.com --detach-sign --output $fname.asc $fname +gpg -u alain.schlesser@gmail.com --detach-sign --output $fname.asc $fname git add $fname $fname.md5 $fname.sha512 $fname.asc From e0b813b1443b3d69d47c2525a1ede7ccf8b4aeef Mon Sep 17 00:00:00 2001 From: Alain Schlesser Date: Tue, 30 Jan 2018 12:29:40 +0100 Subject: [PATCH 193/214] Update extension package Update `wp-cli/extension-command` v1.1.8 => v1.1.9 --- composer.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.lock b/composer.lock index 2767428dc5..f2abe818ee 100644 --- a/composer.lock +++ b/composer.lock @@ -2076,16 +2076,16 @@ }, { "name": "wp-cli/extension-command", - "version": "v1.1.8", + "version": "v1.1.9", "source": { "type": "git", "url": "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/wp-cli/extension-command.git", - "reference": "7ab2a957383ee63e5082f4854479738c0f2a4474" + "reference": "dfacef02b88baed07058c88064afd582f4150a97" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/extension-command/zipball/7ab2a957383ee63e5082f4854479738c0f2a4474", - "reference": "7ab2a957383ee63e5082f4854479738c0f2a4474", + "url": "https://api.github.com/repos/wp-cli/extension-command/zipball/dfacef02b88baed07058c88064afd582f4150a97", + "reference": "dfacef02b88baed07058c88064afd582f4150a97", "shasum": "" }, "require-dev": { @@ -2153,7 +2153,7 @@ ], "description": "Manages plugins and themes, including installs, activations, and updates.", "homepage": "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/wp-cli/extension-command", - "time": "2017-12-08T17:49:39+00:00" + "time": "2018-01-30T11:13:57+00:00" }, { "name": "wp-cli/import-command", From 0c8c9bffed3ecabee3bb5d3b886cc644269da7c3 Mon Sep 17 00:00:00 2001 From: Alain Schlesser Date: Tue, 30 Jan 2018 15:49:49 +0100 Subject: [PATCH 194/214] Update to latest config package * Update to `wp-cli/config-command` v1.1.7 => v1.1.8 * Adds dependency `wp-cli/wp-config-transformer` v1.2.0 --- composer.lock | 67 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/composer.lock b/composer.lock index f2abe818ee..96e350934c 100644 --- a/composer.lock +++ b/composer.lock @@ -1473,18 +1473,21 @@ }, { "name": "wp-cli/config-command", - "version": "v1.1.7", + "version": "v1.1.8", "source": { "type": "git", "url": "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/wp-cli/config-command.git", - "reference": "e0c378457e6eab81ab0cc322aba86afdad57ec45" + "reference": "4e44b3fab9e1ddb8f91e3189b27354ff4ae141ad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/config-command/zipball/e0c378457e6eab81ab0cc322aba86afdad57ec45", - "reference": "e0c378457e6eab81ab0cc322aba86afdad57ec45", + "url": "https://api.github.com/repos/wp-cli/config-command/zipball/4e44b3fab9e1ddb8f91e3189b27354ff4ae141ad", + "reference": "4e44b3fab9e1ddb8f91e3189b27354ff4ae141ad", "shasum": "" }, + "require": { + "wp-cli/wp-config-transformer": "^1.2" + }, "require-dev": { "behat/behat": "~2.5", "wp-cli/wp-cli": "*" @@ -1497,9 +1500,13 @@ "bundled": true, "commands": [ "config", + "config delete", "config create", "config get", - "config path" + "config has", + "config list", + "config path", + "config set" ] }, "autoload": { @@ -1519,11 +1526,16 @@ "name": "Daniel Bachhuber", "email": "daniel@runcommand.io", "homepage": "https://runcommand.io" + }, + { + "name": "Alain Schlesser", + "email": "alain.schlesser@gmail.com", + "homepage": "https://www.alainschlesser.com" } ], - "description": "Manage the wp-config.php file.", + "description": "Generates and reads the wp-config.php file.", "homepage": "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/wp-cli/config-command", - "time": "2017-12-08T15:12:01+00:00" + "time": "2018-01-30T14:12:41+00:00" }, { "name": "wp-cli/core-command", @@ -2920,6 +2932,47 @@ "description": "Adds, moves, and removes widgets; lists sidebars.", "homepage": "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/wp-cli/widget-command", "time": "2017-12-08T17:45:57+00:00" + }, + { + "name": "wp-cli/wp-config-transformer", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "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/wp-cli/wp-config-transformer.git", + "reference": "535007c241ea8425a8840cdb2fa0d395010a0f1c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/wp-config-transformer/zipball/535007c241ea8425a8840cdb2fa0d395010a0f1c", + "reference": "535007c241ea8425a8840cdb2fa0d395010a0f1c", + "shasum": "" + }, + "require": { + "php": ">=5.3.29" + }, + "require-dev": { + "composer/composer": "^1.5.6", + "phpunit/phpunit": "^6.5.5", + "wp-coding-standards/wpcs": "^0.14.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/WPConfigTransformer.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frankie Jarrett", + "email": "fjarrett@gmail.com" + } + ], + "description": "Programmatically edit a wp-config.php file.", + "time": "2018-01-27T11:50:22+00:00" } ], "packages-dev": [ From ca7bc1ebb802a233616c5ef6e110a5988634467a Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 30 Jan 2018 15:16:43 +0000 Subject: [PATCH 195/214] Add COMPOSER_VERSIONS file generated from composer.lock to phar. --- utils/make-phar.php | 71 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 61 insertions(+), 10 deletions(-) diff --git a/utils/make-phar.php b/utils/make-phar.php index 68f29fdee0..14c57e74f2 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -9,7 +9,7 @@ define( 'WP_CLI_BASE_PATH', dirname( dirname( dirname( WP_CLI_ROOT ) ) ) ); define( 'WP_CLI_VENDOR_DIR' , dirname( dirname( WP_CLI_ROOT ) ) ); } else { - echo 'Missing vendor/autoload.php'; + fwrite( STDERR, 'Missing vendor/autoload.php' . PHP_EOL ); exit(1); } require WP_CLI_VENDOR_DIR . '/autoload.php'; @@ -24,7 +24,7 @@ list( $args, $assoc_args, $runtime_config ) = $configurator->parse_args( array_slice( $GLOBALS['argv'], 1 ) ); if ( ! isset( $args[0] ) || empty( $args[0] ) ) { - echo "usage: php -dphar.readonly=0 $argv[0] [--quiet] [--version=same|patch|minor|major|x.y.z] [--store-version]\n"; + fwrite( STDERR, "usage: php -dphar.readonly=0 $argv[0] [--quiet] [--version=same|patch|minor|major|x.y.z] [--store-version] [--build=cli]" . PHP_EOL ); exit(1); } @@ -50,8 +50,9 @@ function add_file( $phar, $path ) { $key = str_replace( WP_CLI_BASE_PATH, '', $path ); - if ( !BE_QUIET ) - echo "$key - $path\n"; + if ( ! BE_QUIET ) { + echo "$key - $path" . PHP_EOL; + } $basename = basename( $path ); if ( 0 === strpos( $basename, 'autoload_' ) && preg_match( '/(?:classmap|files|namespaces|psr4|static)\.php$/', $basename ) ) { @@ -60,11 +61,11 @@ function add_file( $phar, $path ) { if ( null === $strip_res ) { if ( 'cli' === BUILD ) { $strips = array( - '\/(?:behat|composer|gherkin)\/src', + '\/(?:behat|composer|gherkin)\/src\/', '\/phpunit\/', - '\/nb\/oxymel', + '\/nb\/oxymel\/', '-command\/src\/', - '\/wp-cli\/[^\n]+-command\/', + '\/wp-cli\/[^\n]+?-command\/', '\/symfony\/(?!finder|polyfill-mbstring)[^\/]+\/', '\/(?:dealerdirect|squizlabs|wimg)\/', ); @@ -91,12 +92,60 @@ function add_file( $phar, $path ) { function set_file_contents( $phar, $path, $content ) { $key = str_replace( WP_CLI_BASE_PATH, '', $path ); - if ( !BE_QUIET ) - echo "$key - $path\n"; + if ( ! BE_QUIET ) { + echo "$key - $path" . PHP_EOL; + } $phar[ $key ] = $content; } +function get_composer_versions( $current_version ) { + $composer_lock_path = WP_CLI_ROOT . '/composer.lock'; + if ( ! ( $get_composer_lock = file_get_contents( $composer_lock_path ) ) || ! ( $composer_lock = json_decode( $get_composer_lock, true ) ) ) { + fwrite( STDERR, sprintf( "Warning: Failed to read '%s'." . PHP_EOL, $composer_lock_path ) ); + return ''; + } + if ( ! isset( $composer_lock['packages'] ) ) { + fwrite( STDERR, sprintf( "Warning: No packages in '%s'." . PHP_EOL, $composer_lock_path ) ); + return ''; + } + $vendor_versions = array( implode( ' ', array( 'wp-cli/wp-cli', $current_version, date( 'c' ) ) ) ); + $missing_names = $missing_versions = $missing_references = 0; + foreach ( $composer_lock['packages'] as $package ) { + if ( isset( $package['name'] ) ) { + $vendor_version = array( $package['name'] ); + if ( isset( $package['version'] ) ) { + $vendor_version[] = $package['version']; + } else { + $vendor_version[] = 'unknown_version'; + $missing_versions++; + } + if ( isset( $package['source'] ) && isset( $package['source']['reference'] ) ) { + $vendor_version[] = $package['source']['reference']; + } elseif( isset( $package['dist'] ) && isset( $package['dist']['reference'] ) ) { + $vendor_version[] = $package['dist']['reference']; + } else { + $vendor_version[] = 'unknown_reference'; + $missing_references++; + } + $vendor_versions[] = implode( ' ', $vendor_version ); + } else { + $vendor_versions[] = implode( ' ', array( 'unknown_package', 'unknown_version', 'unknown_reference' ) ); + $missing_names++; + } + } + if ( $missing_names ) { + fwrite( STDERR, sprintf( "Warning: %d package names missing from '%s'." . PHP_EOL, $missing_names, $composer_lock_path ) ); + } + if ( $missing_versions ) { + fwrite( STDERR, sprintf( "Warning: %d package versions missing from '%s'." . PHP_EOL, $missing_versions, $composer_lock_path ) ); + } + if ( $missing_references ) { + fwrite( STDERR, sprintf( "Warning: %d package references missing from '%s'." . PHP_EOL, $missing_references, $composer_lock_path ) ); + } + return implode( "\n", $vendor_versions ); +} + if ( file_exists( DEST_PATH ) ) { unlink( DEST_PATH ); } @@ -149,6 +198,7 @@ function set_file_contents( $phar, $path, $content ) { ->in(WP_CLI_VENDOR_DIR . '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/symfony/filesystem') ->in(WP_CLI_VENDOR_DIR . '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/symfony/process') ->in(WP_CLI_VENDOR_DIR . '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/justinrainbow/json-schema') + ->exclude('demo') ->exclude('nb/oxymel/OxymelTest.php') ->exclude('composer/spdx-licenses') ->exclude('composer/composer/src/Composer/Command') @@ -235,6 +285,7 @@ function set_file_contents( $phar, $path, $content ) { } add_file( $phar, WP_CLI_VENDOR_DIR . '/rmccue/requests/library/Requests/Transport/cacert.pem' ); +set_file_contents( $phar, WP_CLI_ROOT . '/COMPOSER_VERSIONS', get_composer_versions( $current_version ) ); set_file_contents( $phar, WP_CLI_ROOT . '/VERSION', $current_version ); $phar_boot = str_replace( WP_CLI_BASE_PATH, '', WP_CLI_ROOT . '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/php/boot-phar.php' ); @@ -253,5 +304,5 @@ function set_file_contents( $phar, $path, $content ) { chmod( DEST_PATH, 0755 ); // Make executable. if ( ! BE_QUIET ) { - echo "Generated " . DEST_PATH . "\n"; + echo "Generated " . DEST_PATH . PHP_EOL; } From 07eea456f8a37dc0eba89f88b95b399d0bd289d4 Mon Sep 17 00:00:00 2001 From: Alain Schlesser Date: Tue, 30 Jan 2018 18:21:14 +0100 Subject: [PATCH 196/214] Trim links to avoid problems with unexpected whitespace --- utils/contrib-list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/contrib-list.php b/utils/contrib-list.php index 5ab696c54e..3abd62de4c 100644 --- a/utils/contrib-list.php +++ b/utils/contrib-list.php @@ -149,7 +149,7 @@ private static function get_project_milestone_pull_requests( $project, $mileston $request_url = false; // Set $request_url to 'rel="next" if present' if ( ! empty( $headers['Link'] ) ) { - $bits = explode( ',', $headers['Link'] ); + $bits = trim( explode( ',', $headers['Link'] ) ); foreach( $bits as $bit ) { if ( false !== stripos( $bit, 'rel="next"' ) ) { $hrefandrel = explode( '; ', $bit ); From 354c2a6efb10b899b9807466d2e02bb38fdf2baa Mon Sep 17 00:00:00 2001 From: Alain Schlesser Date: Wed, 31 Jan 2018 10:00:08 +0100 Subject: [PATCH 197/214] Update VERSION to "1.5.0" --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 1433486b40..bc80560fad 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.5.0-alpha +1.5.0 From 75ead3be27d8d9cae7653c0021b822ffad9b28e1 Mon Sep 17 00:00:00 2001 From: Alain Schlesser Date: Wed, 31 Jan 2018 10:00:25 +0100 Subject: [PATCH 198/214] Update README.md to latest state --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ccb14cd92b..190592ef2f 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Ongoing maintenance is -The current stable release is [version 1.4.1](https://make.wordpress.org/cli/2017/11/13/version-1-4-1-released/). For announcements, follow [@wpcli on Twitter](https://twitter.com/wpcli) or [sign up for email updates](https://make.wordpress.org/cli/subscribe/). [Check out the roadmap](https://make.wordpress.org/cli/handbook/roadmap/) for an overview of what's planned for upcoming releases. +The current stable release is [version 1.5.0](https://make.wordpress.org/cli/2018/01/31/version-1-5-0-released/). For announcements, follow [@wpcli on Twitter](https://twitter.com/wpcli) or [sign up for email updates](https://make.wordpress.org/cli/subscribe/). [Check out the roadmap](https://make.wordpress.org/cli/handbook/roadmap/) for an overview of what's planned for upcoming releases. [![Build Status](https://travis-ci.org/wp-cli/wp-cli.svg?branch=master)](https://travis-ci.org/wp-cli/wp-cli) [![Dependency Status](https://gemnasium.com/badges/github.com/wp-cli/wp-cli.svg)](https://gemnasium.com/github.com/wp-cli/wp-cli) [![Average time to resolve an issue](https://isitmaintained.com/badge/resolution/wp-cli/wp-cli.svg)](https://isitmaintained.com/project/wp-cli/wp-cli "Average time to resolve an issue") [![Percentage of issues still open](https://isitmaintained.com/badge/open/wp-cli/wp-cli.svg)](https://isitmaintained.com/project/wp-cli/wp-cli "Percentage of issues still open") @@ -73,14 +73,17 @@ If WP-CLI was installed successfully, you should see something like this when yo ```bash $ wp --info -PHP binary: /usr/bin/php5 -PHP version: 5.5.9-1ubuntu4.14 -php.ini used: /etc/php5/cli/php.ini +OS: Darwin 16.7.0 Darwin Kernel Version 16.7.0: Thu Jan 11 22:59:40 PST 2018; root:xnu-3789.73.8~1/RELEASE_X86_64 x86_64 +Shell: /bin/zsh +PHP binary: /usr/local/bin/php +PHP version: 7.0.22 +php.ini used: /etc/local/etc/php/7.0/php.ini WP-CLI root dir: /home/wp-cli/.wp-cli +WP-CLI vendor dir: /home/wp-cli/.wp-cli/vendor WP-CLI packages dir: /home/wp-cli/.wp-cli/packages/ WP-CLI global config: /home/wp-cli/.wp-cli/config.yml WP-CLI project config: -WP-CLI version: 1.4.1 +WP-CLI version: 1.5.0 ``` ### Updating From c2de10ec68d02a9bf00eefa1252c43311a88c493 Mon Sep 17 00:00:00 2001 From: Alain Schlesser Date: Thu, 1 Feb 2018 10:30:33 +0100 Subject: [PATCH 199/214] Revert "Support Phive package manager" --- utils/update-phar | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/utils/update-phar b/utils/update-phar index 0b5a37655e..e2b16973ee 100755 --- a/utils/update-phar +++ b/utils/update-phar @@ -43,9 +43,7 @@ echo $md5hash | cut -d ' ' -f 1 > $fname.md5 sha512sum $fname | cut -d ' ' -f 1 > $fname.sha512 -gpg -u alain.schlesser@gmail.com --detach-sign --output $fname.asc $fname - -git add $fname $fname.md5 $fname.sha512 $fname.asc +git add $fname $fname.md5 $fname.sha512 git commit -m "$new_commit_subj" From 1f5ec2998103bbae377ca2f1356fa1540f43df28 Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 1 Feb 2018 12:34:06 +0000 Subject: [PATCH 200/214] Bump working version to 2.0.0-alpha. --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index bc80560fad..fbffcdf951 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.5.0 +2.0.0-alpha From 44df177d9d1c71dbf47df3415e7cf73c5d334e2e Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 7 Feb 2018 16:13:14 +0000 Subject: [PATCH 201/214] Fix phpunit extractor, glob, behat tests. --- tests/test-behat-tags.php | 4 ++-- tests/test-extractor.php | 3 ++- tests/test-utils.php | 3 +++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/test-behat-tags.php b/tests/test-behat-tags.php index 11ea159de2..159226e11c 100644 --- a/tests/test-behat-tags.php +++ b/tests/test-behat-tags.php @@ -121,8 +121,8 @@ function test_behat_tags_extension() { if ( ! extension_loaded( 'imagick' ) ) { $expecteds[] = '~@require-extension-imagick'; } - if ( ! extension_loaded( 'intl' ) ) { - $expecteds[] = '~@require-extension-intl'; + if ( ! extension_loaded( 'curl' ) ) { + $expecteds[] = '~@require-extension-curl'; } $expected = '--tags=' . implode( '&&', array_merge( array( '~@github-api', '~@broken' ), $expecteds ) ); $output = exec( "cd {$this->temp_dir}; php $behat_tags" ); diff --git a/tests/test-extractor.php b/tests/test-extractor.php index 330b993902..7058a1bd10 100644 --- a/tests/test-extractor.php +++ b/tests/test-extractor.php @@ -113,7 +113,8 @@ public function test_extract_tarball() { $output = array(); $return_var = -1; // Need --force-local for Windows to avoid "C:" being interpreted as being on remote machine. - exec( Utils\esc_cmd( 'tar czvf %1$s --force-local --directory=%2$s/src wordpress', $tarball, $temp_dir ), $output, $return_var ); + $cmd = 'tar czvf %1$s' . ( Utils\is_windows() ? ' --force-local' : '' ) . ' --directory=%2$s/src wordpress'; + exec( Utils\esc_cmd( $cmd, $tarball, $temp_dir ), $output, $return_var ); $this->assertSame( 0, $return_var ); $this->assertFalse( empty( $output ) ); sort( $output ); diff --git a/tests/test-utils.php b/tests/test-utils.php index df89914b02..e3b79f51fa 100644 --- a/tests/test-utils.php +++ b/tests/test-utils.php @@ -528,13 +528,16 @@ public function testExpandGlobs( $path, $expected ) { $dir = __DIR__ . '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/data/expand_globs/'; $expected = array_map( function ( $v ) use ( $dir ) { return $dir . $v; }, $expected ); + sort( $expected ); putenv( 'WP_CLI_TEST_EXPAND_GLOBS_NO_GLOB_BRACE=0' ); $out = Utils\expand_globs( $dir . $path ); + sort( $out ); $this->assertSame( $expected, $out ); putenv( 'WP_CLI_TEST_EXPAND_GLOBS_NO_GLOB_BRACE=1' ); $out = Utils\expand_globs( $dir . $path ); + sort( $out ); $this->assertSame( $expected, $out ); putenv( false === $expand_globs_no_glob_brace ? 'WP_CLI_TEST_EXPAND_GLOBS_NO_GLOB_BRACE' : "WP_CLI_TEST_EXPAND_GLOBS_NO_GLOB_BRACE=$expand_globs_no_glob_brace" ); From d7f90a6b11d2ae83f73f8b37be5b3fd4bffcd748 Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 8 Feb 2018 13:58:33 +0000 Subject: [PATCH 202/214] Normalize Mac tar output. --- tests/test-extractor.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/test-extractor.php b/tests/test-extractor.php index 7058a1bd10..9daf4f40dd 100644 --- a/tests/test-extractor.php +++ b/tests/test-extractor.php @@ -112,12 +112,24 @@ public function test_extract_tarball() { // Create test tarball. $output = array(); $return_var = -1; - // Need --force-local for Windows to avoid "C:" being interpreted as being on remote machine. - $cmd = 'tar czvf %1$s' . ( Utils\is_windows() ? ' --force-local' : '' ) . ' --directory=%2$s/src wordpress'; + // Need --force-local for Windows to avoid "C:" being interpreted as being on remote machine, and redirect for Mac as outputs verbosely on STDERR. + $cmd = 'tar czvf %1$s' . ( Utils\is_windows() ? ' --force-local' : '' ) . ' --directory=%2$s/src wordpress 2>&1'; exec( Utils\esc_cmd( $cmd, $tarball, $temp_dir ), $output, $return_var ); $this->assertSame( 0, $return_var ); $this->assertFalse( empty( $output ) ); + + // Normalize (Mac) output. + $output = array_map( function ( $v ) { + if ( 'a ' === substr( $v, 0, 2 ) ) { + $v = substr( $v, 2 ); + } + if ( '/' !== substr( $v, -1 ) && false === strpos( $v, '.' ) ) { + $v .= '/'; + } + return $v; + }, $output ); sort( $output ); + $this->assertSame( self::recursive_scandir( $src_dir ), $output ); // Test. From 9021e95683e88ba76bdd3b63991602e968fb1ae7 Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 8 Feb 2018 15:02:51 +0000 Subject: [PATCH 203/214] Move phpunit PHP directive tests to behat. --- features/class-wp-cli.feature | 17 +++++++++++ features/utils.feature | 52 +++++++++++++++++++++++++++++++++ tests/test-utils.php | 54 ----------------------------------- tests/test-wp-cli.php | 16 ----------- 4 files changed, 69 insertions(+), 70 deletions(-) create mode 100644 features/class-wp-cli.feature create mode 100644 features/utils.feature diff --git a/features/class-wp-cli.feature b/features/class-wp-cli.feature new file mode 100644 index 0000000000..190d65ab7d --- /dev/null +++ b/features/class-wp-cli.feature @@ -0,0 +1,17 @@ +Feature: Various utilities for WP-CLI commands + + Scenario Outline: Check that `proc_open()` and `proc_close()` aren't disabled for `WP_CLI::launch()` + When I try `{INVOKE_WP_CLI_WITH_PHP_ARGS--ddisable_functions=} --skip-wordpress eval 'WP_CLI::launch( null );'` + Then STDERR should contain: + """ + Error: Cannot do 'launch': The PHP functions `proc_open()` and/or `proc_close()` are disabled + """ + And STDOUT should be empty + And the return code should be 1 + + Examples: + | func | + | proc_open | + | proc_close | + + diff --git a/features/utils.feature b/features/utils.feature new file mode 100644 index 0000000000..87a1a6af68 --- /dev/null +++ b/features/utils.feature @@ -0,0 +1,52 @@ +Feature: Utilities that do NOT depend on WordPress code + + Scenario Outline: Check that `proc_open()` and `proc_close()` aren't disabled for `Utils\run_mysql_command()` + When I try `{INVOKE_WP_CLI_WITH_PHP_ARGS--ddisable_functions=} --skip-wordpress eval 'WP_CLI\Utils\run_mysql_command( null, array() );'` + Then STDERR should contain: + """ + Error: Cannot do 'run_mysql_command': The PHP functions `proc_open()` and/or `proc_close()` are disabled + """ + And STDOUT should be empty + And the return code should be 1 + + Examples: + | func | + | proc_open | + | proc_close | + + Scenario Outline: Check that `proc_open()` and `proc_close()` aren't disabled for `Utils\launch_editor_for_input()` + When I try `{INVOKE_WP_CLI_WITH_PHP_ARGS--ddisable_functions=} --skip-wordpress eval 'WP_CLI\Utils\launch_editor_for_input( null, null );'` + Then STDERR should contain: + """ + Error: Cannot do 'launch_editor_for_input': The PHP functions `proc_open()` and/or `proc_close()` are disabled + """ + And STDOUT should be empty + And the return code should be 1 + + Examples: + | func | + | proc_open | + | proc_close | + + # INI directive `sys_temp_dir` introduced PHP 5.5.0. + @require-php-5.5 + Scenario: Check `Utils\get_temp_dir()` when `sys_temp_dir` directive set + # `sys_temp_dir` set to unwritable. + When I try `{INVOKE_WP_CLI_WITH_PHP_ARGS--dsys_temp_dir=\\tmp\\} --skip-wordpress eval 'echo WP_CLI\Utils\get_temp_dir();'` + Then STDERR should contain: + """ + Warning: Temp directory isn't writable + """ + And STDERR should contain: + """ + \tmp/ + """ + And STDOUT should be: + """ + \tmp/ + """ + And the return code should be 0 + + # `sys_temp_dir` unset. + When I run `{INVOKE_WP_CLI_WITH_PHP_ARGS--dsys_temp_dir=} --skip-wordpress eval 'echo WP_CLI\Utils\get_temp_dir();'` + Then STDOUT should match /\/$/ diff --git a/tests/test-utils.php b/tests/test-utils.php index e3b79f51fa..c3e767dd35 100644 --- a/tests/test-utils.php +++ b/tests/test-utils.php @@ -332,28 +332,6 @@ public function testNormalizeEols() { public function testGetTempDir() { $this->assertTrue( '/' === substr( Utils\get_temp_dir(), -1 ) ); - - // INI directive `sys_temp_dir` introduced PHP 5.5.0. - if ( version_compare( PHP_VERSION, '5.5.0', '>=' ) ) { - - // `sys_temp_dir` set to unwritable. - - $cmd = 'php ' . escapeshellarg( '-dsys_temp_dir=\\tmp\\' ) . ' php/boot-fs.php --skip-wordpress eval ' . escapeshellarg( 'echo WP_CLI\\Utils\\get_temp_dir();' ) . ' 2>&1'; - $output = array(); - exec( $cmd, $output ); - $output = trim( implode( "\n", $output ) ); - $this->assertTrue( false !== strpos( $output, 'Warning' ) ); - $this->assertTrue( false !== strpos( $output, 'writable' ) ); - $this->assertTrue( false !== strpos( $output, '\\tmp/' ) ); - - // `sys_temp_dir` unset. - - $cmd = 'php ' . escapeshellarg( '-dsys_temp_dir=' ) . ' php/boot-fs.php --skip-wordpress eval ' . escapeshellarg( 'echo WP_CLI\\Utils\\get_temp_dir();' ) . ' 2>&1'; - $output = array(); - exec( $cmd, $output ); - $output = trim( implode( "\n", $output ) ); - $this->assertTrue( '/' === substr( $output, -1 ) ); - } } public function testHttpRequestBadAddress() { @@ -451,38 +429,6 @@ public function testHttpRequestBadCAcert() { $class_wp_cli_logger->setValue( $prev_logger ); } - public function testRunMysqlCommandProcDisabled() { - $err_msg = 'Error: Cannot do \'run_mysql_command\': The PHP functions `proc_open()` and/or `proc_close()` are disabled'; - - $cmd = 'php -ddisable_functions=proc_open php/boot-fs.php --skip-wordpress eval ' . escapeshellarg( 'WP_CLI\\Utils\\run_mysql_command( null, array() );' ) . ' 2>&1'; - $output = array(); - exec( $cmd, $output ); - $output = trim( implode( "\n", $output ) ); - $this->assertTrue( false !== strpos( $output, $err_msg ) ); - - $cmd = 'php -ddisable_functions=proc_close php/boot-fs.php --skip-wordpress eval ' . escapeshellarg( 'WP_CLI\\Utils\\run_mysql_command( null, array() );' ) . ' 2>&1'; - $output = array(); - exec( $cmd, $output ); - $output = trim( implode( "\n", $output ) ); - $this->assertTrue( false !== strpos( $output, $err_msg ) ); - } - - public function testLaunchEditorForInputProcDisabled() { - $err_msg = 'Error: Cannot do \'launch_editor_for_input\': The PHP functions `proc_open()` and/or `proc_close()` are disabled'; - - $cmd = 'php -ddisable_functions=proc_open php/boot-fs.php --skip-wordpress eval ' . escapeshellarg( 'WP_CLI\\Utils\\launch_editor_for_input( null, null );' ) . ' 2>&1'; - $output = array(); - exec( $cmd, $output ); - $output = trim( implode( "\n", $output ) ); - $this->assertTrue( false !== strpos( $output, $err_msg ) ); - - $cmd = 'php -ddisable_functions=proc_close php/boot-fs.php --skip-wordpress eval ' . escapeshellarg( 'WP_CLI\\Utils\\launch_editor_for_input( null, null );' ) . ' 2>&1'; - $output = array(); - exec( $cmd, $output ); - $output = trim( implode( "\n", $output ) ); - $this->assertTrue( false !== strpos( $output, $err_msg ) ); - } - /** * @dataProvider dataPastTenseVerb */ diff --git a/tests/test-wp-cli.php b/tests/test-wp-cli.php index 209fef8c73..a2a68f83bd 100644 --- a/tests/test-wp-cli.php +++ b/tests/test-wp-cli.php @@ -2,22 +2,6 @@ class WP_CLI_Test extends PHPUnit_Framework_TestCase { - public function testLaunchProcDisabled() { - $err_msg = 'Error: Cannot do \'launch\': The PHP functions `proc_open()` and/or `proc_close()` are disabled'; - - $cmd = 'php -ddisable_functions=proc_open php/boot-fs.php --skip-wordpress eval ' . escapeshellarg( 'WP_CLI::launch( null );' ) . ' 2>&1'; - $output = array(); - exec( $cmd, $output ); - $output = trim( implode( "\n", $output ) ); - $this->assertTrue( false !== strpos( $output, $err_msg ) ); - - $cmd = 'php -ddisable_functions=proc_close php/boot-fs.php --skip-wordpress eval ' . escapeshellarg( 'WP_CLI::launch( null );' ) . ' 2>&1'; - $output = array(); - exec( $cmd, $output ); - $output = trim( implode( "\n", $output ) ); - $this->assertTrue( false !== strpos( $output, $err_msg ) ); - } - public function testGetPHPBinary() { $this->assertSame( WP_CLI\Utils\get_php_binary(), WP_CLI::get_php_binary() ); } From ca1a8437417c2871c30ffa09dc18f749fb05c902 Mon Sep 17 00:00:00 2001 From: Thrijith Thankachan Date: Sat, 10 Feb 2018 00:11:38 +0530 Subject: [PATCH 204/214] update code as suggested to get info in headerless table format --- php/commands/src/CLI_Command.php | 42 +++++++++++++++----------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index 2f864095f8..1fd25c59d7 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -130,33 +130,29 @@ public function info( $_, $assoc_args ) { WP_CLI::line( json_encode( $info ) ); } else { + $info = array( - 'OS' => $system_os, - 'Shell' => $shell, - 'PHP binary' => $php_bin, - 'PHP version' => PHP_VERSION, - 'php.ini used' => get_cfg_var( 'cfg_file_path' ), - 'WP-CLI root dir' => WP_CLI_ROOT, - 'WP-CLI vendor dir' => WP_CLI_VENDOR_DIR, - 'WP_CLI phar path' => ( defined( 'WP_CLI_PHAR_PATH' ) ? WP_CLI_PHAR_PATH : '' ), - 'WP-CLI packages dir' => $packages_dir, - 'WP-CLI global config' => $runner->global_config_path, - 'WP-CLI project config' => $runner->project_config_path, - 'WP-CLI version' => WP_CLI_VERSION, + array( 'OS', $system_os ), + array( 'Shell', $shell ), + array( 'PHP binary', $php_bin ), + array( 'PHP version', PHP_VERSION ), + array( 'php.ini used', get_cfg_var( 'cfg_file_path' ) ), + array( 'WP-CLI root dir', WP_CLI_ROOT ), + array( 'WP-CLI vendor dir', WP_CLI_VENDOR_DIR ), + array( 'WP_CLI phar path', ( defined( 'WP_CLI_PHAR_PATH' ) ? WP_CLI_PHAR_PATH : '' ) ), + array( 'WP-CLI packages dir', $packages_dir ), + array( 'WP-CLI global config', $runner->global_config_path ), + array( 'WP-CLI project config', $runner->project_config_path ), + array( 'WP-CLI version', WP_CLI_VERSION ), ); - $items = array(); - foreach ( $info as $key => $value ) { - $info_format = array( - 'key' => '', - 'value' => '', - ); - $info_format['key'] = $key; - $info_format['value'] = $value; - $items[] = $info_format; + $info_table = new \cli\Table(); + $info_table->setRows( $info ); + $info_table->setRenderer( new \cli\table\Ascii() ); + $lines = array_slice( $info_table->getDisplayLines(), 2 ); + foreach ( $lines as $line ) { + \WP_CLI::line( $line ); } - - WP_CLI\Utils\format_items( 'table', $items, array( 'key', 'value' ) ); } } From ba45ff2424ac3befe93f036ec000e8ef6fcff350 Mon Sep 17 00:00:00 2001 From: Alain Schlesser Date: Wed, 14 Feb 2018 15:49:27 +0100 Subject: [PATCH 205/214] Update wp-cli/package-command to v1.0.12 --- composer.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.lock b/composer.lock index 96e350934c..4530baeb10 100644 --- a/composer.lock +++ b/composer.lock @@ -2381,16 +2381,16 @@ }, { "name": "wp-cli/package-command", - "version": "v1.0.11", + "version": "v1.0.12", "source": { "type": "git", "url": "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/wp-cli/package-command.git", - "reference": "b0f0e59a1d174c80bd11833b2f4a650d835d7a29" + "reference": "bb8b02d9ba1cded95564767000738ceaefbc885b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/package-command/zipball/b0f0e59a1d174c80bd11833b2f4a650d835d7a29", - "reference": "b0f0e59a1d174c80bd11833b2f4a650d835d7a29", + "url": "https://api.github.com/repos/wp-cli/package-command/zipball/bb8b02d9ba1cded95564767000738ceaefbc885b", + "reference": "bb8b02d9ba1cded95564767000738ceaefbc885b", "shasum": "" }, "require": { @@ -2436,7 +2436,7 @@ ], "description": "Lists, installs, and removes WP-CLI packages.", "homepage": "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/wp-cli/package-command", - "time": "2018-01-29T02:32:25+00:00" + "time": "2018-02-09T09:55:33+00:00" }, { "name": "wp-cli/php-cli-tools", From 39d35ef8dd1984d2fb80b9046e9eaccdbbf7717c Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 19 Feb 2018 17:05:19 +0000 Subject: [PATCH 206/214] Empty domain in framework test after get_sites_by_path change. --- features/framework.feature | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/features/framework.feature b/features/framework.feature index 9908eb71ea..116f8073b8 100644 --- a/features/framework.feature +++ b/features/framework.feature @@ -327,6 +327,9 @@ Feature: Load WP-CLI """ Given "define( 'DOMAIN_CURRENT_SITE', 'example.org' );" replaced with " " in the wp-config.php file + # WP < 5.0 have bug which will not find a blog given an empty domain unless wp_blogs.domain empty which was (partly) addressed by https://core.trac.wordpress.org/ticket/42299 + # So empty wp_blogs.domain to make behavior consistent across WP versions. + And I run `wp db query 'UPDATE wp_blogs SET domain = NULL'` When I run `cat wp-config.php` Then STDOUT should not contain: @@ -334,12 +337,16 @@ Feature: Load WP-CLI DOMAIN_CURRENT_SITE """ - When I try `wp option get home` - Then STDERR should be: + # This will work as finds blog with empty domain and thus uses `home` option. + When I run `wp option get home` + Then STDOUT should be: """ - Error: Site not found. Define DOMAIN_CURRENT_SITE in 'wp-config.php' or use `--url=` to override. + http://example.com """ + # Undo above. + Given I run `wp db query 'UPDATE wp_blogs SET domain = "example.com"'` + When I try `wp option get home --url=example.io` Then STDERR should be: """ From c88a7185f14c72a1cbcb443b626783296ea4bc99 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 19 Feb 2018 22:33:32 +0000 Subject: [PATCH 207/214] Debug env. --- ci/test.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci/test.sh b/ci/test.sh index f4bc5ced89..3349d61cfd 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -2,6 +2,8 @@ set -ex +env + # Run the unit tests phpunit From 31df86c2f0d3a77f8e92eb7528401062166663f3 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 19 Feb 2018 23:20:32 +0000 Subject: [PATCH 208/214] Use WP_CLI\Utils in when; remove : from update check; strip wp-config-transformer. --- ci/test.sh | 2 - composer.lock | 208 +++++++++++++------------- features/bootstrap/FeatureContext.php | 2 +- features/steps/when.php | 3 +- php/commands/src/CLI_Command.php | 2 +- utils/make-phar.php | 2 +- 6 files changed, 110 insertions(+), 109 deletions(-) diff --git a/ci/test.sh b/ci/test.sh index 3349d61cfd..f4bc5ced89 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -2,8 +2,6 @@ set -ex -env - # Run the unit tests phpunit diff --git a/composer.lock b/composer.lock index 3e02227ee0..4b9b2ca41f 100644 --- a/composer.lock +++ b/composer.lock @@ -64,35 +64,35 @@ }, { "name": "composer/composer", - "version": "1.5.6", + "version": "1.6.3", "source": { "type": "git", "url": "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/composer/composer.git", - "reference": "4f7f9c12753ec43f1e4629e2a71cabe81f2a4eab" + "reference": "88a69fda0f2187ad8714cedffd7a8872dceaa4c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/4f7f9c12753ec43f1e4629e2a71cabe81f2a4eab", - "reference": "4f7f9c12753ec43f1e4629e2a71cabe81f2a4eab", + "url": "https://api.github.com/repos/composer/composer/zipball/88a69fda0f2187ad8714cedffd7a8872dceaa4c2", + "reference": "88a69fda0f2187ad8714cedffd7a8872dceaa4c2", "shasum": "" }, "require": { "composer/ca-bundle": "^1.0", "composer/semver": "^1.0", - "composer/spdx-licenses": "^1.0", + "composer/spdx-licenses": "^1.2", "justinrainbow/json-schema": "^3.0 || ^4.0 || ^5.0", "php": "^5.3.2 || ^7.0", "psr/log": "^1.0", "seld/cli-prompt": "^1.0", "seld/jsonlint": "^1.4", "seld/phar-utils": "^1.0", - "symfony/console": "^2.7 || ^3.0", - "symfony/filesystem": "^2.7 || ^3.0", - "symfony/finder": "^2.7 || ^3.0", - "symfony/process": "^2.7 || ^3.0" + "symfony/console": "^2.7 || ^3.0 || ^4.0", + "symfony/filesystem": "^2.7 || ^3.0 || ^4.0", + "symfony/finder": "^2.7 || ^3.0 || ^4.0", + "symfony/process": "^2.7 || ^3.0 || ^4.0" }, "require-dev": { - "phpunit/phpunit": "^4.5 || ^5.0.5", + "phpunit/phpunit": "^4.8.35 || ^5.7", "phpunit/phpunit-mock-objects": "^2.3 || ^3.0" }, "suggest": { @@ -106,7 +106,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.5-dev" + "dev-master": "1.6-dev" } }, "autoload": { @@ -137,7 +137,7 @@ "dependency", "package" ], - "time": "2017-12-18T11:09:18+00:00" + "time": "2018-01-31T15:28:18+00:00" }, { "name": "composer/semver", @@ -203,23 +203,23 @@ }, { "name": "composer/spdx-licenses", - "version": "1.1.6", + "version": "1.3.0", "source": { "type": "git", "url": "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/composer/spdx-licenses.git", - "reference": "2603a0d7ddc00a015deb576fa5297ca43dee6b1c" + "reference": "7e111c50db92fa2ced140f5ba23b4e261bc77a30" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/2603a0d7ddc00a015deb576fa5297ca43dee6b1c", - "reference": "2603a0d7ddc00a015deb576fa5297ca43dee6b1c", + "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/7e111c50db92fa2ced140f5ba23b4e261bc77a30", + "reference": "7e111c50db92fa2ced140f5ba23b4e261bc77a30", "shasum": "" }, "require": { "php": "^5.3.2 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "^4.5 || ^5.0.5", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5", "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" }, "type": "library", @@ -260,20 +260,20 @@ "spdx", "validator" ], - "time": "2017-04-03T19:08:52+00:00" + "time": "2018-01-31T13:17:27+00:00" }, { "name": "justinrainbow/json-schema", - "version": "5.2.6", + "version": "5.2.7", "source": { "type": "git", "url": "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/justinrainbow/json-schema.git", - "reference": "d283e11b6e14c6f4664cf080415c4341293e5bbd" + "reference": "8560d4314577199ba51bf2032f02cd1315587c23" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/d283e11b6e14c6f4664cf080415c4341293e5bbd", - "reference": "d283e11b6e14c6f4664cf080415c4341293e5bbd", + "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/8560d4314577199ba51bf2032f02cd1315587c23", + "reference": "8560d4314577199ba51bf2032f02cd1315587c23", "shasum": "" }, "require": { @@ -282,7 +282,7 @@ "require-dev": { "friendsofphp/php-cs-fixer": "^2.1", "json-schema/json-schema-test-suite": "1.2.0", - "phpunit/phpunit": "^4.8.22" + "phpunit/phpunit": "^4.8.35" }, "bin": [ "bin/validate-json" @@ -326,7 +326,7 @@ "json", "schema" ], - "time": "2017-10-21T13:15:38+00:00" + "time": "2018-02-14T22:26:30+00:00" }, { "name": "mustache/mustache", @@ -606,23 +606,23 @@ }, { "name": "seld/jsonlint", - "version": "1.6.2", + "version": "1.7.1", "source": { "type": "git", "url": "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/Seldaek/jsonlint.git", - "reference": "7a30649c67ee0d19faacfd9fa2cfb6cc032d9b19" + "reference": "d15f59a67ff805a44c50ea0516d2341740f81a38" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/7a30649c67ee0d19faacfd9fa2cfb6cc032d9b19", - "reference": "7a30649c67ee0d19faacfd9fa2cfb6cc032d9b19", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/d15f59a67ff805a44c50ea0516d2341740f81a38", + "reference": "d15f59a67ff805a44c50ea0516d2341740f81a38", "shasum": "" }, "require": { "php": "^5.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "^4.5" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" }, "bin": [ "bin/jsonlint" @@ -651,7 +651,7 @@ "parser", "validator" ], - "time": "2017-11-30T15:34:22+00:00" + "time": "2018-01-24T12:46:19+00:00" }, { "name": "seld/phar-utils", @@ -699,16 +699,16 @@ }, { "name": "symfony/config", - "version": "v2.8.32", + "version": "v2.8.34", "source": { "type": "git", "url": "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/symfony/config.git", - "reference": "f4f3f1d7090c464434bbbc3e8aa2b41149c59196" + "reference": "17605ff58313d9fe94e507620a399721fc347b6d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/f4f3f1d7090c464434bbbc3e8aa2b41149c59196", - "reference": "f4f3f1d7090c464434bbbc3e8aa2b41149c59196", + "url": "https://api.github.com/repos/symfony/config/zipball/17605ff58313d9fe94e507620a399721fc347b6d", + "reference": "17605ff58313d9fe94e507620a399721fc347b6d", "shasum": "" }, "require": { @@ -751,20 +751,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2017-11-07T11:56:23+00:00" + "time": "2018-01-21T19:03:25+00:00" }, { "name": "symfony/console", - "version": "v2.8.32", + "version": "v2.8.34", "source": { "type": "git", "url": "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/symfony/console.git", - "reference": "46270f1ca44f08ebc134ce120fd2c2baf5fd63de" + "reference": "162ca7d0ea597599967aa63b23418e747da0896b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/46270f1ca44f08ebc134ce120fd2c2baf5fd63de", - "reference": "46270f1ca44f08ebc134ce120fd2c2baf5fd63de", + "url": "https://api.github.com/repos/symfony/console/zipball/162ca7d0ea597599967aa63b23418e747da0896b", + "reference": "162ca7d0ea597599967aa63b23418e747da0896b", "shasum": "" }, "require": { @@ -812,20 +812,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2017-11-29T09:33:18+00:00" + "time": "2018-01-29T08:54:45+00:00" }, { "name": "symfony/debug", - "version": "v2.8.32", + "version": "v2.8.34", "source": { "type": "git", "url": "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/symfony/debug.git", - "reference": "e72a0340dc2e273b3c4398d8eef9157ba51d8b95" + "reference": "35e36287fc0fdc8a08f70efcd4865ae6d8a6ee55" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/e72a0340dc2e273b3c4398d8eef9157ba51d8b95", - "reference": "e72a0340dc2e273b3c4398d8eef9157ba51d8b95", + "url": "https://api.github.com/repos/symfony/debug/zipball/35e36287fc0fdc8a08f70efcd4865ae6d8a6ee55", + "reference": "35e36287fc0fdc8a08f70efcd4865ae6d8a6ee55", "shasum": "" }, "require": { @@ -869,20 +869,20 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2017-11-19T19:05:05+00:00" + "time": "2018-01-18T22:12:33+00:00" }, { "name": "symfony/dependency-injection", - "version": "v2.8.32", + "version": "v2.8.34", "source": { "type": "git", "url": "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/symfony/dependency-injection.git", - "reference": "d3e81e5402c38500770eb5595d78a6d85ea9e412" + "reference": "91ad61e6f140b050eba4aa39bc52eece713f2a71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/d3e81e5402c38500770eb5595d78a6d85ea9e412", - "reference": "d3e81e5402c38500770eb5595d78a6d85ea9e412", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/91ad61e6f140b050eba4aa39bc52eece713f2a71", + "reference": "91ad61e6f140b050eba4aa39bc52eece713f2a71", "shasum": "" }, "require": { @@ -932,20 +932,20 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2017-11-23T11:13:33+00:00" + "time": "2018-01-29T08:55:23+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v2.8.32", + "version": "v2.8.34", "source": { "type": "git", "url": "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/symfony/event-dispatcher.git", - "reference": "b59aacf238fadda50d612c9de73b74751872a903" + "reference": "d64be24fc1eba62f9daace8a8918f797fc8e87cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b59aacf238fadda50d612c9de73b74751872a903", - "reference": "b59aacf238fadda50d612c9de73b74751872a903", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d64be24fc1eba62f9daace8a8918f797fc8e87cc", + "reference": "d64be24fc1eba62f9daace8a8918f797fc8e87cc", "shasum": "" }, "require": { @@ -992,20 +992,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2017-11-05T15:25:56+00:00" + "time": "2018-01-03T07:36:31+00:00" }, { "name": "symfony/filesystem", - "version": "v2.8.32", + "version": "v2.8.34", "source": { "type": "git", "url": "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/symfony/filesystem.git", - "reference": "15ceb6736a9eebd0d99f9e05a62296ab6ce1cf2b" + "reference": "1f4e8351e0196562f5e8ec584baeceeb8e2e92f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/15ceb6736a9eebd0d99f9e05a62296ab6ce1cf2b", - "reference": "15ceb6736a9eebd0d99f9e05a62296ab6ce1cf2b", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/1f4e8351e0196562f5e8ec584baeceeb8e2e92f6", + "reference": "1f4e8351e0196562f5e8ec584baeceeb8e2e92f6", "shasum": "" }, "require": { @@ -1041,20 +1041,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2017-11-19T18:39:05+00:00" + "time": "2018-01-03T07:36:31+00:00" }, { "name": "symfony/finder", - "version": "v2.8.32", + "version": "v2.8.34", "source": { "type": "git", "url": "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/symfony/finder.git", - "reference": "efeceae6a05a9b2fcb3391333f1d4a828ff44ab8" + "reference": "9786ccb6a1f94a89ae18fc6a1b68de1f070823ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/efeceae6a05a9b2fcb3391333f1d4a828ff44ab8", - "reference": "efeceae6a05a9b2fcb3391333f1d4a828ff44ab8", + "url": "https://api.github.com/repos/symfony/finder/zipball/9786ccb6a1f94a89ae18fc6a1b68de1f070823ed", + "reference": "9786ccb6a1f94a89ae18fc6a1b68de1f070823ed", "shasum": "" }, "require": { @@ -1090,20 +1090,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2017-11-05T15:25:56+00:00" + "time": "2018-01-29T08:54:45+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.6.0", + "version": "v1.7.0", "source": { "type": "git", "url": "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/symfony/polyfill-mbstring.git", - "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296" + "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", - "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b", + "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b", "shasum": "" }, "require": { @@ -1115,7 +1115,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6-dev" + "dev-master": "1.7-dev" } }, "autoload": { @@ -1149,20 +1149,20 @@ "portable", "shim" ], - "time": "2017-10-11T12:05:26+00:00" + "time": "2018-01-30T19:27:44+00:00" }, { "name": "symfony/process", - "version": "v2.8.32", + "version": "v2.8.34", "source": { "type": "git", "url": "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/symfony/process.git", - "reference": "d25449e031f600807949aab7cadbf267712f4eee" + "reference": "905efe90024caa75a2fc93f54e14b26f2a099d96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/d25449e031f600807949aab7cadbf267712f4eee", - "reference": "d25449e031f600807949aab7cadbf267712f4eee", + "url": "https://api.github.com/repos/symfony/process/zipball/905efe90024caa75a2fc93f54e14b26f2a099d96", + "reference": "905efe90024caa75a2fc93f54e14b26f2a099d96", "shasum": "" }, "require": { @@ -1198,20 +1198,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2017-11-05T15:25:56+00:00" + "time": "2018-01-29T08:54:45+00:00" }, { "name": "symfony/translation", - "version": "v2.8.32", + "version": "v2.8.34", "source": { "type": "git", "url": "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/symfony/translation.git", - "reference": "0c63d56516c4c4c323228ca6348eadb7c91b1daf" + "reference": "72235c1121ae282254e897e342c001f3d4bb7e8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/0c63d56516c4c4c323228ca6348eadb7c91b1daf", - "reference": "0c63d56516c4c4c323228ca6348eadb7c91b1daf", + "url": "https://api.github.com/repos/symfony/translation/zipball/72235c1121ae282254e897e342c001f3d4bb7e8d", + "reference": "72235c1121ae282254e897e342c001f3d4bb7e8d", "shasum": "" }, "require": { @@ -1262,20 +1262,20 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2017-11-07T14:08:47+00:00" + "time": "2018-01-18T13:56:23+00:00" }, { "name": "symfony/yaml", - "version": "v2.8.32", + "version": "v2.8.34", "source": { "type": "git", "url": "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/symfony/yaml.git", - "reference": "968ef42161e4bc04200119da473077f9e7015128" + "reference": "be720fcfae4614df204190d57795351059946a77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/968ef42161e4bc04200119da473077f9e7015128", - "reference": "968ef42161e4bc04200119da473077f9e7015128", + "url": "https://api.github.com/repos/symfony/yaml/zipball/be720fcfae4614df204190d57795351059946a77", + "reference": "be720fcfae4614df204190d57795351059946a77", "shasum": "" }, "require": { @@ -1311,7 +1311,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-11-29T09:33:18+00:00" + "time": "2018-01-03T07:36:31+00:00" }, { "name": "wp-cli/autoload-splitter", @@ -3543,12 +3543,12 @@ "source": { "type": "git", "url": "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/Roave/SecurityAdvisories.git", - "reference": "0703d860f83775029738dc4a519301e8e3d81853" + "reference": "94230db36bded9d164ffccabcb38c67eedd63595" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/0703d860f83775029738dc4a519301e8e3d81853", - "reference": "0703d860f83775029738dc4a519301e8e3d81853", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/94230db36bded9d164ffccabcb38c67eedd63595", + "reference": "94230db36bded9d164ffccabcb38c67eedd63595", "shasum": "" }, "conflict": { @@ -3562,9 +3562,10 @@ "codeigniter/framework": "<=3.0.6", "composer/composer": "<=1.0.0-alpha11", "contao-components/mediaelement": ">=2.14.2,<2.21.1", - "contao/core": ">=2,<3.5.31", + "contao/core": ">=2,<3.5.32", "contao/core-bundle": ">=4,<4.4.8", "contao/listing-bundle": ">=4,<4.4.8", + "contao/newsletter-bundle": ">=4,<4.1", "doctrine/annotations": ">=1,<1.2.7", "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2", "doctrine/common": ">=2,<2.4.3|>=2.5,<2.5.1", @@ -3597,18 +3598,19 @@ "onelogin/php-saml": "<2.10.4", "oro/crm": ">=1.7,<1.7.4", "oro/platform": ">=1.7,<1.7.4", + "padraic/humbug_get_contents": "<1.1.2", "phpmailer/phpmailer": ">=5,<5.2.24", "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5.0.10,<5.6.3", - "phpxmlrpc/extras": "<6.0.1", + "phpxmlrpc/extras": "<0.6.1", "pusher/pusher-php-server": "<2.2.1", "sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9", - "shopware/shopware": "<5.2.25", + "shopware/shopware": "<5.3.7", "silverstripe/cms": ">=3,<=3.0.11|>=3.1,<3.1.11", "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", "silverstripe/framework": ">=3,<3.3", "silverstripe/userforms": "<3", - "simplesamlphp/saml2": "<1.8.1|>=1.9,<1.9.1|>=1.10,<1.10.3|>=2,<2.3.3", - "simplesamlphp/simplesamlphp": "<1.14.16", + "simplesamlphp/saml2": "<1.10.4|>=2,<2.3.5|>=3,<3.1.1", + "simplesamlphp/simplesamlphp": "<1.15.2", "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1", "socalnick/scn-social-auth": "<1.15.2", "squizlabs/php_codesniffer": ">=1,<2.8.1", @@ -3638,9 +3640,9 @@ "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4", "willdurand/js-translation-bundle": "<2.1.1", "yiisoft/yii": ">=1.1.14,<1.1.15", - "yiisoft/yii2": "<2.0.5", + "yiisoft/yii2": "<2.0.14", "yiisoft/yii2-bootstrap": "<2.0.4", - "yiisoft/yii2-dev": "<2.0.4", + "yiisoft/yii2-dev": "<2.0.14", "yiisoft/yii2-gii": "<2.0.4", "yiisoft/yii2-jui": "<2.0.4", "zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3", @@ -3680,7 +3682,7 @@ } ], "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", - "time": "2017-12-24T19:52:27+00:00" + "time": "2018-02-19T09:31:21+00:00" }, { "name": "squizlabs/php_codesniffer", @@ -3762,16 +3764,16 @@ }, { "name": "wimg/php-compatibility", - "version": "8.0.1", + "version": "8.1.0", "source": { "type": "git", "url": "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/wimg/PHPCompatibility.git", - "reference": "4c4385fb891dff0501009670f988d4fe36785249" + "reference": "4ac01e4fe8faaa4f8d3b3cd06ea92e5418ce472e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wimg/PHPCompatibility/zipball/4c4385fb891dff0501009670f988d4fe36785249", - "reference": "4c4385fb891dff0501009670f988d4fe36785249", + "url": "https://api.github.com/repos/wimg/PHPCompatibility/zipball/4ac01e4fe8faaa4f8d3b3cd06ea92e5418ce472e", + "reference": "4ac01e4fe8faaa4f8d3b3cd06ea92e5418ce472e", "shasum": "" }, "require": { @@ -3785,7 +3787,7 @@ "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0" }, "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1" + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3" }, "type": "phpcodesniffer-standard", "autoload": { @@ -3810,7 +3812,7 @@ "phpcs", "standards" ], - "time": "2017-08-07T19:39:05+00:00" + "time": "2017-12-27T21:58:38+00:00" }, { "name": "wp-coding-standards/wpcs", diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 99c26294f0..54073d8653 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -129,7 +129,7 @@ private static function get_process_env_variables() { 'BEHAT_RUN' => 1, 'HOME' => Utils\get_temp_dir() . 'wp-cli-home', ); - $env_keys = array( 'GITHUB_TOKEN', 'SYSTEMROOT', 'TERM', 'TMP', 'TRAVIS_BUILD_DIR', 'WP_CLI_CONFIG_PATH', 'WP_CLI_PHP', 'WP_CLI_PHP_ARGS', 'WP_CLI_PHP_USED' ); + $env_keys = array( 'GITHUB_TOKEN', 'SHELL', 'SYSTEMROOT', 'TERM', 'TMP', 'TRAVIS_BUILD_DIR', 'WP_CLI_CONFIG_PATH', 'WP_CLI_PHP', 'WP_CLI_PHP_ARGS', 'WP_CLI_PHP_USED' ); foreach ( $env_keys as $env_key ) { if ( $env_val = getenv( $env_key ) ) { $env[ $env_key ] = $env_val; diff --git a/features/steps/when.php b/features/steps/when.php index 911c163425..d60216407c 100644 --- a/features/steps/when.php +++ b/features/steps/when.php @@ -2,7 +2,8 @@ use Behat\Gherkin\Node\PyStringNode, Behat\Gherkin\Node\TableNode, - WP_CLI\Process; + WP_CLI\Process, + WP_CLI\Utils; function invoke_proc( $proc, $mode ) { $map = array( diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php index e0e4b4d2b6..6465e6e613 100644 --- a/php/commands/src/CLI_Command.php +++ b/php/commands/src/CLI_Command.php @@ -339,7 +339,7 @@ public function update( $_, $assoc_args ) { $php_binary = Utils\get_php_binary(); $process = WP_CLI\Process::create( "{$php_binary} $temp --info {$allow_root}" ); $result = $process->run(); - if ( 0 !== $result->return_code || false === stripos( $result->stdout, 'WP-CLI version:' ) ) { + if ( 0 !== $result->return_code || false === stripos( $result->stdout, 'WP-CLI version' ) ) { $multi_line = explode( PHP_EOL, $result->stderr ); WP_CLI::error_multi_line( $multi_line ); WP_CLI::error( 'The downloaded PHAR is broken, try running wp cli update again.' ); diff --git a/utils/make-phar.php b/utils/make-phar.php index ddb9a3e96c..9afac4a606 100644 --- a/utils/make-phar.php +++ b/utils/make-phar.php @@ -86,7 +86,7 @@ function add_file( $phar, $path ) { '\/phpunit\/', '\/nb\/oxymel\/', '-command\/src\/', - '\/wp-cli\/[^\n]+?-command\/', + '\/wp-cli\/(?:[^\n]+?-command|wp-config-transformer)\/', '\/symfony\/(?!finder|polyfill-mbstring)[^\/]+\/', '\/(?:dealerdirect|squizlabs|wimg)\/', ); From b6ed25451ccbe16020231af9e29c7f5f0736ceee Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 19 Feb 2018 23:42:41 +0000 Subject: [PATCH 209/214] Remove php-compatibility sniff. --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index d82871de47..25b69315fa 100644 --- a/composer.json +++ b/composer.json @@ -70,7 +70,6 @@ "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3", "phpunit/phpunit": "3.7.*", "roave/security-advisories": "dev-master", - "wimg/php-compatibility": "^8.0", "wp-coding-standards/wpcs": "^0.13.1" }, "suggest": { From e7acaa10e36ac4885d8fe84d0182c40cfe79c83f Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 19 Feb 2018 23:46:38 +0000 Subject: [PATCH 210/214] Update composer.lock. --- composer.lock | 54 +-------------------------------------------------- 1 file changed, 1 insertion(+), 53 deletions(-) diff --git a/composer.lock b/composer.lock index 4b9b2ca41f..c1826a0df5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "36f8e11f5ba78726579607300deee9a7", + "content-hash": "0334df0348059a5e489e10a07927b637", "packages": [ { "name": "composer/ca-bundle", @@ -3762,58 +3762,6 @@ ], "time": "2017-05-22T02:43:20+00:00" }, - { - "name": "wimg/php-compatibility", - "version": "8.1.0", - "source": { - "type": "git", - "url": "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/wimg/PHPCompatibility.git", - "reference": "4ac01e4fe8faaa4f8d3b3cd06ea92e5418ce472e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wimg/PHPCompatibility/zipball/4ac01e4fe8faaa4f8d3b3cd06ea92e5418ce472e", - "reference": "4ac01e4fe8faaa4f8d3b3cd06ea92e5418ce472e", - "shasum": "" - }, - "require": { - "php": ">=5.3", - "squizlabs/php_codesniffer": "^2.2 || ^3.0.2" - }, - "conflict": { - "squizlabs/php_codesniffer": "2.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0" - }, - "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3" - }, - "type": "phpcodesniffer-standard", - "autoload": { - "psr-4": { - "PHPCompatibility\\": "PHPCompatibility/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0" - ], - "authors": [ - { - "name": "Wim Godden", - "role": "lead" - } - ], - "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP version compatibility.", - "homepage": "http://techblog.wimgodden.be/tag/codesniffer/", - "keywords": [ - "compatibility", - "phpcs", - "standards" - ], - "time": "2017-12-27T21:58:38+00:00" - }, { "name": "wp-coding-standards/wpcs", "version": "0.13.1", From 8f18cfbc9210ca5dd9da8aa6fdf00c3ca1c67c25 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 19 Feb 2018 23:47:02 +0000 Subject: [PATCH 211/214] Remove composer.lock. --- composer.lock | 3820 ------------------------------------------------- 1 file changed, 3820 deletions(-) delete mode 100644 composer.lock diff --git a/composer.lock b/composer.lock deleted file mode 100644 index c1826a0df5..0000000000 --- a/composer.lock +++ /dev/null @@ -1,3820 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", - "This file is @generated automatically" - ], - "content-hash": "0334df0348059a5e489e10a07927b637", - "packages": [ - { - "name": "composer/ca-bundle", - "version": "1.1.0", - "source": { - "type": "git", - "url": "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/composer/ca-bundle.git", - "reference": "943b2c4fcad1ef178d16a713c2468bf7e579c288" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/943b2c4fcad1ef178d16a713c2468bf7e579c288", - "reference": "943b2c4fcad1ef178d16a713c2468bf7e579c288", - "shasum": "" - }, - "require": { - "ext-openssl": "*", - "ext-pcre": "*", - "php": "^5.3.2 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35", - "psr/log": "^1.0", - "symfony/process": "^2.5 || ^3.0 || ^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\CaBundle\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", - "keywords": [ - "cabundle", - "cacert", - "certificate", - "ssl", - "tls" - ], - "time": "2017-11-29T09:37:33+00:00" - }, - { - "name": "composer/composer", - "version": "1.6.3", - "source": { - "type": "git", - "url": "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/composer/composer.git", - "reference": "88a69fda0f2187ad8714cedffd7a8872dceaa4c2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/88a69fda0f2187ad8714cedffd7a8872dceaa4c2", - "reference": "88a69fda0f2187ad8714cedffd7a8872dceaa4c2", - "shasum": "" - }, - "require": { - "composer/ca-bundle": "^1.0", - "composer/semver": "^1.0", - "composer/spdx-licenses": "^1.2", - "justinrainbow/json-schema": "^3.0 || ^4.0 || ^5.0", - "php": "^5.3.2 || ^7.0", - "psr/log": "^1.0", - "seld/cli-prompt": "^1.0", - "seld/jsonlint": "^1.4", - "seld/phar-utils": "^1.0", - "symfony/console": "^2.7 || ^3.0 || ^4.0", - "symfony/filesystem": "^2.7 || ^3.0 || ^4.0", - "symfony/finder": "^2.7 || ^3.0 || ^4.0", - "symfony/process": "^2.7 || ^3.0 || ^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7", - "phpunit/phpunit-mock-objects": "^2.3 || ^3.0" - }, - "suggest": { - "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages", - "ext-zip": "Enabling the zip extension allows you to unzip archives", - "ext-zlib": "Allow gzip compression of HTTP requests" - }, - "bin": [ - "bin/composer" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\": "src/Composer" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "Composer helps you declare, manage and install dependencies of PHP projects, ensuring you have the right stack everywhere.", - "homepage": "https://getcomposer.org/", - "keywords": [ - "autoload", - "dependency", - "package" - ], - "time": "2018-01-31T15:28:18+00:00" - }, - { - "name": "composer/semver", - "version": "1.4.2", - "source": { - "type": "git", - "url": "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/composer/semver.git", - "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573", - "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.5 || ^5.0.5", - "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Semver\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" - } - ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", - "keywords": [ - "semantic", - "semver", - "validation", - "versioning" - ], - "time": "2016-08-30T16:08:34+00:00" - }, - { - "name": "composer/spdx-licenses", - "version": "1.3.0", - "source": { - "type": "git", - "url": "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/composer/spdx-licenses.git", - "reference": "7e111c50db92fa2ced140f5ba23b4e261bc77a30" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/7e111c50db92fa2ced140f5ba23b4e261bc77a30", - "reference": "7e111c50db92fa2ced140f5ba23b4e261bc77a30", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5", - "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Spdx\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" - } - ], - "description": "SPDX licenses list and validation library.", - "keywords": [ - "license", - "spdx", - "validator" - ], - "time": "2018-01-31T13:17:27+00:00" - }, - { - "name": "justinrainbow/json-schema", - "version": "5.2.7", - "source": { - "type": "git", - "url": "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/justinrainbow/json-schema.git", - "reference": "8560d4314577199ba51bf2032f02cd1315587c23" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/8560d4314577199ba51bf2032f02cd1315587c23", - "reference": "8560d4314577199ba51bf2032f02cd1315587c23", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.1", - "json-schema/json-schema-test-suite": "1.2.0", - "phpunit/phpunit": "^4.8.35" - }, - "bin": [ - "bin/validate-json" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "JsonSchema\\": "src/JsonSchema/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bruno Prieto Reis", - "email": "bruno.p.reis@gmail.com" - }, - { - "name": "Justin Rainbow", - "email": "justin.rainbow@gmail.com" - }, - { - "name": "Igor Wiedler", - "email": "igor@wiedler.ch" - }, - { - "name": "Robert Schönthal", - "email": "seroscho@googlemail.com" - } - ], - "description": "A library to validate a json schema.", - "homepage": "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/justinrainbow/json-schema", - "keywords": [ - "json", - "schema" - ], - "time": "2018-02-14T22:26:30+00:00" - }, - { - "name": "mustache/mustache", - "version": "v2.12.0", - "source": { - "type": "git", - "url": "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/bobthecow/mustache.php.git", - "reference": "fe8fe72e9d580591854de404cc59a1b83ca4d19e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/bobthecow/mustache.php/zipball/fe8fe72e9d580591854de404cc59a1b83ca4d19e", - "reference": "fe8fe72e9d580591854de404cc59a1b83ca4d19e", - "shasum": "" - }, - "require": { - "php": ">=5.2.4" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "~1.11", - "phpunit/phpunit": "~3.7|~4.0|~5.0" - }, - "type": "library", - "autoload": { - "psr-0": { - "Mustache": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Justin Hileman", - "email": "justin@justinhileman.info", - "homepage": "http://justinhileman.com" - } - ], - "description": "A Mustache implementation in PHP.", - "homepage": "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/bobthecow/mustache.php", - "keywords": [ - "mustache", - "templating" - ], - "time": "2017-07-11T12:54:05+00:00" - }, - { - "name": "nb/oxymel", - "version": "v0.1.0", - "source": { - "type": "git", - "url": "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/nb/oxymel.git", - "reference": "cbe626ef55d5c4cc9b5e6e3904b395861ea76e3c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nb/oxymel/zipball/cbe626ef55d5c4cc9b5e6e3904b395861ea76e3c", - "reference": "cbe626ef55d5c4cc9b5e6e3904b395861ea76e3c", - "shasum": "" - }, - "require": { - "php": ">=5.2.4" - }, - "type": "library", - "autoload": { - "psr-0": { - "Oxymel": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nikolay Bachiyski", - "email": "nb@nikolay.bg", - "homepage": "http://extrapolate.me/" - } - ], - "description": "A sweet XML builder", - "homepage": "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/nb/oxymel", - "keywords": [ - "xml" - ], - "time": "2013-02-24T15:01:54+00:00" - }, - { - "name": "psr/log", - "version": "1.0.2", - "source": { - "type": "git", - "url": "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/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "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/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "time": "2016-10-10T12:19:37+00:00" - }, - { - "name": "ramsey/array_column", - "version": "1.1.3", - "source": { - "type": "git", - "url": "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/ramsey/array_column.git", - "reference": "f8e52eb28e67eb50e613b451dd916abcf783c1db" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ramsey/array_column/zipball/f8e52eb28e67eb50e613b451dd916abcf783c1db", - "reference": "f8e52eb28e67eb50e613b451dd916abcf783c1db", - "shasum": "" - }, - "require-dev": { - "jakub-onderka/php-parallel-lint": "0.8.*", - "phpunit/phpunit": "~4.5", - "satooshi/php-coveralls": "0.6.*", - "squizlabs/php_codesniffer": "~2.2" - }, - "type": "library", - "autoload": { - "files": [ - "src/array_column.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ben Ramsey", - "homepage": "http://benramsey.com" - } - ], - "description": "Provides functionality for array_column() to projects using PHP earlier than version 5.5.", - "homepage": "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/ramsey/array_column", - "keywords": [ - "array", - "array_column", - "column" - ], - "time": "2015-03-20T22:07:39+00:00" - }, - { - "name": "rmccue/requests", - "version": "v1.7.0", - "source": { - "type": "git", - "url": "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/rmccue/Requests.git", - "reference": "87932f52ffad70504d93f04f15690cf16a089546" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/rmccue/Requests/zipball/87932f52ffad70504d93f04f15690cf16a089546", - "reference": "87932f52ffad70504d93f04f15690cf16a089546", - "shasum": "" - }, - "require": { - "php": ">=5.2" - }, - "require-dev": { - "requests/test-server": "dev-master" - }, - "type": "library", - "autoload": { - "psr-0": { - "Requests": "library/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], - "authors": [ - { - "name": "Ryan McCue", - "homepage": "http://ryanmccue.info" - } - ], - "description": "A HTTP library written in PHP, for human beings.", - "homepage": "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/rmccue/Requests", - "keywords": [ - "curl", - "fsockopen", - "http", - "idna", - "ipv6", - "iri", - "sockets" - ], - "time": "2016-10-13T00:11:37+00:00" - }, - { - "name": "seld/cli-prompt", - "version": "1.0.3", - "source": { - "type": "git", - "url": "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/Seldaek/cli-prompt.git", - "reference": "a19a7376a4689d4d94cab66ab4f3c816019ba8dd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Seldaek/cli-prompt/zipball/a19a7376a4689d4d94cab66ab4f3c816019ba8dd", - "reference": "a19a7376a4689d4d94cab66ab4f3c816019ba8dd", - "shasum": "" - }, - "require": { - "php": ">=5.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Seld\\CliPrompt\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be" - } - ], - "description": "Allows you to prompt for user input on the command line, and optionally hide the characters they type", - "keywords": [ - "cli", - "console", - "hidden", - "input", - "prompt" - ], - "time": "2017-03-18T11:32:45+00:00" - }, - { - "name": "seld/jsonlint", - "version": "1.7.1", - "source": { - "type": "git", - "url": "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/Seldaek/jsonlint.git", - "reference": "d15f59a67ff805a44c50ea0516d2341740f81a38" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/d15f59a67ff805a44c50ea0516d2341740f81a38", - "reference": "d15f59a67ff805a44c50ea0516d2341740f81a38", - "shasum": "" - }, - "require": { - "php": "^5.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" - }, - "bin": [ - "bin/jsonlint" - ], - "type": "library", - "autoload": { - "psr-4": { - "Seld\\JsonLint\\": "src/Seld/JsonLint/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "JSON Linter", - "keywords": [ - "json", - "linter", - "parser", - "validator" - ], - "time": "2018-01-24T12:46:19+00:00" - }, - { - "name": "seld/phar-utils", - "version": "1.0.1", - "source": { - "type": "git", - "url": "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/Seldaek/phar-utils.git", - "reference": "7009b5139491975ef6486545a39f3e6dad5ac30a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/7009b5139491975ef6486545a39f3e6dad5ac30a", - "reference": "7009b5139491975ef6486545a39f3e6dad5ac30a", - "shasum": "" - }, - "require": { - "php": ">=5.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Seld\\PharUtils\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be" - } - ], - "description": "PHAR file format utilities, for when PHP phars you up", - "keywords": [ - "phra" - ], - "time": "2015-10-13T18:44:15+00:00" - }, - { - "name": "symfony/config", - "version": "v2.8.34", - "source": { - "type": "git", - "url": "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/symfony/config.git", - "reference": "17605ff58313d9fe94e507620a399721fc347b6d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/17605ff58313d9fe94e507620a399721fc347b6d", - "reference": "17605ff58313d9fe94e507620a399721fc347b6d", - "shasum": "" - }, - "require": { - "php": ">=5.3.9", - "symfony/filesystem": "~2.3|~3.0.0" - }, - "require-dev": { - "symfony/yaml": "~2.7|~3.0.0" - }, - "suggest": { - "symfony/yaml": "To use the yaml reference dumper" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Config\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Config Component", - "homepage": "https://symfony.com", - "time": "2018-01-21T19:03:25+00:00" - }, - { - "name": "symfony/console", - "version": "v2.8.34", - "source": { - "type": "git", - "url": "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/symfony/console.git", - "reference": "162ca7d0ea597599967aa63b23418e747da0896b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/162ca7d0ea597599967aa63b23418e747da0896b", - "reference": "162ca7d0ea597599967aa63b23418e747da0896b", - "shasum": "" - }, - "require": { - "php": ">=5.3.9", - "symfony/debug": "^2.7.2|~3.0.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/event-dispatcher": "~2.1|~3.0.0", - "symfony/process": "~2.1|~3.0.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/process": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Console Component", - "homepage": "https://symfony.com", - "time": "2018-01-29T08:54:45+00:00" - }, - { - "name": "symfony/debug", - "version": "v2.8.34", - "source": { - "type": "git", - "url": "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/symfony/debug.git", - "reference": "35e36287fc0fdc8a08f70efcd4865ae6d8a6ee55" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/35e36287fc0fdc8a08f70efcd4865ae6d8a6ee55", - "reference": "35e36287fc0fdc8a08f70efcd4865ae6d8a6ee55", - "shasum": "" - }, - "require": { - "php": ">=5.3.9", - "psr/log": "~1.0" - }, - "conflict": { - "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" - }, - "require-dev": { - "symfony/class-loader": "~2.2|~3.0.0", - "symfony/http-kernel": "~2.3.24|~2.5.9|^2.6.2|~3.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Debug\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Debug Component", - "homepage": "https://symfony.com", - "time": "2018-01-18T22:12:33+00:00" - }, - { - "name": "symfony/dependency-injection", - "version": "v2.8.34", - "source": { - "type": "git", - "url": "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/symfony/dependency-injection.git", - "reference": "91ad61e6f140b050eba4aa39bc52eece713f2a71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/91ad61e6f140b050eba4aa39bc52eece713f2a71", - "reference": "91ad61e6f140b050eba4aa39bc52eece713f2a71", - "shasum": "" - }, - "require": { - "php": ">=5.3.9" - }, - "conflict": { - "symfony/expression-language": "<2.6" - }, - "require-dev": { - "symfony/config": "~2.2|~3.0.0", - "symfony/expression-language": "~2.6|~3.0.0", - "symfony/yaml": "~2.3.42|~2.7.14|~2.8.7|~3.0.7" - }, - "suggest": { - "symfony/config": "", - "symfony/expression-language": "For using expressions in service container configuration", - "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", - "symfony/yaml": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\DependencyInjection\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony DependencyInjection Component", - "homepage": "https://symfony.com", - "time": "2018-01-29T08:55:23+00:00" - }, - { - "name": "symfony/event-dispatcher", - "version": "v2.8.34", - "source": { - "type": "git", - "url": "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/symfony/event-dispatcher.git", - "reference": "d64be24fc1eba62f9daace8a8918f797fc8e87cc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d64be24fc1eba62f9daace8a8918f797fc8e87cc", - "reference": "d64be24fc1eba62f9daace8a8918f797fc8e87cc", - "shasum": "" - }, - "require": { - "php": ">=5.3.9" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "^2.0.5|~3.0.0", - "symfony/dependency-injection": "~2.6|~3.0.0", - "symfony/expression-language": "~2.6|~3.0.0", - "symfony/stopwatch": "~2.3|~3.0.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony EventDispatcher Component", - "homepage": "https://symfony.com", - "time": "2018-01-03T07:36:31+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v2.8.34", - "source": { - "type": "git", - "url": "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/symfony/filesystem.git", - "reference": "1f4e8351e0196562f5e8ec584baeceeb8e2e92f6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/1f4e8351e0196562f5e8ec584baeceeb8e2e92f6", - "reference": "1f4e8351e0196562f5e8ec584baeceeb8e2e92f6", - "shasum": "" - }, - "require": { - "php": ">=5.3.9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Filesystem Component", - "homepage": "https://symfony.com", - "time": "2018-01-03T07:36:31+00:00" - }, - { - "name": "symfony/finder", - "version": "v2.8.34", - "source": { - "type": "git", - "url": "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/symfony/finder.git", - "reference": "9786ccb6a1f94a89ae18fc6a1b68de1f070823ed" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/9786ccb6a1f94a89ae18fc6a1b68de1f070823ed", - "reference": "9786ccb6a1f94a89ae18fc6a1b68de1f070823ed", - "shasum": "" - }, - "require": { - "php": ">=5.3.9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Finder Component", - "homepage": "https://symfony.com", - "time": "2018-01-29T08:54:45+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.7.0", - "source": { - "type": "git", - "url": "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/symfony/polyfill-mbstring.git", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.7-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "time": "2018-01-30T19:27:44+00:00" - }, - { - "name": "symfony/process", - "version": "v2.8.34", - "source": { - "type": "git", - "url": "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/symfony/process.git", - "reference": "905efe90024caa75a2fc93f54e14b26f2a099d96" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/905efe90024caa75a2fc93f54e14b26f2a099d96", - "reference": "905efe90024caa75a2fc93f54e14b26f2a099d96", - "shasum": "" - }, - "require": { - "php": ">=5.3.9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Process Component", - "homepage": "https://symfony.com", - "time": "2018-01-29T08:54:45+00:00" - }, - { - "name": "symfony/translation", - "version": "v2.8.34", - "source": { - "type": "git", - "url": "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/symfony/translation.git", - "reference": "72235c1121ae282254e897e342c001f3d4bb7e8d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/72235c1121ae282254e897e342c001f3d4bb7e8d", - "reference": "72235c1121ae282254e897e342c001f3d4bb7e8d", - "shasum": "" - }, - "require": { - "php": ">=5.3.9", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/config": "<2.7" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~2.8", - "symfony/intl": "~2.7.25|^2.8.18|~3.2.5", - "symfony/yaml": "~2.2|~3.0.0" - }, - "suggest": { - "psr/log": "To use logging capability in translator", - "symfony/config": "", - "symfony/yaml": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Translation\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Translation Component", - "homepage": "https://symfony.com", - "time": "2018-01-18T13:56:23+00:00" - }, - { - "name": "symfony/yaml", - "version": "v2.8.34", - "source": { - "type": "git", - "url": "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/symfony/yaml.git", - "reference": "be720fcfae4614df204190d57795351059946a77" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/be720fcfae4614df204190d57795351059946a77", - "reference": "be720fcfae4614df204190d57795351059946a77", - "shasum": "" - }, - "require": { - "php": ">=5.3.9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "time": "2018-01-03T07:36:31+00:00" - }, - { - "name": "wp-cli/autoload-splitter", - "version": "v0.1.5", - "source": { - "type": "git", - "url": "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/wp-cli/autoload-splitter.git", - "reference": "fb4302da26390811d2631c62b42b75976d224bb8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/autoload-splitter/zipball/fb4302da26390811d2631c62b42b75976d224bb8", - "reference": "fb4302da26390811d2631c62b42b75976d224bb8", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.1" - }, - "type": "composer-plugin", - "extra": { - "class": "WP_CLI\\AutoloadSplitter\\ComposerPlugin" - }, - "autoload": { - "psr-4": { - "WP_CLI\\AutoloadSplitter\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Alain Schlesser", - "email": "alain.schlesser@gmail.com", - "homepage": "https://www.alainschlesser.com" - } - ], - "description": "Composer plugin for splitting a generated autoloader into two distinct parts.", - "homepage": "https://wp-cli.org", - "time": "2017-08-03T08:40:16+00:00" - }, - { - "name": "wp-cli/cache-command", - "version": "v1.0.6", - "source": { - "type": "git", - "url": "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/wp-cli/cache-command.git", - "reference": "d82cba9effa198f17847dce5771c8fb20c443ffa" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/cache-command/zipball/d82cba9effa198f17847dce5771c8fb20c443ffa", - "reference": "d82cba9effa198f17847dce5771c8fb20c443ffa", - "shasum": "" - }, - "require-dev": { - "behat/behat": "~2.5", - "wp-cli/wp-cli": "*" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "bundled": true, - "commands": [ - "cache", - "cache add", - "cache decr", - "cache delete", - "cache flush", - "cache get", - "cache incr", - "cache replace", - "cache set", - "cache type", - "transient", - "transient delete", - "transient get", - "transient set", - "transient type" - ] - }, - "autoload": { - "psr-4": { - "": "src/" - }, - "files": [ - "cache-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Manages object and transient caches.", - "homepage": "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/wp-cli/cache-command", - "time": "2017-12-14T19:21:19+00:00" - }, - { - "name": "wp-cli/checksum-command", - "version": "v1.0.8", - "source": { - "type": "git", - "url": "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/wp-cli/checksum-command.git", - "reference": "360c0c658242919e9a74ba06917fd8a691484174" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/checksum-command/zipball/360c0c658242919e9a74ba06917fd8a691484174", - "reference": "360c0c658242919e9a74ba06917fd8a691484174", - "shasum": "" - }, - "require-dev": { - "behat/behat": "~2.5", - "wp-cli/wp-cli": "^1.5" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "bundled": true, - "commands": [ - "core verify-checksums", - "plugin verify-checksums" - ] - }, - "autoload": { - "psr-4": { - "": "src/" - }, - "files": [ - "checksum-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Verifies file integrity by comparing to published checksums.", - "homepage": "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/wp-cli/checksum-command", - "time": "2018-01-29T16:56:18+00:00" - }, - { - "name": "wp-cli/config-command", - "version": "v1.1.8", - "source": { - "type": "git", - "url": "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/wp-cli/config-command.git", - "reference": "4e44b3fab9e1ddb8f91e3189b27354ff4ae141ad" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/config-command/zipball/4e44b3fab9e1ddb8f91e3189b27354ff4ae141ad", - "reference": "4e44b3fab9e1ddb8f91e3189b27354ff4ae141ad", - "shasum": "" - }, - "require": { - "wp-cli/wp-config-transformer": "^1.2" - }, - "require-dev": { - "behat/behat": "~2.5", - "wp-cli/wp-cli": "*" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "bundled": true, - "commands": [ - "config", - "config delete", - "config create", - "config get", - "config has", - "config list", - "config path", - "config set" - ] - }, - "autoload": { - "psr-4": { - "": "src/" - }, - "files": [ - "config-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - }, - { - "name": "Alain Schlesser", - "email": "alain.schlesser@gmail.com", - "homepage": "https://www.alainschlesser.com" - } - ], - "description": "Generates and reads the wp-config.php file.", - "homepage": "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/wp-cli/config-command", - "time": "2018-01-30T14:12:41+00:00" - }, - { - "name": "wp-cli/core-command", - "version": "v1.0.9", - "source": { - "type": "git", - "url": "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/wp-cli/core-command.git", - "reference": "0e825668d2c060c40ec1d7debbee94bc08eec9b3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/core-command/zipball/0e825668d2c060c40ec1d7debbee94bc08eec9b3", - "reference": "0e825668d2c060c40ec1d7debbee94bc08eec9b3", - "shasum": "" - }, - "require-dev": { - "behat/behat": "~2.5", - "wp-cli/wp-cli": "*" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "bundled": true, - "commands": [ - "core", - "core check-update", - "core download", - "core install", - "core is-installed", - "core multisite-convert", - "core multisite-install", - "core update", - "core update-db", - "core version" - ] - }, - "autoload": { - "psr-4": { - "": "src/" - }, - "files": [ - "core-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Downloads, installs, updates, and manages a WordPress installation.", - "homepage": "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/wp-cli/core-command", - "time": "2018-01-30T06:57:10+00:00" - }, - { - "name": "wp-cli/cron-command", - "version": "v1.0.5", - "source": { - "type": "git", - "url": "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/wp-cli/cron-command.git", - "reference": "9da7e36e8f9c14cb171a3c5204cba2865e0ed7ef" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/cron-command/zipball/9da7e36e8f9c14cb171a3c5204cba2865e0ed7ef", - "reference": "9da7e36e8f9c14cb171a3c5204cba2865e0ed7ef", - "shasum": "" - }, - "require-dev": { - "behat/behat": "~2.5", - "wp-cli/wp-cli": "*" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "bundled": true, - "commands": [ - "cron", - "cron test", - "cron event", - "cron event delete", - "cron event list", - "cron event run", - "cron event schedule", - "cron schedule", - "cron schedule list" - ] - }, - "autoload": { - "psr-4": { - "": "src/" - }, - "files": [ - "cron-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Tests, runs, and deletes WP-Cron events; manages WP-Cron schedules.", - "homepage": "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/wp-cli/cron-command", - "time": "2017-12-08T15:09:54+00:00" - }, - { - "name": "wp-cli/db-command", - "version": "v1.3.3", - "source": { - "type": "git", - "url": "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/wp-cli/db-command.git", - "reference": "7d361a15ffe34dfc9d798a81208fe61b8a2f049a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/db-command/zipball/7d361a15ffe34dfc9d798a81208fe61b8a2f049a", - "reference": "7d361a15ffe34dfc9d798a81208fe61b8a2f049a", - "shasum": "" - }, - "require-dev": { - "behat/behat": "~2.5", - "wp-cli/wp-cli": "^1.5" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "bundled": true, - "commands": [ - "db", - "db create", - "db drop", - "db reset", - "db check", - "db optimize", - "db prefix", - "db repair", - "db cli", - "db query", - "db export", - "db import", - "db search", - "db tables", - "db size" - ] - }, - "autoload": { - "psr-4": { - "": "src/" - }, - "files": [ - "db-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Performs basic database operations using credentials stored in wp-config.php.", - "homepage": "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/wp-cli/db-command", - "time": "2018-01-29T02:30:16+00:00" - }, - { - "name": "wp-cli/embed-command", - "version": "v1.0.0", - "source": { - "type": "git", - "url": "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/wp-cli/embed-command.git", - "reference": "81319d4243a8dfe096389bf54cdc4fc3dec53497" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/embed-command/zipball/81319d4243a8dfe096389bf54cdc4fc3dec53497", - "reference": "81319d4243a8dfe096389bf54cdc4fc3dec53497", - "shasum": "" - }, - "require-dev": { - "behat/behat": "~2.5", - "wp-cli/wp-cli": "^1.5" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "bundled": true, - "commands": [ - "embed", - "embed fetch", - "embed provider list", - "embed provider match", - "embed handler list", - "embed cache clear", - "embed cache find", - "embed cache trigger" - ] - }, - "autoload": { - "psr-4": { - "WP_CLI\\Embeds\\": "src/" - }, - "files": [ - "embed-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Pascal Birchler", - "homepage": "https://pascalbirchler.com/" - } - ], - "description": "Inspects oEmbed providers, clears embed cache, and more.", - "homepage": "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/wp-cli/embed-command", - "time": "2018-01-22T21:26:48+00:00" - }, - { - "name": "wp-cli/entity-command", - "version": "v1.2.0", - "source": { - "type": "git", - "url": "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/wp-cli/entity-command.git", - "reference": "035b74ea16912f5b14db7d28036a6d123eb90547" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/entity-command/zipball/035b74ea16912f5b14db7d28036a6d123eb90547", - "reference": "035b74ea16912f5b14db7d28036a6d123eb90547", - "shasum": "" - }, - "require-dev": { - "behat/behat": "~2.5", - "phpunit/phpunit": "^4.8", - "wp-cli/wp-cli": "^1.5" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "bundled": true, - "commands": [ - "comment", - "comment approve", - "comment count", - "comment create", - "comment delete", - "comment exists", - "comment generate", - "comment get", - "comment list", - "comment meta", - "comment meta add", - "comment meta delete", - "comment meta get", - "comment meta list", - "comment meta patch", - "comment meta pluck", - "comment meta update", - "comment recount", - "comment spam", - "comment status", - "comment trash", - "comment unapprove", - "comment unspam", - "comment untrash", - "comment update", - "menu", - "menu create", - "menu delete", - "menu item", - "menu item add-custom", - "menu item add-post", - "menu item add-term", - "menu item delete", - "menu item list", - "menu item update", - "menu list", - "menu location", - "menu location assign", - "menu location list", - "menu location remove", - "network meta", - "network meta add", - "network meta delete", - "network meta get", - "network meta list", - "network meta patch", - "network meta pluck", - "network meta update", - "option", - "option add", - "option delete", - "option get", - "option list", - "option patch", - "option pluck", - "option update", - "post", - "post create", - "post delete", - "post edit", - "post generate", - "post get", - "post list", - "post meta", - "post meta add", - "post meta delete", - "post meta get", - "post meta list", - "post meta patch", - "post meta pluck", - "post meta update", - "post term", - "post term add", - "post term list", - "post term remove", - "post term set", - "post update", - "post-type", - "post-type get", - "post-type list", - "site", - "site activate", - "site archive", - "site create", - "site deactivate", - "site delete", - "site empty", - "site list", - "site mature", - "site option", - "site private", - "site public", - "site spam", - "site unarchive", - "site unmature", - "site unspam", - "taxonomy", - "taxonomy get", - "taxonomy list", - "term", - "term create", - "term delete", - "term generate", - "term get", - "term list", - "term meta", - "term meta add", - "term meta delete", - "term meta get", - "term meta list", - "term meta patch", - "term meta pluck", - "term meta update", - "term recount", - "term update", - "user", - "user add-cap", - "user add-role", - "user create", - "user delete", - "user generate", - "user get", - "user import-csv", - "user list", - "user list-caps", - "user meta", - "user meta add", - "user meta delete", - "user meta get", - "user meta list", - "user meta patch", - "user meta pluck", - "user meta update", - "user remove-cap", - "user remove-role", - "user reset-password", - "user session", - "user session destroy", - "user session list", - "user set-role", - "user spam", - "user term", - "user term add", - "user term list", - "user term remove", - "user term set", - "user unspam", - "user update" - ] - }, - "autoload": { - "psr-4": { - "": "src/", - "WP_CLI\\": "src/WP_CLI" - }, - "files": [ - "entity-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Manage WordPress core entities.", - "homepage": "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/wp-cli/entity-command", - "time": "2018-01-29T15:10:05+00:00" - }, - { - "name": "wp-cli/eval-command", - "version": "v1.0.5", - "source": { - "type": "git", - "url": "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/wp-cli/eval-command.git", - "reference": "9640d40ab28cd86590396f08f8c382e659f57321" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/eval-command/zipball/9640d40ab28cd86590396f08f8c382e659f57321", - "reference": "9640d40ab28cd86590396f08f8c382e659f57321", - "shasum": "" - }, - "require": { - "wp-cli/wp-cli": "*" - }, - "require-dev": { - "behat/behat": "~2.5" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "bundled": true, - "commands": [ - "eval", - "eval-file" - ] - }, - "autoload": { - "psr-4": { - "": "src/" - }, - "files": [ - "eval-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Executes arbitrary PHP code or files.", - "homepage": "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/wp-cli/eval-command", - "time": "2017-12-08T14:33:34+00:00" - }, - { - "name": "wp-cli/export-command", - "version": "v1.0.6", - "source": { - "type": "git", - "url": "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/wp-cli/export-command.git", - "reference": "4ae43d370ed6ed0cffd166dd84cfc6c8c2f3f633" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/export-command/zipball/4ae43d370ed6ed0cffd166dd84cfc6c8c2f3f633", - "reference": "4ae43d370ed6ed0cffd166dd84cfc6c8c2f3f633", - "shasum": "" - }, - "require": { - "nb/oxymel": "~0.1.0" - }, - "require-dev": { - "behat/behat": "~2.5", - "wp-cli/wp-cli": "^1.5" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "bundled": true, - "commands": [ - "export" - ] - }, - "autoload": { - "psr-4": { - "": "src/" - }, - "files": [ - "export-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Exports WordPress content to a WXR file.", - "homepage": "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/wp-cli/export-command", - "time": "2018-01-29T02:33:05+00:00" - }, - { - "name": "wp-cli/extension-command", - "version": "v1.1.9", - "source": { - "type": "git", - "url": "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/wp-cli/extension-command.git", - "reference": "dfacef02b88baed07058c88064afd582f4150a97" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/extension-command/zipball/dfacef02b88baed07058c88064afd582f4150a97", - "reference": "dfacef02b88baed07058c88064afd582f4150a97", - "shasum": "" - }, - "require-dev": { - "behat/behat": "~2.5", - "wp-cli/wp-cli": "*" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "bundled": true, - "commands": [ - "plugin", - "plugin activate", - "plugin deactivate", - "plugin delete", - "plugin get", - "plugin install", - "plugin is-installed", - "plugin list", - "plugin path", - "plugin search", - "plugin status", - "plugin toggle", - "plugin uninstall", - "plugin update", - "theme", - "theme activate", - "theme delete", - "theme disable", - "theme enable", - "theme get", - "theme install", - "theme is-installed", - "theme list", - "theme mod", - "theme mod get", - "theme mod set", - "theme mod remove", - "theme path", - "theme search", - "theme status", - "theme update" - ] - }, - "autoload": { - "psr-4": { - "": "src/" - }, - "files": [ - "extension-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Manages plugins and themes, including installs, activations, and updates.", - "homepage": "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/wp-cli/extension-command", - "time": "2018-01-30T11:13:57+00:00" - }, - { - "name": "wp-cli/import-command", - "version": "v1.0.6", - "source": { - "type": "git", - "url": "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/wp-cli/import-command.git", - "reference": "d2c21d590a1bfae6ac4e289a0b57fb1870b5990c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/import-command/zipball/d2c21d590a1bfae6ac4e289a0b57fb1870b5990c", - "reference": "d2c21d590a1bfae6ac4e289a0b57fb1870b5990c", - "shasum": "" - }, - "require": { - "wp-cli/wp-cli": "*" - }, - "require-dev": { - "behat/behat": "~2.5" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "bundled": true, - "commands": [ - "import" - ] - }, - "autoload": { - "psr-4": { - "": "src/" - }, - "files": [ - "import-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Imports content from a given WXR file.", - "homepage": "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/wp-cli/import-command", - "time": "2017-12-08T15:13:36+00:00" - }, - { - "name": "wp-cli/language-command", - "version": "v1.0.6", - "source": { - "type": "git", - "url": "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/wp-cli/language-command.git", - "reference": "2a3d1ce5a722a4d70809619a065087aa933f6209" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/language-command/zipball/2a3d1ce5a722a4d70809619a065087aa933f6209", - "reference": "2a3d1ce5a722a4d70809619a065087aa933f6209", - "shasum": "" - }, - "require-dev": { - "behat/behat": "~2.5", - "wp-cli/wp-cli": "*" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "commands": [ - "language", - "language core", - "language core activate", - "language core install", - "language core list", - "language core uninstall", - "language core update" - ], - "bundled": true - }, - "autoload": { - "psr-4": { - "": "src/" - }, - "files": [ - "language-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Installs, activates, and manages language packs.", - "homepage": "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/wp-cli/language-command", - "time": "2017-12-08T17:50:26+00:00" - }, - { - "name": "wp-cli/media-command", - "version": "v1.1.4", - "source": { - "type": "git", - "url": "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/wp-cli/media-command.git", - "reference": "7f8664ba722505446b3ef3dbc6717e8e7f20265c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/media-command/zipball/7f8664ba722505446b3ef3dbc6717e8e7f20265c", - "reference": "7f8664ba722505446b3ef3dbc6717e8e7f20265c", - "shasum": "" - }, - "require-dev": { - "behat/behat": "~2.5", - "wp-cli/wp-cli": "^1.5" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "bundled": true, - "commands": [ - "media", - "media import", - "media regenerate", - "media image-size" - ] - }, - "autoload": { - "psr-4": { - "": "src/" - }, - "files": [ - "media-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Imports files as attachments, regenerates thumbnails, or lists registered image sizes.", - "homepage": "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/wp-cli/media-command", - "time": "2018-01-29T02:17:56+00:00" - }, - { - "name": "wp-cli/mustangostang-spyc", - "version": "0.6.3", - "source": { - "type": "git", - "url": "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/wp-cli/spyc.git", - "reference": "6aa0b4da69ce9e9a2c8402dab8d43cf32c581cc7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/spyc/zipball/6aa0b4da69ce9e9a2c8402dab8d43cf32c581cc7", - "reference": "6aa0b4da69ce9e9a2c8402dab8d43cf32c581cc7", - "shasum": "" - }, - "require": { - "php": ">=5.3.1" - }, - "require-dev": { - "phpunit/phpunit": "4.3.*@dev" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.5.x-dev" - } - }, - "autoload": { - "psr-4": { - "Mustangostang\\": "src/" - }, - "files": [ - "includes/functions.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "mustangostang", - "email": "vlad.andersen@gmail.com" - } - ], - "description": "A simple YAML loader/dumper class for PHP (WP-CLI fork)", - "homepage": "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/mustangostang/spyc/", - "time": "2017-04-25T11:26:20+00:00" - }, - { - "name": "wp-cli/package-command", - "version": "v1.0.12", - "source": { - "type": "git", - "url": "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/wp-cli/package-command.git", - "reference": "bb8b02d9ba1cded95564767000738ceaefbc885b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/package-command/zipball/bb8b02d9ba1cded95564767000738ceaefbc885b", - "reference": "bb8b02d9ba1cded95564767000738ceaefbc885b", - "shasum": "" - }, - "require": { - "composer/composer": "^1.2.0" - }, - "require-dev": { - "behat/behat": "~2.5", - "wp-cli/wp-cli": "^1.5" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "bundled": true, - "commands": [ - "package", - "package browse", - "package install", - "package list", - "package update", - "package uninstall" - ] - }, - "autoload": { - "psr-4": { - "": "src/" - }, - "files": [ - "package-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Lists, installs, and removes WP-CLI packages.", - "homepage": "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/wp-cli/package-command", - "time": "2018-02-09T09:55:33+00:00" - }, - { - "name": "wp-cli/php-cli-tools", - "version": "v0.11.8", - "source": { - "type": "git", - "url": "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/wp-cli/php-cli-tools.git", - "reference": "363c75349f5dde561e0b416dd00f7aaa76fa2c27" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/php-cli-tools/zipball/363c75349f5dde561e0b416dd00f7aaa76fa2c27", - "reference": "363c75349f5dde561e0b416dd00f7aaa76fa2c27", - "shasum": "" - }, - "require": { - "php": ">= 5.3.0" - }, - "type": "library", - "autoload": { - "psr-0": { - "cli": "lib/" - }, - "files": [ - "lib/cli/cli.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "James Logsdon", - "email": "jlogsdon@php.net", - "role": "Developer" - }, - { - "name": "Daniel Bachhuber", - "email": "daniel@handbuilt.co", - "role": "Maintainer" - } - ], - "description": "Console utilities for PHP", - "homepage": "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/wp-cli/php-cli-tools", - "keywords": [ - "cli", - "console" - ], - "time": "2017-10-12T21:50:48+00:00" - }, - { - "name": "wp-cli/rewrite-command", - "version": "v1.0.5", - "source": { - "type": "git", - "url": "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/wp-cli/rewrite-command.git", - "reference": "6b1695887e289ffad14c8f4ea86b5f1d92757408" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/rewrite-command/zipball/6b1695887e289ffad14c8f4ea86b5f1d92757408", - "reference": "6b1695887e289ffad14c8f4ea86b5f1d92757408", - "shasum": "" - }, - "require-dev": { - "behat/behat": "~2.5", - "wp-cli/wp-cli": "*" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "commands": [ - "rewrite", - "rewrite flush", - "rewrite list", - "rewrite structure" - ], - "bundled": true - }, - "autoload": { - "psr-4": { - "": "src/" - }, - "files": [ - "rewrite-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Lists or flushes the site's rewrite rules, updates the permalink structure.", - "homepage": "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/wp-cli/rewrite-command", - "time": "2017-12-08T17:51:04+00:00" - }, - { - "name": "wp-cli/role-command", - "version": "v1.0.5", - "source": { - "type": "git", - "url": "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/wp-cli/role-command.git", - "reference": "be7f8ea91922864d0c75e45953fbe41d44bebb25" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/role-command/zipball/be7f8ea91922864d0c75e45953fbe41d44bebb25", - "reference": "be7f8ea91922864d0c75e45953fbe41d44bebb25", - "shasum": "" - }, - "require-dev": { - "behat/behat": "~2.5", - "wp-cli/wp-cli": "*" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "commands": [ - "role", - "role create", - "role delete", - "role exists", - "role list", - "role reset", - "cap", - "cap add", - "cap list", - "cap remove" - ], - "bundled": true - }, - "autoload": { - "psr-4": { - "": "src/" - }, - "files": [ - "role-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Adds, removes, lists, and resets roles and capabilities.", - "homepage": "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/wp-cli/role-command", - "time": "2017-12-08T17:51:40+00:00" - }, - { - "name": "wp-cli/scaffold-command", - "version": "v1.1.2", - "source": { - "type": "git", - "url": "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/wp-cli/scaffold-command.git", - "reference": "a7ef51b2abd88a2ecb17ecdf7aaad92da37d1eb7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/scaffold-command/zipball/a7ef51b2abd88a2ecb17ecdf7aaad92da37d1eb7", - "reference": "a7ef51b2abd88a2ecb17ecdf7aaad92da37d1eb7", - "shasum": "" - }, - "require-dev": { - "behat/behat": "~2.5", - "wp-cli/wp-cli": "^1.5" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "bundled": true, - "commands": [ - "scaffold", - "scaffold _s", - "scaffold block", - "scaffold child-theme", - "scaffold plugin", - "scaffold plugin-tests", - "scaffold post-type", - "scaffold taxonomy", - "scaffold theme-tests" - ] - }, - "autoload": { - "psr-4": { - "": "src/" - }, - "files": [ - "scaffold-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Generates code for post types, taxonomies, blocks, plugins, child themes, etc.", - "homepage": "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/wp-cli/scaffold-command", - "time": "2018-01-29T02:29:34+00:00" - }, - { - "name": "wp-cli/search-replace-command", - "version": "v1.2.0", - "source": { - "type": "git", - "url": "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/wp-cli/search-replace-command.git", - "reference": "c688e51b35bb87b26a3de308287d6a30cda78e44" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/search-replace-command/zipball/c688e51b35bb87b26a3de308287d6a30cda78e44", - "reference": "c688e51b35bb87b26a3de308287d6a30cda78e44", - "shasum": "" - }, - "require-dev": { - "behat/behat": "~2.5", - "wp-cli/wp-cli": "^1.5" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "bundled": true, - "commands": [ - "search-replace" - ] - }, - "autoload": { - "psr-4": { - "": "src/" - }, - "files": [ - "search-replace-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Searches/replaces strings in the database.", - "homepage": "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/wp-cli/search-replace-command", - "time": "2018-01-29T06:27:32+00:00" - }, - { - "name": "wp-cli/server-command", - "version": "v1.0.9", - "source": { - "type": "git", - "url": "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/wp-cli/server-command.git", - "reference": "6192e6d7becd07e4c11a8f1560655c73a3b3526a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/server-command/zipball/6192e6d7becd07e4c11a8f1560655c73a3b3526a", - "reference": "6192e6d7becd07e4c11a8f1560655c73a3b3526a", - "shasum": "" - }, - "require": { - "wp-cli/wp-cli": "*" - }, - "require-dev": { - "behat/behat": "~2.5" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "commands": [ - "server" - ], - "bundled": true - }, - "autoload": { - "psr-4": { - "": "src/" - }, - "files": [ - "server-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Launches PHP's built-in web server for a specific WordPress installation.", - "homepage": "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/wp-cli/server-command", - "time": "2017-12-14T20:06:24+00:00" - }, - { - "name": "wp-cli/shell-command", - "version": "v1.0.5", - "source": { - "type": "git", - "url": "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/wp-cli/shell-command.git", - "reference": "507603a8994d984b6c4d5bd26e31ede6d9cce37e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/shell-command/zipball/507603a8994d984b6c4d5bd26e31ede6d9cce37e", - "reference": "507603a8994d984b6c4d5bd26e31ede6d9cce37e", - "shasum": "" - }, - "require": { - "wp-cli/wp-cli": "*" - }, - "require-dev": { - "behat/behat": "~2.5" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "commands": [ - "shell" - ], - "bundled": true - }, - "autoload": { - "psr-4": { - "": "src/", - "WP_CLI\\": "src/WP_CLI" - }, - "files": [ - "shell-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Opens an interactive PHP console for running and testing PHP code.", - "homepage": "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/wp-cli/shell-command", - "time": "2017-12-08T16:03:53+00:00" - }, - { - "name": "wp-cli/super-admin-command", - "version": "v1.0.6", - "source": { - "type": "git", - "url": "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/wp-cli/super-admin-command.git", - "reference": "2982d2e6514dbb318561d72d0577746a3a37181e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/super-admin-command/zipball/2982d2e6514dbb318561d72d0577746a3a37181e", - "reference": "2982d2e6514dbb318561d72d0577746a3a37181e", - "shasum": "" - }, - "require-dev": { - "behat/behat": "~2.5", - "wp-cli/wp-cli": "*" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "commands": [ - "super-admin", - "super-admin add", - "super-admin list", - "super-admin remove" - ], - "bundled": true - }, - "autoload": { - "psr-4": { - "": "src/" - }, - "files": [ - "super-admin-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Lists, adds, or removes super admin users on a multisite installation.", - "homepage": "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/wp-cli/super-admin-command", - "time": "2017-12-08T17:43:53+00:00" - }, - { - "name": "wp-cli/widget-command", - "version": "v1.0.5", - "source": { - "type": "git", - "url": "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/wp-cli/widget-command.git", - "reference": "657e0f77d80c892f8f72f90a3a25112c254386df" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/widget-command/zipball/657e0f77d80c892f8f72f90a3a25112c254386df", - "reference": "657e0f77d80c892f8f72f90a3a25112c254386df", - "shasum": "" - }, - "require-dev": { - "behat/behat": "~2.5", - "wp-cli/wp-cli": "*" - }, - "type": "wp-cli-package", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, - "commands": [ - "widget", - "widget add", - "widget deactivate", - "widget delete", - "widget list", - "widget move", - "widget reset", - "widget update", - "sidebar", - "sidebar list" - ], - "bundled": true - }, - "autoload": { - "psr-4": { - "": "src/" - }, - "files": [ - "widget-command.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Bachhuber", - "email": "daniel@runcommand.io", - "homepage": "https://runcommand.io" - } - ], - "description": "Adds, moves, and removes widgets; lists sidebars.", - "homepage": "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/wp-cli/widget-command", - "time": "2017-12-08T17:45:57+00:00" - }, - { - "name": "wp-cli/wp-config-transformer", - "version": "v1.2.0", - "source": { - "type": "git", - "url": "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/wp-cli/wp-config-transformer.git", - "reference": "535007c241ea8425a8840cdb2fa0d395010a0f1c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-cli/wp-config-transformer/zipball/535007c241ea8425a8840cdb2fa0d395010a0f1c", - "reference": "535007c241ea8425a8840cdb2fa0d395010a0f1c", - "shasum": "" - }, - "require": { - "php": ">=5.3.29" - }, - "require-dev": { - "composer/composer": "^1.5.6", - "phpunit/phpunit": "^6.5.5", - "wp-coding-standards/wpcs": "^0.14.0" - }, - "type": "library", - "autoload": { - "files": [ - "src/WPConfigTransformer.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Frankie Jarrett", - "email": "fjarrett@gmail.com" - } - ], - "description": "Programmatically edit a wp-config.php file.", - "time": "2018-01-27T11:50:22+00:00" - } - ], - "packages-dev": [ - { - "name": "behat/behat", - "version": "v2.5.5", - "source": { - "type": "git", - "url": "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/Behat/Behat.git", - "reference": "c1e48826b84669c97a1efa78459aedfdcdcf2120" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Behat/Behat/zipball/c1e48826b84669c97a1efa78459aedfdcdcf2120", - "reference": "c1e48826b84669c97a1efa78459aedfdcdcf2120", - "shasum": "" - }, - "require": { - "behat/gherkin": "~2.3.0", - "php": ">=5.3.1", - "symfony/config": "~2.3", - "symfony/console": "~2.0", - "symfony/dependency-injection": "~2.0", - "symfony/event-dispatcher": "~2.0", - "symfony/finder": "~2.0", - "symfony/translation": "~2.3", - "symfony/yaml": "~2.0" - }, - "require-dev": { - "phpunit/phpunit": "~3.7.19" - }, - "suggest": { - "behat/mink-extension": "for integration with Mink testing framework", - "behat/symfony2-extension": "for integration with Symfony2 web framework", - "behat/yii-extension": "for integration with Yii web framework" - }, - "bin": [ - "bin/behat" - ], - "type": "library", - "autoload": { - "psr-0": { - "Behat\\Behat": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - } - ], - "description": "Scenario-oriented BDD framework for PHP 5.3", - "homepage": "http://behat.org/", - "keywords": [ - "BDD", - "Behat", - "Symfony2" - ], - "time": "2015-06-01T09:37:55+00:00" - }, - { - "name": "behat/gherkin", - "version": "v2.3.5", - "source": { - "type": "git", - "url": "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/Behat/Gherkin.git", - "reference": "2b33963da5525400573560c173ab5c9c057e1852" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Behat/Gherkin/zipball/2b33963da5525400573560c173ab5c9c057e1852", - "reference": "2b33963da5525400573560c173ab5c9c057e1852", - "shasum": "" - }, - "require": { - "php": ">=5.3.1", - "symfony/finder": "~2.0" - }, - "require-dev": { - "symfony/config": "~2.0", - "symfony/translation": "~2.0", - "symfony/yaml": "~2.0" - }, - "suggest": { - "symfony/config": "If you want to use Config component to manage resources", - "symfony/translation": "If you want to use Symfony2 translations adapter", - "symfony/yaml": "If you want to parse features, represented in YAML files" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-develop": "2.2-dev" - } - }, - "autoload": { - "psr-0": { - "Behat\\Gherkin": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - } - ], - "description": "Gherkin DSL parser for PHP 5.3", - "homepage": "http://behat.org/", - "keywords": [ - "BDD", - "Behat", - "DSL", - "Symfony2", - "parser" - ], - "time": "2013-10-15T11:22:17+00:00" - }, - { - "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v0.4.4", - "source": { - "type": "git", - "url": "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/Dealerdirect/phpcodesniffer-composer-installer.git", - "reference": "2e41850d5f7797cbb1af7b030d245b3b24e63a08" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/2e41850d5f7797cbb1af7b030d245b3b24e63a08", - "reference": "2e41850d5f7797cbb1af7b030d245b3b24e63a08", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0", - "php": "^5.3|^7", - "squizlabs/php_codesniffer": "*" - }, - "require-dev": { - "composer/composer": "*", - "wimg/php-compatibility": "^8.0" - }, - "suggest": { - "dealerdirect/qa-tools": "All the PHP QA tools you'll need" - }, - "type": "composer-plugin", - "extra": { - "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" - }, - "autoload": { - "psr-4": { - "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Franck Nijhof", - "email": "f.nijhof@dealerdirect.nl", - "homepage": "http://workingatdealerdirect.eu", - "role": "Developer" - } - ], - "description": "PHP_CodeSniffer Standards Composer Installer Plugin", - "homepage": "http://workingatdealerdirect.eu", - "keywords": [ - "PHPCodeSniffer", - "PHP_CodeSniffer", - "code quality", - "codesniffer", - "composer", - "installer", - "phpcs", - "plugin", - "qa", - "quality", - "standard", - "standards", - "style guide", - "stylecheck", - "tests" - ], - "time": "2017-12-06T16:27:17+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "1.2.18", - "source": { - "type": "git", - "url": "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/sebastianbergmann/php-code-coverage.git", - "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b", - "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "phpunit/php-file-iterator": ">=1.3.0@stable", - "phpunit/php-text-template": ">=1.2.0@stable", - "phpunit/php-token-stream": ">=1.1.3,<1.3.0" - }, - "require-dev": { - "phpunit/phpunit": "3.7.*@dev" - }, - "suggest": { - "ext-dom": "*", - "ext-xdebug": ">=2.0.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "PHP/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "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/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "time": "2014-09-02T10:13:14+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "1.4.5", - "source": { - "type": "git", - "url": "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/sebastianbergmann/php-file-iterator.git", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "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/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "time": "2017-11-27T13:52:08+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "1.2.1", - "source": { - "type": "git", - "url": "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/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "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/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "time": "2015-06-21T13:50:34+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "1.0.9", - "source": { - "type": "git", - "url": "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/sebastianbergmann/php-timer.git", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "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/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "time": "2017-02-26T11:10:40+00:00" - }, - { - "name": "phpunit/php-token-stream", - "version": "1.2.2", - "source": { - "type": "git", - "url": "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/sebastianbergmann/php-token-stream.git", - "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/ad4e1e23ae01b483c16f600ff1bebec184588e32", - "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2-dev" - } - }, - "autoload": { - "classmap": [ - "PHP/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "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/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "time": "2014-03-03T05:10:30+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "3.7.38", - "source": { - "type": "git", - "url": "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/sebastianbergmann/phpunit.git", - "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/38709dc22d519a3d1be46849868aa2ddf822bcf6", - "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "ext-dom": "*", - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=5.3.3", - "phpunit/php-code-coverage": "~1.2", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.1", - "phpunit/php-timer": "~1.0", - "phpunit/phpunit-mock-objects": "~1.2", - "symfony/yaml": "~2.0" - }, - "require-dev": { - "pear-pear.php.net/pear": "1.9.4" - }, - "suggest": { - "phpunit/php-invoker": "~1.1" - }, - "bin": [ - "composer/bin/phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.7.x-dev" - } - }, - "autoload": { - "classmap": [ - "PHPUnit/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "", - "../../symfony/yaml/" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "http://www.phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "time": "2014-10-17T09:04:17+00:00" - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "1.2.3", - "source": { - "type": "git", - "url": "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/sebastianbergmann/phpunit-mock-objects.git", - "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5794e3c5c5ba0fb037b11d8151add2a07fa82875", - "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "phpunit/php-text-template": ">=1.1.1@stable" - }, - "suggest": { - "ext-soap": "*" - }, - "type": "library", - "autoload": { - "classmap": [ - "PHPUnit/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Mock Object library for PHPUnit", - "homepage": "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/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" - ], - "time": "2013-01-13T10:24:48+00:00" - }, - { - "name": "roave/security-advisories", - "version": "dev-master", - "source": { - "type": "git", - "url": "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/Roave/SecurityAdvisories.git", - "reference": "94230db36bded9d164ffccabcb38c67eedd63595" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/94230db36bded9d164ffccabcb38c67eedd63595", - "reference": "94230db36bded9d164ffccabcb38c67eedd63595", - "shasum": "" - }, - "conflict": { - "adodb/adodb-php": "<5.20.6", - "amphp/artax": "<1.0.6|>=2,<2.0.6", - "aws/aws-sdk-php": ">=3,<3.2.1", - "bugsnag/bugsnag-laravel": ">=2,<2.0.2", - "cakephp/cakephp": ">=1.3,<1.3.18|>=2,<2.4.99|>=2.5,<2.5.99|>=2.6,<2.6.12|>=2.7,<2.7.6|>=3,<3.0.15|>=3.1,<3.1.4", - "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4", - "cartalyst/sentry": "<=2.1.6", - "codeigniter/framework": "<=3.0.6", - "composer/composer": "<=1.0.0-alpha11", - "contao-components/mediaelement": ">=2.14.2,<2.21.1", - "contao/core": ">=2,<3.5.32", - "contao/core-bundle": ">=4,<4.4.8", - "contao/listing-bundle": ">=4,<4.4.8", - "contao/newsletter-bundle": ">=4,<4.1", - "doctrine/annotations": ">=1,<1.2.7", - "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2", - "doctrine/common": ">=2,<2.4.3|>=2.5,<2.5.1", - "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2", - "doctrine/doctrine-bundle": "<1.5.2", - "doctrine/doctrine-module": "<=0.7.1", - "doctrine/mongodb-odm": ">=1,<1.0.2", - "doctrine/mongodb-odm-bundle": ">=2,<3.0.1", - "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1", - "dompdf/dompdf": ">=0.6,<0.6.2", - "drupal/core": ">=8,<8.3.7", - "drupal/drupal": ">=8,<8.3.7", - "ezsystems/ezpublish-legacy": ">=5.3,<5.3.12.2|>=5.4,<5.4.10.1|>=2017.8,<2017.8.1.1", - "firebase/php-jwt": "<2", - "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", - "friendsofsymfony/user-bundle": ">=1.2,<1.3.5", - "gree/jose": "<=2.2", - "gregwar/rst": "<1.0.3", - "guzzlehttp/guzzle": ">=6,<6.2.1|>=4.0.0-rc2,<4.2.4|>=5,<5.3.1", - "illuminate/auth": ">=4,<4.0.99|>=4.1,<4.1.26", - "illuminate/database": ">=4,<4.0.99|>=4.1,<4.1.29", - "joomla/session": "<1.3.1", - "laravel/framework": ">=4,<4.0.99|>=4.1,<4.1.29", - "laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10", - "magento/magento1ce": ">=1.5.0.1,<1.9.3.2", - "magento/magento1ee": ">=1.9,<1.14.3.2", - "magento/magento2ce": ">=2,<2.2", - "monolog/monolog": ">=1.8,<1.12", - "namshi/jose": "<2.2", - "onelogin/php-saml": "<2.10.4", - "oro/crm": ">=1.7,<1.7.4", - "oro/platform": ">=1.7,<1.7.4", - "padraic/humbug_get_contents": "<1.1.2", - "phpmailer/phpmailer": ">=5,<5.2.24", - "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5.0.10,<5.6.3", - "phpxmlrpc/extras": "<0.6.1", - "pusher/pusher-php-server": "<2.2.1", - "sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9", - "shopware/shopware": "<5.3.7", - "silverstripe/cms": ">=3,<=3.0.11|>=3.1,<3.1.11", - "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", - "silverstripe/framework": ">=3,<3.3", - "silverstripe/userforms": "<3", - "simplesamlphp/saml2": "<1.10.4|>=2,<2.3.5|>=3,<3.1.1", - "simplesamlphp/simplesamlphp": "<1.15.2", - "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1", - "socalnick/scn-social-auth": "<1.15.2", - "squizlabs/php_codesniffer": ">=1,<2.8.1", - "swiftmailer/swiftmailer": ">=4,<5.4.5", - "symfony/dependency-injection": ">=2,<2.0.17", - "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", - "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2", - "symfony/http-foundation": ">=2,<2.3.27|>=2.4,<2.5.11|>=2.6,<2.6.6", - "symfony/http-kernel": ">=2,<2.3.29|>=2.4,<2.5.12|>=2.6,<2.6.8", - "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", - "symfony/routing": ">=2,<2.0.19", - "symfony/security": ">=2,<2.0.25|>=2.1,<2.1.13|>=2.2,<2.2.9|>=2.3,<2.3.37|>=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8.23,<2.8.25|>=3.2.10,<3.2.12|>=3.3.3,<3.3.5", - "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<2.8.6|>=2.8.23,<2.8.25|>=3,<3.0.6|>=3.2.10,<3.2.12|>=3.3.3,<3.3.5", - "symfony/security-csrf": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", - "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", - "symfony/serializer": ">=2,<2.0.11", - "symfony/symfony": ">=2,<2.3.41|>=2.4,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", - "symfony/translation": ">=2,<2.0.17", - "symfony/validator": ">=2,<2.0.24|>=2.1,<2.1.12|>=2.2,<2.2.5|>=2.3,<2.3.3", - "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4", - "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7", - "thelia/backoffice-default-template": ">=2.1,<2.1.2", - "thelia/thelia": ">=2.1.0-beta1,<2.1.3|>=2.1,<2.1.2", - "twig/twig": "<1.20", - "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.22|>=8,<8.7.5", - "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.10|>=3.1,<3.1.7|>=3.2,<3.2.7|>=3.3,<3.3.5", - "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4", - "willdurand/js-translation-bundle": "<2.1.1", - "yiisoft/yii": ">=1.1.14,<1.1.15", - "yiisoft/yii2": "<2.0.14", - "yiisoft/yii2-bootstrap": "<2.0.4", - "yiisoft/yii2-dev": "<2.0.14", - "yiisoft/yii2-gii": "<2.0.4", - "yiisoft/yii2-jui": "<2.0.4", - "zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3", - "zendframework/zend-captcha": ">=2,<2.4.9|>=2.5,<2.5.2", - "zendframework/zend-crypt": ">=2,<2.4.9|>=2.5,<2.5.2", - "zendframework/zend-db": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.10|>=2.3,<2.3.5", - "zendframework/zend-diactoros": ">=1,<1.0.4", - "zendframework/zend-form": ">=2,<2.2.7|>=2.3,<2.3.1", - "zendframework/zend-http": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.3,<2.3.8|>=2.4,<2.4.1", - "zendframework/zend-json": ">=2.1,<2.1.6|>=2.2,<2.2.6", - "zendframework/zend-ldap": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.8|>=2.3,<2.3.3", - "zendframework/zend-mail": ">=2,<2.4.11|>=2.5,<2.7.2", - "zendframework/zend-navigation": ">=2,<2.2.7|>=2.3,<2.3.1", - "zendframework/zend-session": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.9|>=2.3,<2.3.4", - "zendframework/zend-validator": ">=2.3,<2.3.6", - "zendframework/zend-view": ">=2,<2.2.7|>=2.3,<2.3.1", - "zendframework/zend-xmlrpc": ">=2.1,<2.1.6|>=2.2,<2.2.6", - "zendframework/zendframework": ">=2,<2.4.11|>=2.5,<2.5.1", - "zendframework/zendframework1": "<1.12.20", - "zendframework/zendopenid": ">=2,<2.0.2", - "zendframework/zendxml": ">=1,<1.0.1", - "zetacomponents/mail": "<1.8.2", - "zf-commons/zfc-user": "<1.2.2", - "zfcampus/zf-apigility-doctrine": ">=1,<1.0.3", - "zfr/zfr-oauth2-server-module": "<0.1.2" - }, - "type": "metapackage", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "role": "maintainer" - } - ], - "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", - "time": "2018-02-19T09:31:21+00:00" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "2.9.1", - "source": { - "type": "git", - "url": "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/squizlabs/PHP_CodeSniffer.git", - "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/dcbed1074f8244661eecddfc2a675430d8d33f62", - "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.1.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "bin": [ - "scripts/phpcs", - "scripts/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "classmap": [ - "CodeSniffer.php", - "CodeSniffer/CLI.php", - "CodeSniffer/Exception.php", - "CodeSniffer/File.php", - "CodeSniffer/Fixer.php", - "CodeSniffer/Report.php", - "CodeSniffer/Reporting.php", - "CodeSniffer/Sniff.php", - "CodeSniffer/Tokens.php", - "CodeSniffer/Reports/", - "CodeSniffer/Tokenizers/", - "CodeSniffer/DocGenerators/", - "CodeSniffer/Standards/AbstractPatternSniff.php", - "CodeSniffer/Standards/AbstractScopeSniff.php", - "CodeSniffer/Standards/AbstractVariableSniff.php", - "CodeSniffer/Standards/IncorrectPatternException.php", - "CodeSniffer/Standards/Generic/Sniffs/", - "CodeSniffer/Standards/MySource/Sniffs/", - "CodeSniffer/Standards/PEAR/Sniffs/", - "CodeSniffer/Standards/PSR1/Sniffs/", - "CodeSniffer/Standards/PSR2/Sniffs/", - "CodeSniffer/Standards/Squiz/Sniffs/", - "CodeSniffer/Standards/Zend/Sniffs/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "lead" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "http://www.squizlabs.com/php-codesniffer", - "keywords": [ - "phpcs", - "standards" - ], - "time": "2017-05-22T02:43:20+00:00" - }, - { - "name": "wp-coding-standards/wpcs", - "version": "0.13.1", - "source": { - "type": "git", - "url": "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/WordPress-Coding-Standards/WordPress-Coding-Standards.git", - "reference": "1f64b1a0b5b789822d0303436ee4e30e0135e4dc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/WordPress-Coding-Standards/WordPress-Coding-Standards/zipball/1f64b1a0b5b789822d0303436ee4e30e0135e4dc", - "reference": "1f64b1a0b5b789822d0303436ee4e30e0135e4dc", - "shasum": "" - }, - "require": { - "php": ">=5.3", - "squizlabs/php_codesniffer": "^2.9.0 || ^3.0.2" - }, - "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1" - }, - "type": "phpcodesniffer-standard", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Contributors", - "homepage": "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/WordPress-Coding-Standards/WordPress-Coding-Standards/graphs/contributors" - } - ], - "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress coding conventions", - "keywords": [ - "phpcs", - "standards", - "wordpress" - ], - "time": "2017-08-05T16:08:58+00:00" - } - ], - "aliases": [], - "minimum-stability": "dev", - "stability-flags": { - "roave/security-advisories": 20 - }, - "prefer-stable": true, - "prefer-lowest": false, - "platform": { - "php": ">=5.3.29" - }, - "platform-dev": [], - "platform-overrides": { - "php": "5.3.29" - } -} From 5e5fb42687b6824c00feb227e707d380beb443e4 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 19 Feb 2018 23:53:55 +0000 Subject: [PATCH 212/214] Out damned PHPCompatibility. --- phpcs.xml.dist | 7 ------- 1 file changed, 7 deletions(-) diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 05a05ad455..8d83f89d54 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -20,13 +20,6 @@ */vendor/* */.phan/* - - - - - - - From 3c8822ce584af4797ce2cc7af508952707d8e88d Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 20 Feb 2018 00:14:36 +0000 Subject: [PATCH 213/214] Update utils get_temp_dir test. --- features/utils.feature | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/features/utils.feature b/features/utils.feature index 87a1a6af68..a241f3583c 100644 --- a/features/utils.feature +++ b/features/utils.feature @@ -32,18 +32,18 @@ Feature: Utilities that do NOT depend on WordPress code @require-php-5.5 Scenario: Check `Utils\get_temp_dir()` when `sys_temp_dir` directive set # `sys_temp_dir` set to unwritable. - When I try `{INVOKE_WP_CLI_WITH_PHP_ARGS--dsys_temp_dir=\\tmp\\} --skip-wordpress eval 'echo WP_CLI\Utils\get_temp_dir();'` + When I try `{INVOKE_WP_CLI_WITH_PHP_ARGS--dsys_temp_dir=\\no_such_directory/} --skip-wordpress eval 'echo WP_CLI\Utils\get_temp_dir();'` Then STDERR should contain: """ Warning: Temp directory isn't writable """ And STDERR should contain: """ - \tmp/ + /no_such_directory/ """ And STDOUT should be: """ - \tmp/ + /no_such_directory/ """ And the return code should be 0 From 48a23c003ea01c091c0f5efe4dd41edbb74703eb Mon Sep 17 00:00:00 2001 From: gitlost Date: Fri, 23 Feb 2018 05:11:45 +0000 Subject: [PATCH 214/214] Remove git-setup-pre-commit-hook. --- composer.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/composer.json b/composer.json index 25b69315fa..2929dfacdb 100644 --- a/composer.json +++ b/composer.json @@ -79,11 +79,6 @@ "psr-0": { "WP_CLI": "php" }, "psr-4": { "": "php/commands/src" } }, - "scripts": { - "post-install-cmd": [ - "./utils/git-setup-pre-commit-hook" - ] - }, "extra": { "branch-alias": { "dev-master": "1.5.x-dev"