Module: BB::Gem

Defined in:
lib/blackbox/gem.rb

Overview

Gem utilities.

Class Method Summary (collapse)

Class Method Details

+ (Hash) version_info(*_, **opts)

Return information about the currently installed gem version and the latest available version on rubygems.org.

Parameters:

  • opts (Hash)

    the options to create a message with.

Options Hash (**opts):

  • :check_interval (Fixnum)

    how frequently to query rubygems.org (default: 3600)

  • :disabling_env_var (String) — default: default: #GEMNAMEE}_DISABLE_VERSION_CHECK
  • [] (Object)

    :from ('nobody') From address

Returns:

  • (Hash)

    result

    • :gem_name => name of current gem

    • :gem_installed_version => installed version

    • :gem_latest_version => latest version on rubygems.org

    • :last_checked_for_update => timestamp of last query to rubygems.org

    • :next_check_for_update => timestamp of next query to rubygems.org

    • :gem_update_available => update available?

    • :installed_is_latest => is installed version == latest available version?



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/blackbox/gem.rb', line 22

def version_info(*_, **opts)
  ret = {
    gem_name: :unknown,
    gem_installed_version: :unknown,
    gem_latest_version: :unknown,
    gem_update_available: false,
    last_checked_for_update: :unknown,
    next_check_for_update: :unknown,
    installed_is_latest: true
  }

  calling_file = caller[0].split(':')[0]
  spec = ::Gem::Specification.find do |s|
    File.fnmatch(File.join(s.full_gem_path, '*'), calling_file)
  end

  ret[:gem_installed_version] = spec&.version&.to_s || :unknown
  ret[:gem_name] = spec&.name || :unknown

  opts = { # defaults
    check_interval: 3600,
    disabling_env_var: "#{ret[:gem_name].upcase}_DISABLE_VERSION_CHECK"
  }.merge(opts)

  return ret if ret[:gem_name] == :unknown
  return ret if ret[:gem_installed_version] == :unknown
  if opts[:disabling_env_var] && ENV.include?(opts[:disabling_env_var])
    ret[:next_check_for_update] = :never
    return ret
  end

  require 'gem_update_checker'
  require 'tmpdir'
  require 'fileutils'

  statefile_path = File.join(Dir.tmpdir, "#{ret[:gem_name]}-#{ret[:gem_installed_version]}.last_update_check")

  last_check_at = nil
  begin
    last_check_at = File.stat(statefile_path).mtime
  rescue
    last_check_at = Time.at(0)
  end

  ret.merge!(
    last_checked_for_update: last_check_at,
    next_check_for_update: last_check_at + opts[:check_interval]
  )

  return ret if last_check_at + opts[:check_interval] > Time.now && !opts[:force_check]

  checker = GemUpdateChecker::Client.new(ret[:gem_name], ret[:gem_installed_version])
  last_check_at = Time.now

  ret.merge!(
    gem_latest_version: checker.latest_version,
    last_checked_for_update: last_check_at,
    next_check_for_update: last_check_at + opts[:check_interval],
    installed_is_latest: ret[:gem_installed_version] == checker.latest_version,
    gem_update_available: Versionomy.parse(ret[:gem_installed_version]) < Versionomy.parse(checker.latest_version)
  )

  if ret[:installed_is_latest] || opts[:force_check]
    FileUtils.touch(statefile_path, mtime: Time.now)
  else
    ret[:next_check_for_update] = Time.now
  end

  ret
end