Module: Bundler::Overrule::Patcher
- Defined in:
- lib/bundler/overrule/patcher.rb
Overview
Applies the monkey-patches, and refuses to run if Bundler's internals have moved somewhere we do not recognise.
Two seams carry the whole feature:
1. Bundler::Dsl#to_definition — the Gemfile's own dependency list.
This is what makes `force` beat a `gem 'x', '1.5'` line (B2) and
what keeps the lockfile's DEPENDENCIES section honest.
2. #dependencies / #runtime_dependencies on the spec classes — every
transitive edge. BOTH readers matter: `runtime_dependencies` feeds
resolution (via MatchMetadata#expanded_dependencies) and
SpecSet#validate_deps, while `dependencies` feeds
ParallelInstaller::SpecInstallation#all_dependencies. Filtering only
the former resolves correctly and then deadlocks the installer,
which sits waiting for a banned gem that will never arrive.
Patching the resolver itself (Resolver#to_dependency_hash) also works for resolution and is tempting as a single choke point, but it does not cover installation, so it buys nothing over seam 2 and adds a patch point.
Defined Under Namespace
Modules: GemfileDependencies, ResolveFreshness, SpecDependencies
Constant Summary collapse
- SPEC_CLASSES =
Spec classes whose dependency readers feed resolution and installation.
%w[ Gem::Specification Bundler::RemoteSpecification Bundler::EndpointSpecification Bundler::StubSpecification Bundler::LazySpecification ].freeze
Class Method Summary collapse
- .applied? ⇒ Boolean
-
.apply! ⇒ Object
Idempotent: Bundler 4.0 may re-load plugins.rb during a single run, and the Gemfile itself is evaluated more than once.
-
.reset! ⇒ Object
Test hook.
- .verify_supported! ⇒ Object
Class Method Details
.applied? ⇒ Boolean
38 39 40 |
# File 'lib/bundler/overrule/patcher.rb', line 38 def applied? @applied ||= false end |
.apply! ⇒ Object
Idempotent: Bundler 4.0 may re-load plugins.rb during a single run, and the Gemfile itself is evaluated more than once.
44 45 46 47 48 49 50 51 52 |
# File 'lib/bundler/overrule/patcher.rb', line 44 def apply! return if applied? verify_supported! patch_dsl! patch_spec_classes! patch_resolve_short_circuit! @applied = true end |
.reset! ⇒ Object
Test hook. Prepended modules cannot be un-prepended; this only resets the "have we done it" flag, which is all the specs need.
56 57 58 |
# File 'lib/bundler/overrule/patcher.rb', line 56 def reset! @applied = false end |
.verify_supported! ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/bundler/overrule/patcher.rb', line 60 def verify_supported! unless ::Gem::Requirement.create(SUPPORTED_BUNDLER).satisfied_by?(::Gem::Version.new(::Bundler::VERSION)) raise UnsupportedBundlerError, "Bundler #{::Bundler::VERSION} is outside the tested range." end missing = SPEC_CLASSES.reject { |name| resolve_constant(name) } unless missing.empty? raise UnsupportedBundlerError, "Expected these classes to exist, but they do not: #{missing.join(", ")}." end return if ::Bundler::Dsl.method_defined?(:to_definition) raise UnsupportedBundlerError, "Bundler::Dsl#to_definition is missing." end |