bundler 2.0.2
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 +7 -0
- data/CHANGELOG.md +3111 -0
- data/LICENSE.md +23 -0
- data/README.md +63 -0
- data/bundler.gemspec +65 -0
- data/exe/bundle +31 -0
- data/exe/bundle_ruby +60 -0
- data/exe/bundler +4 -0
- data/lib/bundler.rb +567 -0
- data/lib/bundler/build_metadata.rb +53 -0
- data/lib/bundler/capistrano.rb +22 -0
- data/lib/bundler/cli.rb +792 -0
- data/lib/bundler/cli/add.rb +35 -0
- data/lib/bundler/cli/binstubs.rb +49 -0
- data/lib/bundler/cli/cache.rb +36 -0
- data/lib/bundler/cli/check.rb +38 -0
- data/lib/bundler/cli/clean.rb +25 -0
- data/lib/bundler/cli/common.rb +102 -0
- data/lib/bundler/cli/config.rb +119 -0
- data/lib/bundler/cli/console.rb +43 -0
- data/lib/bundler/cli/doctor.rb +140 -0
- data/lib/bundler/cli/exec.rb +105 -0
- data/lib/bundler/cli/gem.rb +252 -0
- data/lib/bundler/cli/info.rb +50 -0
- data/lib/bundler/cli/init.rb +47 -0
- data/lib/bundler/cli/inject.rb +60 -0
- data/lib/bundler/cli/install.rb +218 -0
- data/lib/bundler/cli/issue.rb +40 -0
- data/lib/bundler/cli/list.rb +58 -0
- data/lib/bundler/cli/lock.rb +63 -0
- data/lib/bundler/cli/open.rb +26 -0
- data/lib/bundler/cli/outdated.rb +266 -0
- data/lib/bundler/cli/package.rb +49 -0
- data/lib/bundler/cli/platform.rb +46 -0
- data/lib/bundler/cli/plugin.rb +24 -0
- data/lib/bundler/cli/pristine.rb +47 -0
- data/lib/bundler/cli/remove.rb +18 -0
- data/lib/bundler/cli/show.rb +75 -0
- data/lib/bundler/cli/update.rb +91 -0
- data/lib/bundler/cli/viz.rb +31 -0
- data/lib/bundler/compact_index_client.rb +109 -0
- data/lib/bundler/compact_index_client/cache.rb +118 -0
- data/lib/bundler/compact_index_client/updater.rb +116 -0
- data/lib/bundler/compatibility_guard.rb +13 -0
- data/lib/bundler/constants.rb +7 -0
- data/lib/bundler/current_ruby.rb +94 -0
- data/lib/bundler/definition.rb +995 -0
- data/lib/bundler/dep_proxy.rb +48 -0
- data/lib/bundler/dependency.rb +139 -0
- data/lib/bundler/deployment.rb +69 -0
- data/lib/bundler/deprecate.rb +44 -0
- data/lib/bundler/dsl.rb +615 -0
- data/lib/bundler/endpoint_specification.rb +141 -0
- data/lib/bundler/env.rb +149 -0
- data/lib/bundler/environment_preserver.rb +59 -0
- data/lib/bundler/errors.rb +158 -0
- data/lib/bundler/feature_flag.rb +75 -0
- data/lib/bundler/fetcher.rb +312 -0
- data/lib/bundler/fetcher/base.rb +52 -0
- data/lib/bundler/fetcher/compact_index.rb +126 -0
- data/lib/bundler/fetcher/dependency.rb +82 -0
- data/lib/bundler/fetcher/downloader.rb +84 -0
- data/lib/bundler/fetcher/index.rb +52 -0
- data/lib/bundler/friendly_errors.rb +131 -0
- data/lib/bundler/gem_helper.rb +217 -0
- data/lib/bundler/gem_helpers.rb +101 -0
- data/lib/bundler/gem_remote_fetcher.rb +43 -0
- data/lib/bundler/gem_tasks.rb +7 -0
- data/lib/bundler/gem_version_promoter.rb +190 -0
- data/lib/bundler/gemdeps.rb +29 -0
- data/lib/bundler/graph.rb +152 -0
- data/lib/bundler/index.rb +213 -0
- data/lib/bundler/injector.rb +253 -0
- data/lib/bundler/inline.rb +74 -0
- data/lib/bundler/installer.rb +318 -0
- data/lib/bundler/installer/gem_installer.rb +85 -0
- data/lib/bundler/installer/parallel_installer.rb +229 -0
- data/lib/bundler/installer/standalone.rb +53 -0
- data/lib/bundler/lazy_specification.rb +123 -0
- data/lib/bundler/lockfile_generator.rb +95 -0
- data/lib/bundler/lockfile_parser.rb +256 -0
- data/lib/bundler/match_platform.rb +24 -0
- data/lib/bundler/mirror.rb +223 -0
- data/lib/bundler/plugin.rb +294 -0
- data/lib/bundler/plugin/api.rb +81 -0
- data/lib/bundler/plugin/api/source.rb +306 -0
- data/lib/bundler/plugin/dsl.rb +53 -0
- data/lib/bundler/plugin/events.rb +61 -0
- data/lib/bundler/plugin/index.rb +165 -0
- data/lib/bundler/plugin/installer.rb +96 -0
- data/lib/bundler/plugin/installer/git.rb +38 -0
- data/lib/bundler/plugin/installer/rubygems.rb +27 -0
- data/lib/bundler/plugin/source_list.rb +27 -0
- data/lib/bundler/process_lock.rb +24 -0
- data/lib/bundler/psyched_yaml.rb +37 -0
- data/lib/bundler/remote_specification.rb +114 -0
- data/lib/bundler/resolver.rb +373 -0
- data/lib/bundler/resolver/spec_group.rb +106 -0
- data/lib/bundler/retry.rb +66 -0
- data/lib/bundler/ruby_dsl.rb +18 -0
- data/lib/bundler/ruby_version.rb +152 -0
- data/lib/bundler/rubygems_ext.rb +209 -0
- data/lib/bundler/rubygems_gem_installer.rb +99 -0
- data/lib/bundler/rubygems_integration.rb +915 -0
- data/lib/bundler/runtime.rb +322 -0
- data/lib/bundler/settings.rb +464 -0
- data/lib/bundler/settings/validator.rb +102 -0
- data/lib/bundler/setup.rb +28 -0
- data/lib/bundler/shared_helpers.rb +386 -0
- data/lib/bundler/similarity_detector.rb +63 -0
- data/lib/bundler/source.rb +94 -0
- data/lib/bundler/source/gemspec.rb +18 -0
- data/lib/bundler/source/git.rb +329 -0
- data/lib/bundler/source/git/git_proxy.rb +262 -0
- data/lib/bundler/source/metadata.rb +62 -0
- data/lib/bundler/source/path.rb +249 -0
- data/lib/bundler/source/path/installer.rb +74 -0
- data/lib/bundler/source/rubygems.rb +539 -0
- data/lib/bundler/source/rubygems/remote.rb +69 -0
- data/lib/bundler/source_list.rb +186 -0
- data/lib/bundler/spec_set.rb +208 -0
- data/lib/bundler/ssl_certs/.document +1 -0
- data/lib/bundler/ssl_certs/certificate_manager.rb +66 -0
- data/lib/bundler/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem +21 -0
- data/lib/bundler/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem +23 -0
- data/lib/bundler/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem +25 -0
- data/lib/bundler/stub_specification.rb +108 -0
- data/lib/bundler/templates/.document +1 -0
- data/lib/bundler/templates/Executable +29 -0
- data/lib/bundler/templates/Executable.bundler +105 -0
- data/lib/bundler/templates/Executable.standalone +14 -0
- data/lib/bundler/templates/Gemfile +7 -0
- data/lib/bundler/templates/gems.rb +8 -0
- data/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +74 -0
- data/lib/bundler/templates/newgem/Gemfile.tt +4 -0
- data/lib/bundler/templates/newgem/LICENSE.txt.tt +21 -0
- data/lib/bundler/templates/newgem/README.md.tt +47 -0
- data/lib/bundler/templates/newgem/Rakefile.tt +29 -0
- data/lib/bundler/templates/newgem/bin/console.tt +14 -0
- data/lib/bundler/templates/newgem/bin/setup.tt +8 -0
- data/lib/bundler/templates/newgem/exe/newgem.tt +3 -0
- data/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt +3 -0
- data/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt +9 -0
- data/lib/bundler/templates/newgem/ext/newgem/newgem.h.tt +6 -0
- data/lib/bundler/templates/newgem/gitignore.tt +20 -0
- data/lib/bundler/templates/newgem/lib/newgem.rb.tt +13 -0
- data/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +7 -0
- data/lib/bundler/templates/newgem/newgem.gemspec.tt +50 -0
- data/lib/bundler/templates/newgem/rspec.tt +3 -0
- data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +9 -0
- data/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +14 -0
- data/lib/bundler/templates/newgem/test/newgem_test.rb.tt +11 -0
- data/lib/bundler/templates/newgem/test/test_helper.rb.tt +8 -0
- data/lib/bundler/templates/newgem/travis.yml.tt +7 -0
- data/lib/bundler/ui.rb +9 -0
- data/lib/bundler/ui/rg_proxy.rb +19 -0
- data/lib/bundler/ui/shell.rb +146 -0
- data/lib/bundler/ui/silent.rb +69 -0
- data/lib/bundler/uri_credentials_filter.rb +37 -0
- data/lib/bundler/vendor/fileutils/lib/fileutils.rb +1741 -0
- data/lib/bundler/vendor/fileutils/lib/fileutils/version.rb +5 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo.rb +12 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb +26 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb +57 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb +81 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +223 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb +36 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb +66 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb +62 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb +63 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb +61 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb +126 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb +46 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb +36 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +136 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +143 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +6 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +101 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb +67 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +837 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +46 -0
- data/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +58 -0
- data/lib/bundler/vendor/net-http-persistent/lib/net/http/faster.rb +27 -0
- data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +1233 -0
- data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/ssl_reuse.rb +129 -0
- data/lib/bundler/vendor/thor/lib/thor.rb +509 -0
- data/lib/bundler/vendor/thor/lib/thor/actions.rb +331 -0
- data/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +104 -0
- data/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +60 -0
- data/lib/bundler/vendor/thor/lib/thor/actions/directory.rb +118 -0
- data/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +143 -0
- data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +373 -0
- data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +109 -0
- data/lib/bundler/vendor/thor/lib/thor/base.rb +678 -0
- data/lib/bundler/vendor/thor/lib/thor/command.rb +135 -0
- data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +97 -0
- data/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb +12 -0
- data/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb +129 -0
- data/lib/bundler/vendor/thor/lib/thor/error.rb +114 -0
- data/lib/bundler/vendor/thor/lib/thor/group.rb +281 -0
- data/lib/bundler/vendor/thor/lib/thor/invocation.rb +177 -0
- data/lib/bundler/vendor/thor/lib/thor/line_editor.rb +17 -0
- data/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb +37 -0
- data/lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb +88 -0
- data/lib/bundler/vendor/thor/lib/thor/parser.rb +4 -0
- data/lib/bundler/vendor/thor/lib/thor/parser/argument.rb +70 -0
- data/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +175 -0
- data/lib/bundler/vendor/thor/lib/thor/parser/option.rb +146 -0
- data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +226 -0
- data/lib/bundler/vendor/thor/lib/thor/rake_compat.rb +71 -0
- data/lib/bundler/vendor/thor/lib/thor/runner.rb +324 -0
- data/lib/bundler/vendor/thor/lib/thor/shell.rb +81 -0
- data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +482 -0
- data/lib/bundler/vendor/thor/lib/thor/shell/color.rb +149 -0
- data/lib/bundler/vendor/thor/lib/thor/shell/html.rb +126 -0
- data/lib/bundler/vendor/thor/lib/thor/util.rb +268 -0
- data/lib/bundler/vendor/thor/lib/thor/version.rb +3 -0
- data/lib/bundler/vendored_fileutils.rb +9 -0
- data/lib/bundler/vendored_molinillo.rb +4 -0
- data/lib/bundler/vendored_persistent.rb +52 -0
- data/lib/bundler/vendored_thor.rb +8 -0
- data/lib/bundler/version.rb +28 -0
- data/lib/bundler/version_ranges.rb +76 -0
- data/lib/bundler/vlad.rb +17 -0
- data/lib/bundler/worker.rb +106 -0
- data/lib/bundler/yaml_serializer.rb +90 -0
- data/man/bundle-add.1 +58 -0
- data/man/bundle-add.1.txt +52 -0
- data/man/bundle-add.ronn +40 -0
- data/man/bundle-binstubs.1 +40 -0
- data/man/bundle-binstubs.1.txt +48 -0
- data/man/bundle-binstubs.ronn +43 -0
- data/man/bundle-check.1 +31 -0
- data/man/bundle-check.1.txt +33 -0
- data/man/bundle-check.ronn +26 -0
- data/man/bundle-clean.1 +24 -0
- data/man/bundle-clean.1.txt +26 -0
- data/man/bundle-clean.ronn +18 -0
- data/man/bundle-config.1 +497 -0
- data/man/bundle-config.1.txt +529 -0
- data/man/bundle-config.ronn +397 -0
- 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 +165 -0
- data/man/bundle-exec.1.txt +178 -0
- data/man/bundle-exec.ronn +152 -0
- data/man/bundle-gem.1 +80 -0
- data/man/bundle-gem.1.txt +91 -0
- data/man/bundle-gem.ronn +78 -0
- data/man/bundle-info.1 +20 -0
- data/man/bundle-info.1.txt +21 -0
- data/man/bundle-info.ronn +17 -0
- data/man/bundle-init.1 +25 -0
- data/man/bundle-init.1.txt +34 -0
- data/man/bundle-init.ronn +29 -0
- data/man/bundle-inject.1 +33 -0
- data/man/bundle-inject.1.txt +32 -0
- data/man/bundle-inject.ronn +22 -0
- data/man/bundle-install.1 +308 -0
- data/man/bundle-install.1.txt +396 -0
- data/man/bundle-install.ronn +378 -0
- 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 +84 -0
- data/man/bundle-lock.1.txt +93 -0
- data/man/bundle-lock.ronn +94 -0
- data/man/bundle-open.1 +32 -0
- data/man/bundle-open.1.txt +29 -0
- data/man/bundle-open.ronn +19 -0
- data/man/bundle-outdated.1 +155 -0
- data/man/bundle-outdated.1.txt +131 -0
- data/man/bundle-outdated.ronn +111 -0
- data/man/bundle-package.1 +55 -0
- data/man/bundle-package.1.txt +79 -0
- data/man/bundle-package.ronn +72 -0
- data/man/bundle-platform.1 +61 -0
- data/man/bundle-platform.1.txt +57 -0
- data/man/bundle-platform.ronn +42 -0
- data/man/bundle-pristine.1 +34 -0
- data/man/bundle-pristine.1.txt +44 -0
- data/man/bundle-pristine.ronn +34 -0
- 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 +23 -0
- data/man/bundle-show.1.txt +27 -0
- data/man/bundle-show.ronn +21 -0
- data/man/bundle-update.1 +394 -0
- data/man/bundle-update.1.txt +391 -0
- data/man/bundle-update.ronn +350 -0
- data/man/bundle-viz.1 +39 -0
- data/man/bundle-viz.1.txt +39 -0
- data/man/bundle-viz.ronn +30 -0
- data/man/bundle.1 +136 -0
- data/man/bundle.1.txt +116 -0
- data/man/bundle.ronn +111 -0
- data/man/gemfile.5 +689 -0
- data/man/gemfile.5.ronn +521 -0
- data/man/gemfile.5.txt +653 -0
- data/man/index.txt +25 -0
- metadata +463 -0
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rubygems/installer"
|
4
|
+
|
5
|
+
module Bundler
|
6
|
+
class RubyGemsGemInstaller < Gem::Installer
|
7
|
+
unless respond_to?(:at)
|
8
|
+
def self.at(*args)
|
9
|
+
new(*args)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def check_executable_overwrite(filename)
|
14
|
+
# Bundler needs to install gems regardless of binstub overwriting
|
15
|
+
end
|
16
|
+
|
17
|
+
def pre_install_checks
|
18
|
+
super && validate_bundler_checksum(options[:bundler_expected_checksum])
|
19
|
+
end
|
20
|
+
|
21
|
+
def build_extensions
|
22
|
+
extension_cache_path = options[:bundler_extension_cache_path]
|
23
|
+
return super unless extension_cache_path && extension_dir = Bundler.rubygems.spec_extension_dir(spec)
|
24
|
+
|
25
|
+
extension_dir = Pathname.new(extension_dir)
|
26
|
+
build_complete = SharedHelpers.filesystem_access(extension_cache_path.join("gem.build_complete"), :read, &:file?)
|
27
|
+
if build_complete && !options[:force]
|
28
|
+
SharedHelpers.filesystem_access(extension_dir.parent, &:mkpath)
|
29
|
+
SharedHelpers.filesystem_access(extension_cache_path) do
|
30
|
+
FileUtils.cp_r extension_cache_path, spec.extension_dir
|
31
|
+
end
|
32
|
+
else
|
33
|
+
super
|
34
|
+
if extension_dir.directory? # not made for gems without extensions
|
35
|
+
SharedHelpers.filesystem_access(extension_cache_path.parent, &:mkpath)
|
36
|
+
SharedHelpers.filesystem_access(extension_cache_path) do
|
37
|
+
FileUtils.cp_r extension_dir, extension_cache_path
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def validate_bundler_checksum(checksum)
|
46
|
+
return true if Bundler.settings[:disable_checksum_validation]
|
47
|
+
return true unless checksum
|
48
|
+
return true unless source = @package.instance_variable_get(:@gem)
|
49
|
+
return true unless source.respond_to?(:with_read_io)
|
50
|
+
digest = source.with_read_io do |io|
|
51
|
+
digest = SharedHelpers.digest(:SHA256).new
|
52
|
+
digest << io.read(16_384) until io.eof?
|
53
|
+
io.rewind
|
54
|
+
send(checksum_type(checksum), digest)
|
55
|
+
end
|
56
|
+
unless digest == checksum
|
57
|
+
raise SecurityError, <<-MESSAGE
|
58
|
+
Bundler cannot continue installing #{spec.name} (#{spec.version}).
|
59
|
+
The checksum for the downloaded `#{spec.full_name}.gem` does not match \
|
60
|
+
the checksum given by the server. This means the contents of the downloaded \
|
61
|
+
gem is different from what was uploaded to the server, and could be a potential security issue.
|
62
|
+
|
63
|
+
To resolve this issue:
|
64
|
+
1. delete the downloaded gem located at: `#{spec.gem_dir}/#{spec.full_name}.gem`
|
65
|
+
2. run `bundle install`
|
66
|
+
|
67
|
+
If you wish to continue installing the downloaded gem, and are certain it does not pose a \
|
68
|
+
security issue despite the mismatching checksum, do the following:
|
69
|
+
1. run `bundle config disable_checksum_validation true` to turn off checksum verification
|
70
|
+
2. run `bundle install`
|
71
|
+
|
72
|
+
(More info: The expected SHA256 checksum was #{checksum.inspect}, but the \
|
73
|
+
checksum for the downloaded gem was #{digest.inspect}.)
|
74
|
+
MESSAGE
|
75
|
+
end
|
76
|
+
true
|
77
|
+
end
|
78
|
+
|
79
|
+
def checksum_type(checksum)
|
80
|
+
case checksum.length
|
81
|
+
when 64 then :hexdigest!
|
82
|
+
when 44 then :base64digest!
|
83
|
+
else raise InstallError, "The given checksum for #{spec.full_name} (#{checksum.inspect}) is not a valid SHA256 hexdigest nor base64digest"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def hexdigest!(digest)
|
88
|
+
digest.hexdigest!
|
89
|
+
end
|
90
|
+
|
91
|
+
def base64digest!(digest)
|
92
|
+
if digest.respond_to?(:base64digest!)
|
93
|
+
digest.base64digest!
|
94
|
+
else
|
95
|
+
[digest.digest!].pack("m0")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,915 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "monitor"
|
4
|
+
|
5
|
+
module Bundler
|
6
|
+
class RubygemsIntegration
|
7
|
+
if defined?(Gem::Ext::Builder::CHDIR_MONITOR)
|
8
|
+
EXT_LOCK = Gem::Ext::Builder::CHDIR_MONITOR
|
9
|
+
else
|
10
|
+
EXT_LOCK = Monitor.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.version
|
14
|
+
@version ||= Gem::Version.new(Gem::VERSION)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.provides?(req_str)
|
18
|
+
Gem::Requirement.new(req_str).satisfied_by?(version)
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@replaced_methods = {}
|
23
|
+
end
|
24
|
+
|
25
|
+
def version
|
26
|
+
self.class.version
|
27
|
+
end
|
28
|
+
|
29
|
+
def provides?(req_str)
|
30
|
+
self.class.provides?(req_str)
|
31
|
+
end
|
32
|
+
|
33
|
+
def build_args
|
34
|
+
Gem::Command.build_args
|
35
|
+
end
|
36
|
+
|
37
|
+
def build_args=(args)
|
38
|
+
Gem::Command.build_args = args
|
39
|
+
end
|
40
|
+
|
41
|
+
def load_path_insert_index
|
42
|
+
Gem.load_path_insert_index
|
43
|
+
end
|
44
|
+
|
45
|
+
def loaded_specs(name)
|
46
|
+
Gem.loaded_specs[name]
|
47
|
+
end
|
48
|
+
|
49
|
+
def mark_loaded(spec)
|
50
|
+
if spec.respond_to?(:activated=)
|
51
|
+
current = Gem.loaded_specs[spec.name]
|
52
|
+
current.activated = false if current
|
53
|
+
spec.activated = true
|
54
|
+
end
|
55
|
+
Gem.loaded_specs[spec.name] = spec
|
56
|
+
end
|
57
|
+
|
58
|
+
def validate(spec)
|
59
|
+
Bundler.ui.silence { spec.validate(false) }
|
60
|
+
rescue Gem::InvalidSpecificationException => e
|
61
|
+
error_message = "The gemspec at #{spec.loaded_from} is not valid. Please fix this gemspec.\n" \
|
62
|
+
"The validation error was '#{e.message}'\n"
|
63
|
+
raise Gem::InvalidSpecificationException.new(error_message)
|
64
|
+
rescue Errno::ENOENT
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
|
68
|
+
def set_installed_by_version(spec, installed_by_version = Gem::VERSION)
|
69
|
+
return unless spec.respond_to?(:installed_by_version=)
|
70
|
+
spec.installed_by_version = Gem::Version.create(installed_by_version)
|
71
|
+
end
|
72
|
+
|
73
|
+
def spec_missing_extensions?(spec, default = true)
|
74
|
+
return spec.missing_extensions? if spec.respond_to?(:missing_extensions?)
|
75
|
+
|
76
|
+
return false if spec_default_gem?(spec)
|
77
|
+
return false if spec.extensions.empty?
|
78
|
+
|
79
|
+
default
|
80
|
+
end
|
81
|
+
|
82
|
+
def spec_default_gem?(spec)
|
83
|
+
spec.respond_to?(:default_gem?) && spec.default_gem?
|
84
|
+
end
|
85
|
+
|
86
|
+
def spec_matches_for_glob(spec, glob)
|
87
|
+
return spec.matches_for_glob(glob) if spec.respond_to?(:matches_for_glob)
|
88
|
+
|
89
|
+
spec.load_paths.map do |lp|
|
90
|
+
Dir["#{lp}/#{glob}#{suffix_pattern}"]
|
91
|
+
end.flatten(1)
|
92
|
+
end
|
93
|
+
|
94
|
+
def spec_extension_dir(spec)
|
95
|
+
return unless spec.respond_to?(:extension_dir)
|
96
|
+
spec.extension_dir
|
97
|
+
end
|
98
|
+
|
99
|
+
def stub_set_spec(stub, spec)
|
100
|
+
stub.instance_variable_set(:@spec, spec)
|
101
|
+
end
|
102
|
+
|
103
|
+
def path(obj)
|
104
|
+
obj.to_s
|
105
|
+
end
|
106
|
+
|
107
|
+
def platforms
|
108
|
+
return [Gem::Platform::RUBY] if Bundler.settings[:force_ruby_platform]
|
109
|
+
Gem.platforms
|
110
|
+
end
|
111
|
+
|
112
|
+
def configuration
|
113
|
+
require "bundler/psyched_yaml"
|
114
|
+
Gem.configuration
|
115
|
+
rescue Gem::SystemExitException, LoadError => e
|
116
|
+
Bundler.ui.error "#{e.class}: #{e.message}"
|
117
|
+
Bundler.ui.trace e
|
118
|
+
raise
|
119
|
+
rescue YamlLibrarySyntaxError => e
|
120
|
+
raise YamlSyntaxError.new(e, "Your RubyGems configuration, which is " \
|
121
|
+
"usually located in ~/.gemrc, contains invalid YAML syntax.")
|
122
|
+
end
|
123
|
+
|
124
|
+
def ruby_engine
|
125
|
+
Gem.ruby_engine
|
126
|
+
end
|
127
|
+
|
128
|
+
def read_binary(path)
|
129
|
+
Gem.read_binary(path)
|
130
|
+
end
|
131
|
+
|
132
|
+
def inflate(obj)
|
133
|
+
if defined?(Gem::Util)
|
134
|
+
Gem::Util.inflate(obj)
|
135
|
+
else
|
136
|
+
Gem.inflate(obj)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def sources=(val)
|
141
|
+
# Gem.configuration creates a new Gem::ConfigFile, which by default will read ~/.gemrc
|
142
|
+
# If that file exists, its settings (including sources) will overwrite the values we
|
143
|
+
# are about to set here. In order to avoid that, we force memoizing the config file now.
|
144
|
+
configuration
|
145
|
+
|
146
|
+
Gem.sources = val
|
147
|
+
end
|
148
|
+
|
149
|
+
def sources
|
150
|
+
Gem.sources
|
151
|
+
end
|
152
|
+
|
153
|
+
def gem_dir
|
154
|
+
Gem.dir
|
155
|
+
end
|
156
|
+
|
157
|
+
def gem_bindir
|
158
|
+
Gem.bindir
|
159
|
+
end
|
160
|
+
|
161
|
+
def user_home
|
162
|
+
Gem.user_home
|
163
|
+
end
|
164
|
+
|
165
|
+
def gem_path
|
166
|
+
Gem.path
|
167
|
+
end
|
168
|
+
|
169
|
+
def reset
|
170
|
+
Gem::Specification.reset
|
171
|
+
end
|
172
|
+
|
173
|
+
def post_reset_hooks
|
174
|
+
Gem.post_reset_hooks
|
175
|
+
end
|
176
|
+
|
177
|
+
def suffix_pattern
|
178
|
+
Gem.suffix_pattern
|
179
|
+
end
|
180
|
+
|
181
|
+
def gem_cache
|
182
|
+
gem_path.map {|p| File.expand_path("cache", p) }
|
183
|
+
end
|
184
|
+
|
185
|
+
def spec_cache_dirs
|
186
|
+
@spec_cache_dirs ||= begin
|
187
|
+
dirs = gem_path.map {|dir| File.join(dir, "specifications") }
|
188
|
+
dirs << Gem.spec_cache_dir if Gem.respond_to?(:spec_cache_dir) # Not in RubyGems 2.0.3 or earlier
|
189
|
+
dirs.uniq.select {|dir| File.directory? dir }
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def marshal_spec_dir
|
194
|
+
Gem::MARSHAL_SPEC_DIR
|
195
|
+
end
|
196
|
+
|
197
|
+
def config_map
|
198
|
+
Gem::ConfigMap
|
199
|
+
end
|
200
|
+
|
201
|
+
def repository_subdirectories
|
202
|
+
%w[cache doc gems specifications]
|
203
|
+
end
|
204
|
+
|
205
|
+
def clear_paths
|
206
|
+
Gem.clear_paths
|
207
|
+
end
|
208
|
+
|
209
|
+
def bin_path(gem, bin, ver)
|
210
|
+
Gem.bin_path(gem, bin, ver)
|
211
|
+
end
|
212
|
+
|
213
|
+
def path_separator
|
214
|
+
File::PATH_SEPARATOR
|
215
|
+
end
|
216
|
+
|
217
|
+
def preserve_paths
|
218
|
+
# this is a no-op outside of RubyGems 1.8
|
219
|
+
yield
|
220
|
+
end
|
221
|
+
|
222
|
+
def loaded_gem_paths
|
223
|
+
# RubyGems 2.2+ can put binary extension into dedicated folders,
|
224
|
+
# therefore use RubyGems facilities to obtain their load paths.
|
225
|
+
if Gem::Specification.method_defined? :full_require_paths
|
226
|
+
loaded_gem_paths = Gem.loaded_specs.map {|_, s| s.full_require_paths }
|
227
|
+
loaded_gem_paths.flatten
|
228
|
+
else
|
229
|
+
$LOAD_PATH.select do |p|
|
230
|
+
Bundler.rubygems.gem_path.any? {|gp| p =~ /^#{Regexp.escape(gp)}/ }
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def load_plugins
|
236
|
+
Gem.load_plugins if Gem.respond_to?(:load_plugins)
|
237
|
+
end
|
238
|
+
|
239
|
+
def load_plugin_files(files)
|
240
|
+
Gem.load_plugin_files(files) if Gem.respond_to?(:load_plugin_files)
|
241
|
+
end
|
242
|
+
|
243
|
+
def ui=(obj)
|
244
|
+
Gem::DefaultUserInteraction.ui = obj
|
245
|
+
end
|
246
|
+
|
247
|
+
def ext_lock
|
248
|
+
EXT_LOCK
|
249
|
+
end
|
250
|
+
|
251
|
+
def fetch_specs(all, pre, &blk)
|
252
|
+
require "rubygems/spec_fetcher"
|
253
|
+
specs = Gem::SpecFetcher.new.list(all, pre)
|
254
|
+
specs.each { yield } if block_given?
|
255
|
+
specs
|
256
|
+
end
|
257
|
+
|
258
|
+
def fetch_prerelease_specs
|
259
|
+
fetch_specs(false, true)
|
260
|
+
rescue Gem::RemoteFetcher::FetchError
|
261
|
+
{} # if we can't download them, there aren't any
|
262
|
+
end
|
263
|
+
|
264
|
+
# TODO: This is for older versions of RubyGems... should we support the
|
265
|
+
# X-Gemfile-Source header on these old versions?
|
266
|
+
# Maybe the newer implementation will work on older RubyGems?
|
267
|
+
# It seems difficult to keep this implementation and still send the header.
|
268
|
+
def fetch_all_remote_specs(remote)
|
269
|
+
old_sources = Bundler.rubygems.sources
|
270
|
+
Bundler.rubygems.sources = [remote.uri.to_s]
|
271
|
+
# Fetch all specs, minus prerelease specs
|
272
|
+
spec_list = fetch_specs(true, false)
|
273
|
+
# Then fetch the prerelease specs
|
274
|
+
fetch_prerelease_specs.each {|k, v| spec_list[k].concat(v) }
|
275
|
+
|
276
|
+
spec_list.values.first
|
277
|
+
ensure
|
278
|
+
Bundler.rubygems.sources = old_sources
|
279
|
+
end
|
280
|
+
|
281
|
+
def with_build_args(args)
|
282
|
+
ext_lock.synchronize do
|
283
|
+
old_args = build_args
|
284
|
+
begin
|
285
|
+
self.build_args = args
|
286
|
+
yield
|
287
|
+
ensure
|
288
|
+
self.build_args = old_args
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def install_with_build_args(args)
|
294
|
+
with_build_args(args) { yield }
|
295
|
+
end
|
296
|
+
|
297
|
+
def gem_from_path(path, policy = nil)
|
298
|
+
require "rubygems/format"
|
299
|
+
Gem::Format.from_file_by_path(path, policy)
|
300
|
+
end
|
301
|
+
|
302
|
+
def spec_from_gem(path, policy = nil)
|
303
|
+
require "rubygems/security"
|
304
|
+
require "bundler/psyched_yaml"
|
305
|
+
gem_from_path(path, security_policies[policy]).spec
|
306
|
+
rescue Gem::Package::FormatError
|
307
|
+
raise GemspecError, "Could not read gem at #{path}. It may be corrupted."
|
308
|
+
rescue Exception, Gem::Exception, Gem::Security::Exception => e
|
309
|
+
if e.is_a?(Gem::Security::Exception) ||
|
310
|
+
e.message =~ /unknown trust policy|unsigned gem/i ||
|
311
|
+
e.message =~ /couldn't verify (meta)?data signature/i
|
312
|
+
raise SecurityError,
|
313
|
+
"The gem #{File.basename(path, ".gem")} can't be installed because " \
|
314
|
+
"the security policy didn't allow it, with the message: #{e.message}"
|
315
|
+
else
|
316
|
+
raise e
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
def build(spec, skip_validation = false)
|
321
|
+
require "rubygems/builder"
|
322
|
+
Gem::Builder.new(spec).build
|
323
|
+
end
|
324
|
+
|
325
|
+
def build_gem(gem_dir, spec)
|
326
|
+
build(spec)
|
327
|
+
end
|
328
|
+
|
329
|
+
def download_gem(spec, uri, path)
|
330
|
+
uri = Bundler.settings.mirror_for(uri)
|
331
|
+
fetcher = Gem::RemoteFetcher.new(configuration[:http_proxy])
|
332
|
+
Bundler::Retry.new("download gem from #{uri}").attempts do
|
333
|
+
fetcher.download(spec, uri, path)
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
def security_policy_keys
|
338
|
+
%w[High Medium Low AlmostNo No].map {|level| "#{level}Security" }
|
339
|
+
end
|
340
|
+
|
341
|
+
def security_policies
|
342
|
+
@security_policies ||= begin
|
343
|
+
require "rubygems/security"
|
344
|
+
Gem::Security::Policies
|
345
|
+
rescue LoadError, NameError
|
346
|
+
{}
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
def reverse_rubygems_kernel_mixin
|
351
|
+
# Disable rubygems' gem activation system
|
352
|
+
kernel = (class << ::Kernel; self; end)
|
353
|
+
[kernel, ::Kernel].each do |k|
|
354
|
+
if k.private_method_defined?(:gem_original_require)
|
355
|
+
redefine_method(k, :require, k.instance_method(:gem_original_require))
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
def binstubs_call_gem?
|
361
|
+
true
|
362
|
+
end
|
363
|
+
|
364
|
+
def stubs_provide_full_functionality?
|
365
|
+
false
|
366
|
+
end
|
367
|
+
|
368
|
+
def replace_gem(specs, specs_by_name)
|
369
|
+
reverse_rubygems_kernel_mixin
|
370
|
+
|
371
|
+
executables = nil
|
372
|
+
|
373
|
+
kernel = (class << ::Kernel; self; end)
|
374
|
+
[kernel, ::Kernel].each do |kernel_class|
|
375
|
+
redefine_method(kernel_class, :gem) do |dep, *reqs|
|
376
|
+
executables ||= specs.map(&:executables).flatten if ::Bundler.rubygems.binstubs_call_gem?
|
377
|
+
if executables && executables.include?(File.basename(caller.first.split(":").first))
|
378
|
+
break
|
379
|
+
end
|
380
|
+
|
381
|
+
reqs.pop if reqs.last.is_a?(Hash)
|
382
|
+
|
383
|
+
unless dep.respond_to?(:name) && dep.respond_to?(:requirement)
|
384
|
+
dep = Gem::Dependency.new(dep, reqs)
|
385
|
+
end
|
386
|
+
|
387
|
+
if spec = specs_by_name[dep.name]
|
388
|
+
return true if dep.matches_spec?(spec)
|
389
|
+
end
|
390
|
+
|
391
|
+
message = if spec.nil?
|
392
|
+
"#{dep.name} is not part of the bundle." \
|
393
|
+
" Add it to your #{Bundler.default_gemfile.basename}."
|
394
|
+
else
|
395
|
+
"can't activate #{dep}, already activated #{spec.full_name}. " \
|
396
|
+
"Make sure all dependencies are added to Gemfile."
|
397
|
+
end
|
398
|
+
|
399
|
+
e = Gem::LoadError.new(message)
|
400
|
+
e.name = dep.name
|
401
|
+
if e.respond_to?(:requirement=)
|
402
|
+
e.requirement = dep.requirement
|
403
|
+
elsif e.respond_to?(:version_requirement=)
|
404
|
+
e.version_requirement = dep.requirement
|
405
|
+
end
|
406
|
+
raise e
|
407
|
+
end
|
408
|
+
|
409
|
+
# backwards compatibility shim, see https://github.com/bundler/bundler/issues/5102
|
410
|
+
kernel_class.send(:public, :gem) if Bundler.feature_flag.setup_makes_kernel_gem_public?
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
def stub_source_index(specs)
|
415
|
+
Gem::SourceIndex.send(:alias_method, :old_initialize, :initialize)
|
416
|
+
redefine_method(Gem::SourceIndex, :initialize) do |*args|
|
417
|
+
@gems = {}
|
418
|
+
# You're looking at this thinking: Oh! This is how I make those
|
419
|
+
# rubygems deprecations go away!
|
420
|
+
#
|
421
|
+
# You'd be correct BUT using of this method in production code
|
422
|
+
# must be approved by the rubygems team itself!
|
423
|
+
#
|
424
|
+
# This is your warning. If you use this and don't have approval
|
425
|
+
# we can't protect you.
|
426
|
+
#
|
427
|
+
Deprecate.skip_during do
|
428
|
+
self.spec_dirs = *args
|
429
|
+
add_specs(*specs)
|
430
|
+
end
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
# Used to make bin stubs that are not created by bundler work
|
435
|
+
# under bundler. The new Gem.bin_path only considers gems in
|
436
|
+
# +specs+
|
437
|
+
def replace_bin_path(specs, specs_by_name)
|
438
|
+
gem_class = (class << Gem; self; end)
|
439
|
+
|
440
|
+
redefine_method(gem_class, :find_spec_for_exe) do |gem_name, *args|
|
441
|
+
exec_name = args.first
|
442
|
+
|
443
|
+
spec_with_name = specs_by_name[gem_name]
|
444
|
+
spec = if exec_name
|
445
|
+
if spec_with_name && spec_with_name.executables.include?(exec_name)
|
446
|
+
spec_with_name
|
447
|
+
else
|
448
|
+
specs.find {|s| s.executables.include?(exec_name) }
|
449
|
+
end
|
450
|
+
else
|
451
|
+
spec_with_name
|
452
|
+
end
|
453
|
+
|
454
|
+
unless spec
|
455
|
+
message = "can't find executable #{exec_name} for gem #{gem_name}"
|
456
|
+
if !exec_name || spec_with_name.nil?
|
457
|
+
message += ". #{gem_name} is not currently included in the bundle, " \
|
458
|
+
"perhaps you meant to add it to your #{Bundler.default_gemfile.basename}?"
|
459
|
+
end
|
460
|
+
raise Gem::Exception, message
|
461
|
+
end
|
462
|
+
|
463
|
+
raise Gem::Exception, "no default executable for #{spec.full_name}" unless exec_name ||= spec.default_executable
|
464
|
+
|
465
|
+
unless spec.name == gem_name
|
466
|
+
Bundler::SharedHelpers.major_deprecation 3,
|
467
|
+
"Bundler is using a binstub that was created for a different gem (#{spec.name}).\n" \
|
468
|
+
"You should run `bundle binstub #{gem_name}` " \
|
469
|
+
"to work around a system/bundle conflict."
|
470
|
+
end
|
471
|
+
spec
|
472
|
+
end
|
473
|
+
|
474
|
+
redefine_method(gem_class, :activate_bin_path) do |name, *args|
|
475
|
+
exec_name = args.first
|
476
|
+
return ENV["BUNDLE_BIN_PATH"] if exec_name == "bundle"
|
477
|
+
|
478
|
+
# Copy of Rubygems activate_bin_path impl
|
479
|
+
requirement = args.last
|
480
|
+
spec = find_spec_for_exe name, exec_name, [requirement]
|
481
|
+
|
482
|
+
gem_bin = File.join(spec.full_gem_path, spec.bindir, exec_name)
|
483
|
+
gem_from_path_bin = File.join(File.dirname(spec.loaded_from), spec.bindir, exec_name)
|
484
|
+
File.exist?(gem_bin) ? gem_bin : gem_from_path_bin
|
485
|
+
end
|
486
|
+
|
487
|
+
redefine_method(gem_class, :bin_path) do |name, *args|
|
488
|
+
exec_name = args.first
|
489
|
+
return ENV["BUNDLE_BIN_PATH"] if exec_name == "bundle"
|
490
|
+
|
491
|
+
spec = find_spec_for_exe(name, *args)
|
492
|
+
exec_name ||= spec.default_executable
|
493
|
+
|
494
|
+
gem_bin = File.join(spec.full_gem_path, spec.bindir, exec_name)
|
495
|
+
gem_from_path_bin = File.join(File.dirname(spec.loaded_from), spec.bindir, exec_name)
|
496
|
+
File.exist?(gem_bin) ? gem_bin : gem_from_path_bin
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
# Because Bundler has a static view of what specs are available,
|
501
|
+
# we don't #refresh, so stub it out.
|
502
|
+
def replace_refresh
|
503
|
+
gem_class = (class << Gem; self; end)
|
504
|
+
redefine_method(gem_class, :refresh) {}
|
505
|
+
end
|
506
|
+
|
507
|
+
# Replace or hook into RubyGems to provide a bundlerized view
|
508
|
+
# of the world.
|
509
|
+
def replace_entrypoints(specs)
|
510
|
+
specs_by_name = specs.reduce({}) do |h, s|
|
511
|
+
h[s.name] = s
|
512
|
+
h
|
513
|
+
end
|
514
|
+
|
515
|
+
Bundler.rubygems.default_stubs.each do |stub|
|
516
|
+
default_spec = stub.to_spec
|
517
|
+
default_spec_name = default_spec.name
|
518
|
+
next if specs_by_name.key?(default_spec_name)
|
519
|
+
|
520
|
+
specs << default_spec
|
521
|
+
specs_by_name[default_spec_name] = default_spec
|
522
|
+
end
|
523
|
+
|
524
|
+
replace_gem(specs, specs_by_name)
|
525
|
+
stub_rubygems(specs)
|
526
|
+
replace_bin_path(specs, specs_by_name)
|
527
|
+
replace_refresh
|
528
|
+
|
529
|
+
Gem.clear_paths
|
530
|
+
end
|
531
|
+
|
532
|
+
# This backports the correct segment generation code from RubyGems 1.4+
|
533
|
+
# by monkeypatching it into the method in RubyGems 1.3.6 and 1.3.7.
|
534
|
+
def backport_segment_generation
|
535
|
+
redefine_method(Gem::Version, :segments) do
|
536
|
+
@segments ||= @version.scan(/[0-9]+|[a-z]+/i).map do |s|
|
537
|
+
/^\d+$/ =~ s ? s.to_i : s
|
538
|
+
end
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
542
|
+
# This backport fixes the marshaling of @segments.
|
543
|
+
def backport_yaml_initialize
|
544
|
+
redefine_method(Gem::Version, :yaml_initialize) do |_, map|
|
545
|
+
@version = map["version"]
|
546
|
+
@segments = nil
|
547
|
+
@hash = nil
|
548
|
+
end
|
549
|
+
end
|
550
|
+
|
551
|
+
# This backports base_dir which replaces installation path
|
552
|
+
# RubyGems 1.8+
|
553
|
+
def backport_base_dir
|
554
|
+
redefine_method(Gem::Specification, :base_dir) do
|
555
|
+
return Gem.dir unless loaded_from
|
556
|
+
File.dirname File.dirname loaded_from
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
560
|
+
def backport_cache_file
|
561
|
+
redefine_method(Gem::Specification, :cache_dir) do
|
562
|
+
@cache_dir ||= File.join base_dir, "cache"
|
563
|
+
end
|
564
|
+
|
565
|
+
redefine_method(Gem::Specification, :cache_file) do
|
566
|
+
@cache_file ||= File.join cache_dir, "#{full_name}.gem"
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
def backport_spec_file
|
571
|
+
redefine_method(Gem::Specification, :spec_dir) do
|
572
|
+
@spec_dir ||= File.join base_dir, "specifications"
|
573
|
+
end
|
574
|
+
|
575
|
+
redefine_method(Gem::Specification, :spec_file) do
|
576
|
+
@spec_file ||= File.join spec_dir, "#{full_name}.gemspec"
|
577
|
+
end
|
578
|
+
end
|
579
|
+
|
580
|
+
def undo_replacements
|
581
|
+
@replaced_methods.each do |(sym, klass), method|
|
582
|
+
redefine_method(klass, sym, method)
|
583
|
+
end
|
584
|
+
if Binding.public_method_defined?(:source_location)
|
585
|
+
post_reset_hooks.reject! {|proc| proc.binding.source_location[0] == __FILE__ }
|
586
|
+
else
|
587
|
+
post_reset_hooks.reject! {|proc| proc.binding.eval("__FILE__") == __FILE__ }
|
588
|
+
end
|
589
|
+
@replaced_methods.clear
|
590
|
+
end
|
591
|
+
|
592
|
+
def redefine_method(klass, method, unbound_method = nil, &block)
|
593
|
+
visibility = method_visibility(klass, method)
|
594
|
+
begin
|
595
|
+
if (instance_method = klass.instance_method(method)) && method != :initialize
|
596
|
+
# doing this to ensure we also get private methods
|
597
|
+
klass.send(:remove_method, method)
|
598
|
+
end
|
599
|
+
rescue NameError
|
600
|
+
# method isn't defined
|
601
|
+
nil
|
602
|
+
end
|
603
|
+
@replaced_methods[[method, klass]] = instance_method
|
604
|
+
if unbound_method
|
605
|
+
klass.send(:define_method, method, unbound_method)
|
606
|
+
klass.send(visibility, method)
|
607
|
+
elsif block
|
608
|
+
klass.send(:define_method, method, &block)
|
609
|
+
klass.send(visibility, method)
|
610
|
+
end
|
611
|
+
end
|
612
|
+
|
613
|
+
def method_visibility(klass, method)
|
614
|
+
if klass.private_method_defined?(method)
|
615
|
+
:private
|
616
|
+
elsif klass.protected_method_defined?(method)
|
617
|
+
:protected
|
618
|
+
else
|
619
|
+
:public
|
620
|
+
end
|
621
|
+
end
|
622
|
+
|
623
|
+
# RubyGems 1.4 through 1.6
|
624
|
+
class Legacy < RubygemsIntegration
|
625
|
+
def initialize
|
626
|
+
super
|
627
|
+
backport_base_dir
|
628
|
+
backport_cache_file
|
629
|
+
backport_spec_file
|
630
|
+
backport_yaml_initialize
|
631
|
+
end
|
632
|
+
|
633
|
+
def stub_rubygems(specs)
|
634
|
+
# RubyGems versions lower than 1.7 use SourceIndex#from_gems_in
|
635
|
+
source_index_class = (class << Gem::SourceIndex; self; end)
|
636
|
+
redefine_method(source_index_class, :from_gems_in) do |*args|
|
637
|
+
Gem::SourceIndex.new.tap do |source_index|
|
638
|
+
source_index.spec_dirs = *args
|
639
|
+
source_index.add_specs(*specs)
|
640
|
+
end
|
641
|
+
end
|
642
|
+
end
|
643
|
+
|
644
|
+
def all_specs
|
645
|
+
Gem.source_index.gems.values
|
646
|
+
end
|
647
|
+
|
648
|
+
def find_name(name)
|
649
|
+
Gem.source_index.find_name(name)
|
650
|
+
end
|
651
|
+
|
652
|
+
def validate(spec)
|
653
|
+
# These versions of RubyGems always validate in "packaging" mode,
|
654
|
+
# which is too strict for the kinds of checks we care about. As a
|
655
|
+
# result, validation is disabled on versions of RubyGems below 1.7.
|
656
|
+
end
|
657
|
+
|
658
|
+
def post_reset_hooks
|
659
|
+
[]
|
660
|
+
end
|
661
|
+
|
662
|
+
def reset
|
663
|
+
end
|
664
|
+
end
|
665
|
+
|
666
|
+
# RubyGems versions 1.3.6 and 1.3.7
|
667
|
+
class Ancient < Legacy
|
668
|
+
def initialize
|
669
|
+
super
|
670
|
+
backport_segment_generation
|
671
|
+
end
|
672
|
+
end
|
673
|
+
|
674
|
+
# RubyGems 1.7
|
675
|
+
class Transitional < Legacy
|
676
|
+
def stub_rubygems(specs)
|
677
|
+
stub_source_index(specs)
|
678
|
+
end
|
679
|
+
|
680
|
+
def validate(spec)
|
681
|
+
# Missing summary is downgraded to a warning in later versions,
|
682
|
+
# so we set it to an empty string to prevent an exception here.
|
683
|
+
spec.summary ||= ""
|
684
|
+
RubygemsIntegration.instance_method(:validate).bind(self).call(spec)
|
685
|
+
end
|
686
|
+
end
|
687
|
+
|
688
|
+
# RubyGems 1.8.5-1.8.19
|
689
|
+
class Modern < RubygemsIntegration
|
690
|
+
def stub_rubygems(specs)
|
691
|
+
Gem::Specification.all = specs
|
692
|
+
|
693
|
+
Gem.post_reset do
|
694
|
+
Gem::Specification.all = specs
|
695
|
+
end
|
696
|
+
|
697
|
+
stub_source_index(specs)
|
698
|
+
end
|
699
|
+
|
700
|
+
def all_specs
|
701
|
+
Gem::Specification.to_a
|
702
|
+
end
|
703
|
+
|
704
|
+
def find_name(name)
|
705
|
+
Gem::Specification.find_all_by_name name
|
706
|
+
end
|
707
|
+
end
|
708
|
+
|
709
|
+
# RubyGems 1.8.0 to 1.8.4
|
710
|
+
class AlmostModern < Modern
|
711
|
+
# RubyGems [>= 1.8.0, < 1.8.5] has a bug that changes Gem.dir whenever
|
712
|
+
# you call Gem::Installer#install with an :install_dir set. We have to
|
713
|
+
# change it back for our sudo mode to work.
|
714
|
+
def preserve_paths
|
715
|
+
old_dir = gem_dir
|
716
|
+
old_path = gem_path
|
717
|
+
yield
|
718
|
+
Gem.use_paths(old_dir, old_path)
|
719
|
+
end
|
720
|
+
end
|
721
|
+
|
722
|
+
# RubyGems 1.8.20+
|
723
|
+
class MoreModern < Modern
|
724
|
+
# RubyGems 1.8.20 and adds the skip_validation parameter, so that's
|
725
|
+
# when we start passing it through.
|
726
|
+
def build(spec, skip_validation = false)
|
727
|
+
require "rubygems/builder"
|
728
|
+
Gem::Builder.new(spec).build(skip_validation)
|
729
|
+
end
|
730
|
+
end
|
731
|
+
|
732
|
+
# RubyGems 2.0
|
733
|
+
class Future < RubygemsIntegration
|
734
|
+
def stub_rubygems(specs)
|
735
|
+
Gem::Specification.all = specs
|
736
|
+
|
737
|
+
Gem.post_reset do
|
738
|
+
Gem::Specification.all = specs
|
739
|
+
end
|
740
|
+
|
741
|
+
redefine_method((class << Gem; self; end), :finish_resolve) do |*|
|
742
|
+
[]
|
743
|
+
end
|
744
|
+
end
|
745
|
+
|
746
|
+
def all_specs
|
747
|
+
Gem::Specification.to_a
|
748
|
+
end
|
749
|
+
|
750
|
+
def find_name(name)
|
751
|
+
Gem::Specification.find_all_by_name name
|
752
|
+
end
|
753
|
+
|
754
|
+
def fetch_specs(source, remote, name)
|
755
|
+
path = source + "#{name}.#{Gem.marshal_version}.gz"
|
756
|
+
fetcher = gem_remote_fetcher
|
757
|
+
fetcher.headers = { "X-Gemfile-Source" => remote.original_uri.to_s } if remote.original_uri
|
758
|
+
string = fetcher.fetch_path(path)
|
759
|
+
Bundler.load_marshal(string)
|
760
|
+
rescue Gem::RemoteFetcher::FetchError => e
|
761
|
+
# it's okay for prerelease to fail
|
762
|
+
raise e unless name == "prerelease_specs"
|
763
|
+
end
|
764
|
+
|
765
|
+
def fetch_all_remote_specs(remote)
|
766
|
+
source = remote.uri.is_a?(URI) ? remote.uri : URI.parse(source.to_s)
|
767
|
+
|
768
|
+
specs = fetch_specs(source, remote, "specs")
|
769
|
+
pres = fetch_specs(source, remote, "prerelease_specs") || []
|
770
|
+
|
771
|
+
specs.concat(pres)
|
772
|
+
end
|
773
|
+
|
774
|
+
def download_gem(spec, uri, path)
|
775
|
+
uri = Bundler.settings.mirror_for(uri)
|
776
|
+
fetcher = gem_remote_fetcher
|
777
|
+
fetcher.headers = { "X-Gemfile-Source" => spec.remote.original_uri.to_s } if spec.remote.original_uri
|
778
|
+
Bundler::Retry.new("download gem from #{uri}").attempts do
|
779
|
+
fetcher.download(spec, uri, path)
|
780
|
+
end
|
781
|
+
end
|
782
|
+
|
783
|
+
def gem_remote_fetcher
|
784
|
+
require "resolv"
|
785
|
+
proxy = configuration[:http_proxy]
|
786
|
+
dns = Resolv::DNS.new
|
787
|
+
Bundler::GemRemoteFetcher.new(proxy, dns)
|
788
|
+
end
|
789
|
+
|
790
|
+
def gem_from_path(path, policy = nil)
|
791
|
+
require "rubygems/package"
|
792
|
+
p = Gem::Package.new(path)
|
793
|
+
p.security_policy = policy if policy
|
794
|
+
p
|
795
|
+
end
|
796
|
+
|
797
|
+
def build(spec, skip_validation = false)
|
798
|
+
require "rubygems/package"
|
799
|
+
Gem::Package.build(spec, skip_validation)
|
800
|
+
end
|
801
|
+
|
802
|
+
def repository_subdirectories
|
803
|
+
Gem::REPOSITORY_SUBDIRECTORIES
|
804
|
+
end
|
805
|
+
|
806
|
+
def install_with_build_args(args)
|
807
|
+
yield
|
808
|
+
end
|
809
|
+
|
810
|
+
def path_separator
|
811
|
+
Gem.path_separator
|
812
|
+
end
|
813
|
+
end
|
814
|
+
|
815
|
+
# RubyGems 2.1.0
|
816
|
+
class MoreFuture < Future
|
817
|
+
def initialize
|
818
|
+
super
|
819
|
+
backport_ext_builder_monitor
|
820
|
+
end
|
821
|
+
|
822
|
+
def all_specs
|
823
|
+
require "bundler/remote_specification"
|
824
|
+
Gem::Specification.stubs.map do |stub|
|
825
|
+
StubSpecification.from_stub(stub)
|
826
|
+
end
|
827
|
+
end
|
828
|
+
|
829
|
+
def backport_ext_builder_monitor
|
830
|
+
# So we can avoid requiring "rubygems/ext" in its entirety
|
831
|
+
Gem.module_eval <<-RB, __FILE__, __LINE__ + 1
|
832
|
+
module Ext
|
833
|
+
end
|
834
|
+
RB
|
835
|
+
|
836
|
+
require "rubygems/ext/builder"
|
837
|
+
|
838
|
+
Gem::Ext::Builder.class_eval do
|
839
|
+
unless const_defined?(:CHDIR_MONITOR)
|
840
|
+
const_set(:CHDIR_MONITOR, EXT_LOCK)
|
841
|
+
end
|
842
|
+
|
843
|
+
remove_const(:CHDIR_MUTEX) if const_defined?(:CHDIR_MUTEX)
|
844
|
+
const_set(:CHDIR_MUTEX, const_get(:CHDIR_MONITOR))
|
845
|
+
end
|
846
|
+
end
|
847
|
+
|
848
|
+
if Gem::Specification.respond_to?(:stubs_for)
|
849
|
+
def find_name(name)
|
850
|
+
Gem::Specification.stubs_for(name).map(&:to_spec)
|
851
|
+
end
|
852
|
+
else
|
853
|
+
def find_name(name)
|
854
|
+
Gem::Specification.stubs.find_all do |spec|
|
855
|
+
spec.name == name
|
856
|
+
end.map(&:to_spec)
|
857
|
+
end
|
858
|
+
end
|
859
|
+
|
860
|
+
if Gem::Specification.respond_to?(:default_stubs)
|
861
|
+
def default_stubs
|
862
|
+
Gem::Specification.default_stubs("*.gemspec")
|
863
|
+
end
|
864
|
+
else
|
865
|
+
def default_stubs
|
866
|
+
Gem::Specification.send(:default_stubs, "*.gemspec")
|
867
|
+
end
|
868
|
+
end
|
869
|
+
|
870
|
+
def use_gemdeps(gemfile)
|
871
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path(gemfile)
|
872
|
+
require "bundler/gemdeps"
|
873
|
+
runtime = Bundler.setup
|
874
|
+
Bundler.ui = nil
|
875
|
+
activated_spec_names = runtime.requested_specs.map(&:to_spec).sort_by(&:name)
|
876
|
+
[Gemdeps.new(runtime), activated_spec_names]
|
877
|
+
end
|
878
|
+
|
879
|
+
if provides?(">= 2.5.2")
|
880
|
+
# RubyGems-generated binstubs call Kernel#gem
|
881
|
+
def binstubs_call_gem?
|
882
|
+
false
|
883
|
+
end
|
884
|
+
|
885
|
+
# only 2.5.2+ has all of the stub methods we want to use, and since this
|
886
|
+
# is a performance optimization _only_,
|
887
|
+
# we'll restrict ourselves to the most
|
888
|
+
# recent RG versions instead of all versions that have stubs
|
889
|
+
def stubs_provide_full_functionality?
|
890
|
+
true
|
891
|
+
end
|
892
|
+
end
|
893
|
+
end
|
894
|
+
end
|
895
|
+
|
896
|
+
def self.rubygems
|
897
|
+
@rubygems ||= if RubygemsIntegration.provides?(">= 2.1.0")
|
898
|
+
RubygemsIntegration::MoreFuture.new
|
899
|
+
elsif RubygemsIntegration.provides?(">= 1.99.99")
|
900
|
+
RubygemsIntegration::Future.new
|
901
|
+
elsif RubygemsIntegration.provides?(">= 1.8.20")
|
902
|
+
RubygemsIntegration::MoreModern.new
|
903
|
+
elsif RubygemsIntegration.provides?(">= 1.8.5")
|
904
|
+
RubygemsIntegration::Modern.new
|
905
|
+
elsif RubygemsIntegration.provides?(">= 1.8.0")
|
906
|
+
RubygemsIntegration::AlmostModern.new
|
907
|
+
elsif RubygemsIntegration.provides?(">= 1.7.0")
|
908
|
+
RubygemsIntegration::Transitional.new
|
909
|
+
elsif RubygemsIntegration.provides?(">= 1.4.0")
|
910
|
+
RubygemsIntegration::Legacy.new
|
911
|
+
else # RubyGems 1.3.6 and 1.3.7
|
912
|
+
RubygemsIntegration::Ancient.new
|
913
|
+
end
|
914
|
+
end
|
915
|
+
end
|