Class: Bundler::Overrule::Reporter

Inherits:
Object
  • Object
show all
Defined in:
lib/bundler/overrule/reporter.rb

Overview

Warnings, overrule list / overrule doctor output, and the state file.

The exact warning text is part of this gem's user experience — it is the only thing standing between an override and a silent surprise — so it is asserted verbatim in the specs.

Constant Summary collapse

STATE_FILE =
"overrule-report.json"
"[bundler-overrule]"
RULE_LABELS =
{ force: "force", ban: "ban  ", swap: "swap " }.freeze
TABLE_HEADERS =
%w[TYPE GEM REQUIREMENT REASON].freeze
TABLE_KEYS =
%w[type gem requirement reason].freeze
TABLE_SEPARATOR =
"  "

Instance Method Summary collapse

Constructor Details

#initialize(registry, ui: nil) ⇒ Reporter

Returns a new instance of Reporter.



24
25
26
27
# File 'lib/bundler/overrule/reporter.rb', line 24

def initialize(registry, ui: nil)
  @registry = registry
  @ui = ui
end

Instance Method Details

#doctorObject

bundle overrule doctor



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/bundler/overrule/reporter.rb', line 66

def doctor
  problems = []
  notes = []

  problems.concat(check_bundler_supported)
  problems.concat(check_bootstrap_present)
  problems.concat(check_stale_rules)
  notes.concat(check_state_freshness)

  out = ["#{BANNER} doctor", ""]
  if problems.empty?
    out << "  ✓ no problems found"
  else
    problems.each { |p| out << "  #{p}" }
  end
  unless notes.empty?
    out << ""
    notes.each { |n| out << "  #{n}" }
  end
  out
end

#healthy?Boolean

Returns:

  • (Boolean)


88
89
90
# File 'lib/bundler/overrule/reporter.rb', line 88

def healthy?
  check_bundler_supported.empty? && check_bootstrap_present.empty? && check_stale_rules.empty?
end

#listObject

bundle overrule list



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/bundler/overrule/reporter.rb', line 46

def list
  state = read_state
  return ["#{BANNER} no rules are active.", "", hint_for_empty(state)] if @registry.empty? && state.nil?

  rules = @registry.any? ? rules_from_registry : rules_from_state(state)
  return ["#{BANNER} no rules are active."] if rules.empty?

  out = ["#{BANNER} #{pluralize(rules.size, "rule")}:", ""]
  out.concat(render_table(rules))
  out << ""
  out << if state
           "Edges below were recorded during the last resolution " \
             "(#{state["generated_at"]}, Bundler #{state["bundler_version"]})."
         else
           "No resolution recorded yet — run `bundle install` to see which edges are rewritten."
         end
  out
end


38
39
40
41
42
43
# File 'lib/bundler/overrule/reporter.rb', line 38

def print_summary
  lines = summary
  return if lines.empty?

  lines.each { |line| ui.warn(line) }
end

#read_stateObject



123
124
125
126
127
128
129
130
# File 'lib/bundler/overrule/reporter.rb', line 123

def read_state
  path = state_path
  return nil if path.nil? || !File.exist?(path)

  JSON.parse(File.read(path))
rescue JSON::ParserError, SystemCallError
  nil
end

#state_pathObject

---- state file -------------------------------------------------------



94
95
96
97
98
# File 'lib/bundler/overrule/reporter.rb', line 94

def state_path
  ::Bundler.app_config_path.join(STATE_FILE)
rescue StandardError
  nil
end

#summaryObject

The block printed during bundle install / bundle update.



30
31
32
33
34
35
36
# File 'lib/bundler/overrule/reporter.rb', line 30

def summary
  return [] if @registry.empty?

  header = "#{BANNER} #{pluralize(@registry.rules.size, "rule")} active — " \
           "YOU own the consequences of these overrides:"
  [header, *@registry.rules.map { |rule| "  #{rule_line(rule)}" }]
end

#write_state!Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/bundler/overrule/reporter.rb', line 100

def write_state!
  path = state_path
  return nil if path.nil? || @registry.empty?

  payload = {
    "schema" => 1,
    "overrule_version" => Overrule::VERSION,
    "bundler_version" => ::Bundler::VERSION,
    "generated_at" => Time.now.utc.iso8601,
    "fingerprint" => @registry.fingerprint,
    "rules" => @registry.rules.map { |r| rule_to_h(r) },
    "edges" => edges_to_persist
  }

  require "fileutils"
  FileUtils.mkdir_p(File.dirname(path))
  File.write(path, "#{JSON.pretty_generate(payload)}\n")
  path
rescue SystemCallError
  # A read-only checkout is not a reason to fail an install.
  nil
end