From a8e4fa9340e76626fa0020e23a59fc1ac018cecc Mon Sep 17 00:00:00 2001 From: Geoff Appleby Date: Thu, 22 Aug 2019 00:22:55 -0700 Subject: [PATCH] Optimize version constraints - Only add one range constraint for most recent security release - Exclude individual unsupported releases that are covered by a security release range --- build/build-composer-json.php | 50 ++++++++++++++++++++++++++++++----- build/src/VersionParser.php | 3 +++ 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/build/build-composer-json.php b/build/build-composer-json.php index d553fa5..6e2cd44 100644 --- a/build/build-composer-json.php +++ b/build/build-composer-json.php @@ -56,6 +56,7 @@ function fetchAllData($url, Client $client) { // Security releases $results = fetchAllData('https://www.drupal.org/api-d7/node.json?type=project_release&taxonomy_vocabulary_7=100&field_release_build_type=static', $client); +$securityVersions = []; foreach ($results as $result) { $nid = $result->field_release_project->id; $core = (int) substr($result->field_release_version, 0, 1); @@ -73,18 +74,33 @@ function fetchAllData($url, Client $client) { } try { - $is_core = ($project->field_project_machine_name == 'drupal') ? TRUE : FALSE; - $constraint = VersionParser::generateRangeConstraint($result->field_release_version, $is_core); - if (!$constraint) { - throw new InvalidArgumentException('Invalid version number.'); + $is_core = ($project->field_project_machine_name == 'drupal'); + $versionGroup = $result->field_release_version_major . (($is_core && $core == 8) ? '.' . $result->field_release_version_minor : ''); + + if (empty($securityVersions[$core]['drupal/' . $project->field_project_machine_name][$versionGroup]) + || + version_compare($securityVersions[$core]['drupal/' . $project->field_project_machine_name][$versionGroup], $result->field_release_version, '<') + ) { + $securityVersions[$core]['drupal/' . $project->field_project_machine_name][$versionGroup] = $result->field_release_version; } - $conflict[$core]['drupal/' . $project->field_project_machine_name][] = $constraint; } catch (\Exception $e) { // @todo: log exception continue; } } +foreach ($securityVersions as $core => $packages) { + foreach ($packages as $package => $majorVersions) { + foreach ($majorVersions as $versionGroup => $version) { + $constraint = VersionParser::generateRangeConstraint($version, ($package == 'drupal/drupal')); + if (!$constraint) { + throw new InvalidArgumentException('Invalid version number.'); + } + $conflict[$core][$package][] = $constraint; + } + } +} + // Insecure releases $results = fetchAllData('https://www.drupal.org/api-d7/node.json?type=project_release&taxonomy_vocabulary_7=188131&field_release_build_type=static', $client); foreach ($results as $result) { @@ -104,7 +120,23 @@ function fetchAllData($url, Client $client) { } try { - $is_core = ($project->field_project_machine_name == 'drupal') ? TRUE : FALSE; + $is_core = ($project->field_project_machine_name == 'drupal'); + $versionGroup = $result->field_release_version_major . (($is_core && $core == 8) ? '.' . $result->field_release_version_minor : ''); + + // Cleanup core versions prior to SemVer (e.g. 8.0-alpha1). + if ($is_core && $core == 8 && empty($result->field_release_version_patch)) { + continue; + } + + // Filter any individual releases older than a security release. + if ( + !empty($securityVersions[$core]['drupal/' . $project->field_project_machine_name][$versionGroup]) + && + version_compare($securityVersions[$core]['drupal/' . $project->field_project_machine_name][$versionGroup], $result->field_release_version, '>') + ) { + continue; + } + $constraint = VersionParser::generateExplicitConstraint($result->field_release_version, $is_core); if (!$constraint) { throw new InvalidArgumentException('Invalid version number.'); @@ -131,7 +163,11 @@ function fetchAllData($url, Client $client) { ]; foreach ($packages as $package => $constraints) { - natsort($constraints); + usort($constraints, function ($a, $b) { + preg_match('/=$major,<$version"; + } return ">=$major.$minor,<$version"; }