discourse/lib/version.rb
Ted Johansson e3ce8d6858
FIX: New features git hash version tweaks (#34671)
There are two issues addressed by this PR:

We log an error to console when a git hash is passed to Discourse#has_needed_version?. This isn't correct. We should just return false.
We only check that the commit hash is in the repo, we don't check that it's actually an ancestor in the current tree. So you'd see the feature even if you're on a branch that doesn't have it.
2025-09-02 10:40:24 +08:00

130 lines
3.8 KiB
Ruby

# frozen_string_literal: true
module Discourse
VERSION_REGEXP = /\A\d+\.\d+\.\d+(\.beta\d+)?\z/
VERSION_COMPATIBILITY_FILENAME = ".discourse-compatibility"
# work around reloader
unless defined?(::Discourse::VERSION)
module VERSION #:nodoc:
# Use the `version_bump:*` rake tasks to update this value
STRING = "3.6.0.beta1-dev"
PARTS = STRING.split(".")
private_constant :PARTS
MAJOR = PARTS[0].to_i
MINOR = PARTS[1].to_i
TINY = PARTS[2].to_i
PRE = PARTS[3]&.split("-", 2)&.[](0)
DEV = PARTS[3]&.split("-", 2)&.[](1)
end
end
class InvalidVersionListError < StandardError
end
def self.has_needed_version?(current, needed)
Gem::Version.new(current) >= Gem::Version.new(needed)
rescue ArgumentError
false
end
# lookup an external resource (theme/plugin)'s best compatible version
# compatible resource files are YAML, in the format:
# `discourse_version: plugin/theme git reference.` For example:
# 2.5.0.beta6: c4a6c17
# 2.5.0.beta4: d1d2d3f
# 2.5.0.beta2: bbffee
# 2.4.4.beta6: some-other-branch-ref
# 2.4.2.beta1: v1-tag
def self.find_compatible_resource(version_list, target_version = ::Discourse::VERSION::STRING)
return if version_list.blank?
begin
version_list = YAML.safe_load(version_list)
rescue Psych::SyntaxError, Psych::DisallowedClass => e
end
raise InvalidVersionListError unless version_list.is_a?(Hash)
version_list =
version_list
.transform_keys do |v|
Gem::Requirement.parse(v)
rescue Gem::Requirement::BadRequirementError => e
raise InvalidVersionListError, "Invalid version specifier: #{v}"
end
.sort_by do |parsed_requirement, _|
operator, version = parsed_requirement
[version, operator == "<" ? 0 : 1]
end
parsed_target_version = Gem::Version.new(target_version)
lowest_matching_entry =
version_list.find do |parsed_requirement, target|
req_operator, req_version = parsed_requirement
req_operator = "<=" if req_operator == "="
if !%w[<= <].include?(req_operator)
raise InvalidVersionListError,
"Invalid version specifier operator for '#{req_operator} #{req_version}'. Operator must be one of <= or <"
end
resolved_requirement = Gem::Requirement.new("#{req_operator} #{req_version}")
resolved_requirement.satisfied_by?(parsed_target_version)
end
return if lowest_matching_entry.nil?
checkout_version = lowest_matching_entry[1]
begin
Discourse::Utils.execute_command "git",
"check-ref-format",
"--allow-onelevel",
checkout_version
rescue RuntimeError
raise InvalidVersionListError, "Invalid ref name: #{checkout_version}"
end
checkout_version
end
# Find a compatible resource from a git repo
def self.find_compatible_git_resource(path)
return unless File.directory?("#{path}/.git")
tree_info =
Discourse::Utils.execute_command(
"git",
"-C",
path,
"ls-tree",
"-l",
"HEAD",
Discourse::VERSION_COMPATIBILITY_FILENAME,
)
blob_size = tree_info.split[3].to_i
if blob_size > Discourse::MAX_METADATA_FILE_SIZE
$stderr.puts "#{Discourse::VERSION_COMPATIBILITY_FILENAME} file in #{path} too big"
return
end
compat_resource =
Discourse::Utils.execute_command(
"git",
"-C",
path,
"show",
"HEAD@{upstream}:#{Discourse::VERSION_COMPATIBILITY_FILENAME}",
)
Discourse.find_compatible_resource(compat_resource)
rescue InvalidVersionListError => e
$stderr.puts "Invalid version list in #{path}"
rescue Discourse::Utils::CommandError => e
nil
end
end