bundle update bundler-multilock
Change-Id: I47f6023ee0f5c50ba0a4cab9a3aa8848e8c540de Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/344095 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Aaron Ogata <aogata@instructure.com> Build-Review: Aaron Ogata <aogata@instructure.com> QA-Review: Cody Cutrer <cody@instructure.com> Product-Review: Cody Cutrer <cody@instructure.com>
This commit is contained in:
parent
6894600a2c
commit
82c87a7b56
2
Gemfile
2
Gemfile
|
@ -15,7 +15,7 @@ source "https://rubygems.org/"
|
|||
Plugin.uninstall(["bundler_lockfile_extensions"], {}) if Plugin.installed?("bundler_lockfile_extensions")
|
||||
|
||||
# vendored until https://github.com/rubygems/rubygems/pull/6957 is merged and released
|
||||
plugin "bundler-multilock", "1.2.3", path: "vendor/gems/bundler-multilock"
|
||||
plugin "bundler-multilock", "1.3.0", path: "vendor/gems/bundler-multilock"
|
||||
# the extra check here is in case `bundle check` or `bundle exec` gets run before `bundle install`,
|
||||
# and is also fixed by the same PR
|
||||
raise GemNotFound, "bundler-multilock plugin is not installed" if !is_a?(Bundler::Plugin::DSL) && !Plugin.installed?("bundler-multilock")
|
||||
|
|
|
@ -169,5 +169,8 @@ DEPENDENCIES
|
|||
rubocop-rake (~> 0.6)
|
||||
rubocop-rspec (~> 2.22)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -70,5 +70,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
simplecov (~> 0.22)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -80,5 +80,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
simplecov (~> 0.22)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -58,5 +58,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
sqlite3
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -70,5 +70,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
sqlite3
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -55,5 +55,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
simplecov (~> 0.22)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -65,5 +65,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
simplecov (~> 0.22)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -113,5 +113,8 @@ DEPENDENCIES
|
|||
railties (~> 7.0)
|
||||
rspec (~> 3.12)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -132,5 +132,8 @@ DEPENDENCIES
|
|||
railties (~> 7.0)
|
||||
rspec (~> 3.12)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -149,5 +149,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
sqlite3
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -170,5 +170,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
sqlite3
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -73,5 +73,8 @@ DEPENDENCIES
|
|||
pry
|
||||
rspec (~> 3.12)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -85,5 +85,8 @@ DEPENDENCIES
|
|||
pry
|
||||
rspec (~> 3.12)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -53,5 +53,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
simplecov (~> 0.22)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -63,5 +63,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
simplecov (~> 0.22)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -149,5 +149,8 @@ DEPENDENCIES
|
|||
rspec
|
||||
timecop
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -169,5 +169,8 @@ DEPENDENCIES
|
|||
rspec
|
||||
timecop
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -151,5 +151,8 @@ DEPENDENCIES
|
|||
simplecov (~> 0.22)
|
||||
thrift_client (= 0.9.3)!
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -170,5 +170,8 @@ DEPENDENCIES
|
|||
simplecov (~> 0.22)
|
||||
thrift_client (= 0.9.3)!
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -20,5 +20,8 @@ DEPENDENCIES
|
|||
canvas_color!
|
||||
rake
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -28,5 +28,8 @@ DEPENDENCIES
|
|||
rake
|
||||
simplecov (~> 0.22)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -61,5 +61,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
simplecov (~> 0.22)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -149,5 +149,8 @@ DEPENDENCIES
|
|||
debug
|
||||
rspec
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -170,5 +170,8 @@ DEPENDENCIES
|
|||
debug
|
||||
rspec
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -48,5 +48,8 @@ DEPENDENCIES
|
|||
rake
|
||||
rspec (~> 3.12)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -58,5 +58,8 @@ DEPENDENCIES
|
|||
rake
|
||||
rspec (~> 3.12)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -174,5 +174,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
webmock (~> 3.18)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -204,5 +204,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
webmock (~> 3.18)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -191,5 +191,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
webmock (~> 3.18)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -221,5 +221,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
webmock (~> 3.18)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -43,5 +43,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
simplecov (~> 0.22)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -201,5 +201,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.0)
|
||||
webmock (~> 3.0)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -230,5 +230,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.0)
|
||||
webmock (~> 3.0)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -117,5 +117,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
simplecov (~> 0.22)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -149,5 +149,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
simplecov (~> 0.22)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -112,5 +112,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
simplecov (~> 0.22)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -122,5 +122,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
simplecov (~> 0.22)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -76,5 +76,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
simplecov (~> 0.22)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -219,5 +219,8 @@ DEPENDENCIES
|
|||
rspec
|
||||
timecop
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -238,5 +238,8 @@ DEPENDENCIES
|
|||
rspec
|
||||
timecop
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -37,5 +37,8 @@ DEPENDENCIES
|
|||
rake
|
||||
rspec (~> 3.12)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -35,5 +35,8 @@ DEPENDENCIES
|
|||
rake
|
||||
rspec (~> 3.12)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -68,5 +68,8 @@ DEPENDENCIES
|
|||
simplecov (~> 0.22)
|
||||
sqlite3
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -80,5 +80,8 @@ DEPENDENCIES
|
|||
simplecov (~> 0.22)
|
||||
sqlite3
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -47,5 +47,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
simplecov (~> 0.22)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -50,5 +50,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
timecop
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -60,5 +60,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
timecop
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -56,5 +56,8 @@ DEPENDENCIES
|
|||
rake
|
||||
rspec (~> 3.12)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -66,5 +66,8 @@ DEPENDENCIES
|
|||
rake
|
||||
rspec (~> 3.12)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -113,5 +113,8 @@ DEPENDENCIES
|
|||
debug
|
||||
rspec
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -132,5 +132,8 @@ DEPENDENCIES
|
|||
debug
|
||||
rspec
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -43,5 +43,8 @@ DEPENDENCIES
|
|||
rake
|
||||
rspec (~> 3.12)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -49,5 +49,8 @@ DEPENDENCIES
|
|||
rake
|
||||
rspec (~> 3.12)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -64,5 +64,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
rspec-mocks
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -136,5 +136,8 @@ DEPENDENCIES
|
|||
rspec
|
||||
timecop
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -155,5 +155,8 @@ DEPENDENCIES
|
|||
rspec
|
||||
timecop
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -198,5 +198,8 @@ DEPENDENCIES
|
|||
sqlite3
|
||||
thrift_client (= 0.9.3)!
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -230,5 +230,8 @@ DEPENDENCIES
|
|||
sqlite3
|
||||
thrift_client (= 0.9.3)!
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -113,5 +113,8 @@ DEPENDENCIES
|
|||
timecop
|
||||
webmock
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -88,5 +88,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
simplecov (~> 0.22)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -98,5 +98,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
simplecov (~> 0.22)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -84,5 +84,8 @@ DEPENDENCIES
|
|||
rake
|
||||
rspec (~> 3.12)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -94,5 +94,8 @@ DEPENDENCIES
|
|||
rake
|
||||
rspec (~> 3.12)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -109,5 +109,8 @@ DEPENDENCIES
|
|||
simplecov (~> 0.22)
|
||||
utf8_cleaner!
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -119,5 +119,8 @@ DEPENDENCIES
|
|||
simplecov (~> 0.22)
|
||||
utf8_cleaner!
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -250,5 +250,8 @@ DEPENDENCIES
|
|||
utf8_cleaner!
|
||||
webrick
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -269,5 +269,8 @@ DEPENDENCIES
|
|||
utf8_cleaner!
|
||||
webrick
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -37,5 +37,8 @@ DEPENDENCIES
|
|||
rake
|
||||
rspec (~> 3.12)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -53,5 +53,8 @@ DEPENDENCIES
|
|||
rake
|
||||
rspec (~> 3.12)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -105,5 +105,8 @@ DEPENDENCIES
|
|||
rake
|
||||
rspec (~> 3.12)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -117,5 +117,8 @@ DEPENDENCIES
|
|||
rake
|
||||
rspec (~> 3.12)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -71,5 +71,8 @@ DEPENDENCIES
|
|||
redcarpet
|
||||
rspec (~> 3.0)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -80,5 +80,8 @@ DEPENDENCIES
|
|||
redcarpet
|
||||
rspec (~> 3.0)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -68,5 +68,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
simplecov (~> 0.22)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -78,5 +78,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
simplecov (~> 0.22)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -47,5 +47,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
sqlite3
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -223,5 +223,8 @@ DEPENDENCIES
|
|||
rspec
|
||||
timecop
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -242,5 +242,8 @@ DEPENDENCIES
|
|||
rspec
|
||||
timecop
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -163,5 +163,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
rubocop-canvas!
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -185,5 +185,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
rubocop-canvas!
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -33,5 +33,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
stringify_ids!
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -36,5 +36,8 @@ DEPENDENCIES
|
|||
tatl_tael!
|
||||
timecop (~> 0.9)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -93,5 +93,8 @@ DEPENDENCIES
|
|||
turnitin_api!
|
||||
webmock (~> 3.0)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -104,5 +104,8 @@ DEPENDENCIES
|
|||
turnitin_api!
|
||||
webmock (~> 3.0)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -116,5 +116,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
twitter!
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -126,5 +126,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
twitter!
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -35,5 +35,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
utf8_cleaner!
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -53,5 +53,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
workflow!
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -65,5 +65,8 @@ DEPENDENCIES
|
|||
rspec (~> 3.12)
|
||||
workflow!
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.1.2p20
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.7
|
||||
|
|
|
@ -56,26 +56,24 @@ module Bundler
|
|||
# allow short-form lockfile names
|
||||
lockfile = expand_lockfile(lockfile)
|
||||
|
||||
if lockfile_definitions.find { |definition| definition[:lockfile] == lockfile }
|
||||
raise ArgumentError, "Lockfile #{lockfile} is already defined"
|
||||
end
|
||||
raise ArgumentError, "Lockfile #{lockfile} is already defined" if lockfile_definitions.key?(lockfile)
|
||||
|
||||
env_lockfile = lockfile if active && ENV["BUNDLE_LOCKFILE"] == "active"
|
||||
env_lockfile ||= ENV["BUNDLE_LOCKFILE"]&.then { |l| expand_lockfile(l) }
|
||||
active = env_lockfile == lockfile if env_lockfile
|
||||
|
||||
if active && (old_active = lockfile_definitions.find { |definition| definition[:active] })
|
||||
if active && (old_active = lockfile_definitions.each_value.find { |definition| definition[:active] })
|
||||
raise ArgumentError, "Only one lockfile (#{old_active[:lockfile]}) can be flagged as active"
|
||||
end
|
||||
|
||||
parent = expand_lockfile(parent)
|
||||
if parent != Bundler.default_lockfile(force_original: true) &&
|
||||
!lockfile_definitions.find { |definition| definition[:lockfile] == parent } &&
|
||||
!lockfile_definitions.key?(parent) &&
|
||||
!parent.exist?
|
||||
raise ArgumentError, "Parent lockfile #{parent} is not defined"
|
||||
end
|
||||
|
||||
lockfile_definitions << (lockfile_def = {
|
||||
lockfile_definitions[lockfile] = (lockfile_def = {
|
||||
gemfile: (gemfile && Bundler.root.join(gemfile).expand_path) || Bundler.default_gemfile,
|
||||
lockfile: lockfile,
|
||||
active: active,
|
||||
|
@ -150,37 +148,52 @@ module Bundler
|
|||
Bundler.ui.debug("Syncing to alternate lockfiles")
|
||||
|
||||
attempts = 1
|
||||
previous_contents = Set.new
|
||||
|
||||
default_root = Bundler.root
|
||||
|
||||
checker = Check.new
|
||||
cache = Cache.new
|
||||
checker = Check.new(cache)
|
||||
synced_any = false
|
||||
local_parser_cache = {}
|
||||
Bundler.settings.temporary(cache_all_platforms: true, suppress_install_using_messages: true) do
|
||||
lockfile_definitions.each do |lockfile_definition|
|
||||
lockfile_definitions.each do |lockfile_name, lockfile_definition|
|
||||
# we already wrote the default lockfile
|
||||
next if lockfile_definition[:lockfile] == Bundler.default_lockfile(force_original: true)
|
||||
next if lockfile_name == Bundler.default_lockfile(force_original: true)
|
||||
|
||||
# root needs to be set so that paths are output relative to the correct root in the lockfile
|
||||
Bundler.root = lockfile_definition[:gemfile].dirname
|
||||
|
||||
relative_lockfile = lockfile_definition[:lockfile].relative_path_from(Dir.pwd)
|
||||
relative_lockfile = lockfile_name.relative_path_from(Dir.pwd)
|
||||
|
||||
# prevent infinite loops of tick-tocking back and forth between two versions
|
||||
current_contents = cache.contents(lockfile_name)
|
||||
if previous_contents.include?(current_contents)
|
||||
Bundler.ui.debug("Unable to converge on a single solution for #{lockfile_name}; " \
|
||||
"perhaps there are conflicting requirements?")
|
||||
attempts = 1
|
||||
previous_contents.clear
|
||||
next
|
||||
end
|
||||
previous_contents << current_contents
|
||||
|
||||
# already up to date?
|
||||
up_to_date = false
|
||||
Bundler.settings.temporary(frozen: true) do
|
||||
Bundler.ui.silence do
|
||||
up_to_date = checker.base_check(lockfile_definition, check_missing_deps: true) &&
|
||||
checker.check(lockfile_definition)
|
||||
checker.deep_check(lockfile_definition)
|
||||
end
|
||||
end
|
||||
if up_to_date
|
||||
attempts = 1
|
||||
previous_contents.clear
|
||||
next
|
||||
end
|
||||
|
||||
if Bundler.frozen_bundle?
|
||||
# if we're frozen, you have to use the pre-existing lockfile
|
||||
unless lockfile_definition[:lockfile].exist?
|
||||
unless lockfile_name.exist?
|
||||
Bundler.ui.error("The bundle is locked, but #{relative_lockfile} is missing. " \
|
||||
"Please make sure you have checked #{relative_lockfile} " \
|
||||
"into version control before deploying.")
|
||||
|
@ -188,19 +201,19 @@ module Bundler
|
|||
end
|
||||
|
||||
Bundler.ui.info("Installing gems for #{relative_lockfile}...")
|
||||
write_lockfile(lockfile_definition, lockfile_definition[:lockfile], install: install)
|
||||
write_lockfile(lockfile_definition, lockfile_name, cache, install: install)
|
||||
else
|
||||
Bundler.ui.info("Syncing to #{relative_lockfile}...") if attempts == 1
|
||||
synced_any = true
|
||||
|
||||
parent = lockfile_definition[:parent]
|
||||
parent_root = parent.dirname
|
||||
checker.load_lockfile(parent)
|
||||
parent_specs = checker.lockfile_specs[parent]
|
||||
specs = lockfile_name.exist? ? cache.specs(lockfile_name) : {}
|
||||
parent_lockfile_name = lockfile_definition[:parent]
|
||||
parent_root = parent_lockfile_name.dirname
|
||||
parent_specs = cache.specs(parent_lockfile_name)
|
||||
|
||||
# adjust locked paths from the parent lockfile to be relative to _this_ gemfile
|
||||
adjusted_parent_lockfile_contents =
|
||||
checker.lockfile_contents[parent].gsub(/PATH\n remote: ([^\n]+)\n/) do |remote|
|
||||
cache.contents(parent_lockfile_name).gsub(/PATH\n remote: ([^\n]+)\n/) do |remote|
|
||||
remote_path = Pathname.new($1)
|
||||
next remote if remote_path.absolute?
|
||||
|
||||
|
@ -220,23 +233,60 @@ module Bundler
|
|||
TEXT
|
||||
end
|
||||
|
||||
if lockfile_definition[:lockfile].exist?
|
||||
if lockfile_name.exist?
|
||||
# if the lockfile already exists, "merge" it together
|
||||
parent_lockfile = LockfileParser.new(adjusted_parent_lockfile_contents)
|
||||
lockfile = LockfileParser.new(lockfile_definition[:lockfile].read)
|
||||
parent_lockfile = if adjusted_parent_lockfile_contents == cache.contents(lockfile_name)
|
||||
cache.parser(parent_lockfile_name)
|
||||
else
|
||||
local_parser_cache[adjusted_parent_lockfile_contents] ||=
|
||||
LockfileParser.new(adjusted_parent_lockfile_contents)
|
||||
end
|
||||
lockfile = cache.parser(lockfile_name)
|
||||
|
||||
dependency_changes = false
|
||||
# replace any duplicate specs with what's in the default lockfile
|
||||
|
||||
spec_precedences = {}
|
||||
|
||||
check_precedence = lambda do |spec, parent_spec|
|
||||
next :parent if spec.nil?
|
||||
next :self if parent_spec.nil?
|
||||
next spec_precedences[spec.name] if spec_precedences.key?(spec.name)
|
||||
|
||||
precedence = :self if cache.conflicting_requirements?(lockfile_name,
|
||||
parent_lockfile_name,
|
||||
spec,
|
||||
parent_spec)
|
||||
|
||||
# look through all reverse dependencies; if any of them say it
|
||||
# has to come from self, due to conflicts, then this gem has
|
||||
# to come from self as well
|
||||
[cache.reverse_dependencies(lockfile_name),
|
||||
cache.reverse_dependencies(parent_lockfile_name)].each do |reverse_dependencies|
|
||||
break if precedence == :self
|
||||
|
||||
reverse_dependencies[spec.name].each do |dep_name|
|
||||
precedence = check_precedence.call(specs[dep_name], parent_specs[dep_name])
|
||||
break if precedence == :self
|
||||
end
|
||||
end
|
||||
|
||||
spec_precedences[spec.name] = precedence || :parent
|
||||
end
|
||||
|
||||
# replace any duplicate specs with what's in the parent lockfile
|
||||
lockfile.specs.map! do |spec|
|
||||
parent_spec = parent_specs[[spec.name, spec.platform]]
|
||||
next spec unless parent_spec
|
||||
|
||||
next spec if check_precedence.call(spec, parent_spec) == :self
|
||||
|
||||
dependency_changes ||= spec != parent_spec
|
||||
parent_spec
|
||||
|
||||
new_spec = parent_spec.dup
|
||||
new_spec.source = spec.source
|
||||
new_spec
|
||||
end
|
||||
|
||||
lockfile.specs.replace(parent_lockfile.specs + lockfile.specs).uniq!
|
||||
lockfile.sources.replace(parent_lockfile.sources + lockfile.sources).uniq!
|
||||
lockfile.platforms.replace(parent_lockfile.platforms).uniq!
|
||||
# prune more specific platforms
|
||||
lockfile.platforms.delete_if do |p1|
|
||||
|
@ -244,9 +294,9 @@ module Bundler
|
|||
p2 != "ruby" && p1 != p2 && MatchPlatform.platforms_match?(p2, p1)
|
||||
end
|
||||
end
|
||||
lockfile.instance_variable_set(:@ruby_version, parent_lockfile.ruby_version)
|
||||
lockfile.instance_variable_set(:@ruby_version, parent_lockfile.ruby_version) if lockfile.ruby_version
|
||||
unless lockfile.bundler_version == parent_lockfile.bundler_version
|
||||
unlocking_bundler = true
|
||||
unlocking_bundler = parent_lockfile.bundler_version
|
||||
lockfile.instance_variable_set(:@bundler_version, parent_lockfile.bundler_version)
|
||||
end
|
||||
|
||||
|
@ -263,24 +313,27 @@ module Bundler
|
|||
temp_lockfile.write(new_contents)
|
||||
temp_lockfile.flush
|
||||
|
||||
had_changes = write_lockfile(lockfile_definition,
|
||||
temp_lockfile.path,
|
||||
install: install,
|
||||
dependency_changes: dependency_changes,
|
||||
unlocking_bundler: unlocking_bundler)
|
||||
had_changes ||= write_lockfile(lockfile_definition,
|
||||
temp_lockfile.path,
|
||||
cache,
|
||||
install: install,
|
||||
dependency_changes: dependency_changes,
|
||||
unlocking_bundler: unlocking_bundler)
|
||||
end
|
||||
cache.invalidate_lockfile(lockfile_name) if had_changes
|
||||
|
||||
# if we had changes, bundler may have updated some common
|
||||
# dependencies beyond the default lockfile, so re-run it
|
||||
# once to reset them back to the default lockfile's version.
|
||||
# if it's already good, the `check` check at the beginning of
|
||||
# the loop will skip the second sync anyway.
|
||||
if had_changes && attempts < 2
|
||||
if had_changes
|
||||
attempts += 1
|
||||
Bundler.ui.debug("Re-running sync to #{relative_lockfile} to reset common dependencies")
|
||||
redo
|
||||
else
|
||||
attempts = 1
|
||||
previous_contents.clear
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -300,7 +353,7 @@ module Bundler
|
|||
@loaded = true
|
||||
return if lockfile_definitions.empty?
|
||||
|
||||
return unless lockfile_definitions.none? { |definition| definition[:active] }
|
||||
return unless lockfile_definitions.each_value.none? { |definition| definition[:active] }
|
||||
|
||||
if ENV["BUNDLE_LOCKFILE"]&.then { |l| expand_lockfile(l) } ==
|
||||
Bundler.default_lockfile(force_original: true)
|
||||
|
@ -310,9 +363,7 @@ module Bundler
|
|||
raise GemfileNotFound, "Could not locate lockfile #{ENV["BUNDLE_LOCKFILE"].inspect}" if ENV["BUNDLE_LOCKFILE"]
|
||||
|
||||
# Gemfile.lock isn't explicitly specified, otherwise it would be active
|
||||
default_lockfile_definition = lockfile_definitions.find do |definition|
|
||||
definition[:lockfile] == Bundler.default_lockfile(force_original: true)
|
||||
end
|
||||
default_lockfile_definition = self.default_lockfile_definition
|
||||
return unless default_lockfile_definition && default_lockfile_definition[:active] == false
|
||||
|
||||
raise GemfileEvalError, "No lockfiles marked as active"
|
||||
|
@ -377,10 +428,15 @@ module Bundler
|
|||
|
||||
# @!visibility private
|
||||
def reset!
|
||||
@lockfile_definitions = []
|
||||
@lockfile_definitions = {}
|
||||
@loaded = false
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
def default_lockfile_definition
|
||||
lockfile_definitions[Bundler.default_lockfile(force_original: true)]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def expand_lockfile(lockfile)
|
||||
|
@ -406,7 +462,12 @@ module Bundler
|
|||
true
|
||||
end
|
||||
|
||||
def write_lockfile(lockfile_definition, lockfile, install:, dependency_changes: false, unlocking_bundler: false)
|
||||
def write_lockfile(lockfile_definition,
|
||||
lockfile,
|
||||
cache,
|
||||
install:,
|
||||
dependency_changes: false,
|
||||
unlocking_bundler: false)
|
||||
prepare_block = lockfile_definition[:prepare]
|
||||
|
||||
gemfile = lockfile_definition[:gemfile]
|
||||
|
@ -415,6 +476,12 @@ module Bundler
|
|||
builder = Dsl.new
|
||||
builder.eval_gemfile(gemfile, &prepare_block) if prepare_block
|
||||
builder.eval_gemfile(gemfile)
|
||||
if !builder.instance_variable_get(:@ruby_version) &&
|
||||
(parent_lockfile = lockfile_definition[:parent]) &&
|
||||
(parent_lockfile_definition = lockfile_definitions[parent_lockfile]) &&
|
||||
(parent_ruby_version_requirement = parent_lockfile_definition[:ruby_version_requirement])
|
||||
builder.instance_variable_set(:@ruby_version, parent_ruby_version_requirement)
|
||||
end
|
||||
|
||||
definition = builder.to_definition(lockfile, { bundler: unlocking_bundler })
|
||||
definition.instance_variable_set(:@dependency_changes, dependency_changes) if dependency_changes
|
||||
|
@ -436,11 +503,12 @@ module Bundler
|
|||
|
||||
current_definition.resolve_with_cache!
|
||||
if current_definition.missing_specs.any?
|
||||
cache.invalidate_checks(current_lockfile)
|
||||
Bundler.with_default_lockfile(current_lockfile) do
|
||||
Installer.install(gemfile.dirname, current_definition, {})
|
||||
end
|
||||
end
|
||||
rescue RubyVersionMismatch, GemNotFound, SolveFailure
|
||||
rescue RubyVersionMismatch, GemNotFound, SolveFailure, InstallError, ProductionError
|
||||
# ignore
|
||||
end
|
||||
end
|
||||
|
@ -470,11 +538,16 @@ module Bundler
|
|||
resolved_remotely = true
|
||||
end
|
||||
SharedHelpers.capture_filesystem_access do
|
||||
definition.instance_variable_set(:@resolved_bundler_version, unlocking_bundler) if unlocking_bundler
|
||||
|
||||
# need to force it to _not_ preserve unknown sections, so that it
|
||||
# will overwrite the ruby version
|
||||
definition.instance_variable_set(:@unlocking_bundler, true)
|
||||
if Bundler.gem_version >= Gem::Version.new("2.5.6")
|
||||
definition.instance_variable_set(:@lockfile, lockfile_definition[:lockfile])
|
||||
definition.lock(true)
|
||||
definition.lock
|
||||
else
|
||||
definition.lock(lockfile_definition[:lockfile], true)
|
||||
definition.lock(lockfile_definition[:lockfile])
|
||||
end
|
||||
end
|
||||
ensure
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative "ui/capture"
|
||||
|
||||
module Bundler
|
||||
module Multilock
|
||||
# caches lockfiles across multiple lockfile checks or sync runs
|
||||
class Cache
|
||||
def initialize
|
||||
@contents = {}
|
||||
@parsers = {}
|
||||
@specs = {}
|
||||
@reverse_dependencies = {}
|
||||
@reverse_requirements = {}
|
||||
@base_checks = {}
|
||||
@deep_checks = {}
|
||||
@base_check_messages = {}
|
||||
@deep_check_messages = {}
|
||||
@missing_specs = Set.new
|
||||
@logged_missing = false
|
||||
end
|
||||
|
||||
# Removes a given lockfile's associated cached data
|
||||
#
|
||||
# Should be called if the lockfile is modified
|
||||
# @param lockfile_name [Pathname]
|
||||
# @return [void]
|
||||
def invalidate_lockfile(lockfile_name)
|
||||
@contents.delete(lockfile_name)
|
||||
@parsers.delete(lockfile_name)
|
||||
@specs.delete(lockfile_name)
|
||||
@reverse_dependencies.delete(lockfile_name)
|
||||
@reverse_requirements.delete(lockfile_name)
|
||||
invalidate_checks(lockfile_name)
|
||||
end
|
||||
|
||||
def invalidate_checks(lockfile_name)
|
||||
@base_checks.delete(lockfile_name)
|
||||
@base_check_messages.delete(lockfile_name)
|
||||
# must clear them all; downstream lockfiles may depend on the state of this lockfile
|
||||
@deep_checks.clear
|
||||
@deep_check_messages.clear
|
||||
end
|
||||
|
||||
# @param lockfile_name [Pathname]
|
||||
# @return [String] the raw contents of the lockfile
|
||||
def contents(lockfile_name)
|
||||
@contents.fetch(lockfile_name) do
|
||||
@contents[lockfile_name] = lockfile_name.file? && lockfile_name.read.freeze
|
||||
end
|
||||
end
|
||||
|
||||
# @param lockfile_name [Pathname]
|
||||
# @return [LockfileParser]
|
||||
def parser(lockfile_name)
|
||||
@parsers[lockfile_name] ||= LockfileParser.new(contents(lockfile_name))
|
||||
end
|
||||
|
||||
def specs(lockfile_name)
|
||||
@specs[lockfile_name] ||= parser(lockfile_name).specs.to_h do |spec|
|
||||
[[spec.name, spec.platform], spec]
|
||||
end
|
||||
end
|
||||
|
||||
# @param lockfile_name [Pathname]
|
||||
# @return [Hash<String, Set<String>>] hash of gem name to set of gem names that depend on it
|
||||
def reverse_dependencies(lockfile_name)
|
||||
ensure_reverse_data(lockfile_name)
|
||||
@reverse_dependencies[lockfile_name]
|
||||
end
|
||||
|
||||
# @param lockfile_name [Pathname]
|
||||
# @return [Hash<String, Gem::Requirement>] hash of gem name to requirement for that gem
|
||||
def reverse_requirements(lockfile_name)
|
||||
ensure_reverse_data(lockfile_name)
|
||||
@reverse_requirements[lockfile_name]
|
||||
end
|
||||
|
||||
def conflicting_requirements?(lockfile1_name, lockfile2_name, spec1, spec2)
|
||||
reverse_requirements1 = reverse_requirements(lockfile1_name)[spec1.name]
|
||||
reverse_requirements2 = reverse_requirements(lockfile2_name)[spec1.name]
|
||||
|
||||
!reverse_requirements1.satisfied_by?(spec2.version) &&
|
||||
!reverse_requirements2.satisfied_by?(spec1.version)
|
||||
end
|
||||
|
||||
def log_missing_spec(spec)
|
||||
return if @missing_specs.include?(spec)
|
||||
|
||||
Bundler.ui.error "The following gems are missing" if @missing_specs.empty?
|
||||
@missing_specs << spec
|
||||
Bundler.ui.error(" * #{spec.name} (#{spec.version})")
|
||||
end
|
||||
|
||||
%i[base deep].each do |type|
|
||||
class_eval <<~RUBY, __FILE__, __LINE__ + 1 # rubocop:disable Style/DocumentDynamicEvalDefinition
|
||||
def #{type}_check(lockfile_name)
|
||||
if @#{type}_checks.key?(lockfile_name)
|
||||
@#{type}_check_messages[lockfile_name].replay
|
||||
@#{type}_checks[lockfile_name]
|
||||
else
|
||||
result = nil
|
||||
messages = Bundler::Multilock::UI::Capture.capture do
|
||||
result = @#{type}_checks[lockfile_name] = yield
|
||||
end
|
||||
@#{type}_check_messages[lockfile_name] = messages.tap(&:replay)
|
||||
result
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ensure_reverse_data(lockfile_name)
|
||||
return if @reverse_requirements.key?(lockfile_name)
|
||||
|
||||
# can use Gem::Requirement.default_prelease when Ruby 2.6 support is dropped
|
||||
reverse_requirements = Hash.new { |h, k| h[k] = Gem::Requirement.new(">= 0.a") }
|
||||
reverse_dependencies = Hash.new { |h, k| h[k] = Set.new }
|
||||
|
||||
lockfile = parser(lockfile_name)
|
||||
|
||||
lockfile.dependencies.each_value do |dep|
|
||||
reverse_requirements[dep.name].requirements.concat(dep.requirement.requirements)
|
||||
end
|
||||
lockfile.specs.each do |spec|
|
||||
spec.dependencies.each do |dep|
|
||||
reverse_requirements[dep.name].requirements.concat(dep.requirement.requirements)
|
||||
reverse_dependencies[dep.name] << spec.name
|
||||
end
|
||||
end
|
||||
|
||||
@reverse_requirements[lockfile_name] = reverse_requirements
|
||||
@reverse_dependencies[lockfile_name] = reverse_dependencies
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,31 +2,19 @@
|
|||
|
||||
require "set"
|
||||
|
||||
require_relative "cache"
|
||||
|
||||
module Bundler
|
||||
module Multilock
|
||||
class Check
|
||||
attr_reader :lockfiles, :lockfile_contents, :lockfile_specs
|
||||
|
||||
class << self
|
||||
def run
|
||||
new.run
|
||||
end
|
||||
end
|
||||
|
||||
def initialize
|
||||
@lockfiles = {}
|
||||
@lockfile_contents = {}
|
||||
@lockfile_specs = {}
|
||||
end
|
||||
|
||||
def load_lockfile(lockfile)
|
||||
return if lockfile_contents.key?(lockfile)
|
||||
|
||||
contents = lockfile_contents[lockfile] = lockfile.read.freeze
|
||||
parser = lockfiles[lockfile] = LockfileParser.new(contents)
|
||||
lockfile_specs[lockfile] = parser.specs.to_h do |spec|
|
||||
[[spec.name, spec.platform], spec]
|
||||
end
|
||||
def initialize(cache = Cache.new)
|
||||
@cache = cache
|
||||
end
|
||||
|
||||
def run(skip_base_checks: false)
|
||||
|
@ -34,177 +22,171 @@ module Bundler
|
|||
|
||||
success = true
|
||||
unless skip_base_checks
|
||||
missing_specs = base_check({ gemfile: Bundler.default_gemfile,
|
||||
lockfile: Bundler.default_lockfile(force_original: true) },
|
||||
return_missing: true).to_set
|
||||
default_lockfile_definition = Multilock.default_lockfile_definition
|
||||
default_lockfile_definition ||= { gemfile: Bundler.default_gemfile,
|
||||
lockfile: Bundler.default_lockfile(force_original: true) }
|
||||
base_check(default_lockfile_definition)
|
||||
end
|
||||
Multilock.lockfile_definitions.each do |lockfile_definition|
|
||||
next if lockfile_definition[:lockfile] == Bundler.default_lockfile(force_original: true)
|
||||
Multilock.lockfile_definitions.each do |lockfile_name, lockfile_definition|
|
||||
next if lockfile_name == Bundler.default_lockfile(force_original: true)
|
||||
|
||||
unless lockfile_definition[:lockfile].exist?
|
||||
Bundler.ui.error("Lockfile #{lockfile_definition[:lockfile]} does not exist.")
|
||||
unless lockfile_name.exist?
|
||||
Bundler.ui.error("Lockfile #{lockfile_name} does not exist.")
|
||||
success = false
|
||||
next
|
||||
end
|
||||
|
||||
unless skip_base_checks
|
||||
new_missing = base_check(lockfile_definition, log_missing: missing_specs, return_missing: true)
|
||||
success = false unless new_missing.empty?
|
||||
missing_specs.merge(new_missing)
|
||||
end
|
||||
success = false unless check(lockfile_definition)
|
||||
success &&= base_check(lockfile_definition) && deep_check(lockfile_definition)
|
||||
end
|
||||
success
|
||||
end
|
||||
|
||||
# this is mostly equivalent to the built in checks in `bundle check`, but even
|
||||
# more conservative, and returns false instead of exiting on failure
|
||||
def base_check(lockfile_definition, log_missing: false, return_missing: false, check_missing_deps: false)
|
||||
return return_missing ? [] : false unless lockfile_definition[:lockfile].file?
|
||||
def base_check(lockfile_definition, check_missing_deps: false)
|
||||
lockfile_name = lockfile_definition[:lockfile]
|
||||
default_root = Bundler.root
|
||||
|
||||
Multilock.prepare_block = lockfile_definition[:prepare]
|
||||
definition = Definition.build(lockfile_definition[:gemfile], lockfile_definition[:lockfile], false)
|
||||
return return_missing ? [] : false unless definition.send(:current_platform_locked?)
|
||||
result = @cache.base_check(lockfile_name) do
|
||||
next false unless lockfile_name.file?
|
||||
|
||||
begin
|
||||
definition.validate_runtime!
|
||||
not_installed = Bundler.ui.silence { definition.missing_specs }
|
||||
rescue RubyVersionMismatch, GemNotFound, SolveFailure
|
||||
return return_missing ? [] : false
|
||||
end
|
||||
Multilock.prepare_block = lockfile_definition[:prepare]
|
||||
# root needs to be set so that paths are output relative to the correct root in the lockfile
|
||||
Bundler.root = lockfile_definition[:gemfile].dirname
|
||||
|
||||
if log_missing
|
||||
not_installed.each do |spec|
|
||||
next if log_missing.include?(spec)
|
||||
definition = Definition.build(lockfile_definition[:gemfile], lockfile_name, false)
|
||||
next false unless definition.send(:current_platform_locked?)
|
||||
|
||||
Bundler.ui.error "The following gems are missing" if log_missing.empty?
|
||||
Bundler.ui.error(" * #{spec.name} (#{spec.version})")
|
||||
begin
|
||||
definition.validate_runtime!
|
||||
not_installed = Bundler.ui.silence { definition.missing_specs }
|
||||
rescue RubyVersionMismatch, GemNotFound, SolveFailure
|
||||
next false
|
||||
end
|
||||
|
||||
if Bundler.ui.error?
|
||||
not_installed.each do |spec|
|
||||
@cache.log_missing_spec(spec)
|
||||
end
|
||||
end
|
||||
|
||||
next false unless not_installed.empty?
|
||||
|
||||
# cache a sentinel so that we can share a cache regardless of the check_missing_deps argument
|
||||
next :missing_deps unless (definition.locked_gems.dependencies.values - definition.dependencies).empty?
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
return not_installed if return_missing
|
||||
return !check_missing_deps if result == :missing_deps
|
||||
|
||||
return false unless not_installed.empty? && definition.no_resolve_needed?
|
||||
return true unless check_missing_deps
|
||||
|
||||
(definition.locked_gems.dependencies.values - definition.dependencies).empty?
|
||||
result
|
||||
ensure
|
||||
Multilock.prepare_block = nil
|
||||
Bundler.root = default_root
|
||||
end
|
||||
|
||||
# this checks for mismatches between the parent lockfile and the given lockfile,
|
||||
# and for pinned dependencies in lockfiles requiring them
|
||||
def check(lockfile_definition)
|
||||
success = true
|
||||
proven_pinned = Set.new
|
||||
needs_pin_check = []
|
||||
lockfile = LockfileParser.new(lockfile_definition[:lockfile].read)
|
||||
lockfile_path = lockfile_definition[:lockfile].relative_path_from(Dir.pwd)
|
||||
parent = lockfile_definition[:parent]
|
||||
load_lockfile(parent)
|
||||
parent_lockfile = lockfiles[parent]
|
||||
unless lockfile.platforms == parent_lockfile.platforms
|
||||
Bundler.ui.error("The platforms in #{lockfile_path} do not match the parent lockfile.")
|
||||
success = false
|
||||
end
|
||||
unless lockfile.bundler_version == parent_lockfile.bundler_version
|
||||
Bundler.ui.error("bundler (#{lockfile.bundler_version}) in #{lockfile_path} " \
|
||||
"does not match the parent lockfile's version (@#{parent_lockfile.bundler_version}).")
|
||||
success = false
|
||||
end
|
||||
|
||||
reverse_dependencies = cache_reverse_dependencies(lockfile)
|
||||
parent_reverse_dependencies = cache_reverse_dependencies(parent_lockfile)
|
||||
|
||||
# look through top-level explicit dependencies for pinned requirements
|
||||
if lockfile_definition[:enforce_pinned_additional_dependencies]
|
||||
find_pinned_dependencies(proven_pinned, lockfile.dependencies.each_value)
|
||||
end
|
||||
|
||||
# check for conflicting requirements (and build list of pins, in the same loop)
|
||||
lockfile.specs.each do |spec|
|
||||
parent_spec = lockfile_specs[parent][[spec.name, spec.platform]]
|
||||
def deep_check(lockfile_definition)
|
||||
lockfile_name = lockfile_definition[:lockfile]
|
||||
@cache.deep_check(lockfile_name) do
|
||||
success = true
|
||||
proven_pinned = Set.new
|
||||
needs_pin_check = []
|
||||
parser = @cache.parser(lockfile_name)
|
||||
lockfile_path = lockfile_name.relative_path_from(Dir.pwd)
|
||||
parent_lockfile_name = lockfile_definition[:parent]
|
||||
parent_parser = @cache.parser(parent_lockfile_name)
|
||||
unless parser.platforms == parent_parser.platforms
|
||||
Bundler.ui.error("The platforms in #{lockfile_path} do not match the parent lockfile.")
|
||||
success = false
|
||||
end
|
||||
unless parser.bundler_version == parent_parser.bundler_version
|
||||
Bundler.ui.error("bundler (#{parser.bundler_version}) in #{lockfile_path} " \
|
||||
"does not match the parent lockfile's version (@#{parent_parser.bundler_version}).")
|
||||
success = false
|
||||
end
|
||||
unless parser.ruby_version == parent_parser.ruby_version
|
||||
Bundler.ui.error("ruby (#{parser.ruby_version || "<none>"}) in #{lockfile_path} " \
|
||||
"does not match the parent lockfile's version (#{parent_parser.ruby_version}).")
|
||||
success = false
|
||||
end
|
||||
|
||||
# look through top-level explicit dependencies for pinned requirements
|
||||
if lockfile_definition[:enforce_pinned_additional_dependencies]
|
||||
# look through what this spec depends on, and keep track of all pinned requirements
|
||||
find_pinned_dependencies(proven_pinned, spec.dependencies)
|
||||
|
||||
needs_pin_check << spec unless parent_spec
|
||||
find_pinned_dependencies(proven_pinned, parser.dependencies.each_value)
|
||||
end
|
||||
|
||||
next unless parent_spec
|
||||
# check for conflicting requirements (and build list of pins, in the same loop)
|
||||
parser.specs.each do |spec|
|
||||
parent_spec = @cache.specs(parent_lockfile_name)[[spec.name, spec.platform]]
|
||||
|
||||
# have to ensure Path sources are relative to their lockfile before comparing
|
||||
same_source = if [parent_spec.source, spec.source].grep(Source::Path).length == 2
|
||||
lockfile_definition[:lockfile]
|
||||
.dirname
|
||||
.join(spec.source.path)
|
||||
.ascend
|
||||
.any?(parent.dirname.join(parent_spec.source.path))
|
||||
else
|
||||
parent_spec.source == spec.source
|
||||
end
|
||||
if lockfile_definition[:enforce_pinned_additional_dependencies]
|
||||
# look through what this spec depends on, and keep track of all pinned requirements
|
||||
find_pinned_dependencies(proven_pinned, spec.dependencies)
|
||||
|
||||
next if parent_spec.version == spec.version && same_source
|
||||
needs_pin_check << spec unless parent_spec
|
||||
end
|
||||
|
||||
# the version in the parent lockfile cannot possibly satisfy the requirements
|
||||
# in this lockfile, and vice versa, so we assume it's intentional and allow it
|
||||
unless reverse_dependencies[spec.name].satisfied_by?(parent_spec.version) ||
|
||||
parent_reverse_dependencies[spec.name].satisfied_by?(spec.version)
|
||||
# we're allowing it to differ from the parent, so pin check requirement comes into play
|
||||
needs_pin_check << spec if lockfile_definition[:enforce_pinned_additional_dependencies]
|
||||
next
|
||||
next unless parent_spec
|
||||
|
||||
# have to ensure Path sources are relative to their lockfile before comparing
|
||||
same_source = if [parent_spec.source, spec.source].grep(Source::Path).length == 2
|
||||
lockfile_name
|
||||
.dirname
|
||||
.join(spec.source.path)
|
||||
.ascend
|
||||
.any?(parent_lockfile_name.dirname.join(parent_spec.source.path))
|
||||
else
|
||||
parent_spec.source == spec.source
|
||||
end
|
||||
|
||||
next if parent_spec.version == spec.version && same_source
|
||||
|
||||
# the version in the parent lockfile cannot possibly satisfy the requirements
|
||||
# in this lockfile, and vice versa, so we assume it's intentional and allow it
|
||||
if @cache.conflicting_requirements?(lockfile_name, parent_lockfile_name, spec, parent_spec)
|
||||
# we're allowing it to differ from the parent, so pin check requirement comes into play
|
||||
needs_pin_check << spec if lockfile_definition[:enforce_pinned_additional_dependencies]
|
||||
next
|
||||
end
|
||||
|
||||
Bundler.ui.error("#{spec}#{spec.git_version} in #{lockfile_path} " \
|
||||
"does not match the parent lockfile's version " \
|
||||
"(@#{parent_spec.version}#{parent_spec.git_version}); " \
|
||||
"this may be due to a conflicting requirement, which would require manual resolution.")
|
||||
success = false
|
||||
end
|
||||
|
||||
Bundler.ui.error("#{spec}#{spec.git_version} in #{lockfile_path} " \
|
||||
"does not match the parent lockfile's version " \
|
||||
"(@#{parent_spec.version}#{parent_spec.git_version}); " \
|
||||
"this may be due to a conflicting requirement, which would require manual resolution.")
|
||||
success = false
|
||||
# now that we have built a list of every gem that is pinned, go through
|
||||
# the gems that were in this lockfile, but not the parent lockfile, and
|
||||
# ensure it's pinned _somehow_
|
||||
needs_pin_check.each do |spec|
|
||||
pinned = case spec.source
|
||||
when Source::Git
|
||||
spec.source.ref == spec.source.revision
|
||||
when Source::Path
|
||||
true
|
||||
when Source::Rubygems
|
||||
proven_pinned.include?(spec.name)
|
||||
else
|
||||
false
|
||||
end
|
||||
|
||||
next if pinned
|
||||
|
||||
Bundler.ui.error("#{spec} in #{lockfile_path} has not been pinned to a specific version, " \
|
||||
"which is required since it is not part of the parent lockfile.")
|
||||
success = false
|
||||
end
|
||||
|
||||
success
|
||||
end
|
||||
|
||||
# now that we have built a list of every gem that is pinned, go through
|
||||
# the gems that were in this lockfile, but not the parent lockfile, and
|
||||
# ensure it's pinned _somehow_
|
||||
needs_pin_check.each do |spec|
|
||||
pinned = case spec.source
|
||||
when Source::Git
|
||||
spec.source.ref == spec.source.revision
|
||||
when Source::Path
|
||||
true
|
||||
when Source::Rubygems
|
||||
proven_pinned.include?(spec.name)
|
||||
else
|
||||
false
|
||||
end
|
||||
|
||||
next if pinned
|
||||
|
||||
Bundler.ui.error("#{spec} in #{lockfile_path} has not been pinned to a specific version, " \
|
||||
"which is required since it is not part of the parent lockfile.")
|
||||
success = false
|
||||
end
|
||||
|
||||
success
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def cache_reverse_dependencies(lockfile)
|
||||
# can use Gem::Requirement.default_prelease when Ruby 2.6 support is dropped
|
||||
reverse_dependencies = Hash.new { |h, k| h[k] = Gem::Requirement.new(">= 0.a") }
|
||||
|
||||
lockfile.dependencies.each_value do |spec|
|
||||
reverse_dependencies[spec.name].requirements.concat(spec.requirement.requirements)
|
||||
end
|
||||
lockfile.specs.each do |spec|
|
||||
spec.dependencies.each do |dependency|
|
||||
reverse_dependencies[dependency.name].requirements.concat(dependency.requirement.requirements)
|
||||
end
|
||||
end
|
||||
|
||||
reverse_dependencies
|
||||
end
|
||||
|
||||
def find_pinned_dependencies(proven_pinned, dependencies)
|
||||
dependencies.each do |dependency|
|
||||
dependency.requirement.requirements.each do |requirement|
|
||||
|
|
|
@ -11,12 +11,22 @@ module Bundler
|
|||
|
||||
# Significant changes:
|
||||
# * evaluate the prepare block as part of the gemfile
|
||||
# * keep track of the ruby version set in the default gemfile
|
||||
# * apply that ruby version to alternate lockfiles if they didn't set one
|
||||
# themselves
|
||||
# * mark Multilock as loaded once the main gemfile is evaluated
|
||||
# so that they're not loaded multiple times
|
||||
def evaluate(gemfile, lockfile, unlock)
|
||||
builder = new
|
||||
builder.eval_gemfile(gemfile, &Multilock.prepare_block) if Multilock.prepare_block
|
||||
builder.eval_gemfile(gemfile)
|
||||
if (ruby_version_requirement = builder.instance_variable_get(:@ruby_version))
|
||||
Multilock.lockfile_definitions[lockfile][:ruby_version_requirement] = ruby_version_requirement
|
||||
elsif (parent_lockfile = Multilock.lockfile_definitions.dig(lockfile, :parent)) &&
|
||||
(parent_lockfile_definition = Multilock.lockfile_definitions[parent_lockfile]) &&
|
||||
(parent_ruby_version_requirement = parent_lockfile_definition[:ruby_version_requirement])
|
||||
builder.instance_variable_set(:@ruby_version, parent_ruby_version_requirement)
|
||||
end
|
||||
Multilock.loaded!
|
||||
builder.to_definition(lockfile, unlock)
|
||||
end
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Bundler
|
||||
module Multilock
|
||||
module UI
|
||||
class Capture < Bundler::UI::Silent
|
||||
class << self
|
||||
def capture
|
||||
original_ui = Bundler.ui
|
||||
Bundler.ui = new
|
||||
yield
|
||||
Bundler.ui
|
||||
ensure
|
||||
Bundler.ui = original_ui
|
||||
end
|
||||
end
|
||||
|
||||
def initialize
|
||||
@messages = []
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def replay
|
||||
@messages.each do |(level, args)|
|
||||
Bundler.ui.send(level, *args)
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def add_color(string, _color)
|
||||
string
|
||||
end
|
||||
|
||||
%i[info confirm warn error debug].each do |level|
|
||||
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
||||
def #{level}(message = nil, newline = nil) # def info(message = nil, newline = nil)
|
||||
@messages << [:#{level}, [message, newline]] # @messages << [:info, [message, newline]]
|
||||
end # end
|
||||
#
|
||||
def #{level}? # def info?
|
||||
true # true
|
||||
end # end
|
||||
RUBY
|
||||
|
||||
def trace(message, newline = nil, force = false) # rubocop:disable Style/OptionalBooleanParameter
|
||||
@messages << [:trace, [message, newline, force]]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
module Bundler
|
||||
module Multilock
|
||||
VERSION = "1.2.3"
|
||||
VERSION = "1.3.0"
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue