bundler 1.9.0 → 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 +1157 -6
- data/README.md +33 -6
- data/bundler.gemspec +51 -18
- data/exe/bundle +31 -0
- data/{bin → exe}/bundle_ruby +10 -6
- data/exe/bundler +4 -0
- data/lib/bundler.rb +326 -207
- data/lib/bundler/build_metadata.rb +53 -0
- data/lib/bundler/capistrano.rb +9 -3
- data/lib/bundler/cli.rb +522 -141
- data/lib/bundler/cli/add.rb +35 -0
- data/lib/bundler/cli/binstubs.rb +22 -11
- data/lib/bundler/cli/cache.rb +7 -6
- data/lib/bundler/cli/check.rb +11 -8
- data/lib/bundler/cli/clean.rb +7 -8
- data/lib/bundler/cli/common.rb +53 -7
- data/lib/bundler/cli/config.rb +84 -49
- data/lib/bundler/cli/console.rb +13 -8
- data/lib/bundler/cli/doctor.rb +140 -0
- data/lib/bundler/cli/exec.rb +77 -16
- data/lib/bundler/cli/gem.rb +120 -52
- data/lib/bundler/cli/info.rb +50 -0
- data/lib/bundler/cli/init.rb +21 -7
- data/lib/bundler/cli/inject.rb +37 -10
- data/lib/bundler/cli/install.rb +139 -78
- 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 +9 -6
- data/lib/bundler/cli/outdated.rb +221 -35
- data/lib/bundler/cli/package.rb +11 -7
- data/lib/bundler/cli/platform.rb +7 -4
- 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 +11 -10
- data/lib/bundler/cli/update.rb +47 -29
- data/lib/bundler/cli/viz.rb +12 -8
- 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 +14 -0
- data/lib/bundler/constants.rb +3 -1
- data/lib/bundler/current_ruby.rb +47 -137
- data/lib/bundler/definition.rb +599 -230
- data/lib/bundler/dep_proxy.rb +15 -10
- data/lib/bundler/dependency.rb +54 -25
- data/lib/bundler/deployment.rb +12 -2
- data/lib/bundler/deprecate.rb +33 -4
- data/lib/bundler/dsl.rb +383 -99
- data/lib/bundler/endpoint_specification.rb +72 -7
- data/lib/bundler/env.rb +121 -41
- data/lib/bundler/environment_preserver.rb +59 -0
- data/lib/bundler/errors.rb +158 -0
- data/lib/bundler/feature_flag.rb +74 -0
- data/lib/bundler/fetcher.rb +171 -280
- 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 +113 -58
- data/lib/bundler/gem_helper.rb +73 -46
- data/lib/bundler/gem_helpers.rb +85 -9
- data/lib/bundler/gem_remote_fetcher.rb +43 -0
- data/lib/bundler/gem_tasks.rb +6 -1
- data/lib/bundler/gem_version_promoter.rb +190 -0
- data/lib/bundler/gemdeps.rb +29 -0
- data/lib/bundler/graph.rb +32 -49
- data/lib/bundler/index.rb +79 -67
- data/lib/bundler/injector.rb +219 -30
- data/lib/bundler/inline.rb +74 -0
- data/lib/bundler/installer.rb +191 -206
- data/lib/bundler/installer/gem_installer.rb +85 -0
- data/lib/bundler/installer/parallel_installer.rb +233 -0
- data/lib/bundler/installer/standalone.rb +53 -0
- data/lib/bundler/lazy_specification.rb +53 -13
- data/lib/bundler/lockfile_generator.rb +95 -0
- data/lib/bundler/lockfile_parser.rb +157 -62
- data/lib/bundler/match_platform.rb +15 -4
- data/lib/bundler/mirror.rb +223 -0
- data/lib/bundler/plugin.rb +292 -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 +162 -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 +17 -6
- data/lib/bundler/remote_specification.rb +68 -11
- data/lib/bundler/resolver.rb +263 -229
- data/lib/bundler/resolver/spec_group.rb +106 -0
- data/lib/bundler/retry.rb +25 -19
- data/lib/bundler/ruby_dsl.rb +9 -2
- data/lib/bundler/ruby_version.rb +101 -66
- data/lib/bundler/rubygems_ext.rb +77 -37
- data/lib/bundler/rubygems_gem_installer.rb +106 -0
- data/lib/bundler/rubygems_integration.rb +450 -163
- data/lib/bundler/runtime.rb +133 -103
- data/lib/bundler/settings.rb +344 -83
- data/lib/bundler/settings/validator.rb +102 -0
- data/lib/bundler/setup.rb +7 -3
- data/lib/bundler/shared_helpers.rb +284 -54
- data/lib/bundler/similarity_detector.rb +21 -21
- data/lib/bundler/source.rb +68 -15
- data/lib/bundler/source/gemspec.rb +18 -0
- data/lib/bundler/source/git.rb +90 -55
- data/lib/bundler/source/git/git_proxy.rb +135 -35
- data/lib/bundler/source/metadata.rb +62 -0
- data/lib/bundler/source/path.rb +84 -61
- data/lib/bundler/source/path/installer.rb +53 -17
- data/lib/bundler/source/rubygems.rb +282 -122
- data/lib/bundler/source/rubygems/remote.rb +69 -0
- data/lib/bundler/source_list.rb +107 -22
- data/lib/bundler/spec_set.rb +83 -45
- data/lib/bundler/ssl_certs/certificate_manager.rb +8 -7
- data/lib/bundler/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem +21 -0
- data/lib/bundler/ssl_certs/{DigiCertHighAssuranceEVRootCA.pem → rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem} +0 -0
- data/lib/bundler/ssl_certs/{AddTrustExternalCARoot-2048.pem → rubygems.org/AddTrustExternalCARoot.pem} +0 -0
- data/lib/bundler/stub_specification.rb +108 -0
- data/lib/bundler/templates/.document +1 -0
- data/lib/bundler/templates/Executable +19 -6
- data/lib/bundler/templates/Executable.bundler +105 -0
- data/lib/bundler/templates/Executable.standalone +6 -4
- data/lib/bundler/templates/Gemfile +4 -1
- data/lib/bundler/templates/gems.rb +8 -0
- data/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +68 -7
- data/lib/bundler/templates/newgem/Gemfile.tt +4 -2
- data/lib/bundler/templates/newgem/LICENSE.txt.tt +1 -1
- data/lib/bundler/templates/newgem/README.md.tt +19 -11
- data/lib/bundler/templates/newgem/Rakefile.tt +10 -6
- data/lib/bundler/templates/newgem/bin/console.tt +1 -1
- data/lib/bundler/templates/newgem/bin/setup.tt +2 -1
- data/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt +4 -4
- data/lib/bundler/templates/newgem/ext/newgem/newgem.h.tt +3 -3
- data/lib/bundler/templates/newgem/gitignore.tt +5 -1
- data/lib/bundler/templates/newgem/lib/newgem.rb.tt +7 -6
- data/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +4 -4
- data/lib/bundler/templates/newgem/newgem.gemspec.tt +31 -15
- data/lib/bundler/templates/newgem/rspec.tt +1 -0
- data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +3 -5
- data/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +14 -2
- data/lib/bundler/templates/newgem/test/{test_newgem.rb.tt → newgem_test.rb.tt} +2 -2
- data/lib/bundler/templates/newgem/test/test_helper.rb.tt +4 -0
- data/lib/bundler/templates/newgem/travis.yml.tt +7 -0
- data/lib/bundler/ui.rb +5 -3
- data/lib/bundler/ui/rg_proxy.rb +5 -7
- data/lib/bundler/ui/shell.rb +69 -18
- data/lib/bundler/ui/silent.rb +26 -1
- data/lib/bundler/uri_credentials_filter.rb +37 -0
- data/lib/bundler/vendor/fileutils/lib/fileutils.rb +1638 -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-0.2.1 → molinillo}/lib/molinillo/modules/specification_provider.rb +11 -0
- data/lib/bundler/vendor/{Molinillo-0.2.1 → molinillo}/lib/molinillo/modules/ui.rb +6 -2
- data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +837 -0
- data/lib/bundler/vendor/{Molinillo-0.2.1 → molinillo}/lib/molinillo/resolver.rb +6 -3
- data/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +58 -0
- data/lib/bundler/vendor/{net → net-http-persistent/lib/net}/http/faster.rb +1 -0
- data/lib/bundler/vendor/{net → net-http-persistent/lib/net}/http/persistent.rb +27 -24
- data/lib/bundler/vendor/{net → net-http-persistent/lib/net}/http/persistent/ssl_reuse.rb +2 -1
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor.rb +47 -22
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/actions.rb +31 -29
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/actions/create_file.rb +3 -2
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/actions/create_link.rb +3 -2
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/actions/directory.rb +3 -3
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/actions/empty_directory.rb +16 -8
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/actions/file_manipulation.rb +66 -18
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/actions/inject_into_file.rb +18 -16
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/base.rb +67 -44
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/command.rb +13 -11
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/core_ext/hash_with_indifferent_access.rb +21 -1
- 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-0.19.1 → thor}/lib/thor/error.rb +3 -3
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/group.rb +14 -14
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/invocation.rb +4 -5
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/line_editor.rb +2 -2
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/line_editor/basic.rb +2 -0
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/line_editor/readline.rb +0 -0
- data/lib/bundler/vendor/thor/lib/thor/parser.rb +4 -0
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/parser/argument.rb +4 -7
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/parser/arguments.rb +16 -16
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/parser/option.rb +42 -21
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/parser/options.rb +13 -10
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/rake_compat.rb +1 -1
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/runner.rb +35 -33
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/shell.rb +4 -4
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/shell/basic.rb +49 -33
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/shell/color.rb +2 -2
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/shell/html.rb +5 -5
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/util.rb +8 -7
- data/lib/bundler/vendor/{thor-0.19.1 → thor}/lib/thor/version.rb +1 -1
- data/lib/bundler/vendored_fileutils.rb +9 -0
- data/lib/bundler/vendored_molinillo.rb +4 -5
- data/lib/bundler/vendored_persistent.rb +45 -4
- data/lib/bundler/vendored_thor.rb +8 -5
- data/lib/bundler/version.rb +23 -1
- data/lib/bundler/version_ranges.rb +76 -0
- data/lib/bundler/vlad.rb +8 -2
- data/lib/bundler/worker.rb +39 -6
- 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 +256 -31
- 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 +19 -3
- 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 +64 -67
- 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 +14 -8
- data/man/bundle-platform.1 +61 -0
- data/man/bundle-platform.1.txt +57 -0
- data/man/bundle-platform.ronn +1 -1
- 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 +180 -18
- 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 +46 -33
- data/man/gemfile.5 +689 -0
- data/man/gemfile.5.ronn +127 -79
- data/man/gemfile.5.txt +653 -0
- data/man/index.txt +25 -7
- metadata +242 -95
- data/.gitignore +0 -16
- data/.rspec +0 -3
- data/.travis.yml +0 -110
- data/CODE_OF_CONDUCT.md +0 -40
- data/CONTRIBUTING.md +0 -32
- data/DEVELOPMENT.md +0 -119
- data/ISSUES.md +0 -96
- data/Rakefile +0 -302
- data/UPGRADING.md +0 -103
- data/bin/bundle +0 -21
- data/bin/bundler +0 -21
- data/lib/bundler/anonymizable_uri.rb +0 -32
- data/lib/bundler/environment.rb +0 -42
- data/lib/bundler/gem_installer.rb +0 -9
- data/lib/bundler/gem_path_manipulation.rb +0 -8
- data/lib/bundler/ssl_certs/AddTrustExternalCARoot.pem +0 -32
- data/lib/bundler/ssl_certs/Class3PublicPrimaryCertificationAuthority.pem +0 -14
- data/lib/bundler/ssl_certs/EntrustnetSecureServerCertificationAuthority.pem +0 -28
- data/lib/bundler/ssl_certs/GeoTrustGlobalCA.pem +0 -20
- data/lib/bundler/templates/newgem/.travis.yml.tt +0 -3
- data/lib/bundler/templates/newgem/test/minitest_helper.rb.tt +0 -4
- data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo.rb +0 -5
- data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/dependency_graph.rb +0 -266
- data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/errors.rb +0 -69
- data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/gem_metadata.rb +0 -3
- data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/resolution.rb +0 -412
- data/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/state.rb +0 -43
- data/lib/bundler/vendor/thor-0.19.1/lib/thor/core_ext/io_binary_read.rb +0 -10
- data/lib/bundler/vendor/thor-0.19.1/lib/thor/core_ext/ordered_hash.rb +0 -98
- data/lib/bundler/vendor/thor-0.19.1/lib/thor/parser.rb +0 -4
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bundler
|
4
|
+
class LockfileGenerator
|
5
|
+
attr_reader :definition
|
6
|
+
attr_reader :out
|
7
|
+
|
8
|
+
# @private
|
9
|
+
def initialize(definition)
|
10
|
+
@definition = definition
|
11
|
+
@out = String.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.generate(definition)
|
15
|
+
new(definition).generate!
|
16
|
+
end
|
17
|
+
|
18
|
+
def generate!
|
19
|
+
add_sources
|
20
|
+
add_platforms
|
21
|
+
add_dependencies
|
22
|
+
add_locked_ruby_version
|
23
|
+
add_bundled_with
|
24
|
+
|
25
|
+
out
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def add_sources
|
31
|
+
definition.send(:sources).lock_sources.each_with_index do |source, idx|
|
32
|
+
out << "\n" unless idx.zero?
|
33
|
+
|
34
|
+
# Add the source header
|
35
|
+
out << source.to_lock
|
36
|
+
|
37
|
+
# Find all specs for this source
|
38
|
+
specs = definition.resolve.select {|s| source.can_lock?(s) }
|
39
|
+
add_specs(specs)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def add_specs(specs)
|
44
|
+
# This needs to be sorted by full name so that
|
45
|
+
# gems with the same name, but different platform
|
46
|
+
# are ordered consistently
|
47
|
+
specs.sort_by(&:full_name).each do |spec|
|
48
|
+
next if spec.name == "bundler".freeze
|
49
|
+
out << spec.to_lock
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_platforms
|
54
|
+
add_section("PLATFORMS", definition.platforms)
|
55
|
+
end
|
56
|
+
|
57
|
+
def add_dependencies
|
58
|
+
out << "\nDEPENDENCIES\n"
|
59
|
+
|
60
|
+
handled = []
|
61
|
+
definition.dependencies.sort_by(&:to_s).each do |dep|
|
62
|
+
next if handled.include?(dep.name)
|
63
|
+
out << dep.to_lock
|
64
|
+
handled << dep.name
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def add_locked_ruby_version
|
69
|
+
return unless locked_ruby_version = definition.locked_ruby_version
|
70
|
+
add_section("RUBY VERSION", locked_ruby_version.to_s)
|
71
|
+
end
|
72
|
+
|
73
|
+
def add_bundled_with
|
74
|
+
add_section("BUNDLED WITH", definition.locked_bundler_version.to_s)
|
75
|
+
end
|
76
|
+
|
77
|
+
def add_section(name, value)
|
78
|
+
out << "\n#{name}\n"
|
79
|
+
case value
|
80
|
+
when Array
|
81
|
+
value.map(&:to_s).sort.each do |val|
|
82
|
+
out << " #{val}\n"
|
83
|
+
end
|
84
|
+
when Hash
|
85
|
+
value.to_a.sort_by {|k, _| k.to_s }.each do |key, val|
|
86
|
+
out << " #{key}: #{val}\n"
|
87
|
+
end
|
88
|
+
when String
|
89
|
+
out << " #{value}\n"
|
90
|
+
else
|
91
|
+
raise ArgumentError, "#{value.inspect} can't be serialized in a lockfile"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Some versions of the Bundler 1.1 RC series introduced corrupted
|
4
4
|
# lockfiles. There were two major problems:
|
@@ -12,60 +12,121 @@ require "strscan"
|
|
12
12
|
|
13
13
|
module Bundler
|
14
14
|
class LockfileParser
|
15
|
-
attr_reader :sources, :dependencies, :specs, :platforms
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
15
|
+
attr_reader :sources, :dependencies, :specs, :platforms, :bundler_version, :ruby_version
|
16
|
+
|
17
|
+
BUNDLED = "BUNDLED WITH".freeze
|
18
|
+
DEPENDENCIES = "DEPENDENCIES".freeze
|
19
|
+
PLATFORMS = "PLATFORMS".freeze
|
20
|
+
RUBY = "RUBY VERSION".freeze
|
21
|
+
GIT = "GIT".freeze
|
22
|
+
GEM = "GEM".freeze
|
23
|
+
PATH = "PATH".freeze
|
24
|
+
PLUGIN = "PLUGIN SOURCE".freeze
|
25
|
+
SPECS = " specs:".freeze
|
23
26
|
OPTIONS = /^ ([a-z]+): (.*)$/i
|
27
|
+
SOURCE = [GIT, GEM, PATH, PLUGIN].freeze
|
28
|
+
|
29
|
+
SECTIONS_BY_VERSION_INTRODUCED = {
|
30
|
+
# The strings have to be dup'ed for old RG on Ruby 2.3+
|
31
|
+
# TODO: remove dup in Bundler 2.0
|
32
|
+
Gem::Version.create("1.0".dup) => [DEPENDENCIES, PLATFORMS, GIT, GEM, PATH].freeze,
|
33
|
+
Gem::Version.create("1.10".dup) => [BUNDLED].freeze,
|
34
|
+
Gem::Version.create("1.12".dup) => [RUBY].freeze,
|
35
|
+
Gem::Version.create("1.13".dup) => [PLUGIN].freeze,
|
36
|
+
}.freeze
|
37
|
+
|
38
|
+
KNOWN_SECTIONS = SECTIONS_BY_VERSION_INTRODUCED.values.flatten.freeze
|
39
|
+
|
40
|
+
ENVIRONMENT_VERSION_SECTIONS = [BUNDLED, RUBY].freeze
|
41
|
+
|
42
|
+
def self.sections_in_lockfile(lockfile_contents)
|
43
|
+
lockfile_contents.scan(/^\w[\w ]*$/).uniq
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.unknown_sections_in_lockfile(lockfile_contents)
|
47
|
+
sections_in_lockfile(lockfile_contents) - KNOWN_SECTIONS
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.sections_to_ignore(base_version = nil)
|
51
|
+
base_version &&= base_version.release
|
52
|
+
base_version ||= Gem::Version.create("1.0".dup)
|
53
|
+
attributes = []
|
54
|
+
SECTIONS_BY_VERSION_INTRODUCED.each do |version, introduced|
|
55
|
+
next if version <= base_version
|
56
|
+
attributes += introduced
|
57
|
+
end
|
58
|
+
attributes
|
59
|
+
end
|
24
60
|
|
25
61
|
def initialize(lockfile)
|
26
62
|
@platforms = []
|
27
63
|
@sources = []
|
28
|
-
@dependencies =
|
29
|
-
@state =
|
64
|
+
@dependencies = {}
|
65
|
+
@state = nil
|
30
66
|
@specs = {}
|
31
67
|
|
32
68
|
@rubygems_aggregate = Source::Rubygems.new
|
33
69
|
|
34
70
|
if lockfile.match(/<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|/)
|
35
|
-
raise LockfileError, "Your
|
36
|
-
"Run `git checkout HEAD --
|
71
|
+
raise LockfileError, "Your #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} contains merge conflicts.\n" \
|
72
|
+
"Run `git checkout HEAD -- #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}` first to get a clean lock."
|
37
73
|
end
|
38
74
|
|
39
75
|
lockfile.split(/(?:\r?\n)+/).each do |line|
|
40
|
-
if line
|
76
|
+
if SOURCE.include?(line)
|
77
|
+
@state = :source
|
78
|
+
parse_source(line)
|
79
|
+
elsif line == DEPENDENCIES
|
41
80
|
@state = :dependency
|
42
81
|
elsif line == PLATFORMS
|
43
82
|
@state = :platform
|
44
|
-
|
83
|
+
elsif line == RUBY
|
84
|
+
@state = :ruby
|
85
|
+
elsif line == BUNDLED
|
86
|
+
@state = :bundled_with
|
87
|
+
elsif line =~ /^[^\s]/
|
88
|
+
@state = nil
|
89
|
+
elsif @state
|
45
90
|
send("parse_#{@state}", line)
|
46
91
|
end
|
47
92
|
end
|
48
|
-
@sources << @rubygems_aggregate
|
49
|
-
@specs = @specs.values
|
93
|
+
@sources << @rubygems_aggregate unless Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
|
94
|
+
@specs = @specs.values.sort_by(&:identifier)
|
95
|
+
warn_for_outdated_bundler_version
|
50
96
|
rescue ArgumentError => e
|
51
97
|
Bundler.ui.debug(e)
|
52
|
-
raise LockfileError, "Your lockfile is unreadable. Run `rm
|
98
|
+
raise LockfileError, "Your lockfile is unreadable. Run `rm #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}` " \
|
53
99
|
"and then `bundle install` to generate a new lockfile."
|
54
100
|
end
|
55
101
|
|
102
|
+
def warn_for_outdated_bundler_version
|
103
|
+
return unless bundler_version
|
104
|
+
prerelease_text = bundler_version.prerelease? ? " --pre" : ""
|
105
|
+
current_version = Gem::Version.create(Bundler::VERSION)
|
106
|
+
case current_version.segments.first <=> bundler_version.segments.first
|
107
|
+
when -1
|
108
|
+
raise LockfileError, "You must use Bundler #{bundler_version.segments.first} or greater with this lockfile."
|
109
|
+
when 0
|
110
|
+
if current_version < bundler_version
|
111
|
+
Bundler.ui.warn "Warning: the running version of Bundler (#{current_version}) is older " \
|
112
|
+
"than the version that created the lockfile (#{bundler_version}). We suggest you " \
|
113
|
+
"upgrade to the latest version of Bundler by running `gem " \
|
114
|
+
"install bundler#{prerelease_text}`.\n"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
56
119
|
private
|
57
120
|
|
58
121
|
TYPES = {
|
59
|
-
GIT
|
60
|
-
GEM
|
61
|
-
PATH
|
62
|
-
|
122
|
+
GIT => Bundler::Source::Git,
|
123
|
+
GEM => Bundler::Source::Rubygems,
|
124
|
+
PATH => Bundler::Source::Path,
|
125
|
+
PLUGIN => Bundler::Plugin,
|
126
|
+
}.freeze
|
63
127
|
|
64
128
|
def parse_source(line)
|
65
129
|
case line
|
66
|
-
when GIT, GEM, PATH
|
67
|
-
@current_source = nil
|
68
|
-
@opts, @type = {}, line
|
69
130
|
when SPECS
|
70
131
|
case @type
|
71
132
|
when PATH
|
@@ -75,15 +136,24 @@ module Bundler
|
|
75
136
|
@current_source = TYPES[@type].from_lock(@opts)
|
76
137
|
# Strip out duplicate GIT sections
|
77
138
|
if @sources.include?(@current_source)
|
78
|
-
@current_source = @sources.find {
|
139
|
+
@current_source = @sources.find {|s| s == @current_source }
|
79
140
|
else
|
80
141
|
@sources << @current_source
|
81
142
|
end
|
82
143
|
when GEM
|
83
|
-
|
84
|
-
@
|
144
|
+
if Bundler.feature_flag.lockfile_uses_separate_rubygems_sources?
|
145
|
+
@opts["remotes"] = @opts.delete("remote")
|
146
|
+
@current_source = TYPES[@type].from_lock(@opts)
|
147
|
+
@sources << @current_source
|
148
|
+
else
|
149
|
+
Array(@opts["remote"]).each do |url|
|
150
|
+
@rubygems_aggregate.add_remote(url)
|
151
|
+
end
|
152
|
+
@current_source = @rubygems_aggregate
|
85
153
|
end
|
86
|
-
|
154
|
+
when PLUGIN
|
155
|
+
@current_source = Plugin.source_from_lock(@opts)
|
156
|
+
@sources << @current_source
|
87
157
|
end
|
88
158
|
when OPTIONS
|
89
159
|
value = $2
|
@@ -98,64 +168,89 @@ module Bundler
|
|
98
168
|
else
|
99
169
|
@opts[key] = value
|
100
170
|
end
|
171
|
+
when *SOURCE
|
172
|
+
@current_source = nil
|
173
|
+
@opts = {}
|
174
|
+
@type = line
|
101
175
|
else
|
102
176
|
parse_spec(line)
|
103
177
|
end
|
104
178
|
end
|
105
179
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
180
|
+
space = / /
|
181
|
+
NAME_VERSION = /
|
182
|
+
^(#{space}{2}|#{space}{4}|#{space}{6})(?!#{space}) # Exactly 2, 4, or 6 spaces at the start of the line
|
183
|
+
(.*?) # Name
|
184
|
+
(?:#{space}\(([^-]*) # Space, followed by version
|
185
|
+
(?:-(.*))?\))? # Optional platform
|
186
|
+
(!)? # Optional pinned marker
|
187
|
+
$ # Line end
|
188
|
+
/xo
|
110
189
|
|
111
190
|
def parse_dependency(line)
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
# Path sources need to know what the default name / version
|
123
|
-
# to use in the case that there are no gemspecs present. A fake
|
124
|
-
# gemspec is created based on the version set on the dependency
|
125
|
-
# TODO: Use the version from the spec instead of from the dependency
|
126
|
-
if version && version.size == 1 && version.first =~ /^\s*= (.+)\s*$/ && dep.source.is_a?(Bundler::Source::Path)
|
127
|
-
dep.source.name = name
|
128
|
-
dep.source.version = $1
|
129
|
-
end
|
130
|
-
end
|
191
|
+
return unless line =~ NAME_VERSION
|
192
|
+
spaces = $1
|
193
|
+
return unless spaces.size == 2
|
194
|
+
name = $2
|
195
|
+
version = $3
|
196
|
+
pinned = $5
|
197
|
+
|
198
|
+
version = version.split(",").map(&:strip) if version
|
199
|
+
|
200
|
+
dep = Bundler::Dependency.new(name, version)
|
131
201
|
|
132
|
-
|
202
|
+
if pinned && dep.name != "bundler"
|
203
|
+
spec = @specs.find {|_, v| v.name == dep.name }
|
204
|
+
dep.source = spec.last.source if spec
|
205
|
+
|
206
|
+
# Path sources need to know what the default name / version
|
207
|
+
# to use in the case that there are no gemspecs present. A fake
|
208
|
+
# gemspec is created based on the version set on the dependency
|
209
|
+
# TODO: Use the version from the spec instead of from the dependency
|
210
|
+
if version && version.size == 1 && version.first =~ /^\s*= (.+)\s*$/ && dep.source.is_a?(Bundler::Source::Path)
|
211
|
+
dep.source.name = name
|
212
|
+
dep.source.version = $1
|
213
|
+
end
|
133
214
|
end
|
215
|
+
|
216
|
+
@dependencies[dep.name] = dep
|
134
217
|
end
|
135
218
|
|
136
219
|
def parse_spec(line)
|
137
|
-
|
138
|
-
|
139
|
-
|
220
|
+
return unless line =~ NAME_VERSION
|
221
|
+
spaces = $1
|
222
|
+
name = $2
|
223
|
+
version = $3
|
224
|
+
platform = $4
|
225
|
+
|
226
|
+
if spaces.size == 4
|
227
|
+
version = Gem::Version.new(version)
|
228
|
+
platform = platform ? Gem::Platform.new(platform) : Gem::Platform::RUBY
|
140
229
|
@current_spec = LazySpecification.new(name, version, platform)
|
141
230
|
@current_spec.source = @current_source
|
142
231
|
|
143
232
|
# Avoid introducing multiple copies of the same spec (caused by
|
144
233
|
# duplicate GIT sections)
|
145
234
|
@specs[@current_spec.identifier] ||= @current_spec
|
146
|
-
elsif
|
147
|
-
|
148
|
-
version = version.split(',').map { |d| d.strip } if version
|
235
|
+
elsif spaces.size == 6
|
236
|
+
version = version.split(",").map(&:strip) if version
|
149
237
|
dep = Gem::Dependency.new(name, version)
|
150
238
|
@current_spec.dependencies << dep
|
151
239
|
end
|
152
240
|
end
|
153
241
|
|
154
242
|
def parse_platform(line)
|
155
|
-
if line =~ /^ (.*)$/
|
156
|
-
|
157
|
-
|
243
|
+
@platforms << Gem::Platform.new($1) if line =~ /^ (.*)$/
|
244
|
+
end
|
245
|
+
|
246
|
+
def parse_bundled_with(line)
|
247
|
+
line = line.strip
|
248
|
+
return unless Gem::Version.correct?(line)
|
249
|
+
@bundler_version = Gem::Version.create(line)
|
158
250
|
end
|
159
251
|
|
252
|
+
def parse_ruby(line)
|
253
|
+
@ruby_version = line.strip
|
254
|
+
end
|
160
255
|
end
|
161
256
|
end
|
@@ -1,13 +1,24 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/gem_helpers"
|
2
4
|
|
3
5
|
module Bundler
|
4
6
|
module MatchPlatform
|
5
7
|
include GemHelpers
|
6
8
|
|
7
9
|
def match_platform(p)
|
8
|
-
|
9
|
-
|
10
|
-
|
10
|
+
MatchPlatform.platforms_match?(platform, p)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.platforms_match?(gemspec_platform, local_platform)
|
14
|
+
return true if gemspec_platform.nil?
|
15
|
+
return true if Gem::Platform::RUBY == gemspec_platform
|
16
|
+
return true if local_platform == gemspec_platform
|
17
|
+
gemspec_platform = Gem::Platform.new(gemspec_platform)
|
18
|
+
return true if GemHelpers.generic(gemspec_platform) === local_platform
|
19
|
+
return true if gemspec_platform === local_platform
|
20
|
+
|
21
|
+
false
|
11
22
|
end
|
12
23
|
end
|
13
24
|
end
|
@@ -0,0 +1,223 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "socket"
|
4
|
+
|
5
|
+
module Bundler
|
6
|
+
class Settings
|
7
|
+
# Class used to build the mirror set and then find a mirror for a given URI
|
8
|
+
#
|
9
|
+
# @param prober [Prober object, nil] by default a TCPSocketProbe, this object
|
10
|
+
# will be used to probe the mirror address to validate that the mirror replies.
|
11
|
+
class Mirrors
|
12
|
+
def initialize(prober = nil)
|
13
|
+
@all = Mirror.new
|
14
|
+
@prober = prober || TCPSocketProbe.new
|
15
|
+
@mirrors = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns a mirror for the given uri.
|
19
|
+
#
|
20
|
+
# Depending on the uri having a valid mirror or not, it may be a
|
21
|
+
# mirror that points to the provided uri
|
22
|
+
def for(uri)
|
23
|
+
if @all.validate!(@prober).valid?
|
24
|
+
@all
|
25
|
+
else
|
26
|
+
fetch_valid_mirror_for(Settings.normalize_uri(uri))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def each
|
31
|
+
@mirrors.each do |k, v|
|
32
|
+
yield k, v.uri.to_s
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def parse(key, value)
|
37
|
+
config = MirrorConfig.new(key, value)
|
38
|
+
mirror = if config.all?
|
39
|
+
@all
|
40
|
+
else
|
41
|
+
@mirrors[config.uri] ||= Mirror.new
|
42
|
+
end
|
43
|
+
config.update_mirror(mirror)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def fetch_valid_mirror_for(uri)
|
49
|
+
downcased = uri.to_s.downcase
|
50
|
+
mirror = @mirrors[downcased] || @mirrors[URI(downcased).host] || Mirror.new(uri)
|
51
|
+
mirror.validate!(@prober)
|
52
|
+
mirror = Mirror.new(uri) unless mirror.valid?
|
53
|
+
mirror
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# A mirror
|
58
|
+
#
|
59
|
+
# Contains both the uri that should be used as a mirror and the
|
60
|
+
# fallback timeout which will be used for probing if the mirror
|
61
|
+
# replies on time or not.
|
62
|
+
class Mirror
|
63
|
+
DEFAULT_FALLBACK_TIMEOUT = 0.1
|
64
|
+
|
65
|
+
attr_reader :uri, :fallback_timeout
|
66
|
+
|
67
|
+
def initialize(uri = nil, fallback_timeout = 0)
|
68
|
+
self.uri = uri
|
69
|
+
self.fallback_timeout = fallback_timeout
|
70
|
+
@valid = nil
|
71
|
+
end
|
72
|
+
|
73
|
+
def uri=(uri)
|
74
|
+
@uri = if uri.nil?
|
75
|
+
nil
|
76
|
+
else
|
77
|
+
URI(uri.to_s)
|
78
|
+
end
|
79
|
+
@valid = nil
|
80
|
+
end
|
81
|
+
|
82
|
+
def fallback_timeout=(timeout)
|
83
|
+
case timeout
|
84
|
+
when true, "true"
|
85
|
+
@fallback_timeout = DEFAULT_FALLBACK_TIMEOUT
|
86
|
+
when false, "false"
|
87
|
+
@fallback_timeout = 0
|
88
|
+
else
|
89
|
+
@fallback_timeout = timeout.to_i
|
90
|
+
end
|
91
|
+
@valid = nil
|
92
|
+
end
|
93
|
+
|
94
|
+
def ==(other)
|
95
|
+
!other.nil? && uri == other.uri && fallback_timeout == other.fallback_timeout
|
96
|
+
end
|
97
|
+
|
98
|
+
def valid?
|
99
|
+
return false if @uri.nil?
|
100
|
+
return @valid unless @valid.nil?
|
101
|
+
false
|
102
|
+
end
|
103
|
+
|
104
|
+
def validate!(probe = nil)
|
105
|
+
@valid = false if uri.nil?
|
106
|
+
if @valid.nil?
|
107
|
+
@valid = fallback_timeout == 0 || (probe || TCPSocketProbe.new).replies?(self)
|
108
|
+
end
|
109
|
+
self
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Class used to parse one configuration line
|
114
|
+
#
|
115
|
+
# Gets the configuration line and the value.
|
116
|
+
# This object provides a `update_mirror` method
|
117
|
+
# used to setup the given mirror value.
|
118
|
+
class MirrorConfig
|
119
|
+
attr_accessor :uri, :value
|
120
|
+
|
121
|
+
def initialize(config_line, value)
|
122
|
+
uri, fallback =
|
123
|
+
config_line.match(%r{\Amirror\.(all|.+?)(\.fallback_timeout)?\/?\z}).captures
|
124
|
+
@fallback = !fallback.nil?
|
125
|
+
@all = false
|
126
|
+
if uri == "all"
|
127
|
+
@all = true
|
128
|
+
else
|
129
|
+
@uri = URI(uri).absolute? ? Settings.normalize_uri(uri) : uri
|
130
|
+
end
|
131
|
+
@value = value
|
132
|
+
end
|
133
|
+
|
134
|
+
def all?
|
135
|
+
@all
|
136
|
+
end
|
137
|
+
|
138
|
+
def update_mirror(mirror)
|
139
|
+
if @fallback
|
140
|
+
mirror.fallback_timeout = @value
|
141
|
+
else
|
142
|
+
mirror.uri = Settings.normalize_uri(@value)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Class used for probing TCP availability for a given mirror.
|
148
|
+
class TCPSocketProbe
|
149
|
+
def replies?(mirror)
|
150
|
+
MirrorSockets.new(mirror).any? do |socket, address, timeout|
|
151
|
+
begin
|
152
|
+
socket.connect_nonblock(address)
|
153
|
+
rescue Errno::EINPROGRESS
|
154
|
+
wait_for_writtable_socket(socket, address, timeout)
|
155
|
+
rescue RuntimeError # Connection failed somehow, again
|
156
|
+
false
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
162
|
+
|
163
|
+
def wait_for_writtable_socket(socket, address, timeout)
|
164
|
+
if IO.select(nil, [socket], nil, timeout)
|
165
|
+
probe_writtable_socket(socket, address)
|
166
|
+
else # TCP Handshake timed out, or there is something dropping packets
|
167
|
+
false
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def probe_writtable_socket(socket, address)
|
172
|
+
socket.connect_nonblock(address)
|
173
|
+
rescue Errno::EISCONN
|
174
|
+
true
|
175
|
+
rescue StandardError # Connection failed
|
176
|
+
false
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# Class used to build the list of sockets that correspond to
|
182
|
+
# a given mirror.
|
183
|
+
#
|
184
|
+
# One mirror may correspond to many different addresses, both
|
185
|
+
# because of it having many dns entries or because
|
186
|
+
# the network interface is both ipv4 and ipv5
|
187
|
+
class MirrorSockets
|
188
|
+
def initialize(mirror)
|
189
|
+
@timeout = mirror.fallback_timeout
|
190
|
+
@addresses = Socket.getaddrinfo(mirror.uri.host, mirror.uri.port).map do |address|
|
191
|
+
SocketAddress.new(address[0], address[3], address[1])
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def any?
|
196
|
+
@addresses.any? do |address|
|
197
|
+
socket = Socket.new(Socket.const_get(address.type), Socket::SOCK_STREAM, 0)
|
198
|
+
socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
199
|
+
value = yield socket, address.to_socket_address, @timeout
|
200
|
+
socket.close unless socket.closed?
|
201
|
+
value
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
# Socket address builder.
|
207
|
+
#
|
208
|
+
# Given a socket type, a host and a port,
|
209
|
+
# provides a method to build sockaddr string
|
210
|
+
class SocketAddress
|
211
|
+
attr_reader :type, :host, :port
|
212
|
+
|
213
|
+
def initialize(type, host, port)
|
214
|
+
@type = type
|
215
|
+
@host = host
|
216
|
+
@port = port
|
217
|
+
end
|
218
|
+
|
219
|
+
def to_socket_address
|
220
|
+
Socket.pack_sockaddr_in(@port, @host)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|