Module: Bundler::Overrule::DependencyRewriter
- Defined in:
- lib/bundler/overrule/dependency_rewriter.rb
Overview
The heart of the gem: given a list of Gem::Dependency objects and a set of rules, return the rewritten list plus the edges that changed.
Deliberately pure — no Bundler objects, no global state, no I/O — so the behavior contract can be unit-tested without running Bundler at all. Both the resolution seam and the installation seam call this same function, which is what keeps the lockfile and the installed gems from ever disagreeing about what a dependency list contains.
Class Method Summary collapse
-
.apply_rule(dependency, rule, owner) ⇒ Array(Gem::Dependency, Edge)
Decide what one dependency becomes under one rule.
- .development?(dependency) ⇒ Boolean
-
.replace(dependency, requirement) ⇒ Object
Swap in a new requirement while keeping everything else about the dependency intact.
- .requirement_string(dependency) ⇒ Object
- .rewrite(dependencies, rules_by_name, owner: nil) ⇒ Array(Array<Gem::Dependency>, Array<Edge>)
Class Method Details
.apply_rule(dependency, rule, owner) ⇒ Array(Gem::Dependency, Edge)
Decide what one dependency becomes under one rule.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/bundler/overrule/dependency_rewriter.rb', line 57 def apply_rule(dependency, rule, owner) # Development dependencies never reach the resolver, but spec objects # still report them. Rewriting or dropping one would be a lie about # what the gem declares, for no benefit. return [dependency, nil] if rule.nil? || development?(dependency) case rule.type when :ban [nil, Edge.new(rule, owner, requirement_string(dependency), nil)] when :force return [dependency, nil] if dependency.requirement == rule.requirement [replace(dependency, rule.requirement), Edge.new(rule, owner, requirement_string(dependency), rule.requirement.to_s)] else [dependency, nil] end end |
.development?(dependency) ⇒ Boolean
76 77 78 |
# File 'lib/bundler/overrule/dependency_rewriter.rb', line 76 def development?(dependency) dependency.respond_to?(:type) && dependency.type == :development end |
.replace(dependency, requirement) ⇒ Object
Swap in a new requirement while keeping everything else about the dependency intact.
We copy-and-mutate rather than construct a fresh object on purpose.
Bundler::Dependency derives #groups, #source, #git, #path, #github,
#branch and #ref lazily from an options hash it keeps privately, and
the shape of that hash has changed across Bundler versions. Rebuilding
from public readers silently drops whichever of those we forgot — a
force on a gem declared with git: would quietly lose its source.
Duplicating preserves the exact class and every option, forever.
94 95 96 97 98 |
# File 'lib/bundler/overrule/dependency_rewriter.rb', line 94 def replace(dependency, requirement) replacement = dependency.dup replacement.instance_variable_set(:@requirement, requirement) replacement end |
.requirement_string(dependency) ⇒ Object
80 81 82 |
# File 'lib/bundler/overrule/dependency_rewriter.rb', line 80 def requirement_string(dependency) dependency.requirement.to_s end |
.rewrite(dependencies, rules_by_name, owner: nil) ⇒ Array(Array<Gem::Dependency>, Array<Edge>)
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/bundler/overrule/dependency_rewriter.rb', line 36 def rewrite(dependencies, rules_by_name, owner: nil) return [dependencies, []] if rules_by_name.empty? || dependencies.nil? || dependencies.empty? edges = [] rewritten = [] dependencies.each do |dependency| rule = rules_by_name[dependency.name] replacement, edge = apply_rule(dependency, rule, owner) rewritten << replacement unless replacement.nil? edges << edge if edge end [rewritten, edges] end |