Browse files

Merge v1.0.20.rc from branch '1-0-stable'

Conflicts:
	CHANGELOG.md
	lib/bundler/cli.rb
	lib/bundler/installer.rb
	lib/bundler/version.rb
  • Loading branch information...
2 parents 8497f4b + 3920fef commit ef4c631bbd4ee849b3021220de060f6c2cd1d972 @indirect indirect committed Sep 19, 2011
View
38 CHANGELOG.md
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
## 1.1.pre.9
Bugfixes:
@@ -119,6 +120,39 @@ Removed:
- Removed bundle install --disable-shared-gems
## 1.0.18 (Aug 16, 2011)
+=======
+## 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:
+
+ - 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)
+>>>>>>> 1-0-stable
Bugfixes:
@@ -133,14 +167,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:
View
4 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
@@ -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'`
View
20 bin/bundle
@@ -1,15 +1,15 @@
#!/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
+ err = "Please remove Bundler 0.8 versions."
+ err << "This can be done by running `gem cleanup bundler`."
+ abort(err)
+ end
+ end
+ require 'bundler/cli'
Bundler::CLI.start
rescue Bundler::BundlerError => e
Bundler.ui.error e.message
View
3 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"]
View
9 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
@@ -39,14 +40,15 @@ 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
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
@@ -115,8 +117,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
View
16 lib/bundler/cli.rb
@@ -158,12 +158,11 @@ def check
"Run bundle clean automatically after clean"
def install
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]
@@ -206,8 +205,8 @@ def install
Bundler.settings[:path] ||= "bundle" if opts[:standalone]
Bundler.settings[:bin] = opts["binstubs"] if opts[:binstubs]
Bundler.settings[:no_prune] = true if opts["no-prune"]
- Bundler.settings[:disable_shared_gems] = '1' if Bundler.settings[:path]
- Bundler.settings.without = opts[:without] unless opts[:without].empty?
+ Bundler.settings[:disable_shared_gems] = Bundler.settings[:path] ? '1' : nil
+ Bundler.settings.without = opts[:without]
Bundler.ui.be_quiet! if opts[:quiet]
Bundler::Fetcher.disable_endpoint = opts["full-index"]
@@ -536,9 +535,10 @@ 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 =~ /-/
+ 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('::')
FileUtils.mkdir_p(File.join(target, 'lib', name))
git_user_name = `git config user.name`.chomp
View
8 lib/bundler/definition.rb
@@ -197,17 +197,17 @@ 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]
# TODO: Warn here if we got here.
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
View
9 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
View
11 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
View
41 lib/bundler/installer.rb
@@ -53,21 +53,7 @@ def run(options)
# the gem.
Installer.post_install_messages = {}
specs.each do |spec|
- Bundler::Fetcher.fetch(spec) if spec.source.is_a?(Bundler::Source::Rubygems)
-
- # 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)
+ install_gem_from_spec(spec)
end
lock
@@ -76,6 +62,31 @@ 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.
+ Bundler::Fetcher.fetch(spec) if spec.source.is_a?(Bundler::Source::Rubygems)
+
+ # 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 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"
+ 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__))
View
4 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
@@ -107,7 +108,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
@@ -135,6 +136,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
View
1 lib/bundler/rubygems_integration.rb
@@ -185,6 +185,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
View
5 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
View
42 lib/bundler/source.rb
@@ -361,7 +361,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"
@@ -481,6 +481,7 @@ def initialize(options)
@revision = options["revision"]
@submodules = options["submodules"]
@update = false
+ @installed = nil
end
def self.from_lock(options)
@@ -616,30 +617,29 @@ def uri_hash
Digest::SHA1.hexdigest(input)
end
- # Escape the URI for git commands
- def uri_escaped
+ # Escape an argument for shell commands.
+ def escape(arg)
if Bundler::WINDOWS
# Windows quoting requires double quotes only, with double quotes
# inside the string escaped by being doubled.
- '"' + uri.gsub('"') {|s| '""'} + '"'
+ '"' + arg.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.
- "'" + uri.gsub("'") {|s| "'\\''"} + "'"
+ "'" + arg.to_s.gsub("'") {|s| "'\\''"} + "'"
end
end
def cache
if cached?
return if has_revision_cached?
Bundler.ui.info "Updating #{uri}"
- in_cache do
- git %|fetch --force --quiet --tags #{uri_escaped} "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)
- git %|clone #{uri_escaped} "#{cache_path}" --bare --no-hardlinks|
+ git %|clone #{escape uri} "#{cache_path}" --bare --no-hardlinks|
end
end
@@ -650,20 +650,20 @@ 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}| }
+ cache unless cached?
+ git %|--git-dir #{escape cache_path} cat-file -e #{@revision}|
true
rescue GitError
false
@@ -676,7 +676,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
@@ -686,11 +687,6 @@ def revision
def cached?
cache_path.exist?
end
-
- def in_cache(&blk)
- cache unless cached?
- Dir.chdir(cache_path, &blk)
- end
end
end
View
70 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<Symbol>:: name of the defaut task
+ # meth<Symbol>:: 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,43 +311,52 @@ 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
nil
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)
View
2 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)
View
2 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"
View
34 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<Hash>:: 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
View
14 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
View
4 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.
View
4 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)
View
20 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
View
21 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,15 +56,16 @@ 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))
new_klass = klass.const_get(const_name)
Thor::RakeCompat.rake_classes << new_klass
end
- rake_namespace(name, &block)
+ super
Thor::RakeCompat.rake_classes.pop
end
end
+
View
2 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
View
2 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
View
4 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
View
20 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
View
2 lib/bundler/vendor/thor/version.rb
@@ -1,3 +1,3 @@
class Thor
- VERSION = "0.14.6".freeze
+ VERSION = "0.15.0.rc2".freeze
end
View
6 man/bundle-install.ronn
@@ -55,9 +55,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].
View
4 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.
View
7 spec/other/gem_helper_spec.rb → 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
View
14 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
View
63 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
@@ -671,36 +670,70 @@
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
File.read(bundled_app("Gemfile.lock")).should_not match("\r\n")
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
View
3 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
View
19 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
View
7 spec/support/builders.rb
@@ -174,7 +174,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

0 comments on commit ef4c631

Please sign in to comment.