bundler 1.0.21 → 1.1.rc
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +7 -0
- data/CHANGELOG.md +153 -1
- data/README.md +3 -3
- data/Rakefile +15 -27
- data/bin/bundle +7 -0
- data/bundler.gemspec +1 -1
- data/lib/bundler/cli.rb +126 -45
- data/lib/bundler/definition.rb +22 -5
- data/lib/bundler/dep_proxy.rb +35 -0
- data/lib/bundler/dsl.rb +17 -34
- data/lib/bundler/endpoint_specification.rb +69 -0
- data/lib/bundler/fetcher.rb +221 -0
- data/lib/bundler/gem_helper.rb +0 -1
- data/lib/bundler/gem_helpers.rb +23 -0
- data/lib/bundler/index.rb +77 -38
- data/lib/bundler/installer.rb +43 -1
- data/lib/bundler/man/bundle-benchmark +19 -0
- data/lib/bundler/man/bundle-benchmark.txt +27 -0
- data/lib/bundler/man/bundle-config +1 -1
- data/lib/bundler/man/bundle-config.txt +3 -3
- data/lib/bundler/man/bundle-install +288 -0
- data/lib/bundler/man/bundle-install.txt +74 -79
- data/lib/bundler/man/bundle-package +1 -1
- data/lib/bundler/man/bundle-package.txt +1 -1
- data/lib/bundler/man/bundle-update +1 -1
- data/lib/bundler/man/bundle-update.txt +41 -41
- data/lib/bundler/man/gemfile.5 +6 -7
- data/lib/bundler/man/gemfile.5.txt +9 -9
- data/lib/bundler/match_platform.rb +13 -0
- data/lib/bundler/remote_specification.rb +6 -8
- data/lib/bundler/resolver.rb +32 -19
- data/lib/bundler/rubygems_ext.rb +2 -86
- data/lib/bundler/rubygems_integration.rb +35 -0
- data/lib/bundler/runtime.rb +84 -1
- data/lib/bundler/source.rb +85 -88
- data/lib/bundler/spec_set.rb +2 -0
- data/lib/bundler/templates/Executable +1 -1
- data/lib/bundler/templates/newgem/Gemfile.tt +1 -1
- data/lib/bundler/templates/newgem/Rakefile.tt +1 -0
- data/lib/bundler/templates/newgem/bin/newgem.tt +1 -1
- data/lib/bundler/templates/newgem/gitignore.tt +14 -1
- data/lib/bundler/templates/newgem/newgem.gemspec.tt +13 -20
- data/lib/bundler/ui.rb +32 -17
- data/lib/bundler/vendor/net/http/faster.rb +27 -0
- data/lib/bundler/vendor/net/http/persistent.rb +468 -0
- data/lib/bundler/version.rb +1 -1
- data/lib/bundler.rb +56 -23
- data/man/bundle-install.ronn +7 -0
- data/man/bundle.ronn +3 -0
- data/man/gemfile.5.ronn +6 -6
- data/spec/bundler/dsl_spec.rb +22 -0
- data/spec/bundler/source_spec.rb +25 -0
- data/spec/install/deprecated_spec.rb +2 -3
- data/spec/install/gems/dependency_api_spec.rb +358 -0
- data/spec/install/gems/flex_spec.rb +1 -1
- data/spec/install/gems/groups_spec.rb +17 -8
- data/spec/install/gems/platform_spec.rb +16 -0
- data/spec/install/gems/post_install_spec.rb +47 -0
- data/spec/install/gems/simple_case_spec.rb +61 -64
- data/spec/install/gems/standalone_spec.rb +238 -0
- data/spec/install/git_spec.rb +62 -0
- data/spec/other/check_spec.rb +30 -0
- data/spec/other/clean_spec.rb +397 -0
- data/spec/other/exec_spec.rb +0 -29
- data/spec/other/newgem_spec.rb +39 -0
- data/spec/other/outdated_spec.rb +93 -0
- data/spec/other/show_spec.rb +6 -0
- data/spec/quality_spec.rb +1 -1
- data/spec/realworld/edgecases_spec.rb +12 -0
- data/spec/runtime/executable_spec.rb +10 -0
- data/spec/runtime/require_spec.rb +8 -9
- data/spec/runtime/with_clean_env_spec.rb +60 -7
- data/spec/spec_helper.rb +8 -1
- data/spec/support/artifice/endopint_marshal_fail_basic_authentication.rb +13 -0
- data/spec/support/artifice/endpoint.rb +54 -0
- data/spec/support/artifice/endpoint_500.rb +37 -0
- data/spec/support/artifice/endpoint_api_missing.rb +16 -0
- data/spec/support/artifice/endpoint_basic_authentication.rb +13 -0
- data/spec/support/artifice/endpoint_extra.rb +27 -0
- data/spec/support/artifice/endpoint_extra_missing.rb +15 -0
- data/spec/support/artifice/endpoint_fallback.rb +18 -0
- data/spec/support/artifice/endpoint_marshal_fail.rb +11 -0
- data/spec/support/artifice/endpoint_redirect.rb +15 -0
- data/spec/support/builders.rb +7 -0
- data/spec/support/fakeweb/rack-1.0.0.marshal +2 -0
- data/spec/support/fakeweb/windows.rb +23 -0
- data/spec/support/helpers.rb +36 -3
- data/spec/support/path.rb +2 -0
- data/spec/support/rubygems_ext.rb +3 -3
- metadata +48 -74
|
@@ -12,11 +12,11 @@ module Bundler
|
|
|
12
12
|
attr_reader :name, :version, :platform
|
|
13
13
|
attr_accessor :source
|
|
14
14
|
|
|
15
|
-
def initialize(name, version, platform,
|
|
16
|
-
@name
|
|
17
|
-
@version
|
|
18
|
-
@platform
|
|
19
|
-
@
|
|
15
|
+
def initialize(name, version, platform, spec_fetcher)
|
|
16
|
+
@name = name
|
|
17
|
+
@version = version
|
|
18
|
+
@platform = platform
|
|
19
|
+
@spec_fetcher = spec_fetcher
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
# Needed before installs, since the arch matters then and quick
|
|
@@ -43,9 +43,7 @@ module Bundler
|
|
|
43
43
|
private
|
|
44
44
|
|
|
45
45
|
def _remote_specification
|
|
46
|
-
@specification ||=
|
|
47
|
-
Gem::SpecFetcher.new.fetch_spec([@name, @version, @platform], URI(@source_uri.to_s))
|
|
48
|
-
end
|
|
46
|
+
@specification ||= @spec_fetcher.fetch_spec([@name, @version, @platform])
|
|
49
47
|
end
|
|
50
48
|
|
|
51
49
|
def method_missing(method, *args, &blk)
|
data/lib/bundler/resolver.rb
CHANGED
|
@@ -137,7 +137,7 @@ module Bundler
|
|
|
137
137
|
@stack = []
|
|
138
138
|
@base = base
|
|
139
139
|
@index = index
|
|
140
|
-
@
|
|
140
|
+
@deps_for = {}
|
|
141
141
|
@missing_gems = Hash.new(0)
|
|
142
142
|
@source_requirements = source_requirements
|
|
143
143
|
end
|
|
@@ -248,11 +248,11 @@ module Bundler
|
|
|
248
248
|
conflicts = Set.new
|
|
249
249
|
|
|
250
250
|
# Fetch all gem versions matching the requirement
|
|
251
|
-
#
|
|
252
|
-
# TODO: Warn / error when no matching versions are found.
|
|
253
251
|
matching_versions = search(current)
|
|
254
252
|
|
|
253
|
+
# If we found no versions that match the current requirement
|
|
255
254
|
if matching_versions.empty?
|
|
255
|
+
# If this is a top-level Gemfile requirement
|
|
256
256
|
if current.required_by.empty?
|
|
257
257
|
if base = @base[current.name] and !base.empty?
|
|
258
258
|
version = base.first.version
|
|
@@ -271,13 +271,14 @@ module Bundler
|
|
|
271
271
|
end
|
|
272
272
|
else
|
|
273
273
|
message = "Could not find gem '#{current}' "
|
|
274
|
-
if @index.
|
|
274
|
+
if @index.source_types.include?(Bundler::Source::Rubygems)
|
|
275
275
|
message << "in any of the gem sources listed in your Gemfile."
|
|
276
276
|
else
|
|
277
277
|
message << "in the gems available on this machine."
|
|
278
278
|
end
|
|
279
279
|
end
|
|
280
280
|
raise GemNotFound, message
|
|
281
|
+
# This is not a top-level Gemfile requirement
|
|
281
282
|
else
|
|
282
283
|
@errors[current.name] = [nil, current]
|
|
283
284
|
end
|
|
@@ -333,8 +334,13 @@ module Bundler
|
|
|
333
334
|
length = @stack.length
|
|
334
335
|
@stack << requirement.name
|
|
335
336
|
retval = catch(requirement.name) do
|
|
337
|
+
# clear the search cache since the catch means we couldn't meet the
|
|
338
|
+
# requirement we need with the current constraints on search
|
|
339
|
+
clear_search_cache
|
|
340
|
+
# try to resolve the next option
|
|
336
341
|
resolve(reqs, activated)
|
|
337
342
|
end
|
|
343
|
+
|
|
338
344
|
# Since we're doing a lot of throw / catches. A push does not necessarily match
|
|
339
345
|
# up to a pop. So, we simply slice the stack back to what it was before the catch
|
|
340
346
|
# block.
|
|
@@ -343,7 +349,11 @@ module Bundler
|
|
|
343
349
|
end
|
|
344
350
|
|
|
345
351
|
def gems_size(dep)
|
|
346
|
-
|
|
352
|
+
search(dep).size
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def clear_search_cache
|
|
356
|
+
@deps_for = {}
|
|
347
357
|
end
|
|
348
358
|
|
|
349
359
|
def search(dep)
|
|
@@ -353,22 +363,25 @@ module Bundler
|
|
|
353
363
|
else
|
|
354
364
|
d = dep.dep
|
|
355
365
|
end
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
+
|
|
367
|
+
@deps_for[d.hash] ||= begin
|
|
368
|
+
index = @source_requirements[d.name] || @index
|
|
369
|
+
results = index.search(d, @base[d.name])
|
|
370
|
+
|
|
371
|
+
if results.any?
|
|
372
|
+
version = results.first.version
|
|
373
|
+
nested = [[]]
|
|
374
|
+
results.each do |spec|
|
|
375
|
+
if spec.version != version
|
|
376
|
+
nested << []
|
|
377
|
+
version = spec.version
|
|
378
|
+
end
|
|
379
|
+
nested.last << spec
|
|
366
380
|
end
|
|
367
|
-
nested.
|
|
381
|
+
deps = nested.map{|a| SpecGroup.new(a) }.select{|sg| sg.for?(dep.__platform) }
|
|
382
|
+
else
|
|
383
|
+
deps = []
|
|
368
384
|
end
|
|
369
|
-
nested.map { |a| SpecGroup.new(a) }.select { |sg| sg.for?(dep.__platform) }
|
|
370
|
-
else
|
|
371
|
-
[]
|
|
372
385
|
end
|
|
373
386
|
end
|
|
374
387
|
|
data/lib/bundler/rubygems_ext.rb
CHANGED
|
@@ -7,6 +7,7 @@ end
|
|
|
7
7
|
|
|
8
8
|
require 'rubygems'
|
|
9
9
|
require 'rubygems/specification'
|
|
10
|
+
require 'bundler/match_platform'
|
|
10
11
|
|
|
11
12
|
module Gem
|
|
12
13
|
@loaded_stacks = Hash.new { |h,k| h[k] = [] }
|
|
@@ -70,22 +71,6 @@ module Gem
|
|
|
70
71
|
dependencies - development_dependencies
|
|
71
72
|
end
|
|
72
73
|
|
|
73
|
-
def add_bundler_dependencies(*groups)
|
|
74
|
-
Bundler.ui.warn "#add_bundler_dependencies is deprecated and will " \
|
|
75
|
-
"be removed in Bundler 1.0. Instead, please use the #gemspec method " \
|
|
76
|
-
"in your Gemfile, which will pull in any dependencies specified in " \
|
|
77
|
-
"your gemspec"
|
|
78
|
-
|
|
79
|
-
groups = [:default] if groups.empty?
|
|
80
|
-
Bundler.definition.dependencies.each do |dep|
|
|
81
|
-
if dep.groups.include?(:development)
|
|
82
|
-
self.add_development_dependency(dep.name, dep.requirement.to_s)
|
|
83
|
-
elsif (dep.groups & groups).any?
|
|
84
|
-
self.add_dependency(dep.name, dep.requirement.to_s)
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
89
74
|
private
|
|
90
75
|
|
|
91
76
|
def dependencies_to_gemfile(dependencies, group = nil)
|
|
@@ -159,79 +144,10 @@ module Gem
|
|
|
159
144
|
|
|
160
145
|
alias eql? ==
|
|
161
146
|
end
|
|
162
|
-
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
module Bundler
|
|
166
|
-
class DepProxy
|
|
167
|
-
|
|
168
|
-
attr_reader :required_by, :__platform, :dep
|
|
169
|
-
|
|
170
|
-
def initialize(dep, platform)
|
|
171
|
-
@dep, @__platform, @required_by = dep, platform, []
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
def hash
|
|
175
|
-
@hash ||= dep.hash
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
def ==(o)
|
|
179
|
-
dep == o.dep && __platform == o.__platform
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
alias eql? ==
|
|
183
|
-
|
|
184
|
-
def type
|
|
185
|
-
@dep.type
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
def to_s
|
|
189
|
-
"#{name} (#{requirement}) #{__platform}"
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
private
|
|
193
|
-
|
|
194
|
-
def method_missing(*args)
|
|
195
|
-
@dep.send(*args)
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
module GemHelpers
|
|
201
|
-
|
|
202
|
-
GENERIC_CACHE = {}
|
|
203
|
-
GENERICS = [
|
|
204
|
-
Gem::Platform::JAVA,
|
|
205
|
-
Gem::Platform::MSWIN,
|
|
206
|
-
Gem::Platform::MINGW,
|
|
207
|
-
Gem::Platform::RUBY
|
|
208
|
-
]
|
|
209
|
-
|
|
210
|
-
def generic(p)
|
|
211
|
-
return p if p == Gem::Platform::RUBY
|
|
212
|
-
|
|
213
|
-
GENERIC_CACHE[p] ||= begin
|
|
214
|
-
found = GENERICS.find do |p2|
|
|
215
|
-
p2.is_a?(Gem::Platform) && p.os == p2.os
|
|
216
|
-
end
|
|
217
|
-
found || Gem::Platform::RUBY
|
|
218
|
-
end
|
|
219
|
-
end
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
module MatchPlatform
|
|
223
|
-
include GemHelpers
|
|
224
|
-
|
|
225
|
-
def match_platform(p)
|
|
226
|
-
Gem::Platform::RUBY == platform or
|
|
227
|
-
platform.nil? or p == platform or
|
|
228
|
-
generic(Gem::Platform.new(platform)) == p
|
|
229
|
-
end
|
|
230
|
-
end
|
|
231
147
|
end
|
|
232
148
|
|
|
233
149
|
module Gem
|
|
234
150
|
class Specification
|
|
235
|
-
include Bundler::MatchPlatform
|
|
151
|
+
include ::Bundler::MatchPlatform
|
|
236
152
|
end
|
|
237
153
|
end
|
|
@@ -266,8 +266,43 @@ module Bundler
|
|
|
266
266
|
end
|
|
267
267
|
end
|
|
268
268
|
|
|
269
|
+
# This backports base_dir which replaces installation path
|
|
270
|
+
# Rubygems 1.8+
|
|
271
|
+
def backport_base_dir
|
|
272
|
+
Gem::Specification.send(:define_method, :base_dir) do
|
|
273
|
+
installation_path
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def backport_cache_file
|
|
278
|
+
Gem::Specification.send(:define_method, :cache_dir) do
|
|
279
|
+
@cache_dir ||= File.join base_dir, "cache"
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
Gem::Specification.send(:define_method, :cache_file) do
|
|
283
|
+
@cache_file ||= File.join cache_dir, "#{full_name}.gem"
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def backport_spec_file
|
|
288
|
+
Gem::Specification.send(:define_method, :spec_dir) do
|
|
289
|
+
@spec_dir ||= File.join base_dir, "specifications"
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
Gem::Specification.send(:define_method, :spec_file) do
|
|
293
|
+
@spec_file ||= File.join spec_dir, "#{full_name}.gemspec"
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
269
297
|
# Rubygems 1.4 through 1.6
|
|
270
298
|
class Legacy < RubygemsIntegration
|
|
299
|
+
def initialize
|
|
300
|
+
super
|
|
301
|
+
backport_base_dir
|
|
302
|
+
backport_cache_file
|
|
303
|
+
backport_spec_file
|
|
304
|
+
end
|
|
305
|
+
|
|
271
306
|
def stub_rubygems(specs)
|
|
272
307
|
stub_source_index137(specs)
|
|
273
308
|
end
|
data/lib/bundler/runtime.rb
CHANGED
|
@@ -69,7 +69,18 @@ module Bundler
|
|
|
69
69
|
end
|
|
70
70
|
rescue LoadError => e
|
|
71
71
|
REGEXPS.find { |r| r =~ e.message }
|
|
72
|
-
|
|
72
|
+
|
|
73
|
+
if dep.name.include?('-')
|
|
74
|
+
begin
|
|
75
|
+
namespaced_file = dep.name.gsub('-', '/')
|
|
76
|
+
Kernel.require namespaced_file
|
|
77
|
+
rescue LoadError
|
|
78
|
+
REGEXPS.find { |r| r =~ e.message }
|
|
79
|
+
raise if dep.autorequire || $1.gsub('-', '/') != namespaced_file
|
|
80
|
+
end
|
|
81
|
+
else
|
|
82
|
+
raise if dep.autorequire || $1 != required_file
|
|
83
|
+
end
|
|
73
84
|
end
|
|
74
85
|
end
|
|
75
86
|
end
|
|
@@ -119,6 +130,78 @@ module Bundler
|
|
|
119
130
|
end
|
|
120
131
|
end
|
|
121
132
|
|
|
133
|
+
def clean
|
|
134
|
+
gem_bins = Dir["#{Gem.dir}/bin/*"]
|
|
135
|
+
git_dirs = Dir["#{Gem.dir}/bundler/gems/*"]
|
|
136
|
+
git_cache_dirs = Dir["#{Gem.dir}/cache/bundler/git/*"]
|
|
137
|
+
gem_dirs = Dir["#{Gem.dir}/gems/*"]
|
|
138
|
+
gem_files = Dir["#{Gem.dir}/cache/*.gem"]
|
|
139
|
+
gemspec_files = Dir["#{Gem.dir}/specifications/*.gemspec"]
|
|
140
|
+
spec_gem_paths = []
|
|
141
|
+
spec_git_paths = []
|
|
142
|
+
spec_git_cache_dirs = []
|
|
143
|
+
spec_gem_executables = []
|
|
144
|
+
spec_cache_paths = []
|
|
145
|
+
spec_gemspec_paths = []
|
|
146
|
+
specs.each do |spec|
|
|
147
|
+
spec_gem_paths << spec.full_gem_path
|
|
148
|
+
# need to check here in case gems are nested like for the rails git repo
|
|
149
|
+
md = %r{(.+bundler/gems/.+-[a-f0-9]{12})}.match(spec.full_gem_path)
|
|
150
|
+
spec_git_paths << md[1] if md
|
|
151
|
+
spec_gem_executables << spec.executables.collect do |executable|
|
|
152
|
+
"#{Gem.dir}/#{spec.bindir}/#{executable}"
|
|
153
|
+
end
|
|
154
|
+
spec_cache_paths << spec.cache_file
|
|
155
|
+
spec_gemspec_paths << spec.spec_file
|
|
156
|
+
spec_git_cache_dirs << spec.source.cache_path.to_s if spec.source.is_a?(Bundler::Source::Git)
|
|
157
|
+
end
|
|
158
|
+
spec_gem_paths.uniq!
|
|
159
|
+
spec_gem_executables.flatten!
|
|
160
|
+
|
|
161
|
+
stale_gem_bins = gem_bins - spec_gem_executables
|
|
162
|
+
stale_git_dirs = git_dirs - spec_git_paths
|
|
163
|
+
stale_git_cache_dirs = git_cache_dirs - spec_git_cache_dirs
|
|
164
|
+
stale_gem_dirs = gem_dirs - spec_gem_paths
|
|
165
|
+
stale_gem_files = gem_files - spec_cache_paths
|
|
166
|
+
stale_gemspec_files = gemspec_files - spec_gemspec_paths
|
|
167
|
+
|
|
168
|
+
stale_gem_bins.each {|bin| FileUtils.rm(bin) }
|
|
169
|
+
output = stale_gem_dirs.collect do |gem_dir|
|
|
170
|
+
full_name = Pathname.new(gem_dir).basename.to_s
|
|
171
|
+
|
|
172
|
+
FileUtils.rm_rf(gem_dir)
|
|
173
|
+
|
|
174
|
+
parts = full_name.split('-')
|
|
175
|
+
name = parts[0..-2].join('-')
|
|
176
|
+
version = parts.last
|
|
177
|
+
output = "#{name} (#{version})"
|
|
178
|
+
|
|
179
|
+
Bundler.ui.info "Removing #{output}"
|
|
180
|
+
|
|
181
|
+
output
|
|
182
|
+
end + stale_git_dirs.collect do |gem_dir|
|
|
183
|
+
full_name = Pathname.new(gem_dir).basename.to_s
|
|
184
|
+
|
|
185
|
+
FileUtils.rm_rf(gem_dir)
|
|
186
|
+
|
|
187
|
+
parts = full_name.split('-')
|
|
188
|
+
name = parts[0..-3].join('-')
|
|
189
|
+
revision = parts[-1]
|
|
190
|
+
version = parts[-2]
|
|
191
|
+
output = "#{name} (#{version} #{revision})"
|
|
192
|
+
|
|
193
|
+
Bundler.ui.info "Removing #{output}"
|
|
194
|
+
|
|
195
|
+
output
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
stale_gem_files.each {|file| FileUtils.rm(file) if File.exists?(file) }
|
|
199
|
+
stale_gemspec_files.each {|file| FileUtils.rm(file) if File.exists?(file) }
|
|
200
|
+
stale_git_cache_dirs.each {|dir| FileUtils.rm_rf(dir) if File.exists?(dir) }
|
|
201
|
+
|
|
202
|
+
output
|
|
203
|
+
end
|
|
204
|
+
|
|
122
205
|
private
|
|
123
206
|
|
|
124
207
|
def cache_path
|
data/lib/bundler/source.rb
CHANGED
|
@@ -10,20 +10,20 @@ module Bundler
|
|
|
10
10
|
module Source
|
|
11
11
|
# TODO: Refactor this class
|
|
12
12
|
class Rubygems
|
|
13
|
-
|
|
13
|
+
FORCE_MODERN_INDEX_LIMIT = 100 # threshold for switching back to the modern index instead of fetching every spec
|
|
14
|
+
|
|
15
|
+
attr_reader :remotes, :caches
|
|
16
|
+
attr_accessor :dependency_names
|
|
14
17
|
|
|
15
18
|
def initialize(options = {})
|
|
16
19
|
@options = options
|
|
17
20
|
@remotes = (options["remotes"] || []).map { |r| normalize_uri(r) }
|
|
21
|
+
@fetchers = {}
|
|
18
22
|
@allow_remote = false
|
|
19
23
|
@allow_cached = false
|
|
20
24
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
File.expand_path("#{x}/cache")
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
@spec_fetch_map = {}
|
|
25
|
+
@caches = [ Bundler.app_cache ] +
|
|
26
|
+
Bundler.rubygems.gem_path.map{|p| File.expand_path("#{p}/cache") }
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def remote!
|
|
@@ -70,15 +70,6 @@ module Bundler
|
|
|
70
70
|
@specs ||= fetch_specs
|
|
71
71
|
end
|
|
72
72
|
|
|
73
|
-
def fetch(spec)
|
|
74
|
-
spec, uri = @spec_fetch_map[spec.full_name]
|
|
75
|
-
if spec
|
|
76
|
-
path = download_gem_from_uri(spec, uri)
|
|
77
|
-
s = Bundler.rubygems.spec_from_gem(path)
|
|
78
|
-
spec.__swap__(s)
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
|
|
82
73
|
def install(spec)
|
|
83
74
|
if installed_specs[spec].any?
|
|
84
75
|
Bundler.ui.info "Using #{spec.name} (#{spec.version}) "
|
|
@@ -87,38 +78,43 @@ module Bundler
|
|
|
87
78
|
|
|
88
79
|
Bundler.ui.info "Installing #{spec.name} (#{spec.version}) "
|
|
89
80
|
path = cached_gem(spec)
|
|
81
|
+
if Bundler.requires_sudo?
|
|
82
|
+
install_path = Bundler.tmp
|
|
83
|
+
bin_path = install_path.join("bin")
|
|
84
|
+
else
|
|
85
|
+
install_path = Bundler.rubygems.gem_dir
|
|
86
|
+
bin_path = Bundler.system_bindir
|
|
87
|
+
end
|
|
90
88
|
|
|
91
89
|
Bundler.rubygems.preserve_paths do
|
|
90
|
+
Bundler::GemInstaller.new(path,
|
|
91
|
+
:install_dir => install_path.to_s,
|
|
92
|
+
:bin_dir => bin_path.to_s,
|
|
93
|
+
:ignore_dependencies => true,
|
|
94
|
+
:wrappers => true,
|
|
95
|
+
:env_shebang => true
|
|
96
|
+
).install
|
|
97
|
+
end
|
|
92
98
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
:ignore_dependencies => true,
|
|
96
|
-
:wrappers => true,
|
|
97
|
-
:env_shebang => true }
|
|
98
|
-
options.merge!(:bin_dir => "#{install_path}/bin") unless spec.executables.nil? || spec.executables.empty?
|
|
99
|
-
|
|
100
|
-
installer = Bundler::GemInstaller.new path, options
|
|
101
|
-
installer.install
|
|
99
|
+
if spec.post_install_message
|
|
100
|
+
Installer.post_install_messages[spec.name] = spec.post_install_message
|
|
102
101
|
end
|
|
103
102
|
|
|
104
103
|
# SUDO HAX
|
|
105
104
|
if Bundler.requires_sudo?
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
sudo "cp -R #{Bundler.tmp}/
|
|
105
|
+
Bundler.mkdir_p "#{Bundler.rubygems.gem_dir}/gems"
|
|
106
|
+
Bundler.mkdir_p "#{Bundler.rubygems.gem_dir}/specifications"
|
|
107
|
+
Bundler.sudo "cp -R #{Bundler.tmp}/gems/#{spec.full_name} #{Bundler.rubygems.gem_dir}/gems/"
|
|
108
|
+
Bundler.sudo "cp -R #{Bundler.tmp}/specifications/#{spec.full_name}.gemspec #{Bundler.rubygems.gem_dir}/specifications/"
|
|
109
109
|
spec.executables.each do |exe|
|
|
110
|
-
|
|
111
|
-
sudo "cp -R #{Bundler.tmp}/bin/#{exe} #{Bundler.
|
|
110
|
+
Bundler.mkdir_p Bundler.system_bindir
|
|
111
|
+
Bundler.sudo "cp -R #{Bundler.tmp}/bin/#{exe} #{Bundler.system_bindir}"
|
|
112
112
|
end
|
|
113
113
|
end
|
|
114
114
|
|
|
115
115
|
spec.loaded_from = "#{Bundler.rubygems.gem_dir}/specifications/#{spec.full_name}.gemspec"
|
|
116
116
|
end
|
|
117
117
|
|
|
118
|
-
def sudo(str)
|
|
119
|
-
Bundler.sudo(str)
|
|
120
|
-
end
|
|
121
|
-
|
|
122
118
|
def cache(spec)
|
|
123
119
|
cached_path = cached_gem(spec)
|
|
124
120
|
raise GemNotFound, "Missing gem file '#{spec.full_name}.gem'." unless cached_path
|
|
@@ -228,56 +224,43 @@ module Bundler
|
|
|
228
224
|
idx = Index.new
|
|
229
225
|
old = Bundler.rubygems.sources
|
|
230
226
|
|
|
227
|
+
sources = {}
|
|
231
228
|
remotes.each do |uri|
|
|
232
|
-
Bundler.
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
229
|
+
fetcher = Bundler::Fetcher.new(uri)
|
|
230
|
+
specs = fetcher.specs(dependency_names, self)
|
|
231
|
+
sources[fetcher] = specs.size
|
|
232
|
+
|
|
233
|
+
idx.use specs
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# don't need to fetch all specifications for every gem/version on
|
|
237
|
+
# the rubygems repo if there's no api endpoints to search over
|
|
238
|
+
# or it has too many specs to fetch
|
|
239
|
+
fetchers = sources.keys
|
|
240
|
+
api_fetchers = fetchers.select {|fetcher| fetcher.has_api }
|
|
241
|
+
modern_index_fetchers = fetchers - api_fetchers
|
|
242
|
+
if api_fetchers.any? && modern_index_fetchers.all? {|fetcher| sources[fetcher] < FORCE_MODERN_INDEX_LIMIT }
|
|
243
|
+
# this will fetch all the specifications on the rubygems repo
|
|
244
|
+
unmet_dependency_names = idx.unmet_dependency_names
|
|
245
|
+
unmet_dependency_names -= ['bundler'] # bundler will always be unmet
|
|
246
|
+
|
|
247
|
+
Bundler.ui.debug "Unmet Dependencies: #{unmet_dependency_names}"
|
|
248
|
+
if unmet_dependency_names.any?
|
|
249
|
+
api_fetchers.each do |fetcher|
|
|
250
|
+
idx.use fetcher.specs(unmet_dependency_names, self)
|
|
241
251
|
end
|
|
242
252
|
end
|
|
253
|
+
else
|
|
254
|
+
Bundler::Fetcher.disable_endpoint = true
|
|
255
|
+
api_fetchers.each {|fetcher| idx.use fetcher.specs([], self) }
|
|
243
256
|
end
|
|
257
|
+
|
|
244
258
|
idx
|
|
245
259
|
ensure
|
|
246
260
|
Bundler.rubygems.sources = old
|
|
247
261
|
end
|
|
248
262
|
end
|
|
249
263
|
|
|
250
|
-
def fetch_all_remote_specs(&blk)
|
|
251
|
-
begin
|
|
252
|
-
# Fetch all specs, minus prerelease specs
|
|
253
|
-
Gem::SpecFetcher.new.list(true, false).each(&blk)
|
|
254
|
-
# Then fetch the prerelease specs
|
|
255
|
-
begin
|
|
256
|
-
Gem::SpecFetcher.new.list(false, true).each(&blk)
|
|
257
|
-
rescue Gem::RemoteFetcher::FetchError
|
|
258
|
-
Bundler.ui.warn "Could not fetch prerelease specs from #{self}"
|
|
259
|
-
end
|
|
260
|
-
rescue Gem::RemoteFetcher::FetchError
|
|
261
|
-
Bundler.ui.warn "Could not reach #{self}"
|
|
262
|
-
end
|
|
263
|
-
end
|
|
264
|
-
|
|
265
|
-
def download_gem_from_uri(spec, uri)
|
|
266
|
-
spec.fetch_platform
|
|
267
|
-
|
|
268
|
-
download_path = Bundler.requires_sudo? ? Bundler.tmp : Bundler.rubygems.gem_dir
|
|
269
|
-
gem_path = "#{Bundler.rubygems.gem_dir}/cache/#{spec.full_name}.gem"
|
|
270
|
-
|
|
271
|
-
FileUtils.mkdir_p("#{download_path}/cache")
|
|
272
|
-
Bundler.rubygems.download_gem(spec, uri, download_path)
|
|
273
|
-
|
|
274
|
-
if Bundler.requires_sudo?
|
|
275
|
-
sudo "mkdir -p #{Bundler.rubygems.gem_dir}/cache"
|
|
276
|
-
sudo "mv #{Bundler.tmp}/cache/#{spec.full_name}.gem #{gem_path}"
|
|
277
|
-
end
|
|
278
|
-
|
|
279
|
-
gem_path
|
|
280
|
-
end
|
|
281
264
|
end
|
|
282
265
|
|
|
283
266
|
class Path
|
|
@@ -381,7 +364,7 @@ module Bundler
|
|
|
381
364
|
index
|
|
382
365
|
end
|
|
383
366
|
|
|
384
|
-
def local_specs
|
|
367
|
+
def local_specs(*)
|
|
385
368
|
@local_specs ||= load_spec_files
|
|
386
369
|
end
|
|
387
370
|
|
|
@@ -456,8 +439,11 @@ module Bundler
|
|
|
456
439
|
gem_file = Dir.chdir(gem_dir){ Gem::Builder.new(spec).build }
|
|
457
440
|
|
|
458
441
|
installer = Installer.new(spec, :env_shebang => false)
|
|
442
|
+
run_hooks(:pre_install, installer)
|
|
459
443
|
installer.build_extensions
|
|
444
|
+
run_hooks(:post_build, installer)
|
|
460
445
|
installer.generate_bin
|
|
446
|
+
run_hooks(:post_install, installer)
|
|
461
447
|
rescue Gem::InvalidSpecificationException => e
|
|
462
448
|
Bundler.ui.warn "\n#{spec.name} at #{spec.full_gem_path} did not have a valid gemspec.\n" \
|
|
463
449
|
"This prevents bundler from installing bins or native extensions, but " \
|
|
@@ -474,6 +460,18 @@ module Bundler
|
|
|
474
460
|
Dir.chdir(gem_dir){ FileUtils.rm_rf(gem_file) if gem_file && File.exist?(gem_file) }
|
|
475
461
|
end
|
|
476
462
|
|
|
463
|
+
def run_hooks(type, installer)
|
|
464
|
+
hooks_meth = "#{type}_hooks"
|
|
465
|
+
return unless Gem.respond_to?(hooks_meth)
|
|
466
|
+
Gem.send(hooks_meth).each do |hook|
|
|
467
|
+
result = hook.call(installer)
|
|
468
|
+
if result == false
|
|
469
|
+
location = " at #{$1}" if hook.inspect =~ /@(.*:\d+)/
|
|
470
|
+
message = "#{type} hook#{location} failed for #{installer.spec.full_name}"
|
|
471
|
+
raise Gem::InstallError, message
|
|
472
|
+
end
|
|
473
|
+
end
|
|
474
|
+
end
|
|
477
475
|
end
|
|
478
476
|
|
|
479
477
|
class Git < Path
|
|
@@ -545,7 +543,7 @@ module Bundler
|
|
|
545
543
|
end
|
|
546
544
|
|
|
547
545
|
# TODO: actually cache git specs
|
|
548
|
-
def specs
|
|
546
|
+
def specs(*)
|
|
549
547
|
if allow_git_ops? && !@update
|
|
550
548
|
# Start by making sure the git cache is up to date
|
|
551
549
|
cache
|
|
@@ -572,6 +570,17 @@ module Bundler
|
|
|
572
570
|
raise GitError, "#{to_s} is not checked out. Please run `bundle install`"
|
|
573
571
|
end
|
|
574
572
|
|
|
573
|
+
def cache_path
|
|
574
|
+
@cache_path ||= begin
|
|
575
|
+
git_scope = "#{base_name}-#{uri_hash}"
|
|
576
|
+
|
|
577
|
+
if Bundler.requires_sudo?
|
|
578
|
+
Bundler.user_bundle_path.join("cache/git", git_scope)
|
|
579
|
+
else
|
|
580
|
+
Bundler.cache.join("git", git_scope)
|
|
581
|
+
end
|
|
582
|
+
end
|
|
583
|
+
end
|
|
575
584
|
private
|
|
576
585
|
|
|
577
586
|
def git(command)
|
|
@@ -628,18 +637,6 @@ module Bundler
|
|
|
628
637
|
end
|
|
629
638
|
end
|
|
630
639
|
|
|
631
|
-
def cache_path
|
|
632
|
-
@cache_path ||= begin
|
|
633
|
-
git_scope = "#{base_name}-#{uri_hash}"
|
|
634
|
-
|
|
635
|
-
if Bundler.requires_sudo?
|
|
636
|
-
Bundler.user_bundle_path.join("cache/git", git_scope)
|
|
637
|
-
else
|
|
638
|
-
Bundler.cache.join("git", git_scope)
|
|
639
|
-
end
|
|
640
|
-
end
|
|
641
|
-
end
|
|
642
|
-
|
|
643
640
|
def cache
|
|
644
641
|
if cached?
|
|
645
642
|
return if has_revision_cached?
|
data/lib/bundler/spec_set.rb
CHANGED
|
@@ -79,8 +79,10 @@ module Bundler
|
|
|
79
79
|
|
|
80
80
|
def materialize(deps, missing_specs = nil)
|
|
81
81
|
materialized = self.for(deps, [], false, true).to_a
|
|
82
|
+
deps = materialized.map {|s| s.name }.uniq
|
|
82
83
|
materialized.map! do |s|
|
|
83
84
|
next s unless s.is_a?(LazySpecification)
|
|
85
|
+
s.source.dependency_names = deps if s.source.respond_to?(:dependency_names=)
|
|
84
86
|
spec = s.__materialize__
|
|
85
87
|
if missing_specs
|
|
86
88
|
missing_specs << s unless spec
|