Class: Bundler::Overrule::Registry
- Inherits:
-
Object
- Object
- Bundler::Overrule::Registry
- Defined in:
- lib/bundler/overrule/registry.rb
Overview
Holds the rules declared in the Gemfile and the edges they rewrote.
There is one of these per process (see Overrule.registry). It is not thread-safe by design: rules are declared during single-threaded Gemfile evaluation. Edge recording does happen from the parallel installer, so that path appends to a plain array and de-duplicates on read rather than locking on every dependency lookup.
Instance Attribute Summary collapse
-
#rules ⇒ Object
readonly
Returns the value of attribute rules.
-
#rules_by_name ⇒ Object
readonly
Fast lookup used on the hot path (once per dependency, per spec).
Instance Method Summary collapse
- #add(rule) ⇒ Object
- #any? ⇒ Boolean
- #bans ⇒ Object
- #clear! ⇒ Object
-
#edges ⇒ Object
Every edge a rule actually changed, de-duplicated.
- #edges_for(rule) ⇒ Object
- #empty? ⇒ Boolean
-
#filter(dependencies, owner: nil) ⇒ Object
Rewrite a dependency list and remember what changed.
-
#fingerprint ⇒ Object
Identifies the current rule set.
- #forces ⇒ Object
-
#initialize ⇒ Registry
constructor
A new instance of Registry.
- #rule_for(name) ⇒ Object
-
#stale_rules ⇒ Object
Rules that matched nothing at all (B3) —
doctorflags these. - #swaps ⇒ Object
Constructor Details
#initialize ⇒ Registry
Returns a new instance of Registry.
21 22 23 |
# File 'lib/bundler/overrule/registry.rb', line 21 def initialize clear! end |
Instance Attribute Details
#rules ⇒ Object (readonly)
Returns the value of attribute rules.
19 20 21 |
# File 'lib/bundler/overrule/registry.rb', line 19 def rules @rules end |
#rules_by_name ⇒ Object (readonly)
Fast lookup used on the hot path (once per dependency, per spec).
41 42 43 |
# File 'lib/bundler/overrule/registry.rb', line 41 def rules_by_name @rules_by_name end |
Instance Method Details
#add(rule) ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/bundler/overrule/registry.rb', line 43 def add(rule) existing = @rules_by_name[rule.name] if existing # Bundler evaluates the Gemfile more than once per invocation, so an # identical re-declaration is expected and must be a no-op. Only a # genuinely different rule for the same gem is an error (B4). return existing if existing == rule raise DuplicateRuleError, <<~MSG duplicate overrule for `#{rule.name}` already declared: #{existing} then declared: #{rule} Each gem may have at most one overrule rule. Pick one and delete the other. MSG end @rules << rule @rules_by_name[rule.name] = rule rule end |
#any? ⇒ Boolean
36 37 38 |
# File 'lib/bundler/overrule/registry.rb', line 36 def any? !empty? end |
#bans ⇒ Object
75 76 77 |
# File 'lib/bundler/overrule/registry.rb', line 75 def bans @rules.select { |r| r.type == :ban } end |
#clear! ⇒ Object
25 26 27 28 29 30 |
# File 'lib/bundler/overrule/registry.rb', line 25 def clear! @rules = [] @rules_by_name = {} @edges = [] self end |
#edges ⇒ Object
Every edge a rule actually changed, de-duplicated. Bundler asks specs for their dependencies many times per run, so the raw list is noisy.
94 95 96 |
# File 'lib/bundler/overrule/registry.rb', line 94 def edges @edges.uniq { |e| [e.rule.name, e.owner, e.was, e.now] } end |
#edges_for(rule) ⇒ Object
98 99 100 |
# File 'lib/bundler/overrule/registry.rb', line 98 def edges_for(rule) edges.select { |e| e.rule.name == rule.name } end |
#empty? ⇒ Boolean
32 33 34 |
# File 'lib/bundler/overrule/registry.rb', line 32 def empty? @rules.empty? end |
#filter(dependencies, owner: nil) ⇒ Object
Rewrite a dependency list and remember what changed.
84 85 86 87 88 89 90 |
# File 'lib/bundler/overrule/registry.rb', line 84 def filter(dependencies, owner: nil) return dependencies if empty? rewritten, edges = DependencyRewriter.rewrite(dependencies, @rules_by_name, owner: owner) @edges.concat(edges) unless edges.empty? rewritten end |
#fingerprint ⇒ Object
Identifies the current rule set. Written to the state file so we can tell when rules changed and a re-resolve is required (see Patcher).
110 111 112 113 114 115 116 |
# File 'lib/bundler/overrule/registry.rb', line 110 def fingerprint return nil if empty? payload = @rules.map { |r| "#{r.type}:#{r.name}:#{r.comparable_requirement}" }.sort.join("\n") # ::Digest — Bundler vendors its own Bundler::Digest, which would win here. ::Digest::SHA256.hexdigest(payload)[0, 16] end |
#forces ⇒ Object
71 72 73 |
# File 'lib/bundler/overrule/registry.rb', line 71 def forces @rules.select { |r| r.type == :force } end |
#rule_for(name) ⇒ Object
67 68 69 |
# File 'lib/bundler/overrule/registry.rb', line 67 def rule_for(name) @rules_by_name[name] end |
#stale_rules ⇒ Object
Rules that matched nothing at all (B3) — doctor flags these.
103 104 105 106 |
# File 'lib/bundler/overrule/registry.rb', line 103 def stale_rules matched = edges.map { |e| e.rule.name }.uniq @rules.reject { |r| matched.include?(r.name) } end |
#swaps ⇒ Object
79 80 81 |
# File 'lib/bundler/overrule/registry.rb', line 79 def swaps @rules.select { |r| r.type == :swap } end |