bundler 1.15.1 → 1.17.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of bundler might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +320 -0
- data/README.md +17 -8
- data/bundler.gemspec +25 -9
- data/exe/bundle +1 -6
- data/exe/bundle_ruby +4 -3
- data/lib/bundler/build_metadata.rb +53 -0
- data/lib/bundler/capistrano.rb +5 -0
- data/lib/bundler/cli/add.rb +15 -6
- data/lib/bundler/cli/binstubs.rb +17 -9
- data/lib/bundler/cli/cache.rb +5 -4
- data/lib/bundler/cli/check.rb +3 -5
- data/lib/bundler/cli/clean.rb +5 -6
- data/lib/bundler/cli/common.rb +11 -2
- data/lib/bundler/cli/config.rb +2 -1
- data/lib/bundler/cli/console.rb +2 -1
- data/lib/bundler/cli/doctor.rb +48 -1
- data/lib/bundler/cli/exec.rb +6 -5
- data/lib/bundler/cli/gem.rb +13 -8
- data/lib/bundler/cli/info.rb +0 -1
- data/lib/bundler/cli/init.rb +18 -6
- data/lib/bundler/cli/inject.rb +1 -0
- data/lib/bundler/cli/install.rb +64 -77
- data/lib/bundler/cli/issue.rb +1 -1
- data/lib/bundler/cli/list.rb +58 -0
- data/lib/bundler/cli/lock.rb +0 -1
- data/lib/bundler/cli/open.rb +2 -2
- data/lib/bundler/cli/outdated.rb +20 -9
- data/lib/bundler/cli/package.rb +9 -6
- data/lib/bundler/cli/platform.rb +1 -0
- data/lib/bundler/cli/plugin.rb +1 -0
- data/lib/bundler/cli/pristine.rb +20 -6
- data/lib/bundler/cli/remove.rb +18 -0
- data/lib/bundler/cli/show.rb +0 -1
- data/lib/bundler/cli/update.rb +35 -7
- data/lib/bundler/cli/viz.rb +4 -0
- data/lib/bundler/cli.rb +234 -90
- data/lib/bundler/compact_index_client/cache.rb +1 -2
- data/lib/bundler/compact_index_client/updater.rb +35 -7
- data/lib/bundler/compact_index_client.rb +1 -0
- data/lib/bundler/compatibility_guard.rb +14 -0
- data/lib/bundler/constants.rb +1 -0
- data/lib/bundler/current_ruby.rb +13 -5
- data/lib/bundler/definition.rb +192 -139
- data/lib/bundler/dep_proxy.rb +3 -1
- data/lib/bundler/dependency.rb +9 -9
- data/lib/bundler/deployment.rb +1 -1
- data/lib/bundler/deprecate.rb +15 -3
- data/lib/bundler/dsl.rb +115 -64
- data/lib/bundler/endpoint_specification.rb +10 -1
- data/lib/bundler/env.rb +90 -29
- data/lib/bundler/environment_preserver.rb +27 -6
- data/lib/bundler/errors.rb +1 -0
- data/lib/bundler/feature_flag.rb +46 -4
- data/lib/bundler/fetcher/base.rb +1 -0
- data/lib/bundler/fetcher/compact_index.rb +2 -11
- data/lib/bundler/fetcher/dependency.rb +2 -1
- data/lib/bundler/fetcher/downloader.rb +11 -5
- data/lib/bundler/fetcher/index.rb +3 -2
- data/lib/bundler/fetcher.rb +18 -11
- data/lib/bundler/friendly_errors.rb +6 -1
- data/lib/bundler/gem_helper.rb +19 -10
- data/lib/bundler/gem_helpers.rb +1 -0
- data/lib/bundler/gem_remote_fetcher.rb +1 -0
- data/lib/bundler/gem_tasks.rb +1 -0
- data/lib/bundler/gem_version_promoter.rb +17 -2
- data/lib/bundler/gemdeps.rb +1 -0
- data/lib/bundler/graph.rb +1 -0
- data/lib/bundler/index.rb +8 -8
- data/lib/bundler/injector.rb +192 -30
- data/lib/bundler/inline.rb +10 -10
- data/lib/bundler/installer/gem_installer.rb +12 -2
- data/lib/bundler/installer/parallel_installer.rb +78 -42
- data/lib/bundler/installer/standalone.rb +1 -0
- data/lib/bundler/installer.rb +138 -53
- data/lib/bundler/lazy_specification.rb +3 -2
- data/lib/bundler/lockfile_generator.rb +95 -0
- data/lib/bundler/lockfile_parser.rb +10 -4
- data/lib/bundler/match_platform.rb +1 -0
- data/lib/bundler/mirror.rb +8 -5
- data/lib/bundler/plugin/api/source.rb +9 -2
- data/lib/bundler/plugin/events.rb +61 -0
- data/lib/bundler/plugin/index.rb +7 -2
- data/lib/bundler/plugin/installer.rb +7 -6
- data/lib/bundler/plugin/source_list.rb +7 -8
- data/lib/bundler/plugin.rb +13 -5
- data/lib/bundler/process_lock.rb +24 -0
- data/lib/bundler/psyched_yaml.rb +10 -0
- data/lib/bundler/remote_specification.rb +10 -1
- data/lib/bundler/resolver/spec_group.rb +106 -0
- data/lib/bundler/resolver.rb +158 -195
- data/lib/bundler/retry.rb +1 -0
- data/lib/bundler/ruby_dsl.rb +1 -0
- data/lib/bundler/ruby_version.rb +2 -1
- data/lib/bundler/rubygems_ext.rb +5 -4
- data/lib/bundler/rubygems_gem_installer.rb +31 -1
- data/lib/bundler/rubygems_integration.rb +71 -32
- data/lib/bundler/runtime.rb +11 -9
- data/lib/bundler/settings/validator.rb +102 -0
- data/lib/bundler/settings.rb +213 -86
- data/lib/bundler/setup.rb +4 -7
- data/lib/bundler/shared_helpers.rb +131 -26
- data/lib/bundler/similarity_detector.rb +1 -0
- data/lib/bundler/source/gemspec.rb +1 -0
- data/lib/bundler/source/git/git_proxy.rb +21 -11
- data/lib/bundler/source/git.rb +24 -19
- data/lib/bundler/source/metadata.rb +62 -0
- data/lib/bundler/source/path/installer.rb +2 -0
- data/lib/bundler/source/path.rb +11 -7
- data/lib/bundler/source/rubygems/remote.rb +8 -2
- data/lib/bundler/source/rubygems.rb +161 -84
- data/lib/bundler/source.rb +36 -0
- data/lib/bundler/source_list.rb +75 -15
- data/lib/bundler/spec_set.rb +12 -6
- data/lib/bundler/ssl_certs/certificate_manager.rb +2 -1
- data/lib/bundler/stub_specification.rb +1 -0
- data/lib/bundler/templates/.document +1 -0
- data/lib/bundler/templates/Executable +12 -0
- data/lib/bundler/templates/Executable.bundler +105 -0
- data/lib/bundler/templates/Gemfile +3 -0
- data/lib/bundler/templates/gems.rb +8 -0
- data/lib/bundler/templates/newgem/Gemfile.tt +2 -0
- data/lib/bundler/templates/newgem/README.md.tt +1 -1
- data/lib/bundler/templates/newgem/gitignore.tt +0 -1
- data/lib/bundler/templates/newgem/lib/newgem.rb.tt +1 -0
- data/lib/bundler/templates/newgem/newgem.gemspec.tt +12 -3
- data/lib/bundler/templates/newgem/rspec.tt +1 -0
- data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +0 -2
- data/lib/bundler/templates/newgem/{.travis.yml.tt → travis.yml.tt} +2 -0
- data/lib/bundler/ui/rg_proxy.rb +1 -0
- data/lib/bundler/ui/shell.rb +17 -4
- data/lib/bundler/ui/silent.rb +1 -0
- data/lib/bundler/ui.rb +1 -0
- data/lib/bundler/uri_credentials_filter.rb +1 -0
- data/lib/bundler/vendor/fileutils/lib/fileutils.rb +1638 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb +26 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +7 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +1 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +1 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +1 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +1 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +1 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +1 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +1 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +1 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +1 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +15 -4
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +3 -2
- data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +75 -7
- data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +2 -1
- data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +1 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb +3 -1
- data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +491 -148
- data/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +1 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +8 -4
- data/lib/bundler/vendor/molinillo/lib/molinillo.rb +2 -0
- data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +3 -1
- data/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +1 -0
- data/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +1 -0
- data/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +9 -1
- data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +45 -8
- data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +9 -3
- data/lib/bundler/vendor/thor/lib/thor/actions.rb +6 -3
- data/lib/bundler/vendor/thor/lib/thor/base.rb +27 -4
- data/lib/bundler/vendor/thor/lib/thor/command.rb +9 -7
- data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +12 -0
- data/lib/bundler/vendor/thor/lib/thor/group.rb +1 -1
- data/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb +2 -0
- data/lib/bundler/vendor/thor/lib/thor/parser/option.rb +5 -5
- data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +6 -5
- data/lib/bundler/vendor/thor/lib/thor/runner.rb +6 -4
- data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +10 -9
- data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
- data/lib/bundler/vendor/thor/lib/thor.rb +25 -8
- data/lib/bundler/vendored_fileutils.rb +9 -0
- data/lib/bundler/vendored_molinillo.rb +1 -0
- data/lib/bundler/vendored_persistent.rb +35 -0
- data/lib/bundler/vendored_thor.rb +1 -0
- data/lib/bundler/version.rb +6 -2
- data/lib/bundler/version_ranges.rb +1 -0
- data/lib/bundler/vlad.rb +5 -0
- data/lib/bundler/worker.rb +1 -0
- data/lib/bundler/yaml_serializer.rb +3 -3
- data/lib/bundler.rb +86 -52
- data/man/bundle-add.1 +18 -3
- data/man/bundle-add.1.txt +26 -14
- data/man/bundle-add.ronn +13 -2
- data/man/bundle-binstubs.1 +11 -1
- data/man/bundle-binstubs.1.txt +33 -18
- data/man/bundle-binstubs.ronn +15 -1
- data/man/bundle-check.1 +4 -4
- data/man/bundle-check.1.txt +15 -14
- data/man/bundle-check.ronn +3 -3
- data/man/bundle-clean.1 +1 -1
- data/man/bundle-clean.1.txt +10 -10
- data/man/bundle-config.1 +129 -29
- data/man/bundle-config.1.txt +285 -174
- data/man/bundle-config.ronn +167 -88
- data/man/bundle-doctor.1 +44 -0
- data/man/bundle-doctor.1.txt +44 -0
- data/man/bundle-doctor.ronn +33 -0
- data/man/bundle-exec.1 +6 -3
- data/man/bundle-exec.1.txt +78 -71
- data/man/bundle-exec.ronn +10 -3
- data/man/bundle-gem.1 +4 -4
- data/man/bundle-gem.1.txt +41 -40
- data/man/bundle-gem.ronn +3 -2
- data/man/bundle-info.1 +1 -1
- data/man/bundle-info.1.txt +8 -8
- data/man/bundle-init.1 +9 -4
- data/man/bundle-init.1.txt +23 -13
- data/man/bundle-init.ronn +15 -4
- data/man/bundle-inject.1 +4 -4
- data/man/bundle-inject.1.txt +10 -10
- data/man/bundle-inject.ronn +3 -3
- data/man/bundle-install.1 +31 -28
- data/man/bundle-install.1.txt +205 -194
- data/man/bundle-install.ronn +44 -35
- data/man/bundle-list.1 +50 -0
- data/man/bundle-list.1.txt +43 -0
- data/man/bundle-list.ronn +33 -0
- data/man/bundle-lock.1 +1 -1
- data/man/bundle-lock.1.txt +47 -47
- data/man/bundle-lock.ronn +1 -1
- data/man/bundle-open.1 +1 -1
- data/man/bundle-open.1.txt +7 -7
- data/man/bundle-outdated.1 +7 -3
- data/man/bundle-outdated.1.txt +40 -36
- data/man/bundle-outdated.ronn +6 -2
- data/man/bundle-package.1 +6 -3
- data/man/bundle-package.1.txt +44 -39
- data/man/bundle-package.ronn +7 -2
- data/man/bundle-platform.1 +1 -1
- data/man/bundle-platform.1.txt +13 -13
- data/man/bundle-pristine.1 +21 -3
- data/man/bundle-pristine.1.txt +33 -10
- data/man/bundle-pristine.ronn +24 -3
- data/man/bundle-remove.1 +31 -0
- data/man/bundle-remove.1.txt +34 -0
- data/man/bundle-remove.ronn +23 -0
- data/man/bundle-show.1 +3 -3
- data/man/bundle-show.1.txt +14 -12
- data/man/bundle-show.ronn +3 -2
- data/man/bundle-update.1 +13 -9
- data/man/bundle-update.1.txt +133 -130
- data/man/bundle-update.ronn +21 -17
- data/man/bundle-viz.1 +7 -7
- data/man/bundle-viz.1.txt +17 -15
- data/man/bundle-viz.ronn +6 -6
- data/man/bundle.1 +31 -32
- data/man/bundle.1.txt +63 -75
- data/man/bundle.ronn +35 -47
- data/man/gemfile.5 +44 -8
- data/man/gemfile.5.ronn +54 -8
- data/man/gemfile.5.txt +218 -165
- data/man/index.txt +25 -15
- metadata +36 -44
- data/.codeclimate.yml +0 -25
- data/.gitignore +0 -18
- data/.rspec +0 -3
- data/.rubocop.yml +0 -131
- data/.rubocop_todo.yml +0 -418
- data/.travis.yml +0 -122
- data/CODE_OF_CONDUCT.md +0 -42
- data/CONTRIBUTING.md +0 -17
- data/Rakefile +0 -346
- data/bin/rake +0 -19
- data/bin/rspec +0 -15
- data/bin/rubocop +0 -17
- data/bin/with_rubygems +0 -39
- data/doc/README.md +0 -30
- data/doc/TROUBLESHOOTING.md +0 -64
- data/doc/contributing/BUG_TRIAGE.md +0 -36
- data/doc/contributing/COMMUNITY.md +0 -13
- data/doc/contributing/GETTING_HELP.md +0 -11
- data/doc/contributing/HOW_YOU_CAN_HELP.md +0 -27
- data/doc/contributing/ISSUES.md +0 -51
- data/doc/contributing/README.md +0 -38
- data/doc/development/NEW_FEATURES.md +0 -10
- data/doc/development/PULL_REQUESTS.md +0 -40
- data/doc/development/README.md +0 -19
- data/doc/development/RELEASING.md +0 -9
- data/doc/development/SETUP.md +0 -29
- data/doc/documentation/README.md +0 -29
- data/doc/documentation/VISION.md +0 -26
- data/doc/documentation/WRITING.md +0 -54
- data/lib/bundler/postit_trampoline.rb +0 -73
- data/lib/bundler/vendor/postit/lib/postit/environment.rb +0 -44
- data/lib/bundler/vendor/postit/lib/postit/installer.rb +0 -28
- data/lib/bundler/vendor/postit/lib/postit/parser.rb +0 -21
- data/lib/bundler/vendor/postit/lib/postit/setup.rb +0 -12
- data/lib/bundler/vendor/postit/lib/postit/version.rb +0 -3
- data/lib/bundler/vendor/postit/lib/postit.rb +0 -15
- data/task/release.rake +0 -116
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "uri"
|
3
4
|
require "rubygems/user_interaction"
|
4
5
|
|
@@ -31,6 +32,7 @@ module Bundler
|
|
31
32
|
end
|
32
33
|
|
33
34
|
def cached!
|
35
|
+
@specs = nil
|
34
36
|
@allow_cached = true
|
35
37
|
end
|
36
38
|
|
@@ -49,6 +51,7 @@ module Bundler
|
|
49
51
|
end
|
50
52
|
|
51
53
|
def can_lock?(spec)
|
54
|
+
return super if Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
|
52
55
|
spec.source.is_a?(Rubygems)
|
53
56
|
end
|
54
57
|
|
@@ -69,8 +72,12 @@ module Bundler
|
|
69
72
|
end
|
70
73
|
|
71
74
|
def to_s
|
72
|
-
|
73
|
-
|
75
|
+
if remotes.empty?
|
76
|
+
"locally installed gems"
|
77
|
+
else
|
78
|
+
remote_names = remotes.map(&:to_s).join(", ")
|
79
|
+
"rubygems repository #{remote_names} or installed locally"
|
80
|
+
end
|
74
81
|
end
|
75
82
|
alias_method :name, :to_s
|
76
83
|
|
@@ -99,8 +106,8 @@ module Bundler
|
|
99
106
|
end
|
100
107
|
end
|
101
108
|
|
102
|
-
if installed?(spec) &&
|
103
|
-
|
109
|
+
if installed?(spec) && !force
|
110
|
+
print_using_message "Using #{version_message(spec)}"
|
104
111
|
return nil # no post-install message
|
105
112
|
end
|
106
113
|
|
@@ -131,6 +138,8 @@ module Bundler
|
|
131
138
|
bin_path = Bundler.system_bindir
|
132
139
|
end
|
133
140
|
|
141
|
+
Bundler.mkdir_p bin_path, :no_sudo => true unless spec.executables.empty? || Bundler.rubygems.provides?(">= 2.7.5")
|
142
|
+
|
134
143
|
installed_spec = nil
|
135
144
|
Bundler.rubygems.preserve_paths do
|
136
145
|
installed_spec = Bundler::RubyGemsGemInstaller.at(
|
@@ -141,7 +150,8 @@ module Bundler
|
|
141
150
|
:wrappers => true,
|
142
151
|
:env_shebang => true,
|
143
152
|
:build_args => opts[:build_args],
|
144
|
-
:bundler_expected_checksum => spec.respond_to?(:checksum) && spec.checksum
|
153
|
+
:bundler_expected_checksum => spec.respond_to?(:checksum) && spec.checksum,
|
154
|
+
:bundler_extension_cache_path => extension_cache_path(spec)
|
145
155
|
).install
|
146
156
|
end
|
147
157
|
spec.full_gem_path = installed_spec.full_gem_path
|
@@ -212,13 +222,21 @@ module Bundler
|
|
212
222
|
@remotes.unshift(uri) unless @remotes.include?(uri)
|
213
223
|
end
|
214
224
|
|
215
|
-
def
|
225
|
+
def equivalent_remotes?(other_remotes)
|
226
|
+
other_remotes.map(&method(:remove_auth)) == @remotes.map(&method(:remove_auth))
|
227
|
+
end
|
228
|
+
|
229
|
+
def replace_remotes(other_remotes, allow_equivalent = false)
|
216
230
|
return false if other_remotes == @remotes
|
217
231
|
|
232
|
+
equivalent = allow_equivalent && equivalent_remotes?(other_remotes)
|
233
|
+
|
218
234
|
@remotes = []
|
219
235
|
other_remotes.reverse_each do |r|
|
220
236
|
add_remote r.to_s
|
221
237
|
end
|
238
|
+
|
239
|
+
!equivalent
|
222
240
|
end
|
223
241
|
|
224
242
|
def unmet_deps
|
@@ -236,6 +254,41 @@ module Bundler
|
|
236
254
|
end
|
237
255
|
end
|
238
256
|
|
257
|
+
def double_check_for(unmet_dependency_names)
|
258
|
+
return unless @allow_remote
|
259
|
+
return unless api_fetchers.any?
|
260
|
+
|
261
|
+
unmet_dependency_names = unmet_dependency_names.call
|
262
|
+
unless unmet_dependency_names.nil?
|
263
|
+
if api_fetchers.size <= 1
|
264
|
+
# can't do this when there are multiple fetchers because then we might not fetch from _all_
|
265
|
+
# of them
|
266
|
+
unmet_dependency_names -= remote_specs.spec_names # avoid re-fetching things we've already gotten
|
267
|
+
end
|
268
|
+
return if unmet_dependency_names.empty?
|
269
|
+
end
|
270
|
+
|
271
|
+
Bundler.ui.debug "Double checking for #{unmet_dependency_names || "all specs (due to the size of the request)"} in #{self}"
|
272
|
+
|
273
|
+
fetch_names(api_fetchers, unmet_dependency_names, specs, false)
|
274
|
+
end
|
275
|
+
|
276
|
+
def dependency_names_to_double_check
|
277
|
+
names = []
|
278
|
+
remote_specs.each do |spec|
|
279
|
+
case spec
|
280
|
+
when EndpointSpecification, Gem::Specification, StubSpecification, LazySpecification
|
281
|
+
names.concat(spec.runtime_dependencies)
|
282
|
+
when RemoteSpecification # from the full index
|
283
|
+
return nil
|
284
|
+
else
|
285
|
+
raise "unhandled spec type (#{spec.inspect})"
|
286
|
+
end
|
287
|
+
end
|
288
|
+
names.map!(&:name) if names
|
289
|
+
names
|
290
|
+
end
|
291
|
+
|
239
292
|
protected
|
240
293
|
|
241
294
|
def credless_remotes
|
@@ -276,7 +329,7 @@ module Bundler
|
|
276
329
|
end
|
277
330
|
|
278
331
|
def suppress_configured_credentials(remote)
|
279
|
-
remote_nouser = remote
|
332
|
+
remote_nouser = remove_auth(remote)
|
280
333
|
if remote.userinfo && remote.userinfo == Bundler.settings[remote_nouser]
|
281
334
|
remote_nouser
|
282
335
|
else
|
@@ -284,15 +337,18 @@ module Bundler
|
|
284
337
|
end
|
285
338
|
end
|
286
339
|
|
340
|
+
def remove_auth(remote)
|
341
|
+
if remote.user || remote.password
|
342
|
+
remote.dup.tap {|uri| uri.user = uri.password = nil }.to_s
|
343
|
+
else
|
344
|
+
remote.to_s
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
287
348
|
def installed_specs
|
288
|
-
@installed_specs ||=
|
289
|
-
idx = Index.new
|
290
|
-
have_bundler = false
|
349
|
+
@installed_specs ||= Index.build do |idx|
|
291
350
|
Bundler.rubygems.all_specs.reverse_each do |spec|
|
292
|
-
if spec.name == "bundler"
|
293
|
-
next unless spec.version.to_s == VERSION
|
294
|
-
have_bundler = true
|
295
|
-
end
|
351
|
+
next if spec.name == "bundler"
|
296
352
|
spec.source = self
|
297
353
|
if Bundler.rubygems.spec_missing_extensions?(spec, false)
|
298
354
|
Bundler.ui.debug "Source #{self} is ignoring #{spec} because it is missing extensions"
|
@@ -300,23 +356,6 @@ module Bundler
|
|
300
356
|
end
|
301
357
|
idx << spec
|
302
358
|
end
|
303
|
-
|
304
|
-
# Always have bundler locally
|
305
|
-
unless have_bundler
|
306
|
-
# We're running bundler directly from the source
|
307
|
-
# so, let's create a fake gemspec for it (it's a path)
|
308
|
-
# gemspec
|
309
|
-
bundler = Gem::Specification.new do |s|
|
310
|
-
s.name = "bundler"
|
311
|
-
s.version = VERSION
|
312
|
-
s.platform = Gem::Platform::RUBY
|
313
|
-
s.source = self
|
314
|
-
s.authors = ["bundler team"]
|
315
|
-
s.loaded_from = File.expand_path("..", __FILE__)
|
316
|
-
end
|
317
|
-
idx << bundler
|
318
|
-
end
|
319
|
-
idx
|
320
359
|
end
|
321
360
|
end
|
322
361
|
|
@@ -334,9 +373,9 @@ module Bundler
|
|
334
373
|
end
|
335
374
|
idx << s
|
336
375
|
end
|
337
|
-
end
|
338
376
|
|
339
|
-
|
377
|
+
idx
|
378
|
+
end
|
340
379
|
end
|
341
380
|
|
342
381
|
def api_fetchers
|
@@ -348,71 +387,36 @@ module Bundler
|
|
348
387
|
index_fetchers = fetchers - api_fetchers
|
349
388
|
|
350
389
|
# gather lists from non-api sites
|
351
|
-
index_fetchers
|
352
|
-
Bundler.ui.info "Fetching source index from #{f.uri}"
|
353
|
-
idx.use f.specs_with_retry(nil, self)
|
354
|
-
end
|
390
|
+
fetch_names(index_fetchers, nil, idx, false)
|
355
391
|
|
356
392
|
# because ensuring we have all the gems we need involves downloading
|
357
393
|
# the gemspecs of those gems, if the non-api sites contain more than
|
358
|
-
# about
|
394
|
+
# about 500 gems, we treat all sites as non-api for speed.
|
359
395
|
allow_api = idx.size < API_REQUEST_LIMIT && dependency_names.size < API_REQUEST_LIMIT
|
360
396
|
Bundler.ui.debug "Need to query more than #{API_REQUEST_LIMIT} gems." \
|
361
397
|
" Downloading full index instead..." unless allow_api
|
362
398
|
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
idx.use f.specs_with_retry(dependency_names, self)
|
367
|
-
Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
|
368
|
-
end
|
369
|
-
|
370
|
-
# Suppose the gem Foo depends on the gem Bar. Foo exists in Source A. Bar has some versions that exist in both
|
371
|
-
# sources A and B. At this point, the API request will have found all the versions of Bar in source A,
|
372
|
-
# but will not have found any versions of Bar from source B, which is a problem if the requested version
|
373
|
-
# of Foo specifically depends on a version of Bar that is only found in source B. This ensures that for
|
374
|
-
# each spec we found, we add all possible versions from all sources to the index.
|
375
|
-
loop do
|
376
|
-
idxcount = idx.size
|
377
|
-
api_fetchers.each do |f|
|
378
|
-
Bundler.ui.info "Fetching version metadata from #{f.uri}", Bundler.ui.debug?
|
379
|
-
idx.use f.specs_with_retry(idx.dependency_names, self), true
|
380
|
-
Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
|
381
|
-
end
|
382
|
-
break if idxcount == idx.size
|
383
|
-
end
|
384
|
-
|
385
|
-
if api_fetchers.any?
|
386
|
-
# it's possible that gems from one source depend on gems from some
|
387
|
-
# other source, so now we download gemspecs and iterate over those
|
388
|
-
# dependencies, looking for gems we don't have info on yet.
|
389
|
-
unmet = idx.unmet_dependency_names
|
390
|
-
|
391
|
-
# if there are any cross-site gems we missed, get them now
|
392
|
-
api_fetchers.each do |f|
|
393
|
-
Bundler.ui.info "Fetching dependency metadata from #{f.uri}", Bundler.ui.debug?
|
394
|
-
idx.use f.specs_with_retry(unmet, self)
|
395
|
-
Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
|
396
|
-
end if unmet.any?
|
397
|
-
else
|
398
|
-
allow_api = false
|
399
|
-
end
|
400
|
-
end
|
399
|
+
fetch_names(api_fetchers, allow_api && dependency_names, idx, false)
|
400
|
+
end
|
401
|
+
end
|
401
402
|
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
403
|
+
def fetch_names(fetchers, dependency_names, index, override_dupes)
|
404
|
+
fetchers.each do |f|
|
405
|
+
if dependency_names
|
406
|
+
Bundler.ui.info "Fetching gem metadata from #{f.uri}", Bundler.ui.debug?
|
407
|
+
index.use f.specs_with_retry(dependency_names, self), override_dupes
|
408
|
+
Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
|
409
|
+
else
|
410
|
+
Bundler.ui.info "Fetching source index from #{f.uri}"
|
411
|
+
index.use f.specs_with_retry(nil, self), override_dupes
|
407
412
|
end
|
408
413
|
end
|
409
414
|
end
|
410
415
|
|
411
416
|
def fetch_gem(spec)
|
412
417
|
return false unless spec.remote
|
413
|
-
|
418
|
+
|
414
419
|
spec.fetch_platform
|
415
|
-
Bundler.ui.confirm("Fetching #{version_message(spec)}")
|
416
420
|
|
417
421
|
download_path = requires_sudo? ? Bundler.tmp(spec.full_name) : rubygems_dir
|
418
422
|
gem_path = "#{rubygems_dir}/cache/#{spec.full_name}.gem"
|
@@ -420,7 +424,7 @@ module Bundler
|
|
420
424
|
SharedHelpers.filesystem_access("#{download_path}/cache") do |p|
|
421
425
|
FileUtils.mkdir_p(p)
|
422
426
|
end
|
423
|
-
|
427
|
+
download_gem(spec, download_path)
|
424
428
|
|
425
429
|
if requires_sudo?
|
426
430
|
SharedHelpers.filesystem_access("#{rubygems_dir}/cache") do |p|
|
@@ -457,6 +461,79 @@ module Bundler
|
|
457
461
|
def cache_path
|
458
462
|
Bundler.app_cache
|
459
463
|
end
|
464
|
+
|
465
|
+
private
|
466
|
+
|
467
|
+
# Checks if the requested spec exists in the global cache. If it does,
|
468
|
+
# we copy it to the download path, and if it does not, we download it.
|
469
|
+
#
|
470
|
+
# @param [Specification] spec
|
471
|
+
# the spec we want to download or retrieve from the cache.
|
472
|
+
#
|
473
|
+
# @param [String] download_path
|
474
|
+
# the local directory the .gem will end up in.
|
475
|
+
#
|
476
|
+
def download_gem(spec, download_path)
|
477
|
+
local_path = File.join(download_path, "cache/#{spec.full_name}.gem")
|
478
|
+
|
479
|
+
if (cache_path = download_cache_path(spec)) && cache_path.file?
|
480
|
+
SharedHelpers.filesystem_access(local_path) do
|
481
|
+
FileUtils.cp(cache_path, local_path)
|
482
|
+
end
|
483
|
+
else
|
484
|
+
uri = spec.remote.uri
|
485
|
+
Bundler.ui.confirm("Fetching #{version_message(spec)}")
|
486
|
+
rubygems_local_path = Bundler.rubygems.download_gem(spec, uri, download_path)
|
487
|
+
if rubygems_local_path != local_path
|
488
|
+
FileUtils.mv(rubygems_local_path, local_path)
|
489
|
+
end
|
490
|
+
cache_globally(spec, local_path)
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
# Checks if the requested spec exists in the global cache. If it does
|
495
|
+
# not, we create the relevant global cache subdirectory if it does not
|
496
|
+
# exist and copy the spec from the local cache to the global cache.
|
497
|
+
#
|
498
|
+
# @param [Specification] spec
|
499
|
+
# the spec we want to copy to the global cache.
|
500
|
+
#
|
501
|
+
# @param [String] local_cache_path
|
502
|
+
# the local directory from which we want to copy the .gem.
|
503
|
+
#
|
504
|
+
def cache_globally(spec, local_cache_path)
|
505
|
+
return unless cache_path = download_cache_path(spec)
|
506
|
+
return if cache_path.exist?
|
507
|
+
|
508
|
+
SharedHelpers.filesystem_access(cache_path.dirname, &:mkpath)
|
509
|
+
SharedHelpers.filesystem_access(cache_path) do
|
510
|
+
FileUtils.cp(local_cache_path, cache_path)
|
511
|
+
end
|
512
|
+
end
|
513
|
+
|
514
|
+
# Returns the global cache path of the calling Rubygems::Source object.
|
515
|
+
#
|
516
|
+
# Note that the Source determines the path's subdirectory. We use this
|
517
|
+
# subdirectory in the global cache path so that gems with the same name
|
518
|
+
# -- and possibly different versions -- from different sources are saved
|
519
|
+
# to their respective subdirectories and do not override one another.
|
520
|
+
#
|
521
|
+
# @param [Gem::Specification] specification
|
522
|
+
#
|
523
|
+
# @return [Pathname] The global cache path.
|
524
|
+
#
|
525
|
+
def download_cache_path(spec)
|
526
|
+
return unless Bundler.feature_flag.global_gem_cache?
|
527
|
+
return unless remote = spec.remote
|
528
|
+
return unless cache_slug = remote.cache_slug
|
529
|
+
|
530
|
+
Bundler.user_cache.join("gems", cache_slug, spec.file_name)
|
531
|
+
end
|
532
|
+
|
533
|
+
def extension_cache_slug(spec)
|
534
|
+
return unless remote = spec.remote
|
535
|
+
remote.cache_slug
|
536
|
+
end
|
460
537
|
end
|
461
538
|
end
|
462
539
|
end
|
data/lib/bundler/source.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Bundler
|
3
4
|
class Source
|
4
5
|
autoload :Gemspec, "bundler/source/gemspec"
|
5
6
|
autoload :Git, "bundler/source/git"
|
7
|
+
autoload :Metadata, "bundler/source/metadata"
|
6
8
|
autoload :Path, "bundler/source/path"
|
7
9
|
autoload :Rubygems, "bundler/source/rubygems"
|
8
10
|
|
@@ -31,6 +33,15 @@ module Bundler
|
|
31
33
|
spec.source == self
|
32
34
|
end
|
33
35
|
|
36
|
+
# it's possible that gems from one source depend on gems from some
|
37
|
+
# other source, so now we download gemspecs and iterate over those
|
38
|
+
# dependencies, looking for gems we don't have info on yet.
|
39
|
+
def double_check_for(*); end
|
40
|
+
|
41
|
+
def dependency_names_to_double_check
|
42
|
+
specs.dependency_names
|
43
|
+
end
|
44
|
+
|
34
45
|
def include?(other)
|
35
46
|
other == self
|
36
47
|
end
|
@@ -39,6 +50,19 @@ module Bundler
|
|
39
50
|
"#<#{self.class}:0x#{object_id} #{self}>"
|
40
51
|
end
|
41
52
|
|
53
|
+
def path?
|
54
|
+
instance_of?(Bundler::Source::Path)
|
55
|
+
end
|
56
|
+
|
57
|
+
def extension_cache_path(spec)
|
58
|
+
return unless Bundler.feature_flag.global_gem_cache?
|
59
|
+
return unless source_slug = extension_cache_slug(spec)
|
60
|
+
Bundler.user_cache.join(
|
61
|
+
"extensions", Gem::Platform.local.to_s, Bundler.ruby_scope,
|
62
|
+
source_slug, spec.full_name
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
42
66
|
private
|
43
67
|
|
44
68
|
def version_color(spec_version, locked_spec_version)
|
@@ -54,5 +78,17 @@ module Bundler
|
|
54
78
|
def earlier_version?(spec_version, locked_spec_version)
|
55
79
|
Gem::Version.new(spec_version) < Gem::Version.new(locked_spec_version)
|
56
80
|
end
|
81
|
+
|
82
|
+
def print_using_message(message)
|
83
|
+
if !message.include?("(was ") && Bundler.feature_flag.suppress_install_using_messages?
|
84
|
+
Bundler.ui.debug message
|
85
|
+
else
|
86
|
+
Bundler.ui.info message
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def extension_cache_slug(_)
|
91
|
+
nil
|
92
|
+
end
|
57
93
|
end
|
58
94
|
end
|
data/lib/bundler/source_list.rb
CHANGED
@@ -1,16 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Bundler
|
3
4
|
class SourceList
|
4
5
|
attr_reader :path_sources,
|
5
6
|
:git_sources,
|
6
|
-
:plugin_sources
|
7
|
+
:plugin_sources,
|
8
|
+
:global_rubygems_source,
|
9
|
+
:metadata_source
|
7
10
|
|
8
11
|
def initialize
|
9
|
-
@path_sources
|
10
|
-
@git_sources
|
11
|
-
@plugin_sources
|
12
|
-
@
|
13
|
-
@
|
12
|
+
@path_sources = []
|
13
|
+
@git_sources = []
|
14
|
+
@plugin_sources = []
|
15
|
+
@global_rubygems_source = nil
|
16
|
+
@rubygems_aggregate = rubygems_aggregate_class.new
|
17
|
+
@rubygems_sources = []
|
18
|
+
@metadata_source = Source::Metadata.new
|
14
19
|
end
|
15
20
|
|
16
21
|
def add_path_source(options = {})
|
@@ -35,13 +40,28 @@ module Bundler
|
|
35
40
|
add_source_to_list Plugin.source(source).new(options), @plugin_sources
|
36
41
|
end
|
37
42
|
|
43
|
+
def global_rubygems_source=(uri)
|
44
|
+
if Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
|
45
|
+
@global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri)
|
46
|
+
end
|
47
|
+
add_rubygems_remote(uri)
|
48
|
+
end
|
49
|
+
|
38
50
|
def add_rubygems_remote(uri)
|
51
|
+
if Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
|
52
|
+
return if Bundler.feature_flag.disable_multisource?
|
53
|
+
raise InvalidOption, "`lockfile_uses_separate_rubygems_sources` cannot be set without `disable_multisource` being set"
|
54
|
+
end
|
39
55
|
@rubygems_aggregate.add_remote(uri)
|
40
56
|
@rubygems_aggregate
|
41
57
|
end
|
42
58
|
|
59
|
+
def default_source
|
60
|
+
global_rubygems_source || @rubygems_aggregate
|
61
|
+
end
|
62
|
+
|
43
63
|
def rubygems_sources
|
44
|
-
@rubygems_sources + [
|
64
|
+
@rubygems_sources + [default_source]
|
45
65
|
end
|
46
66
|
|
47
67
|
def rubygems_remotes
|
@@ -49,18 +69,25 @@ module Bundler
|
|
49
69
|
end
|
50
70
|
|
51
71
|
def all_sources
|
52
|
-
path_sources + git_sources + plugin_sources + rubygems_sources
|
72
|
+
path_sources + git_sources + plugin_sources + rubygems_sources + [metadata_source]
|
53
73
|
end
|
54
74
|
|
55
75
|
def get(source)
|
56
|
-
source_list_for(source).find {|s| source
|
76
|
+
source_list_for(source).find {|s| equal_source?(source, s) || equivalent_source?(source, s) }
|
57
77
|
end
|
58
78
|
|
59
79
|
def lock_sources
|
60
|
-
|
61
|
-
|
80
|
+
if Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
|
81
|
+
[[default_source], @rubygems_sources, git_sources, path_sources, plugin_sources].map do |sources|
|
82
|
+
sources.sort_by(&:to_s)
|
83
|
+
end.flatten(1)
|
84
|
+
else
|
85
|
+
lock_sources = (path_sources + git_sources + plugin_sources).sort_by(&:to_s)
|
86
|
+
lock_sources << combine_rubygems_sources
|
87
|
+
end
|
62
88
|
end
|
63
89
|
|
90
|
+
# Returns true if there are changes
|
64
91
|
def replace_sources!(replacement_sources)
|
65
92
|
return true if replacement_sources.empty?
|
66
93
|
|
@@ -70,13 +97,14 @@ module Bundler
|
|
70
97
|
end
|
71
98
|
end
|
72
99
|
|
73
|
-
replacement_rubygems =
|
100
|
+
replacement_rubygems = !Bundler.feature_flag.lockfile_uses_separate_rubygems_sources? &&
|
74
101
|
replacement_sources.detect {|s| s.is_a?(Source::Rubygems) }
|
75
102
|
@rubygems_aggregate = replacement_rubygems if replacement_rubygems
|
76
103
|
|
77
|
-
|
78
|
-
|
79
|
-
|
104
|
+
return true if !equal_sources?(lock_sources, replacement_sources) && !equivalent_sources?(lock_sources, replacement_sources)
|
105
|
+
return true if replacement_rubygems && rubygems_remotes.to_set != replacement_rubygems.remotes.to_set
|
106
|
+
|
107
|
+
false
|
80
108
|
end
|
81
109
|
|
82
110
|
def cached!
|
@@ -93,6 +121,10 @@ module Bundler
|
|
93
121
|
|
94
122
|
private
|
95
123
|
|
124
|
+
def rubygems_aggregate_class
|
125
|
+
Source::Rubygems
|
126
|
+
end
|
127
|
+
|
96
128
|
def add_source_to_list(source, list)
|
97
129
|
list.unshift(source).uniq!
|
98
130
|
source
|
@@ -122,5 +154,33 @@ module Bundler
|
|
122
154
|
"protocol to keep your data secure."
|
123
155
|
end
|
124
156
|
end
|
157
|
+
|
158
|
+
def equal_sources?(lock_sources, replacement_sources)
|
159
|
+
lock_sources.to_set == replacement_sources.to_set
|
160
|
+
end
|
161
|
+
|
162
|
+
def equal_source?(source, other_source)
|
163
|
+
source == other_source
|
164
|
+
end
|
165
|
+
|
166
|
+
def equivalent_source?(source, other_source)
|
167
|
+
return false unless Bundler.settings[:allow_deployment_source_credential_changes] && source.is_a?(Source::Rubygems)
|
168
|
+
|
169
|
+
equivalent_rubygems_sources?([source], [other_source])
|
170
|
+
end
|
171
|
+
|
172
|
+
def equivalent_sources?(lock_sources, replacement_sources)
|
173
|
+
return false unless Bundler.settings[:allow_deployment_source_credential_changes]
|
174
|
+
|
175
|
+
lock_rubygems_sources, lock_other_sources = lock_sources.partition {|s| s.is_a?(Source::Rubygems) }
|
176
|
+
replacement_rubygems_sources, replacement_other_sources = replacement_sources.partition {|s| s.is_a?(Source::Rubygems) }
|
177
|
+
|
178
|
+
equivalent_rubygems_sources?(lock_rubygems_sources, replacement_rubygems_sources) && equal_sources?(lock_other_sources, replacement_other_sources)
|
179
|
+
end
|
180
|
+
|
181
|
+
def equivalent_rubygems_sources?(lock_sources, replacement_sources)
|
182
|
+
actual_remotes = replacement_sources.map(&:remotes).flatten.uniq
|
183
|
+
lock_sources.all? {|s| s.equivalent_remotes?(actual_remotes) }
|
184
|
+
end
|
125
185
|
end
|
126
186
|
end
|
data/lib/bundler/spec_set.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "tsort"
|
3
4
|
require "forwardable"
|
4
5
|
require "set"
|
@@ -36,7 +37,10 @@ module Bundler
|
|
36
37
|
elsif check
|
37
38
|
return false
|
38
39
|
elsif raise_on_missing
|
39
|
-
|
40
|
+
others = lookup[dep.name] if match_current_platform
|
41
|
+
message = "Unable to find a spec satisfying #{dep} in the set. Perhaps the lockfile is corrupted?"
|
42
|
+
message += " Found #{others.join(", ")} that did not match the current platform." if others && !others.empty?
|
43
|
+
raise GemNotFound, message
|
40
44
|
end
|
41
45
|
end
|
42
46
|
|
@@ -76,7 +80,7 @@ module Bundler
|
|
76
80
|
end
|
77
81
|
|
78
82
|
def materialize(deps, missing_specs = nil)
|
79
|
-
materialized = self.for(deps, [], false, true, missing_specs).to_a
|
83
|
+
materialized = self.for(deps, [], false, true, !missing_specs).to_a
|
80
84
|
deps = materialized.map(&:name).uniq
|
81
85
|
materialized.map! do |s|
|
82
86
|
next s unless s.is_a?(LazySpecification)
|
@@ -109,9 +113,10 @@ module Bundler
|
|
109
113
|
|
110
114
|
def merge(set)
|
111
115
|
arr = sorted.dup
|
112
|
-
set.each do |
|
113
|
-
|
114
|
-
arr
|
116
|
+
set.each do |set_spec|
|
117
|
+
full_name = set_spec.full_name
|
118
|
+
next if arr.any? {|spec| spec.full_name == full_name }
|
119
|
+
arr << set_spec
|
115
120
|
end
|
116
121
|
SpecSet.new(arr)
|
117
122
|
end
|
@@ -160,7 +165,8 @@ module Bundler
|
|
160
165
|
end
|
161
166
|
|
162
167
|
def tsort_each_node
|
163
|
-
|
168
|
+
# MUST sort by name for backwards compatibility
|
169
|
+
@specs.sort_by(&:name).each {|s| yield s }
|
164
170
|
end
|
165
171
|
|
166
172
|
def spec_for_dependency(dep, match_current_platform)
|
@@ -0,0 +1 @@
|
|
1
|
+
# Ignore all files in this directory
|
@@ -1,5 +1,6 @@
|
|
1
1
|
#!/usr/bin/env <%= Bundler.settings[:shebang] || RbConfig::CONFIG["ruby_install_name"] %>
|
2
2
|
# frozen_string_literal: true
|
3
|
+
|
3
4
|
#
|
4
5
|
# This file was generated by Bundler.
|
5
6
|
#
|
@@ -11,6 +12,17 @@ require "pathname"
|
|
11
12
|
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../<%= relative_gemfile_path %>",
|
12
13
|
Pathname.new(__FILE__).realpath)
|
13
14
|
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
14
26
|
require "rubygems"
|
15
27
|
require "bundler/setup"
|
16
28
|
|