diff --git a/CHANGELOG.md b/CHANGELOG.md index 19ea421e2ec..edd9e30f2a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,33 @@ +## 1.0.9 (January 19, 2010) + +Bugfixes: + + - Fix a bug where Bundler.require could remove gems from the load + path. In Rails apps with a default application.rb, this removed + all gems in groups other than :default and Rails.env. + +## 1.0.8 (January 18, 2010) + +Features: + + - Allow overriding gemspec() deps with :git deps + - Add --local option to `bundle update` + - Ignore Gemfile.lock in newly generated gems + - Use `less` as help pager instead of `more` + - Run `bundle exec rake` instead of `rake` in Capistrano tasks + +Bugfixes: + + - Fix --no-cache option for `bundle install` + - Allow Vlad deploys to work without Capistrano gem installed + - Fix group arguments to `bundle console` + - Allow groups to be loaded even if other groups were loaded + - Evaluate gemspec() gemspecs in their directory not the cwd + - Count on Rake to chdir to the right place in GemHelper + - Change Pathnames to Strings for MacRuby + - Check git process exit status correctly + - Fix some warnings in 1.9.3-trunk (thanks tenderlove) + ## 1.0.7 (November 17, 2010) Bugfixes: @@ -290,8 +320,6 @@ isolation. - Fix cases where the same dependency appeared several times in the Gemfile.lock - Fix a bug where require errors were being swallowed during Bundler.require -## BACKFILL COMING - ## 1.0.0.beta.1 - No `bundle lock` command. Locking happens automatically on install or update diff --git a/Rakefile b/Rakefile index cd9c7c50dcf..bddc63dc5a8 100644 --- a/Rakefile +++ b/Rakefile @@ -60,7 +60,7 @@ begin namespace :rubygems do # Rubygems 1.3.5, 1.3.6, and HEAD specs rubyopt = ENV["RUBYOPT"] - %w(master REL_1_3_5 REL_1_3_6).each do |rg| + %w(master v1.3.5 v1.3.6 v1.3.7 v1.4.0 v1.4.1).each do |rg| desc "Run specs with Rubygems #{rg}" RSpec::Core::RakeTask.new(rg) do |t| t.rspec_opts = %w(-fs --color) @@ -69,7 +69,7 @@ begin task "clone_rubygems_#{rg}" do unless File.directory?("tmp/rubygems_#{rg}") - system("git clone git://github.com/jbarnette/rubygems.git tmp/rubygems_#{rg} && cd tmp/rubygems_#{rg} && git reset --hard #{rg}") + system("git clone git://github.com/rubygems/rubygems.git tmp/rubygems_#{rg} && cd tmp/rubygems_#{rg} && git reset --hard #{rg}") end ENV["RUBYOPT"] = "-I#{File.expand_path("tmp/rubygems_#{rg}/lib")} #{rubyopt}" end diff --git a/bundler.gemspec b/bundler.gemspec index 4091a7cb335..d590daac2de 100644 --- a/bundler.gemspec +++ b/bundler.gemspec @@ -8,7 +8,7 @@ Gem::Specification.new do |s| s.name = "bundler" s.version = Bundler::VERSION s.platform = Gem::Platform::RUBY - s.authors = ["Carl Lerche", "Yehuda Katz", "André Arko"] + s.authors = ["Carl Lerche", "Yehuda Katz", "André Arko", "Terence Lee"] s.email = ["carlhuda@engineyard.com"] s.homepage = "http://gembundler.com" s.summary = %q{The best way to manage your application's dependencies} diff --git a/lib/bundler.rb b/lib/bundler.rb index 768393568a1..d489ddcd214 100644 --- a/lib/bundler.rb +++ b/lib/bundler.rb @@ -95,16 +95,18 @@ def bin_path end def setup(*groups) - return @setup if defined?(@setup) && @setup + # Just return if all groups are already loaded + return @setup if defined?(@setup) if groups.empty? # 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 || []) + unloaded = groups - @completed_groups # Record groups that are now loaded - @completed_groups = groups | (@completed_groups || []) + @completed_groups = groups # Load any groups that are not yet loaded unloaded.any? ? load.setup(*unloaded) : load end diff --git a/lib/bundler/capistrano.rb b/lib/bundler/capistrano.rb index a304b09f393..3722ab79749 100644 --- a/lib/bundler/capistrano.rb +++ b/lib/bundler/capistrano.rb @@ -7,4 +7,5 @@ Capistrano::Configuration.instance(:must_exist).load do after "deploy:update_code", "bundle:install" Bundler::Deployment.define_task(self, :task, :except => { :no_release => true }) + set :rake, 'bundle exec rake' end diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index 2b8702450e2..e922fc5c7a7 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -45,7 +45,7 @@ def help(cli = nil) if have_groff? && root !~ %r{^file:/.+!/META-INF/jruby.home/.+} groff = "groff -Wall -mtty-char -mandoc -Tascii" - pager = ENV['MANPAGER'] || ENV['PAGER'] || 'more' + pager = ENV['MANPAGER'] || ENV['PAGER'] || 'less' Kernel.exec "#{groff} #{root}/#{command} | #{pager}" else @@ -199,7 +199,7 @@ def install Bundler.ui.be_quiet! if opts[:quiet] Installer.install(Bundler.root, Bundler.definition, opts) - Bundler.load.cache if Bundler.root.join("vendor/cache").exist? + Bundler.load.cache if Bundler.root.join("vendor/cache").exist? && !options["no-cache"] if Bundler.settings[:path] relative_path = Bundler.settings[:path] @@ -228,6 +228,8 @@ def install possible versions of the gems in the bundle. D method_option "source", :type => :array, :banner => "Update a specific source (and all gems associated with it)" + method_option "local", :type => :boolean, :banner => + "Do not attempt to fetch gems remotely and use the gem cache instead" def update(*gems) sources = Array(options[:source]) @@ -238,7 +240,8 @@ def update(*gems) Bundler.definition(:gems => gems, :sources => sources) end - Installer.install Bundler.root, Bundler.definition, "update" => true + opts = {"update" => true, "local" => options[:local]} + Installer.install Bundler.root, Bundler.definition, opts Bundler.load.cache if Bundler.root.join("vendor/cache").exist? Bundler.ui.confirm "Your bundle is updated! " + "Use `bundle show [gemname]` to see where a bundled gem is installed." @@ -390,8 +393,7 @@ def open(name) desc "console [GROUP]", "Opens an IRB session with the bundle pre-loaded" def console(group = nil) - require 'bundler/setup' - group ? Bundler.require(:default, group) : Bundler.require + group ? Bundler.require(:default, *(group.split.map! {|g| g.to_sym })) : Bundler.require ARGV.clear require 'irb' diff --git a/lib/bundler/deployment.rb b/lib/bundler/deployment.rb index 73ee604d2a2..d51c6281724 100644 --- a/lib/bundler/deployment.rb +++ b/lib/bundler/deployment.rb @@ -1,7 +1,7 @@ module Bundler class Deployment def self.define_task(context, task_method = :task, opts = {}) - if context.is_a?(Capistrano::Configuration) + if defined?(Capistrano) && context.is_a?(Capistrano::Configuration) context_name = "capistrano" role_default = "{:except => {:no_release => true}}" else @@ -9,7 +9,7 @@ def self.define_task(context, task_method = :task, opts = {}) role_default = "[:app]" end - roles = context.fetch(:bundle_roles, nil) + roles = context.fetch(:bundle_roles, false) opts[:roles] = roles if roles context.send :namespace, :bundle do diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb index 3d55c0f0c4c..fa80a76db03 100644 --- a/lib/bundler/dsl.rb +++ b/lib/bundler/dsl.rb @@ -29,7 +29,7 @@ def gemspec(opts = nil) case gemspecs.size when 1 - spec = Gem::Specification.load(gemspecs.first) + 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 group(development_group) do diff --git a/lib/bundler/gem_helper.rb b/lib/bundler/gem_helper.rb index ff5d5421c83..b2510f60de0 100644 --- a/lib/bundler/gem_helper.rb +++ b/lib/bundler/gem_helper.rb @@ -4,9 +4,9 @@ module Bundler class GemHelper - def self.install_tasks(opts = nil) - dir = File.dirname(Rake.application.rakefile_location) - self.new(dir, opts && opts[:name]).install + def self.install_tasks(opts = {}) + dir = opts[:dir] || Dir.pwd + self.new(dir, opts[:name]).install end attr_reader :spec_path, :base, :gemspec @@ -51,7 +51,7 @@ def build_gem def install_gem built_gem_path = build_gem - out, code = sh_with_code("gem install #{built_gem_path}") + out, _ = sh_with_code("gem install #{built_gem_path}") 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 @@ -68,7 +68,7 @@ def release_gem protected def rubygem_push(path) - out, status = sh("gem push #{path}") + out, _ = sh("gem push #{path}") raise "Gem push failed due to lack of RubyGems.org credentials." if out[/Enter your RubyGems.org credentials/] Bundler.ui.confirm "Pushed #{name} #{version} to rubygems.org" end @@ -100,8 +100,7 @@ def guard_clean end def clean? - out, code = sh_with_code("git diff --exit-code") - code == 0 + sh_with_code("git diff --exit-code")[1] == 0 end def tag_version diff --git a/lib/bundler/index.rb b/lib/bundler/index.rb index 1ca9af19a0e..b2105cf6827 100644 --- a/lib/bundler/index.rb +++ b/lib/bundler/index.rb @@ -104,7 +104,7 @@ def search_by_spec(spec) def same_version?(a, b) regex = /^(.*?)(?:\.0)*$/ - ret = a.to_s[regex, 1] == b.to_s[regex, 1] + a.to_s[regex, 1] == b.to_s[regex, 1] end def spec_satisfies_dependency?(spec, dep) diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb index 0a27c092275..4948357c9b8 100644 --- a/lib/bundler/resolver.rb +++ b/lib/bundler/resolver.rb @@ -407,7 +407,7 @@ def gem_message(requirement) end def error_message - output = errors.inject("") do |o, (conflict, (origin, requirement))| + errors.inject("") do |o, (conflict, (origin, requirement))| # origin is the SpecSet of specs from the Gemfile that is conflicted with if origin @@ -422,7 +422,7 @@ def error_message o << " Current Bundler version:\n" newer_bundler_required = requirement.requirement > Gem::Requirement.new(origin.version) # If the origin is a LockfileParser, it does not respond_to :required_by - elsif !origin.respond_to?(:required_by) || !(required_by = origin.required_by.first) + elsif !origin.respond_to?(:required_by) || !(origin.required_by.first) o << " In snapshot (Gemfile.lock):\n" end diff --git a/lib/bundler/runtime.rb b/lib/bundler/runtime.rb index 30e97161f28..92ee2bc17f2 100644 --- a/lib/bundler/runtime.rb +++ b/lib/bundler/runtime.rb @@ -23,7 +23,11 @@ def setup(*groups) e = Gem::LoadError.new "You have already activated #{activated_spec.name} #{activated_spec.version}, " \ "but your Gemfile requires #{spec.name} #{spec.version}. Consider using bundle exec." e.name = spec.name - e.version_requirement = Gem::Requirement.new(spec.version.to_s) + if e.respond_to?(:requirement=) + e.requirement = Gem::Requirement.new(spec.version.to_s) + else + e.version_requirement = Gem::Requirement.new(spec.version.to_s) + end raise e end diff --git a/lib/bundler/shared_helpers.rb b/lib/bundler/shared_helpers.rb index 23e3d01cef8..4a584b09da8 100644 --- a/lib/bundler/shared_helpers.rb +++ b/lib/bundler/shared_helpers.rb @@ -96,15 +96,24 @@ def cripple_rubygems(specs) spec = specs.find { |s| s.name == dep.name } if spec.nil? + e = Gem::LoadError.new "#{dep.name} is not part of the bundle. Add it to Gemfile." e.name = dep.name - e.version_requirement = dep.requirement + if e.respond_to?(:requirement=) + e.requirement = dep.requirement + else + e.version_requirement = dep.requirement + end raise e elsif dep !~ spec e = Gem::LoadError.new "can't activate #{dep}, already activated #{spec.full_name}. " \ "Make sure all dependencies are added to Gemfile." e.name = dep.name - e.version_requirement = dep.requirement + if e.respond_to?(:requirement=) + e.requirement = dep.requirement + else + e.version_requirement = dep.requirement + end raise e end diff --git a/lib/bundler/source.rb b/lib/bundler/source.rb index 9c8e7c69863..a49150780ba 100644 --- a/lib/bundler/source.rb +++ b/lib/bundler/source.rb @@ -549,7 +549,7 @@ def git(command) if allow_git_ops? out = %x{git #{command}} - if $? != 0 + if $?.exitstatus != 0 raise GitError, "An error has occurred in git when running `git #{command}`. Cannot complete bundling." end out diff --git a/spec/install/gems/groups_spec.rb b/spec/install/gems/groups_spec.rb index e54cbd72983..c667114e02e 100644 --- a/spec/install/gems/groups_spec.rb +++ b/spec/install/gems/groups_spec.rb @@ -43,6 +43,23 @@ out = run("require 'thin'; puts THIN") out.should == '1.0' end + + it "removes old groups when new groups are set up" do + run <<-RUBY, :emo, :expect_err => true + Bundler.setup(:default) + require 'thin'; puts THIN + RUBY + @err.should =~ /no such file to load -- thin/i + end + + it "sets up old groups when they have previously been removed" do + out = run <<-RUBY, :emo + Bundler.setup(:default) + Bundler.setup(:default, :emo) + require 'thin'; puts THIN + RUBY + out.should == '1.0' + end end describe "installing --without" do diff --git a/spec/install/gems/packed_spec.rb b/spec/install/gems/packed_spec.rb index a89a4eee3d6..592221226ff 100644 --- a/spec/install/gems/packed_spec.rb +++ b/spec/install/gems/packed_spec.rb @@ -68,5 +68,17 @@ out.should == "1.0.0 RUBY" end end + + it "does not update the cache if --no-cache is passed" do + gemfile <<-G + source "file://#{gem_repo1}" + gem "rack" + G + bundled_app("vendor/cache").mkpath + bundled_app("vendor/cache").children.should be_empty + + bundle "install --no-cache" + bundled_app("vendor/cache").children.should be_empty + end end end diff --git a/spec/install/gems/platform_spec.rb b/spec/install/gems/platform_spec.rb index 47876a1cd1a..b604bc1d7f7 100644 --- a/spec/install/gems/platform_spec.rb +++ b/spec/install/gems/platform_spec.rb @@ -177,7 +177,7 @@ end it "does not blow up on sources with all platform-excluded specs" do - git = build_git "foo" + build_git "foo" install_gemfile <<-G platform :#{not_local_tag} do diff --git a/spec/install/gemspec_spec.rb b/spec/install/gemspec_spec.rb index e7992c1147d..90e9a2fe7f1 100644 --- a/spec/install/gemspec_spec.rb +++ b/spec/install/gemspec_spec.rb @@ -93,4 +93,16 @@ should_be_installed "bar-dev 1.0.0", :groups => :dev end + it "should evaluate the gemspec in its directory" do + build_lib("foo", :path => tmp.join("foo")) + File.open(tmp.join("foo/foo.gemspec"), "w") do |s| + s.write "raise 'ahh' unless Dir.pwd == '#{tmp.join("foo")}'" + end + + install_gemfile <<-G, :expect_err => true + gemspec :path => '#{tmp.join("foo")}' + G + @err.should_not match(/ahh/) + end + end diff --git a/spec/other/help_spec.rb b/spec/other/help_spec.rb index 06bc949015d..c443fa5cd09 100644 --- a/spec/other/help_spec.rb +++ b/spec/other/help_spec.rb @@ -1,7 +1,9 @@ require "spec_helper" describe "bundle help" do - it "complains if older versions of bundler are installed" do + # Rubygems 1.4+ no longer load gem plugins so this test is no longer needed + rubygems_under_14 = Gem::Requirement.new("< 1.4").satisfied_by?(Gem::Version.new(Gem::VERSION)) + it "complains if older versions of bundler are installed", :if => rubygems_under_14 do system_gems "bundler-0.8.1" bundle "help", :expect_err => true diff --git a/spec/quality_spec.rb b/spec/quality_spec.rb index 9a8054e1207..6228dd746ac 100644 --- a/spec/quality_spec.rb +++ b/spec/quality_spec.rb @@ -49,7 +49,7 @@ def check_for_extra_spaces(filename) it "can still be built" do Dir.chdir(root) do `gem build bundler.gemspec` - $?.should == 0 + check $?.should == 0 # clean up the .gem generated system("rm bundler-#{Bundler::VERSION}.gem") diff --git a/spec/runtime/setup_spec.rb b/spec/runtime/setup_spec.rb index 1bfa4ca79a1..fe755238fd2 100644 --- a/spec/runtime/setup_spec.rb +++ b/spec/runtime/setup_spec.rb @@ -1,6 +1,65 @@ require "spec_helper" describe "Bundler.setup" do + describe "with no arguments" do + it "makes all groups available" do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :group => :test + G + + ruby <<-RUBY + require 'rubygems' + require 'bundler' + Bundler.setup + + require 'rack' + puts RACK + RUBY + err.should == "" + out.should == "1.0.0" + end + end + + describe "when called with groups" do + before(:each) do + install_gemfile <<-G + source "file://#{gem_repo1}" + gem "rack", :group => :test + G + end + + it "doesn't make all groups available" do + ruby <<-RUBY + require 'rubygems' + require 'bundler' + Bundler.setup(:default) + + begin + require 'rack' + rescue LoadError + puts "WIN" + end + RUBY + err.should == "" + out.should == "WIN" + end + + it "leaves all groups available if they were already" do + ruby <<-RUBY + require 'rubygems' + require 'bundler' + Bundler.setup + Bundler.setup(:default) + + require 'rack' + puts RACK + RUBY + err.should == "" + out.should == "1.0.0" + end + end + it "raises if the Gemfile was not yet installed" do gemfile <<-G source "file://#{gem_repo1}" @@ -68,7 +127,7 @@ gem "rack" G - lockfile = File.read(bundled_app("Gemfile.lock")) + File.read(bundled_app("Gemfile.lock")) FileUtils.rm(bundled_app("Gemfile.lock")) @@ -107,7 +166,7 @@ should_be_installed "rack 1.0.0" end - describe "cripping rubygems" do + describe "crippling rubygems" do describe "by replacing #gem" do before :each do install_gemfile <<-G @@ -129,6 +188,19 @@ out.should == "WIN" end + it "version_requirement is now deprecated in rubygems 1.4.0+ when gem is missing" do + run <<-R, :expect_err => true + begin + gem "activesupport" + puts "FAIL" + rescue LoadError + puts "WIN" + end + R + + err.should be_empty + end + it "replaces #gem but raises when the version is wrong" do run <<-R begin @@ -141,6 +213,19 @@ out.should == "WIN" end + + it "version_requirement is now deprecated in rubygesm 1.4.0+ when the version is wrong" do + run <<-R, :expect_err => true + begin + gem "rack", "1.0.0" + puts "FAIL" + rescue LoadError + puts "WIN" + end + R + + err.should be_empty + end end describe "by hiding system gems" do @@ -348,6 +433,31 @@ out.should == "You have already activated thin 1.1, but your Gemfile requires thin 1.0. Consider using bundle exec." end + + it "version_requirement is now deprecated in rubygems 1.4.0+" do + system_gems "thin-1.0", "rack-1.0.0" + build_gem "thin", "1.1", :to_system => true do |s| + s.add_dependency "rack" + end + + gemfile <<-G + gem "thin", "1.0" + G + + ruby <<-R, :expect_err => true + require 'rubygems' + gem "thin" + require 'bundler' + begin + Bundler.setup + puts "FAIL" + rescue Gem::LoadError => e + puts e.message + end + R + + err.should be_empty + end end end @@ -560,8 +670,8 @@ def Bundler.require(path) Bundler.load RUBY - err.should be_empty - out.should be_empty + err.should == "" + out.should == "" end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 5fa031555fd..867d80a681d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -26,7 +26,7 @@ Spec::Rubygems.setup FileUtils.rm_rf(Spec::Path.gem_repo1) -ENV['RUBYOPT'] = "-I#{Spec::Path.root}/spec/support/rubygems_hax" +ENV['RUBYOPT'] = "#{ENV['RUBYOPT']} -r#{Spec::Path.root}/spec/support/rubygems_hax/platform.rb" ENV['BUNDLE_SPEC_RUN'] = "true" RSpec.configure do |config| diff --git a/spec/support/builders.rb b/spec/support/builders.rb index 665428552c9..321eba2f116 100644 --- a/spec/support/builders.rb +++ b/spec/support/builders.rb @@ -489,7 +489,7 @@ def _build(options) end class GitUpdater < LibBuilder - WINDOWS = Config::CONFIG["host_os"] =~ %r!(msdos|mswin|djgpp|mingw)! + WINDOWS = RbConfig::CONFIG["host_os"] =~ %r!(msdos|mswin|djgpp|mingw)! NULL = WINDOWS ? "NUL" : "/dev/null" def silently(str) diff --git a/spec/support/helpers.rb b/spec/support/helpers.rb index 02705634e8e..9f751feb996 100644 --- a/spec/support/helpers.rb +++ b/spec/support/helpers.rb @@ -3,7 +3,7 @@ module Helpers def reset! @in_p, @out_p, @err_p = nil, nil, nil Dir["#{tmp}/{gems/*,*}"].each do |dir| - next if %(base remote1 gems rubygems_1_3_5 rubygems_1_3_6 rubygems_master).include?(File.basename(dir)) + next if %(base remote1 gems rubygems_v1.3.5 rubygems_v1.3.6 rubygems_v1.3.7 rubygems_v1.4.0 rubygems_v1.4.1 rubygems_master).include?(File.basename(dir)) unless ENV['BUNDLER_SUDO_TESTS'] FileUtils.rm_rf(dir) else diff --git a/spec/support/rubygems_hax/rubygems_plugin.rb b/spec/support/rubygems_hax/platform.rb similarity index 89% rename from spec/support/rubygems_hax/rubygems_plugin.rb rename to spec/support/rubygems_hax/platform.rb index 35a375a5d97..183d0801a77 100644 --- a/spec/support/rubygems_hax/rubygems_plugin.rb +++ b/spec/support/rubygems_hax/platform.rb @@ -1,3 +1,5 @@ +require 'rubygems' + class Gem::Platform @local = new(ENV['BUNDLER_SPEC_PLATFORM']) if ENV['BUNDLER_SPEC_PLATFORM'] end diff --git a/spec/update/gems_spec.rb b/spec/update/gems_spec.rb index b4d59c984a7..dcc69602039 100644 --- a/spec/update/gems_spec.rb +++ b/spec/update/gems_spec.rb @@ -43,6 +43,15 @@ should_be_installed "rack 1.2", "rack-obama 1.0", "activesupport 2.3.5" end end + + describe "with --local option" do + it "doesn't hit repo2" do + FileUtils.rm_rf(gem_repo2) + + bundle "update --local" + out.should_not match(/Fetching source index/) + end + end end describe "bundle update in more complicated situations" do