diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..c99d2e7 --- /dev/null +++ b/.rspec @@ -0,0 +1 @@ +--require spec_helper diff --git a/.rspec-local b/.rspec-local deleted file mode 100644 index 4e1e0d2..0000000 --- a/.rspec-local +++ /dev/null @@ -1 +0,0 @@ ---color diff --git a/lib/bundler/multilock.rb b/lib/bundler/multilock.rb index b20007e..39163af 100644 --- a/lib/bundler/multilock.rb +++ b/lib/bundler/multilock.rb @@ -146,6 +146,7 @@ def after_install_all(install: true) require "tempfile" require_relative "multilock/lockfile_generator" + Bundler.ui.debug("Syncing to alternate lockfiles") Bundler.ui.info "" default_lockfile_contents = Bundler.default_lockfile.read.freeze @@ -321,6 +322,8 @@ def loaded? # @!visibility private def inject_preamble + Bundler.ui.debug("Injecting multilock preamble") + minor_version = Gem::Version.new(::Bundler::Multilock::VERSION).segments[0..1].join(".") bundle_preamble1_match = %(plugin "bundler-multilock") bundle_preamble1 = <<~RUBY @@ -346,7 +349,16 @@ def inject_preamble end builder = Bundler::Plugin::DSL.new - builder.eval_gemfile(Bundler.default_gemfile) + # this method is called as part of the plugin loading, but @loaded_plugin_names + # hasn't been set yet, so avoid re-entrancy issues + plugins = Bundler::Plugin.instance_variable_get(:@loaded_plugin_names) + original_plugins = plugins.dup + plugins << "bundler-multilock" + begin + builder.eval_gemfile(Bundler.default_gemfile) + ensure + plugins.replace(original_plugins) + end gemfiles = builder.instance_variable_get(:@gemfiles).map(&:read) modified = inject_specific_preamble(gemfile, gemfiles, injection_point, bundle_preamble2, add_newline: true) @@ -448,3 +460,26 @@ def write_lockfile(lockfile_definition, lockfile, install:, dependency_changes: end Bundler::Multilock.inject_preamble unless Bundler::Multilock.loaded? + +# this is terrible, but we can't prepend into these modules because we only load +# _inside_ of the CLI commands already running +if defined?(Bundler::CLI::Check) + require_relative "multilock/check" + at_exit do + next unless $!.nil? + next if $!.is_a?(SystemExit) && !$!.success? + + next if Bundler::Multilock::Check.run + + Bundler.ui.warn("You can attempt to fix by running `bundle install`") + exit 1 + end +end +if defined?(Bundler::CLI::Lock) + at_exit do + next unless $!.nil? + next if $!.is_a?(SystemExit) && !$!.success? + + Bundler::Multilock.after_install_all(install: false) + end +end diff --git a/plugins.rb b/plugins.rb index 35ae7a2..419a6b7 100644 --- a/plugins.rb +++ b/plugins.rb @@ -20,29 +20,6 @@ require_relative "lib/bundler/multilock" -# this is terrible, but we can't prepend into these modules because we only load -# _inside_ of the CLI commands already running -if defined?(Bundler::CLI::Check) - require_relative "lib/bundler/multilock/check" - at_exit do - next unless $!.nil? - next if $!.is_a?(SystemExit) && !$!.success? - - next if Bundler::Multilock::Check.run - - Bundler.ui.warn("You can attempt to fix by running `bundle install`") - exit 1 - end -end -if defined?(Bundler::CLI::Lock) - at_exit do - next unless $!.nil? - next if $!.is_a?(SystemExit) && !$!.success? - - Bundler::Multilock.after_install_all(install: false) - end -end - Bundler::Plugin.add_hook(Bundler::Plugin::Events::GEM_AFTER_INSTALL_ALL) do |_| Bundler::Multilock.after_install_all end diff --git a/spec/bundler/multilock_spec.rb b/spec/bundler/multilock_spec.rb index c26219c..a9a5c86 100644 --- a/spec/bundler/multilock_spec.rb +++ b/spec/bundler/multilock_spec.rb @@ -192,7 +192,7 @@ gem "concurrent-ruby", "1.2.2" RUBY - create_local_gem("test_local", "") + create_local_gem("test_local") invoke_bundler("install") @@ -611,11 +611,32 @@ end end + it "only syncs once per lockfile" do + with_gemfile(<<~RUBY) do + gemspec + + lockfile("rails-7.0", default: true) do + gem "activesupport", "~> 7.0.0" + end + RUBY + create_local_gem("test", subdirectory: false) + invoke_bundler("install") + output = invoke_bundler("install", env: { "DEBUG" => "1" }) + + expect(output.split("\n").grep(/Syncing to alternate lockfiles/).length).to be 1 + end + end + private - def create_local_gem(name, content) - FileUtils.mkdir_p(name) - File.write("#{name}/#{name}.gemspec", <<~RUBY) + def create_local_gem(name, content = "", subdirectory: true) + if subdirectory + FileUtils.mkdir_p(name) + subdirectory = "#{name}/" + else + subdirectory = nil + end + File.write("#{subdirectory}#{name}.gemspec", <<~RUBY) Gem::Specification.new do |spec| spec.name = #{name.inspect} spec.version = "0.0.1" @@ -626,6 +647,8 @@ def create_local_gem(name, content) end RUBY + return unless subdirectory + File.write("#{name}/Gemfile", <<~RUBY) source "https://rubygems.org" diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b0af0ef..723ef9a 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "debug" + RSpec.configure do |config| config.expect_with :rspec do |c| c.max_formatted_output_length = nil