summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Arko <andre@arko.net>2015-05-07 16:34:39 +0100
committerAndre Arko <andre@arko.net>2015-05-07 16:34:39 +0100
commit95858d54e19a6fe1adffeefc9e7eba942d3c8332 (patch)
tree723915396db04a4393f46fa330ae8a00a54f1934
parent30569377750ae306997a37cde6e2fd814e1d24cd (diff)
parent21e6fe9ebb520b36b201d0e569d0b8b7c2b3980c (diff)
downloadbundler-95858d54e19a6fe1adffeefc9e7eba942d3c8332.tar.gz
Merge branch '1-99-dev' into 2-0-dev
-rw-r--r--.travis.yml6
-rw-r--r--CHANGELOG.md124
-rw-r--r--Rakefile44
-rwxr-xr-xbin/bundle_ruby59
-rw-r--r--bundler.gemspec7
-rw-r--r--lib/bundler.rb15
-rw-r--r--lib/bundler/cli.rb10
-rw-r--r--lib/bundler/cli/gem.rb26
-rw-r--r--lib/bundler/cli/install.rb42
-rw-r--r--lib/bundler/cli/outdated.rb11
-rw-r--r--lib/bundler/definition.rb57
-rw-r--r--lib/bundler/dependency.rb13
-rw-r--r--lib/bundler/deployment.rb66
-rw-r--r--lib/bundler/dsl.rb137
-rw-r--r--lib/bundler/fetcher.rb326
-rw-r--r--lib/bundler/fetcher/base.rb27
-rw-r--r--lib/bundler/fetcher/dependency.rb88
-rw-r--r--lib/bundler/fetcher/downloader.rb61
-rw-r--r--lib/bundler/fetcher/index.rb31
-rw-r--r--lib/bundler/friendly_errors.rb17
-rw-r--r--lib/bundler/gem_helper.rb9
-rw-r--r--lib/bundler/gem_helpers.rb1
-rw-r--r--lib/bundler/index.rb4
-rw-r--r--lib/bundler/installer.rb101
-rw-r--r--lib/bundler/installer/parallel_installer.rb117
-rw-r--r--lib/bundler/lazy_specification.rb2
-rw-r--r--lib/bundler/lockfile_parser.rb30
-rw-r--r--lib/bundler/match_platform.rb2
-rw-r--r--lib/bundler/remote_specification.rb20
-rw-r--r--lib/bundler/resolver.rb8
-rw-r--r--lib/bundler/retry.rb21
-rw-r--r--lib/bundler/rubygems_integration.rb47
-rw-r--r--lib/bundler/runtime.rb3
-rw-r--r--lib/bundler/settings.rb52
-rw-r--r--lib/bundler/shared_helpers.rb40
-rw-r--r--lib/bundler/source.rb5
-rw-r--r--lib/bundler/source/git.rb4
-rw-r--r--lib/bundler/source/path.rb2
-rw-r--r--lib/bundler/source/path/installer.rb25
-rw-r--r--lib/bundler/source/rubygems.rb61
-rw-r--r--lib/bundler/source_list.rb16
-rw-r--r--lib/bundler/templates/newgem/.travis.yml.tt1
-rw-r--r--lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt4
-rw-r--r--lib/bundler/templates/newgem/Rakefile.tt2
-rw-r--r--lib/bundler/templates/newgem/newgem.gemspec.tt12
-rw-r--r--lib/bundler/templates/newgem/test/newgem_test.rb.tt (renamed from lib/bundler/templates/newgem/test/test_newgem.rb.tt)4
-rw-r--r--lib/bundler/templates/newgem/test/test_helper.rb.tt (renamed from lib/bundler/templates/newgem/test/minitest_helper.rb.tt)0
-rw-r--r--lib/bundler/ui/shell.rb18
-rw-r--r--lib/bundler/ui/silent.rb3
-rw-r--r--lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo.rb5
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo.rb5
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb (renamed from lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/dependency_graph.rb)2
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/errors.rb (renamed from lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/errors.rb)0
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb (renamed from lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/gem_metadata.rb)2
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb (renamed from lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/modules/specification_provider.rb)0
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb (renamed from lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/modules/ui.rb)0
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb (renamed from lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/resolution.rb)27
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb (renamed from lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/resolver.rb)4
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/state.rb (renamed from lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/state.rb)0
-rw-r--r--lib/bundler/vendor/thor-0.19.1/lib/thor/parser.rb4
-rw-r--r--lib/bundler/vendor/thor/lib/thor.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor.rb)2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/actions.rb)14
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions/create_file.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/actions/create_file.rb)2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions/create_link.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/actions/create_link.rb)2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions/directory.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/actions/directory.rb)2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/actions/empty_directory.rb)0
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/actions/file_manipulation.rb)0
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/actions/inject_into_file.rb)2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/base.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/base.rb)24
-rw-r--r--lib/bundler/vendor/thor/lib/thor/command.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/command.rb)0
-rw-r--r--lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/core_ext/hash_with_indifferent_access.rb)0
-rw-r--r--lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/core_ext/io_binary_read.rb)0
-rw-r--r--lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/core_ext/ordered_hash.rb)0
-rw-r--r--lib/bundler/vendor/thor/lib/thor/error.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/error.rb)0
-rw-r--r--lib/bundler/vendor/thor/lib/thor/group.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/group.rb)2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/invocation.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/invocation.rb)0
-rw-r--r--lib/bundler/vendor/thor/lib/thor/line_editor.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/line_editor.rb)4
-rw-r--r--lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/line_editor/basic.rb)0
-rw-r--r--lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/line_editor/readline.rb)0
-rw-r--r--lib/bundler/vendor/thor/lib/thor/parser.rb4
-rw-r--r--lib/bundler/vendor/thor/lib/thor/parser/argument.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/parser/argument.rb)0
-rw-r--r--lib/bundler/vendor/thor/lib/thor/parser/arguments.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/parser/arguments.rb)0
-rw-r--r--lib/bundler/vendor/thor/lib/thor/parser/option.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/parser/option.rb)0
-rw-r--r--lib/bundler/vendor/thor/lib/thor/parser/options.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/parser/options.rb)0
-rw-r--r--lib/bundler/vendor/thor/lib/thor/rake_compat.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/rake_compat.rb)2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/runner.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/runner.rb)8
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/shell.rb)6
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell/basic.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/shell/basic.rb)0
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell/color.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/shell/color.rb)2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell/html.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/shell/html.rb)2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/util.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/util.rb)0
-rw-r--r--lib/bundler/vendor/thor/lib/thor/version.rb (renamed from lib/bundler/vendor/thor-0.19.1/lib/thor/version.rb)0
-rw-r--r--lib/bundler/vendored_molinillo.rb7
-rw-r--r--lib/bundler/vendored_thor.rb8
-rw-r--r--lib/bundler/version.rb2
-rw-r--r--man/bundle-config.ronn43
-rw-r--r--man/bundle-install.ronn54
-rw-r--r--man/gemfile.5.ronn14
-rw-r--r--spec/bundler/bundler_spec.rb8
-rw-r--r--spec/bundler/fetcher_spec.rb11
-rw-r--r--spec/bundler/friendly_errors_spec.rb17
-rw-r--r--spec/bundler/gem_helper_spec.rb19
-rw-r--r--spec/bundler/retry_spec.rb11
-rw-r--r--spec/bundler/settings_spec.rb28
-rw-r--r--spec/bundler/source_list_spec.rb31
-rw-r--r--spec/cache/git_spec.rb2
-rw-r--r--spec/commands/binstubs_spec.rb6
-rw-r--r--spec/commands/check_spec.rb12
-rw-r--r--spec/commands/clean_spec.rb26
-rw-r--r--spec/commands/config_spec.rb3
-rw-r--r--spec/commands/exec_spec.rb14
-rw-r--r--spec/commands/lock_spec.rb5
-rw-r--r--spec/commands/newgem_spec.rb107
-rw-r--r--spec/commands/open_spec.rb8
-rw-r--r--spec/commands/outdated_spec.rb35
-rw-r--r--spec/commands/package_spec.rb2
-rw-r--r--spec/commands/show_spec.rb2
-rw-r--r--spec/deprecation_spec.rb119
-rw-r--r--spec/install/bundler_spec.rb6
-rw-r--r--spec/install/force_spec.rb20
-rw-r--r--spec/install/gemfile/git_spec.rb6
-rw-r--r--spec/install/gemfile/path_spec.rb6
-rw-r--r--spec/install/gems/flex_spec.rb3
-rw-r--r--spec/install/gems/groups_spec.rb74
-rw-r--r--spec/install/gems/install_if.rb38
-rw-r--r--spec/install/gems/post_install_spec.rb195
-rw-r--r--spec/install/gems/sources_spec.rb101
-rw-r--r--spec/install/gems/sudo_spec.rb20
-rw-r--r--spec/install/gemspecs_spec.rb4
-rw-r--r--spec/install/parallel/spec_installation_spec.rb37
-rw-r--r--spec/install/post_bundle_message_spec.rb16
-rw-r--r--spec/lock/lockfile_spec.rb341
-rw-r--r--spec/other/bundle_ruby_spec.rb158
-rw-r--r--spec/other/ext_spec.rb16
-rw-r--r--spec/other/platform_spec.rb8
-rw-r--r--spec/quality_spec.rb2
-rw-r--r--spec/realworld/edgecases_spec.rb4
-rw-r--r--spec/realworld/parallel_spec.rb4
-rw-r--r--spec/resolver/platform_spec.rb13
-rw-r--r--spec/runtime/gem_tasks_spec.rb35
-rw-r--r--spec/runtime/require_spec.rb18
-rw-r--r--spec/runtime/setup_spec.rb74
-rw-r--r--spec/support/builders.rb13
-rw-r--r--spec/support/matchers.rb12
-rw-r--r--spec/update/gems_spec.rb15
-rw-r--r--spec/update/git_spec.rb2
146 files changed, 2878 insertions, 865 deletions
diff --git a/.travis.yml b/.travis.yml
index cc6bb6fda3..95c2f51d61 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,7 +5,12 @@ before_script: travis_retry rake spec:travis:deps
branches:
only:
- master
+<<<<<<< HEAD
- 2-0-dev
+=======
+ - 1-99-dev
+ - 1-9-stable
+>>>>>>> 1-99-dev
- 1-8-stable
- 1-7-stable
- 1-6-stable
@@ -33,6 +38,7 @@ rvm:
- 2.0.0
- 1.9.3
- 1.8.7
+ - rbx-2
# Rubygems versions MUST be available as rake tasks
# see Rakefile:66 for the list of possible RGV values
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2c9a0ac206..3a037c104d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,95 @@
+## 1.10.0.pre.1 (2015-05-05)
+
+Bugfixes:
+
+ - always clean up tmp dirs (#3277, @hone, @indirect, @segiddins)
+
+## 1.10.0.pre (2015-05-03)
+
+Features:
+
+ - support gem extensions built into any directory on RubyGems 2.2+ (#3582, @voxik)
+ - add 'bundler/inline' which provides a `gemfile` method (#3440, @segiddins)
+ - improved error reports for Gemfile errors (#3480, @segiddins)
+ - `lock` command (#3437, @segiddins)
+ - add `ignore_messages` config to suppress post-install text (#3510, @pducks32)
+ - improve `gem` minitest template (#3513, #3515, @arthurnn)
+ - add `install --force` to re-install installed gems (#3519, @segiddins)
+ - show more `outdated` information, including groups (@smlance, @indirect)
+ - add optional groups to the Gemfile (#3531, @jhass)
+ - accept glob argument to `gemspec` in Gemfile (#3464, @pjump)
+ - make timeouts and retries configurable via `config` (#3601, @pducks32)
+ - add `install_if` Gemfile method for conditional installs (#3611, @segiddins)
+
+Bugfixes:
+
+ - standalone mode now uses builtin gems correctly (#3610, @segiddins)
+ - fix `rake spec:deps` on MinGW Ruby 2.0+ (#3487, @marutosi)
+ - remember all y/n answers when generating gems (#3579, @pducks32)
+
+Performance:
+
+ - use RubyGems stub specifications when possible (#3580, @segiddins)
+
+Deprecations:
+
+ - deprecated the (never enabled) `bundle_ruby` binary (@smlance)
+
+## 1.9.6 (2015-05-02)
+
+Bugfixes:
+
+ - use RubyGems spec stubs if available (@segiddins)
+ - allow creating gems with names containing two dashes (#3483, @janlelis)
+ - allow creating gems with names extending constants (#3603, @amatsuda)
+
+## 1.9.5 (2015-04-29)
+
+Bugfixes:
+
+ - respect Gemfile sources when installing a gem present in two sources (#3585, @tmoore)
+
+## 1.9.4 (2015-04-13)
+
+Bugfixes:
+
+ - fix regression in installing x86 and universal gems (#3565, @jdmundrawala)
+ - improve error when gems are missing (#3564, @sealocal)
+
+## 1.9.3 (2015-04-12)
+
+Bugfixes:
+
+ - handle removal of `specs` from rubygems/rubygems@620910 (#3558, @indirect)
+ - install 'universal' gems on Windows (#3066, @jdmundrawala)
+ - stop passing --local during `rake install` task (#3236, @indirect)
+ - guard against all possible accidental public gem pushes (#3533, @indirect)
+
+## 1.9.2 (2015-03-30)
+
+Bugfixes:
+
+ - ensure gem executables are executable (#3517, #3511, @indirect)
+ - fix warnings in Molinillo (#3516, @segiddins)
+ - ensure duplicate dependencies do not propagate (#3522, @segiddins)
+ - keep gems locked when updating another gem from the same source (#3520, @indirect)
+ - resolve race that could build gems without saved arguments (#3404, @indirect)
+
+## 1.9.1 (2015-03-21)
+
+Bugfixes:
+
+ - avoid exception in 'bundler/gem_tasks' (#3492, @segiddins)
+
+## 1.9.0 (2015-03-20)
+
## 1.9.0.rc (2015-03-13)
Bugfixes:
- make Bundler.which stop finding directories (@nohoho)
- handle Bundler prereleases correctly (#3470, @segiddins)
+ - add before_install to .travis.yml template for new gems (@kodnin)
## 1.9.0.pre.1 (2015-03-11)
@@ -23,6 +109,31 @@ Features:
- Molinillo resolver, shared with CocoaPods (@segiddins)
- updated Thor to v0.19.1 (@segiddins)
+## 1.8.9 (2015-05-02)
+
+Bugfixes:
+
+ - Use RubyGems spec stubs if available (@segiddins)
+
+## 1.8.8 (2015-04-29)
+
+Bugfixes:
+
+ - Respect Gemfile sources when installing a gem present in two sources (#3585, @tmoore)
+
+## 1.8.7 (2015-04-07)
+
+Bugfixes:
+
+ - stop suppressing errors inside gems that get required (#3549, @indirect)
+
+## 1.8.6 (2015-03-30)
+
+Bugfixes:
+
+ - keep gems locked when updating another gem from the same source (#3250, @indirect)
+ - resolve race that could build gems without saved arguments (#3404, @indirect)
+
## 1.8.5 (2015-03-11)
Bugfixes:
@@ -122,6 +233,19 @@ Documentation:
- add missing Gemfile global `path` explanation (@agenteo)
+## 1.7.15 (2015-04-29)
+
+Bugfixes:
+
+ - Respect Gemfile sources when installing a gem present in two sources (#3585, @tmoore)
+
+## 1.7.14 (2015-03-30)
+
+Bugfixes:
+
+ - Keep gems locked when updating another gem from the same source (#3250, @indirect)
+ - Don't add extra quotes around long, quoted config values (@aroben, #3338)
+
## 1.7.13 (2015-02-07)
Bugfixes:
diff --git a/Rakefile b/Rakefile
index 1a9a31a137..462c3be143 100644
--- a/Rakefile
+++ b/Rakefile
@@ -27,23 +27,32 @@ module Rake
end
end
+def clean_files(files, regex, replacement = '')
+ files.each do |file|
+ contents = File.read(file)
+ contents.gsub!(regex, replacement)
+ File.open(file, 'w') { |f| f << contents }
+ end
+end
+
namespace :molinillo do
task :namespace do
- files = Dir.glob('lib/bundler/vendor/Molinillo*/**/*.rb')
- sh "sed -i.bak 's/Molinillo/Bundler::Molinillo/g' #{files.join(' ')}"
- sh "rm #{files.join('.bak ')}.bak"
+ files = Dir.glob('lib/bundler/vendor/molinillo*/**/*.rb')
+ clean_files(files, 'Molinillo', 'Bundler::Molinillo')
+ clean_files(files, /require (["'])molinillo/, 'require \1bundler/vendor/molinillo/lib/molinillo')
end
task :clean do
- files = Dir.glob('lib/bundler/vendor/Molinillo*/*', File::FNM_DOTMATCH).reject { |f| %(. .. lib).include? f.split('/').last }
- puts files
- sh "rm -r #{files.join(' ')}"
+ files = Dir.glob('lib/bundler/vendor/molinillo*/*', File::FNM_DOTMATCH).reject { |f| %(. .. lib).include? f.split('/').last }
+ rm_r files
end
task :update, [:tag] => [] do |t, args|
tag = args[:tag]
Dir.chdir 'lib/bundler/vendor' do
- `curl -L https://github.com/CocoaPods/molinillo/archive/#{tag}.tar.gz | tar -xz`
+ rm_rf 'molinillo'
+ sh "curl -L https://github.com/CocoaPods/molinillo/archive/#{tag}.tar.gz | tar -xz"
+ sh "mv Molinillo-* molinillo"
end
Rake::Task['molinillo:namespace'].invoke
Rake::Task['molinillo:clean'].invoke
@@ -53,20 +62,22 @@ end
namespace :thor do
task :namespace do
files = Dir.glob('lib/bundler/vendor/thor*/**/*.rb')
- sh "sed -i.bak 's/Thor/Bundler::Thor/g' #{files.join(' ')}"
- sh "rm #{files.join('.bak ')}.bak"
+ clean_files(files, 'Thor', 'Bundler::Thor')
+ clean_files(files, /require (["'])thor/, 'require \1bundler/vendor/thor/lib/thor')
+ clean_files(files, /(autoload\s+[:\w]+,\s+["'])(thor[\w\/]+["'])/, '\1bundler/vendor/thor/lib/\2')
end
task :clean do
files = Dir.glob('lib/bundler/vendor/thor*/*', File::FNM_DOTMATCH).reject { |f| %(. .. lib).include? f.split('/').last }
- puts files
- sh "rm -r #{files.join(' ')}"
+ rm_r files
end
task :update, [:tag] => [] do |t, args|
tag = args[:tag]
Dir.chdir 'lib/bundler/vendor' do
- `curl -L https://github.com/erikhuda/thor/archive/#{tag}.tar.gz | tar -xz`
+ rm_rf 'thor'
+ sh "curl -L https://github.com/erikhuda/thor/archive/#{tag}.tar.gz | tar -xz"
+ sh "mv thor-* thor"
end
Rake::Task['thor:namespace'].invoke
Rake::Task['thor:clean'].invoke
@@ -280,12 +291,15 @@ begin
task :clean do
rm_rf "lib/bundler/man"
end
+
+ task(:require) { }
end
rescue LoadError
namespace :man do
- task(:build) { warn "Install the ronn gem to be able to release!" }
- task(:clean) { warn "Install the ronn gem to be able to release!" }
+ task(:require) { abort "Install the ronn gem to be able to release!" }
+ task(:build) { warn "Install the ronn gem to build the help pages" }
+ task(:clean) { }
end
end
@@ -297,6 +311,6 @@ end
require 'bundler/gem_tasks'
task :build => ["man:clean", "man:build"]
-task :release => ["man:clean", "man:build"]
+task :release => ["man:require", "man:clean", "man:build"]
task :default => :spec
diff --git a/bin/bundle_ruby b/bin/bundle_ruby
new file mode 100755
index 0000000000..1309b8d6fd
--- /dev/null
+++ b/bin/bundle_ruby
@@ -0,0 +1,59 @@
+#!/usr/bin/env ruby
+
+Signal.trap("INT") { exit 1 }
+
+require 'bundler/ruby_version'
+require 'bundler/ruby_dsl'
+require 'bundler/shared_helpers'
+
+module Bundler
+ class GemfileError < RuntimeError; end
+ class Dsl
+ include RubyDsl
+
+ attr_accessor :ruby_version
+
+ def initialize
+ @ruby_version = nil
+ end
+
+ def eval_gemfile(gemfile, contents = nil)
+ contents ||= File.open(gemfile, "rb") { |f| f.read }
+ instance_eval(contents, gemfile.to_s, 1)
+ rescue SyntaxError => e
+ bt = e.message.split("\n")[1..-1]
+ raise GemfileError, ["Gemfile syntax error:", *bt].join("\n")
+ rescue ScriptError, RegexpError, NameError, ArgumentError => e
+ e.backtrace[0] = "#{e.backtrace[0]}: #{e.message} (#{e.class})"
+ STDERR.puts e.backtrace.join("\n ")
+ raise GemfileError, "There was an error in your Gemfile," \
+ " and Bundler cannot continue."
+ end
+
+ def source(source, options = {})
+ end
+
+ def gem(name, *args)
+ end
+
+ def group(*args, &blk)
+ end
+ end
+end
+
+STDERR.puts "DEPRECATION: bundle_ruby is deprecated and will be removed in " \
+ "Bundler 2.0."
+
+dsl = Bundler::Dsl.new
+begin
+ dsl.eval_gemfile(Bundler::SharedHelpers.default_gemfile)
+ ruby_version = dsl.ruby_version
+ if ruby_version
+ puts ruby_version
+ else
+ puts "No ruby version specified"
+ end
+rescue Bundler::GemfileError => e
+ puts e.message
+ exit(-1)
+end
diff --git a/bundler.gemspec b/bundler.gemspec
index bd7e32e7c9..c9fafa59bd 100644
--- a/bundler.gemspec
+++ b/bundler.gemspec
@@ -16,10 +16,11 @@ Gem::Specification.new do |s|
s.required_ruby_version = '>= 1.8.7'
s.required_rubygems_version = '>= 1.3.6'
- s.add_development_dependency 'mustache', '0.99.6'
+ s.add_development_dependency 'mustache', '0.99.6'
s.add_development_dependency 'rdiscount', '~> 1.6'
- s.add_development_dependency 'ronn', '~> 0.7.3'
- s.add_development_dependency 'rspec', '~> 3.0'
+ s.add_development_dependency 'ronn', '~> 0.7.3'
+ s.add_development_dependency 'rspec', '~> 3.0'
+ s.add_development_dependency 'rake'
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
# we don't check in man pages, but we need to ship them because
diff --git a/lib/bundler.rb b/lib/bundler.rb
index 83c066e5e5..197e88c222 100644
--- a/lib/bundler.rb
+++ b/lib/bundler.rb
@@ -120,12 +120,7 @@ module Bundler
# Load all groups, but only once
@setup = load.setup
else
- @completed_groups ||= []
- # Figure out which groups haven't been loaded yet
- unloaded = groups - @completed_groups
- # Record groups that are now loaded
- @completed_groups = groups
- unloaded.any? ? load.setup(*groups) : load
+ load.setup(*groups)
end
end
@@ -211,13 +206,11 @@ module Bundler
end
def tmp(name = Process.pid.to_s)
- @tmp ||= Pathname.new Dir.mktmpdir("bundler")
- @tmp.join(name)
+ Pathname.new(Dir.mktmpdir(["bundler", name]))
end
- def cleanup
- FileUtils.remove_entry_secure(@tmp) if @tmp
- rescue
+ def rm_rf(path)
+ FileUtils.remove_entry_secure(path) if path && File.exist?(path)
end
def settings
diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb
index 7d9d9d949c..37844de4d3 100644
--- a/lib/bundler/cli.rb
+++ b/lib/bundler/cli.rb
@@ -11,8 +11,6 @@ module Bundler
rescue Exception => e
Bundler.ui = UI::Shell.new
raise e
- ensure
- Bundler.cleanup
end
def initialize(*args)
@@ -20,7 +18,7 @@ module Bundler
current_cmd = args.last[:current_command].name
custom_gemfile = options[:gemfile] || Bundler.settings[:gemfile]
ENV['BUNDLE_GEMFILE'] = File.expand_path(custom_gemfile) if custom_gemfile
- Bundler::Retry.attempts = options[:retry] || Bundler.settings[:retry] || Bundler::Retry::DEFAULT_ATTEMPTS
+ Bundler.settings[:retry] = options[:retry] if options[:retry]
Bundler.rubygems.ui = UI::RGProxy.new(Bundler.ui)
auto_install if AUTO_INSTALL_CMDS.include?(current_cmd)
rescue UnknownArgumentError => e
@@ -134,6 +132,8 @@ module Bundler
"Do not attempt to fetch gems remotely and use the gem cache instead"
method_option "cache", :type => :boolean, :banner =>
"Update the existing gem cache."
+ method_option "force", :type => :boolean, :banner =>
+ "Force downloading every gem."
method_option "no-prune", :type => :boolean, :banner =>
"Don't remove stale gems from the cache."
method_option "path", :type => :string, :banner =>
@@ -151,6 +151,8 @@ module Bundler
Bundler.rubygems.security_policy_keys.join('|')
method_option "without", :type => :array, :banner =>
"Exclude gems that are part of the specified named group."
+ method_option "with", :type => :array, :banner =>
+ "Include gems that are part of the specified named group."
def install
require 'bundler/cli/install'
@@ -175,6 +177,8 @@ module Bundler
"Only output warnings and errors."
method_option "source", :type => :array, :banner =>
"Update a specific source (and all gems associated with it)"
+ method_option "force", :type => :boolean, :banner =>
+ "Force downloading every gem."
def update(*gems)
require 'bundler/cli/update'
Update.new(options, gems).run
diff --git a/lib/bundler/cli/gem.rb b/lib/bundler/cli/gem.rb
index 9ce8de4a05..f58e12a594 100644
--- a/lib/bundler/cli/gem.rb
+++ b/lib/bundler/cli/gem.rb
@@ -20,9 +20,9 @@ module Bundler
underscored_name = name.tr('-', '_')
namespaced_path = name.tr('-', '/')
- constant_name = name.split('_').map{|p| p[0..0].upcase + p[1..-1] unless p.empty?}.join
- constant_name = constant_name.split('-').map{|q| q[0..0].upcase + q[1..-1] }.join('::') if constant_name =~ /-/
+ constant_name = name.gsub(/-[_-]*(?![_-]|$)/){ '::' }.gsub(/([_-]+|(::)|^)(.|$)/){ $2.to_s + $3.upcase }
constant_array = constant_name.split('::')
+
git_user_name = `git config user.name`.chomp
git_user_email = `git config user.email`.chomp
@@ -54,6 +54,11 @@ module Bundler
"bin/setup.tt" => "bin/setup"
}
+ executables = %w[
+ bin/console
+ bin/setup
+ ]
+
if ask_and_set(:coc, "Do you want to include a code of conduct in gems you generate?",
"Codes of conduct can increase contributions to your project by contributors who " \
"prefer collaborative, safe spaces. You can read more about the code of conduct at " \
@@ -61,6 +66,7 @@ module Bundler
"of enforcing it, so be sure that you are prepared to do that. For suggestions about " \
"how to enforce codes of conduct, see bit.ly/coc-enforcement."
)
+ Bundler.ui.info "Code of conduct enabled in config"
templates.merge!("CODE_OF_CONDUCT.md.tt" => "CODE_OF_CONDUCT.md")
end
@@ -70,10 +76,12 @@ module Bundler
"at choosealicense.com/licenses/mit."
)
config[:mit] = true
+ Bundler.ui.info "MIT License enabled in config"
templates.merge!("LICENSE.txt.tt" => "LICENSE.txt")
end
if test_framework = ask_and_set_test_framework
+ config[:test] = test_framework
templates.merge!(".travis.yml.tt" => ".travis.yml")
case test_framework
@@ -85,8 +93,8 @@ module Bundler
)
when 'minitest'
templates.merge!(
- "test/minitest_helper.rb.tt" => "test/minitest_helper.rb",
- "test/test_newgem.rb.tt" => "test/test_#{namespaced_path}.rb"
+ "test/test_helper.rb.tt" => "test/test_helper.rb",
+ "test/newgem_test.rb.tt" => "test/#{namespaced_path}_test.rb"
)
end
end
@@ -105,6 +113,12 @@ module Bundler
thor.template("newgem/#{src}", target.join(dst), config)
end
+ executables.each do |file|
+ path = target.join(file)
+ executable = (path.stat.mode | 0111)
+ path.chmod(executable)
+ end
+
Bundler.ui.info "Initializing git repo in #{target}"
Dir.chdir(target) { `git init`; `git add .` }
@@ -125,7 +139,7 @@ module Bundler
if choice.nil?
Bundler.ui.confirm header
- choice = (Bundler.ui.ask("#{message} y/(n):") =~ /y|yes/)
+ choice = Bundler.ui.yes? "#{message} y/(n):"
Bundler.settings.set_global("gem.#{key}", choice)
end
@@ -174,7 +188,7 @@ module Bundler
if name =~ /^\d/
Bundler.ui.error "Invalid gem name #{name} Please give a name which does not start with numbers."
exit 1
- elsif Object.const_defined?(constant_array.first)
+ elsif constant_array.inject(Object) {|c, s| (c.const_defined?(s) && c.const_get(s)) || break }
Bundler.ui.error "Invalid gem name #{name} constant #{constant_array.join("::")} is already in use. Please choose another gem name."
exit 1
end
diff --git a/lib/bundler/cli/install.rb b/lib/bundler/cli/install.rb
index e88c093538..7d09444596 100644
--- a/lib/bundler/cli/install.rb
+++ b/lib/bundler/cli/install.rb
@@ -10,10 +10,35 @@ module Bundler
warn_if_root
- if options[:without]
- options[:without] = options[:without].map{|g| g.tr(' ', ':') }
+ [:with, :without].each do |option|
+ if options[option]
+ options[option] = options[option].join(":").tr(" ", ":").split(":")
+ end
+ end
+
+ if options[:without] && options[:with]
+ conflicting_groups = options[:without] & options[:with]
+ unless conflicting_groups.empty?
+ Bundler.ui.error "You can't list a group in both, --with and --without." \
+ "The offending groups are: #{conflicting_groups.join(", ")}."
+ exit 1
+ end
end
+ Bundler.settings.with = [] if options[:with] && options[:with].empty?
+ Bundler.settings.without = [] if options[:without] && options[:without].empty?
+
+ with = options.fetch("with", [])
+ with |= Bundler.settings.with.map {|group| group.to_s }
+ with -= options[:without] if options[:without]
+
+ without = options.fetch("without", [])
+ without |= Bundler.settings.without.map {|group| group.to_s }
+ without -= options[:with] if options[:with]
+
+ options[:with] = with
+ options[:without] = without
+
ENV['RB_USER_INSTALL'] = '1' if Bundler::FREEBSD
# Just disable color in deployment mode
@@ -69,6 +94,7 @@ module Bundler
Bundler.settings[:no_install] = true if options["no-install"]
Bundler.settings[:clean] = options["clean"] if options["clean"]
Bundler.settings.without = options[:without]
+ Bundler.settings.with = options[:with]
Bundler::Fetcher.disable_endpoint = options["full-index"]
Bundler.settings[:disable_shared_gems] = Bundler.settings[:path] ? '1' : nil
@@ -91,9 +117,10 @@ module Bundler
Bundler.ui.confirm "Use `bundle show [gemname]` to see where a bundled gem is installed."
end
- Installer.post_install_messages.to_a.each do |name, msg|
- Bundler.ui.confirm "Post-install message from #{name}:"
- Bundler.ui.info msg
+ unless Bundler.settings["ignore_messages"]
+ Installer.post_install_messages.to_a.each do |name, msg|
+ print_post_install_message(name, msg) unless Bundler.settings["ignore_messages.#{name}"]
+ end
end
Installer.ambiguous_gems.to_a.each do |name, installed_from_uri, *also_found_in_uris|
@@ -152,5 +179,10 @@ module Bundler
"#{count} #{count == 1 ? 'gem' : 'gems'} now installed"
end
+ def print_post_install_message(name, msg)
+ Bundler.ui.confirm "Post-install message from #{name}:"
+ Bundler.ui.info msg
+ end
+
end
end
diff --git a/lib/bundler/cli/outdated.rb b/lib/bundler/cli/outdated.rb
index f8779d762a..08bcbde609 100644
--- a/lib/bundler/cli/outdated.rb
+++ b/lib/bundler/cli/outdated.rb
@@ -62,8 +62,15 @@ module Bundler
spec_version = "#{active_spec.version}#{active_spec.git_version}"
current_version = "#{current_spec.version}#{current_spec.git_version}"
- dependency_version = %|Gemfile specifies "#{dependency.requirement}"| if dependency && dependency.specific?
- Bundler.ui.info " * #{active_spec.name} (#{spec_version} > #{current_version}) #{dependency_version}".rstrip
+ dependency_version = %|, requested #{dependency.requirement}| if dependency && dependency.specific?
+
+ if dependency
+ groups = dependency.groups.join(", ")
+ pl = (dependency.groups.length > 1) ? "s" : ""
+ groups = " in group#{pl} \"#{groups}\""
+ end
+
+ Bundler.ui.info " * #{active_spec.name} (newest #{spec_version}, installed #{current_version}#{dependency_version})#{groups}".rstrip
out_count += 1
end
Bundler.ui.debug "from #{active_spec.loaded_from}"
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index 4c15866577..eb97b81a5d 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -43,10 +43,11 @@ module Bundler
# @param unlock [Hash, Boolean, nil] Gems that have been requested
# to be updated or true if all gems should be updated
# @param ruby_version [Bundler::RubyVersion, nil] Requested Ruby Version
- def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil)
+ # @param optional_groups [Array(String)] A list of optional groups
+ def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, optional_groups = [])
@unlocking = unlock == true || !unlock.empty?
- @dependencies, @sources, @unlock = dependencies, sources, unlock
+ @dependencies, @sources, @unlock, @optional_groups = dependencies, sources, unlock, optional_groups
@remote = false
@specs = nil
@lockfile_contents = ""
@@ -56,6 +57,7 @@ module Bundler
@lockfile_contents = Bundler.read_file(lockfile)
locked = LockfileParser.new(@lockfile_contents)
@platforms = locked.platforms
+ @locked_bundler_version = locked.bundler_version
if unlock != true
@locked_deps = locked.dependencies
@@ -161,7 +163,7 @@ module Bundler
def requested_specs
@requested_specs ||= begin
- groups = self.groups - Bundler.settings.without
+ groups = requested_groups
groups.map! { |g| g.to_sym }
specs_for(groups)
end
@@ -184,11 +186,10 @@ module Bundler
# @return [SpecSet] resolved dependencies
def resolve
@resolve ||= begin
+ last_resolve = converge_locked_specs
if Bundler.settings[:frozen] || (!@unlocking && nothing_changed?)
- @locked_specs
+ last_resolve
else
- last_resolve = converge_locked_specs
-
# Run a resolve against the locally available gems
last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve)
end
@@ -248,6 +249,16 @@ module Bundler
return
end
+ if @locked_bundler_version
+ locked_major = @locked_bundler_version.segments.first
+ current_major = Gem::Version.create(Bundler::VERSION).segments.first
+
+ if locked_major < current_major
+ Bundler.ui.warn "Warning: the lockfile is being updated to Bundler #{Bundler::VERSION.split('.').first}, " \
+ "after which you will be unable to return to Bundler #{@locked_bundler_version.segments.first}."
+ end
+ end
+
File.open(file, 'wb'){|f| f.puts(contents) }
rescue Errno::EACCES
raise Bundler::InstallError,
@@ -256,6 +267,16 @@ module Bundler
"#{File.expand_path(file)}"
end
+ # Returns the version of Bundler that is creating or has created
+ # Gemfile.lock. Used in #to_lock.
+ def lock_version
+ if @locked_bundler_version && @locked_bundler_version < Gem::Version.new(Bundler::VERSION)
+ new_version = Bundler::VERSION
+ end
+
+ new_version || @locked_bundler_version || Bundler::VERSION
+ end
+
def to_lock
out = ""
@@ -272,7 +293,7 @@ module Bundler
each do |spec|
next if spec.name == 'bundler'
out << spec.to_lock
- end
+ end
out << "\n"
end
@@ -294,6 +315,10 @@ module Bundler
handled << dep.name
end
+ # Record the version of Bundler that was used to create the lockfile
+ out << "\nBUNDLED WITH\n"
+ out << " #{lock_version}\n"
+
out
end
@@ -521,7 +546,9 @@ module Bundler
converged = []
@locked_specs.each do |s|
- s.source = sources.get(s.source)
+ # Replace the locked dependency's source with the equivalent source from the Gemfile
+ dep = @dependencies.find { |d| s.satisfies?(d) }
+ s.source = (dep && dep.source) || sources.get(s.source)
# Don't add a spec to the list if its source is expired. For example,
# if you change a Git gem to Rubygems.
@@ -561,12 +588,15 @@ module Bundler
resolve
end
- def in_locked_deps?(dep, d)
- d && dep.source == d.source
+ def in_locked_deps?(dep, locked_dep)
+ # Because the lockfile can't link a dep to a specific remote, we need to
+ # treat sources as equivalent anytime the locked dep has all the remotes
+ # that the Gemfile dep does.
+ locked_dep && locked_dep.source && dep.source && locked_dep.source.include?(dep.source)
end
def satisfies_locked_spec?(dep)
- @locked_specs.any? { |s| s.satisfies?(dep) && (!dep.source || s.source == dep.source) }
+ @locked_specs.any? { |s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) }
end
def expanded_dependencies
@@ -586,7 +616,7 @@ module Bundler
end
def requested_dependencies
- groups = self.groups - Bundler.settings.without
+ groups = requested_groups
groups.map! { |g| g.to_sym }
dependencies.reject { |d| !d.should_include? || (d.groups & groups).empty? }
end
@@ -620,5 +650,8 @@ module Bundler
names
end
+ def requested_groups
+ self.groups - Bundler.settings.without - @optional_groups + Bundler.settings.with
+ end
end
end
diff --git a/lib/bundler/dependency.rb b/lib/bundler/dependency.rb
index 6a9284fd56..e58ed4b7d5 100644
--- a/lib/bundler/dependency.rb
+++ b/lib/bundler/dependency.rb
@@ -50,11 +50,12 @@ module Bundler
type = options["type"] || :runtime
super(name, version, type)
- @autorequire = nil
- @groups = Array(options["group"] || :default).map { |g| g.to_sym }
- @source = options["source"]
- @platforms = Array(options["platforms"])
- @env = options["env"]
+ @autorequire = nil
+ @groups = Array(options["group"] || :default).map { |g| g.to_sym }
+ @source = options["source"]
+ @platforms = Array(options["platforms"])
+ @env = options["env"]
+ @should_include = options.fetch("should_include", true)
if options.key?('require')
@autorequire = Array(options['require'] || [])
@@ -74,7 +75,7 @@ module Bundler
end
def should_include?
- current_env? && current_platform?
+ @should_include && current_env? && current_platform?
end
def current_env?
diff --git a/lib/bundler/deployment.rb b/lib/bundler/deployment.rb
new file mode 100644
index 0000000000..2a76ccc859
--- /dev/null
+++ b/lib/bundler/deployment.rb
@@ -0,0 +1,66 @@
+$stderr.puts "DEPRECATION: Bundler no longer integrates with " \
+ "Capistrano, but Capistrano provides its own integration with " \
+ "Bundler via the capistrano-bundler gem. Use it instead."
+
+module Bundler
+ class Deployment
+ def self.define_task(context, task_method = :task, opts = {})
+ if defined?(Capistrano) && context.is_a?(Capistrano::Configuration)
+ context_name = "capistrano"
+ role_default = "{:except => {:no_release => true}}"
+ error_type = ::Capistrano::CommandError
+ else
+ context_name = "vlad"
+ role_default = "[:app]"
+ error_type = ::Rake::CommandFailedError
+ end
+
+ roles = context.fetch(:bundle_roles, false)
+ opts[:roles] = roles if roles
+
+ context.send :namespace, :bundle do
+ send :desc, <<-DESC
+ Install the current Bundler environment. By default, gems will be \
+ installed to the shared/bundle path. Gems in the development and \
+ test group will not be installed. The install command is executed \
+ with the --deployment and --quiet flags. If the bundle cmd cannot \
+ be found then you can override the bundle_cmd variable to specify \
+ which one it should use. The base path to the app is fetched from \
+ the :latest_release variable. Set it for custom deploy layouts.
+
+ You can override any of these defaults by setting the variables shown below.
+
+ N.B. bundle_roles must be defined before you require 'bundler/#{context_name}' \
+ in your deploy.rb file.
+
+ set :bundle_gemfile, "Gemfile"
+ set :bundle_dir, File.join(fetch(:shared_path), 'bundle')
+ set :bundle_flags, "--deployment --quiet"
+ set :bundle_without, [:development, :test]
+ set :bundle_with, [:mysql]
+ set :bundle_cmd, "bundle" # e.g. "/opt/ruby/bin/bundle"
+ set :bundle_roles, #{role_default} # e.g. [:app, :batch]
+ DESC
+ send task_method, :install, opts do
+ bundle_cmd = context.fetch(:bundle_cmd, "bundle")
+ bundle_flags = context.fetch(:bundle_flags, "--deployment --quiet")
+ bundle_dir = context.fetch(:bundle_dir, File.join(context.fetch(:shared_path), 'bundle'))
+ bundle_gemfile = context.fetch(:bundle_gemfile, "Gemfile")
+ bundle_without = [*context.fetch(:bundle_without, [:development, :test])].compact
+ bundle_with = [*context.fetch(:bundle_with, [])].compact
+ app_path = context.fetch(:latest_release)
+ if app_path.to_s.empty?
+ raise error_type.new("Cannot detect current release path - make sure you have deployed at least once.")
+ end
+ args = ["--gemfile #{File.join(app_path, bundle_gemfile)}"]
+ args << "--path #{bundle_dir}" unless bundle_dir.to_s.empty?
+ args << bundle_flags.to_s
+ args << "--without #{bundle_without.join(" ")}" unless bundle_without.empty?
+ args << "--with #{bundle_with.join(" ")}" unless bundle_with.empty?
+
+ run "cd #{app_path} && #{bundle_cmd} install #{args.join(' ')}"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb
index f9f09e8b00..dfefc59785 100644
--- a/lib/bundler/dsl.rb
+++ b/lib/bundler/dsl.rb
@@ -16,14 +16,16 @@ module Bundler
attr_accessor :dependencies
def initialize
- @source = nil
- @sources = SourceList.new
- @git_sources = {}
- @dependencies = []
- @groups = []
- @platforms = []
- @env = nil
- @ruby_version = nil
+ @source = nil
+ @sources = SourceList.new
+ @git_sources = {}
+ @dependencies = []
+ @groups = []
+ @install_conditionals = []
+ @optional_groups = []
+ @platforms = []
+ @env = nil
+ @ruby_version = nil
add_git_sources
end
@@ -37,6 +39,7 @@ module Bundler
def gemspec(opts = nil)
path = opts && opts[:path] || '.'
+ glob = opts && opts[:glob]
name = opts && opts[:name] || '{,*}'
development_group = opts && opts[:development_group] || :development
expanded_path = File.expand_path(path, Bundler.default_gemfile.dirname)
@@ -47,7 +50,7 @@ module Bundler
when 1
spec = Bundler.load_gemspec(gemspecs.first)
raise InvalidOption, "There was an error loading the gemspec at #{gemspecs.first}." unless spec
- gem spec.name, :path => path
+ gem spec.name, :path => path, :glob => glob
group(development_group) do
spec.development_dependencies.each do |dep|
gem dep.name, *(dep.requirement.as_list + [:type => :development])
@@ -153,16 +156,32 @@ module Bundler
end
def to_definition(lockfile, unlock)
- Definition.new(lockfile, @dependencies, @sources, unlock, @ruby_version)
+ Definition.new(lockfile, @dependencies, @sources, unlock, @ruby_version, @optional_groups)
end
def group(*args, &blk)
+ opts = Hash === args.last ? args.pop.dup : {}
+ normalize_group_options(opts, args)
+
@groups.concat args
+
+ if opts["optional"]
+ optional_groups = args - @optional_groups
+ @optional_groups.concat optional_groups
+ end
+
yield
ensure
args.each { @groups.pop }
end
+ def install_if(*args, &blk)
+ @install_conditionals.concat args
+ blk.call
+ ensure
+ args.each { @groups.pop }
+ end
+
def platforms(*platforms)
@platforms.concat platforms
yield
@@ -187,12 +206,24 @@ module Bundler
def add_git_sources
git_source(:github) do |repo_name|
repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
- "git://github.com/#{repo_name}.git"
+ # TODO 2.0 upgrade this setting to the default
+ if Bundler.settings["github.https"]
+ "https://github.com/#{repo_name}.git"
+ else
+ warn_github_source_change(repo_name)
+ "git://github.com/#{repo_name}.git"
+ end
end
- git_source(:gist){ |repo_name| "https://gist.github.com/#{repo_name}.git" }
+ # TODO 2.0 remove this deprecated git source
+ git_source(:gist) do |repo_name|
+ warn_deprecated_git_source(:gist, 'https://gist.github.com/#{repo_name}.git')
+ "https://gist.github.com/#{repo_name}.git"
+ end
+ # TODO 2.0 remove this deprecated git source
git_source(:bitbucket) do |repo_name|
+ warn_deprecated_git_source(:bitbucket, 'https://#{user_name}@bitbucket.org/#{user_name}/#{repo_name}.git')
user_name, repo_name = repo_name.split '/'
repo_name ||= user_name
"https://#{user_name}@bitbucket.org/#{user_name}/#{repo_name}.git"
@@ -217,7 +248,7 @@ module Bundler
end
def valid_keys
- @valid_keys ||= %w(group groups git path name branch ref tag require submodules platform platforms type source)
+ @valid_keys ||= %w(group groups git path glob name branch ref tag require submodules platform platforms type source install_if)
end
def normalize_options(name, version, opts)
@@ -231,25 +262,19 @@ module Bundler
normalize_hash(opts)
git_names = @git_sources.keys.map(&:to_s)
-
- invalid_keys = opts.keys - (valid_keys + git_names)
- if invalid_keys.any?
- message = "You passed #{invalid_keys.map{|k| ':'+k }.join(", ")} "
- message << if invalid_keys.size > 1
- "as options for gem '#{name}', but they are invalid."
- else
- "as an option for gem '#{name}', but it is invalid."
- end
-
- message << " Valid options are: #{valid_keys.join(", ")}"
- raise InvalidOption, message
- end
+ validate_keys("gem '#{name}'", opts, valid_keys + git_names)
groups = @groups.dup
opts["group"] = opts.delete("groups") || opts["group"]
groups.concat Array(opts.delete("group"))
groups = [:default] if groups.empty?
+ install_if = @install_conditionals.dup
+ install_if.concat Array(opts.delete("install_if"))
+ install_if = install_if.reduce(true) do |memo, val|
+ memo && (val.respond_to?(:call) ? val.call : val)
+ end
+
platforms = @platforms.dup
opts["platforms"] = opts["platform"] || opts["platforms"]
platforms.concat Array(opts.delete("platforms"))
@@ -282,10 +307,35 @@ module Bundler
end
end
- opts["source"] ||= @source
- opts["env"] ||= @env
- opts["platforms"] = platforms.dup
- opts["group"] = groups
+ opts["source"] ||= @source
+ opts["env"] ||= @env
+ opts["platforms"] = platforms.dup
+ opts["group"] = groups
+ opts["should_include"] = install_if
+ end
+
+ def normalize_group_options(opts, groups)
+ normalize_hash(opts)
+
+ groups = groups.map {|group| ":#{group}" }.join(", ")
+ validate_keys("group #{groups}", opts, %w(optional))
+
+ opts["optional"] ||= false
+ end
+
+ def validate_keys(command, opts, valid_keys)
+ invalid_keys = opts.keys - valid_keys
+ if invalid_keys.any?
+ message = "You passed #{invalid_keys.map{|k| ':'+k }.join(", ")} "
+ message << if invalid_keys.size > 1
+ "as options for #{command}, but they are invalid."
+ else
+ "as an option for #{command}, but it is invalid."
+ end
+
+ message << " Valid options are: #{valid_keys.join(", ")}"
+ raise InvalidOption, message
+ end
end
def normalize_source(source)
@@ -305,21 +355,37 @@ module Bundler
def check_primary_source_safety(source)
return unless source.rubygems_primary_remotes.any?
+ # TODO 2.0 upgrade from setting to default
if Bundler.settings[:disable_multisource]
raise GemspecError, "Warning: this Gemfile contains multiple primary sources. " \
"Each source after the first must include a block to indicate which gems " \
- "should come from that source. To downgrade this error to a warning, run " \
- "`bundle config --delete disable_multisource`."
+ "should come from that source."
else
- Bundler.ui.warn "Warning: this Gemfile contains multiple primary sources. " \
+ Bundler.ui.deprecate "Your Gemfile contains multiple primary sources. " \
"Using `source` more than once without a block is a security risk, and " \
"may result in installing unexpected gems. To resolve this warning, use " \
"a block to indicate which gems should come from the secondary source. " \
- "To upgrade this warning to an error, run `bundle config " \
- "disable_multisource true`."
+ "It will be an error to have multiple primary sources in Bundler 2.0. " \
+ "To enable that error now, run `bundle config disable_multisource true`."
end
end
+ def warn_github_source_change(repo_name)
+ # TODO 2.0 remove deprecation
+ Bundler.ui.deprecate "The :github option uses the git: protocol, which is not secure. " \
+ "Bundler 2.0 will use the https: protcol, which is secure. Enable this change now by " \
+ "running `bundle config github.https true`."
+ end
+
+ def warn_deprecated_git_source(name, repo_string)
+ # TODO 2.0 remove deprecation
+ Bundler.ui.deprecate "The :#{name} git source is deprecated, and will be removed " \
+ "in Bundler 2.0. Add this code to your Gemfile to ensure it continues to work:\n" \
+ " git_source(:#{name}) do |repo_name|\n" \
+ " #{repo_string}\n" \
+ " end", true
+ end
+
class DSLError < GemfileError
# @return [String] the description that should be presented to the user.
#
@@ -422,4 +488,5 @@ module Bundler
end
end
+
end
diff --git a/lib/bundler/fetcher.rb b/lib/bundler/fetcher.rb
index a60adcabb2..42c6eb6717 100644
--- a/lib/bundler/fetcher.rb
+++ b/lib/bundler/fetcher.rb
@@ -1,11 +1,15 @@
require 'bundler/vendored_persistent'
-require 'securerandom'
require 'cgi'
+require 'securerandom'
module Bundler
# Handles all the fetching with the rubygems server
class Fetcher
+ autoload :Downloader, 'bundler/fetcher/downloader'
+ autoload :Dependency, 'bundler/fetcher/dependency'
+ autoload :Index, 'bundler/fetcher/index'
+
# This error is raised when it looks like the network is down
class NetworkDownError < HTTPError; end
# This error is raised if the API returns a 413 (only printed in verbose)
@@ -52,93 +56,19 @@ module Bundler
class << self
attr_accessor :disable_endpoint, :api_timeout, :redirect_limit, :max_retries
-
- def download_gem_from_uri(spec, uri)
- spec.fetch_platform
-
- download_path = Bundler.requires_sudo? ? Bundler.tmp(spec.full_name) : Bundler.rubygems.gem_dir
- gem_path = "#{Bundler.rubygems.gem_dir}/cache/#{spec.full_name}.gem"
-
- FileUtils.mkdir_p("#{download_path}/cache")
- Bundler.rubygems.download_gem(spec, uri, download_path)
-
- if Bundler.requires_sudo?
- Bundler.mkdir_p "#{Bundler.rubygems.gem_dir}/cache"
- Bundler.sudo "mv #{Bundler.tmp(spec.full_name)}/cache/#{spec.full_name}.gem #{gem_path}"
- end
-
- gem_path
- end
-
- def user_agent
- @user_agent ||= begin
- ruby = Bundler.ruby_version
-
- agent = "bundler/#{Bundler::VERSION}"
- agent << " rubygems/#{Gem::VERSION}"
- agent << " ruby/#{ruby.version}"
- agent << " (#{ruby.host})"
- agent << " command/#{ARGV.first}"
-
- if ruby.engine != "ruby"
- # engine_version raises on unknown engines
- engine_version = ruby.engine_version rescue "???"
- agent << " #{ruby.engine}/#{engine_version}"
- end
-
- agent << " options/#{Bundler.settings.all.join(",")}"
-
- # add a random ID so we can consolidate runs server-side
- agent << " " << SecureRandom.hex(8)
-
- # add any user agent strings set in the config
- extra_ua = Bundler.settings[:user_agent]
- agent << " " << extra_ua if extra_ua
-
- agent
- end
- end
-
end
- def initialize(remote)
- @redirect_limit = 5 # How many redirects to allow in one request
- @api_timeout = 10 # How long to wait for each API call
- @max_retries = 3 # How many retries for the API call
+ self.redirect_limit = Bundler.settings[:redirect] # How many redirects to allow in one request
+ self.api_timeout = Bundler.settings[:timeout] # How long to wait for each API call
+ self.max_retries = Bundler.settings[:retry] # How many retries for the API call
+ def initialize(remote)
@remote = remote
Socket.do_not_reverse_lookup = true
connection # create persistent connection
end
- def connection
- @connection ||= begin
- needs_ssl = remote_uri.scheme == "https" ||
- Bundler.settings[:ssl_verify_mode] ||
- Bundler.settings[:ssl_client_cert]
- raise SSLError if needs_ssl && !defined?(OpenSSL::SSL)
-
- con = Net::HTTP::Persistent.new 'bundler', :ENV
-
- if remote_uri.scheme == "https"
- con.verify_mode = (Bundler.settings[:ssl_verify_mode] ||
- OpenSSL::SSL::VERIFY_PEER)
- con.cert_store = bundler_cert_store
- end
-
- if Bundler.settings[:ssl_client_cert]
- pem = File.read(Bundler.settings[:ssl_client_cert])
- con.cert = OpenSSL::X509::Certificate.new(pem)
- con.key = OpenSSL::PKey::RSA.new(pem)
- end
-
- con.read_timeout = @api_timeout
- con.override_headers["User-Agent"] = self.class.user_agent
- con
- end
- end
-
def uri
@remote.anonymized_uri
end
@@ -154,37 +84,26 @@ module Bundler
elsif cached_spec_path = gemspec_cached_path(spec_file_name)
Bundler.load_gemspec(cached_spec_path)
else
- Bundler.load_marshal Gem.inflate(fetch(uri))
+ Bundler.load_marshal Gem.inflate(downloader.fetch uri)
end
rescue MarshalError
raise HTTPError, "Gemspec #{spec} contained invalid data.\n" \
"Your network or your gem server is probably having issues right now."
end
- # cached gem specification path, if one exists
- def gemspec_cached_path spec_file_name
- paths = Bundler.rubygems.spec_cache_dirs.map { |dir| File.join(dir, spec_file_name) }
- paths = paths.select {|path| File.file? path }
- paths.first
- end
-
# return the specs in the bundler format as an index
def specs(gem_names, source)
old = Bundler.rubygems.sources
- index = Index.new
-
- if gem_names && use_api
- specs = fetch_remote_specs(gem_names)
- end
-
- if specs.nil?
- # API errors mean we should treat this as a non-API source
- @use_api = false
+ index = Bundler::Index.new
- specs = Bundler::Retry.new("source fetch", AUTH_ERRORS).attempts do
- fetch_all_remote_specs
+ specs = {}
+ fetchers.dup.each do |f|
+ unless f.api_fetcher? && !gem_names
+ break if specs = f.specs(gem_names)
end
+ fetchers.delete(f)
end
+ @use_api = false if fetchers.none?(&:api_fetcher?)
specs[remote_uri].each do |name, version, platform, dependencies|
next if name == 'bundler'
@@ -200,184 +119,106 @@ module Bundler
end
index
- rescue CertificateFailureError => e
+ rescue CertificateFailureError
Bundler.ui.info "" if gem_names && use_api # newline after dots
- raise e
+ raise
ensure
Bundler.rubygems.sources = old
end
- # fetch index
- def fetch_remote_specs(gem_names, full_dependency_list = [], last_spec_list = [])
- query_list = gem_names - full_dependency_list
-
- # only display the message on the first run
- if Bundler.ui.debug?
- Bundler.ui.debug "Query List: #{query_list.inspect}"
- else
- Bundler.ui.info ".", false
- end
-
- return {remote_uri => last_spec_list} if query_list.empty?
-
- remote_specs = Bundler::Retry.new("dependency api", AUTH_ERRORS).attempts do
- fetch_dependency_remote_specs(query_list)
- end
-
- spec_list, deps_list = remote_specs
- returned_gems = spec_list.map {|spec| spec.first }.uniq
- fetch_remote_specs(deps_list, full_dependency_list + returned_gems, spec_list + last_spec_list)
- rescue HTTPError, MarshalError, GemspecError
- Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
- Bundler.ui.debug "could not fetch from the dependency API, trying the full index"
- @use_api = false
- return nil
- end
-
def use_api
return @use_api if defined?(@use_api)
if remote_uri.scheme == "file" || Bundler::Fetcher.disable_endpoint
@use_api = false
- elsif fetch(dependency_api_uri)
- @use_api = true
+ else
+ fetchers.reject! { |f| f.api_fetcher? && !f.api_available? }
+ @use_api = fetchers.any?(&:api_fetcher?)
end
- rescue NetworkDownError => e
- raise HTTPError, e.message
- rescue AuthenticationRequiredError
- # We got a 401 from the server. Don't fall back to the full index, just fail.
- raise
- rescue HTTPError
- @use_api = false
end
- def inspect
- "#<#{self.class}:0x#{object_id} uri=#{uri}>"
- end
+ def user_agent
+ @user_agent ||= begin
+ ruby = Bundler.ruby_version
- private
+ agent = "bundler/#{Bundler::VERSION}"
+ agent << " rubygems/#{Gem::VERSION}"
+ agent << " ruby/#{ruby.version}"
+ agent << " (#{ruby.host})"
+ agent << " command/#{ARGV.first}"
- HTTP_ERRORS = [
- Timeout::Error, EOFError, SocketError, Errno::ENETDOWN,
- Errno::EINVAL, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EAGAIN,
- Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError,
- Net::HTTP::Persistent::Error
- ]
+ if ruby.engine != "ruby"
+ # engine_version raises on unknown engines
+ engine_version = ruby.engine_version rescue "???"
+ agent << " #{ruby.engine}/#{engine_version}"
+ end
- def fetch(uri, counter = 0)
- raise HTTPError, "Too many redirects" if counter >= @redirect_limit
+ agent << " options/#{Bundler.settings.all.join(",")}"
- response = request(uri)
- Bundler.ui.debug("HTTP #{response.code} #{response.message}")
+ # add a random ID so we can consolidate runs server-side
+ agent << " " << SecureRandom.hex(8)
- case response
- when Net::HTTPRedirection
- new_uri = URI.parse(response["location"])
- if new_uri.host == uri.host
- new_uri.user = uri.user
- new_uri.password = uri.password
- end
- fetch(new_uri, counter + 1)
- when Net::HTTPSuccess
- response.body
- when Net::HTTPRequestEntityTooLarge
- raise FallbackError, response.body
- when Net::HTTPUnauthorized
- raise AuthenticationRequiredError, remote_uri.host
- else
- raise HTTPError, "#{response.class}: #{response.body}"
+ # add any user agent strings set in the config
+ extra_ua = Bundler.settings[:user_agent]
+ agent << " " << extra_ua if extra_ua
+
+ agent
end
end
- def request(uri)
- Bundler.ui.debug "HTTP GET #{uri}"
- req = Net::HTTP::Get.new uri.request_uri
- if uri.user
- user = CGI.unescape(uri.user)
- password = uri.password ? CGI.unescape(uri.password) : nil
- req.basic_auth(user, password)
- end
- connection.request(uri, req)
- rescue OpenSSL::SSL::SSLError
- raise CertificateFailureError.new(uri)
- rescue *HTTP_ERRORS => e
- Bundler.ui.trace e
- case e.message
- when /host down:/, /getaddrinfo: nodename nor servname provided/
- raise NetworkDownError, "Could not reach host #{uri.host}. Check your network " \
- "connection and try again."
- else
- raise HTTPError, "Network error while fetching #{uri}"
- end
+ def fetchers
+ @fetchers ||= FETCHERS.map { |f| f.new(downloader, remote_uri, fetch_uri, uri) }
end
- def dependency_api_uri(gem_names = [])
- uri = fetch_uri + "api/v1/dependencies"
- uri.query = "gems=#{URI.encode(gem_names.join(","))}" if gem_names.any?
- uri
+ def inspect
+ "#<#{self.class}:0x#{object_id} uri=#{uri}>"
end
- # fetch from Gemcutter Dependency Endpoint API
- def fetch_dependency_remote_specs(gem_names)
- Bundler.ui.debug "Query Gemcutter Dependency Endpoint API: #{gem_names.join(',')}"
- gem_list = []
- deps_list = []
+ private
- gem_names.each_slice(Source::Rubygems::API_REQUEST_SIZE) do |names|
- marshalled_deps = fetch dependency_api_uri(names)
- gem_list += Bundler.load_marshal(marshalled_deps)
- end
+ FETCHERS = [Dependency, Index]
- spec_list = gem_list.map do |s|
- dependencies = s[:dependencies].map do |name, requirement|
- dep = well_formed_dependency(name, requirement.split(", "))
- deps_list << dep.name
- dep
- end
+ def connection
+ @connection ||= begin
+ needs_ssl = remote_uri.scheme == "https" ||
+ Bundler.settings[:ssl_verify_mode] ||
+ Bundler.settings[:ssl_client_cert]
+ raise SSLError if needs_ssl && !defined?(OpenSSL::SSL)
- [s[:name], Gem::Version.new(s[:number]), s[:platform], dependencies]
- end
+ con = Net::HTTP::Persistent.new 'bundler', :ENV
- [spec_list, deps_list.uniq]
- end
+ if remote_uri.scheme == "https"
+ con.verify_mode = (Bundler.settings[:ssl_verify_mode] ||
+ OpenSSL::SSL::VERIFY_PEER)
+ con.cert_store = bundler_cert_store
+ end
- # fetch from modern index: specs.4.8.gz
- def fetch_all_remote_specs
- old_sources = Bundler.rubygems.sources
- Bundler.rubygems.sources = [remote_uri.to_s]
- Bundler.rubygems.fetch_all_remote_specs
- rescue Gem::RemoteFetcher::FetchError, OpenSSL::SSL::SSLError => e
- case e.message
- when /certificate verify failed/
- raise CertificateFailureError.new(uri)
- when /401/
- raise AuthenticationRequiredError, remote_uri
- when /403/
- if remote_uri.userinfo
- raise BadAuthenticationError, remote_uri
- else
- raise AuthenticationRequiredError, remote_uri
+ if Bundler.settings[:ssl_client_cert]
+ pem = File.read(Bundler.settings[:ssl_client_cert])
+ con.cert = OpenSSL::X509::Certificate.new(pem)
+ con.key = OpenSSL::PKey::RSA.new(pem)
end
- else
- Bundler.ui.trace e
- raise HTTPError, "Could not fetch specs from #{uri}"
+
+ con.read_timeout = Fetcher.api_timeout
+ con.override_headers["User-Agent"] = user_agent
+ con
end
- ensure
- Bundler.rubygems.sources = old_sources
end
- def well_formed_dependency(name, *requirements)
- Gem::Dependency.new(name, *requirements)
- rescue ArgumentError => e
- illformed = 'Ill-formed requirement ["#<YAML::Syck::DefaultKey'
- raise e unless e.message.include?(illformed)
- puts # we shouldn't print the error message on the "fetching info" status line
- raise GemspecError,
- "Unfortunately, the gem #{s[:name]} (#{s[:number]}) has an invalid " \
- "gemspec. \nPlease ask the gem author to yank the bad version to fix " \
- "this issue. For more information, see http://bit.ly/syck-defaultkey."
+ # cached gem specification path, if one exists
+ def gemspec_cached_path spec_file_name
+ paths = Bundler.rubygems.spec_cache_dirs.map { |dir| File.join(dir, spec_file_name) }
+ paths = paths.select {|path| File.file? path }
+ paths.first
end
+ HTTP_ERRORS = [
+ Timeout::Error, EOFError, SocketError, Errno::ENETDOWN,
+ Errno::EINVAL, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EAGAIN,
+ Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError,
+ Net::HTTP::Persistent::Error
+ ]
+
def bundler_cert_store
store = OpenSSL::X509::Store.new
if Bundler.settings[:ssl_ca_cert]
@@ -411,5 +252,10 @@ module Bundler
def remote_uri
@remote.uri
end
+
+ def downloader
+ @downloader ||= Downloader.new(connection, self.class.redirect_limit)
+ end
+
end
end
diff --git a/lib/bundler/fetcher/base.rb b/lib/bundler/fetcher/base.rb
new file mode 100644
index 0000000000..31d6f8a09b
--- /dev/null
+++ b/lib/bundler/fetcher/base.rb
@@ -0,0 +1,27 @@
+module Bundler
+ class Fetcher
+ class Base
+ attr_reader :downloader
+ attr_reader :remote_uri
+ attr_reader :fetch_uri
+ attr_reader :display_uri
+
+ def initialize(downloader, remote_uri, fetch_uri, display_uri)
+ raise 'Abstract class' if self.class == Base
+ @downloader = downloader
+ @remote_uri = remote_uri
+ @fetch_uri = fetch_uri
+ @display_uri = display_uri
+ end
+
+ def api_available?
+ api_fetcher?
+ end
+
+ def api_fetcher?
+ false
+ end
+
+ end
+ end
+end
diff --git a/lib/bundler/fetcher/dependency.rb b/lib/bundler/fetcher/dependency.rb
new file mode 100644
index 0000000000..ca36dcb53f
--- /dev/null
+++ b/lib/bundler/fetcher/dependency.rb
@@ -0,0 +1,88 @@
+require 'bundler/fetcher/base'
+
+module Bundler
+ class Fetcher
+ class Dependency < Base
+ def api_available?
+ downloader.fetch(dependency_api_uri)
+ rescue NetworkDownError => e
+ raise HTTPError, e.message
+ rescue AuthenticationRequiredError
+ # We got a 401 from the server. Just fail.
+ raise
+ rescue HTTPError
+ end
+
+ def api_fetcher?
+ true
+ end
+
+ def specs(gem_names, full_dependency_list = [], last_spec_list = [])
+ query_list = gem_names - full_dependency_list
+
+ # only display the message on the first run
+ if Bundler.ui.debug?
+ Bundler.ui.debug "Query List: #{query_list.inspect}"
+ else
+ Bundler.ui.info ".", false
+ end
+
+ return {remote_uri => last_spec_list} if query_list.empty?
+
+ remote_specs = Bundler::Retry.new("dependency api", AUTH_ERRORS).attempts do
+ dependency_specs(query_list)
+ end
+
+ spec_list, deps_list = remote_specs
+ returned_gems = spec_list.map(&:first).uniq
+ specs(deps_list, full_dependency_list + returned_gems, spec_list + last_spec_list)
+ rescue HTTPError, MarshalError, GemspecError
+ Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
+ Bundler.ui.debug "could not fetch from the dependency API, trying the full index"
+ return nil
+ end
+
+ def dependency_specs(gem_names)
+ Bundler.ui.debug "Query Gemcutter Dependency Endpoint API: #{gem_names.join(',')}"
+ gem_list = []
+ deps_list = []
+
+ gem_names.each_slice(Source::Rubygems::API_REQUEST_SIZE) do |names|
+ marshalled_deps = downloader.fetch dependency_api_uri(names)
+ gem_list += Bundler.load_marshal(marshalled_deps)
+ end
+
+ spec_list = gem_list.map do |s|
+ dependencies = s[:dependencies].map do |name, requirement|
+ dep = well_formed_dependency(name, requirement.split(", "))
+ deps_list << dep.name
+ dep
+ end
+
+ [s[:name], Gem::Version.new(s[:number]), s[:platform], dependencies]
+ end
+
+ [spec_list, deps_list.uniq]
+ end
+
+ def dependency_api_uri(gem_names = [])
+ uri = fetch_uri + "api/v1/dependencies"
+ uri.query = "gems=#{URI.encode(gem_names.join(","))}" if gem_names.any?
+ uri
+ end
+
+ def well_formed_dependency(name, *requirements)
+ Gem::Dependency.new(name, *requirements)
+ rescue ArgumentError => e
+ illformed = 'Ill-formed requirement ["#<YAML::Syck::DefaultKey'
+ raise e unless e.message.include?(illformed)
+ puts # we shouldn't print the error message on the "fetching info" status line
+ raise GemspecError,
+ "Unfortunately, the gem #{s[:name]} (#{s[:number]}) has an invalid " \
+ "gemspec. \nPlease ask the gem author to yank the bad version to fix " \
+ "this issue. For more information, see http://bit.ly/syck-defaultkey."
+ end
+
+ end
+ end
+end
diff --git a/lib/bundler/fetcher/downloader.rb b/lib/bundler/fetcher/downloader.rb
new file mode 100644
index 0000000000..b480b4bae9
--- /dev/null
+++ b/lib/bundler/fetcher/downloader.rb
@@ -0,0 +1,61 @@
+module Bundler
+ class Fetcher
+ class Downloader
+ attr_reader :connection
+ attr_reader :redirect_limit
+
+ def initialize(connection, redirect_limit)
+ @connection = connection
+ @redirect_limit = redirect_limit
+ end
+
+ def fetch(uri, counter = 0)
+ raise HTTPError, "Too many redirects" if counter >= redirect_limit
+
+ response = request(uri)
+ Bundler.ui.debug("HTTP #{response.code} #{response.message}")
+
+ case response
+ when Net::HTTPRedirection
+ new_uri = URI.parse(response["location"])
+ if new_uri.host == uri.host
+ new_uri.user = uri.user
+ new_uri.password = uri.password
+ end
+ fetch(new_uri, counter + 1)
+ when Net::HTTPSuccess
+ response.body
+ when Net::HTTPRequestEntityTooLarge
+ raise FallbackError, response.body
+ when Net::HTTPUnauthorized
+ raise AuthenticationRequiredError, uri.host
+ else
+ raise HTTPError, "#{response.class}: #{response.body}"
+ end
+ end
+
+ def request(uri)
+ Bundler.ui.debug "HTTP GET #{uri}"
+ req = Net::HTTP::Get.new uri.request_uri
+ if uri.user
+ user = CGI.unescape(uri.user)
+ password = uri.password ? CGI.unescape(uri.password) : nil
+ req.basic_auth(user, password)
+ end
+ connection.request(uri, req)
+ rescue OpenSSL::SSL::SSLError
+ raise CertificateFailureError.new(uri)
+ rescue *HTTP_ERRORS => e
+ Bundler.ui.trace e
+ case e.message
+ when /host down:/, /getaddrinfo: nodename nor servname provided/
+ raise NetworkDownError, "Could not reach host #{uri.host}. Check your network " \
+ "connection and try again."
+ else
+ raise HTTPError, "Network error while fetching #{uri}"
+ end
+ end
+
+ end
+ end
+end \ No newline at end of file
diff --git a/lib/bundler/fetcher/index.rb b/lib/bundler/fetcher/index.rb
new file mode 100644
index 0000000000..f9bd279d0d
--- /dev/null
+++ b/lib/bundler/fetcher/index.rb
@@ -0,0 +1,31 @@
+require 'bundler/fetcher/base'
+
+module Bundler
+ class Fetcher
+ class Index < Base
+ def specs(_gem_names)
+ old_sources = Bundler.rubygems.sources
+ Bundler.rubygems.sources = [remote_uri.to_s]
+ Bundler.rubygems.fetch_all_remote_specs
+ rescue Gem::RemoteFetcher::FetchError, OpenSSL::SSL::SSLError => e
+ case e.message
+ when /certificate verify failed/
+ raise CertificateFailureError.new(display_uri)
+ when /401/
+ raise AuthenticationRequiredError, remote_uri
+ when /403/
+ if remote_uri.userinfo
+ raise BadAuthenticationError, remote_uri
+ else
+ raise AuthenticationRequiredError, remote_uri
+ end
+ else
+ Bundler.ui.trace e
+ raise HTTPError, "Could not fetch specs from #{display_uri}"
+ end
+ ensure
+ Bundler.rubygems.sources = old_sources
+ end
+ end
+ end
+end
diff --git a/lib/bundler/friendly_errors.rb b/lib/bundler/friendly_errors.rb
index 4bd3e53381..9d4389e398 100644
--- a/lib/bundler/friendly_errors.rb
+++ b/lib/bundler/friendly_errors.rb
@@ -44,18 +44,27 @@ module Bundler
def self.request_issue_report_for(e)
Bundler.ui.info <<-EOS.gsub(/^ {6}/, '')
- #{'――― ERROR REPORT TEMPLATE ―――――――――――――――――――――――――――――――――――――――――――――――――――――――'}
+ #{'--- ERROR REPORT TEMPLATE -------------------------------------------------------'}
- What did you do?
+
+ I ran the command `#{$PROGRAM_NAME} #{ARGV.join(' ')}`
+
- What did you expect to happen?
+
+ I expected Bundler to...
+
- What happened instead?
+ Instead, what actually happened was...
+
+
Error details
#{e.class}: #{e.message}
- #{e.backtrace.join("\n ")}
+ #{e.backtrace.join("\n ")}
#{Bundler::Env.new.report(:print_gemfile => false).gsub(/\n/, "\n ").strip}
- #{'――― TEMPLATE END ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――'}
+ #{'--- TEMPLATE END ----------------------------------------------------------------'}
EOS
@@ -73,7 +82,7 @@ module Bundler
def self.issues_url(exception)
'https://github.com/bundler/bundler/search?q=' \
- "#{CGI.escape(exception.message)}&type=Issues"
+ "#{CGI.escape(exception.message.lines.first.chomp)}&type=Issues"
end
end
diff --git a/lib/bundler/gem_helper.rb b/lib/bundler/gem_helper.rb
index 6db31901e4..9aac3e0d75 100644
--- a/lib/bundler/gem_helper.rb
+++ b/lib/bundler/gem_helper.rb
@@ -44,6 +44,11 @@ module Bundler
install_gem(built_gem_path)
end
+ desc "Build and install #{name}-#{version}.gem into system gems without network access."
+ task 'install:local' => 'build' do
+ install_gem(built_gem_path, :local)
+ end
+
desc "Create tag #{version_tag} and build and push #{name}-#{version}.gem to Rubygems\n" \
"To prevent publishing in Rubygems use `gem_push=no rake release`"
task 'release' => ['build', 'release:guard_clean',
@@ -76,9 +81,9 @@ module Bundler
File.join(base, 'pkg', file_name)
end
- def install_gem(built_gem_path=nil)
+ def install_gem(built_gem_path = nil, local = false)
built_gem_path ||= build_gem
- out, _ = sh_with_code("gem install '#{built_gem_path}' --local")
+ out, _ = sh_with_code("gem install '#{built_gem_path}'#{' --local' if local}")
raise "Couldn't install gem, run `gem install #{built_gem_path}' for more detailed output" unless out[/Successfully installed/]
Bundler.ui.confirm "#{name} (#{version}) installed."
end
diff --git a/lib/bundler/gem_helpers.rb b/lib/bundler/gem_helpers.rb
index a3bb514954..2af87c94d9 100644
--- a/lib/bundler/gem_helpers.rb
+++ b/lib/bundler/gem_helpers.rb
@@ -6,6 +6,7 @@ module Bundler
[Gem::Platform.new('java'), Gem::Platform.new('java')],
[Gem::Platform.new('mswin32'), Gem::Platform.new('mswin32')],
[Gem::Platform.new('mswin64'), Gem::Platform.new('mswin64')],
+ [Gem::Platform.new('universal-mingw32'), Gem::Platform.new('universal-mingw32')],
[Gem::Platform.new('x64-mingw32'), Gem::Platform.new('x64-mingw32')],
[Gem::Platform.new('x86_64-mingw32'), Gem::Platform.new('x64-mingw32')],
[Gem::Platform.new('mingw32'), Gem::Platform.new('x86-mingw32')]
diff --git a/lib/bundler/index.rb b/lib/bundler/index.rb
index 8076c685e5..ea1edaca21 100644
--- a/lib/bundler/index.rb
+++ b/lib/bundler/index.rb
@@ -81,10 +81,6 @@ module Bundler
end
end
- def source_types
- sources.map{|s| s.class }.uniq
- end
-
alias [] search
def <<(spec)
diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb
index 10526115a4..d0a7dc4fda 100644
--- a/lib/bundler/installer.rb
+++ b/lib/bundler/installer.rb
@@ -79,38 +79,50 @@ module Bundler
options["local"] ? @definition.resolve_with_cache! : @definition.resolve_remotely!
end
+ force = options["force"]
+
# the order that the resolver provides is significant, since
# dependencies might actually affect the installation of a gem.
# that said, it's a rare situation (other than rake), and parallel
# installation is just SO MUCH FASTER. so we let people opt in.
jobs = [Bundler.settings[:jobs].to_i-1, 1].max
if jobs > 1 && can_install_in_parallel?
- install_in_parallel jobs, options[:standalone]
+ require 'bundler/installer/parallel_installer'
+ install_in_parallel jobs, options[:standalone], force
else
- install_sequentially options[:standalone]
+ install_sequentially options[:standalone], force
end
lock unless Bundler.settings[:frozen]
generate_standalone(options[:standalone]) if options[:standalone]
end
- def install_gem_from_spec(spec, standalone = false, worker = 0)
+ def install_gem_from_spec(spec, standalone = false, worker = 0, force = false)
# Fetch the build settings, if there are any
- settings = Bundler.settings["build.#{spec.name}"]
- install_message = nil
- post_install_message = nil
- debug_message = nil
- Bundler.rubygems.with_build_args [settings] do
- install_message, post_install_message, debug_message = spec.source.install(spec)
- if install_message.include? 'Installing'
- Bundler.ui.confirm install_message
- else
- Bundler.ui.info install_message
+ settings = Bundler.settings["build.#{spec.name}"]
+ messages = nil
+
+ install_options = { :force => force, :ensure_builtin_gems_cached => standalone }
+
+ if settings
+ # Build arguments are global, so this is mutexed
+ Bundler.rubygems.with_build_args [settings] do
+ messages = spec.source.install(spec, install_options)
end
- Bundler.ui.debug debug_message if debug_message
- Bundler.ui.debug "#{worker}: #{spec.name} (#{spec.version}) from #{spec.loaded_from}"
+ else
+ messages = spec.source.install(spec, install_options)
end
+ install_message, post_install_message, debug_message = *messages
+
+ if install_message.include? 'Installing'
+ Bundler.ui.confirm install_message
+ else
+ Bundler.ui.info install_message
+ end
+ Bundler.ui.debug debug_message if debug_message
+ Bundler.ui.debug "#{worker}: #{spec.name} (#{spec.version}) from #{spec.loaded_from}"
+
if Bundler.settings[:bin] && standalone
generate_standalone_bundler_executable_stubs(spec)
elsif Bundler.settings[:bin]
@@ -258,68 +270,17 @@ module Bundler
end
end
- def install_sequentially(standalone)
+ def install_sequentially(standalone, force = false)
specs.each do |spec|
- message = install_gem_from_spec spec, standalone, 0
+ message = install_gem_from_spec spec, standalone, 0, force
if message
Installer.post_install_messages[spec.name] = message
end
end
end
- def install_in_parallel(size, standalone)
- name2spec = {}
- remains = {}
- enqueued = {}
- specs.each do |spec|
- name2spec[spec.name] = spec
- remains[spec.name] = true
- end
-
- worker_pool = Worker.new size, lambda { |name, worker_num|
- spec = name2spec[name]
- message = install_gem_from_spec spec, standalone, worker_num
- { :name => spec.name, :post_install => message }
- }
-
- # Keys in the remains hash represent uninstalled gems specs.
- # We enqueue all gem specs that do not have any dependencies.
- # Later we call this lambda again to install specs that depended on
- # previously installed specifications. We continue until all specs
- # are installed.
- enqueue_remaining_specs = lambda do
- remains.keys.each do |name|
- next if enqueued[name]
- spec = name2spec[name]
- if ready_to_install?(spec, remains)
- worker_pool.enq name
- enqueued[name] = true
- end
- end
- end
- enqueue_remaining_specs.call
-
- until remains.empty?
- message = worker_pool.deq
- remains.delete message[:name]
- if message[:post_install]
- Installer.post_install_messages[message[:name]] = message[:post_install]
- end
- enqueue_remaining_specs.call
- end
- message
- ensure
- worker_pool && worker_pool.stop
- end
-
- # We only want to install a gem spec if all its dependencies are met.
- # If the dependency is no longer in the `remains` hash then it has been met.
- # If a dependency is only development or is self referential it can be ignored.
- def ready_to_install?(spec, remains)
- spec.dependencies.none? do |dep|
- next if dep.type == :development || dep.name == spec.name
- remains[dep.name]
- end
+ def install_in_parallel(size, standalone, force = false)
+ ParallelInstaller.call(self, specs, size, standalone, force)
end
def create_bundle_path
diff --git a/lib/bundler/installer/parallel_installer.rb b/lib/bundler/installer/parallel_installer.rb
new file mode 100644
index 0000000000..9c08c83b4c
--- /dev/null
+++ b/lib/bundler/installer/parallel_installer.rb
@@ -0,0 +1,117 @@
+require 'bundler/worker'
+
+
+class ParallelInstaller
+
+ class SpecInstallation
+
+ attr_accessor :spec, :name, :post_install_message, :state
+ def initialize(spec)
+ @spec, @name = spec, spec.name
+ @state = :none
+ @post_install_message = ""
+ end
+
+ def installed?
+ state == :installed
+ end
+
+ def enqueued?
+ state == :enqueued
+ end
+
+ # Only true when spec in neither installed nor already enqueued
+ def ready_to_enqueue?
+ !installed? && !enqueued?
+ end
+
+ def has_post_install_message?
+ !post_install_message.empty?
+ end
+
+ def ignorable_dependency?(dep)
+ dep.type == :development || dep.name == @name
+ end
+
+ # Checks installed dependencies against spec's dependencies to make
+ # sure needed dependencies have been installed.
+ def dependencies_installed?(remaining_specs)
+ installed_specs = remaining_specs.reject(&:installed?).map(&:name)
+ already_installed = lambda {|dep| installed_specs.include? dep.name }
+ dependencies.all? {|d| already_installed[d] }
+ end
+
+ # Represents only the non-development dependencies and the ones that
+ # are itself.
+ def dependencies
+ @dependencies ||= all_dependencies.reject {|dep| ignorable_dependency? dep }
+ end
+
+ # Represents all dependencies
+ def all_dependencies
+ @spec.dependencies
+ end
+ end
+
+ def self.call(*args)
+ new(*args).call
+ end
+
+ # Returns max number of threads machine can handle with a min of 1
+ def self.max_threads
+ [Bundler.settings[:jobs].to_i-1, 1].max
+ end
+
+ def initialize(installer, all_specs, size, standalone, force)
+ @installer = installer
+ @size = size
+ @standalone = standalone
+ @force = force
+ @specs = all_specs.map { |s| SpecInstallation.new(s) }
+ end
+
+ def call
+ enqueue_specs
+ process_specs until @specs.all?(&:installed?)
+ ensure
+ worker_pool && worker_pool.stop
+ end
+
+ def worker_pool
+ @worker_pool ||= Bundler::Worker.new @size, lambda { |spec_install, worker_num|
+ message = @installer.install_gem_from_spec spec_install.spec, @standalone, worker_num, @force
+ spec_install.post_install_message = message unless message.nil?
+ spec_install
+ }
+ end
+
+ # Dequeue a spec and save its post-install message and then enqueue the
+ # remaining specs.
+ # Some specs might've had to wait til this spec was installed to be
+ # processed so the call to `enqueue_specs` is important after every
+ # dequeue.
+ def process_specs
+ spec = worker_pool.deq
+ spec.state = :installed
+ collect_post_install_message spec if spec.has_post_install_message?
+ enqueue_specs
+ end
+
+ def collect_post_install_message(spec)
+ Bundler::Installer.post_install_messages[spec.name] = spec.post_install_message
+ end
+
+ # Keys in the remains hash represent uninstalled gems specs.
+ # We enqueue all gem specs that do not have any dependencies.
+ # Later we call this lambda again to install specs that depended on
+ # previously installed specifications. We continue until all specs
+ # are installed.
+ def enqueue_specs
+ @specs.select(&:ready_to_enqueue?).each do |spec|
+ if spec.dependencies_installed? @specs
+ worker_pool.enq spec
+ spec.state = :enqueued
+ end
+ end
+ end
+end
diff --git a/lib/bundler/lazy_specification.rb b/lib/bundler/lazy_specification.rb
index 16f46b8580..1119bdeed8 100644
--- a/lib/bundler/lazy_specification.rb
+++ b/lib/bundler/lazy_specification.rb
@@ -41,7 +41,7 @@ module Bundler
out = " #{name} (#{version}-#{platform})\n"
end
- dependencies.sort_by {|d| d.to_s }.each do |dep|
+ dependencies.sort_by {|d| d.to_s }.uniq.each do |dep|
next if dep.type == :development
out << " #{dep.to_lock}\n"
end
diff --git a/lib/bundler/lockfile_parser.rb b/lib/bundler/lockfile_parser.rb
index 7030508988..21367fe70c 100644
--- a/lib/bundler/lockfile_parser.rb
+++ b/lib/bundler/lockfile_parser.rb
@@ -12,8 +12,9 @@ require "strscan"
module Bundler
class LockfileParser
- attr_reader :sources, :dependencies, :specs, :platforms
+ attr_reader :sources, :dependencies, :specs, :platforms, :bundler_version
+ BUNDLED = "BUNDLED WITH"
DEPENDENCIES = "DEPENDENCIES"
PLATFORMS = "PLATFORMS"
GIT = "GIT"
@@ -41,18 +42,38 @@ module Bundler
@state = :dependency
elsif line == PLATFORMS
@state = :platform
+ elsif line == BUNDLED
+ @state = :bundled_with
else
send("parse_#{@state}", line)
end
end
@sources << @rubygems_aggregate
@specs = @specs.values
+ warn_for_outdated_bundler_version
rescue ArgumentError => e
Bundler.ui.debug(e)
raise LockfileError, "Your lockfile is unreadable. Run `rm Gemfile.lock` " \
"and then `bundle install` to generate a new lockfile."
end
+ def warn_for_outdated_bundler_version
+ return unless bundler_version
+ prerelease_text = bundler_version.prerelease? ? " --pre" : ""
+ current_version = Gem::Version.create(Bundler::VERSION)
+ case current_version.segments.first <=> bundler_version.segments.first
+ when -1
+ raise LockfileError, "You must use Bundler #{bundler_version.segments.first} or greater with this lockfile."
+ when 0
+ if current_version < bundler_version
+ Bundler.ui.warn "Warning: the running version of Bundler is older " \
+ "than the version that created the lockfile. We suggest you " \
+ "upgrade to the latest version of Bundler by running `gem " \
+ "install bundler#{prerelease_text}`.\n"
+ end
+ end
+ end
+
private
TYPES = {
@@ -157,5 +178,12 @@ module Bundler
end
end
+ def parse_bundled_with(line)
+ line = line.strip
+ if Gem::Version.correct?(line)
+ @bundler_version = Gem::Version.create(line)
+ end
+ end
+
end
end
diff --git a/lib/bundler/match_platform.rb b/lib/bundler/match_platform.rb
index 523dafbbd6..e6a33ecbad 100644
--- a/lib/bundler/match_platform.rb
+++ b/lib/bundler/match_platform.rb
@@ -7,7 +7,7 @@ module Bundler
def match_platform(p)
Gem::Platform::RUBY == platform or
platform.nil? or p == platform or
- generic(Gem::Platform.new(platform)) == p
+ generic(Gem::Platform.new(platform)) === p
end
end
end
diff --git a/lib/bundler/remote_specification.rb b/lib/bundler/remote_specification.rb
index c80eaa40fc..456686dc0f 100644
--- a/lib/bundler/remote_specification.rb
+++ b/lib/bundler/remote_specification.rb
@@ -54,4 +54,24 @@ module Bundler
end
end
end
+
+ class StubSpecification < RemoteSpecification
+ def self.from_stub(stub)
+ spec = new(stub.name, stub.version, stub.platform, nil)
+ spec.stub = stub
+ spec
+ end
+
+ attr_accessor :stub
+
+ def to_yaml
+ _remote_specification.to_yaml
+ end
+
+ private
+
+ def _remote_specification
+ stub.to_spec
+ end
+ end
end
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index df2c515cc5..511a74139a 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -323,12 +323,8 @@ module Bundler
message << "Source does not contain any versions of '#{requirement}'"
end
else
- message = "Could not find gem '#{requirement}' "
- if @index.source_types.include?(Bundler::Source::Rubygems)
- message << "in any of the gem sources listed in your Gemfile."
- else
- message << "in the gems available on this machine."
- end
+ message = "Could not find gem '#{requirement}' in any of the gem sources " \
+ "listed in your Gemfile or available on this machine."
end
raise GemNotFound, message
end
diff --git a/lib/bundler/retry.rb b/lib/bundler/retry.rb
index ea4d7577d9..585888f8e1 100644
--- a/lib/bundler/retry.rb
+++ b/lib/bundler/retry.rb
@@ -1,23 +1,24 @@
module Bundler
# General purpose class for retrying code that may fail
class Retry
- DEFAULT_ATTEMPTS = 2
attr_accessor :name, :total_runs, :current_run
class << self
- attr_accessor :attempts
+ def default_attempts
+ default_retries + 1
+ end
+ alias_method :attempts, :default_attempts
+
+ def default_retries
+ Bundler.settings[:retry]
+ end
end
- def initialize(name, exceptions = nil, attempts = nil)
+ def initialize(name, exceptions = nil, retries = self.class.default_retries)
@name = name
- attempts ||= default_attempts
+ @retries = retries
@exceptions = Array(exceptions) || []
- @total_runs = attempts.next # will run once, then upto attempts.times
- end
-
- def default_attempts
- return Integer(self.class.attempts) if self.class.attempts
- DEFAULT_ATTEMPTS
+ @total_runs = @retries + 1 # will run once, then upto attempts.times
end
def attempt(&block)
diff --git a/lib/bundler/rubygems_integration.rb b/lib/bundler/rubygems_integration.rb
index 1cb9e72808..047aa891a6 100644
--- a/lib/bundler/rubygems_integration.rb
+++ b/lib/bundler/rubygems_integration.rb
@@ -131,6 +131,19 @@ module Bundler
yield
end
+ def loaded_gem_paths
+ # RubyGems 2.2+ can put binary extension into dedicated folders,
+ # therefore use RubyGems facilities to obtain their load paths.
+ if Gem::Specification.method_defined? :full_require_paths
+ loaded_gem_paths = Gem.loaded_specs.map {|n, s| s.full_require_paths}
+ loaded_gem_paths.flatten
+ else
+ $LOAD_PATH.select do |p|
+ Bundler.rubygems.gem_path.any?{|gp| p =~ /^#{Regexp.escape(gp)}/ }
+ end
+ end
+ end
+
def ui=(obj)
Gem::DefaultUserInteraction.ui = obj
end
@@ -161,12 +174,14 @@ module Bundler
end
def with_build_args(args)
- old_args = self.build_args
- begin
- self.build_args = args
- yield
- ensure
- self.build_args = old_args
+ ext_lock.synchronize do
+ old_args = self.build_args
+ begin
+ self.build_args = args
+ yield
+ ensure
+ self.build_args = old_args
+ end
end
end
@@ -559,12 +574,20 @@ module Bundler
end
end
+ # RubyGems 2.1.0
class MoreFuture < Future
def initialize
super
backport_ext_builder_monitor
end
+ def all_specs
+ require 'bundler/remote_specification'
+ Gem::Specification.stubs.map do |stub|
+ StubSpecification.from_stub(stub)
+ end
+ end
+
def backport_ext_builder_monitor
require 'rubygems/ext'
@@ -583,6 +606,18 @@ module Bundler
def ext_lock
Gem::Ext::Builder::CHDIR_MONITOR
end
+
+ if Gem::Specification.respond_to?(:stubs_for)
+ def find_name(name)
+ Gem::Specification.stubs_for(name).map(&:to_spec)
+ end
+ else
+ def find_name(name)
+ Gem::Specification.stubs.find_all do |spec|
+ spec.name == name
+ end.map(&:to_spec)
+ end
+ end
end
end
diff --git a/lib/bundler/runtime.rb b/lib/bundler/runtime.rb
index f83cb30742..be61c2b15b 100644
--- a/lib/bundler/runtime.rb
+++ b/lib/bundler/runtime.rb
@@ -88,9 +88,6 @@ module Bundler
raise if $1 != namespaced_file
end
end
- rescue => e
- Bundler.ui.debug e
- Bundler.ui.warn "Unable to require #{required_file}. #{e.class}: #{e.message}."
end
end
end
diff --git a/lib/bundler/settings.rb b/lib/bundler/settings.rb
index bed2c8e4d7..7a58c8af54 100644
--- a/lib/bundler/settings.rb
+++ b/lib/bundler/settings.rb
@@ -2,7 +2,9 @@ require 'uri'
module Bundler
class Settings
- BOOL_KEYS = %w(frozen cache_all no_prune disable_local_branch_check gem.mit gem.coc).freeze
+ BOOL_KEYS = %w(frozen cache_all no_prune disable_local_branch_check ignore_messages gem.mit gem.coc).freeze
+ NUMBER_KEYS = %w(retry timeout redirect).freeze
+ DEFAULT_CONFIG = {:retry => 3, :timeout => 10, :redirect => 5}
def initialize(root = nil)
@root = root
@@ -12,10 +14,13 @@ module Bundler
def [](name)
key = key_for(name)
- value = (@local_config[key] || ENV[key] || @global_config[key])
+ value = (@local_config[key] || ENV[key] || @global_config[key] || DEFAULT_CONFIG[name])
- if !value.nil? && is_bool(name)
+ case
+ when !value.nil? && is_bool(name)
to_bool(value)
+ when !value.nil? && is_num(name)
+ value.to_i
else
value
end
@@ -84,6 +89,7 @@ module Bundler
locations[:local] = @local_config[key] if @local_config.key?(key)
locations[:env] = ENV[key] if ENV[key]
locations[:global] = @global_config[key] if @global_config.key?(key)
+ locations[:default] = DEFAULT_CONFIG[key] if DEFAULT_CONFIG.key?(key)
locations
end
@@ -108,11 +114,19 @@ module Bundler
end
def without=(array)
- self[:without] = (array.empty? ? nil : array.join(":")) if array
+ set_array(:without, array)
+ end
+
+ def with=(array)
+ set_array(:with, array)
end
def without
- self[:without] ? self[:without].split(":").map { |w| w.to_sym } : []
+ get_array(:without)
+ end
+
+ def with
+ get_array(:with)
end
# @local_config["BUNDLE_PATH"] should be prioritized over ENV["BUNDLE_PATH"]
@@ -153,14 +167,38 @@ module Bundler
"BUNDLE_#{key}"
end
- def is_bool(key)
- BOOL_KEYS.include?(key.to_s)
+ def parent_setting_for(name)
+ split_specfic_setting_for(name)[0]
+ end
+
+ def specfic_gem_for(name)
+ split_specfic_setting_for(name)[1]
+ end
+
+ def split_specfic_setting_for(name)
+ name.split(".")
+ end
+
+ def is_bool(name)
+ BOOL_KEYS.include?(name.to_s) || BOOL_KEYS.include?(parent_setting_for(name.to_s))
end
def to_bool(value)
!(value.nil? || value == '' || value =~ /^(false|f|no|n|0)$/i || value == false)
end
+ def is_num(value)
+ NUMBER_KEYS.include?(value.to_s)
+ end
+
+ def get_array(key)
+ self[key] ? self[key].split(":").map { |w| w.to_sym } : []
+ end
+
+ def set_array(key, array)
+ self[key] = (array.empty? ? nil : array.join(":")) if array
+ end
+
def set_key(key, value, hash, file)
key = key_for(key)
diff --git a/lib/bundler/shared_helpers.rb b/lib/bundler/shared_helpers.rb
index 0087f0786a..f950041acc 100644
--- a/lib/bundler/shared_helpers.rb
+++ b/lib/bundler/shared_helpers.rb
@@ -21,6 +21,7 @@ module Bundler
def default_gemfile
gemfile = find_gemfile
+ deprecate_gemfile(gemfile)
raise GemfileNotFound, "Could not locate Gemfile" unless gemfile
Pathname.new(gemfile)
end
@@ -35,32 +36,27 @@ module Bundler
end
def default_bundle_dir
- global_bundle_dir = File.join(Bundler.rubygems.user_home, ".bundle")
bundle_dir = find_directory(".bundle")
+ return nil unless bundle_dir
- if bundle_dir && bundle_dir != global_bundle_dir
- Pathname.new(bundle_dir)
- else
- nil
- end
+ global_bundle_dir = File.join(Bundler.rubygems.user_home, ".bundle")
+ return nil if bundle_dir == global_bundle_dir
+
+ Pathname.new(bundle_dir)
end
def in_bundle?
find_gemfile
end
- def chdir_monitor
- Bundler.rubygems.ext_lock
- end
-
def chdir(dir, &blk)
- chdir_monitor.synchronize do
+ Bundler.rubygems.ext_lock.synchronize do
Dir.chdir dir, &blk
end
end
def pwd
- chdir_monitor.synchronize do
+ Bundler.rubygems.ext_lock.synchronize do
Dir.pwd
end
end
@@ -102,7 +98,6 @@ module Bundler
def find_gemfile
given = ENV['BUNDLE_GEMFILE']
return given if given && !given.empty?
-
find_file('Gemfile', 'gems.rb')
end
@@ -140,15 +135,28 @@ module Bundler
# handle 1.9 where system gems are always on the load path
if defined?(::Gem)
me = File.expand_path("../../", __FILE__)
+ me = /^#{Regexp.escape(me)}/
+
+ loaded_gem_paths = Bundler.rubygems.loaded_gem_paths
+
$LOAD_PATH.reject! do |p|
- next if File.expand_path(p) =~ /^#{Regexp.escape(me)}/
- p != File.dirname(__FILE__) &&
- Bundler.rubygems.gem_path.any?{|gp| p =~ /^#{Regexp.escape(gp)}/ }
+ next if File.expand_path(p) =~ me
+ loaded_gem_paths.delete(p)
end
$LOAD_PATH.uniq!
end
end
+ def deprecate_gemfile(gemfile)
+ if gemfile && File.basename(gemfile) == "Gemfile"
+ Bundler.respond_to?(:ui) && Bundler.ui.deprecate(
+ "Gemfile and Gemfile.lock are " \
+ "deprecated and will be replaced with gems.rb and " \
+ "gems.locked in Bundler 2.0.\n"
+ )
+ end
+ end
+
extend self
end
end
diff --git a/lib/bundler/source.rb b/lib/bundler/source.rb
index 213e98fb98..869931a1f0 100644
--- a/lib/bundler/source.rb
+++ b/lib/bundler/source.rb
@@ -27,5 +27,10 @@ module Bundler
def can_lock?(spec)
spec.source == self
end
+
+ def include?(other)
+ other == self
+ end
+
end
end
diff --git a/lib/bundler/source/git.rb b/lib/bundler/source/git.rb
index 62d615088c..230aa8fc40 100644
--- a/lib/bundler/source/git.rb
+++ b/lib/bundler/source/git.rb
@@ -159,9 +159,9 @@ module Bundler
local_specs
end
- def install(spec)
+ def install(spec, force = false)
debug = nil
- if requires_checkout? && !@copied
+ if requires_checkout? && !@copied && !force
debug = " * Checking out revision: #{ref}"
git_proxy.copy_to(install_path, submodules)
serialize_gemspecs_in(install_path)
diff --git a/lib/bundler/source/path.rb b/lib/bundler/source/path.rb
index 2b53bc7831..862fbcb97a 100644
--- a/lib/bundler/source/path.rb
+++ b/lib/bundler/source/path.rb
@@ -69,7 +69,7 @@ module Bundler
File.basename(expanded_path.to_s)
end
- def install(spec)
+ def install(spec, force = false)
generate_bin(spec, :disable_extensions)
["Using #{version_message(spec)} from #{to_s}", nil]
end
diff --git a/lib/bundler/source/path/installer.rb b/lib/bundler/source/path/installer.rb
index 28e69875aa..ef9faa9cbe 100644
--- a/lib/bundler/source/path/installer.rb
+++ b/lib/bundler/source/path/installer.rb
@@ -3,33 +3,38 @@ module Bundler
class Path
class Installer < Bundler::GemInstaller
+ attr_reader :spec
+
def initialize(spec, options = {})
@spec = spec
- @tmp_bin_dir = "#{Bundler.tmp(spec.full_name)}/bin"
- @gem_bin_dir = "#{Bundler.rubygems.gem_dir}/bin"
- @bin_dir = Bundler.requires_sudo? ? @tmp_bin_dir : @gem_bin_dir
@gem_dir = Bundler.rubygems.path(spec.full_gem_path)
- @wrappers = options[:wrappers] || true
- @env_shebang = options[:env_shebang] || true
+ @wrappers = true
+ @env_shebang = true
@format_executable = options[:format_executable] || false
@build_args = options[:build_args] || Bundler.rubygems.build_args
+ @gem_bin_dir = "#{Bundler.rubygems.gem_dir}/bin"
+
+ if Bundler.requires_sudo?
+ @tmp_dir = Bundler.tmp(spec.full_name).to_s
+ @bin_dir = "#{@tmp_dir}/bin"
+ else
+ @bin_dir = @gem_bin_dir
+ end
end
def generate_bin
return if spec.executables.nil? || spec.executables.empty?
- if Bundler.requires_sudo?
- FileUtils.mkdir_p(@tmp_bin_dir) unless File.exist?(@tmp_bin_dir)
- end
-
super
if Bundler.requires_sudo?
Bundler.mkdir_p @gem_bin_dir
spec.executables.each do |exe|
- Bundler.sudo "cp -R #{@tmp_bin_dir}/#{exe} #{@gem_bin_dir}"
+ Bundler.sudo "cp -R #{@bin_dir}/#{exe} #{@gem_bin_dir}"
end
end
+ ensure
+ Bundler.rm_rf(@tmp_dir) if Bundler.requires_sudo?
end
end
diff --git a/lib/bundler/source/rubygems.rb b/lib/bundler/source/rubygems.rb
index 8f504bcf7f..797988f365 100644
--- a/lib/bundler/source/rubygems.rb
+++ b/lib/bundler/source/rubygems.rb
@@ -38,11 +38,15 @@ module Bundler
end
def eql?(o)
- o.is_a?(Rubygems) && remotes_equal?(o.remotes)
+ o.is_a?(Rubygems) && o.credless_remotes == credless_remotes
end
alias == eql?
+ def include?(o)
+ o.is_a?(Rubygems) && (o.credless_remotes - credless_remotes).empty?
+ end
+
def can_lock?(spec)
spec.source.is_a?(Rubygems)
end
@@ -81,8 +85,21 @@ module Bundler
end
end
- def install(spec)
- return ["Using #{version_message(spec)}", nil] if installed_specs[spec].any?
+ def install(spec, opts = {})
+ force = opts[:force]
+ ensure_builtin_gems_cached = opts[:ensure_builtin_gems_cached]
+
+ if ensure_builtin_gems_cached && builtin_gem?(spec)
+ if !cached_path(spec)
+ cached_built_in_gem(spec) unless spec.remote
+ force = true
+ else
+ spec.loaded_from = loaded_from(spec)
+ end
+ end
+
+ return ["Using #{version_message(spec)}", nil] if installed_specs[spec].any? && !force
+
# Download the gem to get the spec, because some specs that are returned
# by rubygems.org are broken and wrong.
@@ -143,9 +160,7 @@ module Bundler
spec.loaded_from = loaded_from(spec)
["Installing #{version_message(spec)}", spec.post_install_message]
ensure
- if install_path && Bundler.requires_sudo?
- FileUtils.remove_entry_secure(install_path)
- end
+ Bundler.rm_rf(install_path) if Bundler.requires_sudo?
end
def cache(spec, custom_path = nil)
@@ -203,6 +218,10 @@ module Bundler
protected
+ def credless_remotes
+ remotes.map(&method(:suppress_configured_credentials))
+ end
+
def remotes_for_spec(spec)
specs.search_all(spec.name).inject([]) do |uris, s|
uris << s.remote if s.remote
@@ -210,8 +229,6 @@ module Bundler
end
end
- private
-
def loaded_from(spec)
"#{Bundler.rubygems.gem_dir}/specifications/#{spec.full_name}.gemspec"
end
@@ -293,7 +310,7 @@ module Bundler
end
def api_fetchers
- fetchers.select{|f| f.use_api }
+ fetchers.select(&:use_api)
end
def remote_specs
@@ -334,7 +351,7 @@ module Bundler
end
end until idxcount == idx.size
- if api_fetchers.any? && api_fetchers.all?{|f| f.use_api }
+ if api_fetchers.any?
# it's possible that gems from one source depend on gems from some
# other source, so now we download gemspecs and iterate over those
# dependencies, looking for gems we don't have info on yet.
@@ -351,7 +368,7 @@ module Bundler
end
end
- if !allow_api
+ unless allow_api
api_fetchers.each do |f|
Bundler.ui.info "Fetching source index from #{f.uri}"
idx.use f.specs(nil, self)
@@ -362,7 +379,23 @@ module Bundler
def fetch_gem(spec)
return false unless spec.remote
- Fetcher.download_gem_from_uri(spec, spec.remote.uri)
+ uri = spec.remote.uri
+ spec.fetch_platform
+
+ download_path = Bundler.requires_sudo? ? Bundler.tmp(spec.full_name) : Bundler.rubygems.gem_dir
+ gem_path = "#{Bundler.rubygems.gem_dir}/cache/#{spec.full_name}.gem"
+
+ FileUtils.mkdir_p("#{download_path}/cache")
+ Bundler.rubygems.download_gem(spec, uri, download_path)
+
+ if Bundler.requires_sudo?
+ Bundler.mkdir_p "#{Bundler.rubygems.gem_dir}/cache"
+ Bundler.sudo "mv #{download_path}/cache/#{spec.full_name}.gem #{gem_path}"
+ end
+
+ gem_path
+ ensure
+ Bundler.rm_rf(download_path) if Bundler.requires_sudo?
end
def builtin_gem?(spec)
@@ -373,10 +406,6 @@ module Bundler
spec.loaded_from && spec.loaded_from.include?("specifications/default/")
end
- def remotes_equal?(other_remotes)
- remotes.map(&method(:suppress_configured_credentials)) == other_remotes.map(&method(:suppress_configured_credentials))
- end
-
end
end
end
diff --git a/lib/bundler/source_list.rb b/lib/bundler/source_list.rb
index 49efbf7a8e..546b3b14be 100644
--- a/lib/bundler/source_list.rb
+++ b/lib/bundler/source_list.rb
@@ -15,7 +15,9 @@ module Bundler
end
def add_git_source(options = {})
- add_source_to_list Source::Git.new(options), git_sources
+ source = add_source_to_list(Source::Git.new(options), git_sources)
+ warn_on_git_protocol(source)
+ source
end
def add_rubygems_source(options = {})
@@ -97,5 +99,17 @@ module Bundler
def combine_rubygems_sources
Source::Rubygems.new("remotes" => rubygems_remotes)
end
+
+ def warn_on_git_protocol(source)
+ return if Bundler.settings["git.allow_insecure"]
+
+ if source.uri =~ %r{^git\:}
+ Bundler.ui.warn "The git source `#{source.uri}` uses the `git` protocol, " \
+ "which transmits data without encryption. Disable this warning with " \
+ "`bundle config git.allow_insecure true`, or switch to the `https` " \
+ "protocol to keep your data secure."
+ end
+ end
+
end
end
diff --git a/lib/bundler/templates/newgem/.travis.yml.tt b/lib/bundler/templates/newgem/.travis.yml.tt
index 4c7eba6364..d78885d0ee 100644
--- a/lib/bundler/templates/newgem/.travis.yml.tt
+++ b/lib/bundler/templates/newgem/.travis.yml.tt
@@ -1,3 +1,4 @@
language: ruby
rvm:
- <%= RUBY_VERSION %>
+before_install: gem install bundler -v <%= Bundler::VERSION %>
diff --git a/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt b/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt
index c5393d1403..ce9bee75b0 100644
--- a/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt
+++ b/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt
@@ -2,7 +2,7 @@
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
-We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
+We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
@@ -10,4 +10,4 @@ Project maintainers have the right and responsibility to remove, edit, or reject
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
-This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
+This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
diff --git a/lib/bundler/templates/newgem/Rakefile.tt b/lib/bundler/templates/newgem/Rakefile.tt
index e0e87e59a7..3d3fb674a0 100644
--- a/lib/bundler/templates/newgem/Rakefile.tt
+++ b/lib/bundler/templates/newgem/Rakefile.tt
@@ -4,6 +4,8 @@ require "rake/testtask"
Rake::TestTask.new(:test) do |t|
t.libs << "test"
+ t.libs << "lib"
+ t.test_files = FileList['test/**/*_test.rb']
end
task :default => :test
diff --git a/lib/bundler/templates/newgem/newgem.gemspec.tt b/lib/bundler/templates/newgem/newgem.gemspec.tt
index e647c17f69..16f12f279b 100644
--- a/lib/bundler/templates/newgem/newgem.gemspec.tt
+++ b/lib/bundler/templates/newgem/newgem.gemspec.tt
@@ -13,6 +13,14 @@ Gem::Specification.new do |spec|
spec.license = "MIT"
<%- end -%>
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
+ # delete this section to allow pushing this gem to any host.
+ if spec.respond_to?(:metadata)
+ spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
+ else
+ raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
+ end
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
@@ -21,10 +29,6 @@ Gem::Specification.new do |spec|
spec.extensions = ["ext/<%=config[:underscored_name]%>/extconf.rb"]
<%- end -%>
- if spec.respond_to?(:metadata)
- spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com' to prevent pushes to rubygems.org, or delete to allow pushes to any server."
- end
-
spec.add_development_dependency "bundler", "~> <%= config[:bundler_version] %>"
spec.add_development_dependency "rake", "~> 10.0"
<%- if config[:ext] -%>
diff --git a/lib/bundler/templates/newgem/test/test_newgem.rb.tt b/lib/bundler/templates/newgem/test/newgem_test.rb.tt
index d50f7da243..95e33a34ea 100644
--- a/lib/bundler/templates/newgem/test/test_newgem.rb.tt
+++ b/lib/bundler/templates/newgem/test/newgem_test.rb.tt
@@ -1,6 +1,6 @@
-require 'minitest_helper'
+require 'test_helper'
-class Test<%= config[:constant_name] %> < Minitest::Test
+class <%= config[:constant_name] %>Test < Minitest::Test
def test_that_it_has_a_version_number
refute_nil ::<%= config[:constant_name] %>::VERSION
end
diff --git a/lib/bundler/templates/newgem/test/minitest_helper.rb.tt b/lib/bundler/templates/newgem/test/test_helper.rb.tt
index 49a56c1800..49a56c1800 100644
--- a/lib/bundler/templates/newgem/test/minitest_helper.rb.tt
+++ b/lib/bundler/templates/newgem/test/test_helper.rb.tt
diff --git a/lib/bundler/ui/shell.rb b/lib/bundler/ui/shell.rb
index 8eb723181b..777aed0d86 100644
--- a/lib/bundler/ui/shell.rb
+++ b/lib/bundler/ui/shell.rb
@@ -3,7 +3,7 @@ module Bundler
class Shell
LEVELS = %w(silent error warn confirm info debug)
- attr_writer :shell
+ attr_writer :shell, :deprecation_messages
def initialize(options = {})
if options["no-color"] || !STDOUT.tty?
@@ -11,6 +11,7 @@ module Bundler
end
@shell = Thor::Base.shell.new
@level = ENV['DEBUG'] ? "debug" : "info"
+ @deprecation_messages = Set.new
end
def info(msg, newline = nil)
@@ -25,6 +26,13 @@ module Bundler
tell_stdout(msg, :yellow, newline) if level("warn")
end
+ def deprecate(msg, newline = nil)
+ unless @deprecation_messages.include?(msg)
+ @deprecation_messages.add(msg)
+ tell_stderr("DEPRECATION: " + msg, :yellow, newline)
+ end
+ end
+
def error(msg, newline = nil)
tell_stderr(msg, :red, newline) if level("error")
end
@@ -46,6 +54,14 @@ module Bundler
@shell.ask(msg)
end
+ def yes?(msg)
+ @shell.yes?(msg)
+ end
+
+ def no?
+ @shell.no?(msg)
+ end
+
def level=(level)
raise ArgumentError unless LEVELS.include?(level.to_s)
@level = level
diff --git a/lib/bundler/ui/silent.rb b/lib/bundler/ui/silent.rb
index 3eb3199b5c..b2420af7fb 100644
--- a/lib/bundler/ui/silent.rb
+++ b/lib/bundler/ui/silent.rb
@@ -10,6 +10,9 @@ module Bundler
def warn(message, newline = nil)
end
+ def deprecate(message, newline = nil)
+ end
+
def error(message, newline = nil)
end
diff --git a/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo.rb b/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo.rb
deleted file mode 100644
index bf740e4848..0000000000
--- a/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'molinillo/gem_metadata'
-require 'molinillo/errors'
-require 'molinillo/resolver'
-require 'molinillo/modules/ui'
-require 'molinillo/modules/specification_provider'
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo.rb b/lib/bundler/vendor/molinillo/lib/molinillo.rb
new file mode 100644
index 0000000000..50af4a912c
--- /dev/null
+++ b/lib/bundler/vendor/molinillo/lib/molinillo.rb
@@ -0,0 +1,5 @@
+require 'bundler/vendor/molinillo/lib/molinillo/gem_metadata'
+require 'bundler/vendor/molinillo/lib/molinillo/errors'
+require 'bundler/vendor/molinillo/lib/molinillo/resolver'
+require 'bundler/vendor/molinillo/lib/molinillo/modules/ui'
+require 'bundler/vendor/molinillo/lib/molinillo/modules/specification_provider'
diff --git a/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/dependency_graph.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb
index 4ee5708a56..7cde9fa5eb 100644
--- a/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/dependency_graph.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb
@@ -61,7 +61,7 @@ module Bundler::Molinillo
hash[name] = vertex.dup.tap { |v| v.graph = self }
end
end
- @root_vertices = Hash[vertices.select { |n, _v| other.root_vertices[n] }]
+ @root_vertices = Hash[@vertices.select { |n, _v| other.root_vertices[n] }]
@edges = other.edges.map do |edge|
Edge.new(
vertex_named(edge.origin.name),
diff --git a/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/errors.rb b/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb
index b828d0c20d..b828d0c20d 100644
--- a/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/errors.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb
diff --git a/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/gem_metadata.rb b/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb
index 0736b89c3c..2cf1b60b12 100644
--- a/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/gem_metadata.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb
@@ -1,3 +1,3 @@
module Bundler::Molinillo
- VERSION = '0.2.1'
+ VERSION = '0.2.3'
end
diff --git a/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/modules/specification_provider.rb b/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb
index 79a85e778f..79a85e778f 100644
--- a/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/modules/specification_provider.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb
diff --git a/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/modules/ui.rb b/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb
index 097c0264ac..097c0264ac 100644
--- a/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/modules/ui.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb
diff --git a/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/resolution.rb b/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb
index 376e4d4ed2..46a47d8028 100644
--- a/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/resolution.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb
@@ -73,6 +73,19 @@ module Bundler::Molinillo
end_resolution
end
+ # @return [Integer] the number of resolver iterations in between calls to
+ # {#resolver_ui}'s {UI#indicate_progress} method
+ attr_accessor :iteration_rate
+ private :iteration_rate
+
+ # @return [Time] the time at which resolution began
+ attr_accessor :started_at
+ private :started_at
+
+ # @return [Array<ResolutionState>] the stack of states for the resolution
+ attr_accessor :states
+ private :states
+
private
# Sets up the resolution process
@@ -98,18 +111,8 @@ module Bundler::Molinillo
debug { 'Activated: ' + Hash[activated.vertices.select { |_n, v| v.payload }].keys.join(', ') } if state
end
- require 'molinillo/state'
- require 'molinillo/modules/specification_provider'
-
- # @return [Integer] the number of resolver iterations in between calls to
- # {#resolver_ui}'s {UI#indicate_progress} method
- attr_accessor :iteration_rate
-
- # @return [Time] the time at which resolution began
- attr_accessor :started_at
-
- # @return [Array<ResolutionState>] the stack of states for the resolution
- attr_accessor :states
+ require 'bundler/vendor/molinillo/lib/molinillo/state'
+ require 'bundler/vendor/molinillo/lib/molinillo/modules/specification_provider'
ResolutionState.new.members.each do |member|
define_method member do |*args, &block|
diff --git a/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/resolver.rb b/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb
index 7cfe914d34..9a9d8fd1f8 100644
--- a/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/resolver.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb
@@ -1,4 +1,4 @@
-require 'molinillo/dependency_graph'
+require 'bundler/vendor/molinillo/lib/molinillo/dependency_graph'
module Bundler::Molinillo
# This class encapsulates a dependency resolver.
@@ -7,7 +7,7 @@ module Bundler::Molinillo
#
#
class Resolver
- require 'molinillo/resolution'
+ require 'bundler/vendor/molinillo/lib/molinillo/resolution'
# @return [SpecificationProvider] the specification provider used
# in the resolution process
diff --git a/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/state.rb b/lib/bundler/vendor/molinillo/lib/molinillo/state.rb
index 8e394f8672..8e394f8672 100644
--- a/lib/bundler/vendor/Molinillo-0.2.1/lib/molinillo/state.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/state.rb
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/parser.rb b/lib/bundler/vendor/thor-0.19.1/lib/thor/parser.rb
deleted file mode 100644
index 74c789b763..0000000000
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/parser.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require "thor/parser/argument"
-require "thor/parser/arguments"
-require "thor/parser/option"
-require "thor/parser/options"
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor.rb b/lib/bundler/vendor/thor/lib/thor.rb
index 8775d6a3e0..9ed67a44e2 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor.rb
+++ b/lib/bundler/vendor/thor/lib/thor.rb
@@ -1,5 +1,5 @@
require "set"
-require "thor/base"
+require "bundler/vendor/thor/lib/thor/base"
class Bundler::Thor # rubocop:disable ClassLength
class << self
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/actions.rb b/lib/bundler/vendor/thor/lib/thor/actions.rb
index 7edc70f472..5a82dfd45f 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/actions.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions.rb
@@ -1,12 +1,12 @@
require "fileutils"
require "uri"
-require "thor/core_ext/io_binary_read"
-require "thor/actions/create_file"
-require "thor/actions/create_link"
-require "thor/actions/directory"
-require "thor/actions/empty_directory"
-require "thor/actions/file_manipulation"
-require "thor/actions/inject_into_file"
+require "bundler/vendor/thor/lib/thor/core_ext/io_binary_read"
+require "bundler/vendor/thor/lib/thor/actions/create_file"
+require "bundler/vendor/thor/lib/thor/actions/create_link"
+require "bundler/vendor/thor/lib/thor/actions/directory"
+require "bundler/vendor/thor/lib/thor/actions/empty_directory"
+require "bundler/vendor/thor/lib/thor/actions/file_manipulation"
+require "bundler/vendor/thor/lib/thor/actions/inject_into_file"
class Bundler::Thor
module Actions
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/actions/create_file.rb b/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb
index 711ccb7d7b..a0f5640333 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/actions/create_file.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb
@@ -1,4 +1,4 @@
-require "thor/actions/empty_directory"
+require "bundler/vendor/thor/lib/thor/actions/empty_directory"
class Bundler::Thor
module Actions
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/actions/create_link.rb b/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb
index f633f25c18..be437922b6 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/actions/create_link.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb
@@ -1,4 +1,4 @@
-require "thor/actions/create_file"
+require "bundler/vendor/thor/lib/thor/actions/create_file"
class Bundler::Thor
module Actions
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/actions/directory.rb b/lib/bundler/vendor/thor/lib/thor/actions/directory.rb
index 3ed0649c27..1a2e25da2f 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/actions/directory.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions/directory.rb
@@ -1,4 +1,4 @@
-require "thor/actions/empty_directory"
+require "bundler/vendor/thor/lib/thor/actions/empty_directory"
class Bundler::Thor
module Actions
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/actions/empty_directory.rb b/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb
index cdc3768b4c..cdc3768b4c 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/actions/empty_directory.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/actions/file_manipulation.rb b/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb
index 2bdc78f578..2bdc78f578 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/actions/file_manipulation.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/actions/inject_into_file.rb b/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb
index 45a70701b1..91ab245ae1 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/actions/inject_into_file.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb
@@ -1,4 +1,4 @@
-require "thor/actions/empty_directory"
+require "bundler/vendor/thor/lib/thor/actions/empty_directory"
class Bundler::Thor
module Actions
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/base.rb b/lib/bundler/vendor/thor/lib/thor/base.rb
index 56b78ebad6..c3667521a5 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/base.rb
+++ b/lib/bundler/vendor/thor/lib/thor/base.rb
@@ -1,17 +1,17 @@
-require "thor/command"
-require "thor/core_ext/hash_with_indifferent_access"
-require "thor/core_ext/ordered_hash"
-require "thor/error"
-require "thor/invocation"
-require "thor/parser"
-require "thor/shell"
-require "thor/line_editor"
-require "thor/util"
+require "bundler/vendor/thor/lib/thor/command"
+require "bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access"
+require "bundler/vendor/thor/lib/thor/core_ext/ordered_hash"
+require "bundler/vendor/thor/lib/thor/error"
+require "bundler/vendor/thor/lib/thor/invocation"
+require "bundler/vendor/thor/lib/thor/parser"
+require "bundler/vendor/thor/lib/thor/shell"
+require "bundler/vendor/thor/lib/thor/line_editor"
+require "bundler/vendor/thor/lib/thor/util"
class Bundler::Thor
- autoload :Actions, "thor/actions"
- autoload :RakeCompat, "thor/rake_compat"
- autoload :Group, "thor/group"
+ autoload :Actions, "bundler/vendor/thor/lib/thor/actions"
+ autoload :RakeCompat, "bundler/vendor/thor/lib/thor/rake_compat"
+ autoload :Group, "bundler/vendor/thor/lib/thor/group"
# Shortcuts for help.
HELP_MAPPINGS = %w[-h -? --help -D]
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/command.rb b/lib/bundler/vendor/thor/lib/thor/command.rb
index 72c8348cb6..72c8348cb6 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/command.rb
+++ b/lib/bundler/vendor/thor/lib/thor/command.rb
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/core_ext/hash_with_indifferent_access.rb b/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb
index 6cf61db812..6cf61db812 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/core_ext/hash_with_indifferent_access.rb
+++ b/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/core_ext/io_binary_read.rb b/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb
index 19f3c3d43e..19f3c3d43e 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/core_ext/io_binary_read.rb
+++ b/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/core_ext/ordered_hash.rb b/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb
index 7e80672a07..7e80672a07 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/core_ext/ordered_hash.rb
+++ b/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/error.rb b/lib/bundler/vendor/thor/lib/thor/error.rb
index fc34c11268..fc34c11268 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/error.rb
+++ b/lib/bundler/vendor/thor/lib/thor/error.rb
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/group.rb b/lib/bundler/vendor/thor/lib/thor/group.rb
index 71e7f1c3b8..13d168ad62 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/group.rb
+++ b/lib/bundler/vendor/thor/lib/thor/group.rb
@@ -1,4 +1,4 @@
-require "thor/base"
+require "bundler/vendor/thor/lib/thor/base"
# Bundler::Thor has a special class called Bundler::Thor::Group. The main difference to Bundler::Thor class
# is that it invokes all commands at once. It also include some methods that allows
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/invocation.rb b/lib/bundler/vendor/thor/lib/thor/invocation.rb
index 684df2c616..684df2c616 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/invocation.rb
+++ b/lib/bundler/vendor/thor/lib/thor/invocation.rb
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/line_editor.rb b/lib/bundler/vendor/thor/lib/thor/line_editor.rb
index 95c848e0e3..ce81a17484 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/line_editor.rb
+++ b/lib/bundler/vendor/thor/lib/thor/line_editor.rb
@@ -1,5 +1,5 @@
-require "thor/line_editor/basic"
-require "thor/line_editor/readline"
+require "bundler/vendor/thor/lib/thor/line_editor/basic"
+require "bundler/vendor/thor/lib/thor/line_editor/readline"
class Bundler::Thor
module LineEditor
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/line_editor/basic.rb b/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb
index b121e95575..b121e95575 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/line_editor/basic.rb
+++ b/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/line_editor/readline.rb b/lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb
index dd39cff35d..dd39cff35d 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/line_editor/readline.rb
+++ b/lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb
diff --git a/lib/bundler/vendor/thor/lib/thor/parser.rb b/lib/bundler/vendor/thor/lib/thor/parser.rb
new file mode 100644
index 0000000000..08f80e565d
--- /dev/null
+++ b/lib/bundler/vendor/thor/lib/thor/parser.rb
@@ -0,0 +1,4 @@
+require "bundler/vendor/thor/lib/thor/parser/argument"
+require "bundler/vendor/thor/lib/thor/parser/arguments"
+require "bundler/vendor/thor/lib/thor/parser/option"
+require "bundler/vendor/thor/lib/thor/parser/options"
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/parser/argument.rb b/lib/bundler/vendor/thor/lib/thor/parser/argument.rb
index 84957903cd..84957903cd 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/parser/argument.rb
+++ b/lib/bundler/vendor/thor/lib/thor/parser/argument.rb
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/parser/arguments.rb b/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb
index c7bb648e31..c7bb648e31 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/parser/arguments.rb
+++ b/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/parser/option.rb b/lib/bundler/vendor/thor/lib/thor/parser/option.rb
index eb893617f4..eb893617f4 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/parser/option.rb
+++ b/lib/bundler/vendor/thor/lib/thor/parser/option.rb
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/parser/options.rb b/lib/bundler/vendor/thor/lib/thor/parser/options.rb
index deac6a0c16..deac6a0c16 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/parser/options.rb
+++ b/lib/bundler/vendor/thor/lib/thor/parser/options.rb
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/rake_compat.rb b/lib/bundler/vendor/thor/lib/thor/rake_compat.rb
index fcf6719df6..60282e2991 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/rake_compat.rb
+++ b/lib/bundler/vendor/thor/lib/thor/rake_compat.rb
@@ -5,7 +5,7 @@ class Bundler::Thor
# Adds a compatibility layer to your Bundler::Thor classes which allows you to use
# rake package tasks. For example, to use rspec rake tasks, one can do:
#
- # require 'thor/rake_compat'
+ # require 'bundler/vendor/thor/lib/thor/rake_compat'
# require 'rspec/core/rake_task'
#
# class Default < Bundler::Thor
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/runner.rb b/lib/bundler/vendor/thor/lib/thor/runner.rb
index 5552fe44bd..f0d7bfe2e0 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/runner.rb
+++ b/lib/bundler/vendor/thor/lib/thor/runner.rb
@@ -1,6 +1,6 @@
-require "thor"
-require "thor/group"
-require "thor/core_ext/io_binary_read"
+require "bundler/vendor/thor/lib/thor"
+require "bundler/vendor/thor/lib/thor/group"
+require "bundler/vendor/thor/lib/thor/core_ext/io_binary_read"
require "fileutils"
require "open-uri"
@@ -102,7 +102,7 @@ class Bundler::Thor::Runner < Bundler::Thor #:nodoc: # rubocop:disable ClassLeng
desc "version", "Show Bundler::Thor version"
def version
- require "thor/version"
+ require "bundler/vendor/thor/lib/thor/version"
say "Bundler::Thor #{Bundler::Thor::VERSION}"
end
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/shell.rb b/lib/bundler/vendor/thor/lib/thor/shell.rb
index 6a6ec5e0a4..91afdce2aa 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/shell.rb
+++ b/lib/bundler/vendor/thor/lib/thor/shell.rb
@@ -24,9 +24,9 @@ class Bundler::Thor
SHELL_DELEGATED_METHODS = [:ask, :error, :set_color, :yes?, :no?, :say, :say_status, :print_in_columns, :print_table, :print_wrapped, :file_collision, :terminal_width]
attr_writer :shell
- autoload :Basic, "thor/shell/basic"
- autoload :Color, "thor/shell/color"
- autoload :HTML, "thor/shell/html"
+ autoload :Basic, "bundler/vendor/thor/lib/thor/shell/basic"
+ autoload :Color, "bundler/vendor/thor/lib/thor/shell/color"
+ autoload :HTML, "bundler/vendor/thor/lib/thor/shell/html"
# Add shell to initialize config values.
#
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/shell/basic.rb b/lib/bundler/vendor/thor/lib/thor/shell/basic.rb
index 278ffa3df0..278ffa3df0 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/shell/basic.rb
+++ b/lib/bundler/vendor/thor/lib/thor/shell/basic.rb
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/shell/color.rb b/lib/bundler/vendor/thor/lib/thor/shell/color.rb
index 3c2feba4e5..1e2d26cfc5 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/shell/color.rb
+++ b/lib/bundler/vendor/thor/lib/thor/shell/color.rb
@@ -1,4 +1,4 @@
-require "thor/shell/basic"
+require "bundler/vendor/thor/lib/thor/shell/basic"
class Bundler::Thor
module Shell
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/shell/html.rb b/lib/bundler/vendor/thor/lib/thor/shell/html.rb
index 9e28690ad0..e1ea0de599 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/shell/html.rb
+++ b/lib/bundler/vendor/thor/lib/thor/shell/html.rb
@@ -1,4 +1,4 @@
-require "thor/shell/basic"
+require "bundler/vendor/thor/lib/thor/shell/basic"
class Bundler::Thor
module Shell
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/util.rb b/lib/bundler/vendor/thor/lib/thor/util.rb
index f4e98fc19f..f4e98fc19f 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/util.rb
+++ b/lib/bundler/vendor/thor/lib/thor/util.rb
diff --git a/lib/bundler/vendor/thor-0.19.1/lib/thor/version.rb b/lib/bundler/vendor/thor/lib/thor/version.rb
index 74b020a5ab..74b020a5ab 100644
--- a/lib/bundler/vendor/thor-0.19.1/lib/thor/version.rb
+++ b/lib/bundler/vendor/thor/lib/thor/version.rb
diff --git a/lib/bundler/vendored_molinillo.rb b/lib/bundler/vendored_molinillo.rb
index ce9ef0a3a1..4081f3fa92 100644
--- a/lib/bundler/vendored_molinillo.rb
+++ b/lib/bundler/vendored_molinillo.rb
@@ -1,5 +1,2 @@
-vendor = File.expand_path('../vendor/Molinillo-0.2.1/lib', __FILE__)
-loaded = $:.include?(vendor)
-$:.unshift(vendor) unless loaded
-require 'molinillo'
-$:.delete(vendor) unless loaded
+module Bundler; end
+require 'bundler/vendor/molinillo/lib/molinillo'
diff --git a/lib/bundler/vendored_thor.rb b/lib/bundler/vendored_thor.rb
index 2426f0c406..1931b5f278 100644
--- a/lib/bundler/vendored_thor.rb
+++ b/lib/bundler/vendored_thor.rb
@@ -1,5 +1,3 @@
-vendor = File.expand_path('../vendor/thor-0.19.1/lib', __FILE__)
-loaded = $:.include?(vendor)
-$:.unshift(vendor) unless loaded
-require 'thor'
-require 'thor/actions'
+module Bundler; end
+require 'bundler/vendor/thor/lib/thor'
+require 'bundler/vendor/thor/lib/thor/actions'
diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb
index 6d53a18d95..c27bfd8933 100644
--- a/lib/bundler/version.rb
+++ b/lib/bundler/version.rb
@@ -2,5 +2,5 @@ module Bundler
# We're doing this because we might write tests that deal
# with other versions of bundler and we are unsure how to
# handle this better.
- VERSION = "1.9.0.rc" unless defined?(::Bundler::VERSION)
+ VERSION = "1.99.0.pre" unless defined?(::Bundler::VERSION)
end
diff --git a/man/bundle-config.ronn b/man/bundle-config.ronn
index 8bbc5140e1..b57dc45bef 100644
--- a/man/bundle-config.ronn
+++ b/man/bundle-config.ronn
@@ -35,6 +35,38 @@ local and global sources. Not compatible with --global or --local flag.
Executing bundle with the `BUNDLE_IGNORE_CONFIG` environment variable set will
cause it to ignore all configuration.
+## REMEMBERING OPTIONS
+
+Flags passed to `bundle install` or the Bundler runtime, such as `--path foo` or `--without production`, are not remembered between commands. If these options must be remembered, they must be set using `bundle config` (e.g., `bundle config path foo`).
+
+The options that can be remembered for future commands are:
+
+* `binstubs`:
+ Creates a directory (defaults to `~/bin`) and place any executables from the
+ gem there. These executables run in Bundler's context. If used, you might add
+ this directory to your environment's `PATH` variable. For instance, if the
+ `rails` gem comes with a `rails` executable, this flag will create a
+ `bin/rails` executable that ensures that all referred dependencies will be
+ resolved using the bundled gems.
+
+* `deployment`:
+ In deployment mode, Bundler will 'roll-out' the bundle for
+ `production` use. Please check carefully if you want to have this option
+ enabled in `development` or `test` environments.
+
+* `path`:
+ The location to install the specified gems to. This defaults to Rubygems'
+ setting. Bundler shares this location with Rubygems, `gem install ...` will
+ have gem installed there, too. Therefore, gems installed without a
+ `--path ...` setting will show up by calling `gem list`. Accodingly, gems
+ installed to other locations will not get listed.
+
+* `without`:
+ A space-separated list of groups referencing gems to skip during installation.
+
+* `with`:
+ A space-separated list of optional groups to be installed.
+
## BUILD OPTIONS
You can use `bundle config` to give bundler the flags to pass to the gem
@@ -102,9 +134,18 @@ learn more about their operation in [bundle install(1)][bundle-install].
* `ssl_client_cert` (`BUNDLE_SSL_CLIENT_CERT`):
Path to a designated file containing a X.509 client certificate
and key in PEM format.
+* `cache_path` (`BUNDLE_CACHE_PATH`): The directory that bundler will place
+ cached gems in when running <code>bundle package</code>, and that bundler
+ will look in when installing gems.
+* `disable_multisource` (`BUNDLE_DISABLE_MULTISOURCE`): When set, Gemfiles
+ containing multiple sources will produce errors instead of warnings. Use
+ `bundle config --delete disable_multisource` to unset.
+* `ignore_messages` (`BUNDLE_IGNORE_MESSAGES`): When set, no post install
+ messages will be printed. To silence a single gem, use dot notation like
+ `ignore_messages.httparty true`.
In general, you should set these settings per-application by using the applicable
-flag to the [bundle install(1)][bundle-install] command.
+flag to the [bundle install(1)][bundle-install] or [bundle package(1)][bundle-package] command.
You can set them globally either via environment variables or `bundle config`,
whichever is preferable for your setup. If you use both, environment variables
diff --git a/man/bundle-install.ronn b/man/bundle-install.ronn
index 0af3fb6708..9db1832fd7 100644
--- a/man/bundle-install.ronn
+++ b/man/bundle-install.ronn
@@ -8,16 +8,19 @@ bundle-install(1) -- Install the dependencies specified in your Gemfile
[--full-index]
[--gemfile=GEMFILE]
[--jobs=NUMBER]
- [--local] [--deployment]
+ [--local]
+ [--deployment]
[--cache]
[--no-prune]
- [--path PATH] [--system]
+ [--path PATH]
+ [--system]
[--quiet]
[--retry=NUMBER]
[--shebang]
[--standalone[=GROUP[ GROUP...]]]
[--trust-policy=POLICY]
[--without=GROUP[ GROUP...]]
+ [--with=GROUP[ GROUP...]]
## DESCRIPTION
@@ -38,6 +41,9 @@ update process below under [CONSERVATIVE UPDATING][].
## OPTIONS
+To apply any of `--deployment`, `--path`, `--binstubs`, or `--without` every
+time `bundle install` is run, use `bundle config` (see bundle-config(1)).
+
* `--binstubs[=<directory>]`:
Creates a directory (defaults to `~/bin`) and place any executables from the
gem there. These executables run in Bundler's context. If used, you might add
@@ -79,7 +85,7 @@ update process below under [CONSERVATIVE UPDATING][].
* `--system`:
Installs the gems specified in the bundle to the system's Rubygems location.
- This overrides any previous [remembered][REMEMBERED OPTIONS] use of `--path`.
+ This overrides any previous configuration of `--path`.
* `--cache`:
Update the cache in `vendor/cache` with the newly bundled gems during the
@@ -93,8 +99,7 @@ update process below under [CONSERVATIVE UPDATING][].
setting. Bundler shares this location with Rubygems, `gem install ...` will
have gem installed there, too. Therefore, gems installed without a
`--path ...` setting will show up by calling `gem list`. Accodingly, gems
- installed to other locations will not get listed. This setting is a
- [remembered option][REMEMBERED OPTIONS].
+ installed to other locations will not get listed.
* `--quiet`:
Do not print progress information to the standard output. Instead, Bundler
@@ -124,8 +129,10 @@ update process below under [CONSERVATIVE UPDATING][].
* `--without=<list>`:
A space-separated list of groups referencing gems to skip during installation.
- This is a [remembered option][REMEMBERED OPTIONS].
+* `--with=<list>`:
+ A space-separated list of groups referencing gems to install. If an
+ optional group is given it is installed.
## DEPLOYMENT MODE
@@ -250,41 +257,6 @@ the vagaries of the dependency resolution process, this usually
affects more than just the gems you list in your Gemfile(5), and can
(surprisingly) radically change the gems you are using.
-## REMEMBERED OPTIONS
-
-Some options (marked above in the [OPTIONS][] section) are remembered
-between calls to `bundle install`, and by the Bundler runtime.
-
-For instance, if you run `bundle install --without test`, a subsequent
-call to `bundle install` that does not include a `--without` flag will
-remember your previous choice.
-
-In addition, a call to `Bundler.setup` will not attempt to make the
-gems in those groups available on the Ruby load path, as they were
-not installed.
-
-The settings that are remembered are:
-
-* `--deployment`:
- At runtime, this remembered setting will also result in Bundler
- raising an exception if the `Gemfile.lock` is out of date.
-
-* `--path`:
- Subsequent calls to `bundle install` will install gems to the
- directory originally passed to `--path`. The Bundler runtime
- will look for gems in that location. You can revert this
- option by running `bundle install --system`.
-
-* `--binstubs`:
- Bundler will update the executables every subsequent call to
- `bundle install`.
-
-* `--without`:
- As described above, Bundler will skip the gems specified by
- `--without` in subsequent calls to `bundle install`. The
- Bundler runtime will also not try to make the gems in the
- skipped groups available.
-
## THE GEMFILE.LOCK
When you run `bundle install`, Bundler will persist the full names
diff --git a/man/gemfile.5.ronn b/man/gemfile.5.ronn
index 876c927380..89911695fc 100644
--- a/man/gemfile.5.ronn
+++ b/man/gemfile.5.ronn
@@ -430,11 +430,15 @@ applied to a group of gems by using block form.
gem "sqlite3"
end
- group :development do
+ group :development, :optional => true do
gem "wirble"
gem "faker"
end
+In the case of the group block form the :optional option can be given
+to prevent a group from being installed unless listed in the `--with`
+option given to the `bundle install` command.
+
In the case of the `git` block form, the `:ref`, `:branch`, `:tag`,
and `:submodules` options may be passed to the `git` method, and
all gems in the block will inherit those options.
@@ -453,10 +457,10 @@ files in your test code as you would if the project were installed as a gem; you
need not manipulate the load path manually or require project files via relative
paths.
-The `gemspec` method supports optional `:path`, `:name`, and `:development_group`
-options, which control where bundler looks for the `.gemspec`, what named
-`.gemspec` it uses (if more than one is present), and which group development
-dependencies are included in.
+The `gemspec` method supports optional `:path`, `:glob`, `:name`, and `:development_group`
+options, which control where bundler looks for the `.gemspec`, the glob it uses to look
+for the gemspec (defaults to: "{,*,*/*}.gemspec"), what named `.gemspec` it uses
+(if more than one is present), and which group development dependencies are included in.
## SOURCE PRIORITY
diff --git a/spec/bundler/bundler_spec.rb b/spec/bundler/bundler_spec.rb
index f26183e073..fa226002cc 100644
--- a/spec/bundler/bundler_spec.rb
+++ b/spec/bundler/bundler_spec.rb
@@ -17,13 +17,11 @@ describe Bundler do
end
end
- context "on Ruby 1.8", :ruby => "1.8" do
- it "catches YAML syntax errors" do
- expect { subject }.to raise_error(Bundler::GemspecError)
- end
+ it "catches YAML syntax errors" do
+ expect { subject }.to raise_error(Bundler::GemspecError)
end
- context "on Ruby 1.9", :ruby => "1.9", :if => defined?(YAML::ENGINE) do
+ context "on Rubies with a settable YAML engine", :if => defined?(YAML::ENGINE) do
context "with Syck as YAML::Engine" do
it "raises a GemspecError after YAML load throws ArgumentError" do
orig_yamler, YAML::ENGINE.yamler = YAML::ENGINE.yamler, 'syck'
diff --git a/spec/bundler/fetcher_spec.rb b/spec/bundler/fetcher_spec.rb
index 4640f63519..0d47bc5e90 100644
--- a/spec/bundler/fetcher_spec.rb
+++ b/spec/bundler/fetcher_spec.rb
@@ -1,6 +1,9 @@
require 'spec_helper'
+require 'bundler/fetcher'
describe Bundler::Fetcher do
+ subject(:fetcher) { Bundler::Fetcher.new(double("remote", :uri => URI("https://example.com"))) }
+
before do
allow(Bundler).to receive(:root){ Pathname.new("root") }
end
@@ -8,10 +11,10 @@ describe Bundler::Fetcher do
describe "#user_agent" do
it "builds user_agent with current ruby version and Bundler settings" do
allow(Bundler.settings).to receive(:all).and_return(["foo", "bar"])
- expect(described_class.user_agent).to match(/bundler\/(\d.)/)
- expect(described_class.user_agent).to match(/rubygems\/(\d.)/)
- expect(described_class.user_agent).to match(/ruby\/(\d.)/)
- expect(described_class.user_agent).to match(/options\/foo,bar/)
+ expect(fetcher.user_agent).to match(/bundler\/(\d.)/)
+ expect(fetcher.user_agent).to match(/rubygems\/(\d.)/)
+ expect(fetcher.user_agent).to match(/ruby\/(\d.)/)
+ expect(fetcher.user_agent).to match(/options\/foo,bar/)
end
end
end
diff --git a/spec/bundler/friendly_errors_spec.rb b/spec/bundler/friendly_errors_spec.rb
index 96c333a739..ee0667cb2f 100644
--- a/spec/bundler/friendly_errors_spec.rb
+++ b/spec/bundler/friendly_errors_spec.rb
@@ -10,4 +10,21 @@ describe Bundler, "friendly errors" do
end
}.to raise_error(SystemExit)
end
+
+ describe "#issues_url" do
+ it "generates a search URL for the exception message" do
+ exception = Exception.new("Exception message")
+
+ expect(Bundler.issues_url(exception)).to eq("https://github.com/bundler/bundler/search?q=Exception+message&type=Issues")
+ end
+
+ it "generates a search URL for only the first line of a multi-line exception message" do
+ exception = Exception.new(<<END)
+First line of the exception message
+Second line of the exception message
+END
+
+ expect(Bundler.issues_url(exception)).to eq("https://github.com/bundler/bundler/search?q=First+line+of+the+exception+message&type=Issues")
+ end
+ end
end
diff --git a/spec/bundler/gem_helper_spec.rb b/spec/bundler/gem_helper_spec.rb
index 2b0f3d97aa..8cfacbac01 100644
--- a/spec/bundler/gem_helper_spec.rb
+++ b/spec/bundler/gem_helper_spec.rb
@@ -28,6 +28,15 @@ describe Bundler::GemHelper do
end
context "interpolates the name" do
+ before do
+ # Remove exception that prevents public pushes on older RubyGems versions
+ if Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.0")
+ content = File.read(app_gemspec_path)
+ content.sub!(/raise "RubyGems 2\.0 or newer.*/, "")
+ File.open(app_gemspec_path, "w"){|f| f.write(content) }
+ end
+ end
+
it "when there is only one gemspec" do
expect(subject.gemspec.name).to eq(app_name)
end
@@ -62,7 +71,7 @@ describe Bundler::GemHelper do
let(:app_version) { "0.1.0" }
let(:app_gem_dir) { app_path.join("pkg") }
let(:app_gem_path) { app_gem_dir.join("#{app_name}-#{app_version}.gem") }
- let(:app_gemspec_content) { File.read(app_gemspec_path) }
+ let(:app_gemspec_content) { remove_push_guard(File.read(app_gemspec_path)) }
before(:each) do
content = app_gemspec_content.gsub("TODO: ", "")
@@ -70,6 +79,14 @@ describe Bundler::GemHelper do
File.open(app_gemspec_path, "w") { |file| file << content }
end
+ def remove_push_guard(gemspec_content)
+ # Remove exception that prevents public pushes on older RubyGems versions
+ if Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.0")
+ gemspec_content.sub!(/raise "RubyGems 2\.0 or newer.*/, "")
+ end
+ gemspec_content
+ end
+
it "uses a shell UI for output" do
expect(Bundler.ui).to be_a(Bundler::UI::Shell)
end
diff --git a/spec/bundler/retry_spec.rb b/spec/bundler/retry_spec.rb
index 8e35a1013d..aa4e5e42ad 100644
--- a/spec/bundler/retry_spec.rb
+++ b/spec/bundler/retry_spec.rb
@@ -11,17 +11,6 @@ describe Bundler::Retry do
expect(attempts).to eq(1)
end
- it "defaults to retrying twice" do
- attempts = 0
- expect {
- Bundler::Retry.new(nil).attempt do
- attempts += 1
- raise "nope"
- end
- }.to raise_error("nope")
- expect(attempts).to eq(3)
- end
-
it "returns the first valid result" do
jobs = [Proc.new{ raise "foo" }, Proc.new{ :bar }, Proc.new{ raise "foo" }]
attempts = 0
diff --git a/spec/bundler/settings_spec.rb b/spec/bundler/settings_spec.rb
index 1e197f22f0..cb8440689e 100644
--- a/spec/bundler/settings_spec.rb
+++ b/spec/bundler/settings_spec.rb
@@ -15,6 +15,34 @@ describe Bundler::Settings do
end
end
+ describe "#[]" do
+ context "when not set" do
+ context "when default value present" do
+ it "retrieves value" do
+ expect(settings[:retry]).to be 3
+ end
+ end
+
+ it "returns nil" do
+ expect(settings[:buttermilk]).to be nil
+ end
+ end
+
+ context "when is boolean" do
+ it "returns a boolean" do
+ settings[:frozen] = "true"
+ expect(settings[:frozen]).to be true
+ end
+ context "when specific gem is configured" do
+ it "returns a boolean" do
+ settings["ignore_messages.foobar"] = "true"
+ expect(settings["ignore_messages.foobar"]).to be true
+ end
+ end
+ end
+ end
+
+
describe "#mirror_for" do
let(:uri) { URI("https://rubygems.org/") }
diff --git a/spec/bundler/source_list_spec.rb b/spec/bundler/source_list_spec.rb
index f5a8575ae8..25e0e54391 100644
--- a/spec/bundler/source_list_spec.rb
+++ b/spec/bundler/source_list_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Bundler::SourceList do
before do
- allow(Bundler).to receive(:root) { Pathname.new '/' }
+ allow(Bundler).to receive(:root) { Pathname.new './tmp/bundled_app' }
end
subject(:source_list) { Bundler::SourceList.new }
@@ -40,26 +40,45 @@ describe Bundler::SourceList do
end
describe "#add_git_source" do
- before do
- @duplicate = source_list.add_git_source('uri' => 'git://host/path.git')
- @new_source = source_list.add_git_source('uri' => 'git://host/path.git')
- end
-
it "returns the new git source" do
+ @new_source = source_list.add_git_source('uri' => 'git://host/path.git')
expect(@new_source).to be_instance_of(Bundler::Source::Git)
end
it "passes the provided options to the new source" do
+ @new_source = source_list.add_git_source('uri' => 'git://host/path.git')
expect(@new_source.options).to eq('uri' => 'git://host/path.git')
end
it "adds the source to the beginning of git_sources" do
+ @new_source = source_list.add_git_source('uri' => 'git://host/path.git')
expect(source_list.git_sources.first).to equal(@new_source)
end
it "removes existing duplicates" do
+ @duplicate = source_list.add_git_source('uri' => 'git://host/path.git')
+ @new_source = source_list.add_git_source('uri' => 'git://host/path.git')
expect(source_list.git_sources).not_to include equal(@duplicate)
end
+
+ context "with the git: protocol" do
+ let(:msg) { "The git source `git://existing-git.org/path.git` " \
+ "uses the `git` protocol, which transmits data without encryption. " \
+ "Disable this warning with `bundle config git.allow_insecure true`, " \
+ "or switch to the `https` protocol to keep your data secure."
+ }
+
+ it "warns about git protocols" do
+ expect(Bundler.ui).to receive(:warn).with(msg)
+ source_list.add_git_source('uri' => 'git://existing-git.org/path.git')
+ end
+
+ it "ignores git protocols on request" do
+ Bundler.settings["git.allow_insecure"] = true
+ expect(Bundler.ui).to_not receive(:warn).with(msg)
+ source_list.add_git_source('uri' => 'git://existing-git.org/path.git')
+ end
+ end
end
describe "#add_rubygems_source" do
diff --git a/spec/cache/git_spec.rb b/spec/cache/git_spec.rb
index b369504dcb..bfaa0c5f63 100644
--- a/spec/cache/git_spec.rb
+++ b/spec/cache/git_spec.rb
@@ -59,7 +59,7 @@ end
bundle "#{cmd} --all"
bundle "#{cmd} --all"
- expect(err).to eq("")
+ expect(err).to lack_errors
FileUtils.rm_rf lib_path("foo-1.0")
should_be_installed "foo 1.0"
end
diff --git a/spec/commands/binstubs_spec.rb b/spec/commands/binstubs_spec.rb
index b92076911f..47bbe35317 100644
--- a/spec/commands/binstubs_spec.rb
+++ b/spec/commands/binstubs_spec.rb
@@ -47,7 +47,7 @@ describe "bundle binstubs <gem>" do
bundle "binstubs"
expect(exitstatus).to eq(1) if exitstatus
- expect(err).to eq("`bundle binstubs` needs at least one gem to run.")
+ expect(err).to include("`bundle binstubs` needs at least one gem to run.")
end
it "does not bundle the bundler binary" do
@@ -58,7 +58,7 @@ describe "bundle binstubs <gem>" do
bundle "binstubs bundler"
expect(bundled_app("bin/bundle")).not_to exist
- expect(out).to eq("Sorry, Bundler can only be run via Rubygems.")
+ expect(out).to include("Sorry, Bundler can only be run via Rubygems.")
end
it "installs binstubs from git gems" do
@@ -114,7 +114,7 @@ describe "bundle binstubs <gem>" do
bundle "binstubs doesnt_exist"
expect(exitstatus).to eq(7) if exitstatus
- expect(err).to eq("Could not find gem 'doesnt_exist'.")
+ expect(err).to include("Could not find gem 'doesnt_exist'.")
end
end
diff --git a/spec/commands/check_spec.rb b/spec/commands/check_spec.rb
index 76d8264718..d5c1247bd3 100644
--- a/spec/commands/check_spec.rb
+++ b/spec/commands/check_spec.rb
@@ -9,7 +9,7 @@ describe "bundle check" do
bundle :check
expect(exitstatus).to eq(0) if exitstatus
- expect(out).to eq("The Gemfile's dependencies are satisfied")
+ expect(out).to include("The Gemfile's dependencies are satisfied")
end
it "works with the --gemfile flag when not in the directory" do
@@ -20,7 +20,7 @@ describe "bundle check" do
Dir.chdir tmp
bundle "check --gemfile bundled_app/Gemfile"
- expect(out).to eq("The Gemfile's dependencies are satisfied")
+ expect(out).to include("The Gemfile's dependencies are satisfied")
end
it "creates a Gemfile.lock by default if one does not exist" do
@@ -152,7 +152,7 @@ describe "bundle check" do
G
bundle :check
- expect(out).to eq("The Gemfile's dependencies are satisfied")
+ expect(out).to include("The Gemfile's dependencies are satisfied")
end
it "works with env conditionals" do
@@ -183,7 +183,7 @@ describe "bundle check" do
G
bundle :check
- expect(out).to eq("The Gemfile's dependencies are satisfied")
+ expect(out).to include("The Gemfile's dependencies are satisfied")
end
it "outputs an error when the default Gemfile is not found" do
@@ -242,7 +242,7 @@ describe "bundle check" do
it "returns success" do
bundle "check --path vendor/bundle"
expect(exitstatus).to eq(0) if exitstatus
- expect(out).to eq("The Gemfile's dependencies are satisfied")
+ expect(out).to include("The Gemfile's dependencies are satisfied")
end
it "should write to .bundle/config" do
@@ -265,7 +265,7 @@ describe "bundle check" do
bundle :install
bundle :check
expect(exitstatus).to eq(0) if exitstatus
- expect(out).to eq("The Gemfile's dependencies are satisfied")
+ expect(out).to include("The Gemfile's dependencies are satisfied")
end
it "shows what is missing with the current Gemfile if it is not satisfied" do
diff --git a/spec/commands/clean_spec.rb b/spec/commands/clean_spec.rb
index 4c69e68eb8..14b9226844 100644
--- a/spec/commands/clean_spec.rb
+++ b/spec/commands/clean_spec.rb
@@ -36,7 +36,7 @@ describe "bundle clean" do
bundle :clean
- expect(out).to eq("Removing foo (1.0)")
+ expect(out).to include("Removing foo (1.0)")
should_have_gems 'thin-1.0', 'rack-1.0.0'
should_not_have_gems 'foo-1.0'
@@ -64,7 +64,7 @@ describe "bundle clean" do
bundle :clean
- expect(out).to eq("Removing rack (0.9.1)")
+ expect(out).to include("Removing rack (0.9.1)")
should_have_gems 'foo-1.0', 'rack-1.0.0'
should_not_have_gems 'rack-0.9.1'
@@ -92,7 +92,7 @@ describe "bundle clean" do
bundle :clean
- expect(out).to eq("Removing rack (1.0.0)")
+ expect(out).to include("Removing rack (1.0.0)")
should_have_gems 'foo-1.0', 'rack-0.9.1'
should_not_have_gems 'rack-1.0.0'
@@ -115,7 +115,7 @@ describe "bundle clean" do
bundle "install --without test_group"
bundle :clean
- expect(out).to eq("Removing rack (1.0.0)")
+ expect(out).to include("Removing rack (1.0.0)")
should_have_gems 'foo-1.0'
should_not_have_gems 'rack-1.0.0'
@@ -170,7 +170,7 @@ describe "bundle clean" do
bundle :clean
- expect(out).to eq("Removing foo (#{revision[0..11]})")
+ expect(out).to include("Removing foo (#{revision[0..11]})")
expect(vendored_gems("gems/rack-1.0.0")).to exist
expect(vendored_gems("bundler/gems/foo-#{revision[0..11]}")).not_to exist
@@ -203,7 +203,7 @@ describe "bundle clean" do
bundle "update"
bundle :clean
- expect(out).to eq("Removing foo-bar (#{revision[0..11]})")
+ expect(out).to include("Removing foo-bar (#{revision[0..11]})")
expect(vendored_gems("gems/rack-1.0.0")).to exist
expect(vendored_gems("bundler/gems/foo-bar-#{revision[0..11]}")).not_to exist
@@ -227,7 +227,7 @@ describe "bundle clean" do
bundle "install --path vendor/bundle"
bundle :clean
- expect(out).to eq("")
+ expect(out).to include("")
expect(vendored_gems("bundler/gems/rails-#{revision[0..11]}")).to exist
end
@@ -251,7 +251,7 @@ describe "bundle clean" do
bundle :clean
- expect(out).to eq("")
+ expect(out).to include("")
expect(vendored_gems("bundler/gems/foo-#{revision[0..11]}")).to exist
digest = Digest::SHA1.hexdigest(git_path.to_s)
expect(vendored_gems("cache/bundler/git/foo-#{digest}")).to_not exist
@@ -451,7 +451,7 @@ describe "bundle clean" do
bundle :install
bundle "clean --force"
- expect(out).to eq("Removing foo (1.0)")
+ expect(out).to include("Removing foo (1.0)")
sys_exec "gem list"
expect(out).not_to include("foo (1.0)")
expect(out).to include("rack (1.0.0)")
@@ -552,8 +552,8 @@ describe "bundle clean" do
bundle "clean --dry-run"
- expect(out).not_to eq("Removing foo (1.0)")
- expect(out).to eq("Would have removed foo (1.0)")
+ expect(out).not_to include("Removing foo (1.0)")
+ expect(out).to include("Would have removed foo (1.0)")
should_have_gems 'thin-1.0', 'rack-1.0.0', 'foo-1.0'
@@ -581,8 +581,8 @@ describe "bundle clean" do
bundle "clean"
- expect(out).to eq("Removing foo (1.0)")
- expect(out).not_to eq("Would have removed foo (1.0)")
+ expect(out).to include("Removing foo (1.0)")
+ expect(out).not_to include("Would have removed foo (1.0)")
should_have_gems 'thin-1.0', 'rack-1.0.0'
should_not_have_gems 'foo-1.0'
diff --git a/spec/commands/config_spec.rb b/spec/commands/config_spec.rb
index f12a844cc1..cd1f23e4a0 100644
--- a/spec/commands/config_spec.rb
+++ b/spec/commands/config_spec.rb
@@ -258,6 +258,9 @@ E
"here is quite a long string that will wrap to a second line but will not be " \
"surrounded by quotes"
end
+ let(:long_string_without_special_characters) do
+ "here is quite a long string that will wrap to a second line but will not be surrounded by quotes"
+ end
it "doesn't wrap values" do
bundle "config foo #{long_string}"
diff --git a/spec/commands/exec_spec.rb b/spec/commands/exec_spec.rb
index ebc8c7cfde..47e9629a63 100644
--- a/spec/commands/exec_spec.rb
+++ b/spec/commands/exec_spec.rb
@@ -30,7 +30,7 @@ describe "bundle exec" do
bundle "exec 'cd #{tmp('gems')} && rackup'"
- expect(out).to eq("1.0.0")
+ expect(out).to include("1.0.0")
end
it "works when exec'ing something else" do
@@ -85,14 +85,14 @@ describe "bundle exec" do
expect(out).to eq("Ruby version #{RUBY_VERSION} defaults to keeping non-standard file descriptors on Kernel#exec.")
end
- expect(err).to eq("")
+ expect(err).to lack_errors
end
it "accepts --keep-file-descriptors" do
install_gemfile ''
bundle "exec --keep-file-descriptors echo foobar"
- expect(err).to eq("")
+ expect(err).to lack_errors
end
it "can run a command named --verbose" do
@@ -178,10 +178,10 @@ describe "bundle exec" do
rubylib = rubylib.uniq.join(File::PATH_SEPARATOR)
bundle "exec 'echo $RUBYLIB'"
- expect(out).to eq(rubylib)
+ expect(out).to include(rubylib)
bundle "exec 'echo $RUBYLIB'", :env => {"RUBYLIB" => rubylib}
- expect(out).to eq(rubylib)
+ expect(out).to include(rubylib)
end
it "errors nicely when the argument doesn't exist" do
@@ -226,13 +226,13 @@ describe "bundle exec" do
it "works when unlocked" do
bundle "exec 'cd #{tmp('gems')} && rackup'"
- expect(out).to eq("1.0.0")
+ expect(out).to include("1.0.0")
end
it "works when locked" do
should_be_locked
bundle "exec 'cd #{tmp('gems')} && rackup'"
- expect(out).to eq("1.0.0")
+ expect(out).to include("1.0.0")
end
end
diff --git a/spec/commands/lock_spec.rb b/spec/commands/lock_spec.rb
index 5e6f07dd4a..975e541d15 100644
--- a/spec/commands/lock_spec.rb
+++ b/spec/commands/lock_spec.rb
@@ -47,13 +47,16 @@ describe "bundle lock" do
foo
rails
with_license
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
L
end
it "prints a lockfile when there is no existing lockfile with --print" do
bundle "lock --print"
- expect(out).to eq(@lockfile)
+ expect(out).to include(@lockfile)
end
it "prints a lockfile when there is an existing lockfile with --print" do
diff --git a/spec/commands/newgem_spec.rb b/spec/commands/newgem_spec.rb
index c8c5bf5917..9dd54176e2 100644
--- a/spec/commands/newgem_spec.rb
+++ b/spec/commands/newgem_spec.rb
@@ -7,6 +7,15 @@ describe "bundle gem" do
global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false"
end
+ def remove_push_guard(gem_name)
+ # Remove exception that prevents public pushes on older RubyGems versions
+ if Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.0")
+ path = "#{gem_name}/#{gem_name}.gemspec"
+ content = File.read(path).sub(/raise "RubyGems 2\.0 or newer.*/, "")
+ File.open(path, "w"){|f| f.write(content) }
+ end
+ end
+
before do
@git_name = `git config --global user.name`.chomp
`git config --global user.name "Bundler User"`
@@ -48,7 +57,6 @@ describe "bundle gem" do
bundle "gem newgem --bin"
process_file(bundled_app('newgem', "newgem.gemspec")) do |line|
- next line unless line =~ /TODO/
# Simulate replacing TODOs with real values
case line
when /spec\.metadata\['allowed_push_host'\]/, /spec\.homepage/
@@ -57,6 +65,9 @@ describe "bundle gem" do
line.gsub(/\=.*$/, "= %q{A short summary of my new gem.}")
when /spec\.description/
line.gsub(/\=.*$/, "= %q{A longer description of my new gem.}")
+ # Remove exception that prevents public pushes on older RubyGems versions
+ when /raise "RubyGems 2.0 or newer/
+ line.gsub(/.*/, '') if Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.0")
else
line
end
@@ -112,6 +123,7 @@ describe "bundle gem" do
before do
bundle "gem #{gem_name}"
+ remove_push_guard(gem_name)
# reset gemspec cache for each test because of commit 3d4163a
Bundler.clear_gemspec_cache
end
@@ -125,6 +137,11 @@ describe "bundle gem" do
expect(bundled_app("test_gem/lib/test_gem.rb")).to exist
expect(bundled_app("test_gem/lib/test_gem/version.rb")).to exist
expect(bundled_app("test_gem/.gitignore")).to exist
+
+ expect(bundled_app("test_gem/bin/setup")).to exist
+ expect(bundled_app("test_gem/bin/console")).to exist
+ expect(bundled_app("test_gem/bin/setup")).to be_executable
+ expect(bundled_app("test_gem/bin/console")).to be_executable
end
it "starts with version 0.1.0" do
@@ -145,6 +162,7 @@ describe "bundle gem" do
reset!
in_app_root
bundle "gem #{gem_name}"
+ remove_push_guard(gem_name)
end
it_should_behave_like "git config is absent"
@@ -152,7 +170,7 @@ describe "bundle gem" do
it "sets gemspec metadata['allowed_push_host']", :rubygems => "2.0" do
expect(generated_gem.gemspec.metadata['allowed_push_host']).
- to match("delete to allow pushes to any server")
+ to match(/mygemserver\.com/)
end
it "requires the version file" do
@@ -255,8 +273,8 @@ describe "bundle gem" do
end
it "builds spec skeleton" do
- expect(bundled_app("test_gem/test/test_test_gem.rb")).to exist
- expect(bundled_app("test_gem/test/minitest_helper.rb")).to exist
+ expect(bundled_app("test_gem/test/test_gem_test.rb")).to exist
+ expect(bundled_app("test_gem/test/test_helper.rb")).to exist
end
end
@@ -268,20 +286,20 @@ describe "bundle gem" do
end
it "builds spec skeleton" do
- expect(bundled_app("test_gem/test/test_test_gem.rb")).to exist
- expect(bundled_app("test_gem/test/minitest_helper.rb")).to exist
+ expect(bundled_app("test_gem/test/test_gem_test.rb")).to exist
+ expect(bundled_app("test_gem/test/test_helper.rb")).to exist
end
it "requires 'test-gem'" do
- expect(bundled_app("test_gem/test/minitest_helper.rb").read).to include("require 'test_gem'")
+ expect(bundled_app("test_gem/test/test_helper.rb").read).to include("require 'test_gem'")
end
it "requires 'minitest_helper'" do
- expect(bundled_app("test_gem/test/test_test_gem.rb").read).to include("require 'minitest_helper'")
+ expect(bundled_app("test_gem/test/test_gem_test.rb").read).to include("require 'test_helper'")
end
it "creates a default test which fails" do
- expect(bundled_app("test_gem/test/test_test_gem.rb").read).to include("assert false")
+ expect(bundled_app("test_gem/test/test_gem_test.rb").read).to include("assert false")
end
end
@@ -318,6 +336,7 @@ describe "bundle gem" do
before do
bundle "gem #{gem_name} --mit"
+ remove_push_guard(gem_name)
# reset gemspec cache for each test because of commit 3d4163a
Bundler.clear_gemspec_cache
end
@@ -359,6 +378,7 @@ describe "bundle gem" do
before do
bundle "gem #{gem_name}"
+ remove_push_guard(gem_name)
# reset gemspec cache for each test because of commit 3d4163a
Bundler.clear_gemspec_cache
end
@@ -392,16 +412,12 @@ describe "bundle gem" do
reset!
in_app_root
bundle "gem #{gem_name}"
+ remove_push_guard(gem_name)
end
it_should_behave_like "git config is absent"
end
- it "sets gemspec metadata['allowed_push_host']", :rubygems => "2.0" do
- expect(generated_gem.gemspec.metadata['allowed_push_host']).
- to match("delete to allow pushes to any server")
- end
-
it "requires the version file" do
expect(bundled_app("test-gem/lib/test/gem.rb").read).to match(/require "test\/gem\/version"/)
end
@@ -499,20 +515,20 @@ describe "bundle gem" do
end
it "builds spec skeleton" do
- expect(bundled_app("test-gem/test/test_test/gem.rb")).to exist
- expect(bundled_app("test-gem/test/minitest_helper.rb")).to exist
+ expect(bundled_app("test-gem/test/test/gem_test.rb")).to exist
+ expect(bundled_app("test-gem/test/test_helper.rb")).to exist
end
it "requires 'test/gem'" do
- expect(bundled_app("test-gem/test/minitest_helper.rb").read).to match(/require 'test\/gem'/)
+ expect(bundled_app("test-gem/test/test_helper.rb").read).to match(/require 'test\/gem'/)
end
- it "requires 'minitest_helper'" do
- expect(bundled_app("test-gem/test/test_test/gem.rb").read).to match(/require 'minitest_helper'/)
+ it "requires 'test_helper'" do
+ expect(bundled_app("test-gem/test/test/gem_test.rb").read).to match(/require 'test_helper'/)
end
it "creates a default test which fails" do
- expect(bundled_app("test-gem/test/test_test/gem.rb").read).to match(/assert false/)
+ expect(bundled_app("test-gem/test/test/gem_test.rb").read).to match(/assert false/)
end
it "creates a default rake task to run the test suite" do
@@ -522,6 +538,8 @@ describe "bundle gem" do
Rake::TestTask.new(:test) do |t|
t.libs << "test"
+ t.libs << "lib"
+ t.test_files = FileList['test/**/*_test.rb']
end
task :default => :test
@@ -578,6 +596,44 @@ describe "bundle gem" do
end
end
+ describe "uncommon gem names" do
+ it "can deal with two dashes" do
+ bundle "gem a--a"
+ Bundler.clear_gemspec_cache
+
+ expect(bundled_app("a--a/a--a.gemspec")).to exist
+ end
+ end
+
+ describe "#ensure_safe_gem_name" do
+ before do
+ bundle "gem #{subject}"
+ end
+ after do
+ Bundler.clear_gemspec_cache
+ end
+
+ context "with an existing const name" do
+ subject { "gem" }
+ it { expect(out).to include("Invalid gem name #{subject}") }
+ end
+
+ context "with an existing hyphenated const name" do
+ subject { "gem-specification" }
+ it { expect(out).to include("Invalid gem name #{subject}") }
+ end
+
+ context "starting with an existing const name" do
+ subject { "gem-somenewconstantname" }
+ it { expect(out).not_to include("Invalid gem name #{subject}") }
+ end
+
+ context "ending with an existing const name" do
+ subject { "somenewconstantname-gem" }
+ it { expect(out).not_to include("Invalid gem name #{subject}") }
+ end
+ end
+
context "on first run" do
before do
in_app_root
@@ -591,6 +647,17 @@ describe "bundle gem" do
end
expect(bundled_app("foobar/spec/spec_helper.rb")).to exist
+ rakefile = strip_whitespace <<-RAKEFILE
+ require "bundler/gem_tasks"
+ require "rspec/core/rake_task"
+
+ RSpec::Core::RakeTask.new(:spec)
+
+ task :default => :spec
+ RAKEFILE
+
+ expect(bundled_app("foobar/Rakefile").read).to eq(rakefile)
+ expect(bundled_app("foobar/foobar.gemspec").read).to include('spec.add_development_dependency "rspec"')
end
it "asks about MIT license" do
diff --git a/spec/commands/open_spec.rb b/spec/commands/open_spec.rb
index 099a400a55..71945a85fa 100644
--- a/spec/commands/open_spec.rb
+++ b/spec/commands/open_spec.rb
@@ -10,17 +10,17 @@ describe "bundle open" do
it "opens the gem with BUNDLER_EDITOR as highest priority" do
bundle "open rails", :env => {"EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor"}
- expect(out).to eq("bundler_editor #{default_bundle_path('gems', 'rails-2.3.2')}")
+ expect(out).to include("bundler_editor #{default_bundle_path('gems', 'rails-2.3.2')}")
end
it "opens the gem with VISUAL as 2nd highest priority" do
bundle "open rails", :env => {"EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => ""}
- expect(out).to eq("visual #{default_bundle_path('gems', 'rails-2.3.2')}")
+ expect(out).to include("visual #{default_bundle_path('gems', 'rails-2.3.2')}")
end
it "opens the gem with EDITOR as 3rd highest priority" do
bundle "open rails", :env => {"EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => ""}
- expect(out).to eq("editor #{default_bundle_path('gems', 'rails-2.3.2')}")
+ expect(out).to include("editor #{default_bundle_path('gems', 'rails-2.3.2')}")
end
it "complains if no EDITOR is set" do
@@ -54,7 +54,7 @@ describe "bundle open" do
it "opens the gem with short words" do
bundle "open rec" , :env => {"EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor"}
- expect(out).to eq("bundler_editor #{default_bundle_path('gems', 'activerecord-2.3.2')}")
+ expect(out).to include("bundler_editor #{default_bundle_path('gems', 'activerecord-2.3.2')}")
end
it "select the gem from many match gems" do
diff --git a/spec/commands/outdated_spec.rb b/spec/commands/outdated_spec.rb
index 7ccd383f5f..6bb3a94baf 100644
--- a/spec/commands/outdated_spec.rb
+++ b/spec/commands/outdated_spec.rb
@@ -27,9 +27,9 @@ describe "bundle outdated" do
bundle "outdated"
- expect(out).to include("activesupport (3.0 > 2.3.5) Gemfile specifies \"= 2.3.5\"")
- expect(out).to include("weakling (0.2 > 0.0.3) Gemfile specifies \"~> 0.0.1\"")
- expect(out).to include("foo (1.0")
+ expect(out).to include("activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5)")
+ expect(out).to include("weakling (newest 0.2, installed 0.0.3, requested ~> 0.0.1)")
+ expect(out).to include("foo (newest 1.0")
# Gem names are one per-line, between "*" and their parenthesized version.
gem_list = out.split("\n").map { |g| g[ /\* (.*) \(/, 1] }.compact
@@ -52,6 +52,21 @@ describe "bundle outdated" do
expect(exitstatus).to be_zero if exitstatus
end
+
+ it "adds gem group to dependency output when repo is updated" do
+ install_gemfile <<-G
+ source "file://#{gem_repo2}"
+
+ group :development, :test do
+ gem 'activesupport', '2.3.5'
+ end
+ G
+
+ update_repo2 { build_gem "activesupport", "3.0" }
+
+ bundle "outdated --verbose"
+ expect(out).to include("activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5) in groups \"development, test\"")
+ end
end
describe "with --local option" do
@@ -71,8 +86,8 @@ describe "bundle outdated" do
end
bundle "outdated foo"
- expect(out).not_to include("activesupport (3.0 > 2.3.5)")
- expect(out).to include("foo (1.0")
+ expect(out).not_to include("activesupport (newest")
+ expect(out).to include("foo (newest 1.0")
end
end
@@ -95,7 +110,7 @@ describe "bundle outdated" do
end
bundle "outdated --pre"
- expect(out).to include("activesupport (3.0.0.beta > 2.3.5) Gemfile specifies \"= 2.3.5\"")
+ expect(out).to include("activesupport (newest 3.0.0.beta, installed 2.3.5, requested = 2.3.5)")
end
end
@@ -112,7 +127,7 @@ describe "bundle outdated" do
G
bundle "outdated"
- expect(out).to include("activesupport (3.0.0.beta.2 > 3.0.0.beta.1) Gemfile specifies \"= 3.0.0.beta.1\"")
+ expect(out).to include("(newest 3.0.0.beta.2, installed 3.0.0.beta.1, requested = 3.0.0.beta.1)")
end
end
end
@@ -126,8 +141,8 @@ describe "bundle outdated" do
bundle "outdated --strict"
- expect(out).to_not include("activesupport (3.0 > 2.3.5) Gemfile specifies \"= 2.3.5\"")
- expect(out).to include("weakling (0.0.5 > 0.0.3) Gemfile specifies \"~> 0.0.1\"")
+ expect(out).to_not include("activesupport (newest")
+ expect(out).to include("(newest 0.0.5, installed 0.0.3, requested ~> 0.0.1)")
end
it "only reports gem dependencies when they can actually be updated" do
@@ -138,7 +153,7 @@ describe "bundle outdated" do
bundle "outdated --strict"
- expect(out).to_not include("rack (1.2 > 0.9.1)")
+ expect(out).to_not include("rack (1.2")
end
end
diff --git a/spec/commands/package_spec.rb b/spec/commands/package_spec.rb
index f72868cb2a..bc0ebdfc21 100644
--- a/spec/commands/package_spec.rb
+++ b/spec/commands/package_spec.rb
@@ -100,7 +100,7 @@ describe "bundle install with gem sources" do
end
bundle :install
- expect(err).to be_empty
+ expect(err).to lack_errors
should_be_installed "rack 1.0"
end
diff --git a/spec/commands/show_spec.rb b/spec/commands/show_spec.rb
index 3e5f9f8020..f38da20222 100644
--- a/spec/commands/show_spec.rb
+++ b/spec/commands/show_spec.rb
@@ -121,7 +121,7 @@ describe "bundle show" do
it "does not output git errors" do
bundle :show
- expect(err).to be_empty
+ expect(err).to lack_errors
end
end
diff --git a/spec/deprecation_spec.rb b/spec/deprecation_spec.rb
new file mode 100644
index 0000000000..fce0702653
--- /dev/null
+++ b/spec/deprecation_spec.rb
@@ -0,0 +1,119 @@
+require "spec_helper"
+
+describe "Bundler version 1.99" do
+ context "when bundle is run" do
+ it "should print a single deprecation warning" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"
+ G
+
+ expect(err).to eq("DEPRECATION: Gemfile and Gemfile.lock are " \
+ "deprecated and will be replaced with gems.rb and gems.locked in " \
+ "Bundler 2.0.")
+ end
+
+ it "should not warn about gems.rb" do
+ create_file "gems.rb", <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"
+ G
+
+ bundle :install
+ expect(err).to lack_errors
+ end
+ end
+
+ context "when Bundler.setup is run in a ruby script" do
+ it "should print a single deprecation warning" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack", :group => :test
+ G
+
+ ruby <<-RUBY
+ require 'rubygems'
+ require 'bundler'
+ require 'bundler/vendored_thor'
+
+ Bundler.ui = Bundler::UI::Shell.new
+ Bundler.setup
+ Bundler.setup
+ RUBY
+
+ expect(err).to eq("DEPRECATION: Gemfile and Gemfile.lock are " \
+ "deprecated and will be replaced with gems.rb and gems.locked in " \
+ "Bundler 2.0.")
+ end
+ end
+
+ context "when `bundler/deployment` is required in a ruby script" do
+ it "should print a capistrano deprecation warning" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack", :group => :test
+ G
+
+ ruby(<<-RUBY, { :expect_err => true })
+ require 'bundler/deployment'
+ RUBY
+
+ expect(err).to eq("DEPRECATION: Bundler no longer integrates " \
+ "with Capistrano, but Capistrano provides " \
+ "its own integration with Bundler via the " \
+ "capistrano-bundler gem. Use it instead.")
+ end
+ end
+
+ describe Bundler::Dsl do
+ before do
+ @rubygems = double("rubygems")
+ allow(Bundler::Source::Rubygems).to receive(:new){ @rubygems }
+ end
+
+ context "with github gems" do
+ it "warns about the https change" do
+ allow(Bundler.ui).to receive(:deprecate)
+ msg = "The :github option uses the git: protocol, which is not secure. " \
+ "Bundler 2.0 will use the https: protcol, which is secure. Enable this change now by " \
+ "running `bundle config github.https true`."
+ expect(Bundler.ui).to receive(:deprecate).with(msg)
+ subject.gem("sparks", :github => "indirect/sparks")
+ end
+
+ it "upgrades to https on request" do
+ Bundler.settings["github.https"] = true
+ subject.gem("sparks", :github => "indirect/sparks")
+ github_uri = "https://github.com/indirect/sparks.git"
+ expect(subject.dependencies.first.source.uri).to eq(github_uri)
+ end
+ end
+
+ context "with bitbucket gems" do
+ it "warns about removal" do
+ allow(Bundler.ui).to receive(:deprecate)
+ msg = "The :bitbucket git source is deprecated, and will be removed " \
+ "in Bundler 2.0. Add this code to your Gemfile to ensure it " \
+ "continues to work:\n git_source(:bitbucket) do |repo_name|\n " \
+ " https://\#{user_name}@bitbucket.org/\#{user_name}/\#{repo_name}" \
+ ".git\n end"
+ expect(Bundler.ui).to receive(:deprecate).with(msg, true)
+ subject.gem("not-really-a-gem", :bitbucket => "mcorp/flatlab-rails")
+ end
+ end
+
+ context "with gist gems" do
+ it "warns about removal" do
+ allow(Bundler.ui).to receive(:deprecate)
+ msg = "The :gist git source is deprecated, and will be removed " \
+ "in Bundler 2.0. Add this code to your Gemfile to ensure it " \
+ "continues to work:\n git_source(:gist) do |repo_name|\n " \
+ " https://gist.github.com/\#{repo_name}.git\n" \
+ " end"
+ expect(Bundler.ui).to receive(:deprecate).with(msg, true)
+ subject.gem("not-really-a-gem", :gist => "1234")
+ end
+ end
+ end
+
+end
diff --git a/spec/install/bundler_spec.rb b/spec/install/bundler_spec.rb
index 309f8c4e88..53e4768c18 100644
--- a/spec/install/bundler_spec.rb
+++ b/spec/install/bundler_spec.rb
@@ -102,7 +102,7 @@ describe "bundle install" do
rails_fail (>= 0) ruby depends on
activesupport (= 1.2.3) ruby
E
- expect(err).to eq(nice_error)
+ expect(err).to include(nice_error)
end
it "causes a conflict if a child dependency conflicts with the Gemfile" do
@@ -120,7 +120,7 @@ describe "bundle install" do
activesupport (= 2.3.5) ruby
E
- expect(err).to eq(nice_error)
+ expect(err).to include(nice_error)
end
it "can install dependencies with newer bundler version" do
@@ -133,7 +133,7 @@ describe "bundle install" do
#simulate_new_machine
bundle "check"
- expect(out).to eq("The Gemfile's dependencies are satisfied")
+ expect(out).to include("The Gemfile's dependencies are satisfied")
end
end
diff --git a/spec/install/force_spec.rb b/spec/install/force_spec.rb
new file mode 100644
index 0000000000..269390994a
--- /dev/null
+++ b/spec/install/force_spec.rb
@@ -0,0 +1,20 @@
+require "spec_helper"
+
+describe "bundle install" do
+ describe "with --force" do
+ before :each do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"
+ G
+
+ bundle "install"
+ end
+
+ it "re-installs installed gems" do
+ bundle "install --force"
+ expect(out).to include "Installing rack 1.0.0"
+ should_be_installed "rack 1.0.0"
+ end
+ end
+end
diff --git a/spec/install/gemfile/git_spec.rb b/spec/install/gemfile/git_spec.rb
index ccaee588bd..107f44b08b 100644
--- a/spec/install/gemfile/git_spec.rb
+++ b/spec/install/gemfile/git_spec.rb
@@ -162,7 +162,7 @@ describe "bundle install with git sources" do
gem "foo"
end
G
- expect(err).to eq("")
+ expect(err).to lack_errors
run <<-RUBY
require 'foo'
@@ -782,7 +782,7 @@ describe "bundle install with git sources" do
bundle :install, :expect_err => true,
:requires => [lib_path('install_hooks.rb')]
- expect(err).to eq("Ran pre-install hook: foo-1.0")
+ expect(err).to eq_err("Ran pre-install hook: foo-1.0")
end
it "runs post-install hooks" do
@@ -802,7 +802,7 @@ describe "bundle install with git sources" do
bundle :install, :expect_err => true,
:requires => [lib_path('install_hooks.rb')]
- expect(err).to eq("Ran post-install hook: foo-1.0")
+ expect(err).to eq_err("Ran post-install hook: foo-1.0")
end
it "complains if the install hook fails" do
diff --git a/spec/install/gemfile/path_spec.rb b/spec/install/gemfile/path_spec.rb
index 7dd651f70d..57c7e9d366 100644
--- a/spec/install/gemfile/path_spec.rb
+++ b/spec/install/gemfile/path_spec.rb
@@ -262,7 +262,7 @@ describe "bundle install with explicit source paths" do
install_gemfile <<-G
gem 'foo', '1.0', :path => "#{lib_path('foo-1.0')}"
G
- expect(err).to eq("")
+ expect(err).to lack_errors
end
it "removes the .gem file after installing" do
@@ -472,7 +472,7 @@ describe "bundle install with explicit source paths" do
bundle :install, :expect_err => true,
:requires => [lib_path('install_hooks.rb')]
- expect(err).to eq("Ran pre-install hook: foo-1.0")
+ expect(err).to eq_err("Ran pre-install hook: foo-1.0")
end
it "runs post-install hooks" do
@@ -492,7 +492,7 @@ describe "bundle install with explicit source paths" do
bundle :install, :expect_err => true,
:requires => [lib_path('install_hooks.rb')]
- expect(err).to eq("Ran post-install hook: foo-1.0")
+ expect(err).to eq_err("Ran post-install hook: foo-1.0")
end
it "complains if the install hook fails" do
diff --git a/spec/install/gems/flex_spec.rb b/spec/install/gems/flex_spec.rb
index ec565ca790..50638784dd 100644
--- a/spec/install/gems/flex_spec.rb
+++ b/spec/install/gems/flex_spec.rb
@@ -265,6 +265,9 @@ describe "bundle flex_install" do
DEPENDENCIES
rack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
L
end
end
diff --git a/spec/install/gems/groups_spec.rb b/spec/install/gems/groups_spec.rb
index 23af4aee65..c6bbebb435 100644
--- a/spec/install/gems/groups_spec.rb
+++ b/spec/install/gems/groups_spec.rb
@@ -26,7 +26,7 @@ describe "bundle install with groups" do
puts ACTIVESUPPORT
R
- expect(err).to eq("ZOMG LOAD ERROR")
+ expect(err).to eq_err("ZOMG LOAD ERROR")
end
it "installs gems with inline :groups into those groups" do
@@ -37,7 +37,7 @@ describe "bundle install with groups" do
puts THIN
R
- expect(err).to eq("ZOMG LOAD ERROR")
+ expect(err).to eq_err("ZOMG LOAD ERROR")
end
it "sets up everything if Bundler.setup is used with no groups" do
@@ -58,7 +58,7 @@ describe "bundle install with groups" do
puts THIN
RUBY
- expect(err).to eq("ZOMG LOAD ERROR")
+ expect(err).to eq_err("ZOMG LOAD ERROR")
end
it "sets up old groups when they have previously been removed" do
@@ -80,6 +80,9 @@ describe "bundle install with groups" do
group :emo do
gem "activesupport", "2.3.5"
end
+ group :debugging, :optional => true do
+ gem "thin"
+ end
G
end
@@ -159,6 +162,69 @@ describe "bundle install with groups" do
bundle :install
should_not_be_installed "activesupport 2.3.5"
end
+
+ it "does not install gems from the optional group" do
+ bundle :install
+ should_not_be_installed "thin 1.0"
+ end
+
+ it "does install gems from the optional group when requested" do
+ bundle :install, :with => "debugging"
+ should_be_installed "thin 1.0"
+ end
+
+ it "does install gems from the previously requested group" do
+ bundle :install, :with => "debugging"
+ should_be_installed "thin 1.0"
+ bundle :install
+ should_be_installed "thin 1.0"
+ end
+
+ it "does install gems from the optional groups requested with BUNDLE_WITH" do
+ ENV["BUNDLE_WITH"] = "debugging"
+ bundle :install
+ should_be_installed "thin 1.0"
+ ENV["BUNDLE_WITH"] = nil
+ end
+
+ it "clears with when passed an empty list" do
+ bundle :install, :with => "debugging"
+ bundle 'install --with ""'
+ should_not_be_installed "thin 1.0"
+ end
+
+ it "does remove groups from without when passed at with" do
+ bundle :install, :without => "emo"
+ bundle :install, :with => "emo"
+ should_be_installed "activesupport 2.3.5"
+ end
+
+ it "does remove groups from with when passed at without" do
+ bundle :install, :with => "debugging"
+ bundle :install, :without => "debugging"
+ should_not_be_installed "thin 1.0"
+ end
+
+ it "errors out when passing a group to with and without" do
+ bundle :install, :with => "emo debugging", :without => "emo"
+ expect(out).to include("The offending groups are: emo")
+ end
+
+ it "can add and remove a group at the same time" do
+ bundle :install, :with => "debugging", :without => "emo"
+ should_be_installed "thin 1.0"
+ should_not_be_installed "activesupport 2.3.5"
+ end
+
+ it "does have no effect when listing a not optional group in with" do
+ bundle :install, :with => "emo"
+ should_be_installed "activesupport 2.3.5"
+ end
+
+ it "does have no effect when listing an optional group in without" do
+ bundle :install, :without => "debugging"
+ should_not_be_installed "thin 1.0"
+ end
end
describe "with gems assigned to multiple groups" do
@@ -301,7 +367,7 @@ describe "bundle install with groups" do
it "does not hit the remote a second time" do
FileUtils.rm_rf gem_repo2
bundle "install --without rack"
- expect(err).to be_empty
+ expect(err).to lack_errors
end
end
diff --git a/spec/install/gems/install_if.rb b/spec/install/gems/install_if.rb
new file mode 100644
index 0000000000..79e6dd87bd
--- /dev/null
+++ b/spec/install/gems/install_if.rb
@@ -0,0 +1,38 @@
+require "spec_helper"
+
+describe "bundle install with install_if conditionals" do
+ it "follows the install_if DSL" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"
+ install_if(lambda { true }) do
+ gem "activesupport", "2.3.5"
+ end
+ gem "thin", :install_if => false
+ G
+
+ should_be_installed("rack 1.0", "activesupport 2.3.5")
+ should_not_be_installed("thin")
+
+ lockfile_should_be <<-L
+ GEM
+ remote: file:#{gem_repo1}/
+ specs:
+ activesupport (2.3.5)
+ rack (1.0.0)
+ thin (1.0)
+ rack
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ activesupport (= 2.3.5)
+ rack
+ thin
+
+ BUNDLED WITH
+ 1.9.4
+ L
+ end
+end
diff --git a/spec/install/gems/post_install_spec.rb b/spec/install/gems/post_install_spec.rb
index 69841fea44..76a3a6ca0d 100644
--- a/spec/install/gems/post_install_spec.rb
+++ b/spec/install/gems/post_install_spec.rb
@@ -1,121 +1,150 @@
require 'spec_helper'
-describe "bundle install with gem sources" do
- describe "when gems include post install messages" do
- it "should display the post-install messages after installing" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'rack'
- gem 'thin'
- gem 'rack-obama'
- G
-
- bundle :install
- expect(out).to include("Post-install message from rack:")
- expect(out).to include("Rack's post install message")
- expect(out).to include("Post-install message from thin:")
- expect(out).to include("Thin's post install message")
- expect(out).to include("Post-install message from rack-obama:")
- expect(out).to include("Rack-obama's post install message")
+describe "bundle install" do
+ context "with gem sources" do
+ context "when gems include post install messages" do
+ it "should display the post-install messages after installing" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem 'rack'
+ gem 'thin'
+ gem 'rack-obama'
+ G
+
+ bundle :install
+ expect(out).to include("Post-install message from rack:")
+ expect(out).to include("Rack's post install message")
+ expect(out).to include("Post-install message from thin:")
+ expect(out).to include("Thin's post install message")
+ expect(out).to include("Post-install message from rack-obama:")
+ expect(out).to include("Rack-obama's post install message")
+ end
end
- end
- describe "when gems do not include post install messages" do
- it "should not display any post-install messages" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem "activesupport"
- G
+ context "when gems do not include post install messages" do
+ it "should not display any post-install messages" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "activesupport"
+ G
- bundle :install
- expect(out).not_to include("Post-install message")
+ bundle :install
+ expect(out).not_to include("Post-install message")
+ end
end
- end
- describe "when a dependecy includes a post install message" do
- it "should display the post install message" do
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'rack_middleware'
- G
+ context "when a dependecy includes a post install message" do
+ it "should display the post install message" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem 'rack_middleware'
+ G
- bundle :install
- expect(out).to include("Post-install message from rack:")
- expect(out).to include("Rack's post install message")
+ bundle :install
+ expect(out).to include("Post-install message from rack:")
+ expect(out).to include("Rack's post install message")
+ end
end
end
-end
-describe "bundle install with git sources" do
- describe "when gems include post install messages" do
- it "should display the post-install messages after installing" do
- build_git "foo" do |s|
- s.post_install_message = "Foo's post install message"
+ context "with git sources" do
+ context "when gems include post install messages" do
+ it "should display the post-install messages after installing" do
+ build_git "foo" do |s|
+ s.post_install_message = "Foo's post install message"
+ end
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem 'foo', :git => '#{lib_path("foo-1.0")}'
+ G
+
+ bundle :install
+ expect(out).to include("Post-install message from foo:")
+ expect(out).to include("Foo's post install message")
end
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'foo', :git => '#{lib_path("foo-1.0")}'
- G
-
- bundle :install
- expect(out).to include("Post-install message from foo:")
- expect(out).to include("Foo's post install message")
- end
- it "should display the post-install messages if repo is updated" do
- build_git "foo" do |s|
- s.post_install_message = "Foo's post install message"
+ it "should display the post-install messages if repo is updated" do
+ build_git "foo" do |s|
+ s.post_install_message = "Foo's post install message"
+ end
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem 'foo', :git => '#{lib_path("foo-1.0")}'
+ G
+ bundle :install
+
+ build_git "foo", "1.1" do |s|
+ s.post_install_message = "Foo's 1.1 post install message"
+ end
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem 'foo', :git => '#{lib_path("foo-1.1")}'
+ G
+ bundle :install
+
+ expect(out).to include("Post-install message from foo:")
+ expect(out).to include("Foo's 1.1 post install message")
end
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'foo', :git => '#{lib_path("foo-1.0")}'
- G
- bundle :install
- build_git "foo", "1.1" do |s|
- s.post_install_message = "Foo's 1.1 post install message"
+ it "should not display the post-install messages if repo is not updated" do
+ build_git "foo" do |s|
+ s.post_install_message = "Foo's post install message"
+ end
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem 'foo', :git => '#{lib_path("foo-1.0")}'
+ G
+
+ bundle :install
+ expect(out).to include("Post-install message from foo:")
+ expect(out).to include("Foo's post install message")
+
+ bundle :install
+ expect(out).not_to include("Post-install message")
end
- gemfile <<-G
- source "file://#{gem_repo1}"
- gem 'foo', :git => '#{lib_path("foo-1.1")}'
- G
- bundle :install
-
- expect(out).to include("Post-install message from foo:")
- expect(out).to include("Foo's 1.1 post install message")
end
- it "should not display the post-install messages if repo is not updated" do
- build_git "foo" do |s|
- s.post_install_message = "Foo's post install message"
+ context "when gems do not include post install messages" do
+ it "should not display any post-install messages" do
+ build_git "foo" do |s|
+ s.post_install_message = nil
+ end
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem 'foo', :git => '#{lib_path("foo-1.0")}'
+ G
+
+ bundle :install
+ expect(out).not_to include("Post-install message")
end
+ end
+ end
+
+ context "when ignore post-install messages for gem is set" do
+ it "doesn't display any post-install messages" do
gemfile <<-G
source "file://#{gem_repo1}"
- gem 'foo', :git => '#{lib_path("foo-1.0")}'
+ gem "rack"
G
- bundle :install
- expect(out).to include("Post-install message from foo:")
- expect(out).to include("Foo's post install message")
+ bundle "config ignore_messages.rack true"
bundle :install
expect(out).not_to include("Post-install message")
end
end
- describe "when gems do not include post install messages" do
- it "should not display any post-install messages" do
- build_git "foo" do |s|
- s.post_install_message = nil
- end
+ context "when ignore post-install messages for all gems" do
+ it "doesn't display any post-install messages" do
gemfile <<-G
source "file://#{gem_repo1}"
- gem 'foo', :git => '#{lib_path("foo-1.0")}'
+ gem "rack"
G
+ bundle "config ignore_messages true"
+
bundle :install
expect(out).not_to include("Post-install message")
end
end
-
end
diff --git a/spec/install/gems/sources_spec.rb b/spec/install/gems/sources_spec.rb
index a268436248..78a1c0af2b 100644
--- a/spec/install/gems/sources_spec.rb
+++ b/spec/install/gems/sources_spec.rb
@@ -30,7 +30,7 @@ describe "bundle install with gems on multiple sources" do
it "warns about ambiguous gems, but installs anyway, prioritizing sources last to first" do
bundle :install
- expect(out).to include("Warning: this Gemfile contains multiple primary sources.")
+ expect(err).to include("DEPRECATION: Your Gemfile contains multiple primary sources.")
expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
expect(err).to include("Installed from: file:#{gem_repo1}")
should_be_installed("rack-obama 1.0.0", "rack 1.0.0")
@@ -59,7 +59,7 @@ describe "bundle install with gems on multiple sources" do
it "warns about ambiguous gems, but installs anyway" do
bundle :install
- expect(out).to include("Warning: this Gemfile contains multiple primary sources.")
+ expect(err).to include("DEPRECATION: Your Gemfile contains multiple primary sources.")
expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
expect(err).to include("Installed from: file:#{gem_repo1}")
should_be_installed("rack-obama 1.0.0", "rack 1.0.0")
@@ -223,12 +223,47 @@ describe "bundle install with gems on multiple sources" do
it "installs from the other source and warns about ambiguous gems" do
bundle :install
- expect(out).to include("Warning: this Gemfile contains multiple primary sources.")
+
+ expect(err).to include("DEPRECATION: Your Gemfile contains multiple primary sources.")
expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
expect(err).to include("Installed from: file:#{gem_repo2}")
should_be_installed("depends_on_rack 1.0.1", "rack 1.0.0")
end
end
+
+ context "and only the dependency is pinned" do
+ before do
+ # need this to be broken to check for correct source ordering
+ build_repo gem_repo2 do
+ build_gem "rack", "1.0.0" do |s|
+ s.write "lib/rack.rb", "RACK = 'FAIL'"
+ end
+ end
+
+ gemfile <<-G
+ source "file://#{gem_repo3}" # contains depends_on_rack
+ source "file://#{gem_repo2}" # contains broken rack
+
+ gem "depends_on_rack" # installed from gem_repo3
+ gem "rack", :source => "file://#{gem_repo1}"
+ G
+ end
+
+ it "installs the dependency from the pinned source without warning" do
+ bundle :install
+
+ expect(out).not_to include("Warning: the gem 'rack' was found in multiple sources.")
+ should_be_installed("depends_on_rack 1.0.1", "rack 1.0.0")
+
+ # In https://github.com/bundler/bundler/issues/3585 this failed
+ # when there is already a lock file, and the gems are missing, so try again
+ system_gems []
+ bundle :install
+
+ expect(out).not_to include("Warning: the gem 'rack' was found in multiple sources.")
+ should_be_installed("depends_on_rack 1.0.1", "rack 1.0.0")
+ end
+ end
end
end
@@ -319,4 +354,64 @@ describe "bundle install with gems on multiple sources" do
should_be_installed("rack 1.0.0")
end
end
+
+ context "when a single source contains multiple locked gems" do
+ before do
+ # 1. With these gems,
+ build_repo4 do
+ build_gem "foo", "0.1"
+ build_gem "bar", "0.1"
+ end
+
+ # 2. Installing this gemfile will produce...
+ gemfile <<-G
+ source 'file://#{gem_repo1}'
+ gem 'rack'
+ gem 'foo', '~> 0.1', :source => 'file://#{gem_repo4}'
+ gem 'bar', '~> 0.1', :source => 'file://#{gem_repo4}'
+ G
+
+ # 3. this lockfile.
+ lockfile <<-L
+ GEM
+ remote: file:/Users/andre/src/bundler/bundler/tmp/gems/remote1/
+ remote: file:/Users/andre/src/bundler/bundler/tmp/gems/remote4/
+ specs:
+ bar (0.1)
+ foo (0.1)
+ rack (1.0.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ bar (~> 0.1)!
+ foo (~> 0.1)!
+ rack
+ L
+
+ bundle "install --path ../gems/system"
+
+ # 4. Then we add some new versions...
+ update_repo4 do
+ build_gem "foo", "0.2"
+ build_gem "bar", "0.3"
+ end
+ end
+
+ it "allows them to be unlocked separately" do
+ # 5. and install this gemfile, updating only foo.
+ install_gemfile <<-G
+ source 'file://#{gem_repo1}'
+ gem 'rack'
+ gem 'foo', '~> 0.2', :source => 'file://#{gem_repo4}'
+ gem 'bar', '~> 0.1', :source => 'file://#{gem_repo4}'
+ G
+
+ # 6. Which should update foo to 0.2, but not the (locked) bar 0.1
+ should_be_installed("foo 0.2")
+ should_be_installed("bar 0.1")
+ end
+ end
+
end
diff --git a/spec/install/gems/sudo_spec.rb b/spec/install/gems/sudo_spec.rb
index 366432188b..3e833960e2 100644
--- a/spec/install/gems/sudo_spec.rb
+++ b/spec/install/gems/sudo_spec.rb
@@ -96,8 +96,11 @@ describe "when using sudo", :sudo => true do
end
describe "and BUNDLE_PATH is not writable" do
- it "installs" do
+ before do
sudo "chmod ugo-w #{default_bundle_path}"
+ end
+
+ it "installs" do
install_gemfile <<-G
source "file://#{gem_repo1}"
gem "rack", '1.0'
@@ -106,6 +109,21 @@ describe "when using sudo", :sudo => true do
expect(default_bundle_path("gems/rack-1.0.0")).to exist
should_be_installed "rack 1.0"
end
+
+ it "cleans up the tmpdirs generated" do
+ require 'tmpdir'
+ Dir.glob("#{Dir.tmpdir}/bundler*").each do |tmpdir|
+ FileUtils.remove_entry_secure(tmpdir)
+ end
+
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"
+ G
+ tmpdirs = Dir.glob("#{Dir.tmpdir}/bundler*")
+
+ expect(tmpdirs).to be_empty
+ end
end
describe "and GEM_HOME is not writable" do
diff --git a/spec/install/gemspecs_spec.rb b/spec/install/gemspecs_spec.rb
index 201ba9564a..47ef073f2c 100644
--- a/spec/install/gemspecs_spec.rb
+++ b/spec/install/gemspecs_spec.rb
@@ -15,7 +15,7 @@ describe "bundle install" do
gem "yaml_spec"
G
bundle :install
- expect(err).to be_empty
+ expect(err).to lack_errors
end
it "still installs correctly when using path" do
@@ -24,7 +24,7 @@ describe "bundle install" do
install_gemfile <<-G
gem 'yaml_spec', :path => "#{lib_path('yaml_spec-1.0')}"
G
- expect(err).to eq("")
+ expect(err).to lack_errors
end
end
diff --git a/spec/install/parallel/spec_installation_spec.rb b/spec/install/parallel/spec_installation_spec.rb
new file mode 100644
index 0000000000..97288fe02f
--- /dev/null
+++ b/spec/install/parallel/spec_installation_spec.rb
@@ -0,0 +1,37 @@
+require 'spec_helper'
+require 'bundler/installer/parallel_installer'
+
+describe ParallelInstaller::SpecInstallation do
+ describe "#ready_to_enqueue?" do
+
+ let!(:dep) do
+ a_spec = Object.new
+ def a_spec.name
+ "I like tests"
+ end
+ a_spec
+ end
+
+ context "when in enqueued state" do
+ it "is falsey" do
+ spec = ParallelInstaller::SpecInstallation.new(dep)
+ spec.state = :enqueued
+ expect(spec.ready_to_enqueue?).to be_falsey
+ end
+ end
+
+ context "when in installed state" do
+ it "returns falsey" do
+ spec = ParallelInstaller::SpecInstallation.new(dep)
+ spec.state = :installed
+ expect(spec.ready_to_enqueue?).to be_falsey
+ end
+ end
+
+ it "returns truthy" do
+ spec = ParallelInstaller::SpecInstallation.new(dep)
+ expect(spec.ready_to_enqueue?).to be_truthy
+ end
+ end
+
+end
diff --git a/spec/install/post_bundle_message_spec.rb b/spec/install/post_bundle_message_spec.rb
index 78133d9283..5bdf165062 100644
--- a/spec/install/post_bundle_message_spec.rb
+++ b/spec/install/post_bundle_message_spec.rb
@@ -81,6 +81,22 @@ describe "post bundle message" do
expect(out).to include(bundle_complete_message)
end
end
+
+ describe "with misspelled or non-existent gem name" do
+ before :each do
+ gemfile <<-G
+ source 'https://rubygems.org/'
+ gem "rails"
+ gem "misspelled-gem-name", :group => :development
+ G
+ end
+
+ it "should report a helpufl error message" do
+ bundle :install
+ expect(out).to include("Fetching gem metadata from https://rubygems.org/")
+ expect(out).to include("Could not find gem 'misspelled-gem-name (>= 0) ruby' in any of the gem sources listed in your Gemfile or available on this machine.")
+ end
+ end
end
describe "for second bundle install run" do
diff --git a/spec/lock/lockfile_spec.rb b/spec/lock/lockfile_spec.rb
index 4ae6baac44..618dafc69e 100644
--- a/spec/lock/lockfile_spec.rb
+++ b/spec/lock/lockfile_spec.rb
@@ -4,12 +4,255 @@ describe "the lockfile format" do
include Bundler::GemHelpers
it "generates a simple lockfile for a single source, gem" do
+
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ gem "rack"
+ G
+
+ lockfile_should_be <<-G
+ GEM
+ remote: file:#{gem_repo1}/
+ specs:
+ rack (1.0.0)
+
+ PLATFORMS
+ #{generic(Gem::Platform.local)}
+
+ DEPENDENCIES
+ rack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+ end
+
+ it "updates the lockfile's bundler version if current ver. is newer" do
+
+ # TODO: verno below should be one less than prev ver (unless at min)
+
+ lockfile <<-L
+ GIT
+ remote: git://github.com/nex3/haml.git
+ revision: 8a2271f
+ specs:
+
+ GEM
+ remote: file://#{gem_repo1}/
+ specs:
+ rack (1.0.0)
+
+ PLATFORMS
+ #{generic(Gem::Platform.local)}
+
+ DEPENDENCIES
+ omg!
+ rack
+
+ BUNDLED WITH
+ 1.8.2
+ L
+
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ gem "rack"
+ G
+
+ lockfile_should_be <<-G
+ GEM
+ remote: file:#{gem_repo1}/
+ specs:
+ rack (1.0.0)
+
+ PLATFORMS
+ #{generic(Gem::Platform.local)}
+
+ DEPENDENCIES
+ rack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+ end
+
+ it "updates the lockfile's bundler version if not present" do
+
+ lockfile <<-L
+ GEM
+ remote: file:#{gem_repo1}/
+ specs:
+ rack (1.0.0)
+
+ PLATFORMS
+ #{generic(Gem::Platform.local)}
+
+ DEPENDENCIES
+ rack
+ L
+
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ gem "rack"
+ G
+
+ lockfile_should_be <<-G
+ GEM
+ remote: file:#{gem_repo1}/
+ specs:
+ rack (1.0.0)
+
+ PLATFORMS
+ #{generic(Gem::Platform.local)}
+
+ DEPENDENCIES
+ rack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+ end
+
+ it "outputs a warning if the current is older than lockfile's bundler version" do
+ lockfile <<-L
+ GEM
+ remote: file:#{gem_repo1}/
+ specs:
+ rack (1.0.0)
+
+ PLATFORMS
+ #{generic(Gem::Platform.local)}
+
+ DEPENDENCIES
+ rack
+
+ BUNDLED WITH
+ 9999999.1.0
+ L
+
+ simulate_bundler_version "9999999.0.0" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ gem "rack"
+ G
+ end
+
+ expect(out).to include("Warning: the running version of Bundler is " \
+ "older than the version that created the lockfile")
+
+ lockfile_should_be <<-G
+ GEM
+ remote: file:#{gem_repo1}/
+ specs:
+ rack (1.0.0)
+
+ PLATFORMS
+ #{generic(Gem::Platform.local)}
+
+ DEPENDENCIES
+ rack
+
+ BUNDLED WITH
+ 9999999.1.0
+ G
+ end
+
+ it "errors if the current is a major version older than lockfile's bundler version" do
+ lockfile <<-L
+ GEM
+ remote: file:#{gem_repo1}/
+ specs:
+ rack (1.0.0)
+
+ PLATFORMS
+ #{generic(Gem::Platform.local)}
+
+ DEPENDENCIES
+ rack
+
+ BUNDLED WITH
+ 9999999.0.0
+ L
+
install_gemfile <<-G
source "file://#{gem_repo1}"
gem "rack"
G
+ expect(exitstatus > 0) if exitstatus
+ expect(out).to include("You must use Bundler 9999999 or greater with this lockfile.")
+ end
+
+ it "shows a friendly error when running with a new bundler 2 lockfile" do
+ lockfile <<-L
+ GEM
+ remote: https://rails-assets.org/
+ specs:
+ rails-assets-bootstrap (3.3.4)
+ rails-assets-jquery (>= 1.9.1)
+ rails-assets-jquery (2.1.4)
+
+ GEM
+ remote: https://rubygems.org/
+ specs:
+ rake (10.4.2)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ rails-assets-bootstrap!
+ rake
+
+ BUNDLED WITH
+ 9999999.0.0
+ L
+
+ install_gemfile <<-G
+ source 'https://rubygems.org'
+ gem 'rake'
+
+ source 'https://rails-assets.org' do
+ gem 'rails-assets-bootstrap'
+ end
+ G
+
+ expect(exitstatus > 0) if exitstatus
+ expect(out).to include("You must use Bundler 9999999 or greater with this lockfile.")
+ end
+
+ it "warns when updating bundler major version" do
+ lockfile <<-L
+ GEM
+ remote: file:#{gem_repo1}/
+ specs:
+ rack (1.0.0)
+
+ PLATFORMS
+ #{generic(Gem::Platform.local)}
+
+ DEPENDENCIES
+ rack
+
+ BUNDLED WITH
+ 1.10.0
+ L
+
+ simulate_bundler_version "9999999.0.0" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ gem "rack"
+ G
+ end
+
+ expect(out).to include("Warning: the lockfile is being updated to Bundler " \
+ "9999999, after which you will be unable to return to Bundler 1.")
+
lockfile_should_be <<-G
GEM
remote: file:#{gem_repo1}/
@@ -21,6 +264,9 @@ describe "the lockfile format" do
DEPENDENCIES
rack
+
+ BUNDLED WITH
+ 9999999.0.0
G
end
@@ -44,6 +290,9 @@ describe "the lockfile format" do
DEPENDENCIES
rack-obama
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -67,6 +316,9 @@ describe "the lockfile format" do
DEPENDENCIES
rack-obama (>= 1.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -94,6 +346,9 @@ describe "the lockfile format" do
DEPENDENCIES
rack-obama (>= 1.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -116,6 +371,9 @@ describe "the lockfile format" do
DEPENDENCIES
net-sftp
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
should_be_installed "net-sftp 1.1.1", "net-ssh 1.0.0"
@@ -143,6 +401,9 @@ describe "the lockfile format" do
DEPENDENCIES
foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -176,6 +437,9 @@ describe "the lockfile format" do
DEPENDENCIES
omg!
rack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
L
bundle "install"
@@ -206,6 +470,9 @@ describe "the lockfile format" do
DEPENDENCIES
foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -233,6 +500,9 @@ describe "the lockfile format" do
DEPENDENCIES
foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -260,6 +530,9 @@ describe "the lockfile format" do
DEPENDENCIES
foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -284,6 +557,9 @@ describe "the lockfile format" do
DEPENDENCIES
foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -323,6 +599,9 @@ describe "the lockfile format" do
bar!
foo!
rack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -355,6 +634,9 @@ describe "the lockfile format" do
actionpack
rack-obama
thin
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -391,6 +673,9 @@ describe "the lockfile format" do
DEPENDENCIES
rails
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -414,6 +699,9 @@ describe "the lockfile format" do
DEPENDENCIES
double_deps
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -437,6 +725,9 @@ describe "the lockfile format" do
DEPENDENCIES
rack-obama (>= 1.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -460,6 +751,9 @@ describe "the lockfile format" do
DEPENDENCIES
rack-obama (>= 1.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -485,6 +779,9 @@ describe "the lockfile format" do
DEPENDENCIES
foo
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -510,6 +807,9 @@ describe "the lockfile format" do
DEPENDENCIES
foo
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -535,6 +835,9 @@ describe "the lockfile format" do
DEPENDENCIES
foo
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -559,6 +862,9 @@ describe "the lockfile format" do
DEPENDENCIES
foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -574,6 +880,9 @@ describe "the lockfile format" do
DEPENDENCIES
rack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
install_gemfile <<-G
@@ -596,6 +905,9 @@ describe "the lockfile format" do
DEPENDENCIES
rack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -622,6 +934,9 @@ describe "the lockfile format" do
DEPENDENCIES
platform_specific
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -650,6 +965,9 @@ describe "the lockfile format" do
DEPENDENCIES
activesupport
rack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -671,6 +989,9 @@ describe "the lockfile format" do
DEPENDENCIES
rack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -692,6 +1013,9 @@ describe "the lockfile format" do
DEPENDENCIES
rack (= 1.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -713,6 +1037,9 @@ describe "the lockfile format" do
DEPENDENCIES
rack (= 1.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -756,6 +1083,9 @@ describe "the lockfile format" do
DEPENDENCIES
rack (> 0.9, < 1.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
G
end
@@ -803,6 +1133,9 @@ describe "the lockfile format" do
DEPENDENCIES
omg!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
L
FileUtils.rm_rf(bundled_app('vendor'))
@@ -827,6 +1160,9 @@ describe "the lockfile format" do
DEPENDENCIES
omg!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
L
end
@@ -836,7 +1172,9 @@ describe "the lockfile format" do
File.utime(time, time, bundled_app('Gemfile.lock'))
end
before(:each) do
+
build_repo2
+
install_gemfile <<-G
source "file://#{gem_repo2}"
gem "rack"
@@ -913,6 +1251,9 @@ describe "the lockfile format" do
DEPENDENCIES
rack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
L
install_gemfile(<<-G, :expect_err => true)
diff --git a/spec/other/bundle_ruby_spec.rb b/spec/other/bundle_ruby_spec.rb
new file mode 100644
index 0000000000..d3ecbca430
--- /dev/null
+++ b/spec/other/bundle_ruby_spec.rb
@@ -0,0 +1,158 @@
+require "spec_helper"
+
+describe "bundle_ruby" do
+ context "when run" do
+ it "displays a deprecation warning" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ ruby "1.9.3", :engine => 'ruby', :engine_version => '1.9.3'
+
+ gem "foo"
+ G
+
+ bundle_ruby
+
+ expect(err).to include("DEPRECATION: bundle_ruby is deprecated and will " \
+ "be removed in Bundler 2.0.")
+ end
+ end
+
+ context "without patchlevel" do
+ it "returns the ruby version" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ ruby "1.9.3", :engine => 'ruby', :engine_version => '1.9.3'
+
+ gem "foo"
+ G
+
+ bundle_ruby
+
+ expect(out).to include("ruby 1.9.3")
+ end
+
+ it "engine defaults to MRI" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ ruby "1.9.3"
+
+ gem "foo"
+ G
+
+ bundle_ruby
+
+ expect(out).to include("ruby 1.9.3")
+ end
+
+ it "handles jruby" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ ruby "1.8.7", :engine => 'jruby', :engine_version => '1.6.5'
+
+ gem "foo"
+ G
+
+ bundle_ruby
+
+ expect(out).to include("ruby 1.8.7 (jruby 1.6.5)")
+ end
+
+ it "handles rbx" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ ruby "1.8.7", :engine => 'rbx', :engine_version => '1.2.4'
+
+ gem "foo"
+ G
+
+ bundle_ruby
+
+ expect(out).to include("ruby 1.8.7 (rbx 1.2.4)")
+ end
+
+ it "raises an error if engine is used but engine version is not" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ ruby "1.8.7", :engine => 'rbx'
+
+ gem "foo"
+ G
+
+ bundle_ruby :exitstatus => true
+ expect(exitstatus).not_to eq(0) if exitstatus
+
+ bundle_ruby
+ expect(out).to include("Please define :engine_version")
+ end
+
+ it "raises an error if engine_version is used but engine is not" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ ruby "1.8.7", :engine_version => '1.2.4'
+
+ gem "foo"
+ G
+
+ bundle_ruby :exitstatus => true
+ expect(exitstatus).not_to eq(0) if exitstatus
+
+ bundle_ruby
+ expect(out).to include("Please define :engine")
+ end
+
+ it "raises an error if engine version doesn't match ruby version for MRI" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ ruby "1.8.7", :engine => 'ruby', :engine_version => '1.2.4'
+
+ gem "foo"
+ G
+
+ bundle_ruby :exitstatus => true
+ expect(exitstatus).not_to eq(0) if exitstatus
+
+ bundle_ruby
+ expect(out).to include("ruby_version must match the :engine_version for MRI")
+ end
+
+ it "should print if no ruby version is specified" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+
+ gem "foo"
+ G
+
+ bundle_ruby
+
+ expect(out).to include("No ruby version specified")
+ end
+ end
+
+ context "when using patchlevel" do
+ it "returns the ruby version" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ ruby "1.9.3", :patchlevel => '429', :engine => 'ruby', :engine_version => '1.9.3'
+
+ gem "foo"
+ G
+
+ bundle_ruby
+
+ expect(out).to include("ruby 1.9.3p429")
+ end
+
+ it "handles an engine" do
+ gemfile <<-G
+ source "file://#{gem_repo1}"
+ ruby "1.9.3", :patchlevel => '392', :engine => 'jruby', :engine_version => '1.7.4'
+
+ gem "foo"
+ G
+
+ bundle_ruby
+
+ expect(out).to include("ruby 1.9.3p392 (jruby 1.7.4)")
+ end
+ end
+end
diff --git a/spec/other/ext_spec.rb b/spec/other/ext_spec.rb
index cbee163771..dca6c80a59 100644
--- a/spec/other/ext_spec.rb
+++ b/spec/other/ext_spec.rb
@@ -5,6 +5,14 @@ describe "Gem::Specification#match_platform" do
darwin = gem "lol", "1.0", "platform_specific-1.0-x86-darwin-10"
expect(darwin.match_platform(pl('java'))).to eq(false)
end
+
+ context "when platform is a string" do
+ it "matches when platform is a string" do
+ lazy_spec = Bundler::LazySpecification.new("lol", "1.0", "universal-mingw32")
+ expect(lazy_spec.match_platform(pl('x86-mingw32'))).to eq(true)
+ expect(lazy_spec.match_platform(pl('x64-mingw32'))).to eq(true)
+ end
+ end
end
describe "Bundler::GemHelpers#generic" do
@@ -49,12 +57,12 @@ describe "Gem::SourceIndex#refresh!" do
end
it "does not explode when called", :if => rubygems_1_7 do
- run "Gem.source_index.refresh!"
- run "Gem::SourceIndex.new([]).refresh!"
+ run "Gem.source_index.refresh!", :expect_err => true
+ run "Gem::SourceIndex.new([]).refresh!", :expect_err => true
end
it "does not explode when called", :unless => rubygems_1_7 do
- run "Gem.source_index.refresh!"
- run "Gem::SourceIndex.from_gems_in([]).refresh!"
+ run "Gem.source_index.refresh!", :expect_err => true
+ run "Gem::SourceIndex.from_gems_in([]).refresh!", :expect_err => true
end
end
diff --git a/spec/other/platform_spec.rb b/spec/other/platform_spec.rb
index b71446ff49..86216df2a7 100644
--- a/spec/other/platform_spec.rb
+++ b/spec/other/platform_spec.rb
@@ -1126,8 +1126,8 @@ G
G
bundle "outdated"
- expect(out).to include("activesupport (3.0 > 2.3.5)")
- expect(out).to include("foo (1.0")
+ expect(out).to include("activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5")
+ expect(out).to include("foo (newest 1.0")
end
it "returns list of outdated gems when the ruby version matches for any engine" do
@@ -1146,8 +1146,8 @@ G
G
bundle "outdated"
- expect(out).to include("activesupport (3.0 > 2.3.5)")
- expect(out).to include("foo (1.0")
+ expect(out).to include("activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5)")
+ expect(out).to include("foo (newest 1.0")
end
end
diff --git a/spec/quality_spec.rb b/spec/quality_spec.rb
index 81fcddfb32..7654007ba9 100644
--- a/spec/quality_spec.rb
+++ b/spec/quality_spec.rb
@@ -97,7 +97,7 @@ describe "The library itself" do
end
end
- expect(@err.split("\n").reject { |f| f =~ %r{lib/bundler/vendor} }).to eq([])
+ expect(@err.split("\n").reject{|r| r =~ /^DEPRECATION/ }).to eq([])
expect(@out).to eq("")
end
end
diff --git a/spec/realworld/edgecases_spec.rb b/spec/realworld/edgecases_spec.rb
index 15c7697564..19d5bae578 100644
--- a/spec/realworld/edgecases_spec.rb
+++ b/spec/realworld/edgecases_spec.rb
@@ -7,7 +7,7 @@ describe "real world edgecases", :realworld => true do
source :rubygems
gem "linecache", "0.46"
G
- expect(err).to eq("")
+ expect(err).to lack_errors
end
# https://github.com/bundler/bundler/issues/1202
@@ -81,7 +81,7 @@ describe "real world edgecases", :realworld => true do
bundle "install --path vendor/bundle", :expect_err => true
expect(err).not_to include("Could not find rake")
- expect(err).to be_empty
+ expect(err).to lack_errors
end
it "checks out git repos when the lockfile is corrupted" do
diff --git a/spec/realworld/parallel_spec.rb b/spec/realworld/parallel_spec.rb
index 67311a7e7c..409c146d9b 100644
--- a/spec/realworld/parallel_spec.rb
+++ b/spec/realworld/parallel_spec.rb
@@ -6,7 +6,7 @@ describe "parallel", :realworld => true do
source "https://rubygems.org"
gem 'activesupport', '~> 3.2.13'
gem 'faker', '~> 1.1.2'
- gem 'i18n', '~> 0.6.0' # Because 1.7+ requires Ruby 1.9.3+
+ gem 'i18n', '~> 0.6.0' # Because 0.7+ requires Ruby 1.9.3+
G
bundle :install, :jobs => 4, :env => {"DEBUG" => "1"}
@@ -38,7 +38,7 @@ describe "parallel", :realworld => true do
source "https://rubygems.org"
gem 'activesupport', '~> 3.2.12'
gem 'faker', '~> 1.1.2'
- gem 'i18n', '~> 0.6.0' # Because 1.7+ requires Ruby 1.9.3+
+ gem 'i18n', '~> 0.6.0' # Because 0.7+ requires Ruby 1.9.3+
G
bundle :update, :jobs => 4, :env => {"DEBUG" => "1"}
diff --git a/spec/resolver/platform_spec.rb b/spec/resolver/platform_spec.rb
index 2a126e4836..149bc921fc 100644
--- a/spec/resolver/platform_spec.rb
+++ b/spec/resolver/platform_spec.rb
@@ -35,6 +35,7 @@ describe "Resolving platform craziness" do
platforms "mingw32 mswin32 x64-mingw32" do |platform|
gem "thin", "1.2.7", platform
end
+ gem "win32-api", "1.5.1", "universal-mingw32"
end
end
@@ -57,6 +58,18 @@ describe "Resolving platform craziness" do
dep "thin"
should_resolve_as %w(thin-1.2.7-x64-mingw32)
end
+
+ it "finds universal-mingw gems on x86-mingw" do
+ platform "x86-mingw32"
+ dep "win32-api"
+ should_resolve_as %w(win32-api-1.5.1-universal-mingw32)
+ end
+
+ it "finds universal-mingw gems on x64-mingw" do
+ platform "x64-mingw32"
+ dep "win32-api"
+ should_resolve_as %w(win32-api-1.5.1-universal-mingw32)
+ end
end
describe "with conflicting cases" do
diff --git a/spec/runtime/gem_tasks_spec.rb b/spec/runtime/gem_tasks_spec.rb
new file mode 100644
index 0000000000..5124b05a3c
--- /dev/null
+++ b/spec/runtime/gem_tasks_spec.rb
@@ -0,0 +1,35 @@
+require "spec_helper"
+
+describe "require 'bundler/gem_tasks'" do
+ before :each do
+ bundled_app("foo.gemspec").open("w") do |f|
+ f.write <<-GEMSPEC
+ Gem::Specification.new do |s|
+ s.name = "foo"
+ end
+ GEMSPEC
+ end
+ bundled_app("Rakefile").open("w") do |f|
+ f.write <<-RAKEFILE
+ $:.unshift("#{bundler_path}")
+ require "bundler/gem_tasks"
+ RAKEFILE
+ end
+ end
+
+ it "includes the relevant tasks" do
+ with_gem_path_as(Spec::Path.base_system_gems.to_s) do
+ sys_exec "ruby -S rake -T"
+ end
+
+ expect(err).to eq("")
+ expected_tasks = [
+ "rake build",
+ "rake install",
+ "rake release",
+ ]
+ tasks = out.lines.to_a.map { |s| s.split('#').first.strip }
+ expect(tasks & expected_tasks).to eq(expected_tasks)
+ expect(exitstatus).to eq(0) if exitstatus
+ end
+end
diff --git a/spec/runtime/require_spec.rb b/spec/runtime/require_spec.rb
index 5e5e9db22f..59c7a6850c 100644
--- a/spec/runtime/require_spec.rb
+++ b/spec/runtime/require_spec.rb
@@ -95,7 +95,7 @@ describe "Bundler.require" do
Bundler.require
R
- expect(err).to eq("ZOMG LOAD ERROR")
+ expect(err).to eq_err("ZOMG LOAD ERROR")
end
it "doesn't swallow the error when the library has an unrelated error" do
@@ -117,7 +117,7 @@ describe "Bundler.require" do
RUBY
run(cmd, :expect_err => true)
- expect(err).to eq("ZOMG LOAD ERROR: cannot load such file -- load-bar")
+ expect(err).to eq_err("ZOMG LOAD ERROR: cannot load such file -- load-bar")
end
describe "with namespaced gems" do
@@ -153,7 +153,7 @@ describe "Bundler.require" do
RUBY
ruby(cmd, :expect_err => true)
- expect(err).to be_empty
+ expect(err).to lack_errors
end
it "does not mangle explictly given requires" do
@@ -165,7 +165,7 @@ describe "Bundler.require" do
load_error_run <<-R, 'jquery-rails'
Bundler.require
R
- expect(err).to eq("ZOMG LOAD ERROR")
+ expect(err).to eq_err("ZOMG LOAD ERROR")
end
it "handles the case where regex fails" do
@@ -187,7 +187,7 @@ describe "Bundler.require" do
RUBY
run(cmd, :expect_err => true)
- expect(err).to eq("ZOMG LOAD ERROR")
+ expect(err).to eq_err("ZOMG LOAD ERROR")
end
it "doesn't swallow the error when the library has an unrelated error" do
@@ -210,7 +210,7 @@ describe "Bundler.require" do
RUBY
run(cmd, :expect_err => true)
- expect(err).to eq("ZOMG LOAD ERROR: cannot load such file -- load-bar")
+ expect(err).to eq_err("ZOMG LOAD ERROR: cannot load such file -- load-bar")
end
end
@@ -316,7 +316,7 @@ describe "Bundler.require" do
load_error_run <<-R, 'no_such_file_omg'
Bundler.require
R
- expect(err).to eq('ZOMG LOAD ERROR')
+ expect(err).to eq_err('ZOMG LOAD ERROR')
end
end
end
@@ -335,7 +335,7 @@ describe "Bundler.require with platform specific dependencies" do
G
run "Bundler.require", :expect_err => true
- expect(err).to be_empty
+ expect(err).to lack_errors
end
it "requires gems pinned to multiple platforms, including the current one" do
@@ -350,6 +350,6 @@ describe "Bundler.require with platform specific dependencies" do
run "Bundler.require; puts RACK", :expect_err => true
expect(out).to eq("1.0.0")
- expect(err).to be_empty
+ expect(err).to lack_errors
end
end
diff --git a/spec/runtime/setup_spec.rb b/spec/runtime/setup_spec.rb
index 934e3218dd..68640e1074 100644
--- a/spec/runtime/setup_spec.rb
+++ b/spec/runtime/setup_spec.rb
@@ -16,7 +16,7 @@ describe "Bundler.setup" do
require 'rack'
puts RACK
RUBY
- expect(err).to eq("")
+ expect(err).to lack_errors
expect(out).to eq("1.0.0")
end
end
@@ -42,7 +42,7 @@ describe "Bundler.setup" do
puts "WIN"
end
RUBY
- expect(err).to eq("")
+ expect(err).to lack_errors
expect(out).to eq("WIN")
end
@@ -55,7 +55,7 @@ describe "Bundler.setup" do
require 'rack'
puts RACK
RUBY
- expect(err).to eq("")
+ expect(err).to lack_errors
expect(out).to eq("1.0.0")
end
@@ -69,7 +69,7 @@ describe "Bundler.setup" do
require 'rack'
puts RACK
RUBY
- expect(err).to eq("")
+ expect(err).to lack_errors
expect(out).to eq("1.0.0")
end
@@ -87,9 +87,24 @@ describe "Bundler.setup" do
puts "FAIL"
end
RUBY
- expect(err).to eq("")
+ expect(err).to lack_errors
expect(out).to match("WIN")
end
+
+ it "handles multiple non-additive invocations" do
+ ruby <<-RUBY
+ require 'bundler'
+ Bundler.setup(:default, :test)
+ Bundler.setup(:default)
+ require 'rack'
+
+ puts "FAIL"
+ RUBY
+
+ expect(err).to match("rack")
+ expect(err).to match("LoadError")
+ expect(out).not_to match("FAIL")
+ end
end
it "raises if the Gemfile was not yet installed" do
@@ -230,7 +245,7 @@ describe "Bundler.setup" do
end
R
- expect(err).to be_empty
+ expect(err).to lack_errors
end
it "replaces #gem but raises when the version is wrong" do
@@ -256,7 +271,7 @@ describe "Bundler.setup" do
end
R
- expect(err).to be_empty
+ expect(err).to lack_errors
end
end
@@ -572,7 +587,7 @@ describe "Bundler.setup" do
end
R
- expect(err).to be_empty
+ expect(err).to lack_errors
end
end
end
@@ -607,7 +622,7 @@ describe "Bundler.setup" do
ENV["GEM_HOME"] = ""
bundle %{exec ruby -e "require 'set'"}
- expect(err).to be_empty
+ expect(err).to lack_errors
end
it "should prepend gemspec require paths to $LOAD_PATH in order" do
@@ -628,6 +643,39 @@ describe "Bundler.setup" do
expect(out).to eq("yay")
end
+ it "should clean $LOAD_PATH properly" do
+ gem_name = 'very_simple_binary'
+ full_gem_name = gem_name + '-1.0'
+ ext_dir = File.join(tmp "extenstions", full_gem_name)
+
+ install_gem full_gem_name
+
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ G
+
+ ruby <<-R
+ if Gem::Specification.method_defined? :extension_dir
+ s = Gem::Specification.find_by_name '#{gem_name}'
+ s.extension_dir = '#{ext_dir}'
+
+ # Don't build extensions.
+ s.class.send(:define_method, :build_extensions) { nil }
+ end
+
+ require 'bundler'
+ gem '#{gem_name}'
+
+ puts $LOAD_PATH.count {|path| path =~ /#{gem_name}/} >= 2
+
+ Bundler.setup
+
+ puts $LOAD_PATH.count {|path| path =~ /#{gem_name}/} == 0
+ R
+
+ expect(out).to eq("true\ntrue")
+ end
+
it "stubs out Gem.refresh so it does not reveal system gems" do
system_gems "rack-1.0.0"
@@ -663,7 +711,7 @@ describe "Bundler.setup" do
require 'foo'
R
end
- expect(err).to eq("")
+ expect(err).to lack_errors
end
it "should make sure the Bundler.root is really included in the path relative to the Gemfile" do
@@ -688,7 +736,7 @@ describe "Bundler.setup" do
R
end
- expect(err).to eq("")
+ expect(err).to lack_errors
end
end
@@ -834,7 +882,7 @@ describe "Bundler.setup" do
Bundler.load
RUBY
- expect(err).to eq("")
+ expect(err).to lack_errors
expect(out).to eq("")
end
end
@@ -846,7 +894,7 @@ describe "Bundler.setup" do
G
bundle %|exec ruby -e "require 'bundler'; Bundler.setup"|
- expect(err).to be_empty
+ expect(err).to lack_errors
end
end
diff --git a/spec/support/builders.rb b/spec/support/builders.rb
index 5490a2b976..1a1c916779 100644
--- a/spec/support/builders.rb
+++ b/spec/support/builders.rb
@@ -260,12 +260,15 @@ module Spec
FileUtils.rm_rf Dir[gem_repo3("prerelease*")]
end
- # A repo that has no pre-installed gems included. (The caller completely determines the contents with the block)
- def build_repo4(&blk)
+ # A repo that has no pre-installed gems included. (The caller completely
+ # determines the contents with the block.)
+ def build_repo4
FileUtils.rm_rf gem_repo4
- build_repo(gem_repo4) do
- yield if block_given?
- end
+ build_repo(gem_repo4) { yield }
+ end
+
+ def update_repo4
+ update_repo(gem_repo4) { yield }
end
def update_repo2
diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb
index e42c67be57..66d4a81ba6 100644
--- a/spec/support/matchers.rb
+++ b/spec/support/matchers.rb
@@ -1,5 +1,17 @@
module Spec
module Matchers
+ RSpec::Matchers.define :lack_errors do
+ match do |actual|
+ actual.gsub(/(^DEPRECATION:.+)/, '') == ''
+ end
+ end
+
+ RSpec::Matchers.define :eq_err do |expected|
+ match do |actual|
+ actual.gsub(/(^DEPRECATION:.+\n)/, '') == expected
+ end
+ end
+
RSpec::Matchers.define :have_dep do |*args|
dep = Bundler::Dependency.new(*args)
diff --git a/spec/update/gems_spec.rb b/spec/update/gems_spec.rb
index 83928a5213..32ebbd45d0 100644
--- a/spec/update/gems_spec.rb
+++ b/spec/update/gems_spec.rb
@@ -99,6 +99,16 @@ describe "bundle update" do
should_not_be_installed "rack 1.2"
end
end
+
+ describe "in a frozen bundle" do
+ it "should fail loudly" do
+ bundle "install --deployment"
+ bundle "update"
+
+ expect(out).to match(/You are trying to install in deployment mode after changing.your Gemfile/m)
+ expect(exitstatus).not_to eq(0) if exitstatus
+ end
+ end
end
describe "bundle update in more complicated situations" do
@@ -155,6 +165,11 @@ describe "bundle update when a gem depends on a newer version of bundler" do
G
end
+ it "should not explode" do
+ bundle "update"
+ expect(err).to lack_errors
+ end
+
it "should explain that bundler conflicted" do
bundle "update"
expect(err).not_to match(/in snapshot/i)
diff --git a/spec/update/git_spec.rb b/spec/update/git_spec.rb
index 9f5e71b3e2..8e075be80c 100644
--- a/spec/update/git_spec.rb
+++ b/spec/update/git_spec.rb
@@ -89,7 +89,7 @@ describe "bundle update" do
gem "foo", "1.0", :git => "#{lib_path('foo_two')}"
G
- expect(err).to be_empty
+ expect(err).to lack_errors
expect(out).to include("Fetching #{lib_path}/foo_two")
expect(out).to include("Bundle complete!")
end