bundler 1.16.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 +195 -0
- data/README.md +5 -1
- data/bundler.gemspec +9 -2
- data/lib/bundler/build_metadata.rb +19 -4
- data/lib/bundler/cli/add.rb +15 -5
- data/lib/bundler/cli/binstubs.rb +8 -2
- data/lib/bundler/cli/check.rb +1 -1
- data/lib/bundler/cli/doctor.rb +47 -1
- data/lib/bundler/cli/exec.rb +4 -4
- data/lib/bundler/cli/gem.rb +5 -2
- data/lib/bundler/cli/init.rb +5 -0
- data/lib/bundler/cli/install.rb +10 -7
- data/lib/bundler/cli/list.rb +41 -5
- data/lib/bundler/cli/outdated.rb +8 -2
- data/lib/bundler/cli/pristine.rb +4 -0
- data/lib/bundler/cli/remove.rb +18 -0
- data/lib/bundler/cli/update.rb +3 -3
- data/lib/bundler/cli.rb +66 -22
- data/lib/bundler/compact_index_client/updater.rb +10 -1
- data/lib/bundler/current_ruby.rb +8 -1
- data/lib/bundler/definition.rb +48 -39
- data/lib/bundler/dep_proxy.rb +2 -2
- data/lib/bundler/dependency.rb +3 -2
- data/lib/bundler/deprecate.rb +2 -1
- data/lib/bundler/dsl.rb +19 -3
- data/lib/bundler/endpoint_specification.rb +1 -1
- data/lib/bundler/env.rb +10 -8
- data/lib/bundler/feature_flag.rb +7 -0
- data/lib/bundler/fetcher/downloader.rb +10 -5
- data/lib/bundler/fetcher/index.rb +2 -2
- data/lib/bundler/fetcher.rb +3 -3
- data/lib/bundler/friendly_errors.rb +2 -0
- data/lib/bundler/gem_helper.rb +1 -1
- data/lib/bundler/gem_version_promoter.rb +16 -2
- data/lib/bundler/injector.rb +173 -14
- data/lib/bundler/installer/gem_installer.rb +9 -2
- data/lib/bundler/installer/parallel_installer.rb +6 -1
- data/lib/bundler/installer.rb +41 -10
- data/lib/bundler/lazy_specification.rb +1 -1
- data/lib/bundler/mirror.rb +2 -2
- data/lib/bundler/plugin/events.rb +61 -0
- data/lib/bundler/plugin/index.rb +7 -2
- data/lib/bundler/plugin.rb +12 -5
- data/lib/bundler/process_lock.rb +1 -1
- data/lib/bundler/resolver/spec_group.rb +0 -5
- data/lib/bundler/resolver.rb +11 -10
- data/lib/bundler/ruby_version.rb +1 -1
- data/lib/bundler/rubygems_gem_installer.rb +7 -0
- data/lib/bundler/rubygems_integration.rb +9 -3
- data/lib/bundler/runtime.rb +10 -4
- data/lib/bundler/settings/validator.rb +23 -0
- data/lib/bundler/settings.rb +24 -3
- data/lib/bundler/shared_helpers.rb +33 -5
- data/lib/bundler/source/git/git_proxy.rb +6 -1
- data/lib/bundler/source/git.rb +2 -1
- data/lib/bundler/source/metadata.rb +2 -3
- data/lib/bundler/source/rubygems/remote.rb +4 -1
- data/lib/bundler/source/rubygems.rb +11 -2
- data/lib/bundler/source.rb +9 -9
- data/lib/bundler/spec_set.rb +4 -1
- data/lib/bundler/templates/Executable +1 -1
- data/lib/bundler/templates/newgem/lib/newgem.rb.tt +1 -0
- data/lib/bundler/templates/newgem/newgem.gemspec.tt +8 -2
- data/lib/bundler/templates/newgem/travis.yml.tt +2 -0
- data/lib/bundler/ui/shell.rb +3 -1
- data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb +11 -1
- data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +7 -2
- data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +1 -1
- data/lib/bundler/version.rb +1 -1
- data/lib/bundler.rb +38 -16
- data/man/bundle-add.1 +18 -3
- data/man/bundle-add.1.txt +17 -5
- data/man/bundle-add.ronn +13 -2
- data/man/bundle-binstubs.1 +4 -4
- data/man/bundle-binstubs.1.txt +4 -4
- data/man/bundle-binstubs.ronn +3 -3
- data/man/bundle-check.1 +4 -4
- data/man/bundle-check.1.txt +6 -5
- data/man/bundle-check.ronn +3 -3
- data/man/bundle-clean.1 +1 -1
- data/man/bundle-clean.1.txt +1 -1
- data/man/bundle-config.1 +48 -6
- data/man/bundle-config.1.txt +64 -26
- data/man/bundle-config.ronn +34 -9
- 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 +4 -4
- data/man/bundle-exec.1.txt +9 -9
- data/man/bundle-exec.ronn +3 -3
- data/man/bundle-gem.1 +2 -2
- data/man/bundle-gem.1.txt +2 -2
- data/man/bundle-gem.ronn +1 -1
- data/man/bundle-info.1 +1 -1
- data/man/bundle-info.1.txt +1 -1
- data/man/bundle-init.1 +9 -4
- data/man/bundle-init.1.txt +16 -6
- data/man/bundle-init.ronn +15 -4
- data/man/bundle-inject.1 +4 -4
- data/man/bundle-inject.1.txt +5 -5
- data/man/bundle-inject.ronn +3 -3
- data/man/bundle-install.1 +7 -4
- data/man/bundle-install.1.txt +119 -108
- data/man/bundle-install.ronn +13 -4
- data/man/bundle-list.1 +32 -2
- data/man/bundle-list.1.txt +24 -2
- data/man/bundle-list.ronn +19 -1
- data/man/bundle-lock.1 +2 -2
- data/man/bundle-lock.1.txt +2 -2
- data/man/bundle-lock.ronn +1 -1
- data/man/bundle-open.1 +1 -1
- data/man/bundle-open.1.txt +1 -1
- data/man/bundle-outdated.1 +7 -3
- data/man/bundle-outdated.1.txt +11 -7
- data/man/bundle-outdated.ronn +5 -1
- data/man/bundle-package.1 +3 -3
- data/man/bundle-package.1.txt +6 -6
- data/man/bundle-package.ronn +3 -3
- data/man/bundle-platform.1 +1 -1
- data/man/bundle-platform.1.txt +1 -1
- data/man/bundle-pristine.1 +1 -1
- data/man/bundle-pristine.1.txt +1 -1
- 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 +6 -4
- data/man/bundle-show.ronn +3 -2
- data/man/bundle-update.1 +17 -13
- data/man/bundle-update.1.txt +68 -63
- data/man/bundle-update.ronn +19 -15
- data/man/bundle-viz.1 +2 -2
- data/man/bundle-viz.1.txt +3 -2
- data/man/bundle-viz.ronn +1 -1
- data/man/bundle.1 +32 -28
- data/man/bundle.1.txt +31 -28
- data/man/bundle.ronn +30 -27
- data/man/gemfile.5 +19 -9
- data/man/gemfile.5.ronn +24 -9
- data/man/gemfile.5.txt +114 -97
- data/man/index.txt +2 -0
- metadata +16 -3
data/lib/bundler/feature_flag.rb
CHANGED
@@ -30,6 +30,7 @@ module Bundler
|
|
30
30
|
settings_flag(:allow_bundler_dependency_conflicts) { bundler_2_mode? }
|
31
31
|
settings_flag(:allow_offline_install) { bundler_2_mode? }
|
32
32
|
settings_flag(:auto_clean_without_path) { bundler_2_mode? }
|
33
|
+
settings_flag(:auto_config_jobs) { bundler_2_mode? }
|
33
34
|
settings_flag(:cache_all) { bundler_2_mode? }
|
34
35
|
settings_flag(:cache_command_is_package) { bundler_2_mode? }
|
35
36
|
settings_flag(:console_command) { !bundler_2_mode? }
|
@@ -38,11 +39,13 @@ module Bundler
|
|
38
39
|
settings_flag(:disable_multisource) { bundler_2_mode? }
|
39
40
|
settings_flag(:error_on_stderr) { bundler_2_mode? }
|
40
41
|
settings_flag(:forget_cli_options) { bundler_2_mode? }
|
42
|
+
settings_flag(:global_path_appends_ruby_scope) { bundler_2_mode? }
|
41
43
|
settings_flag(:global_gem_cache) { bundler_2_mode? }
|
42
44
|
settings_flag(:init_gems_rb) { bundler_2_mode? }
|
43
45
|
settings_flag(:list_command) { bundler_2_mode? }
|
44
46
|
settings_flag(:lockfile_uses_separate_rubygems_sources) { bundler_2_mode? }
|
45
47
|
settings_flag(:only_update_to_newer_versions) { bundler_2_mode? }
|
48
|
+
settings_flag(:path_relative_to_cwd) { bundler_2_mode? }
|
46
49
|
settings_flag(:plugins) { @bundler_version >= Gem::Version.new("1.14") }
|
47
50
|
settings_flag(:prefer_gems_rb) { bundler_2_mode? }
|
48
51
|
settings_flag(:print_only_version_number) { bundler_2_mode? }
|
@@ -52,9 +55,13 @@ module Bundler
|
|
52
55
|
settings_flag(:suppress_install_using_messages) { bundler_2_mode? }
|
53
56
|
settings_flag(:unlock_source_unlocks_spec) { !bundler_2_mode? }
|
54
57
|
settings_flag(:update_requires_all_flag) { bundler_2_mode? }
|
58
|
+
settings_flag(:use_gem_version_promoter_for_major_updates) { bundler_2_mode? }
|
59
|
+
settings_flag(:viz_command) { !bundler_2_mode? }
|
55
60
|
|
56
61
|
settings_option(:default_cli_command) { bundler_2_mode? ? :cli_help : :install }
|
57
62
|
|
63
|
+
settings_method(:github_https?, "github.https") { bundler_2_mode? }
|
64
|
+
|
58
65
|
def initialize(bundler_version)
|
59
66
|
@bundler_version = Gem::Version.create(bundler_version)
|
60
67
|
end
|
@@ -11,10 +11,10 @@ module Bundler
|
|
11
11
|
@redirect_limit = redirect_limit
|
12
12
|
end
|
13
13
|
|
14
|
-
def fetch(uri,
|
14
|
+
def fetch(uri, headers = {}, counter = 0)
|
15
15
|
raise HTTPError, "Too many redirects" if counter >= redirect_limit
|
16
16
|
|
17
|
-
response = request(uri,
|
17
|
+
response = request(uri, headers)
|
18
18
|
Bundler.ui.debug("HTTP #{response.code} #{response.message} #{uri}")
|
19
19
|
|
20
20
|
case response
|
@@ -26,7 +26,12 @@ module Bundler
|
|
26
26
|
new_uri.user = uri.user
|
27
27
|
new_uri.password = uri.password
|
28
28
|
end
|
29
|
-
fetch(new_uri,
|
29
|
+
fetch(new_uri, headers, counter + 1)
|
30
|
+
when Net::HTTPRequestedRangeNotSatisfiable
|
31
|
+
new_headers = headers.dup
|
32
|
+
new_headers.delete("Range")
|
33
|
+
new_headers["Accept-Encoding"] = "gzip"
|
34
|
+
fetch(uri, new_headers)
|
30
35
|
when Net::HTTPRequestEntityTooLarge
|
31
36
|
raise FallbackError, response.body
|
32
37
|
when Net::HTTPUnauthorized
|
@@ -38,11 +43,11 @@ module Bundler
|
|
38
43
|
end
|
39
44
|
end
|
40
45
|
|
41
|
-
def request(uri,
|
46
|
+
def request(uri, headers)
|
42
47
|
validate_uri_scheme!(uri)
|
43
48
|
|
44
49
|
Bundler.ui.debug "HTTP GET #{uri}"
|
45
|
-
req = Net::HTTP::Get.new uri.request_uri,
|
50
|
+
req = Net::HTTP::Get.new uri.request_uri, headers
|
46
51
|
if uri.user
|
47
52
|
user = CGI.unescape(uri.user)
|
48
53
|
password = uri.password ? CGI.unescape(uri.password) : nil
|
@@ -29,11 +29,11 @@ module Bundler
|
|
29
29
|
|
30
30
|
uri = URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz")
|
31
31
|
if uri.scheme == "file"
|
32
|
-
Bundler.load_marshal
|
32
|
+
Bundler.load_marshal Bundler.rubygems.inflate(Gem.read_binary(uri.path))
|
33
33
|
elsif cached_spec_path = gemspec_cached_path(spec_file_name)
|
34
34
|
Bundler.load_gemspec(cached_spec_path)
|
35
35
|
else
|
36
|
-
Bundler.load_marshal
|
36
|
+
Bundler.load_marshal Bundler.rubygems.inflate(downloader.fetch(uri).body)
|
37
37
|
end
|
38
38
|
rescue MarshalError
|
39
39
|
raise HTTPError, "Gemspec #{spec} contained invalid data.\n" \
|
data/lib/bundler/fetcher.rb
CHANGED
@@ -96,11 +96,11 @@ module Bundler
|
|
96
96
|
|
97
97
|
uri = URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz")
|
98
98
|
if uri.scheme == "file"
|
99
|
-
Bundler.load_marshal
|
99
|
+
Bundler.load_marshal Bundler.rubygems.inflate(Gem.read_binary(uri.path))
|
100
100
|
elsif cached_spec_path = gemspec_cached_path(spec_file_name)
|
101
101
|
Bundler.load_gemspec(cached_spec_path)
|
102
102
|
else
|
103
|
-
Bundler.load_marshal
|
103
|
+
Bundler.load_marshal Bundler.rubygems.inflate(downloader.fetch(uri).body)
|
104
104
|
end
|
105
105
|
rescue MarshalError
|
106
106
|
raise HTTPError, "Gemspec #{spec} contained invalid data.\n" \
|
@@ -178,7 +178,7 @@ module Bundler
|
|
178
178
|
# engine_version raises on unknown engines
|
179
179
|
engine_version = begin
|
180
180
|
ruby.engine_versions
|
181
|
-
rescue
|
181
|
+
rescue RuntimeError
|
182
182
|
"???"
|
183
183
|
end
|
184
184
|
agent << " #{ruby.engine}/#{ruby.versions_string(engine_version)}"
|
@@ -45,6 +45,8 @@ module Bundler
|
|
45
45
|
"Alternatively, you can increase the amount of memory the JVM is able to use by running Bundler with jruby -J-Xmx1024m -S bundle (JRuby defaults to 500MB)."
|
46
46
|
else request_issue_report_for(error)
|
47
47
|
end
|
48
|
+
rescue
|
49
|
+
raise error
|
48
50
|
end
|
49
51
|
|
50
52
|
def exit_status(error)
|
data/lib/bundler/gem_helper.rb
CHANGED
@@ -153,7 +153,7 @@ module Bundler
|
|
153
153
|
sh "git tag -m \"Version #{version}\" #{version_tag}"
|
154
154
|
Bundler.ui.confirm "Tagged #{version_tag}."
|
155
155
|
yield if block_given?
|
156
|
-
rescue
|
156
|
+
rescue RuntimeError
|
157
157
|
Bundler.ui.error "Untagging #{version_tag} due to error."
|
158
158
|
sh_with_code "git tag -d #{version_tag}"
|
159
159
|
raise
|
@@ -7,6 +7,8 @@ module Bundler
|
|
7
7
|
# available dependency versions as found in its index, before returning it to
|
8
8
|
# to the resolution engine to select the best version.
|
9
9
|
class GemVersionPromoter
|
10
|
+
DEBUG = ENV["DEBUG_RESOLVER"]
|
11
|
+
|
10
12
|
attr_reader :level, :locked_specs, :unlock_gems
|
11
13
|
|
12
14
|
# By default, strict is false, meaning every available version of a gem
|
@@ -22,6 +24,8 @@ module Bundler
|
|
22
24
|
# existing in the referenced source.
|
23
25
|
attr_accessor :strict
|
24
26
|
|
27
|
+
attr_accessor :prerelease_specified
|
28
|
+
|
25
29
|
# Given a list of locked_specs and a list of gems to unlock creates a
|
26
30
|
# GemVersionPromoter instance.
|
27
31
|
#
|
@@ -37,6 +41,7 @@ module Bundler
|
|
37
41
|
@locked_specs = locked_specs
|
38
42
|
@unlock_gems = unlock_gems
|
39
43
|
@sort_versions = {}
|
44
|
+
@prerelease_specified = {}
|
40
45
|
end
|
41
46
|
|
42
47
|
# @param value [Symbol] One of three Symbols: :major, :minor or :patch.
|
@@ -61,7 +66,7 @@ module Bundler
|
|
61
66
|
# @return [SpecGroup] A new instance of the SpecGroup Array sorted and
|
62
67
|
# possibly filtered.
|
63
68
|
def sort_versions(dep, spec_groups)
|
64
|
-
before_result = "before sort_versions: #{debug_format_result(dep, spec_groups).inspect}" if
|
69
|
+
before_result = "before sort_versions: #{debug_format_result(dep, spec_groups).inspect}" if DEBUG
|
65
70
|
|
66
71
|
@sort_versions[dep] ||= begin
|
67
72
|
gem_name = dep.name
|
@@ -75,7 +80,7 @@ module Bundler
|
|
75
80
|
else
|
76
81
|
sort_dep_specs(spec_groups, locked_spec)
|
77
82
|
end.tap do |specs|
|
78
|
-
if
|
83
|
+
if DEBUG
|
79
84
|
STDERR.puts before_result
|
80
85
|
STDERR.puts " after sort_versions: #{debug_format_result(dep, specs).inspect}"
|
81
86
|
end
|
@@ -121,6 +126,15 @@ module Bundler
|
|
121
126
|
result = spec_groups.sort do |a, b|
|
122
127
|
@a_ver = a.version
|
123
128
|
@b_ver = b.version
|
129
|
+
|
130
|
+
unless @prerelease_specified[@gem_name]
|
131
|
+
a_pre = @a_ver.prerelease?
|
132
|
+
b_pre = @b_ver.prerelease?
|
133
|
+
|
134
|
+
next -1 if a_pre && !b_pre
|
135
|
+
next 1 if b_pre && !a_pre
|
136
|
+
end
|
137
|
+
|
124
138
|
if major?
|
125
139
|
@a_ver <=> @b_ver
|
126
140
|
elsif either_version_older_than_locked
|
data/lib/bundler/injector.rb
CHANGED
@@ -2,18 +2,28 @@
|
|
2
2
|
|
3
3
|
module Bundler
|
4
4
|
class Injector
|
5
|
+
INJECTED_GEMS = "injected gems".freeze
|
6
|
+
|
5
7
|
def self.inject(new_deps, options = {})
|
6
8
|
injector = new(new_deps, options)
|
7
9
|
injector.inject(Bundler.default_gemfile, Bundler.default_lockfile)
|
8
10
|
end
|
9
11
|
|
10
|
-
def
|
11
|
-
|
12
|
+
def self.remove(gems, options = {})
|
13
|
+
injector = new(gems, options)
|
14
|
+
injector.remove(Bundler.default_gemfile, Bundler.default_lockfile)
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(deps, options = {})
|
18
|
+
@deps = deps
|
12
19
|
@options = options
|
13
20
|
end
|
14
21
|
|
22
|
+
# @param [Pathname] gemfile_path The Gemfile in which to inject the new dependency.
|
23
|
+
# @param [Pathname] lockfile_path The lockfile in which to inject the new dependency.
|
24
|
+
# @return [Array]
|
15
25
|
def inject(gemfile_path, lockfile_path)
|
16
|
-
if Bundler.
|
26
|
+
if Bundler.frozen_bundle?
|
17
27
|
# ensure the lock and Gemfile are synced
|
18
28
|
Bundler.definition.ensure_equivalent_gemfile_and_lockfile(true)
|
19
29
|
end
|
@@ -25,18 +35,19 @@ module Bundler
|
|
25
35
|
builder.eval_gemfile(gemfile_path)
|
26
36
|
|
27
37
|
# don't inject any gems that are already in the Gemfile
|
28
|
-
@
|
38
|
+
@deps -= builder.dependencies
|
29
39
|
|
30
40
|
# add new deps to the end of the in-memory Gemfile
|
31
|
-
# Set conservative versioning to false because
|
32
|
-
|
41
|
+
# Set conservative versioning to false because
|
42
|
+
# we want to let the resolver resolve the version first
|
43
|
+
builder.eval_gemfile(INJECTED_GEMS, build_gem_lines(false)) if @deps.any?
|
33
44
|
|
34
45
|
# resolve to see if the new deps broke anything
|
35
46
|
@definition = builder.to_definition(lockfile_path, {})
|
36
47
|
@definition.resolve_remotely!
|
37
48
|
|
38
49
|
# since nothing broke, we can add those gems to the gemfile
|
39
|
-
append_to(gemfile_path, build_gem_lines(@options[:conservative_versioning])) if @
|
50
|
+
append_to(gemfile_path, build_gem_lines(@options[:conservative_versioning])) if @deps.any?
|
40
51
|
|
41
52
|
# since we resolved successfully, write out the lockfile
|
42
53
|
@definition.lock(Bundler.default_lockfile)
|
@@ -45,7 +56,21 @@ module Bundler
|
|
45
56
|
Bundler.reset_paths!
|
46
57
|
|
47
58
|
# return an array of the deps that we added
|
48
|
-
@
|
59
|
+
@deps
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# @param [Pathname] gemfile_path The Gemfile from which to remove dependencies.
|
64
|
+
# @param [Pathname] lockfile_path The lockfile from which to remove dependencies.
|
65
|
+
# @return [Array]
|
66
|
+
def remove(gemfile_path, lockfile_path)
|
67
|
+
# remove gems from each gemfiles we have
|
68
|
+
Bundler.definition.gemfiles.each do |path|
|
69
|
+
deps = remove_deps(path)
|
70
|
+
|
71
|
+
show_warning("No gems were removed from the gemfile.") if deps.empty?
|
72
|
+
|
73
|
+
deps.each {|dep| Bundler.ui.confirm "#{SharedHelpers.pretty_dependency(dep, false)} was removed." }
|
49
74
|
end
|
50
75
|
end
|
51
76
|
|
@@ -58,11 +83,21 @@ module Bundler
|
|
58
83
|
seg_end_index = version >= Gem::Version.new("1.0") ? 1 : 2
|
59
84
|
|
60
85
|
prerelease_suffix = version.to_s.gsub(version.release.to_s, "") if version.prerelease?
|
61
|
-
"
|
86
|
+
"#{version_prefix}#{segments[0..seg_end_index].join(".")}#{prerelease_suffix}"
|
87
|
+
end
|
88
|
+
|
89
|
+
def version_prefix
|
90
|
+
if @options[:strict]
|
91
|
+
"= "
|
92
|
+
elsif @options[:optimistic]
|
93
|
+
">= "
|
94
|
+
else
|
95
|
+
"~> "
|
96
|
+
end
|
62
97
|
end
|
63
98
|
|
64
99
|
def build_gem_lines(conservative_versioning)
|
65
|
-
@
|
100
|
+
@deps.map do |d|
|
66
101
|
name = d.name.dump
|
67
102
|
|
68
103
|
requirement = if conservative_versioning
|
@@ -72,7 +107,7 @@ module Bundler
|
|
72
107
|
end
|
73
108
|
|
74
109
|
if d.groups != Array(:default)
|
75
|
-
group = d.groups.size == 1 ? ", :group => #{d.groups.inspect}" : ", :groups => #{d.groups.inspect}"
|
110
|
+
group = d.groups.size == 1 ? ", :group => #{d.groups.first.inspect}" : ", :groups => #{d.groups.inspect}"
|
76
111
|
end
|
77
112
|
|
78
113
|
source = ", :source => \"#{d.source}\"" unless d.source.nil?
|
@@ -84,11 +119,135 @@ module Bundler
|
|
84
119
|
def append_to(gemfile_path, new_gem_lines)
|
85
120
|
gemfile_path.open("a") do |f|
|
86
121
|
f.puts
|
87
|
-
if @options["timestamp"] || @options["timestamp"].nil?
|
88
|
-
f.puts "# Added at #{Time.now} by #{`whoami`.chomp}:"
|
89
|
-
end
|
90
122
|
f.puts new_gem_lines
|
91
123
|
end
|
92
124
|
end
|
125
|
+
|
126
|
+
# evalutes a gemfile to remove the specified gem
|
127
|
+
# from it.
|
128
|
+
def remove_deps(gemfile_path)
|
129
|
+
initial_gemfile = IO.readlines(gemfile_path)
|
130
|
+
|
131
|
+
Bundler.ui.info "Removing gems from #{gemfile_path}"
|
132
|
+
|
133
|
+
# evaluate the Gemfile we have
|
134
|
+
builder = Dsl.new
|
135
|
+
builder.eval_gemfile(gemfile_path)
|
136
|
+
|
137
|
+
removed_deps = remove_gems_from_dependencies(builder, @deps, gemfile_path)
|
138
|
+
|
139
|
+
# abort the opertion if no gems were removed
|
140
|
+
# no need to operate on gemfile furthur
|
141
|
+
return [] if removed_deps.empty?
|
142
|
+
|
143
|
+
cleaned_gemfile = remove_gems_from_gemfile(@deps, gemfile_path)
|
144
|
+
|
145
|
+
SharedHelpers.write_to_gemfile(gemfile_path, cleaned_gemfile)
|
146
|
+
|
147
|
+
# check for errors
|
148
|
+
# including extra gems being removed
|
149
|
+
# or some gems not being removed
|
150
|
+
# and return the actual removed deps
|
151
|
+
cross_check_for_errors(gemfile_path, builder.dependencies, removed_deps, initial_gemfile)
|
152
|
+
end
|
153
|
+
|
154
|
+
# @param [Dsl] builder Dsl object of current Gemfile.
|
155
|
+
# @param [Array] gems Array of names of gems to be removed.
|
156
|
+
# @param [Pathname] path of the Gemfile
|
157
|
+
# @return [Array] removed_deps Array of removed dependencies.
|
158
|
+
def remove_gems_from_dependencies(builder, gems, gemfile_path)
|
159
|
+
removed_deps = []
|
160
|
+
|
161
|
+
gems.each do |gem_name|
|
162
|
+
deleted_dep = builder.dependencies.find {|d| d.name == gem_name }
|
163
|
+
|
164
|
+
if deleted_dep.nil?
|
165
|
+
raise GemfileError, "`#{gem_name}` is not specified in #{gemfile_path} so it could not be removed."
|
166
|
+
end
|
167
|
+
|
168
|
+
builder.dependencies.delete(deleted_dep)
|
169
|
+
|
170
|
+
removed_deps << deleted_dep
|
171
|
+
end
|
172
|
+
|
173
|
+
removed_deps
|
174
|
+
end
|
175
|
+
|
176
|
+
# @param [Array] gems Array of names of gems to be removed.
|
177
|
+
# @param [Pathname] gemfile_path The Gemfile from which to remove dependencies.
|
178
|
+
def remove_gems_from_gemfile(gems, gemfile_path)
|
179
|
+
patterns = /gem\s+(['"])#{Regexp.union(gems)}\1|gem\s*\((['"])#{Regexp.union(gems)}\2\)/
|
180
|
+
|
181
|
+
# remove lines which match the regex
|
182
|
+
new_gemfile = IO.readlines(gemfile_path).reject {|line| line.match(patterns) }
|
183
|
+
|
184
|
+
# remove lone \n and append them with other strings
|
185
|
+
new_gemfile.each_with_index do |_line, index|
|
186
|
+
if new_gemfile[index + 1] == "\n"
|
187
|
+
new_gemfile[index] += new_gemfile[index + 1]
|
188
|
+
new_gemfile.delete_at(index + 1)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
%w[group source env install_if].each {|block| remove_nested_blocks(new_gemfile, block) }
|
193
|
+
|
194
|
+
new_gemfile.join.chomp
|
195
|
+
end
|
196
|
+
|
197
|
+
# @param [Array] gemfile Array of gemfile contents.
|
198
|
+
# @param [String] block_name Name of block name to look for.
|
199
|
+
def remove_nested_blocks(gemfile, block_name)
|
200
|
+
nested_blocks = 0
|
201
|
+
|
202
|
+
# count number of nested blocks
|
203
|
+
gemfile.each_with_index {|line, index| nested_blocks += 1 if !gemfile[index + 1].nil? && gemfile[index + 1].include?(block_name) && line.include?(block_name) }
|
204
|
+
|
205
|
+
while nested_blocks >= 0
|
206
|
+
nested_blocks -= 1
|
207
|
+
|
208
|
+
gemfile.each_with_index do |line, index|
|
209
|
+
next unless !line.nil? && line.include?(block_name)
|
210
|
+
if gemfile[index + 1] =~ /^\s*end\s*$/
|
211
|
+
gemfile[index] = nil
|
212
|
+
gemfile[index + 1] = nil
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
gemfile.compact!
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# @param [Pathname] gemfile_path The Gemfile from which to remove dependencies.
|
221
|
+
# @param [Array] original_deps Array of original dependencies.
|
222
|
+
# @param [Array] removed_deps Array of removed dependencies.
|
223
|
+
# @param [Array] initial_gemfile Contents of original Gemfile before any operation.
|
224
|
+
def cross_check_for_errors(gemfile_path, original_deps, removed_deps, initial_gemfile)
|
225
|
+
# evalute the new gemfile to look for any failure cases
|
226
|
+
builder = Dsl.new
|
227
|
+
builder.eval_gemfile(gemfile_path)
|
228
|
+
|
229
|
+
# record gems which were removed but not requested
|
230
|
+
extra_removed_gems = original_deps - builder.dependencies
|
231
|
+
|
232
|
+
# if some extra gems were removed then raise error
|
233
|
+
# and revert Gemfile to original
|
234
|
+
unless extra_removed_gems.empty?
|
235
|
+
SharedHelpers.write_to_gemfile(gemfile_path, initial_gemfile.join)
|
236
|
+
|
237
|
+
raise InvalidOption, "Gems could not be removed. #{extra_removed_gems.join(", ")} would also have been removed. Bundler cannot continue."
|
238
|
+
end
|
239
|
+
|
240
|
+
# record gems which could not be removed due to some reasons
|
241
|
+
errored_deps = builder.dependencies.select {|d| d.gemfile == gemfile_path } & removed_deps.select {|d| d.gemfile == gemfile_path }
|
242
|
+
|
243
|
+
show_warning "#{errored_deps.map(&:name).join(", ")} could not be removed." unless errored_deps.empty?
|
244
|
+
|
245
|
+
# return actual removed dependencies
|
246
|
+
removed_deps - errored_deps
|
247
|
+
end
|
248
|
+
|
249
|
+
def show_warning(message)
|
250
|
+
Bundler.ui.info Bundler.ui.add_color(message, :yellow)
|
251
|
+
end
|
93
252
|
end
|
94
253
|
end
|
@@ -21,7 +21,7 @@ module Bundler
|
|
21
21
|
raise
|
22
22
|
rescue Errno::ENOSPC
|
23
23
|
return false, out_of_space_message
|
24
|
-
rescue => e
|
24
|
+
rescue StandardError => e
|
25
25
|
return false, specific_failure_message(e)
|
26
26
|
end
|
27
27
|
|
@@ -44,7 +44,14 @@ module Bundler
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def gem_install_message
|
47
|
-
|
47
|
+
source = spec.source
|
48
|
+
return unless source.respond_to?(:remotes)
|
49
|
+
|
50
|
+
if source.remotes.size == 1
|
51
|
+
"Make sure that `gem install #{spec.name} -v '#{spec.version}' --source '#{source.remotes.first}'` succeeds before bundling."
|
52
|
+
else
|
53
|
+
"Make sure that `gem install #{spec.name} -v '#{spec.version}'` succeeds before bundling."
|
54
|
+
end
|
48
55
|
end
|
49
56
|
|
50
57
|
def spec_settings
|
@@ -87,6 +87,7 @@ module Bundler
|
|
87
87
|
@force = force
|
88
88
|
@specs = all_specs.map {|s| SpecInstallation.new(s) }
|
89
89
|
@spec_set = all_specs
|
90
|
+
@rake = @specs.find {|s| s.name == "rake" }
|
90
91
|
end
|
91
92
|
|
92
93
|
def call
|
@@ -155,12 +156,13 @@ module Bundler
|
|
155
156
|
end
|
156
157
|
|
157
158
|
def do_install(spec_install, worker_num)
|
159
|
+
Plugin.hook(Plugin::Events::GEM_BEFORE_INSTALL, spec_install)
|
158
160
|
gem_installer = Bundler::GemInstaller.new(
|
159
161
|
spec_install.spec, @installer, @standalone, worker_num, @force
|
160
162
|
)
|
161
163
|
success, message = begin
|
162
164
|
gem_installer.install_from_spec
|
163
|
-
rescue => e
|
165
|
+
rescue RuntimeError => e
|
164
166
|
raise e, "#{e}\n\n#{require_tree_for_spec(spec_install.spec)}"
|
165
167
|
end
|
166
168
|
if success
|
@@ -170,6 +172,7 @@ module Bundler
|
|
170
172
|
spec_install.state = :failed
|
171
173
|
spec_install.error = "#{message}\n\n#{require_tree_for_spec(spec_install.spec)}"
|
172
174
|
end
|
175
|
+
Plugin.hook(Plugin::Events::GEM_AFTER_INSTALL, spec_install)
|
173
176
|
spec_install
|
174
177
|
end
|
175
178
|
|
@@ -218,6 +221,8 @@ module Bundler
|
|
218
221
|
# are installed.
|
219
222
|
def enqueue_specs
|
220
223
|
@specs.select(&:ready_to_enqueue?).each do |spec|
|
224
|
+
next if @rake && !@rake.installed? && spec.name != @rake.name
|
225
|
+
|
221
226
|
if spec.dependencies_installed? @specs
|
222
227
|
spec.state = :enqueued
|
223
228
|
worker_pool.enq spec
|
data/lib/bundler/installer.rb
CHANGED
@@ -21,8 +21,9 @@ module Bundler
|
|
21
21
|
# For more information see the #run method on this class.
|
22
22
|
def self.install(root, definition, options = {})
|
23
23
|
installer = new(root, definition)
|
24
|
-
Plugin.hook(
|
24
|
+
Plugin.hook(Plugin::Events::GEM_BEFORE_INSTALL_ALL, definition.dependencies)
|
25
25
|
installer.run(options)
|
26
|
+
Plugin.hook(Plugin::Events::GEM_AFTER_INSTALL_ALL, definition.dependencies)
|
26
27
|
installer
|
27
28
|
end
|
28
29
|
|
@@ -70,7 +71,7 @@ module Bundler
|
|
70
71
|
create_bundle_path
|
71
72
|
|
72
73
|
ProcessLock.lock do
|
73
|
-
if Bundler.
|
74
|
+
if Bundler.frozen_bundle?
|
74
75
|
@definition.ensure_equivalent_gemfile_and_lockfile(options[:deployment])
|
75
76
|
end
|
76
77
|
|
@@ -90,7 +91,7 @@ module Bundler
|
|
90
91
|
end
|
91
92
|
install(options)
|
92
93
|
|
93
|
-
lock unless Bundler.
|
94
|
+
lock unless Bundler.frozen_bundle?
|
94
95
|
Standalone.new(options[:standalone], @definition).generate if options[:standalone]
|
95
96
|
end
|
96
97
|
end
|
@@ -135,7 +136,11 @@ module Bundler
|
|
135
136
|
end
|
136
137
|
|
137
138
|
File.open(binstub_path, "w", 0o777 & ~File.umask) do |f|
|
138
|
-
|
139
|
+
if RUBY_VERSION >= "2.6"
|
140
|
+
f.puts ERB.new(template, :trim_mode => "-").result(binding)
|
141
|
+
else
|
142
|
+
f.puts ERB.new(template, nil, "-").result(binding)
|
143
|
+
end
|
139
144
|
end
|
140
145
|
end
|
141
146
|
|
@@ -171,7 +176,11 @@ module Bundler
|
|
171
176
|
executable_path = Pathname(spec.full_gem_path).join(spec.bindir, executable).relative_path_from(bin_path)
|
172
177
|
executable_path = executable_path
|
173
178
|
File.open "#{bin_path}/#{executable}", "w", 0o755 do |f|
|
174
|
-
|
179
|
+
if RUBY_VERSION >= "2.6"
|
180
|
+
f.puts ERB.new(template, :trim_mode => "-").result(binding)
|
181
|
+
else
|
182
|
+
f.puts ERB.new(template, nil, "-").result(binding)
|
183
|
+
end
|
175
184
|
end
|
176
185
|
end
|
177
186
|
end
|
@@ -184,14 +193,36 @@ module Bundler
|
|
184
193
|
# installation is SO MUCH FASTER. so we let people opt in.
|
185
194
|
def install(options)
|
186
195
|
force = options["force"]
|
187
|
-
jobs = options
|
188
|
-
|
189
|
-
|
196
|
+
jobs = installation_parallelization(options)
|
197
|
+
install_in_parallel jobs, options[:standalone], force
|
198
|
+
end
|
199
|
+
|
200
|
+
def installation_parallelization(options)
|
201
|
+
if jobs = options.delete(:jobs)
|
202
|
+
return jobs
|
203
|
+
end
|
204
|
+
|
205
|
+
return 1 unless can_install_in_parallel?
|
206
|
+
|
207
|
+
auto_config_jobs = Bundler.feature_flag.auto_config_jobs?
|
208
|
+
if jobs = Bundler.settings[:jobs]
|
209
|
+
if auto_config_jobs
|
210
|
+
jobs
|
190
211
|
else
|
191
|
-
1
|
212
|
+
[jobs.pred, 1].max
|
192
213
|
end
|
214
|
+
elsif auto_config_jobs
|
215
|
+
processor_count
|
216
|
+
else
|
217
|
+
1
|
193
218
|
end
|
194
|
-
|
219
|
+
end
|
220
|
+
|
221
|
+
def processor_count
|
222
|
+
require "etc"
|
223
|
+
Etc.nprocessors
|
224
|
+
rescue
|
225
|
+
1
|
195
226
|
end
|
196
227
|
|
197
228
|
def load_plugins
|
@@ -80,7 +80,7 @@ module Bundler
|
|
80
80
|
"To use the platform-specific version of the gem, run `bundle config specific_platform true` and install again."
|
81
81
|
search = source.specs.search(self).last
|
82
82
|
end
|
83
|
-
search.dependencies = dependencies if search.is_a?(RemoteSpecification) || search.is_a?(EndpointSpecification)
|
83
|
+
search.dependencies = dependencies if search && (search.is_a?(RemoteSpecification) || search.is_a?(EndpointSpecification))
|
84
84
|
search
|
85
85
|
end
|
86
86
|
end
|
data/lib/bundler/mirror.rb
CHANGED
@@ -152,7 +152,7 @@ module Bundler
|
|
152
152
|
socket.connect_nonblock(address)
|
153
153
|
rescue Errno::EINPROGRESS
|
154
154
|
wait_for_writtable_socket(socket, address, timeout)
|
155
|
-
rescue # Connection failed somehow, again
|
155
|
+
rescue RuntimeError # Connection failed somehow, again
|
156
156
|
false
|
157
157
|
end
|
158
158
|
end
|
@@ -172,7 +172,7 @@ module Bundler
|
|
172
172
|
socket.connect_nonblock(address)
|
173
173
|
rescue Errno::EISCONN
|
174
174
|
true
|
175
|
-
rescue # Connection failed
|
175
|
+
rescue StandardError # Connection failed
|
176
176
|
false
|
177
177
|
end
|
178
178
|
end
|