diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-06-12 18:10:26 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-06-12 18:10:26 +0300 |
commit | c0b17cee8be646588b14db49ad6d91b8cc818f97 (patch) | |
tree | 97287971303bccd649da1718c1a3a1ba8f345df6 /app/presenters/packages | |
parent | 8ef107c43390ea9c9932afb55d1318e4716fbf3b (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/presenters/packages')
4 files changed, 93 insertions, 4 deletions
diff --git a/app/presenters/packages/nuget/packages_metadata_presenter.rb b/app/presenters/packages/nuget/packages_metadata_presenter.rb index 10a19060f8a..f87f447fb23 100644 --- a/app/presenters/packages/nuget/packages_metadata_presenter.rb +++ b/app/presenters/packages/nuget/packages_metadata_presenter.rb @@ -59,8 +59,8 @@ module Packages end def sorted_versions - versions = @packages.map(&:version).compact - VersionSorter.sort(versions) + versions = @packages.filter_map(&:version) + sort_versions(versions) end strong_memoize_attr :sorted_versions end diff --git a/app/presenters/packages/nuget/presenter_helpers.rb b/app/presenters/packages/nuget/presenter_helpers.rb index ea8558c54f4..16c32a9d0d0 100644 --- a/app/presenters/packages/nuget/presenter_helpers.rb +++ b/app/presenters/packages/nuget/presenter_helpers.rb @@ -4,6 +4,7 @@ module Packages module Nuget module PresenterHelpers include ::API::Helpers::RelatedResourcesHelpers + include Packages::Nuget::VersionHelpers PACKAGE_DEPENDENCY_GROUP = 'PackageDependencyGroup' PACKAGE_DEPENDENCY = 'PackageDependency' diff --git a/app/presenters/packages/nuget/search_results_presenter.rb b/app/presenters/packages/nuget/search_results_presenter.rb index 45c2c5170ae..020e8656a36 100644 --- a/app/presenters/packages/nuget/search_results_presenter.rb +++ b/app/presenters/packages/nuget/search_results_presenter.rb @@ -45,8 +45,8 @@ module Packages end def latest_version(packages) - versions = packages.map(&:version).compact - VersionSorter.sort(versions).last + versions = packages.filter_map(&:version) + sort_versions(versions).last end end end diff --git a/app/presenters/packages/nuget/version_helpers.rb b/app/presenters/packages/nuget/version_helpers.rb new file mode 100644 index 00000000000..8c9c82791b3 --- /dev/null +++ b/app/presenters/packages/nuget/version_helpers.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +module Packages + module Nuget + module VersionHelpers + private + + def sort_versions(versions) + versions.sort { |a, b| compare_versions(a, b) } + end + + # NuGet version sorting algorithm as per https://semver.org/spec/v2.0.0.html#spec-item-11 + def compare_versions(version_a, version_b) + return 0 if version_a == version_b + return 1 if version_b.nil? + return -1 if version_a.nil? + + a_without_build_meta, a_build_meta = version_a.split('+', 2) + b_without_build_meta, b_build_meta = version_b.split('+', 2) + + a_core, a_pre = a_without_build_meta.split(/-/, 2) + b_core, b_pre = b_without_build_meta.split(/-/, 2) + + a_core_parts = a_core.split('.') + b_core_parts = b_core.split('.') + + compare_core_parts(a_core_parts, b_core_parts) || + compare_pre_release_parts(a_pre, b_pre) || + pick_non_nil(a_pre, b_pre) || + compare_build_meta_parts(a_build_meta, b_build_meta) + end + + def compare_core_parts(a_core_parts, b_core_parts) + while a_core_parts.any? || b_core_parts.any? + a_part = a_core_parts.shift&.to_i || 0 + b_part = b_core_parts.shift&.to_i || 0 + return a_part <=> b_part if a_part != b_part + end + end + + def compare_pre_release_parts(a_pre, b_pre) + return unless a_pre && b_pre + + a_pre_parts = a_pre.split('.').map(&:downcase) + b_pre_parts = b_pre.split('.').map(&:downcase) + + while a_pre_parts.any? || b_pre_parts.any? + a_pre_part = a_pre_parts.shift + b_pre_part = b_pre_parts.shift + + # Empty parts are considered lower + return -1 if a_pre_part.nil? + return 1 if b_pre_part.nil? + + a_num = a_pre_part.to_i + b_num = b_pre_part.to_i + next if a_num == b_num && a_pre_part.to_s == b_pre_part.to_s # Both are same numeric/alphanumeric parts + + return select_numeric_before_alphanumeric(a_num, a_pre_part, b_num, b_pre_part) || + compare_numeric_parts(a_pre_part, a_num, b_pre_part, b_num) || + a_pre_part <=> b_pre_part + end + end + + def compare_build_meta_parts(a_build_meta, b_build_meta) + (a_build_meta || '').casecmp(b_build_meta || '') + end + + def select_numeric_before_alphanumeric(a_num, a_pre_part, b_num, b_pre_part) + return -1 if a_num != b_num && numeric?(a_pre_part) && !numeric?(b_pre_part) + return 1 if a_num != b_num && !numeric?(a_pre_part) && numeric?(b_pre_part) + end + + def numeric?(pre_part) + !!Integer(pre_part, exception: false) + end + + def compare_numeric_parts(a_pre_part, a_num, b_pre_part, b_num) + a_num <=> b_num if a_num != b_num && numeric?(a_pre_part) && numeric?(b_pre_part) + end + + def pick_non_nil(var_a, var_b) + return -1 if var_a && !var_b + return 1 if !var_a && var_b + end + end + end +end |