<commit_before><?php
/**
 * List all contributors to this release.
 *
 * Usage: wp --require=utils/contrib-list.php contrib-list
 *
 * If you run into GitHub API rate limit issues, set a GITHUB_TOKEN
 * environment variable.
 */

use WP_CLI\Utils;

class Contrib_List_Command {

	/**
	 * List all contributors to this release.
	 *
	 * Run within the main WP-CLI project repository.
	 *
	 * ## OPTIONS
	 *
	 * [--format=<format>]
	 * : Render output in a specific format.
	 * ---
	 * default: markdown
	 * options:
	 *   - markdown
	 *   - html
	 * ---
	 *
	 * @when before_wp_load
	 */
	public function __invoke( $_, $assoc_args ) {

		$contributors = array();
		$contributor_count = 0;
		$pull_request_count = 0;

		// Get the contributors to the current open wp-cli/wp-cli milestone
		$milestones = self::get_project_milestones( 'wp-cli/wp-cli' );
		// Cheap way to get the latest milestone
		$milestone = array_shift( $milestones );
		WP_CLI::log( 'Current open wp-cli/wp-cli milestone: ' . $milestone->title );
		$pull_requests = self::get_project_milestone_pull_requests( 'wp-cli/wp-cli', $milestone->number );
		$repo_contributors = self::parse_contributors_from_pull_requests( $pull_requests );
		WP_CLI::log( ' - Contributors: ' . count( $repo_contributors ) );
		WP_CLI::log( ' - Pull requests: ' . count( $pull_requests ) );
		$pull_request_count += count( $pull_requests );
		$contributors = array_merge( $contributors, $repo_contributors );

		// Get the contributors to the current open wp-cli/handbook milestone
		$milestones = self::get_project_milestones( 'wp-cli/handbook' );
		// Cheap way to get the latest milestone
		$milestone = array_shift( $milestones );
		WP_CLI::log( 'Current open wp-cli/handbook milestone: ' . $milestone->title );
		$pull_requests = self::get_project_milestone_pull_requests( 'wp-cli/handbook', $milestone->number );
		$repo_contributors = self::parse_contributors_from_pull_requests( $pull_requests );
		WP_CLI::log( ' - Contributors: ' . count( $repo_contributors ) );
		WP_CLI::log( ' - Pull requests: ' . count( $pull_requests ) );
		$pull_request_count += count( $pull_requests );
		$contributors = array_merge( $contributors, $repo_contributors );

		// Identify all command dependencies and their contributors
		$response = Utils\http_request( 'GET', 'https://raw.githubusercontent.com/wp-cli/wp-cli/master/composer.json' );
		if ( 200 !== $response->status_code ) {
			WP_CLI::error( sprintf( 'Could not fetch composer.json (HTTP code %d)', $response->status_code ) );
		}
		$composer_json = json_decode( $response->body, true );
		foreach( $composer_json['require'] as $package => $version_constraint ) {
			if ( ! preg_match( '#^wp-cli/.+-command$#', $package ) ) {
				continue;
			}
			// Normalize version constraint to something ew can compare
			$version_constraint = ltrim( $version_constraint, '^' );
			// Closed milestones denote a tagged release
			$milestones = self::get_project_milestones( $package, array( 'state' => 'closed' ) );
			$milestone_ids = array();
			$milestone_titles = array();
			foreach( $milestones as $milestone ) {
				if ( ! version_compare( $milestone->title, $version_constraint, '>' ) ) {
					continue;
				}
				$milestone_ids[] = $milestone->number;
				$milestone_titles[] = $milestone->title;
			}
			// No shipped releases for this milestone.
			if ( empty( $milestone_ids ) ) {
				continue;
			}
			WP_CLI::log( 'Closed ' . $package . ' milestone(s): ' . implode( ', ', $milestone_titles ) );
			foreach( $milestone_ids as $milestone_id ) {
				$pull_requests = self::get_project_milestone_pull_requests( $package, $milestone_id );
				$repo_contributors = self::parse_contributors_from_pull_requests( $pull_requests );
				WP_CLI::log( ' - Contributors: ' . count( $repo_contributors ) );
				WP_CLI::log( ' - Pull requests: ' . count( $pull_requests ) );
				$pull_request_count += count( $pull_requests );
				$contributors = array_merge( $contributors, $repo_contributors );
			}
		}

		WP_CLI::log( 'Total contributors: ' . count( $contributors ) );
		WP_CLI::log( 'Total pull requests: ' . $pull_request_count );

		// Sort and render the contributor list
		asort( $contributors, SORT_NATURAL | SORT_FLAG_CASE );
		if ( in_array( $assoc_args['format'], array( 'markdown', 'html' ) ) ) {
			$contrib_list = '';
			foreach( $contributors as $url => $login ) {
				if ( 'markdown' === $assoc_args['format'] ) {
					$contrib_list .= '[' . $login . '](' . $url . '), ';
				} elseif ( 'html' === $assoc_args['format'] ) {
					$contrib_list .= '<a href="' . $url . '">' . $login . '</a>, ';
				}
			}
			$contrib_list = rtrim( $contrib_list, ', ' );
			WP_CLI::log( $contrib_list );
		}
	}
<commit_msg>Use `composer.lock` of prior release to determine package version<commit_after><?php
/**
 * List all contributors to this release.
 *
 * Usage: wp --require=utils/contrib-list.php contrib-list
 *
 * If you run into GitHub API rate limit issues, set a GITHUB_TOKEN
 * environment variable.
 */

use WP_CLI\Utils;

class Contrib_List_Command {

	/**
	 * List all contributors to this release.
	 *
	 * Run within the main WP-CLI project repository.
	 *
	 * ## OPTIONS
	 *
	 * [--format=<format>]
	 * : Render output in a specific format.
	 * ---
	 * default: markdown
	 * options:
	 *   - markdown
	 *   - html
	 * ---
	 *
	 * @when before_wp_load
	 */
	public function __invoke( $_, $assoc_args ) {

		$contributors = array();
		$contributor_count = 0;
		$pull_request_count = 0;

		// Get the contributors to the current open wp-cli/wp-cli milestone
		$milestones = self::get_project_milestones( 'wp-cli/wp-cli' );
		// Cheap way to get the latest milestone
		$milestone = array_shift( $milestones );
		WP_CLI::log( 'Current open wp-cli/wp-cli milestone: ' . $milestone->title );
		$pull_requests = self::get_project_milestone_pull_requests( 'wp-cli/wp-cli', $milestone->number );
		$repo_contributors = self::parse_contributors_from_pull_requests( $pull_requests );
		WP_CLI::log( ' - Contributors: ' . count( $repo_contributors ) );
		WP_CLI::log( ' - Pull requests: ' . count( $pull_requests ) );
		$pull_request_count += count( $pull_requests );
		$contributors = array_merge( $contributors, $repo_contributors );

		// Get the contributors to the current open wp-cli/handbook milestone
		$milestones = self::get_project_milestones( 'wp-cli/handbook' );
		// Cheap way to get the latest milestone
		$milestone = array_shift( $milestones );
		WP_CLI::log( 'Current open wp-cli/handbook milestone: ' . $milestone->title );
		$pull_requests = self::get_project_milestone_pull_requests( 'wp-cli/handbook', $milestone->number );
		$repo_contributors = self::parse_contributors_from_pull_requests( $pull_requests );
		WP_CLI::log( ' - Contributors: ' . count( $repo_contributors ) );
		WP_CLI::log( ' - Pull requests: ' . count( $pull_requests ) );
		$pull_request_count += count( $pull_requests );
		$contributors = array_merge( $contributors, $repo_contributors );

		// Identify all command dependencies and their contributors
		$milestones = self::get_project_milestones( 'wp-cli/wp-cli', array( 'state' => 'closed' ) );
		// Cheap way to get the latest closed milestone
		$milestone = array_shift( $milestones );
		$composer_lock_url = sprintf( 'https://raw.githubusercontent.com/wp-cli/wp-cli/v%s/composer.lock', $milestone->title );
		WP_CLI::log( 'Fetching ' . $composer_lock_url );
		$response = Utils\http_request( 'GET', $composer_lock_url );
		if ( 200 !== $response->status_code ) {
			WP_CLI::error( sprintf( 'Could not fetch composer.json (HTTP code %d)', $response->status_code ) );
		}
		$composer_json = json_decode( $response->body, true );
		foreach( $composer_json['packages'] as $_ => $package ) {
			$package_name = $package['name'];
			$version_constraint = str_replace( 'v', '', $package['version'] );
			if ( ! preg_match( '#^wp-cli/.+-command$#', $package_name ) ) {
				continue;
			}
			// Closed milestones denote a tagged release
			$milestones = self::get_project_milestones( $package_name, array( 'state' => 'closed' ) );
			$milestone_ids = array();
			$milestone_titles = array();
			foreach( $milestones as $milestone ) {
				if ( ! version_compare( $milestone->title, $version_constraint, '>' ) ) {
					continue;
				}
				$milestone_ids[] = $milestone->number;
				$milestone_titles[] = $milestone->title;
			}
			// No shipped releases for this milestone.
			if ( empty( $milestone_ids ) ) {
				continue;
			}
			WP_CLI::log( 'Closed ' . $package_name . ' milestone(s): ' . implode( ', ', $milestone_titles ) );
			foreach( $milestone_ids as $milestone_id ) {
				$pull_requests = self::get_project_milestone_pull_requests( $package_name, $milestone_id );
				$repo_contributors = self::parse_contributors_from_pull_requests( $pull_requests );
				WP_CLI::log( ' - Contributors: ' . count( $repo_contributors ) );
				WP_CLI::log( ' - Pull requests: ' . count( $pull_requests ) );
				$pull_request_count += count( $pull_requests );
				$contributors = array_merge( $contributors, $repo_contributors );
			}
		}

		WP_CLI::log( 'Total contributors: ' . count( $contributors ) );
		WP_CLI::log( 'Total pull requests: ' . $pull_request_count );

		// Sort and render the contributor list
		asort( $contributors, SORT_NATURAL | SORT_FLAG_CASE );
		if ( in_array( $assoc_args['format'], array( 'markdown', 'html' ) ) ) {
			$contrib_list = '';
			foreach( $contributors as $url => $login ) {
				if ( 'markdown' === $assoc_args['format'] ) {
					$contrib_list .= '[' . $login . '](' . $url . '), ';
				} elseif ( 'html' === $assoc_args['format'] ) {
					$contrib_list .= '<a href="' . $url . '">' . $login . '</a>, ';
				}
			}
			$contrib_list = rtrim( $contrib_list, ', ' );
			WP_CLI::log( $contrib_list );
		}
	}

{'fraction_non_alphanumeric': 0.1555168527814773, 'fraction_numerical': 0.001024485196188915, 'mean_word_length': 3.87125748502994, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 39, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1322052', 'n_tokens_mistral': 3671, 'n_tokens_neox': 3235, 'n_words': 710}