Module: RecentRuby

Defined in:
lib/recent_ruby.rb,
lib/recent_ruby/version.rb,
lib/recent_ruby/xml_ast.rb

Defined Under Namespace

Classes: XMLAST

Constant Summary collapse

RUBY_NODE_XPATH =
"//send[symbol-val[@value='ruby']]"
VERSION_XPATH =
"#{RUBY_NODE_XPATH}/str/string-val/@value"
FILE_XPATH =
"#{RUBY_NODE_XPATH}/hash/pair[sym[symbol-val[@value='file']]]"
FILE_VALUE_XPATH =
"#{FILE_XPATH}/str/string-val/@value"
PATCHLEVEL_XPATH =
"#{RUBY_NODE_XPATH}/hash/pair[sym[symbol-val[@value='patchlevel']]]"
PATCHLEVEL_VALUE_XPATH =
"#{PATCHLEVEL_XPATH}/int/integer-val/@value"
VERSION =
'0.1.6'.freeze

Instance Method Summary collapse

Instance Method Details

#check_eol(version, version_base_url) ⇒ Object



81
82
83
84
85
86
87
88
89
# File 'lib/recent_ruby.rb', line 81

def check_eol(version, version_base_url)
  puts "Downloading details for #{version}..."
  details = http_get("#{version_base_url}#{version}")
  puts 'Checking EOL status...'

  return unless details =~ / warn_eol /
  puts "EOL warning found for #{version}!"
  exit 1
end

#compare_versions(version, latest, minor) ⇒ Object



91
92
93
94
95
96
# File 'lib/recent_ruby.rb', line 91

def compare_versions(version, latest, minor)
  puts 'Comparing version numbers...'
  return if version == latest
  puts "Current version is #{version}, but the latest patch release for #{minor.join('.')} is #{latest}!"
  exit 1
end

#get_rubies(versions_url) ⇒ Object



64
65
66
67
# File 'lib/recent_ruby.rb', line 64

def get_rubies(versions_url)
  puts 'Downloading latest list of Rubies from Github...'
  JSON.parse(http_get(versions_url))
end

#http_get(url) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/recent_ruby.rb', line 16

def http_get(url)
  uri = URI(url)
  Net::HTTP.start(uri.host, uri.port,
                  use_ssl: uri.scheme == 'https') do |http|
    request = Net::HTTP::Get.new uri
    response = http.request request
    if response.code != '200'
      puts "Error: received HTTP #{response.code} response from Github:\n\n#{response.body}"
      exit(2)
    end
    response.body
  end
end

#latest_minor_version(rubies, minor) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
# File 'lib/recent_ruby.rb', line 69

def latest_minor_version(rubies, minor)
  minor_rubies = rubies.map { |n| n['name'] }.select do |n|
    n =~ /^\d+\.\d+\.\d+(-p\d+)?$/ &&
      n.split('.')[0, 2] == minor
  end

  minor_rubies.max_by do |ruby|
    a, b, c, d = *ruby.sub('-p', '.').split('.').map(&:to_i)
    [a, b, c, d || -1]
  end
end

#parse_gemfile(gemfile) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/recent_ruby.rb', line 40

def parse_gemfile(gemfile)
  ast = parser_for_current_ruby.parse(File.read(gemfile))
  xml = RecentRuby::XMLAST.new(ast)

  file = xml.xpath(FILE_VALUE_XPATH)&.first&.value
  version = xml.xpath(VERSION_XPATH)&.first&.value
  version = File.read(file).strip if !version && file

  unless version
    puts 'Unable to find ruby version in gemfile.'
    exit(1)
  end

  patchlevel = xml.xpath(PATCHLEVEL_VALUE_XPATH)&.first&.value
  version += "-p#{patchlevel}" if patchlevel
  version
end

#parser_for_current_rubyObject



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/recent_ruby.rb', line 99

def parser_for_current_ruby
  code_version = RUBY_VERSION.to_f

  if code_version <= 3.3
    require 'parser/current'
    Parser::CurrentRuby
  else
    require 'prism'
    case code_version
    when 3.3
      Prism::Translation::Parser33
    when 3.4
      Prism::Translation::Parser34
    else
      warn "Unknown Ruby version #{code_version}, using 3.4 as a fallback"
      Prism::Translation::Parser34
    end
  end
end

#validate_args(gemfile, version) ⇒ Object



30
31
32
33
34
35
36
37
38
# File 'lib/recent_ruby.rb', line 30

def validate_args(gemfile, version)
  if gemfile && version
    puts 'Please supply only one argument. Run with -h for more information.'
    exit(1)
  elsif !gemfile && !version
    puts 'Please supply either a gemfile path or a version string. Run with -h for more information.'
    exit(1)
  end
end

#validate_mri_version(version) ⇒ Object



58
59
60
61
62
# File 'lib/recent_ruby.rb', line 58

def validate_mri_version(version)
  return if version =~ /^(\d+\.\d+\.\d+(-p\d+)?)$/
  puts 'Only stable release MRI version strings are currently supported. (e.g. 2.3.1 or 2.3.1-p12)'
  exit(1)
end