From 830e0ad0fe5a1a1059eaf3e9139d0f59afb0bad8 Mon Sep 17 00:00:00 2001 From: Danial Pearce Date: Wed, 1 Jun 2011 11:30:28 +1000 Subject: [PATCH 01/32] Use the --git-dir and --work-tree options for existing git repos rather than chdir to them. This is due to some problem with cron not properly chdir'ing. --- lib/bundler/source.rb | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/lib/bundler/source.rb b/lib/bundler/source.rb index 581b2e654db..b3f94b465e3 100644 --- a/lib/bundler/source.rb +++ b/lib/bundler/source.rb @@ -608,11 +608,11 @@ def uri_hash Digest::SHA1.hexdigest(input) end - # Escape the URI for shell commands. To support a single quote - # within the URI we must end the string, escape the quote and + # Escape an argument for shell commands. To support a single quote + # within the argument we must end the string, escape the quote and # restart. - def uri_escaped - "'#{uri.gsub("'") {|s| "'\\''"}}'" + def escape(string) + "'#{string.to_s.gsub("'") {|s| "'\\''"}}'" end def cache_path @@ -632,12 +632,12 @@ def cache return if has_revision_cached? Bundler.ui.info "Updating #{uri}" in_cache do - git %|fetch --force --quiet --tags #{uri_escaped} "refs/heads/*:refs/heads/*"| + git %|--git-dir #{escape Dir.pwd} fetch --force --quiet --tags #{escape uri} "refs/heads/*:refs/heads/*"| end else Bundler.ui.info "Fetching #{uri}" FileUtils.mkdir_p(cache_path.dirname) - git %|clone #{uri_escaped} "#{cache_path}" --bare --no-hardlinks| + git %|clone #{escape uri} "#{cache_path}" --bare --no-hardlinks| end end @@ -648,20 +648,19 @@ def checkout git %|clone --no-checkout "#{cache_path}" "#{path}"| File.chmod((0777 & ~File.umask), path) end - Dir.chdir(path) do - git %|fetch --force --quiet --tags "#{cache_path}"| - git "reset --hard #{revision}" + dir_opts = %|--git-dir #{escape path}/.git --work-tree #{escape path}| + git %|#{dir_opts} fetch --force --quiet --tags "#{cache_path}"| + git "#{dir_opts} reset --hard #{revision}" - if @submodules - git "submodule init" - git "submodule update" - end + if @submodules + git "#{dir_opts} submodule init" + git "#{dir_opts} submodule update" end end def has_revision_cached? return unless @revision - in_cache { git %|cat-file -e #{@revision}| } + in_cache { git %|--git-dir #{escape Dir.pwd} cat-file -e #{@revision}| } true rescue GitError false From 127cf0760717d8d61aacfb9ffd2dd25d76e4e0fe Mon Sep 17 00:00:00 2001 From: Danial Pearce Date: Sat, 11 Jun 2011 18:33:36 +1000 Subject: [PATCH 02/32] Remove in_cache in favour of passing the cache_path to everything that needs it. --- lib/bundler/source.rb | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/lib/bundler/source.rb b/lib/bundler/source.rb index fe9ac1dbfd4..372583288e2 100644 --- a/lib/bundler/source.rb +++ b/lib/bundler/source.rb @@ -613,11 +613,11 @@ def escape(string) if Bundler::WINDOWS # Windows quoting requires double quotes only, with double quotes # inside the string escaped by being doubled. - '"' + string.gsub('"') {|s| '""'} + '"' + '"' + string.to_s.gsub('"') {|s| '""'} + '"' else # Bash requires single quoted strings, with the single quotes escaped # by ending the string, escaping the quote, and restarting the string. - "'" + string.gsub("'") {|s| "'\\''"} + "'" + "'" + string.to_s.gsub("'") {|s| "'\\''"} + "'" end end @@ -637,9 +637,8 @@ def cache if cached? return if has_revision_cached? Bundler.ui.info "Updating #{uri}" - in_cache do - git %|--git-dir #{escape Dir.pwd} fetch --force --quiet --tags #{escape uri} "refs/heads/*:refs/heads/*"| - end + cache unless cached? + git %|--git-dir #{escape cache_path} fetch --force --quiet --tags #{escape uri} "refs/heads/*:refs/heads/*"| else Bundler.ui.info "Fetching #{uri}" FileUtils.mkdir_p(cache_path.dirname) @@ -666,7 +665,8 @@ def checkout def has_revision_cached? return unless @revision - in_cache { git %|--git-dir #{escape Dir.pwd} cat-file -e #{@revision}| } + cache unless cached? + git %|--git-dir #{escape cache_path} cat-file -e #{@revision}| true rescue GitError false @@ -679,7 +679,8 @@ def allow_git_ops? def revision @revision ||= begin if allow_git_ops? - in_cache { git("rev-parse #{ref}").strip } + cache unless cached? + git("--git-dir #{escape cache_path} rev-parse #{ref}").strip else raise GitError, "The git source #{uri} is not yet checked out. Please run `bundle install` before trying to start your application" end @@ -689,11 +690,6 @@ def revision def cached? cache_path.exist? end - - def in_cache(&blk) - cache unless cached? - Dir.chdir(cache_path, &blk) - end end end From dc15dc56446ab10c17028810ac83eb577b375753 Mon Sep 17 00:00:00 2001 From: Robert Wahler Date: Thu, 18 Aug 2011 11:21:09 -0400 Subject: [PATCH 03/32] Gemfile.lock should not be touched if nothing has changed This fixes issue #1105, Gemfile.lock always updated on Windows when running bundle install --- lib/bundler/definition.rb | 8 ++--- spec/lock/lockfile_spec.rb | 60 +++++++++++++++++++++++++++++--------- 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 962838aab74..82e1aa3e277 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -180,6 +180,10 @@ def groups def lock(file) contents = to_lock + # Convert to \r\n if the existing lock has them + # i.e., Windows with `git config core.autocrlf=true` + contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match("\r\n") + return if @lockfile_contents == contents if Bundler.settings[:frozen] @@ -187,10 +191,6 @@ def lock(file) return end - # Convert to \r\n if the existing lock has them - # i.e., Windows with `git config core.autocrlf=true` - contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match("\r\n") - File.open(file, 'wb'){|f| f.puts(contents) } end diff --git a/spec/lock/lockfile_spec.rb b/spec/lock/lockfile_spec.rb index 86663f23afa..e78eb41d5ac 100644 --- a/spec/lock/lockfile_spec.rb +++ b/spec/lock/lockfile_spec.rb @@ -671,13 +671,18 @@ end - context "line endings" do + describe "line endings" do + def set_lockfile_mtime_to_known_value + time = Time.local(2000, 1, 1, 0, 0, 0) + File.utime(time, time, bundled_app('Gemfile.lock')) + end before(:each) do build_repo2 install_gemfile <<-G source "file://#{gem_repo2}" gem "rack" G + set_lockfile_mtime_to_known_value end it "generates Gemfile.lock with \\n line endings" do @@ -685,22 +690,51 @@ should_be_installed "rack 1.0" end - it "preserves Gemfile.lock \\n line endings" do - update_repo2 + context "during updates" do - bundle "update" - File.read(bundled_app("Gemfile.lock")).should_not match("\r\n") - should_be_installed "rack 1.2" + it "preserves Gemfile.lock \\n line endings" do + update_repo2 + + lambda { bundle "update" }.should change { File.mtime(bundled_app('Gemfile.lock')) } + File.read(bundled_app("Gemfile.lock")).should_not match("\r\n") + should_be_installed "rack 1.2" + end + + it "preserves Gemfile.lock \\n\\r line endings" do + update_repo2 + win_lock = File.read(bundled_app("Gemfile.lock")).gsub(/\n/, "\r\n") + File.open(bundled_app("Gemfile.lock"), "wb"){|f| f.puts(win_lock) } + set_lockfile_mtime_to_known_value + + lambda { bundle "update" }.should change { File.mtime(bundled_app('Gemfile.lock')) } + File.read(bundled_app("Gemfile.lock")).should match("\r\n") + should_be_installed "rack 1.2" + end end - it "preserves Gemfile.lock \\n\\r line endings" do - update_repo2 - win_lock = File.read(bundled_app("Gemfile.lock")).gsub(/\n/, "\r\n") - File.open(bundled_app("Gemfile.lock"), "wb"){|f| f.puts(win_lock) } + context "when nothing changes" do - bundle "update" - File.read(bundled_app("Gemfile.lock")).should match("\r\n") - should_be_installed "rack 1.2" + it "preserves Gemfile.lock \\n line endings" do + lambda { ruby <<-RUBY + require 'rubygems' + require 'bundler' + Bundler.setup + RUBY + }.should_not change { File.mtime(bundled_app('Gemfile.lock')) } + end + + it "preserves Gemfile.lock \\n\\r line endings" do + win_lock = File.read(bundled_app("Gemfile.lock")).gsub(/\n/, "\r\n") + File.open(bundled_app("Gemfile.lock"), "wb"){|f| f.puts(win_lock) } + set_lockfile_mtime_to_known_value + + lambda { ruby <<-RUBY + require 'rubygems' + require 'bundler' + Bundler.setup + RUBY + }.should_not change { File.mtime(bundled_app('Gemfile.lock')) } + end end end end From 671141da4b005c9ae15ec10aff9a2d85e294bdff Mon Sep 17 00:00:00 2001 From: Kevin Radloff Date: Mon, 29 Aug 2011 15:19:17 -0400 Subject: [PATCH 04/32] Don't hose existing load paths if Bundle.setup is called a multiple times with a different set of groups. --- lib/bundler.rb | 3 +-- spec/runtime/setup_spec.rb | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/bundler.rb b/lib/bundler.rb index b70f718ab67..bff021e0972 100644 --- a/lib/bundler.rb +++ b/lib/bundler.rb @@ -111,8 +111,7 @@ def setup(*groups) unloaded = groups - @completed_groups # Record groups that are now loaded @completed_groups = groups - # Load any groups that are not yet loaded - unloaded.any? ? load.setup(*unloaded) : load + unloaded.any? ? load.setup(*groups) : load end end diff --git a/spec/runtime/setup_spec.rb b/spec/runtime/setup_spec.rb index 44d433700c8..34a2c5df135 100644 --- a/spec/runtime/setup_spec.rb +++ b/spec/runtime/setup_spec.rb @@ -25,6 +25,7 @@ before(:each) do install_gemfile <<-G source "file://#{gem_repo1}" + gem "yard" gem "rack", :group => :test G end @@ -58,6 +59,24 @@ err.should eq("") out.should eq("1.0.0") end + + it "leaves :default available if setup is called twice" do + ruby <<-RUBY + require 'rubygems' + require 'bundler' + Bundler.setup(:default) + Bundler.setup(:default, :test) + + begin + require 'yard' + puts "WIN" + rescue LoadError + puts "FAIL" + end + RUBY + err.should eq("") + out.should match("WIN") + end end it "raises if the Gemfile was not yet installed" do From 290c8dbd69ef52b6f30a96493b5a2e6d6d41daa1 Mon Sep 17 00:00:00 2001 From: Ryan Wilcox Date: Mon, 29 Aug 2011 16:39:55 -0400 Subject: [PATCH 05/32] Information on what gem we're starting to install, to ease debugging errors --- lib/bundler/installer.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb index e0728a25a76..5e11115227b 100644 --- a/lib/bundler/installer.rb +++ b/lib/bundler/installer.rb @@ -47,6 +47,8 @@ def run(options) # as dependencies might actually affect the installation of # the gem. specs.each do |spec| + puts + puts " Currently processing '#{spec.name}'..." spec.source.fetch(spec) if spec.source.respond_to?(:fetch) # unless requested_specs.include?(spec) From a28546837b056ea514749dfd7e3bc82f2a8996e8 Mon Sep 17 00:00:00 2001 From: Ryan Wilcox Date: Mon, 29 Aug 2011 20:53:00 -0400 Subject: [PATCH 06/32] put debugging information in an exception handler, instead of spamming output --- lib/bundler/installer.rb | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb index 5e11115227b..ca4b94e8f8e 100644 --- a/lib/bundler/installer.rb +++ b/lib/bundler/installer.rb @@ -47,23 +47,26 @@ def run(options) # as dependencies might actually affect the installation of # the gem. specs.each do |spec| - puts - puts " Currently processing '#{spec.name}'..." - spec.source.fetch(spec) if spec.source.respond_to?(:fetch) + begin + spec.source.fetch(spec) if spec.source.respond_to?(:fetch) - # unless requested_specs.include?(spec) - # Bundler.ui.debug " * Not in requested group; skipping." - # next - # end + # unless requested_specs.include?(spec) + # Bundler.ui.debug " * Not in requested group; skipping." + # next + # end - Bundler.rubygems.with_build_args [Bundler.settings["build.#{spec.name}"]] do - spec.source.install(spec) - Bundler.ui.debug "from #{spec.loaded_from} " - end + Bundler.rubygems.with_build_args [Bundler.settings["build.#{spec.name}"]] do + spec.source.install(spec) + Bundler.ui.debug "from #{spec.loaded_from} " + end - Bundler.ui.info "" - generate_bundler_executable_stubs(spec) if Bundler.settings[:bin] - FileUtils.rm_rf(Bundler.tmp) + Bundler.ui.info "" + generate_bundler_executable_stubs(spec) if Bundler.settings[:bin] + FileUtils.rm_rf(Bundler.tmp) + rescue Exception + puts "Error: '#{$!.message}', when installing #{spec.name}" + raise + end end lock From 82ac6b6b73ef3ccd2c3e09fb4b8ce1bb92c2213c Mon Sep 17 00:00:00 2001 From: Ryan Wilcox Date: Mon, 5 Sep 2011 22:22:04 -0400 Subject: [PATCH 07/32] use bundler.ui + wording changes for exception handling --- lib/bundler/installer.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb index ca4b94e8f8e..f672584cf29 100644 --- a/lib/bundler/installer.rb +++ b/lib/bundler/installer.rb @@ -63,8 +63,10 @@ def run(options) Bundler.ui.info "" generate_bundler_executable_stubs(spec) if Bundler.settings[:bin] FileUtils.rm_rf(Bundler.tmp) - rescue Exception - puts "Error: '#{$!.message}', when installing #{spec.name}" + rescue Exception => e + Bundler.ui.warn "#{e.class}: #{e.message}" + Bundler.ui.error "An error (#{e.message}) occured while installing #{spec.name} (#{spec.version})" + Bundler.ui.error "Bundler can not continue. Try manually installing the gem, to determine if this is a Bundler specfic issue or issue with the gem itself" raise end end From 4925f523882a0450347a9b87e9b4a456066baaaa Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Thu, 8 Sep 2011 13:20:20 -0700 Subject: [PATCH 08/32] Fix "warning: assigned but unused variable - reqs". --- lib/bundler/rubygems_integration.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bundler/rubygems_integration.rb b/lib/bundler/rubygems_integration.rb index 1c0c55050a0..418b1e9518b 100644 --- a/lib/bundler/rubygems_integration.rb +++ b/lib/bundler/rubygems_integration.rb @@ -205,7 +205,7 @@ def replace_bin_path(specs) gem_class = (class << Gem ; self ; end) gem_class.send(:remove_method, :bin_path) gem_class.send(:define_method, :bin_path) do |name, *args| - exec_name, *reqs = args + exec_name, = args if exec_name == 'bundle' return ENV['BUNDLE_BIN_PATH'] From 9f80959eb316c78f90f7725a030eb39dacc727af Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Mon, 12 Sep 2011 10:12:57 -0700 Subject: [PATCH 09/32] Binstubs should be installable on RG 1.8.10 (thx @jeremy) --- lib/bundler/source.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bundler/source.rb b/lib/bundler/source.rb index 9d8ebe7285b..25b59927af0 100644 --- a/lib/bundler/source.rb +++ b/lib/bundler/source.rb @@ -385,7 +385,7 @@ def local_specs @local_specs ||= load_spec_files end - class Installer < Gem::Installer + class Installer < Bundler::GemInstaller def initialize(spec, options = {}) @spec = spec @bin_dir = Bundler.requires_sudo? ? "#{Bundler.tmp}/bin" : "#{Bundler.rubygems.gem_dir}/bin" From aed177930cbe0e37b4a7b734ac2857942d41af50 Mon Sep 17 00:00:00 2001 From: Lee Reilly Date: Mon, 12 Sep 2011 15:46:30 -0700 Subject: [PATCH 10/32] Killed a comma. --- UPGRADING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPGRADING.md b/UPGRADING.md index 666dcf7ae4f..b2344839c1f 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -100,4 +100,4 @@ Bundler 0.9 changes the following Bundler 0.8 Gemfile APIs: mode, where using system gems, this becomes `Bundler.setup(:multiple, :groups)`. If you don't specify any groups, this puts all groups on the load - path. In locked, mode, it becomes `require '.bundle/environment'` + path. In locked mode, it becomes `require '.bundle/environment'` From 86f56e59569cd5c6ef085b68b7c9dba4fa13f240 Mon Sep 17 00:00:00 2001 From: Lee Reilly Date: Mon, 12 Sep 2011 15:50:47 -0700 Subject: [PATCH 11/32] Fixed broken link; http://gembundler.com/v0.9/deploying.html works, but http://gembundler.com/v1.0/deploying.html does not; http://gembundler.com/deploying.html points to latest version. --- UPGRADING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPGRADING.md b/UPGRADING.md index b2344839c1f..e50ecfb9b5f 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -33,7 +33,7 @@ your deploy.rb file to run Bundler automatically as part of deploying: require 'bundler/capistrano' For more details on deploying using bundler, see the documentation -for the bundler cap task, and the [documentation on deploying](http://gembundler.com/v1.0/deploying.html). +for the bundler cap task, and the [documentation on deploying](http://gembundler.com/deploying.html). ## Bundler 0.8 to 0.9 and above From 704545214e7da8085c543697696fa72750a8a125 Mon Sep 17 00:00:00 2001 From: Matt Sanders Date: Tue, 13 Sep 2011 00:34:22 -0500 Subject: [PATCH 12/32] Raise more helpful error when current_release path cannot be successfully detected. --- lib/bundler/deployment.rb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/bundler/deployment.rb b/lib/bundler/deployment.rb index 727f357e7e9..213972a7940 100644 --- a/lib/bundler/deployment.rb +++ b/lib/bundler/deployment.rb @@ -4,9 +4,11 @@ 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) @@ -39,13 +41,16 @@ def self.define_task(context, task_method = :task, opts = {}) 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 - - args = ["--gemfile #{File.join(context.fetch(:current_release), bundle_gemfile)}"] + current_release = context.fetch(:current_release) + if current_release.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(current_release, 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? - run "cd #{context.fetch(:current_release)} && #{bundle_cmd} install #{args.join(' ')}" + run "cd #{current_release} && #{bundle_cmd} install #{args.join(' ')}" end end end From 7c5e5456ee819c1d4dae0382b9ae05921d7319c3 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Tue, 13 Sep 2011 15:30:12 -0700 Subject: [PATCH 13/32] Better gem install failure error, no backtrace --- lib/bundler.rb | 3 ++- lib/bundler/installer.rb | 47 +++++++++++++++++++++------------------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/lib/bundler.rb b/lib/bundler.rb index 9b31b597f7e..70c93282707 100644 --- a/lib/bundler.rb +++ b/lib/bundler.rb @@ -37,7 +37,7 @@ module Bundler autoload :UI, 'bundler/ui' class BundlerError < StandardError - def self.status_code(code = nil) + def self.status_code(code) define_method(:status_code) { code } end end @@ -45,6 +45,7 @@ def self.status_code(code = nil) class GemfileNotFound < BundlerError; status_code(10) ; end class GemNotFound < BundlerError; status_code(7) ; end class GemfileError < BundlerError; status_code(4) ; end + class InstallError < BundlerError; status_code(5) ; end class PathError < BundlerError; status_code(13) ; end class GitError < BundlerError; status_code(11) ; end class DeprecatedError < BundlerError; status_code(12) ; end diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb index f672584cf29..3ffd6901b6c 100644 --- a/lib/bundler/installer.rb +++ b/lib/bundler/installer.rb @@ -47,28 +47,7 @@ def run(options) # as dependencies might actually affect the installation of # the gem. specs.each do |spec| - begin - spec.source.fetch(spec) if spec.source.respond_to?(:fetch) - - # unless requested_specs.include?(spec) - # Bundler.ui.debug " * Not in requested group; skipping." - # next - # end - - Bundler.rubygems.with_build_args [Bundler.settings["build.#{spec.name}"]] do - spec.source.install(spec) - Bundler.ui.debug "from #{spec.loaded_from} " - end - - Bundler.ui.info "" - generate_bundler_executable_stubs(spec) if Bundler.settings[:bin] - FileUtils.rm_rf(Bundler.tmp) - rescue Exception => e - Bundler.ui.warn "#{e.class}: #{e.message}" - Bundler.ui.error "An error (#{e.message}) occured while installing #{spec.name} (#{spec.version})" - Bundler.ui.error "Bundler can not continue. Try manually installing the gem, to determine if this is a Bundler specfic issue or issue with the gem itself" - raise - end + install_gem_from_spec(spec) end lock @@ -76,6 +55,30 @@ def run(options) private + def install_gem_from_spec(spec) + # Download the gem to get the spec, because some specs that are returned + # by rubygems.org are broken and wrong. + spec.source.fetch(spec) if spec.source.respond_to?(:fetch) + + # Fetch the build settings, if there are any + settings = Bundler.settings["build.#{spec.name}"] + Bundler.rubygems.with_build_args [settings] do + spec.source.install(spec) + Bundler.ui.debug "from #{spec.loaded_from} " + end + + # newline after installing, some gems say "with native extensions" + Bundler.ui.info "" + generate_bundler_executable_stubs(spec) if Bundler.settings[:bin] + FileUtils.rm_rf(Bundler.tmp) + rescue Exception => e + Bundler.ui.warn "#{e.class}: #{e.message}" + msg = "An error occured while installing #{spec.name} (#{spec.version})," + msg << " and Bundler cannot continue.\nMake sure that `gem install" + msg << " #{spec.name} -v '#{spec.version}'` succeeds before bundling." + raise Bundler::InstallError, msg + end + def generate_bundler_executable_stubs(spec) bin_path = Bundler.bin_path template = File.read(File.expand_path('../templates/Executable', __FILE__)) From b4b409de2f9edf08a8df78fde1b6c7536fc73db5 Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Thu, 8 Sep 2011 13:33:14 -0700 Subject: [PATCH 14/32] Fix "method redefined" warnings. --- lib/bundler/rubygems_ext.rb | 2 ++ lib/bundler/rubygems_integration.rb | 1 + 2 files changed, 3 insertions(+) diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb index 54e72c53b79..20c08b7379e 100644 --- a/lib/bundler/rubygems_ext.rb +++ b/lib/bundler/rubygems_ext.rb @@ -40,6 +40,7 @@ def load_paths end # RubyGems 1.8+ used only. + remove_method :gem_dir if method_defined? :gem_dir def gem_dir full_gem_path end @@ -151,6 +152,7 @@ class Platform MSWIN = Gem::Platform.new('mswin32') MINGW = Gem::Platform.new('x86-mingw32') + undef_method :hash if method_defined? :hash def hash @cpu.hash ^ @os.hash ^ @version.hash end diff --git a/lib/bundler/rubygems_integration.rb b/lib/bundler/rubygems_integration.rb index 418b1e9518b..bbbc7007d0a 100644 --- a/lib/bundler/rubygems_integration.rb +++ b/lib/bundler/rubygems_integration.rb @@ -180,6 +180,7 @@ def stub_source_index137(specs) end def stub_source_index170(specs) + Gem::SourceIndex.send(:alias_method, :old_initialize, :initialize) Gem::SourceIndex.send(:define_method, :initialize) do |*args| @gems = {} # You're looking at this thinking: Oh! This is how I make those From 67cfb2f7d5b2c6e30cfed686074d23e32c4e5eaa Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Tue, 13 Sep 2011 16:07:58 -0700 Subject: [PATCH 15/32] Fix "instance variable @installed not initialized" warning. --- lib/bundler/source.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/bundler/source.rb b/lib/bundler/source.rb index 9d8ebe7285b..cba2135aadf 100644 --- a/lib/bundler/source.rb +++ b/lib/bundler/source.rb @@ -490,6 +490,7 @@ def initialize(options) @revision = options["revision"] @submodules = options["submodules"] @update = false + @installed = nil end def self.from_lock(options) From b6e0fd31d419a28fd8f9b252462a838d268a6a58 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Tue, 13 Sep 2011 16:09:21 -0700 Subject: [PATCH 16/32] Version 1.0.19.rc --- CHANGELOG.md | 20 +++++++++++++++++--- lib/bundler/version.rb | 2 +- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3ca587a2f8..d7a907e2ba5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,18 @@ -## 1.0.18 (Aug 16, 2011) +## 1.0.19.rc (September 13, 2011) + +Features: + + - Compatability with Rubygems 1.8.10 installer changes + - Report gem installation failures clearly (@rwilcox, #1380) + - Useful error for cap and vlad on first deploy (@nexmat, @kirs) + +Bugfixes: + + - `exec` now works when the command contains 'exec' + - Only touch lock after changes on Windows (@robertwahler, #1358) + - Keep load paths when #setup is called multiple times (@radsaq, #1379) + +## 1.0.18 (August 16, 2011) Bugfixes: @@ -13,14 +27,14 @@ Features: - Make fetch_specs faster (@zeha, #1294) - Allow overriding development deps loaded by #gemspec (@lgierth, #1245) -## 1.0.17 (Aug 8, 2011) +## 1.0.17 (August 8, 2011) Bugfixes: - Fix rake issues with rubygems 1.3.x (#1342) - Fixed invalid byte sequence error while installing gem on Ruby 1.9 (#1341) -## 1.0.16 (Aug 8, 2011) +## 1.0.16 (August 8, 2011) Features: diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb index e2303c160e1..f09ba8d53a3 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.0.18" unless defined?(::Bundler::VERSION) + VERSION = "1.0.19.rc" unless defined?(::Bundler::VERSION) end From debd9372207f8b524de47a41614ecea7ccba5817 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Tue, 13 Sep 2011 17:13:40 -0700 Subject: [PATCH 17/32] remove tabs from changelog --- CHANGELOG.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7a907e2ba5..281d76e06b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,15 +2,15 @@ Features: - - Compatability with Rubygems 1.8.10 installer changes - - Report gem installation failures clearly (@rwilcox, #1380) - - Useful error for cap and vlad on first deploy (@nexmat, @kirs) + - Compatability with Rubygems 1.8.10 installer changes + - Report gem installation failures clearly (@rwilcox, #1380) + - Useful error for cap and vlad on first deploy (@nexmat, @kirs) Bugfixes: - - `exec` now works when the command contains 'exec' + - `exec` now works when the command contains 'exec' - Only touch lock after changes on Windows (@robertwahler, #1358) - - Keep load paths when #setup is called multiple times (@radsaq, #1379) + - Keep load paths when #setup is called multiple times (@radsaq, #1379) ## 1.0.18 (August 16, 2011) From 27656fb92fba2b50db41687a67220614dc2572f8 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Wed, 14 Sep 2011 15:49:09 -0700 Subject: [PATCH 18/32] Fix fake yard for Rubygems 1.8.10+ --- spec/support/builders.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/spec/support/builders.rb b/spec/support/builders.rb index 936e1a4a2cf..caaa1061c5e 100644 --- a/spec/support/builders.rb +++ b/spec/support/builders.rb @@ -167,7 +167,12 @@ def build_repo1 # The yard gem iterates over Gem.source_index looking for plugins build_gem "yard" do |s| s.write "lib/yard.rb", <<-Y - Gem.source_index.find_name('').each do |gem| + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new("1.8.10") + specs = Gem::Specification + else + specs = Gem.source_index.find_name('') + end + specs.each do |gem| puts gem.full_name end Y From 2c04e28d2cf0d77ede90ec96e1db23615ff23ab2 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Wed, 14 Sep 2011 00:22:24 -0700 Subject: [PATCH 19/32] fix line break when gem install errors --- lib/bundler/installer.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb index 3ffd6901b6c..95b1dc865ed 100644 --- a/lib/bundler/installer.rb +++ b/lib/bundler/installer.rb @@ -67,11 +67,12 @@ def install_gem_from_spec(spec) Bundler.ui.debug "from #{spec.loaded_from} " end - # newline after installing, some gems say "with native extensions" + # newline comes after installing, some gems say "with native extensions" Bundler.ui.info "" generate_bundler_executable_stubs(spec) if Bundler.settings[:bin] FileUtils.rm_rf(Bundler.tmp) rescue Exception => e + Bundler.ui.info "" Bundler.ui.warn "#{e.class}: #{e.message}" msg = "An error occured while installing #{spec.name} (#{spec.version})," msg << " and Bundler cannot continue.\nMake sure that `gem install" From d758698c4eff5d13eabe33c8e62cbbfc19d648db Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sat, 17 Sep 2011 12:20:07 -0700 Subject: [PATCH 20/32] rescue interrupts while bundler is loading closes #1395 --- bin/bundle | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/bin/bundle b/bin/bundle index 778c79c36cb..b6adbed50d8 100755 --- a/bin/bundle +++ b/bin/bundle @@ -1,15 +1,13 @@ #!/usr/bin/env ruby - -# Check if an older version of bundler is installed -require 'bundler' -$:.each do |path| - if path =~ %r'/bundler-0.(\d+)' && $1.to_i < 9 - abort "Please remove older versions of bundler. This can be done by running `gem cleanup bundler`." - end -end -require 'bundler/cli' - begin + require 'bundler' + # Check if an older version of bundler is installed + $:.each do |path| + if path =~ %r'/bundler-0.(\d+)' && $1.to_i < 9 + abort "Please remove 0.8 versions of bundler. This can be done by running `gem cleanup bundler`." + end + end + require 'bundler/cli' Bundler::CLI.start rescue Bundler::BundlerError => e Bundler.ui.error e.message From 667f0017badfef3c36046e725fb3c9b696494067 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sat, 17 Sep 2011 13:49:26 -0700 Subject: [PATCH 21/32] Remove trailing slashes in gem names fixes #1372 --- lib/bundler/cli.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index beb01543f0e..4ed5b7ab1cd 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -473,6 +473,7 @@ def viz desc "gem GEM", "Creates a skeleton for creating a rubygem" method_option :bin, :type => :boolean, :default => false, :aliases => '-b', :banner => "Generate a binary for your library." def gem(name) + name = name.chomp("/") # remove trailing slash if present target = File.join(Dir.pwd, name) constant_name = name.split('_').map{|p| p.capitalize}.join constant_name = constant_name.split('-').map{|q| q.capitalize}.join('::') if constant_name =~ /-/ From cb1dd15b383ab7333a0c481c3e8debcf35f5bb00 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sat, 17 Sep 2011 14:29:32 -0700 Subject: [PATCH 22/32] remove double-implementation of Dependency#to_lock --- lib/bundler/dependency.rb | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/lib/bundler/dependency.rb b/lib/bundler/dependency.rb index cb5709d17d4..a798b6cbfff 100644 --- a/lib/bundler/dependency.rb +++ b/lib/bundler/dependency.rb @@ -71,15 +71,8 @@ def current_platform? end def to_lock - out = " #{name}" - - unless requirement == Gem::Requirement.default - reqs = requirement.requirements.map{|o,v| "#{o} #{v}" } - out << " (#{reqs.join(', ')})" - end - + out = super out << '!' if source - out << "\n" end From 3a2a18a112015156e0d5ac1c7f9918cbc0be1b39 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sat, 17 Sep 2011 14:30:48 -0700 Subject: [PATCH 23/32] lock down requirements order via String#<=> refs #1375 --- lib/bundler/rubygems_ext.rb | 2 +- spec/lock/lockfile_spec.rb | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb index 20c08b7379e..a52ce02dc1e 100644 --- a/lib/bundler/rubygems_ext.rb +++ b/lib/bundler/rubygems_ext.rb @@ -124,7 +124,7 @@ def to_yaml_properties def to_lock out = " #{name}" unless requirement == Gem::Requirement.default - reqs = requirement.requirements.map{|o,v| "#{o} #{v}" } + reqs = requirement.requirements.map{|o,v| "#{o} #{v}" }.sort.reverse out << " (#{reqs.join(', ')})" end out diff --git a/spec/lock/lockfile_spec.rb b/spec/lock/lockfile_spec.rb index e78eb41d5ac..d920571eddf 100644 --- a/spec/lock/lockfile_spec.rb +++ b/spec/lock/lockfile_spec.rb @@ -70,10 +70,9 @@ G end - it "parses lockfiles w/ crazy shit" do + it "generates lockfiles with multiple requirements" do install_gemfile <<-G source "file://#{gem_repo1}" - gem "net-sftp" G From 9c15875cf5edfc15eeb973d1de9cc5e6d2577f4c Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sat, 17 Sep 2011 15:26:07 -0700 Subject: [PATCH 24/32] Fix the help spec for the 0.8 error --- bin/bundle | 4 +++- spec/other/help_spec.rb | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/bin/bundle b/bin/bundle index b6adbed50d8..b2aa229425c 100755 --- a/bin/bundle +++ b/bin/bundle @@ -4,7 +4,9 @@ begin # Check if an older version of bundler is installed $:.each do |path| if path =~ %r'/bundler-0.(\d+)' && $1.to_i < 9 - abort "Please remove 0.8 versions of bundler. This can be done by running `gem cleanup bundler`." + err = "Please remove Bundler 0.8 versions." + err << "This can be done by running `gem cleanup bundler`." + abort(err) end end require 'bundler/cli' diff --git a/spec/other/help_spec.rb b/spec/other/help_spec.rb index c443fa5cd09..4896fd44bb1 100644 --- a/spec/other/help_spec.rb +++ b/spec/other/help_spec.rb @@ -7,7 +7,8 @@ system_gems "bundler-0.8.1" bundle "help", :expect_err => true - err.should == "Please remove older versions of bundler. This can be done by running `gem cleanup bundler`." + err.should include("Please remove Bundler 0.8 versions.") + err.should include("This can be done by running `gem cleanup bundler`.") end it "uses groff when available" do From f4307761cf8b25f5ab300331bb7ab03025c4db86 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sat, 17 Sep 2011 17:42:03 -0700 Subject: [PATCH 25/32] move gem_helper_spec to conventional location --- bundler.gemspec | 3 ++- spec/{other => bundler}/gem_helper_spec.rb | 0 2 files changed, 2 insertions(+), 1 deletion(-) rename spec/{other => bundler}/gem_helper_spec.rb (100%) diff --git a/bundler.gemspec b/bundler.gemspec index cb7f795c298..86eab2cdfc5 100644 --- a/bundler.gemspec +++ b/bundler.gemspec @@ -22,7 +22,8 @@ Gem::Specification.new do |s| # Man files are required because they are ignored by git man_files = Dir.glob("lib/bundler/man/**/*") - s.files = `git ls-files`.split("\n") + man_files + git_files = `git ls-files`.split("\n") rescue '' + s.files = git_files + man_files s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.executables = %w(bundle) s.require_paths = ["lib"] diff --git a/spec/other/gem_helper_spec.rb b/spec/bundler/gem_helper_spec.rb similarity index 100% rename from spec/other/gem_helper_spec.rb rename to spec/bundler/gem_helper_spec.rb From ba7e1b082a45460cacefe0eb5c67b2632c4ee498 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sat, 17 Sep 2011 17:50:21 -0700 Subject: [PATCH 26/32] String#capitalize downcases the rest of the string :( fixes #1303 --- lib/bundler/cli.rb | 4 ++-- spec/bundler/gem_helper_spec.rb | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index 4ed5b7ab1cd..8839c8c4307 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -475,8 +475,8 @@ def viz def gem(name) name = name.chomp("/") # remove trailing slash if present target = File.join(Dir.pwd, name) - constant_name = name.split('_').map{|p| p.capitalize}.join - constant_name = constant_name.split('-').map{|q| q.capitalize}.join('::') if constant_name =~ /-/ + constant_name = name.split('_').map{|p| p[0..0].upcase + p[1..-1] }.join + constant_name = constant_name.split('-').map{|q| q[0..0].upcase + q[1..-1] }.join('::') if constant_name =~ /-/ constant_array = constant_name.split('::') git_author_name = `git config user.name`.chomp git_author_email = `git config user.email`.chomp diff --git a/spec/bundler/gem_helper_spec.rb b/spec/bundler/gem_helper_spec.rb index bb21b60ceda..ad2bb327924 100644 --- a/spec/bundler/gem_helper_spec.rb +++ b/spec/bundler/gem_helper_spec.rb @@ -31,6 +31,13 @@ File.open(File.join(app.to_s, 'test2.gemspec'), 'w') {|f| f << ''} proc { Bundler::GemHelper.new(app.to_s) }.should raise_error(/Unable to determine name/) end + + it "handles namespaces and converting to CamelCase" do + bundle 'gem test-foo_bar' + lib = bundled_app('test-foo_bar').join('lib/test-foo_bar.rb').read + lib.should include("module Test") + lib.should include("module FooBar") + end end context "gem management" do From c46d91421c7f838c3db9f64e1c35eee601a0255a Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sat, 17 Sep 2011 17:55:22 -0700 Subject: [PATCH 27/32] correct docs on source order fixes #1310 --- man/gemfile.5.ronn | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/gemfile.5.ronn b/man/gemfile.5.ronn index d97dadc2d1e..d6d5886bf7f 100644 --- a/man/gemfile.5.ronn +++ b/man/gemfile.5.ronn @@ -280,5 +280,5 @@ bundler uses the following priority order: repository otherwise declared. This results in bundler prioritizing the ActiveSupport gem from the Rails git repository over ones from `rubygems.org` - 3. The sources specified via `source`, in the order in which they were - declared in the `Gemfile`. + 3. The sources specified via `source`, searching each source in your `Gemfile` + from last added to first added. From 2eb123ab46877354d8a86e6bba6537568c768e4f Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sat, 17 Sep 2011 18:51:14 -0700 Subject: [PATCH 28/32] Update to Thor 0.15.2.rc --- lib/bundler/vendor/thor.rb | 70 ++++++++++++------- .../vendor/thor/actions/create_link.rb | 2 +- .../vendor/thor/actions/file_manipulation.rb | 2 +- lib/bundler/vendor/thor/base.rb | 34 +++++++-- lib/bundler/vendor/thor/group.rb | 14 ++-- lib/bundler/vendor/thor/invocation.rb | 4 +- lib/bundler/vendor/thor/parser/arguments.rb | 4 ++ lib/bundler/vendor/thor/parser/options.rb | 20 ++++-- lib/bundler/vendor/thor/rake_compat.rb | 21 +++--- lib/bundler/vendor/thor/runner.rb | 2 + lib/bundler/vendor/thor/shell.rb | 2 +- lib/bundler/vendor/thor/shell/basic.rb | 4 +- lib/bundler/vendor/thor/task.rb | 20 +++++- lib/bundler/vendor/thor/version.rb | 2 +- 14 files changed, 141 insertions(+), 60 deletions(-) diff --git a/lib/bundler/vendor/thor.rb b/lib/bundler/vendor/thor.rb index 92b24342e8a..c7ba3e15a45 100644 --- a/lib/bundler/vendor/thor.rb +++ b/lib/bundler/vendor/thor.rb @@ -5,7 +5,7 @@ class << self # Sets the default task when thor is executed without an explicit task to be called. # # ==== Parameters - # meth:: name of the defaut task + # meth:: name of the default task # def default_task(meth=nil) case meth @@ -108,6 +108,8 @@ def method_options(options=nil) @method_options end + alias options method_options + # Adds an option to the set of method options. If :for is given as option, # it allows you to change the options from a previous defined task. # @@ -143,6 +145,8 @@ def method_option(name, options={}) build_option(name, options, scope) end + alias option method_option + # Prints help information for the given task. # # ==== Parameters @@ -202,7 +206,11 @@ def subcommands def subcommand(subcommand, subcommand_class) self.subcommands << subcommand.to_s subcommand_class.subcommand_help subcommand - define_method(subcommand) { |*args| invoke subcommand_class, args } + + define_method(subcommand) do |*args| + args, opts = Thor::Arguments.split(args) + invoke subcommand_class, args, opts + end end # Extend check unknown options to accept a hash of conditions. @@ -259,8 +267,11 @@ def dispatch(meth, given_args, given_opts, config) #:nodoc: opts = given_opts || opts || [] config.merge!(:current_task => task, :task_options => task.options) + instance = new(args, opts, config) + yield instance if block_given? + args = instance.args trailing = args[Range.new(arguments.size, -1)] - new(args, opts, config).invoke_task(task, trailing || []) + instance.invoke_task(task, trailing || []) end # The banner for this class. You can customize it if you are invoking the @@ -300,7 +311,6 @@ def initialize_added #:nodoc: # Retrieve the task name from given args. def retrieve_task_name(args) #:nodoc: meth = args.first.to_s unless args.empty? - if meth && (map[meth] || meth !~ /^\-/) args.shift else @@ -308,35 +318,45 @@ def retrieve_task_name(args) #:nodoc: end end - # Receives a task name (can be nil), and try to get a map from it. - # If a map can't be found use the sent name or the default task. + # receives a (possibly nil) task name and returns a name that is in + # the tasks hash. In addition to normalizing aliases, this logic + # will determine if a shortened command is an unambiguous prefix of + # a task or alias. + # + # +normalize_task_name+ also converts names like +animal-prison+ + # into +animal_prison+. def normalize_task_name(meth) #:nodoc: - meth = map[meth.to_s] || find_subcommand_and_update_argv(meth) || meth || default_task - meth.to_s.gsub('-','_') # treat foo-bar > foo_bar - end - - # terrible hack that overwrites ARGV - def find_subcommand_and_update_argv(subcmd_name) #:nodoc: - return unless subcmd_name - cmd = find_subcommand(subcmd_name) - ARGV[0] = cmd if cmd - cmd - end + return default_task.to_s.gsub('-', '_') unless meth - def find_subcommand(subcmd_name) - possibilities = find_subcommand_possibilities subcmd_name + possibilities = find_task_possibilities(meth) if possibilities.size > 1 - raise "Ambiguous subcommand #{subcmd_name} matches [#{possibilities.join(', ')}]" + raise ArgumentError, "Ambiguous task #{meth} matches [#{possibilities.join(', ')}]" elsif possibilities.size < 1 - return nil + meth = meth || default_task + elsif map[meth] + meth = map[meth] + else + meth = possibilities.first end - possibilities.first + meth.to_s.gsub('-','_') # treat foo-bar as foo_bar end - def find_subcommand_possibilities(subcmd_name) - len = subcmd_name.length - all_tasks.map {|t| t.first}.select { |n| subcmd_name == n[0, len] } + # this is the logic that takes the task name passed in by the user + # and determines whether it is an unambiguous prefix of a task or + # alias name. + def find_task_possibilities(meth) + len = meth.to_s.length + possibilities = all_tasks.merge(map).keys.select { |n| meth == n[0, len] }.sort + unique_possibilities = possibilities.map { |k| map[k] || k }.uniq + + if possibilities.include?(meth) + [meth] + elsif unique_possibilities.size == 1 + unique_possibilities + else + possibilities + end end def subcommand_help(cmd) diff --git a/lib/bundler/vendor/thor/actions/create_link.rb b/lib/bundler/vendor/thor/actions/create_link.rb index 1975644a001..864a1e9923d 100644 --- a/lib/bundler/vendor/thor/actions/create_link.rb +++ b/lib/bundler/vendor/thor/actions/create_link.rb @@ -41,7 +41,7 @@ def invoke! invoke_with_conflict_check do FileUtils.mkdir_p(File.dirname(destination)) # Create a symlink by default - config[:symbolic] ||= true + config[:symbolic] = true if config[:symbolic].nil? File.unlink(destination) if exists? if config[:symbolic] File.symlink(render, destination) diff --git a/lib/bundler/vendor/thor/actions/file_manipulation.rb b/lib/bundler/vendor/thor/actions/file_manipulation.rb index ad049b3cf85..dee9fbdd8ea 100644 --- a/lib/bundler/vendor/thor/actions/file_manipulation.rb +++ b/lib/bundler/vendor/thor/actions/file_manipulation.rb @@ -187,7 +187,7 @@ def append_to_file(path, *args, &block) # # ==== Examples # - # inject_into_class "app/controllers/application_controller.rb", " filter_parameter :password\n" + # inject_into_class "app/controllers/application_controller.rb", ApplicationController, " filter_parameter :password\n" # # inject_into_class "app/controllers/application_controller.rb", ApplicationController do # " filter_parameter :password\n" diff --git a/lib/bundler/vendor/thor/base.rb b/lib/bundler/vendor/thor/base.rb index 65399ffbe67..62706f727d8 100644 --- a/lib/bundler/vendor/thor/base.rb +++ b/lib/bundler/vendor/thor/base.rb @@ -19,7 +19,7 @@ class Thor action add_file create_file in_root inside run run_ruby_script) module Base - attr_accessor :options + attr_accessor :options, :parent_options, :args # It receives arguments in an Array and two hashes, one for options and # other for configuration. @@ -38,22 +38,43 @@ module Base # config:: Configuration for this Thor class. # def initialize(args=[], options={}, config={}) - args = Thor::Arguments.parse(self.class.arguments, args) - args.each { |key, value| send("#{key}=", value) } - parse_options = self.class.class_options + # The start method splits inbound arguments at the first argument + # that looks like an option (starts with - or --). It then calls + # new, passing in the two halves of the arguments Array as the + # first two parameters. + if options.is_a?(Array) task_options = config.delete(:task_options) # hook for start parse_options = parse_options.merge(task_options) if task_options array_options, hash_options = options, {} else + # Handle the case where the class was explicitly instantiated + # with pre-parsed options. array_options, hash_options = [], options end + # Let Thor::Options parse the options first, so it can remove + # declared options from the array. This will leave us with + # a list of arguments that weren't declared. opts = Thor::Options.new(parse_options, hash_options) self.options = opts.parse(array_options) + + # If unknown options are disallowed, make sure that none of the + # remaining arguments looks like an option. opts.check_unknown! if self.class.check_unknown_options?(config) + + # Add the remaining arguments from the options parser to the + # arguments passed in to initialize. Then remove any positional + # arguments declared using #argument (this is primarily used + # by Thor::Group). Tis will leave us with the remaining + # positional arguments. + thor_args = Thor::Arguments.new(self.class.arguments) + thor_args.parse(args + opts.remaining).each { |k,v| send("#{k}=", v) } + args = thor_args.remaining + + @args = args end class << self @@ -405,8 +426,8 @@ def public_task(*names) end end - def handle_no_task_error(task) #:nodoc: - if $thor_runner + def handle_no_task_error(task, has_namespace = $thor_runner) #:nodoc: + if has_namespace raise UndefinedTaskError, "Could not find task #{task.inspect} in #{namespace.inspect} namespace." else raise UndefinedTaskError, "Could not find task #{task.inspect}." @@ -506,6 +527,7 @@ def find_and_refresh_task(name) #:nodoc: # and file into baseclass. def inherited(klass) Thor::Base.register_klass_file(klass) + klass.instance_variable_set(:@no_tasks, false) end # Fire this callback whenever a method is added. Added methods are diff --git a/lib/bundler/vendor/thor/group.rb b/lib/bundler/vendor/thor/group.rb index 3dbab98afe8..e948b9aefdf 100644 --- a/lib/bundler/vendor/thor/group.rb +++ b/lib/bundler/vendor/thor/group.rb @@ -187,9 +187,9 @@ def get_options_from_invocations(group_options, base_options) #:nodoc: human_name = value.respond_to?(:classify) ? value.classify : value group_options[human_name] ||= [] - group_options[human_name] += klass.class_options.values.select do |option| - base_options[option.name.to_sym].nil? && option.group.nil? && - !group_options.values.flatten.any? { |i| i.name == option.name } + group_options[human_name] += klass.class_options.values.select do |class_option| + base_options[class_option.name.to_sym].nil? && class_option.group.nil? && + !group_options.values.flatten.any? { |i| i.name == class_option.name } end yield klass if block_given? @@ -220,10 +220,14 @@ def dispatch(task, given_args, given_opts, config) #:nodoc: args, opts = Thor::Options.split(given_args) opts = given_opts || opts + instance = new(args, opts, config) + yield instance if block_given? + args = instance.args + if task - new(args, opts, config).invoke_task(all_tasks[task]) + instance.invoke_task(all_tasks[task]) else - new(args, opts, config).invoke_all + instance.invoke_all end end diff --git a/lib/bundler/vendor/thor/invocation.rb b/lib/bundler/vendor/thor/invocation.rb index 6315dd42963..9c645472287 100644 --- a/lib/bundler/vendor/thor/invocation.rb +++ b/lib/bundler/vendor/thor/invocation.rb @@ -106,7 +106,9 @@ def invoke(name=nil, *args) raise "Expected Thor class, got #{klass}" unless klass <= Thor::Base args, opts, config = _parse_initialization_options(args, opts, config) - klass.send(:dispatch, task, args, opts, config) + klass.send(:dispatch, task, args, opts, config) do |instance| + instance.parent_options = options + end end # Invoke the given task if the given args. diff --git a/lib/bundler/vendor/thor/parser/arguments.rb b/lib/bundler/vendor/thor/parser/arguments.rb index 888ef692463..12db2b2348d 100644 --- a/lib/bundler/vendor/thor/parser/arguments.rb +++ b/lib/bundler/vendor/thor/parser/arguments.rb @@ -49,6 +49,10 @@ def parse(args) @assigns end + def remaining + @pile + end + private def no_or_skip?(arg) diff --git a/lib/bundler/vendor/thor/parser/options.rb b/lib/bundler/vendor/thor/parser/options.rb index 9b1d042d101..c6829c0bb54 100644 --- a/lib/bundler/vendor/thor/parser/options.rb +++ b/lib/bundler/vendor/thor/parser/options.rb @@ -38,7 +38,7 @@ def initialize(hash_options={}, defaults={}) @non_assigned_required.delete(hash_options[key]) end - @shorts, @switches, @unknown = {}, {}, [] + @shorts, @switches, @extra = {}, {}, [] options.each do |option| @switches[option.switch_name] = option @@ -49,14 +49,19 @@ def initialize(hash_options={}, defaults={}) end end + def remaining + @extra + end + def parse(args) @pile = args.dup while peek match, is_switch = current_is_switch? + shifted = shift if is_switch - case shift + case shifted when SHORT_SQ_RE unshift($1.split('').map { |f| "-#{f}" }) next @@ -71,9 +76,10 @@ def parse(args) option = switch_option(switch) @assigns[option.human_name] = parse_peek(switch, option) elsif match - @unknown << shift + @extra << shifted + @extra << shift while peek && peek !~ /^-/ else - shift + @extra << shifted end end @@ -85,9 +91,9 @@ def parse(args) end def check_unknown! - unless ARGV.include?("exec") || ARGV.include?("config") - raise UnknownArgumentError, "Unknown switches '#{@unknown.join(', ')}'" unless @unknown.empty? - end + # an unknown option starts with - or -- and has no more --'s afterward. + unknown = @extra.select { |str| str =~ /^--?(?:(?!--).)*$/ } + raise UnknownArgumentError, "Unknown switches '#{unknown.join(', ')}'" unless unknown.empty? end protected diff --git a/lib/bundler/vendor/thor/rake_compat.rb b/lib/bundler/vendor/thor/rake_compat.rb index 0d0757fddae..c86e840578d 100644 --- a/lib/bundler/vendor/thor/rake_compat.rb +++ b/lib/bundler/vendor/thor/rake_compat.rb @@ -1,4 +1,5 @@ require 'rake' +require 'rake/dsl_definition' class Thor # Adds a compatibility layer to your Thor classes which allows you to use @@ -16,6 +17,8 @@ class Thor # end # module RakeCompat + include Rake::DSL if defined?(Rake::DSL) + def self.rake_classes @rake_classes ||= [] end @@ -29,12 +32,12 @@ def self.included(base) end end -class Object #:nodoc: - alias :rake_task :task - alias :rake_namespace :namespace +# override task on (main), for compatibility with Rake 0.9 +self.instance_eval do + alias rake_namespace namespace - def task(*args, &block) - task = rake_task(*args, &block) + def task(*) + task = super if klass = Thor::RakeCompat.rake_classes.last non_namespaced_name = task.name.split(':').last @@ -43,7 +46,8 @@ def task(*args, &block) description << task.arg_names.map{ |n| n.to_s.upcase }.join(' ') description.strip! - klass.desc description, task.comment || non_namespaced_name + klass.desc description, Rake.application.last_description || non_namespaced_name + Rake.application.last_description = nil klass.send :define_method, non_namespaced_name do |*args| Rake::Task[task.name.to_sym].invoke(*args) end @@ -52,7 +56,7 @@ def task(*args, &block) task end - def namespace(name, &block) + def namespace(name) if klass = Thor::RakeCompat.rake_classes.last const_name = Thor::Util.camel_case(name.to_s).to_sym klass.const_set(const_name, Class.new(Thor)) @@ -60,7 +64,8 @@ def namespace(name, &block) Thor::RakeCompat.rake_classes << new_klass end - rake_namespace(name, &block) + super Thor::RakeCompat.rake_classes.pop end end + diff --git a/lib/bundler/vendor/thor/runner.rb b/lib/bundler/vendor/thor/runner.rb index 0d9e3c05e8b..18c63c438ec 100644 --- a/lib/bundler/vendor/thor/runner.rb +++ b/lib/bundler/vendor/thor/runner.rb @@ -17,6 +17,7 @@ def help(meth = nil) if meth && !self.respond_to?(meth) initialize_thorfiles(meth) klass, task = Thor::Util.find_class_and_task_by_namespace(meth) + self.class.handle_no_task_error(task, false) if klass.nil? klass.start(["-h", task].compact, :shell => self.shell) else super @@ -30,6 +31,7 @@ def method_missing(meth, *args) meth = meth.to_s initialize_thorfiles(meth) klass, task = Thor::Util.find_class_and_task_by_namespace(meth) + self.class.handle_no_task_error(task, false) if klass.nil? args.unshift(task) if task klass.start(args, :shell => self.shell) end diff --git a/lib/bundler/vendor/thor/shell.rb b/lib/bundler/vendor/thor/shell.rb index b52c9da2e0f..784fde95a34 100644 --- a/lib/bundler/vendor/thor/shell.rb +++ b/lib/bundler/vendor/thor/shell.rb @@ -8,7 +8,7 @@ module Base def self.shell @shell ||= if ENV['THOR_SHELL'] && ENV['THOR_SHELL'].size > 0 Thor::Shell.const_get(ENV['THOR_SHELL']) - elsif RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ + elsif ((RbConfig::CONFIG['host_os'] =~ /mswin|mingw/) && !(ENV['ANSICON'])) Thor::Shell::Basic else Thor::Shell::Color diff --git a/lib/bundler/vendor/thor/shell/basic.rb b/lib/bundler/vendor/thor/shell/basic.rb index c8411d3d3d3..a7c464ada39 100644 --- a/lib/bundler/vendor/thor/shell/basic.rb +++ b/lib/bundler/vendor/thor/shell/basic.rb @@ -5,10 +5,10 @@ module Shell class Basic attr_accessor :base, :padding - # Initialize base and padding to nil. + # Initialize base, mute and padding to nil. # def initialize #:nodoc: - @base, @padding = nil, 0 + @base, @mute, @padding = nil, false, 0 end # Mute everything that's inside given block diff --git a/lib/bundler/vendor/thor/task.rb b/lib/bundler/vendor/thor/task.rb index 6db3b60817b..f94d5b6b7fd 100644 --- a/lib/bundler/vendor/thor/task.rb +++ b/lib/bundler/vendor/thor/task.rb @@ -18,8 +18,15 @@ def hidden? # By default, a task invokes a method in the thor class. You can change this # implementation to create custom tasks. def run(instance, args=[]) - public_method?(instance) ? - instance.send(name, *args) : instance.class.handle_no_task_error(name) + if private_method?(instance) + instance.class.handle_no_task_error(name) + elsif public_method?(instance) + instance.send(name, *args) + elsif local_method?(instance, :method_missing) + instance.send(:method_missing, name.to_sym, *args) + else + instance.class.handle_no_task_error(name) + end rescue ArgumentError => e handle_argument_error?(instance, e, caller) ? instance.class.handle_argument_error(self, e) : (raise e) @@ -70,6 +77,15 @@ def public_method?(instance) #:nodoc: !(instance.public_methods & [name.to_s, name.to_sym]).empty? end + def private_method?(instance) + !(instance.private_methods & [name.to_s, name.to_sym]).empty? + end + + def local_method?(instance, name) + methods = instance.public_methods(false) + instance.private_methods(false) + instance.protected_methods(false) + !(methods & [name.to_s, name.to_sym]).empty? + end + def sans_backtrace(backtrace, caller) #:nodoc: saned = backtrace.reject { |frame| frame =~ FILE_REGEXP } saned -= caller diff --git a/lib/bundler/vendor/thor/version.rb b/lib/bundler/vendor/thor/version.rb index 7de92f164a8..4a0e37ad7f6 100644 --- a/lib/bundler/vendor/thor/version.rb +++ b/lib/bundler/vendor/thor/version.rb @@ -1,3 +1,3 @@ class Thor - VERSION = "0.14.6".freeze + VERSION = "0.15.0.rc2".freeze end From 73b04ed902aa0265f70ea8fc54b018de554674e0 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sat, 17 Sep 2011 18:55:42 -0700 Subject: [PATCH 29/32] Don't require Psych if Syck is loaded fixes #1239 --- lib/bundler.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/bundler.rb b/lib/bundler.rb index ba1cd5573ae..eb1ae751e44 100644 --- a/lib/bundler.rb +++ b/lib/bundler.rb @@ -3,7 +3,8 @@ require 'pathname' begin - require 'psych' + # Pull in Psych if we can, but not if Syck is already loaded + require 'psych' unless defined?(YAML) rescue LoadError end From 83dbe36e70f75c767bbadf25242c4659d5ecb042 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sat, 17 Sep 2011 19:28:56 -0700 Subject: [PATCH 30/32] Allow clearing --without groups fixes #1259 --- lib/bundler/cli.rb | 9 ++++----- lib/bundler/settings.rb | 5 ++--- spec/install/gems/groups_spec.rb | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index 8839c8c4307..7b5f63d9ce8 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -150,12 +150,11 @@ def check "Install using defaults tuned for deployment environments" def install(path = nil) opts = options.dup - opts[:without] ||= [] - if opts[:without].size == 1 - opts[:without] = opts[:without].map{|g| g.split(" ") } + if opts[:without] + opts[:without].map!{|g| g.split(" ") } opts[:without].flatten! + opts[:without].map!{|g| g.to_sym } end - opts[:without] = opts[:without].map{|g| g.to_sym } # Can't use Bundler.settings for this because settings needs gemfile.dirname ENV['BUNDLE_GEMFILE'] = File.expand_path(opts[:gemfile]) if opts[:gemfile] @@ -214,7 +213,7 @@ def install(path = nil) Bundler.settings[:bin] = opts["binstubs"] if opts[:binstubs] Bundler.settings[:no_prune] = true if opts["no-prune"] Bundler.settings[:disable_shared_gems] = Bundler.settings[:path] ? '1' : nil - Bundler.settings.without = opts[:without] unless opts[:without].empty? + Bundler.settings.without = opts[:without] Bundler.ui.be_quiet! if opts[:quiet] Installer.install(Bundler.root, Bundler.definition, opts) diff --git a/lib/bundler/settings.rb b/lib/bundler/settings.rb index c3209c3ad3e..a663eb8f79d 100644 --- a/lib/bundler/settings.rb +++ b/lib/bundler/settings.rb @@ -62,9 +62,7 @@ def pretty_values_for(exposed_key) end def without=(array) - unless array.empty? - self[:without] = array.join(":") - end + self[:without] = (array.empty? ? nil : array.join(":")) if array end def without @@ -95,6 +93,7 @@ def key_for(key) def set_key(key, value, hash, file) key = key_for(key) + puts key.inspect unless hash[key] == value hash[key] = value diff --git a/spec/install/gems/groups_spec.rb b/spec/install/gems/groups_spec.rb index 51865ab6217..af3cdab31f4 100644 --- a/spec/install/gems/groups_spec.rb +++ b/spec/install/gems/groups_spec.rb @@ -136,6 +136,20 @@ ENV["BUNDLE_WITHOUT"] = nil end + + it "clears without when passed an empty list" do + bundle :install, :without => "emo" + + bundle 'install --without ""' + should_be_installed "activesupport 2.3.5" + end + + it "doesn't clear without when nothing is passed" do + bundle :install, :without => "emo" + + bundle :install + should_not_be_installed "activesupport 2.3.5" + end end describe "with gems assigned to multiple groups" do From d9dd6edda2e34e9461f0be6e00006cfa3b2f52fc Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sat, 17 Sep 2011 19:37:58 -0700 Subject: [PATCH 31/32] Update --local docs to be accurate fixes #1244 --- man/bundle-install.ronn | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/man/bundle-install.ronn b/man/bundle-install.ronn index 3b2d5231fba..a5aec12fb64 100644 --- a/man/bundle-install.ronn +++ b/man/bundle-install.ronn @@ -54,9 +54,9 @@ update process below under [CONSERVATIVE UPDATING][]. * `--local`: Do not attempt to connect to `rubygems.org`, instead using just - the gems located in `vendor/cache`. Note that if a more - appropriate platform-specific gem exists on `rubygems.org`, - this will bypass the normal lookup. + the gems already present in Rubygems' cache or in `vendor/cache`. + Note that if a more appropriate platform-specific gem exists on + `rubygems.org`, it will not be found. * `--deployment`: Switches bundler's defaults into [deployment mode][DEPLOYMENT MODE]. From 3920fef3fbcefad7b74f310c470468f6195d3eb0 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sun, 18 Sep 2011 18:57:23 -0700 Subject: [PATCH 32/32] Version 1.0.20.rc --- CHANGELOG.md | 16 ++++++++++++++++ lib/bundler/version.rb | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 281d76e06b0..03efa56d0c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +## 1.0.20.rc (September 18, 2011) + +Features: + + - Rescue interrupts to `bundle` while loading bundler.rb (#1395) + - Pass git directory paths instead of cd'ing (@tigris, #1213) + - Allow clearing without groups by passing `--without ''` (#1259) + +Bugfixes: + + - Manually sort requirements in the lockfile (#1375) + - Remove several warnings generated by ruby -w (@stephencelis) + - Handle trailing slashes on names passed to `gem` (#1372) + - Name modules for gems like 'test-foo_bar' correctly (#1303) + - Don't require Psych if Syck is already loaded (#1239) + ## 1.0.19.rc (September 13, 2011) Features: diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb index f09ba8d53a3..cef3a48a434 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.0.19.rc" unless defined?(::Bundler::VERSION) + VERSION = "1.0.20.rc" unless defined?(::Bundler::VERSION) end