bundler 1.3.0.pre.7 → 1.3.0.pre.8

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 (69) hide show
  1. data/.rspec +1 -1
  2. data/.travis.yml +5 -0
  3. data/CHANGELOG.md +47 -0
  4. data/CONTRIBUTE.md +1 -2
  5. data/CONTRIBUTING.md +1 -1
  6. data/{LICENSE → LICENSE.md} +1 -1
  7. data/Rakefile +16 -13
  8. data/bundler.gemspec +20 -24
  9. data/lib/bundler.rb +6 -6
  10. data/lib/bundler/cli.rb +48 -11
  11. data/lib/bundler/deployment.rb +2 -1
  12. data/lib/bundler/deprecate.rb +1 -1
  13. data/lib/bundler/dsl.rb +4 -1
  14. data/lib/bundler/env.rb +1 -1
  15. data/lib/bundler/fetcher.rb +85 -57
  16. data/lib/bundler/friendly_errors.rb +0 -12
  17. data/lib/bundler/index.rb +2 -2
  18. data/lib/bundler/injector.rb +1 -1
  19. data/lib/bundler/installer.rb +7 -3
  20. data/lib/bundler/resolver.rb +17 -0
  21. data/lib/bundler/rubygems_ext.rb +4 -3
  22. data/lib/bundler/rubygems_integration.rb +38 -19
  23. data/lib/bundler/runtime.rb +9 -3
  24. data/lib/bundler/source/git.rb +20 -12
  25. data/lib/bundler/source/git/git_proxy.rb +1 -0
  26. data/lib/bundler/source/path/installer.rb +1 -1
  27. data/lib/bundler/source/rubygems.rb +25 -31
  28. data/lib/bundler/templates/newgem/.travis.yml.tt +3 -0
  29. data/lib/bundler/templates/newgem/LICENSE.txt.tt +1 -1
  30. data/lib/bundler/templates/newgem/newgem.gemspec.tt +17 -16
  31. data/lib/bundler/templates/newgem/test/test_newgem.rb.tt +1 -1
  32. data/lib/bundler/ui.rb +3 -2
  33. data/lib/bundler/vendor/net/http/persistent.rb +743 -91
  34. data/lib/bundler/vendor/net/http/persistent/ssl_reuse.rb +129 -0
  35. data/lib/bundler/vendored_persistent.rb +11 -0
  36. data/lib/bundler/version.rb +1 -1
  37. data/lib/bundler/vlad.rb +1 -1
  38. data/man/bundle-config.ronn +3 -2
  39. data/man/bundle-install.ronn +19 -4
  40. data/man/bundle-package.ronn +1 -1
  41. data/man/bundle-platform.ronn +1 -1
  42. data/man/bundle-update.ronn +5 -5
  43. data/man/gemfile.5.ronn +1 -1
  44. data/spec/bundler/bundler_spec.rb +26 -0
  45. data/spec/cache/git_spec.rb +1 -1
  46. data/spec/install/gems/dependency_api_spec.rb +12 -23
  47. data/spec/install/gems/flex_spec.rb +1 -0
  48. data/spec/install/gems/groups_spec.rb +0 -19
  49. data/spec/install/gems/simple_case_spec.rb +4 -1
  50. data/spec/install/gems/sudo_spec.rb +11 -15
  51. data/spec/install/git_spec.rb +17 -0
  52. data/spec/install/security_policy_spec.rb +78 -0
  53. data/spec/other/licenses_spec.rb +18 -0
  54. data/spec/other/newgem_spec.rb +36 -0
  55. data/spec/other/outdated_spec.rb +10 -2
  56. data/spec/other/show_spec.rb +6 -1
  57. data/spec/realworld/dependency_api_spec.rb +2 -2
  58. data/spec/realworld/edgecases_spec.rb +3 -3
  59. data/spec/resolver/basic_spec.rb +7 -1
  60. data/spec/resolver/platform_spec.rb +1 -1
  61. data/spec/runtime/executable_spec.rb +2 -2
  62. data/spec/runtime/setup_spec.rb +14 -1
  63. data/spec/support/artifice/endpoint.rb +2 -0
  64. data/spec/support/builders.rb +74 -1
  65. data/spec/support/fakeweb/windows.rb +1 -1
  66. data/spec/support/indexes.rb +22 -0
  67. data/spec/support/path.rb +4 -0
  68. data/spec/support/rubygems_ext.rb +1 -0
  69. metadata +63 -83
data/.rspec CHANGED
@@ -1,2 +1,2 @@
1
1
  --format documentation
2
- --color
2
+ --color
@@ -16,6 +16,11 @@ notifications:
16
16
  on_failure: always
17
17
  channels:
18
18
  - "irc.freenode.org#bundler"
19
+ campfire:
20
+ on_success: change
21
+ on_failure: always
22
+ rooms:
23
+ - secure: "geau3P+A9ZJHkA/OHN5v9Mcb8hAti1PllXw5DsHNJfLAWBAw5ReGGMA8Xfpf\nLdT7ktIUlQwzw94cKQ6sRZk8szXTiHncf3bxXTACJf2RpiKmbkoQU51TmCDq\nYSMuY1FIryk/3t9aZCrarufbIDI3DBscDEe4Bj9bERl+TJ8ArBY="
19
24
  rvm:
20
25
  - 1.9.3
21
26
  - 1.9.2
@@ -1,3 +1,34 @@
1
+ ## 1.3.0.pre.8 (12 February 2013)
2
+
3
+ Security:
4
+
5
+ - validate SSL certificate chain during HTTPS network requests
6
+ - don't send HTTP Basic Auth creds when redirected to other hosts (@perplexes)
7
+ - add `--trust-policy` to `install`, like `gem install -P` (@CosmicCat, #2293)
8
+
9
+ Features:
10
+
11
+ - optimize resolver when too new of a gem is already activated (@rykov, #2248)
12
+ - update Net::HTTP::Persistent for SSL cert validation and no_proxy ENV
13
+ - explain SSL cert validation failures
14
+ - generate gemspecs when installing git repos, removing shellouts
15
+ - add pager selection (@csgui)
16
+ - add `licenses` command (@bryanwoods, #1898)
17
+ - sort output from `outdated` (@richardkmichael, #1896)
18
+ - add a .travis.yml to `gem -t` (@ndbroadbent, #2143)
19
+ - inform users when the resolver starts
20
+ - disable reverse DNS to speed up API requests (@raggi)
21
+
22
+ Bugfixes:
23
+
24
+ - raise errors while requiring dashed gems (#1807)
25
+ - quote the Bundler path on Windows (@jgeiger, #1862, #1856)
26
+ - load gemspecs containing unicode (@gaffneyc, #2301)
27
+ - support any ruby version in --standalone
28
+ - resolve some ruby -w warnings (@chastell, #2193)
29
+ - don't scare users with an error message during API fallback
30
+ - `install --binstubs` is back to overwriting. thanks, SemVer.
31
+
1
32
  ## 1.3.0.pre.7 (22 January 2013)
2
33
 
3
34
  Bugfixes:
@@ -107,6 +138,22 @@ Bugfixes:
107
138
  - `gem` generates gemspecs that block double-requires
108
139
  - `gem` generates gemspecs that admit they depend on rake
109
140
 
141
+ ## 1.2.4 (Feb 12, 2013)
142
+
143
+ Features:
144
+
145
+ - warn about Ruby 2.0 and Rubygems 2.0
146
+ - inform users when the resolver starts
147
+ - disable reverse DNS to speed up API requests (@raggi)
148
+
149
+ Bugfixes:
150
+
151
+ - don't send user/pass when redirected to another host (@perplexes)
152
+ - load gemspecs containing unicode (@gaffneyc, #2301)
153
+ - support any ruby version in --standalone
154
+ - resolve some ruby -w warnings (@chastell, #2193)
155
+ - don't scare users with an error message during API fallback
156
+
110
157
  ## 1.2.3 (Nov 29, 2012)
111
158
 
112
159
  Bugfixes:
@@ -1,4 +1,3 @@
1
-
2
1
  Great to have you here! Here are a few ways you can help out with [Bundler](http://github.com/carlhuda/bundler).
3
2
 
4
3
  # Learn & listen
@@ -94,4 +93,4 @@ If you let someone on the core team know you wrote about Bundler, we will add yo
94
93
 
95
94
  If you’re interested in contributing to Bundler, that’s awesome! We’d love your help.
96
95
 
97
- If you have any questions after reading this page, please feel free to contact either [@indirect](http://github.com/indirect) or [@hone](http://github.com/hone). They are both happy to provide help working through your first bugfix or thinking through the problem you’re trying to resolve.
96
+ If you have any questions after reading this page, please feel free to contact either [@indirect](http://github.com/indirect) or [@hone](http://github.com/hone). They are both happy to provide help working through your first bugfix or thinking through the problem you’re trying to resolve.
@@ -10,4 +10,4 @@ If you'd like to discuss features, ask questions, or just engage in general Bund
10
10
 
11
11
  If you'd like to help make Bundler better, you totally rock! Please check out the [CONTRIBUTE](https://github.com/carlhuda/bundler/blob/master/CONTRIBUTE.md) file for an introduction to the project, guidelines for contributing, and suggestions for things anyone can do that would be helpful.
12
12
 
13
- Thanks for helping us make Bundler better.
13
+ Thanks for helping us make Bundler better.
@@ -20,4 +20,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
20
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
21
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
22
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile CHANGED
@@ -5,6 +5,16 @@ require 'rubygems'
5
5
  require 'shellwords'
6
6
  require 'benchmark'
7
7
 
8
+ task :build => ["man:clean", "man:build"]
9
+ task :release => ["man:clean", "man:build"]
10
+
11
+ def safe_task(&block)
12
+ yield
13
+ true
14
+ rescue
15
+ false
16
+ end
17
+
8
18
  # Benchmark task execution
9
19
  module Rake
10
20
  class Task
@@ -19,20 +29,13 @@ module Rake
19
29
  end
20
30
  end
21
31
 
22
- task :release => ["man:clean", "man:build"]
23
-
24
- def safe_task(&block)
25
- yield
26
- true
27
- rescue
28
- false
29
- end
30
-
31
32
  namespace :spec do
32
33
  desc "Ensure spec dependencies are installed"
33
34
  task :deps do
34
- sh "#{Gem.ruby} -S gem list ronn | (grep 'ronn' 1> /dev/null) || #{Gem.ruby} -S gem install ronn --no-ri --no-rdoc"
35
- sh "#{Gem.ruby} -S gem list rspec | (grep 'rspec (2.' 1> /dev/null) || #{Gem.ruby} -S gem install rspec --no-ri --no-rdoc"
35
+ {"rdiscount" => "~> 1.6", "ronn" => "~> 0.7.3", "rspec" => "~> 2.12"}.each do |name, version|
36
+ sh "#{Gem.ruby} -S gem list #{name} -v '#{version}' | grep '#{name}' -q || " \
37
+ "#{Gem.ruby} -S gem install #{name} -v '#{version}' --no-ri --no-rdoc"
38
+ end
36
39
  end
37
40
 
38
41
  namespace :travis do
@@ -88,7 +91,7 @@ begin
88
91
  namespace :rubygems do
89
92
  # Rubygems specs by version
90
93
  rubyopt = ENV["RUBYOPT"]
91
- %w(master v1.3.6 v1.3.7 v1.4.2 v1.5.3 v1.6.2 v1.7.2 v1.8.24 v2.0.0.preview2.2).each do |rg|
94
+ %w(master v1.3.6 v1.3.7 v1.4.2 v1.5.3 v1.6.2 v1.7.2 v1.8.24 v2.0.0.rc.1).each do |rg|
92
95
  desc "Run specs with Rubygems #{rg}"
93
96
  RSpec::Core::RakeTask.new(rg) do |t|
94
97
  t.rspec_opts = %w(-fs --color)
@@ -142,7 +145,7 @@ begin
142
145
 
143
146
  desc "Run the tests on Travis CI against a rubygem version (using ENV['RGV'])"
144
147
  task :travis do
145
- rg = ENV['RGV'] || 'master'
148
+ rg = ENV['RGV'] || 'v1.8.24'
146
149
 
147
150
  puts "\n\e[1;33m[Travis CI] Running bundler specs against rubygems #{rg}\e[m\n\n"
148
151
  specs = safe_task { Rake::Task["spec:rubygems:#{rg}"].invoke }
@@ -1,32 +1,28 @@
1
- # -*- encoding: utf-8 -*-
1
+ # coding: utf-8
2
2
  lib = File.expand_path('../lib/', __FILE__)
3
3
  $:.unshift lib unless $:.include?(lib)
4
-
5
4
  require 'bundler/version'
6
5
 
7
- Gem::Specification.new do |s|
8
- s.name = "bundler"
9
- s.version = Bundler::VERSION
10
- s.platform = Gem::Platform::RUBY
11
- s.license = "MIT"
12
- s.authors = ["André Arko", "Terence Lee", "Carl Lerche", "Yehuda Katz"]
13
- s.email = ["andre@arko.net"]
14
- s.homepage = "http://gembundler.com"
15
- s.summary = %q{The best way to manage your application's dependencies}
16
- s.description = %q{Bundler manages an application's dependencies through its entire life, across many machines, systematically and repeatably}
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'bundler'
8
+ spec.version = Bundler::VERSION
9
+ spec.licenses = ['MIT']
10
+ spec.authors = ["André Arko", "Terence Lee", "Carl Lerche", "Yehuda Katz"]
11
+ spec.email = ["andre@arko.net"]
12
+ spec.homepage = "http://gembundler.com"
13
+ spec.summary = %q{The best way to manage your application's dependencies}
14
+ spec.description = %q{Bundler manages an application's dependencies through its entire life, across many machines, systematically and repeatably}
15
+
16
+ spec.required_ruby_version = '>= 1.8.7'
17
+ spec.required_rubygems_version = '>= 1.3.6'
17
18
 
18
- s.required_ruby_version = ">= 1.8.7"
19
- s.required_rubygems_version = ">= 1.3.6"
20
- s.rubyforge_project = "bundler"
19
+ spec.add_development_dependency 'ronn', '~> 0.7.3'
20
+ spec.add_development_dependency 'rspec', '~> 2.11'
21
21
 
22
- s.add_development_dependency "ronn"
23
- s.add_development_dependency "rspec", "~> 2.11"
22
+ spec.files = `git ls-files`.split($/)
23
+ spec.files += Dir.glob('man/**/*') # man/ is ignored by git
24
+ spec.test_files = spec.files.grep(%r{^spec/})
24
25
 
25
- # Man files are required because they are ignored by git
26
- man_files = Dir.glob("lib/bundler/man/**/*")
27
- git_files = `git ls-files`.split("\n") rescue ''
28
- s.files = git_files + man_files
29
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
30
- s.executables = %w(bundle)
31
- s.require_paths = ["lib"]
26
+ spec.executables = %w(bundle)
27
+ spec.require_paths = ["lib"]
32
28
  end
@@ -1,6 +1,6 @@
1
- require 'rbconfig'
2
1
  require 'fileutils'
3
2
  require 'pathname'
3
+ require 'rbconfig'
4
4
  require 'bundler/gem_path_manipulation'
5
5
  require 'bundler/rubygems_ext'
6
6
  require 'bundler/rubygems_integration'
@@ -61,6 +61,7 @@ module Bundler
61
61
  class ProductionError < BundlerError; status_code(16) ; end
62
62
  class HTTPError < BundlerError; status_code(17) ; end
63
63
  class RubyVersionMismatch < BundlerError; status_code(18) ; end
64
+ class SecurityError < BundlerError; status_code(19) ; end
64
65
 
65
66
  WINDOWS = RbConfig::CONFIG["host_os"] =~ %r!(msdos|mswin|djgpp|mingw)!
66
67
  FREEBSD = RbConfig::CONFIG["host_os"] =~ /bsd/
@@ -100,9 +101,9 @@ module Bundler
100
101
  def bin_path
101
102
  @bin_path ||= begin
102
103
  path = settings[:bin] || "bin"
103
- path = Pathname.new(path).expand_path(root)
104
+ path = Pathname.new(path).expand_path(root).expand_path
104
105
  FileUtils.mkdir_p(path)
105
- Pathname.new(path).expand_path
106
+ path
106
107
  end
107
108
  end
108
109
 
@@ -320,9 +321,9 @@ module Bundler
320
321
 
321
322
  def eval_gemspec(path, contents)
322
323
  eval(contents, TOPLEVEL_BINDING, path.expand_path.to_s)
323
- rescue LoadError, SyntaxError => e
324
+ rescue ScriptError, StandardError => e
324
325
  original_line = e.backtrace.find { |line| line.include?(path.to_s) }
325
- msg = "There was a #{e.class} while evaluating #{path.basename}: \n#{e.message}"
326
+ msg = "There was a #{e.class} while loading #{path.basename}: \n#{e.message}"
326
327
  msg << " from\n #{original_line}" if original_line
327
328
  msg << "\n"
328
329
 
@@ -335,7 +336,6 @@ module Bundler
335
336
 
336
337
  def configure_gem_home_and_path
337
338
  blank_home = ENV['GEM_HOME'].nil? || ENV['GEM_HOME'].empty?
338
-
339
339
  if settings[:disable_shared_gems]
340
340
  ENV['GEM_PATH'] = ''
341
341
  configure_gem_home
@@ -1,7 +1,7 @@
1
+ require 'bundler/similarity_detector'
1
2
  require 'bundler/vendored_thor'
2
3
  require 'rubygems/user_interaction'
3
- require 'rubygems/config_file'
4
- require 'bundler/similarity_detector'
4
+ require 'rubygems/security'
5
5
 
6
6
  module Bundler
7
7
  class CLI < Thor
@@ -18,7 +18,6 @@ module Bundler
18
18
  end
19
19
 
20
20
  check_unknown_options!(:except => [:config, :exec])
21
-
22
21
  stop_on_unknown_option! :exec
23
22
 
24
23
  default_task :install
@@ -46,8 +45,8 @@ module Bundler
46
45
  root = File.expand_path("../man", __FILE__)
47
46
 
48
47
  if have_groff? && root !~ %r{^file:/.+!/META-INF/jruby.home/.+}
49
- groff = "groff -Wall -mtty-char -mandoc -Tascii"
50
- pager = ENV['MANPAGER'] || ENV['PAGER'] || 'less -R'
48
+ groff = "groff -Wall -mtty-char -mandoc -Tascii"
49
+ pager = pager_system
51
50
 
52
51
  Kernel.exec "#{groff} #{root}/#{command} | #{pager}"
53
52
  else
@@ -171,6 +170,9 @@ module Bundler
171
170
  "Use the rubygems modern index instead of the API endpoint"
172
171
  method_option "clean", :type => :boolean, :banner =>
173
172
  "Run bundle clean automatically after install"
173
+ method_option "trust-policy", :alias => "P", :type => :string, :banner =>
174
+ "Gem trust policy (like gem install -P). Must be one of " + Gem::Security::Policies.keys.join('|')
175
+
174
176
  def install
175
177
  opts = options.dup
176
178
  if opts[:without]
@@ -190,6 +192,17 @@ module Bundler
190
192
  exit 1
191
193
  end
192
194
 
195
+ if (opts["trust-policy"])
196
+ unless (Gem::Security::Policies.keys.include?(opts["trust-policy"]))
197
+ Bundler.ui.error "Rubygems doesn't know about trust policy '#{opts["trust-policy"]}'. " \
198
+ "The known policies are: #{Gem::Security::Policies.keys.join(', ')}."
199
+ exit 1
200
+ end
201
+ Bundler.settings["trust-policy"] = opts["trust-policy"]
202
+ else
203
+ Bundler.settings["trust-policy"] = nil if Bundler.settings["trust-policy"]
204
+ end
205
+
193
206
  if opts[:deployment] || opts[:frozen]
194
207
  unless Bundler.default_lockfile.exist?
195
208
  flag = opts[:deployment] ? '--deployment' : '--frozen'
@@ -222,7 +235,7 @@ module Bundler
222
235
  Bundler.settings[:no_prune] = true if opts["no-prune"]
223
236
  Bundler.settings[:disable_shared_gems] = Bundler.settings[:path] ? '1' : nil
224
237
  Bundler.settings.without = opts[:without]
225
- Bundler.ui.be_quiet! if opts[:quiet]
238
+ Bundler.ui.quiet = opts[:quiet]
226
239
  Bundler.settings[:clean] = opts[:clean] if opts[:clean]
227
240
 
228
241
  Bundler::Fetcher.disable_endpoint = opts["full-index"]
@@ -276,7 +289,7 @@ module Bundler
276
289
  "Use the rubygems modern index instead of the API endpoint"
277
290
  def update(*gems)
278
291
  sources = Array(options[:source])
279
- Bundler.ui.be_quiet! if options[:quiet]
292
+ Bundler.ui.quiet = options[:quiet]
280
293
 
281
294
  if gems.empty? && sources.empty?
282
295
  # We're doing a full update
@@ -344,8 +357,8 @@ module Bundler
344
357
  Bundler.definition.validate_ruby!
345
358
  Bundler.settings[:bin] = options["path"] if options["path"]
346
359
  Bundler.settings[:bin] = nil if options["path"] && options["path"].empty?
347
- installer = Installer.new(Bundler.root, Bundler.definition)
348
- spec = installer.specs.find{|s| s.name == gem_name }
360
+ installer = Installer.new(Bundler.root, Bundler.definition)
361
+ spec = installer.specs.find{|s| s.name == gem_name }
349
362
  raise GemNotFound, not_found_message(gem_name, Bundler.load.specs) unless spec
350
363
 
351
364
  if spec.name == "bundler"
@@ -383,7 +396,7 @@ module Bundler
383
396
 
384
397
  out_count = 0
385
398
  # Loop through the current specs
386
- current_specs.each do |current_spec|
399
+ current_specs.sort_by { |s| s.name }.each do |current_spec|
387
400
  next if !gems.empty? && !gems.include?(current_spec.name)
388
401
 
389
402
  active_spec = definition.index[current_spec.name].sort_by { |b| b.version }
@@ -593,6 +606,20 @@ module Bundler
593
606
  end
594
607
  map %w(-v --version) => :version
595
608
 
609
+ desc "licenses", "Prints the license of all gems in the bundle"
610
+ def licenses
611
+ Bundler.load.specs.sort_by { |s| s.license.to_s }.reverse.each do |s|
612
+ gem_name = s.name
613
+ license = s.license || s.licenses
614
+
615
+ if license.empty?
616
+ Bundler.ui.warn "#{gem_name}: Unknown"
617
+ else
618
+ Bundler.ui.info "#{gem_name}: #{license}"
619
+ end
620
+ end
621
+ end
622
+
596
623
  desc 'viz', "Generates a visual dependency graph"
597
624
  long_desc <<-D
598
625
  Viz generates a PNG file of the current Gemfile as a dependency graph.
@@ -625,7 +652,7 @@ module Bundler
625
652
 
626
653
  desc "gem GEM", "Creates a skeleton for creating a rubygem"
627
654
  method_option :bin, :type => :boolean, :default => false, :aliases => '-b', :banner => "Generate a binary for your library."
628
- method_option :test, :type => :string, :default => 'rspec', :aliases => '-t', :banner => "Generate a test directory for your library: 'rspec' is the default, but 'minitest' is also supported."
655
+ method_option :test, :type => :string, :lazy_default => 'rspec', :aliases => '-t', :banner => "Generate a test directory for your library: 'rspec' is the default, but 'minitest' is also supported."
629
656
  method_option :edit, :type => :string, :aliases => "-e",
630
657
  :lazy_default => [ENV['BUNDLER_EDITOR'], ENV['VISUAL'], ENV['EDITOR']].find{|e| !e.nil? && !e.empty? },
631
658
  :required => false, :banner => "/path/to/your/editor",
@@ -670,6 +697,9 @@ module Bundler
670
697
  template(File.join("newgem/test/minitest_helper.rb.tt"), File.join(target, "test/minitest_helper.rb"), opts)
671
698
  template(File.join("newgem/test/test_newgem.rb.tt"), File.join(target, "test/test_#{namespaced_path}.rb"), opts)
672
699
  end
700
+ if options[:test]
701
+ template(File.join("newgem/.travis.yml.tt"), File.join(target, ".travis.yml"), opts)
702
+ end
673
703
  Bundler.ui.info "Initializating git repo in #{target}"
674
704
  Dir.chdir(target) { `git init`; `git add .` }
675
705
 
@@ -801,5 +831,12 @@ module Bundler
801
831
  message
802
832
  end
803
833
 
834
+ def pager_system
835
+ pager = ENV['PAGER'] || ENV['MANPAGER']
836
+ pager ||= 'less -R' if !(`which less` rescue '').empty?
837
+ pager ||= 'more' if !(`which more` rescue '').empty?
838
+ pager ||= 'cat'
839
+ end
840
+
804
841
  end
805
842
  end
@@ -21,7 +21,8 @@ module Bundler
21
21
  test group will not be installed. The install command is executed \
22
22
  with the --deployment and --quiet flags. If the bundle cmd cannot \
23
23
  be found then you can override the bundle_cmd variable to specifiy \
24
- which one it should use.
24
+ which one it should use. The base path to the app is fetched from \
25
+ the :latest_release variable. Set it for custom deploy layouts.
25
26
 
26
27
  You can override any of these defaults by setting the variables shown below.
27
28
 
@@ -12,4 +12,4 @@ module Bundler
12
12
  def Deprecate.skip_during; yield; end
13
13
  end
14
14
 
15
- end
15
+ end
@@ -107,7 +107,10 @@ module Bundler
107
107
  def source(source, options = {})
108
108
  case source
109
109
  when :gemcutter, :rubygems, :rubyforge then
110
- @rubygems_source.add_remote "http://rubygems.org"
110
+ Bundler.ui.warn "The source :#{source} is deprecated because HTTP " \
111
+ "requests are insecure.\nPlease change your source to 'https://" \
112
+ "rubygems.org' if possible, or 'http://rubygems.org' if not."
113
+ @rubygems_source.add_remote "https://rubygems.org"
111
114
  return
112
115
  when String
113
116
  @rubygems_source.add_remote source
@@ -53,4 +53,4 @@ module Bundler
53
53
  end
54
54
 
55
55
  end
56
- end
56
+ end
@@ -1,15 +1,24 @@
1
- require 'uri'
2
1
  require 'bundler/vendored_persistent'
3
- require 'openssl' if defined?(JRUBY_VERSION)
4
2
 
5
3
  module Bundler
4
+ # This is the error raised if OpenSSL fails the cert verification
5
+ class CertificateFailureError < HTTPError
6
+ def initialize(message = nil)
7
+ @message = message
8
+ @message ||= "\nCould not verify the SSL certificate for " \
9
+ "#{@remote_uri}. Either you don't have the CA certificates needed to " \
10
+ "verify it, or you are experiencing a man-in-the-middle attack. To " \
11
+ "connect without using SSL, edit your Gemfile sources to and change " \
12
+ "'https' to 'http'."
13
+ end
14
+ end
15
+
6
16
  # Handles all the fetching with the rubygems server
7
17
  class Fetcher
8
18
  REDIRECT_LIMIT = 5
9
19
  # how long to wait for each gemcutter API call
10
20
  API_TIMEOUT = 10
11
-
12
- attr_reader :has_api
21
+ class FallbackError < Bundler::HTTPError; end
13
22
 
14
23
  class << self
15
24
  attr_accessor :disable_endpoint
@@ -20,7 +29,7 @@ module Bundler
20
29
  spec, uri = @@spec_fetch_map[spec.full_name]
21
30
  if spec
22
31
  path = download_gem_from_uri(spec, uri)
23
- s = Bundler.rubygems.spec_from_gem(path)
32
+ s = Bundler.rubygems.spec_from_gem(path, Bundler.settings["trust-policy"])
24
33
  spec.__swap__(s)
25
34
  end
26
35
  end
@@ -45,9 +54,12 @@ module Bundler
45
54
 
46
55
  def initialize(remote_uri)
47
56
  @remote_uri = remote_uri
48
- @has_api = true # will be set to false if the rubygems index is ever fetched
49
- @@connection ||= Net::HTTP::Persistent.new nil, :ENV
50
- @@connection.read_timeout = API_TIMEOUT
57
+ @public_uri = remote_uri.dup
58
+ @public_uri.user, @public_uri.password = nil, nil # don't print these
59
+ @connection ||= Net::HTTP::Persistent.new 'bundler', :ENV
60
+ @connection.read_timeout = API_TIMEOUT
61
+
62
+ Socket.do_not_reverse_lookup = true
51
63
  end
52
64
 
53
65
  # fetch a gem specification
@@ -65,35 +77,19 @@ module Bundler
65
77
  def specs(gem_names, source)
66
78
  index = Index.new
67
79
 
68
- specs = nil
80
+ if gem_names && use_api
81
+ Bundler.ui.info "Fetching gem metadata from #{@public_uri}", Bundler.ui.debug?
82
+ specs = fetch_remote_specs(gem_names)
83
+ # new line now that the dots are over
84
+ Bundler.ui.info "" if specs && !Bundler.ui.debug?
85
+ end
69
86
 
70
- if !gem_names || @remote_uri.scheme == "file" || Bundler::Fetcher.disable_endpoint
71
- Bundler.ui.info "Fetching source index from #{strip_user_pass_from_uri(@remote_uri)}"
72
- specs = fetch_all_remote_specs
73
- else
74
- Bundler.ui.info "Fetching gem metadata from #{strip_user_pass_from_uri(@remote_uri)}", Bundler.ui.debug?
75
- begin
76
- specs = fetch_remote_specs(gem_names)
77
- # fall back to the legacy index in the following cases
78
- # 1. Gemcutter Endpoint doesn't return a 200
79
- # 2. Marshal blob doesn't load properly
80
- # 3. One of the YAML gemspecs has the Syck::DefaultKey problem
81
- rescue HTTPError, TypeError, GemspecError => e
82
- # new line now that the dots are over
83
- Bundler.ui.info "" unless Bundler.ui.debug?
84
-
85
- if @remote_uri.to_s.include?("rubygems.org")
86
- Bundler.ui.info "Error #{e.class} during request to dependency API"
87
- end
88
- Bundler.ui.debug e.message
89
- Bundler.ui.debug e.backtrace
87
+ if specs.nil?
88
+ # API errors mean we should treat this as a non-API source
89
+ @use_api = false
90
90
 
91
- Bundler.ui.info "Fetching full source index from #{strip_user_pass_from_uri(@remote_uri)}"
92
- specs = fetch_all_remote_specs
93
- else
94
- # new line now that the dots are over
95
- Bundler.ui.info "" unless Bundler.ui.debug?
96
- end
91
+ Bundler.ui.info "Fetching source index from #{@public_uri}"
92
+ specs = fetch_all_remote_specs
97
93
  end
98
94
 
99
95
  specs[@remote_uri].each do |name, version, platform, dependencies|
@@ -110,6 +106,8 @@ module Bundler
110
106
  end
111
107
 
112
108
  index
109
+ rescue OpenSSL::SSL::SSLError
110
+ raise CertificateFailureError.new
113
111
  end
114
112
 
115
113
  # fetch index
@@ -129,6 +127,36 @@ module Bundler
129
127
  returned_gems = spec_list.map {|spec| spec.first }.uniq
130
128
 
131
129
  fetch_remote_specs(deps_list, full_dependency_list + returned_gems, spec_list + last_spec_list)
130
+ # fall back to the legacy index in the following cases
131
+ # 1. Gemcutter Endpoint doesn't return a 200
132
+ # 2,3. Marshal blob doesn't load properly
133
+ # 4. One of the YAML gemspecs has the Syck::DefaultKey problem
134
+ rescue HTTPError, ArgumentError, TypeError, GemspecError => e
135
+ @use_api = false
136
+
137
+ # new line now that the dots are over
138
+ Bundler.ui.info "" unless Bundler.ui.debug?
139
+
140
+ Bundler.ui.debug "Error during API request. #{e.class}: #{e.message}"
141
+ Bundler.ui.debug e.backtrace.join(" ")
142
+
143
+ return nil
144
+ end
145
+
146
+ def use_api
147
+ return @use_api if defined?(@use_api)
148
+
149
+ if @remote_uri.scheme == "file" || Bundler::Fetcher.disable_endpoint
150
+ @use_api = false
151
+ elsif fetch(dependency_api_uri)
152
+ @use_api = true
153
+ end
154
+ rescue HTTPError
155
+ @use_api = false
156
+ end
157
+
158
+ def inspect
159
+ "#<#{self.class}:0x#{object_id} uri=#{@public_uri.to_s}>"
132
160
  end
133
161
 
134
162
  private
@@ -138,7 +166,7 @@ module Bundler
138
166
 
139
167
  begin
140
168
  Bundler.ui.debug "Fetching from: #{uri}"
141
- response = @@connection.request(uri)
169
+ response = @connection.request(uri)
142
170
  rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, Errno::ETIMEDOUT,
143
171
  EOFError, SocketError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError,
144
172
  Errno::EAGAIN, Net::HTTP::Persistent::Error, Net::ProtocolError
@@ -149,24 +177,31 @@ module Bundler
149
177
  when Net::HTTPRedirection
150
178
  Bundler.ui.debug("HTTP Redirection")
151
179
  new_uri = URI.parse(response["location"])
152
- new_uri.user = uri.user
153
- new_uri.password = uri.password
180
+ if new_uri.host == uri.host
181
+ new_uri.user = uri.user
182
+ new_uri.password = uri.password
183
+ end
154
184
  fetch(new_uri, counter + 1)
155
185
  when Net::HTTPSuccess
156
186
  Bundler.ui.debug("HTTP Success")
157
187
  response.body
188
+ when Net::HTTPRequestEntityTooLarge
189
+ raise FallbackError, response.body
158
190
  else
159
- Bundler.ui.debug("HTTP Error")
160
- raise HTTPError, "Don't know how to process #{response.class}"
191
+ raise HTTPError, "#{response.class}: #{response.body}"
161
192
  end
162
193
  end
163
194
 
195
+ def dependency_api_uri(gem_names = [])
196
+ url = "#{@remote_uri}api/v1/dependencies"
197
+ url << "?gems=#{URI.encode(gem_names.join(","))}" if gem_names.any?
198
+ URI.parse(url)
199
+ end
200
+
164
201
  # fetch from Gemcutter Dependency Endpoint API
165
202
  def fetch_dependency_remote_specs(gem_names)
166
- Bundler.ui.debug "Query Gemcutter Dependency Endpoint API: #{gem_names.join(' ')}"
167
- encoded_gem_names = URI.encode(gem_names.join(","))
168
- uri = URI.parse("#{@remote_uri}api/v1/dependencies?gems=#{encoded_gem_names}")
169
- marshalled_deps = fetch(uri)
203
+ Bundler.ui.debug "Query Gemcutter Dependency Endpoint API: #{gem_names.join(',')}"
204
+ marshalled_deps = fetch dependency_api_uri(gem_names)
170
205
  gem_list = Marshal.load(marshalled_deps)
171
206
  deps_list = []
172
207
 
@@ -200,22 +235,15 @@ module Bundler
200
235
 
201
236
  # fetch from modern index: specs.4.8.gz
202
237
  def fetch_all_remote_specs
203
- @has_api = false
204
238
  Bundler.rubygems.sources = ["#{@remote_uri}"]
205
-
206
- begin
207
- Bundler.rubygems.fetch_all_remote_specs
208
- rescue Gem::RemoteFetcher::FetchError
209
- raise HTTPError, "Could not reach #{strip_user_pass_from_uri(@remote_uri)}"
239
+ Bundler.rubygems.fetch_all_remote_specs
240
+ rescue Gem::RemoteFetcher::FetchError => e
241
+ if e.message.match("certificate verify failed")
242
+ raise CertificateFailureError.new
243
+ else
244
+ raise HTTPError, "Could not fetch specs from #{@public_uri}"
210
245
  end
211
246
  end
212
247
 
213
- def strip_user_pass_from_uri(uri)
214
- uri_dup = uri.dup
215
- uri_dup.user = "****" if uri_dup.user
216
- uri_dup.password = "****" if uri_dup.password
217
-
218
- uri_dup
219
- end
220
248
  end
221
249
  end