bundler 1.1.pre.4 → 1.1.pre.5

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.

Files changed (65) hide show
  1. data/.travis.yml +1 -0
  2. data/CHANGELOG.md +51 -2
  3. data/ISSUES.md +25 -11
  4. data/README.md +3 -3
  5. data/Rakefile +44 -48
  6. data/lib/bundler.rb +21 -20
  7. data/lib/bundler/cli.rb +46 -11
  8. data/lib/bundler/definition.rb +6 -4
  9. data/lib/bundler/dependency.rb +5 -0
  10. data/lib/bundler/dsl.rb +1 -7
  11. data/lib/bundler/endpoint_specification.rb +22 -0
  12. data/lib/bundler/fetcher.rb +76 -22
  13. data/lib/bundler/gem_helper.rb +2 -7
  14. data/lib/bundler/gem_tasks.rb +2 -0
  15. data/lib/bundler/index.rb +48 -41
  16. data/lib/bundler/installer.rb +5 -0
  17. data/lib/bundler/lazy_specification.rb +7 -6
  18. data/lib/bundler/resolver.rb +1 -1
  19. data/lib/bundler/rubygems_ext.rb +1 -1
  20. data/lib/bundler/rubygems_integration.rb +69 -31
  21. data/lib/bundler/runtime.rb +2 -2
  22. data/lib/bundler/setup.rb +3 -0
  23. data/lib/bundler/shared_helpers.rb +2 -2
  24. data/lib/bundler/source.rb +48 -46
  25. data/lib/bundler/spec_set.rb +1 -0
  26. data/lib/bundler/templates/newgem/Gemfile.tt +1 -1
  27. data/lib/bundler/templates/newgem/Rakefile.tt +2 -2
  28. data/lib/bundler/templates/newgem/bin/newgem.tt +1 -1
  29. data/lib/bundler/templates/newgem/gitignore.tt +14 -1
  30. data/lib/bundler/templates/newgem/lib/newgem.rb.tt +2 -0
  31. data/lib/bundler/templates/newgem/newgem.gemspec.tt +13 -17
  32. data/lib/bundler/ui.rb +29 -15
  33. data/lib/bundler/vendor/net/http/persistent.rb +4 -0
  34. data/lib/bundler/vendored_thor.rb +7 -0
  35. data/lib/bundler/version.rb +1 -1
  36. data/man/bundle-install.ronn +7 -0
  37. data/man/bundle.ronn +6 -0
  38. data/man/gemfile.5.ronn +2 -0
  39. data/spec/cache/gems_spec.rb +11 -0
  40. data/spec/install/deploy_spec.rb +1 -1
  41. data/spec/install/gems/dependency_api_spec.rb +62 -7
  42. data/spec/install/gems/groups_spec.rb +3 -3
  43. data/spec/install/gems/post_install_spec.rb +47 -0
  44. data/spec/install/gems/sudo_spec.rb +3 -2
  45. data/spec/install/git_spec.rb +1 -2
  46. data/spec/install/path_spec.rb +1 -1
  47. data/spec/lock/lockfile_spec.rb +1 -1
  48. data/spec/other/check_spec.rb +30 -6
  49. data/spec/other/exec_spec.rb +4 -33
  50. data/spec/other/init_spec.rb +3 -3
  51. data/spec/other/newgem_spec.rb +5 -1
  52. data/spec/other/outdated_spec.rb +36 -6
  53. data/spec/quality_spec.rb +5 -1
  54. data/spec/runtime/require_spec.rb +10 -10
  55. data/spec/runtime/setup_spec.rb +31 -8
  56. data/spec/spec_helper.rb +1 -5
  57. data/spec/support/artifice/endpoint.rb +4 -0
  58. data/spec/support/artifice/endpoint_basic_authentication.rb +13 -0
  59. data/spec/support/artifice/endpoint_fallback.rb +0 -4
  60. data/spec/support/artifice/endpoint_redirect.rb +4 -0
  61. data/spec/support/builders.rb +6 -1
  62. data/spec/support/matchers.rb +1 -1
  63. data/spec/support/rubygems_ext.rb +4 -3
  64. data/spec/update/git_spec.rb +2 -2
  65. metadata +55 -143
@@ -46,7 +46,7 @@ module Bundler
46
46
  end
47
47
 
48
48
  def gem_dir
49
- Gem.dir.to_s
49
+ Gem.dir
50
50
  end
51
51
 
52
52
  def gem_bindir
@@ -58,9 +58,7 @@ module Bundler
58
58
  end
59
59
 
60
60
  def gem_path
61
- # Make sure that Gem.path is an array of Strings, not some
62
- # internal Rubygems object
63
- Gem.path.map { |x| x.to_s }
61
+ Gem.path
64
62
  end
65
63
 
66
64
  def marshal_spec_dir
@@ -75,6 +73,11 @@ module Bundler
75
73
  Gem.bin_path(gem, bin, ver)
76
74
  end
77
75
 
76
+ def preserve_paths
77
+ # this is a no-op outside of Rubygems 1.8
78
+ yield
79
+ end
80
+
78
81
  def ui=(obj)
79
82
  Gem::DefaultUserInteraction.ui = obj
80
83
  end
@@ -120,7 +123,7 @@ module Bundler
120
123
  if executables.include? File.basename(caller.first.split(':').first)
121
124
  return
122
125
  end
123
- opts = reqs.last.is_a?(Hash) ? reqs.pop : {}
126
+ reqs.pop if reqs.last.is_a?(Hash)
124
127
 
125
128
  unless dep.respond_to?(:name) && dep.respond_to?(:requirement)
126
129
  dep = Gem::Dependency.new(dep, reqs)
@@ -154,6 +157,16 @@ module Bundler
154
157
  end
155
158
  end
156
159
 
160
+ if defined? ::Deprecate
161
+ Deprecate = ::Deprecate
162
+ elsif defined? Gem::Deprecate
163
+ Deprecate = Gem::Deprecate
164
+ else
165
+ class Deprecate
166
+ def skip_during; yield; end
167
+ end
168
+ end
169
+
157
170
  def stub_source_index137(specs)
158
171
  # Rubygems versions lower than 1.7 use SourceIndex#from_gems_in
159
172
  source_index_class = (class << Gem::SourceIndex ; self ; end)
@@ -169,8 +182,19 @@ module Bundler
169
182
  def stub_source_index170(specs)
170
183
  Gem::SourceIndex.send(:define_method, :initialize) do |*args|
171
184
  @gems = {}
172
- self.spec_dirs = *args
173
- add_specs(*specs)
185
+ # You're looking at this thinking: Oh! This is how I make those
186
+ # rubygems deprecations go away!
187
+ #
188
+ # You'd be correct BUT using of this method in production code
189
+ # must be approved by the rubygems team itself!
190
+ #
191
+ # This is your warning. If you use this and don't have approval
192
+ # we can't protect you.
193
+ #
194
+ Deprecate.skip_during do
195
+ self.spec_dirs = *args
196
+ add_specs(*specs)
197
+ end
174
198
  end
175
199
  end
176
200
 
@@ -226,56 +250,70 @@ module Bundler
226
250
  Gem.clear_paths
227
251
  end
228
252
 
229
- class Modern < RubygemsIntegration
253
+ # Rubygems versions 1.3.6 through 1.6.2
254
+ class Legacy < RubygemsIntegration
230
255
  def stub_rubygems(specs)
231
- Gem::Specification.all = specs
232
-
233
- Gem.post_reset {
234
- Gem::Specification.all = specs
235
- }
236
-
237
- stub_source_index170(specs)
256
+ stub_source_index137(specs)
238
257
  end
239
258
 
240
259
  def all_specs
241
- Gem::Specification.to_a
260
+ Gem.source_index.gems.values
242
261
  end
243
262
 
244
263
  def find_name(name)
245
- Gem::Specification.find_all_by_name name
264
+ Gem.source_index.find_name(name)
246
265
  end
266
+ end
247
267
 
268
+ # Rubygems 1.7
269
+ class Transitional < Legacy
270
+ def stub_rubygems(specs)
271
+ stub_source_index170(specs)
272
+ end
248
273
  end
249
274
 
250
- class Legacy < RubygemsIntegration
275
+ # Rubygems 1.8.5
276
+ class Modern < RubygemsIntegration
251
277
  def stub_rubygems(specs)
252
- stub_source_index137(specs)
278
+ Gem::Specification.all = specs
279
+
280
+ Gem.post_reset {
281
+ Gem::Specification.all = specs
282
+ }
283
+
284
+ stub_source_index170(specs)
253
285
  end
254
286
 
255
287
  def all_specs
256
- Gem.source_index.all_gems.values
288
+ Gem::Specification.to_a
257
289
  end
258
290
 
259
291
  def find_name(name)
260
- Gem.source_index.find_name(name)
292
+ Gem::Specification.find_all_by_name name
261
293
  end
262
294
  end
263
295
 
264
- class Transitional < Legacy
265
- def stub_rubygems(specs)
266
- stub_source_index170(specs)
296
+ # Rubygems 1.8.0 to 1.8.4
297
+ class AlmostModern < Modern
298
+ # Rubygems [>= 1.8.0, < 1.8.5] has a bug that changes Gem.dir whenever
299
+ # you call Gem::Installer#install with an :install_dir set. We have to
300
+ # change it back for our sudo mode to work.
301
+ def preserve_paths
302
+ old_dir, old_path = gem_dir, gem_path
303
+ yield
304
+ Gem.use_paths(old_dir, old_path)
267
305
  end
268
306
  end
269
307
 
270
308
  end
271
309
 
272
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.7.0')
273
- if Gem::Specification.respond_to? :all=
274
- @rubygems = RubygemsIntegration::Modern.new
275
- else
276
- @rubygems = RubygemsIntegration::Transitional.new
277
- end
278
- else
310
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.8.5')
311
+ @rubygems = RubygemsIntegration::Modern.new
312
+ elsif Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.8.0')
313
+ @rubygems = RubygemsIntegration::AlmostModern.new
314
+ elsif Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.7.0')
315
+ @rubygems = RubygemsIntegration::Transitional.new
316
+ else # Rubygems 1.3.6 through 1.6.2
279
317
  @rubygems = RubygemsIntegration::Legacy.new
280
318
  end
281
319
 
@@ -85,7 +85,7 @@ module Bundler
85
85
  alias gems specs
86
86
 
87
87
  def cache
88
- FileUtils.mkdir_p(cache_path)
88
+ FileUtils.mkdir_p(cache_path) unless File.exists?(cache_path)
89
89
 
90
90
  Bundler.ui.info "Updating .gem files in vendor/cache"
91
91
  specs.each do |spec|
@@ -96,7 +96,7 @@ module Bundler
96
96
  end
97
97
 
98
98
  def prune_cache
99
- FileUtils.mkdir_p(cache_path)
99
+ FileUtils.mkdir_p(cache_path) unless File.exists?(cache_path)
100
100
 
101
101
  resolve = @definition.resolve
102
102
  cached = Dir["#{cache_path}/*.gem"]
@@ -8,6 +8,9 @@ if Bundler::SharedHelpers.in_bundle?
8
8
  rescue Bundler::BundlerError => e
9
9
  puts "\e[31m#{e.message}\e[0m"
10
10
  puts e.backtrace.join("\n") if ENV["DEBUG"]
11
+ if Bundler::GemNotFound === e
12
+ puts "\e[33mRun `bundle install` to install missing gems.\e[0m"
13
+ end
11
14
  exit e.status_code
12
15
  end
13
16
  else
@@ -58,9 +58,9 @@ module Bundler
58
58
  if defined?(::Gem)
59
59
  me = File.expand_path("../../", __FILE__)
60
60
  $LOAD_PATH.reject! do |p|
61
- next if File.expand_path(p) =~ /^#{me}/
61
+ next if File.expand_path(p) =~ /^#{Regexp.escape(me)}/
62
62
  p != File.dirname(__FILE__) &&
63
- Bundler.rubygems.gem_path.any?{|gp| p =~ /^#{gp}/ }
63
+ Bundler.rubygems.gem_path.any?{|gp| p =~ /^#{Regexp.escape(gp)}/ }
64
64
  end
65
65
  $LOAD_PATH.uniq!
66
66
  end
@@ -11,6 +11,7 @@ module Bundler
11
11
  # TODO: Refactor this class
12
12
  class Rubygems
13
13
  attr_reader :remotes, :caches
14
+ attr_accessor :dependencies
14
15
 
15
16
  def initialize(options = {})
16
17
  @options = options
@@ -65,8 +66,8 @@ module Bundler
65
66
  end
66
67
  alias_method :name, :to_s
67
68
 
68
- def specs(dependencies = nil)
69
- @specs ||= fetch_specs(dependencies)
69
+ def specs
70
+ @specs ||= fetch_specs
70
71
  end
71
72
 
72
73
  def fetch(spec)
@@ -74,41 +75,35 @@ module Bundler
74
75
  if spec
75
76
  path = download_gem_from_uri(spec, uri)
76
77
  s = Bundler.rubygems.spec_from_gem(path)
77
- spec.__swap__(s)
78
+ spec.__swap__(s) if spec.is_a?(RemoteSpecification)
78
79
  end
79
80
  end
80
81
 
81
- def outdated(spec)
82
- installed_spec = installed_specs[spec.name]
83
- installed_spec = installed_spec.first
84
-
85
- if installed_spec && spec.version == installed_spec.version
86
- Bundler.ui.debug "Up to date: #{spec.name} (#{installed_spec.version}) "
87
- return
88
- end
89
-
90
- Bundler.ui.info "#{spec.name} (#{spec.version} > #{installed_spec.version}) "
91
- end
92
-
93
82
  def install(spec)
94
- path = cached_gem(spec)
95
-
96
83
  if installed_specs[spec].any?
97
84
  Bundler.ui.info "Using #{spec.name} (#{spec.version}) "
98
85
  return
99
86
  end
100
87
 
101
88
  Bundler.ui.info "Installing #{spec.name} (#{spec.version}) "
89
+ path = cached_gem(spec)
90
+
91
+ Bundler.rubygems.preserve_paths do
92
+
93
+ install_path = Bundler.requires_sudo? ? Bundler.tmp : Bundler.rubygems.gem_dir
94
+ options = { :install_dir => install_path,
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?
102
99
 
103
- install_path = Bundler.requires_sudo? ? Bundler.tmp : Bundler.rubygems.gem_dir
104
- options = { :install_dir => install_path,
105
- :ignore_dependencies => true,
106
- :wrappers => true,
107
- :env_shebang => true }
108
- options.merge!(:bin_dir => "#{install_path}/bin") unless spec.executables.nil? || spec.executables.empty?
100
+ installer = Gem::Installer.new path, options
101
+ installer.install
102
+ end
109
103
 
110
- installer = Gem::Installer.new path, options
111
- installer.install
104
+ if spec.post_install_message
105
+ Installer.post_install_messages[spec.name] = spec.post_install_message
106
+ end
112
107
 
113
108
  # SUDO HAX
114
109
  if Bundler.requires_sudo?
@@ -151,7 +146,11 @@ module Bundler
151
146
 
152
147
  def cached_gem(spec)
153
148
  possibilities = @caches.map { |p| "#{p}/#{spec.file_name}" }
154
- possibilities.find { |p| File.exist?(p) }
149
+ cached_gem = possibilities.find { |p| File.exist?(p) }
150
+ unless cached_gem
151
+ raise Bundler::GemNotFound, "Could not find #{spec.file_name} for installation"
152
+ end
153
+ cached_gem
155
154
  end
156
155
 
157
156
  def normalize_uri(uri)
@@ -162,11 +161,11 @@ module Bundler
162
161
  uri
163
162
  end
164
163
 
165
- def fetch_specs(dependencies = nil)
164
+ def fetch_specs
166
165
  Index.build do |idx|
167
166
  idx.use installed_specs
168
167
  idx.use cached_specs if @allow_cached || @allow_remote
169
- idx.use remote_specs(dependencies) if @allow_remote
168
+ idx.use remote_specs if @allow_remote
170
169
  end
171
170
  end
172
171
 
@@ -206,7 +205,7 @@ module Bundler
206
205
 
207
206
  path = Bundler.app_cache
208
207
  Dir["#{path}/*.gem"].each do |gemfile|
209
- next if gemfile =~ /bundler\-[\d\.]+?\.gem/
208
+ next if gemfile =~ /^bundler\-[\d\.]+?\.gem/
210
209
 
211
210
  begin
212
211
  s ||= Bundler.rubygems.spec_from_gem(gemfile)
@@ -222,28 +221,17 @@ module Bundler
222
221
  idx
223
222
  end
224
223
 
225
- def remote_specs(dependencies = nil)
224
+ def remote_specs
226
225
  @remote_specs ||= begin
227
226
  idx = Index.new
228
227
  old = Bundler.rubygems.sources
229
228
 
230
229
  remotes.each do |uri|
231
- Bundler.ui.info "Fetching source index for #{uri}"
232
230
 
233
231
  @fetchers[uri] = Bundler::Fetcher.new(uri)
234
- gem_names =
235
- if dependencies
236
- dependencies.map {|d| d.name }
237
- end
238
- @fetchers[uri].fetch_remote_specs(gem_names) do |n,v|
239
- v.each do |name, version, platform|
240
- next if name == 'bundler'
241
- spec = RemoteSpecification.new(name, version, platform, @fetchers[uri])
242
- spec.source = self
243
- @spec_fetch_map[spec.full_name] = [spec, uri]
244
- idx << spec
245
- end
246
- end
232
+ gem_names = dependencies && dependencies.map{|d| d.name }
233
+
234
+ idx.use @fetchers[uri].specs(gem_names, self, @spec_fetch_map)
247
235
  end
248
236
  idx
249
237
  ensure
@@ -603,6 +591,19 @@ module Bundler
603
591
  Digest::SHA1.hexdigest(input)
604
592
  end
605
593
 
594
+ # Escape the URI for git commands
595
+ def uri_escaped
596
+ if Bundler::WINDOWS
597
+ # Windows quoting requires double quotes only, with double quotes
598
+ # inside the string escaped by being doubled.
599
+ '"' + uri.gsub('"') {|s| '""'} + '"'
600
+ else
601
+ # Bash requires single quoted strings, with the single quotes escaped
602
+ # by ending the string, escaping the quote, and restarting the string.
603
+ "'" + uri.gsub("'") {|s| "'\\''"} + "'"
604
+ end
605
+ end
606
+
606
607
  def cache_path
607
608
  @cache_path ||= begin
608
609
  git_scope = "#{base_name}-#{uri_hash}"
@@ -620,12 +621,12 @@ module Bundler
620
621
  return if has_revision_cached?
621
622
  Bundler.ui.info "Updating #{uri}"
622
623
  in_cache do
623
- git %|fetch --force --quiet --tags "#{uri}" "refs/heads/*:refs/heads/*"|
624
+ git %|fetch --force --quiet --tags #{uri_escaped} "refs/heads/*:refs/heads/*"|
624
625
  end
625
626
  else
626
627
  Bundler.ui.info "Fetching #{uri}"
627
628
  FileUtils.mkdir_p(cache_path.dirname)
628
- git %|clone "#{uri}" "#{cache_path}" --bare --no-hardlinks|
629
+ git %|clone #{uri_escaped} "#{cache_path}" --bare --no-hardlinks|
629
630
  end
630
631
  end
631
632
 
@@ -634,6 +635,7 @@ module Bundler
634
635
  FileUtils.mkdir_p(path.dirname)
635
636
  FileUtils.rm_rf(path)
636
637
  git %|clone --no-checkout "#{cache_path}" "#{path}"|
638
+ File.chmod((0777 & ~File.umask), path)
637
639
  end
638
640
  Dir.chdir(path) do
639
641
  git %|fetch --force --quiet --tags "#{cache_path}"|
@@ -80,6 +80,7 @@ module Bundler
80
80
  materialized = self.for(deps, [], false, true).to_a
81
81
  materialized.map! do |s|
82
82
  next s unless s.is_a?(LazySpecification)
83
+ s.source.dependencies = deps if s.source.respond_to?(:dependencies=)
83
84
  spec = s.__materialize__
84
85
  if missing_specs
85
86
  missing_specs << s unless spec
@@ -1,4 +1,4 @@
1
- source "http://rubygems.org"
1
+ source 'http://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in <%=config[:name]%>.gemspec
4
4
  gemspec
@@ -1,2 +1,2 @@
1
- require 'bundler'
2
- Bundler::GemHelper.install_tasks
1
+ #!/usr/bin/env rake
2
+ require 'bundler/gem_tasks'
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "<%= config[:name] %>"
3
+ require '<%= config[:name] %>'
@@ -1,4 +1,17 @@
1
1
  *.gem
2
+ *.rbc
2
3
  .bundle
4
+ .config
5
+ .yardoc
3
6
  Gemfile.lock
4
- pkg/*
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
@@ -1,3 +1,5 @@
1
+ require "<%=config[:name]%>/version"
2
+
1
3
  <%- config[:constant_array].each_with_index do |c,i| -%>
2
4
  <%= ' '*i %>module <%= c %>
3
5
  <%- end -%>