aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib/rails/vendor
diff options
context:
space:
mode:
Diffstat (limited to 'railties/lib/rails/vendor')
-rw-r--r--railties/lib/rails/vendor/bundler/LICENSE20
-rw-r--r--railties/lib/rails/vendor/bundler/README.markdown162
-rw-r--r--railties/lib/rails/vendor/bundler/Rakefile57
-rw-r--r--railties/lib/rails/vendor/bundler/lib/bundler.rb34
-rw-r--r--railties/lib/rails/vendor/bundler/lib/bundler/cli.rb44
-rw-r--r--railties/lib/rails/vendor/bundler/lib/bundler/commands/bundle_command.rb31
-rw-r--r--railties/lib/rails/vendor/bundler/lib/bundler/commands/exec_command.rb31
-rw-r--r--railties/lib/rails/vendor/bundler/lib/bundler/dependency.rb56
-rw-r--r--railties/lib/rails/vendor/bundler/lib/bundler/dsl.rb109
-rw-r--r--railties/lib/rails/vendor/bundler/lib/bundler/environment.rb111
-rw-r--r--railties/lib/rails/vendor/bundler/lib/bundler/finder.rb51
-rw-r--r--railties/lib/rails/vendor/bundler/lib/bundler/gem_bundle.rb11
-rw-r--r--railties/lib/rails/vendor/bundler/lib/bundler/gem_ext.rb25
-rw-r--r--railties/lib/rails/vendor/bundler/lib/bundler/repository.rb151
-rw-r--r--railties/lib/rails/vendor/bundler/lib/bundler/repository/directory_repository.rb46
-rw-r--r--railties/lib/rails/vendor/bundler/lib/bundler/repository/gem_repository.rb108
-rw-r--r--railties/lib/rails/vendor/bundler/lib/bundler/resolver.rb189
-rw-r--r--railties/lib/rails/vendor/bundler/lib/bundler/runtime.rb2
-rw-r--r--railties/lib/rails/vendor/bundler/lib/bundler/source.rb150
-rw-r--r--railties/lib/rails/vendor/bundler/lib/bundler/templates/app_script.erb3
-rw-r--r--railties/lib/rails/vendor/bundler/lib/bundler/templates/environment.erb127
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/CHANGELOG.rdoc77
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/LICENSE20
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/README.rdoc234
-rwxr-xr-xrailties/lib/rails/vendor/thor-0.11.6/bin/rake2thor87
-rwxr-xr-xrailties/lib/rails/vendor/thor-0.11.6/bin/thor7
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor.rb243
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions.rb273
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions/create_file.rb102
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions/directory.rb87
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions/empty_directory.rb133
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions/file_manipulation.rb219
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions/inject_into_file.rb101
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/base.rb517
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/core_ext/hash_with_indifferent_access.rb75
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/core_ext/ordered_hash.rb100
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/error.rb27
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/group.rb263
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/invocation.rb178
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/parser.rb4
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/parser/argument.rb67
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/parser/arguments.rb145
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/parser/option.rb132
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/parser/options.rb142
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/rake_compat.rb67
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/runner.rb299
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/shell.rb72
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/shell/basic.rb219
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/shell/color.rb108
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/task.rb122
-rw-r--r--railties/lib/rails/vendor/thor-0.11.6/lib/thor/util.rb251
51 files changed, 5889 insertions, 0 deletions
diff --git a/railties/lib/rails/vendor/bundler/LICENSE b/railties/lib/rails/vendor/bundler/LICENSE
new file mode 100644
index 0000000000..41decca113
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2009 Engine Yard
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/railties/lib/rails/vendor/bundler/README.markdown b/railties/lib/rails/vendor/bundler/README.markdown
new file mode 100644
index 0000000000..26863e96f2
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/README.markdown
@@ -0,0 +1,162 @@
+## Bundler : A gem to bundle gems
+
+ Github: http://github.com/wycats/bundler
+ Mailing list: http://groups.google.com/group/ruby-bundler
+ IRC: #carlhuda on freenode
+
+## Intro
+
+Bundler is a tool that manages gem dependencies for your ruby application. It
+takes a gem manifest file and is able to fetch, download, and install the gems
+and all child dependencies specified in this manifest. It can manage any update
+to the gem manifest file and update the bundled gems accordingly. It also lets
+you run any ruby code in context of the bundled gem environment.
+
+## Disclaimer
+
+This project is under rapid development. It is usable today, but there will be
+many changes in the near future, including to the Gemfile DSL. We will bump up
+versions with changes though. We greatly appreciate feedback.
+
+## Installation
+
+Bundler has no dependencies. Just clone the git repository and install the gem
+with the following rake task:
+
+ rake install
+
+## Usage
+
+Bundler requires a gem manifest file to be created. This should be a file named
+`Gemfile` located in the root directory of your application. After the manifest
+has been created, in your shell, cd into your application's directory and run
+`gem bundle`. This will start the bundling process.
+
+### Manifest file
+
+This is where you specify all of your application's dependencies. By default
+this should be in a file named `Gemfile` located in your application's root
+directory. The following is an example of a potential `Gemfile`. For more
+information, please refer to Bundler::ManifestBuilder.
+
+ # Specify a dependency on rails. When the bundler downloads gems,
+ # it will download rails as well as all of rails' dependencies (such as
+ # activerecord, actionpack, etc...)
+ #
+ # At least one dependency must be specified
+ gem "rails"
+
+ # Specify a dependency on rack v.1.0.0. The version is optional. If present,
+ # it can be specified the same way as with rubygems' #gem method.
+ gem "rack", "1.0.0"
+
+ # Specify a dependency rspec, but only activate that gem in the "testing"
+ # environment (read more about environments later). :except is also a valid
+ # option to specify environment restrictions.
+ gem "rspec", :only => :testing
+
+ # Add http://gems.github.com as a source that the bundler will use
+ # to find gems listed in the manifest. By default,
+ # http://gems.rubyforge.org is already added to the list.
+ #
+ # This is an optional setting.
+ source "http://gems.github.com"
+
+ # Specify where the bundled gems should be stashed. This directory will
+ # be a gem repository where all gems are downloaded to and installed to.
+ #
+ # This is an optional setting.
+ # The default is: vendor/gems
+ bundle_path "my/bundled/gems"
+
+ # Specify where gem executables should be copied to.
+ #
+ # This is an optional setting.
+ # The default is: bin
+ bin_path "my/executables"
+
+ # Specify that rubygems should be completely disabled. This means that it
+ # will be impossible to require it and that available gems will be
+ # limited exclusively to gems that have been bundled.
+ #
+ # The default is to automatically require rubygems. There is also a
+ # `disable_system_gems` option that will limit available rubygems to
+ # the ones that have been bundled.
+ disable_rubygems
+
+### Running Bundler
+
+Once a manifest file has been created, the only thing that needs to be done
+is to run the `gem bundle` command anywhere in your application. The script
+will load the manifest file, resole all the dependencies, download all
+needed gems, and install them into the specified directory.
+
+Every time an update is made to the manifest file, run `gem bundle` again to
+get the changes installed. This will only check the remote sources if your
+currently installed gems do not satisfy the `Gemfile`. If you want to force
+checking for updates on the remote sources, use the `--update` option.
+
+### Running your application
+
+The easiest way to run your application is to start it with an executable
+copied to the specified bin directory (by default, simply bin). For example,
+if the application in question is a rack app, start it with `bin/rackup`.
+This will automatically set the gem environment correctly.
+
+Another way to run arbitrary ruby code in context of the bundled gems is to
+run it with the `gem exec` command. For example:
+
+ gem exec ruby my_ruby_script.rb
+
+Yet another way is to manually require the environment file first. This is
+located in `[bundle_path]/environments/default.rb`. For example:
+
+ ruby -r vendor/gems/environment.rb my_ruby_script.rb
+
+### Using Bundler with Rails today
+
+It should be possible to use Bundler with Rails today. Here are the steps
+to follow.
+
+* In your rails app, create a Gemfile and specify the gems that your
+ application depends on. Make sure to specify rails as well:
+
+ gem "rails", "2.1.2"
+ gem "will_paginate"
+
+ # Optionally, you can disable system gems all together and only
+ # use bundled gems.
+ disable_system_gems
+
+* Run `gem bundle`
+
+* You can now use rails if you prepend `gem exec` to every call to `script/*`
+ but that isn't fun.
+
+* At the top of `config/boot.rb`, add the following line:
+
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'vendor', 'gems', 'environment'))
+
+In theory, this should be enough to get going.
+
+## To require rubygems or not
+
+Ideally, no gem would assume the presence of rubygems at runtime. Rubygems provides
+enough features so that this isn't necessary. However, there are a number of gems
+that require specific rubygem features.
+
+If the `disable_rubygems` option is used, Bundler will stub out the most common
+of these features, but it is possible that things will not go as intended quite
+yet. So, if you are brave, try your code without rubygems at runtime.
+
+## Known Issues
+
+* When a gem points to a git repository, the git repository will be cloned
+ every time Bundler does a gem dependency resolve.
+
+## Reporting bugs
+
+Please report all bugs on the github issue tracker for the project located
+at:
+
+ http://github.com/wycats/bundler/issues/ \ No newline at end of file
diff --git a/railties/lib/rails/vendor/bundler/Rakefile b/railties/lib/rails/vendor/bundler/Rakefile
new file mode 100644
index 0000000000..dc4c3d6d46
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/Rakefile
@@ -0,0 +1,57 @@
+require 'rubygems' unless ENV['NO_RUBYGEMS']
+require 'rubygems/specification'
+require 'date'
+
+spec = Gem::Specification.new do |s|
+ s.name = "bundler"
+ s.version = "0.5.0.pre"
+ s.author = "Yehuda Katz"
+ s.email = "wycats@gmail.com"
+ s.homepage = "http://github.com/wycats/bundler"
+ s.description = s.summary = "An easy way to vendor gem dependencies"
+
+ s.platform = Gem::Platform::RUBY
+ s.has_rdoc = true
+ s.extra_rdoc_files = ["README.markdown", "LICENSE"]
+
+ s.required_rubygems_version = ">= 1.3.5"
+
+ s.require_path = 'lib'
+ s.files = %w(LICENSE README.markdown Rakefile) + Dir.glob("lib/**/*")
+end
+
+task :default => :spec
+
+begin
+ require 'spec/rake/spectask'
+rescue LoadError
+ task(:spec) { $stderr.puts '`gem install rspec` to run specs' }
+else
+ desc "Run specs"
+ Spec::Rake::SpecTask.new do |t|
+ t.spec_files = FileList['spec/**/*_spec.rb'] - FileList['spec/fixtures/**/*_spec.rb']
+ t.spec_opts = %w(-fs --color)
+ end
+end
+
+begin
+ require 'rake/gempackagetask'
+rescue LoadError
+ task(:gem) { $stderr.puts '`gem install rake` to package gems' }
+else
+ Rake::GemPackageTask.new(spec) do |pkg|
+ pkg.gem_spec = spec
+ end
+end
+
+desc "install the gem locally"
+task :install => [:package] do
+ sh %{gem install pkg/#{spec.name}-#{spec.version}}
+end
+
+desc "create a gemspec file"
+task :make_spec do
+ File.open("#{spec.name}.gemspec", "w") do |file|
+ file.puts spec.to_ruby
+ end
+end
diff --git a/railties/lib/rails/vendor/bundler/lib/bundler.rb b/railties/lib/rails/vendor/bundler/lib/bundler.rb
new file mode 100644
index 0000000000..1ede3517dd
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/lib/bundler.rb
@@ -0,0 +1,34 @@
+require 'pathname'
+require 'logger'
+require 'set'
+require 'erb'
+# Required elements of rubygems
+require "rubygems/remote_fetcher"
+require "rubygems/installer"
+
+require "bundler/gem_bundle"
+require "bundler/source"
+require "bundler/finder"
+require "bundler/gem_ext"
+require "bundler/resolver"
+require "bundler/environment"
+require "bundler/dsl"
+require "bundler/cli"
+require "bundler/repository"
+require "bundler/dependency"
+
+module Bundler
+ VERSION = "0.5.0"
+
+ class << self
+ attr_writer :logger
+
+ def logger
+ @logger ||= begin
+ logger = Logger.new(STDOUT, Logger::INFO)
+ logger.formatter = proc {|_,_,_,msg| "#{msg}\n" }
+ logger
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails/vendor/bundler/lib/bundler/cli.rb b/railties/lib/rails/vendor/bundler/lib/bundler/cli.rb
new file mode 100644
index 0000000000..df9181fbc4
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/lib/bundler/cli.rb
@@ -0,0 +1,44 @@
+require "optparse"
+
+module Bundler
+ class CLI
+ def self.run(command, options = {})
+ new(options).run(command)
+ rescue DefaultManifestNotFound => e
+ Bundler.logger.error "Could not find a Gemfile to use"
+ exit 2
+ rescue InvalidEnvironmentName => e
+ Bundler.logger.error "Gemfile error: #{e.message}"
+ exit
+ rescue InvalidRepository => e
+ Bundler.logger.error e.message
+ exit
+ rescue VersionConflict => e
+ Bundler.logger.error e.message
+ exit
+ rescue GemNotFound => e
+ Bundler.logger.error e.message
+ exit
+ end
+
+ def initialize(options)
+ @options = options
+ @manifest = Bundler::Environment.load(@options[:manifest])
+ end
+
+ def bundle
+ @manifest.install(@options[:update])
+ end
+
+ def exec
+ @manifest.setup_environment
+ # w0t?
+ super(*@options[:args])
+ end
+
+ def run(command)
+ send(command)
+ end
+
+ end
+end
diff --git a/railties/lib/rails/vendor/bundler/lib/bundler/commands/bundle_command.rb b/railties/lib/rails/vendor/bundler/lib/bundler/commands/bundle_command.rb
new file mode 100644
index 0000000000..a1f9590f75
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/lib/bundler/commands/bundle_command.rb
@@ -0,0 +1,31 @@
+class Gem::Commands::BundleCommand < Gem::Command
+
+ def initialize
+ super('bundle', 'Create a gem bundle based on your Gemfile', {:manifest => nil, :update => false})
+
+ add_option('-m', '--manifest MANIFEST', "Specify the path to the manifest file") do |manifest, options|
+ options[:manifest] = manifest
+ end
+
+ add_option('-u', '--update', "Force a remote check for newer gems") do
+ options[:update] = true
+ end
+ end
+
+ def usage
+ "#{program_name}"
+ end
+
+ def description # :nodoc:
+ <<-EOF
+Bundle stuff
+ EOF
+ end
+
+ def execute
+ # Prevent the bundler from getting required unless it is actually being used
+ require 'bundler'
+ Bundler::CLI.run(:bundle, options)
+ end
+
+end \ No newline at end of file
diff --git a/railties/lib/rails/vendor/bundler/lib/bundler/commands/exec_command.rb b/railties/lib/rails/vendor/bundler/lib/bundler/commands/exec_command.rb
new file mode 100644
index 0000000000..228aa60619
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/lib/bundler/commands/exec_command.rb
@@ -0,0 +1,31 @@
+class Gem::Commands::ExecCommand < Gem::Command
+
+ def initialize
+ super('exec', 'Run a command in context of a gem bundle', {:manifest => nil})
+
+ add_option('-m', '--manifest MANIFEST', "Specify the path to the manifest file") do |manifest, options|
+ options[:manifest] = manifest
+ end
+ end
+
+ def usage
+ "#{program_name} COMMAND"
+ end
+
+ def arguments # :nodoc:
+ "COMMAND command to run in context of the gem bundle"
+ end
+
+ def description # :nodoc:
+ <<-EOF.gsub(' ', '')
+ Run in context of a bundle
+ EOF
+ end
+
+ def execute
+ # Prevent the bundler from getting required unless it is actually being used
+ require 'bundler'
+ Bundler::CLI.run(:exec, options)
+ end
+
+end \ No newline at end of file
diff --git a/railties/lib/rails/vendor/bundler/lib/bundler/dependency.rb b/railties/lib/rails/vendor/bundler/lib/bundler/dependency.rb
new file mode 100644
index 0000000000..b627b58662
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/lib/bundler/dependency.rb
@@ -0,0 +1,56 @@
+module Bundler
+ class InvalidEnvironmentName < StandardError; end
+
+ class Dependency
+ attr_reader :name, :version, :require_as, :only, :except
+
+ def initialize(name, options = {}, &block)
+ options.each do |k, v|
+ options[k.to_s] = v
+ end
+
+ @name = name
+ @version = options["version"] || ">= 0"
+ @require_as = Array(options["require_as"] || name)
+ @only = options["only"]
+ @except = options["except"]
+ @block = block
+
+ if (@only && @only.include?("rubygems")) || (@except && @except.include?("rubygems"))
+ raise InvalidEnvironmentName, "'rubygems' is not a valid environment name"
+ end
+ end
+
+ def in?(environment)
+ environment = environment.to_s
+
+ return false unless !@only || @only.include?(environment)
+ return false if @except && @except.include?(environment)
+ true
+ end
+
+ def to_s
+ to_gem_dependency.to_s
+ end
+
+ def require(environment)
+ return unless in?(environment)
+
+ @require_as.each do |file|
+ super(file)
+ end
+
+ @block.call if @block
+ end
+
+ def to_gem_dependency
+ @gem_dep ||= Gem::Dependency.new(name, version)
+ end
+
+ def ==(o)
+ [name, version, require_as, only, except] ==
+ [o.name, o.version, o.require_as, o.only, o.except]
+ end
+
+ end
+end
diff --git a/railties/lib/rails/vendor/bundler/lib/bundler/dsl.rb b/railties/lib/rails/vendor/bundler/lib/bundler/dsl.rb
new file mode 100644
index 0000000000..d9a86ee1fd
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/lib/bundler/dsl.rb
@@ -0,0 +1,109 @@
+module Bundler
+ class ManifestFileNotFound < StandardError; end
+
+ class Dsl
+ def initialize(environment)
+ @environment = environment
+ @sources = Hash.new { |h,k| h[k] = {} }
+ end
+
+ def bundle_path(path)
+ path = Pathname.new(path)
+ @environment.gem_path = (path.relative? ?
+ @environment.root.join(path) : path).expand_path
+ end
+
+ def bin_path(path)
+ path = Pathname.new(path)
+ @environment.bindir = (path.relative? ?
+ @environment.root.join(path) : path).expand_path
+ end
+
+ def disable_rubygems
+ @environment.rubygems = false
+ end
+
+ def disable_system_gems
+ @environment.system_gems = false
+ end
+
+ def source(source)
+ source = GemSource.new(:uri => source)
+ unless @environment.sources.include?(source)
+ @environment.add_source(source)
+ end
+ end
+
+ def only(env)
+ old, @only = @only, _combine_onlys(env)
+ yield
+ @only = old
+ end
+
+ def except(env)
+ old, @except = @except, _combine_excepts(env)
+ yield
+ @except = old
+ end
+
+ def clear_sources
+ @environment.clear_sources
+ end
+
+ def gem(name, *args)
+ options = args.last.is_a?(Hash) ? args.pop : {}
+ version = args.last
+
+ options[:only] = _combine_onlys(options[:only] || options["only"])
+ options[:except] = _combine_excepts(options[:except] || options["except"])
+
+ dep = Dependency.new(name, options.merge(:version => version))
+
+ # OMG REFACTORZ. KTHX
+ if vendored_at = options[:vendored_at]
+ vendored_at = Pathname.new(vendored_at)
+ vendored_at = @environment.filename.dirname.join(vendored_at) if vendored_at.relative?
+
+ @sources[:directory][vendored_at.to_s] ||= begin
+ source = DirectorySource.new(
+ :name => name,
+ :version => version,
+ :location => vendored_at
+ )
+ @environment.add_priority_source(source)
+ true
+ end
+ elsif git = options[:git]
+ @sources[:git][git] ||= begin
+ source = GitSource.new(
+ :name => name,
+ :version => version,
+ :uri => git,
+ :ref => options[:commit] || options[:tag],
+ :branch => options[:branch]
+ )
+ @environment.add_priority_source(source)
+ true
+ end
+ end
+
+ @environment.dependencies << dep
+ end
+
+ private
+
+ def _combine_onlys(only)
+ return @only unless only
+ only = [only].flatten.compact.uniq.map { |o| o.to_s }
+ only &= @only if @only
+ only
+ end
+
+ def _combine_excepts(except)
+ return @except unless except
+ except = [except].flatten.compact.uniq.map { |o| o.to_s }
+ except |= @except if @except
+ except
+ end
+ end
+end
diff --git a/railties/lib/rails/vendor/bundler/lib/bundler/environment.rb b/railties/lib/rails/vendor/bundler/lib/bundler/environment.rb
new file mode 100644
index 0000000000..f07a9e2c6f
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/lib/bundler/environment.rb
@@ -0,0 +1,111 @@
+require "rubygems/source_index"
+
+module Bundler
+ class DefaultManifestNotFound < StandardError; end
+
+ class Environment
+ attr_reader :filename, :dependencies
+ attr_accessor :rubygems, :system_gems, :gem_path, :bindir
+
+ def self.load(gemfile = nil)
+ gemfile = gemfile ? Pathname.new(gemfile) : default_manifest_file
+
+ unless gemfile.file?
+ raise ManifestFileNotFound, "#{filename.inspect} does not exist"
+ end
+
+ new(gemfile)
+ end
+
+ def self.default_manifest_file
+ current = Pathname.new(Dir.pwd)
+
+ until current.root?
+ filename = current.join("Gemfile")
+ return filename if filename.exist?
+ current = current.parent
+ end
+
+ raise DefaultManifestNotFound
+ end
+
+ def initialize(filename) #, sources, dependencies, bindir, path, rubygems, system_gems)
+ @filename = filename
+ @default_sources = [GemSource.new(:uri => "http://gems.rubyforge.org")]
+ @sources = []
+ @priority_sources = []
+ @dependencies = []
+ @rubygems = true
+ @system_gems = true
+
+ # Evaluate the Gemfile
+ builder = Dsl.new(self)
+ builder.instance_eval(File.read(filename))
+ end
+
+ def install(update = false)
+ begin
+ tmp_path = filename.dirname.join(".tmp")
+ FileUtils.mkdir_p(tmp_path)
+ sources.each { |s| s.tmp_path = tmp_path }
+ repository.install(gem_dependencies, sources,
+ :rubygems => rubygems,
+ :system_gems => system_gems,
+ :manifest => filename,
+ :update => update
+ )
+ ensure
+ FileUtils.rm_rf(tmp_path)
+ end
+ Bundler.logger.info "Done."
+ end
+
+ def setup_environment
+ unless system_gems
+ ENV["GEM_HOME"] = gem_path
+ ENV["GEM_PATH"] = gem_path
+ end
+ ENV["PATH"] = "#{bindir}:#{ENV["PATH"]}"
+ ENV["RUBYOPT"] = "-r#{gem_path}/environment #{ENV["RUBYOPT"]}"
+ end
+
+ def root
+ filename.parent
+ end
+
+ def gem_path
+ @gem_path ||= root.join("vendor", "gems")
+ end
+
+ def bindir
+ @bindir ||= root.join("bin")
+ end
+
+ def sources
+ @priority_sources + @sources + @default_sources
+ end
+
+ def add_source(source)
+ @sources << source
+ end
+
+ def add_priority_source(source)
+ @priority_sources << source
+ end
+
+ def clear_sources
+ @sources.clear
+ @default_sources.clear
+ end
+
+ private
+
+ def repository
+ @repository ||= Repository.new(gem_path, bindir)
+ end
+
+ def gem_dependencies
+ @gem_dependencies ||= dependencies.map { |d| d.to_gem_dependency }
+ end
+ end
+end
diff --git a/railties/lib/rails/vendor/bundler/lib/bundler/finder.rb b/railties/lib/rails/vendor/bundler/lib/bundler/finder.rb
new file mode 100644
index 0000000000..b77ca65709
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/lib/bundler/finder.rb
@@ -0,0 +1,51 @@
+module Bundler
+ # Finder behaves like a rubygems source index in that it responds
+ # to #search. It also resolves a list of dependencies finding the
+ # best possible configuration of gems that satisifes all requirements
+ # without causing any gem activation errors.
+ class Finder
+
+ # Takes an array of gem sources and fetches the full index of
+ # gems from each one. It then combines the indexes together keeping
+ # track of the original source so that any resolved gem can be
+ # fetched from the correct source.
+ #
+ # ==== Parameters
+ # *sources<String>:: URI pointing to the gem repository
+ def initialize(*sources)
+ @cache = {}
+ @index = {}
+ @sources = sources
+ end
+
+ # Searches for a gem that matches the dependency
+ #
+ # ==== Parameters
+ # dependency<Gem::Dependency>:: The gem dependency to search for
+ #
+ # ==== Returns
+ # [Gem::Specification]:: A collection of gem specifications
+ # matching the search
+ def search(dependency)
+ @cache[dependency.hash] ||= begin
+ find_by_name(dependency.name).select do |spec|
+ dependency =~ spec
+ end.sort_by {|s| s.version }
+ end
+ end
+
+ private
+
+ def find_by_name(name)
+ matches = @index[name] ||= begin
+ versions = {}
+ @sources.reverse_each do |source|
+ versions.merge! source.specs[name] || {}
+ end
+ versions
+ end
+ matches.values
+ end
+
+ end
+end \ No newline at end of file
diff --git a/railties/lib/rails/vendor/bundler/lib/bundler/gem_bundle.rb b/railties/lib/rails/vendor/bundler/lib/bundler/gem_bundle.rb
new file mode 100644
index 0000000000..80d7710683
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/lib/bundler/gem_bundle.rb
@@ -0,0 +1,11 @@
+module Bundler
+ class GemBundle < Array
+ def download(repository)
+ sort_by {|s| s.full_name.downcase }.each do |spec|
+ spec.source.download(spec, repository)
+ end
+
+ self
+ end
+ end
+end \ No newline at end of file
diff --git a/railties/lib/rails/vendor/bundler/lib/bundler/gem_ext.rb b/railties/lib/rails/vendor/bundler/lib/bundler/gem_ext.rb
new file mode 100644
index 0000000000..155ad04c7e
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/lib/bundler/gem_ext.rb
@@ -0,0 +1,25 @@
+module Gem
+ class Installer
+ def app_script_text(bin_file_name)
+ path = @gem_home
+ template = File.read(File.join(File.dirname(__FILE__), "templates", "app_script.erb"))
+ erb = ERB.new(template, nil, '-')
+ erb.result(binding)
+ end
+ end
+
+ class Specification
+ attr_accessor :source
+ attr_accessor :location
+
+ # Hack to fix github's strange marshal file
+ def specification_version
+ @specification_version && @specification_version.to_i
+ end
+
+ alias full_gem_path_without_location full_gem_path
+ def full_gem_path
+ @location ? @location : full_gem_path_without_location
+ end
+ end
+end
diff --git a/railties/lib/rails/vendor/bundler/lib/bundler/repository.rb b/railties/lib/rails/vendor/bundler/lib/bundler/repository.rb
new file mode 100644
index 0000000000..1a1dc7497d
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/lib/bundler/repository.rb
@@ -0,0 +1,151 @@
+require "bundler/repository/gem_repository"
+require "bundler/repository/directory_repository"
+
+module Bundler
+ class InvalidRepository < StandardError ; end
+
+ class Repository
+ attr_reader :path
+
+ def initialize(path, bindir)
+ FileUtils.mkdir_p(path)
+
+ @path = Pathname.new(path)
+ @bindir = Pathname.new(bindir)
+
+ @repos = {
+ :gem => Gems.new(@path, @bindir),
+ :directory => Directory.new(@path.join("dirs"), @bindir)
+ }
+ end
+
+ def install(dependencies, sources, options = {})
+ if options[:update] || !satisfies?(dependencies)
+ fetch(dependencies, sources)
+ expand(options)
+ else
+ # Remove any gems that are still around if the Gemfile changed without
+ # requiring new gems to be download (e.g. a line in the Gemfile was
+ # removed)
+ cleanup(Resolver.resolve(dependencies, [source_index]))
+ end
+ configure(options)
+ sync
+ end
+
+ def gems
+ gems = []
+ each_repo do |repo|
+ gems.concat repo.gems
+ end
+ gems
+ end
+
+ def satisfies?(dependencies)
+ index = source_index
+ dependencies.all? { |dep| index.search(dep).size > 0 }
+ end
+
+ def source_index
+ index = Gem::SourceIndex.new
+
+ each_repo do |repo|
+ index.gems.merge!(repo.source_index.gems)
+ end
+
+ index
+ end
+
+ def add_spec(type, spec)
+ @repos[type].add_spec(spec)
+ end
+
+ def download_path_for(type)
+ @repos[type].download_path_for
+ end
+
+ private
+
+ def cleanup(bundle)
+ each_repo do |repo|
+ repo.cleanup(bundle)
+ end
+ end
+
+ def each_repo
+ @repos.each do |k, repo|
+ yield repo
+ end
+ end
+
+ def fetch(dependencies, sources)
+ bundle = Resolver.resolve(dependencies, sources)
+ # Cleanup here to remove any gems that could cause problem in the expansion
+ # phase
+ #
+ # TODO: Try to avoid double cleanup
+ cleanup(bundle)
+ bundle.download(self)
+ end
+
+ def sync
+ glob = gems.map { |g| g.executables }.flatten.join(',')
+
+ (Dir[@bindir.join("*")] - Dir[@bindir.join("{#{glob}}")]).each do |file|
+ Bundler.logger.info "Deleting bin file: #{File.basename(file)}"
+ FileUtils.rm_rf(file)
+ end
+ end
+
+ def expand(options)
+ each_repo do |repo|
+ repo.expand(options)
+ end
+ end
+
+ def configure(options)
+ generate_environment(options)
+ end
+
+ def generate_environment(options)
+ FileUtils.mkdir_p(path)
+
+ specs = gems
+ load_paths = load_paths_for_specs(specs)
+ bindir = @bindir.relative_path_from(path).to_s
+ filename = options[:manifest].relative_path_from(path).to_s
+ spec_files = specs.inject({}) do |hash, spec|
+ relative = spec.loaded_from.relative_path_from(@path).to_s
+ hash.merge!(spec.name => relative)
+ end
+
+ File.open(path.join("environment.rb"), "w") do |file|
+ template = File.read(File.join(File.dirname(__FILE__), "templates", "environment.erb"))
+ erb = ERB.new(template, nil, '-')
+ file.puts erb.result(binding)
+ end
+ end
+
+ def load_paths_for_specs(specs)
+ load_paths = []
+ specs.each do |spec|
+ gem_path = Pathname.new(spec.full_gem_path)
+ if spec.bindir
+ load_paths << gem_path.join(spec.bindir).relative_path_from(@path).to_s
+ end
+ spec.require_paths.each do |path|
+ load_paths << gem_path.join(path).relative_path_from(@path).to_s
+ end
+ end
+ load_paths
+ end
+
+ def require_code(file, dep)
+ constraint = case
+ when dep.only then %{ if #{dep.only.inspect}.include?(env)}
+ when dep.except then %{ unless #{dep.except.inspect}.include?(env)}
+ end
+ "require #{file.inspect}#{constraint}"
+ end
+ end
+end \ No newline at end of file
diff --git a/railties/lib/rails/vendor/bundler/lib/bundler/repository/directory_repository.rb b/railties/lib/rails/vendor/bundler/lib/bundler/repository/directory_repository.rb
new file mode 100644
index 0000000000..e97dd38dd5
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/lib/bundler/repository/directory_repository.rb
@@ -0,0 +1,46 @@
+module Bundler
+ class Repository
+ class Directory
+ attr_reader :path, :bindir
+
+ def initialize(path, bindir)
+ @path = path
+ @bindir = bindir
+
+ FileUtils.mkdir_p(path.to_s)
+ end
+
+ def source_index
+ index = Gem::SourceIndex.from_gems_in(@path.join("specifications"))
+ index.each { |n, spec| spec.loaded_from = @path.join("specifications", "#{spec.full_name}.gemspec") }
+ index
+ end
+
+ def gems
+ source_index.gems.values
+ end
+
+ def add_spec(spec)
+ destination = path.join('specifications')
+ destination.mkdir unless destination.exist?
+
+ File.open(destination.join("#{spec.full_name}.gemspec"), 'w') do |f|
+ f.puts spec.to_ruby
+ end
+ end
+
+ def download_path_for
+ @path.join("dirs")
+ end
+
+ # Checks whether a gem is installed
+ def expand(options)
+ # raise NotImplementedError
+ end
+
+ def cleanup(gems)
+ # raise NotImplementedError
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/railties/lib/rails/vendor/bundler/lib/bundler/repository/gem_repository.rb b/railties/lib/rails/vendor/bundler/lib/bundler/repository/gem_repository.rb
new file mode 100644
index 0000000000..90de49d83d
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/lib/bundler/repository/gem_repository.rb
@@ -0,0 +1,108 @@
+module Bundler
+ class Repository
+ class Gems
+ attr_reader :path, :bindir
+
+ def initialize(path, bindir)
+ @path = path
+ @bindir = bindir
+ end
+
+ # Returns the source index for all gems installed in the
+ # repository
+ def source_index
+ index = Gem::SourceIndex.from_gems_in(@path.join("specifications"))
+ index.each { |n, spec| spec.loaded_from = @path.join("specifications", "#{spec.full_name}.gemspec") }
+ index
+ end
+
+ def gems
+ source_index.gems.values
+ end
+
+ # Checks whether a gem is installed
+ def expand(options)
+ cached_gems.each do |name, version|
+ unless installed?(name, version)
+ install_cached_gem(name, version, options)
+ end
+ end
+ end
+
+ def cleanup(gems)
+ glob = gems.map { |g| g.full_name }.join(',')
+ base = path.join("{cache,specifications,gems}")
+
+ (Dir[base.join("*")] - Dir[base.join("{#{glob}}{.gemspec,.gem,}")]).each do |file|
+ if File.basename(file) =~ /\.gem$/
+ name = File.basename(file, '.gem')
+ Bundler.logger.info "Deleting gem: #{name}"
+ end
+ FileUtils.rm_rf(file)
+ end
+ end
+
+ def add_spec(spec)
+ raise NotImplementedError
+ end
+
+ def download_path_for
+ path
+ end
+
+ private
+
+ def cache_path
+ @path.join("cache")
+ end
+
+ def cache_files
+ Dir[cache_path.join("*.gem")]
+ end
+
+ def cached_gems
+ cache_files.map do |f|
+ full_name = File.basename(f).gsub(/\.gem$/, '')
+ full_name.split(/-(?=[^-]+$)/)
+ end
+ end
+
+ def spec_path
+ @path.join("specifications")
+ end
+
+ def spec_files
+ Dir[spec_path.join("*.gemspec")]
+ end
+
+ def gem_path
+ @path.join("gems")
+ end
+
+ def gem_paths
+ Dir[gem_path.join("*")]
+ end
+
+ def installed?(name, version)
+ spec_files.any? { |g| File.basename(g) == "#{name}-#{version}.gemspec" } &&
+ gem_paths.any? { |g| File.basename(g) == "#{name}-#{version}" }
+ end
+
+ def install_cached_gem(name, version, options = {})
+ cached_gem = cache_path.join("#{name}-#{version}.gem")
+ # TODO: Add a warning if cached_gem is not a file
+ if cached_gem.file?
+ Bundler.logger.info "Installing #{name}-#{version}.gem"
+ installer = Gem::Installer.new(cached_gem.to_s, options.merge(
+ :install_dir => @path,
+ :ignore_dependencies => true,
+ :env_shebang => true,
+ :wrappers => true,
+ :bin_dir => @bindir
+ ))
+ installer.install
+ end
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/railties/lib/rails/vendor/bundler/lib/bundler/resolver.rb b/railties/lib/rails/vendor/bundler/lib/bundler/resolver.rb
new file mode 100644
index 0000000000..2a6a6371c2
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/lib/bundler/resolver.rb
@@ -0,0 +1,189 @@
+# This is the latest iteration of the gem dependency resolving algorithm. As of now,
+# it can resolve (as a success of failure) any set of gem dependencies we throw at it
+# in a reasonable amount of time. The most iterations I've seen it take is about 150.
+# The actual implementation of the algorithm is not as good as it could be yet, but that
+# can come later.
+
+# Extending Gem classes to add necessary tracking information
+module Gem
+ class Dependency
+ def required_by
+ @required_by ||= []
+ end
+ end
+ class Specification
+ def required_by
+ @required_by ||= []
+ end
+ end
+end
+
+module Bundler
+ class GemNotFound < StandardError; end
+ class VersionConflict < StandardError; end
+
+ class Resolver
+
+ attr_reader :errors
+
+ # Figures out the best possible configuration of gems that satisfies
+ # the list of passed dependencies and any child dependencies without
+ # causing any gem activation errors.
+ #
+ # ==== Parameters
+ # *dependencies<Gem::Dependency>:: The list of dependencies to resolve
+ #
+ # ==== Returns
+ # <GemBundle>,nil:: If the list of dependencies can be resolved, a
+ # collection of gemspecs is returned. Otherwise, nil is returned.
+ def self.resolve(requirements, sources)
+ Bundler.logger.info "Calculating dependencies..."
+
+ resolver = new(sources)
+ result = catch(:success) do
+ resolver.resolve(requirements, {})
+ output = resolver.errors.inject("") do |o, (conflict, (origin, requirement))|
+ o << " Conflict on: #{conflict.inspect}:\n"
+ o << " * #{conflict} (#{origin.version}) activated by #{origin.required_by.first}\n"
+ o << " * #{requirement} required by #{requirement.required_by.first}\n"
+ o << " All possible versions of origin requirements conflict."
+ end
+ raise VersionConflict, "No compatible versions could be found for required dependencies:\n #{output}"
+ nil
+ end
+ result && GemBundle.new(result.values)
+ end
+
+ def initialize(sources)
+ @errors = {}
+ @stack = []
+ @specs = Hash.new { |h,k| h[k] = {} }
+ @cache = {}
+ @index = {}
+
+ sources.reverse_each do |source|
+ source.gems.values.each do |spec|
+ # TMP HAX FOR OPTZ
+ spec.source = source
+ next unless Gem::Platform.match(spec.platform)
+ @specs[spec.name][spec.version] = spec
+ end
+ end
+ end
+
+ def resolve(reqs, activated)
+ # If the requirements are empty, then we are in a success state. Aka, all
+ # gem dependencies have been resolved.
+ throw :success, activated if reqs.empty?
+
+ # Sort requirements so that the ones that are easiest to resolve are first.
+ # Easiest to resolve is defined by: Is this gem already activated? Otherwise,
+ # check the number of child dependencies this requirement has.
+ reqs = reqs.sort_by do |req|
+ activated[req.name] ? 0 : search(req).size
+ end
+
+ activated = activated.dup
+ # Pull off the first requirement so that we can resolve it
+ current = reqs.shift
+
+ # Check if the gem has already been activated, if it has, we will make sure
+ # that the currently activated gem satisfies the requirement.
+ if existing = activated[current.name]
+ if current.version_requirements.satisfied_by?(existing.version)
+ @errors.delete(existing.name)
+ # Since the current requirement is satisfied, we can continue resolving
+ # the remaining requirements.
+ resolve(reqs, activated)
+ else
+ @errors[existing.name] = [existing, current]
+ # Since the current requirement conflicts with an activated gem, we need
+ # to backtrack to the current requirement's parent and try another version
+ # of it (maybe the current requirement won't be present anymore). If the
+ # current requirement is a root level requirement, we need to jump back to
+ # where the conflicting gem was activated.
+ parent = current.required_by.last || existing.required_by.last
+ # We track the spot where the current gem was activated because we need
+ # to keep a list of every spot a failure happened.
+ throw parent.name, existing.required_by.last.name
+ end
+ else
+ # There are no activated gems for the current requirement, so we are going
+ # to find all gems that match the current requirement and try them in decending
+ # order. We also need to keep a set of all conflicts that happen while trying
+ # this gem. This is so that if no versions work, we can figure out the best
+ # place to backtrack to.
+ conflicts = Set.new
+
+ # Fetch all gem versions matching the requirement
+ #
+ # TODO: Warn / error when no matching versions are found.
+ matching_versions = search(current)
+
+ if matching_versions.empty?
+ if current.required_by.empty?
+ raise GemNotFound, "Could not find gem '#{current}' in any of the sources"
+ end
+ Bundler.logger.warn "Could not find gem '#{current}' (required by '#{current.required_by.last}') in any of the sources"
+ end
+
+ matching_versions.reverse_each do |spec|
+ conflict = resolve_requirement(spec, current, reqs.dup, activated.dup)
+ conflicts << conflict if conflict
+ end
+ # If the current requirement is a root level gem and we have conflicts, we
+ # can figure out the best spot to backtrack to.
+ if current.required_by.empty? && !conflicts.empty?
+ # Check the current "catch" stack for the first one that is included in the
+ # conflicts set. That is where the parent of the conflicting gem was required.
+ # By jumping back to this spot, we can try other version of the parent of
+ # the conflicting gem, hopefully finding a combination that activates correctly.
+ @stack.reverse_each do |savepoint|
+ if conflicts.include?(savepoint)
+ throw savepoint
+ end
+ end
+ end
+ end
+ end
+
+ def resolve_requirement(spec, requirement, reqs, activated)
+ # We are going to try activating the spec. We need to keep track of stack of
+ # requirements that got us to the point of activating this gem.
+ spec.required_by.replace requirement.required_by
+ spec.required_by << requirement
+
+ activated[spec.name] = spec
+
+ # Now, we have to loop through all child dependencies and add them to our
+ # array of requirements.
+ spec.dependencies.each do |dep|
+ next if dep.type == :development
+ dep.required_by << requirement
+ reqs << dep
+ end
+
+ # We create a savepoint and mark it by the name of the requirement that caused
+ # the gem to be activated. If the activated gem ever conflicts, we are able to
+ # jump back to this point and try another version of the gem.
+ length = @stack.length
+ @stack << requirement.name
+ retval = catch(requirement.name) do
+ resolve(reqs, activated)
+ end
+ # Since we're doing a lot of throw / catches. A push does not necessarily match
+ # up to a pop. So, we simply slice the stack back to what it was before the catch
+ # block.
+ @stack.slice!(length..-1)
+ retval
+ end
+
+ def search(dependency)
+ @cache[dependency.hash] ||= begin
+ @specs[dependency.name].values.select do |spec|
+ dependency =~ spec
+ end.sort_by {|s| s.version }
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/railties/lib/rails/vendor/bundler/lib/bundler/runtime.rb b/railties/lib/rails/vendor/bundler/lib/bundler/runtime.rb
new file mode 100644
index 0000000000..27e0254966
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/lib/bundler/runtime.rb
@@ -0,0 +1,2 @@
+require File.join(File.dirname(__FILE__), "runtime", "dsl")
+require File.join(File.dirname(__FILE__), "runtime", "dependency") \ No newline at end of file
diff --git a/railties/lib/rails/vendor/bundler/lib/bundler/source.rb b/railties/lib/rails/vendor/bundler/lib/bundler/source.rb
new file mode 100644
index 0000000000..37828ca316
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/lib/bundler/source.rb
@@ -0,0 +1,150 @@
+module Bundler
+ # Represents a source of rubygems. Initially, this is only gem repositories, but
+ # eventually, this will be git, svn, HTTP
+ class Source
+ attr_accessor :tmp_path
+ end
+
+ class GemSource < Source
+ attr_reader :uri
+
+ def initialize(options)
+ @uri = options[:uri]
+ @uri = URI.parse(@uri) unless @uri.is_a?(URI)
+ raise ArgumentError, "The source must be an absolute URI" unless @uri.absolute?
+ end
+
+ def gems
+ @specs ||= fetch_specs
+ end
+
+ def ==(other)
+ uri == other.uri
+ end
+
+ def to_s
+ @uri.to_s
+ end
+
+ class RubygemsRetardation < StandardError; end
+
+ def download(spec, repository)
+ Bundler.logger.info "Downloading #{spec.full_name}.gem"
+
+ destination = repository.download_path_for(:gem)
+
+ unless destination.writable?
+ raise RubygemsRetardation
+ end
+
+ Gem::RemoteFetcher.fetcher.download(spec, uri, repository.download_path_for(:gem))
+ end
+
+ private
+
+ def fetch_specs
+ Bundler.logger.info "Updating source: #{to_s}"
+
+ deflated = Gem::RemoteFetcher.fetcher.fetch_path("#{uri}/Marshal.4.8.Z")
+ inflated = Gem.inflate deflated
+
+ index = Marshal.load(inflated)
+ index.gems
+ rescue Gem::RemoteFetcher::FetchError => e
+ raise ArgumentError, "#{to_s} is not a valid source: #{e.message}"
+ end
+ end
+
+ class DirectorySource < Source
+ def initialize(options)
+ @name = options[:name]
+ @version = options[:version]
+ @location = options[:location]
+ @require_paths = options[:require_paths] || %w(lib)
+ end
+
+ def gems
+ @gems ||= begin
+ specs = {}
+
+ # Find any gemspec files in the directory and load those specs
+ Dir[@location.join('**', '*.gemspec')].each do |file|
+ path = Pathname.new(file).relative_path_from(@location).dirname
+ spec = eval(File.read(file))
+ spec.require_paths.map! { |p| path.join(p) }
+ specs[spec.full_name] = spec
+ end
+
+ # If a gemspec for the dependency was not found, add it to the list
+ if specs.keys.grep(/^#{Regexp.escape(@name)}/).empty?
+ case
+ when @version.nil?
+ raise ArgumentError, "If you use :at, you must specify the gem" \
+ "and version you wish to stand in for"
+ when !Gem::Version.correct?(@version)
+ raise ArgumentError, "If you use :at, you must specify a gem and" \
+ "version. You specified #{@version} for the version"
+ end
+
+ default = Gem::Specification.new do |s|
+ s.name = @name
+ s.version = Gem::Version.new(@version) if @version
+ end
+ specs[default.full_name] = default
+ end
+
+ specs
+ end
+ end
+
+ def ==(other)
+ # TMP HAX
+ other.is_a?(DirectorySource)
+ end
+
+ def to_s
+ "#{@name} (#{@version}) Located at: '#{@location}'"
+ end
+
+ def download(spec, repository)
+ spec.require_paths.map! { |p| File.join(@location, p) }
+ repository.add_spec(:directory, spec)
+ end
+ end
+
+ class GitSource < DirectorySource
+ def initialize(options)
+ super
+ @uri = options[:uri]
+ @ref = options[:ref]
+ @branch = options[:branch]
+ end
+
+ def gems
+ FileUtils.mkdir_p(tmp_path.join("gitz"))
+
+ # TMP HAX to get the *.gemspec reading to work
+ @location = tmp_path.join("gitz", @name)
+
+ Bundler.logger.info "Cloning git repository at: #{@uri}"
+ `git clone #{@uri} #{@location} --no-hardlinks`
+
+ if @ref
+ Dir.chdir(@location) { `git checkout #{@ref}` }
+ elsif @branch && @branch != "master"
+ Dir.chdir(@location) { `git checkout origin/#{@branch}` }
+ end
+ super
+ end
+
+ def download(spec, repository)
+ dest = repository.download_path_for(:directory).join(@name)
+ spec.require_paths.map! { |p| File.join(dest, p) }
+ repository.add_spec(:directory, spec)
+ if spec.name == @name
+ FileUtils.mkdir_p(dest.dirname)
+ FileUtils.mv(tmp_path.join("gitz", spec.name), dest)
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/railties/lib/rails/vendor/bundler/lib/bundler/templates/app_script.erb b/railties/lib/rails/vendor/bundler/lib/bundler/templates/app_script.erb
new file mode 100644
index 0000000000..3e47a53ca8
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/lib/bundler/templates/app_script.erb
@@ -0,0 +1,3 @@
+<%= shebang bin_file_name %>
+require File.join(File.dirname(__FILE__), "<%= path.join("environment").relative_path_from(Pathname.new(bin_dir)) %>")
+load File.join(File.dirname(__FILE__), "<%= path.join("gems", @spec.full_name, @spec.bindir, bin_file_name).relative_path_from(Pathname.new(bin_dir)) %>") \ No newline at end of file
diff --git a/railties/lib/rails/vendor/bundler/lib/bundler/templates/environment.erb b/railties/lib/rails/vendor/bundler/lib/bundler/templates/environment.erb
new file mode 100644
index 0000000000..21f3de8854
--- /dev/null
+++ b/railties/lib/rails/vendor/bundler/lib/bundler/templates/environment.erb
@@ -0,0 +1,127 @@
+# DO NOT MODIFY THIS FILE
+module Bundler
+ dir = File.dirname(__FILE__)
+
+<% unless options[:system_gems] -%>
+ ENV["GEM_HOME"] = dir
+ ENV["GEM_PATH"] = dir
+<% end -%>
+ ENV["PATH"] = "#{dir}/<%= bindir %>:#{ENV["PATH"]}"
+ ENV["RUBYOPT"] = "-r#{__FILE__} #{ENV["RUBYOPT"]}"
+
+<% load_paths.each do |load_path| -%>
+ $LOAD_PATH.unshift File.expand_path("#{dir}/<%= load_path %>")
+<% end -%>
+
+ @gemfile = "#{dir}/<%= filename %>"
+
+<% if options[:rubygems] -%>
+ require "rubygems"
+
+ @bundled_specs = {}
+<% spec_files.each do |name, path| -%>
+ @bundled_specs["<%= name %>"] = eval(File.read("#{dir}/<%= path %>"))
+ @bundled_specs["<%= name %>"].loaded_from = "#{dir}/<%= path %>"
+<% end -%>
+
+ def self.add_specs_to_loaded_specs
+ Gem.loaded_specs.merge! @bundled_specs
+ end
+
+ def self.add_specs_to_index
+ @bundled_specs.each do |name, spec|
+ Gem.source_index.add_spec spec
+ end
+ end
+
+ add_specs_to_loaded_specs
+ add_specs_to_index
+<% end -%>
+
+ def self.require_env(env = nil)
+ context = Class.new do
+ def initialize(env) @env = env && env.to_s ; end
+ def method_missing(*) ; end
+ def only(env)
+ old, @only = @only, _combine_onlys(env)
+ yield
+ @only = old
+ end
+ def except(env)
+ old, @except = @except, _combine_excepts(env)
+ yield
+ @except = old
+ end
+ def gem(name, *args)
+ opt = args.last || {}
+ only = _combine_onlys(opt[:only] || opt["only"])
+ except = _combine_excepts(opt[:except] || opt["except"])
+ files = opt[:require_as] || opt["require_as"] || name
+
+ return unless !only || only.any? {|e| e == @env }
+ return if except && except.any? {|e| e == @env }
+
+ files.each { |f| require f }
+ yield if block_given?
+ true
+ end
+ private
+ def _combine_onlys(only)
+ return @only unless only
+ only = [only].flatten.compact.uniq.map { |o| o.to_s }
+ only &= @only if @only
+ only
+ end
+ def _combine_excepts(except)
+ return @except unless except
+ except = [except].flatten.compact.uniq.map { |o| o.to_s }
+ except |= @except if @except
+ except
+ end
+ end
+ context.new(env && env.to_s).instance_eval(File.read(@gemfile))
+ end
+end
+
+<% if options[:rubygems] -%>
+module Gem
+ def source_index.refresh!
+ super
+ Bundler.add_specs_to_index
+ end
+end
+<% else -%>
+$" << "rubygems.rb"
+
+module Kernel
+ def gem(*)
+ # Silently ignore calls to gem, since, in theory, everything
+ # is activated correctly already.
+ end
+end
+
+# Define all the Gem errors for gems that reference them.
+module Gem
+ def self.ruby ; <%= Gem.ruby.inspect %> ; end
+ class LoadError < ::LoadError; end
+ class Exception < RuntimeError; end
+ class CommandLineError < Exception; end
+ class DependencyError < Exception; end
+ class DependencyRemovalException < Exception; end
+ class GemNotInHomeException < Exception ; end
+ class DocumentError < Exception; end
+ class EndOfYAMLException < Exception; end
+ class FilePermissionError < Exception; end
+ class FormatException < Exception; end
+ class GemNotFoundException < Exception; end
+ class InstallError < Exception; end
+ class InvalidSpecificationException < Exception; end
+ class OperationNotSupportedError < Exception; end
+ class RemoteError < Exception; end
+ class RemoteInstallationCancelled < Exception; end
+ class RemoteInstallationSkipped < Exception; end
+ class RemoteSourceException < Exception; end
+ class VerificationError < Exception; end
+ class SystemExitException < SystemExit; end
+end
+<% end -%> \ No newline at end of file
diff --git a/railties/lib/rails/vendor/thor-0.11.6/CHANGELOG.rdoc b/railties/lib/rails/vendor/thor-0.11.6/CHANGELOG.rdoc
new file mode 100644
index 0000000000..dba25b7205
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/CHANGELOG.rdoc
@@ -0,0 +1,77 @@
+== TODO
+
+* Improve spec coverage for Thor::Runner
+
+== 0.11.x, released 2009-07-01
+
+* Added a rake compatibility layer. It allows you to use spec and rdoc tasks on
+ Thor classes.
+
+* BACKWARDS INCOMPATIBLE: aliases are not generated automatically anymore
+ since it wrong behavior to the invocation system.
+
+* thor help now show information about any class/task. All those calls are
+ possible:
+
+ thor help describe
+ thor help describe:amazing
+
+ Or even with default namespaces:
+
+ thor help :spec
+
+* Thor::Runner now invokes the default task if none is supplied:
+
+ thor describe # invokes the default task, usually help
+
+* Thor::Runner now works with mappings:
+
+ thor describe -h
+
+* Added some documentation and code refactoring.
+
+== 0.9.8, released 2008-10-20
+
+* Fixed some tiny issues that were introduced lately.
+
+== 0.9.7, released 2008-10-13
+
+* Setting global method options on the initialize method works as expected:
+ All other tasks will accept these global options in addition to their own.
+* Added 'group' notion to Thor task sets (class Thor); by default all tasks
+ are in the 'standard' group. Running 'thor -T' will only show the standard
+ tasks - adding --all will show all tasks. You can also filter on a specific
+ group using the --group option: thor -T --group advanced
+
+== 0.9.6, released 2008-09-13
+
+* Generic improvements
+
+== 0.9.5, released 2008-08-27
+
+* Improve Windows compatibility
+* Update (incorrect) README and task.thor sample file
+* Options hash is now frozen (once returned)
+* Allow magic predicates on options object. For instance: `options.force?`
+* Add support for :numeric type
+* BACKWARDS INCOMPATIBLE: Refactor Thor::Options. You cannot access shorthand forms in options hash anymore (for instance, options[:f])
+* Allow specifying optional args with default values: method_options(:user => "mislav")
+* Don't write options for nil or false values. This allows, for example, turning color off when running specs.
+* Exit with the status of the spec command to help CI stuff out some.
+
+== 0.9.4, released 2008-08-13
+
+* Try to add Windows compatibility.
+* BACKWARDS INCOMPATIBLE: options hash is now accessed as a property in your class and is not passed as last argument anymore
+* Allow options at the beginning of the argument list as well as the end.
+* Make options available with symbol keys in addition to string keys.
+* Allow true to be passed to Thor#method_options to denote a boolean option.
+* If loading a thor file fails, don't give up, just print a warning and keep going.
+* Make sure that we re-raise errors if they happened further down the pipe than we care about.
+* Only delete the old file on updating when the installation of the new one is a success
+* Make it Ruby 1.8.5 compatible.
+* Don't raise an error if a boolean switch is defined multiple times.
+* Thor::Options now doesn't parse through things that look like options but aren't.
+* Add URI detection to install task, and make sure we don't append ".thor" to URIs
+* Add rake2thor to the gem binfiles.
+* Make sure local Thorfiles override system-wide ones.
diff --git a/railties/lib/rails/vendor/thor-0.11.6/LICENSE b/railties/lib/rails/vendor/thor-0.11.6/LICENSE
new file mode 100644
index 0000000000..98722da459
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2008 Yehuda Katz
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/railties/lib/rails/vendor/thor-0.11.6/README.rdoc b/railties/lib/rails/vendor/thor-0.11.6/README.rdoc
new file mode 100644
index 0000000000..f1106f02b6
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/README.rdoc
@@ -0,0 +1,234 @@
+= thor
+
+Map options to a class. Simply create a class with the appropriate annotations
+and have options automatically map to functions and parameters.
+
+Example:
+
+ class App < Thor # [1]
+ map "-L" => :list # [2]
+
+ desc "install APP_NAME", "install one of the available apps" # [3]
+ method_options :force => :boolean, :alias => :string # [4]
+ def install(name)
+ user_alias = options[:alias]
+ if options.force?
+ # do something
+ end
+ # other code
+ end
+
+ desc "list [SEARCH]", "list all of the available apps, limited by SEARCH"
+ def list(search="")
+ # list everything
+ end
+ end
+
+Thor automatically maps commands as such:
+
+ thor app:install myname --force
+
+That gets converted to:
+
+ App.new.install("myname")
+ # with {'force' => true} as options hash
+
+1. Inherit from Thor to turn a class into an option mapper
+2. Map additional non-valid identifiers to specific methods. In this case, convert -L to :list
+3. Describe the method immediately below. The first parameter is the usage information, and the second parameter is the description
+4. Provide any additional options that will be available the instance method options.
+
+== Types for <tt>method_options</tt>
+
+* :boolean - is parsed as <tt>--option</tt> or <tt>--option=true</tt>
+* :string - is parsed as <tt>--option=VALUE</tt>
+* :numeric - is parsed as <tt>--option=N</tt>
+* :array - is parsed as <tt>--option=one two three</tt>
+* :hash - is parsed as <tt>--option=name:string age:integer</tt>
+
+Besides, method_option allows a default value to be given, examples:
+
+ method_options :force => false
+ #=> Creates a boolean option with default value false
+
+ method_options :alias => "bar"
+ #=> Creates a string option with default value "bar"
+
+ method_options :threshold => 3.0
+ #=> Creates a numeric option with default value 3.0
+
+You can also supply <tt>:option => :required</tt> to mark an option as required. The
+type is assumed to be string. If you want a required hash with default values
+as option, you can use <tt>method_option</tt> which uses a more declarative style:
+
+ method_option :attributes, :type => :hash, :default => {}, :required => true
+
+All arguments can be set to nil (except required arguments), by suppling a no or
+skip variant. For example:
+
+ thor app name --no-attributes
+
+In previous versions, aliases for options were created automatically, but now
+they should be explicit. You can supply aliases in both short and declarative
+styles:
+
+ method_options %w( force -f ) => :boolean
+
+Or:
+
+ method_option :force, :type => :boolean, :aliases => "-f"
+
+You can supply as many aliases as you want.
+
+NOTE: Type :optional available in Thor 0.9.0 was deprecated. Use :string or :boolean instead.
+
+== Namespaces
+
+By default, your Thor tasks are invoked using Ruby namespace. In the example
+above, tasks are invoked as:
+
+ thor app:install name --force
+
+However, you could namespace your class as:
+
+ module Sinatra
+ class App < Thor
+ # tasks
+ end
+ end
+
+And then you should invoke your tasks as:
+
+ thor sinatra:app:install name --force
+
+If desired, you can change the namespace:
+
+ module Sinatra
+ class App < Thor
+ namespace :myapp
+ # tasks
+ end
+ end
+
+And then your tasks hould be invoked as:
+
+ thor myapp:install name --force
+
+== Invocations
+
+Thor comes with a invocation-dependency system as well which allows a task to be
+invoked only once. For example:
+
+ class Counter < Thor
+ desc "one", "Prints 1, 2, 3"
+ def one
+ puts 1
+ invoke :two
+ invoke :three
+ end
+
+ desc "two", "Prints 2, 3"
+ def two
+ puts 2
+ invoke :three
+ end
+
+ desc "three", "Prints 3"
+ def three
+ puts 3
+ end
+ end
+
+When invoking the task one:
+
+ thor counter:one
+
+The output is "1 2 3", which means that the three task was invoked only once.
+You can even invoke tasks from another class, so be sure to check the
+documentation.
+
+== Thor::Group
+
+Thor has a special class called Thor::Group. The main difference to Thor class
+is that it invokes all tasks at once. The example above could be rewritten in
+Thor::Group as this:
+
+ class Counter < Thor::Group
+ desc "Prints 1, 2, 3"
+
+ def one
+ puts 1
+ end
+
+ def two
+ puts 2
+ end
+
+ def three
+ puts 3
+ end
+ end
+
+When invoked:
+
+ thor counter
+
+It prints "1 2 3" as well. Notice you should describe (using the method <tt>desc</tt>)
+only the class and not each task anymore. Thor::Group is a great tool to create
+generators, since you can define several steps which are invoked in the order they
+are defined (Thor::Group is the tool use in generators in Rails 3.0).
+
+Besides, Thor::Group can parse arguments and options as Thor tasks:
+
+ class Counter < Thor::Group
+ # number will be available as attr_accessor
+ argument :number, :type => :numeric, :desc => "The number to start counting"
+ desc "Prints the 'number' given upto 'number+2'"
+
+ def one
+ puts number + 0
+ end
+
+ def two
+ puts number + 1
+ end
+
+ def three
+ puts number + 2
+ end
+ end
+
+The counter above expects one parameter and has the folling outputs:
+
+ thor counter 5
+ # Prints "5 6 7"
+
+ thor counter 11
+ # Prints "11 12 13"
+
+You can also give options to Thor::Group, but instead of using <tt>method_option</tt>
+and <tt>method_options</tt>, you should use <tt>class_option</tt> and <tt>class_options</tt>.
+Both argument and class_options methods are available to Thor class as well.
+
+== Actions
+
+Thor comes with several actions which helps with script and generator tasks. You
+might be familiar with them since some came from Rails Templates. They are:
+<tt>say</tt>, <tt>ask</tt>, <tt>yes?</tt>, <tt>no?</tt>, <tt>add_file</tt>,
+<tt>remove_file</tt>, <tt>copy_file</tt>, <tt>template</tt>, <tt>directory</tt>,
+<tt>inside</tt>, <tt>run</tt>, <tt>inject_into_file</tt> and a couple more.
+
+To use them, you just need to include Thor::Actions in your Thor classes:
+
+ class App < Thor
+ include Thor::Actions
+ # tasks
+ end
+
+Some actions like copy file requires that a class method called source_root is
+defined in your class. This is the directory where your templates should be
+placed. Be sure to check the documentation.
+
+== License
+
+See MIT LICENSE.
diff --git a/railties/lib/rails/vendor/thor-0.11.6/bin/rake2thor b/railties/lib/rails/vendor/thor-0.11.6/bin/rake2thor
new file mode 100755
index 0000000000..50c7410d80
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/bin/rake2thor
@@ -0,0 +1,87 @@
+#!/usr/bin/env ruby
+
+require 'rubygems'
+require 'ruby2ruby'
+require 'parse_tree'
+if Ruby2Ruby::VERSION >= "1.2.0"
+ require 'parse_tree_extensions'
+end
+require 'rake'
+
+input = ARGV[0] || 'Rakefile'
+output = ARGV[1] || 'Thorfile'
+
+$requires = []
+
+module Kernel
+ def require_with_record(file)
+ $requires << file if caller[1] =~ /rake2thor:/
+ require_without_record file
+ end
+ alias_method :require_without_record, :require
+ alias_method :require, :require_with_record
+end
+
+load input
+
+@private_methods = []
+
+def file_task_name(name)
+ "compile_" + name.gsub('/', '_slash_').gsub('.', '_dot_').gsub(/\W/, '_')
+end
+
+def method_for_task(task)
+ file_task = task.is_a?(Rake::FileTask)
+ comment = task.instance_variable_get('@comment')
+ prereqs = task.instance_variable_get('@prerequisites').select(&Rake::Task.method(:task_defined?))
+ actions = task.instance_variable_get('@actions')
+ name = task.name.gsub(/^([^:]+:)+/, '')
+ name = file_task_name(name) if file_task
+ meth = ''
+
+ meth << "desc #{name.inspect}, #{comment.inspect}\n" if comment
+ meth << "def #{name}\n"
+
+ meth << prereqs.map do |pre|
+ pre = pre.to_s
+ pre = file_task_name(pre) if Rake::Task[pre].is_a?(Rake::FileTask)
+ ' ' + pre
+ end.join("\n")
+
+ meth << "\n\n" unless prereqs.empty? || actions.empty?
+
+ meth << actions.map do |act|
+ act = act.to_ruby
+ unless act.gsub!(/^proc \{ \|(\w+)\|\n/,
+ " \\1 = Struct.new(:name).new(#{name.inspect}) # A crude mock Rake::Task object\n")
+ act.gsub!(/^proc \{\n/, '')
+ end
+ act.gsub(/\n\}$/, '')
+ end.join("\n")
+
+ meth << "\nend"
+
+ if file_task
+ @private_methods << meth
+ return
+ end
+
+ meth
+end
+
+body = Rake::Task.tasks.map(&method(:method_for_task)).compact.map { |meth| meth.gsub(/^/, ' ') }.join("\n\n")
+
+unless @private_methods.empty?
+ body << "\n\n private\n\n"
+ body << @private_methods.map { |meth| meth.gsub(/^/, ' ') }.join("\n\n")
+end
+
+requires = $requires.map { |r| "require #{r.inspect}" }.join("\n")
+
+File.open(output, 'w') { |f| f.write(<<END.lstrip) }
+#{requires}
+
+class Default < Thor
+#{body}
+end
+END
diff --git a/railties/lib/rails/vendor/thor-0.11.6/bin/thor b/railties/lib/rails/vendor/thor-0.11.6/bin/thor
new file mode 100755
index 0000000000..eaf849fb4a
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/bin/thor
@@ -0,0 +1,7 @@
+#!/usr/bin/env ruby
+# -*- mode: ruby -*-
+
+require File.join(File.dirname(__FILE__), '..', 'lib', 'thor')
+require 'thor/runner'
+
+Thor::Runner.start
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor.rb
new file mode 100644
index 0000000000..3b45c4e9b7
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor.rb
@@ -0,0 +1,243 @@
+$:.unshift File.expand_path(File.dirname(__FILE__))
+require 'thor/base'
+require 'thor/group'
+require 'thor/actions'
+
+class Thor
+ 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
+ #
+ def default_task(meth=nil)
+ case meth
+ when :none
+ @default_task = 'help'
+ when nil
+ @default_task ||= from_superclass(:default_task, 'help')
+ else
+ @default_task = meth.to_s
+ end
+ end
+
+ # Defines the usage and the description of the next task.
+ #
+ # ==== Parameters
+ # usage<String>
+ # description<String>
+ #
+ def desc(usage, description, options={})
+ if options[:for]
+ task = find_and_refresh_task(options[:for])
+ task.usage = usage if usage
+ task.description = description if description
+ else
+ @usage, @desc = usage, description
+ end
+ end
+
+ # Maps an input to a task. If you define:
+ #
+ # map "-T" => "list"
+ #
+ # Running:
+ #
+ # thor -T
+ #
+ # Will invoke the list task.
+ #
+ # ==== Parameters
+ # Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given task.
+ #
+ def map(mappings=nil)
+ @map ||= from_superclass(:map, {})
+
+ if mappings
+ mappings.each do |key, value|
+ if key.respond_to?(:each)
+ key.each {|subkey| @map[subkey] = value}
+ else
+ @map[key] = value
+ end
+ end
+ end
+
+ @map
+ end
+
+ # Declares the options for the next task to be declared.
+ #
+ # ==== Parameters
+ # Hash[Symbol => Object]:: The hash key is the name of the option and the value
+ # is the type of the option. Can be :string, :array, :hash, :boolean, :numeric
+ # or :required (string). If you give a value, the type of the value is used.
+ #
+ def method_options(options=nil)
+ @method_options ||= {}
+ build_options(options, @method_options) if options
+ @method_options
+ end
+
+ # Adds an option to the set of class options. If :for is given as option,
+ # it allows you to change the options from a previous defined task.
+ #
+ # def previous_task
+ # # magic
+ # end
+ #
+ # method_options :foo => :bar, :for => :previous_task
+ #
+ # def next_task
+ # # magic
+ # end
+ #
+ # ==== Parameters
+ # name<Symbol>:: The name of the argument.
+ # options<Hash>:: Described below.
+ #
+ # ==== Options
+ # :desc - Description for the argument.
+ # :required - If the argument is required or not.
+ # :default - Default value for this argument. It cannot be required and have default values.
+ # :aliases - Aliases for this option.
+ # :type - The type of the argument, can be :string, :hash, :array, :numeric or :boolean.
+ # :group - The group for this options. Use by class options to output options in different levels.
+ # :banner - String to show on usage notes.
+ #
+ def method_option(name, options={})
+ scope = if options[:for]
+ find_and_refresh_task(options[:for]).options
+ else
+ method_options
+ end
+
+ build_option(name, options, scope)
+ end
+
+ # Parses the task and options from the given args, instantiate the class
+ # and invoke the task. This method is used when the arguments must be parsed
+ # from an array. If you are inside Ruby and want to use a Thor class, you
+ # can simply initialize it:
+ #
+ # script = MyScript.new(args, options, config)
+ # script.invoke(:task, first_arg, second_arg, third_arg)
+ #
+ def start(given_args=ARGV, config={})
+ super do
+ meth = normalize_task_name(given_args.shift)
+ task = all_tasks[meth]
+
+ if task
+ args, opts = Thor::Options.split(given_args)
+ config.merge!(:task_options => task.options)
+ else
+ args, opts = given_args, {}
+ end
+
+ task ||= Thor::Task::Dynamic.new(meth)
+ trailing = args[Range.new(arguments.size, -1)]
+ new(args, opts, config).invoke(task, trailing || [])
+ end
+ end
+
+ # Prints help information. If a task name is given, it shows information
+ # only about the specific task.
+ #
+ # ==== Parameters
+ # meth<String>:: An optional task name to print usage information about.
+ #
+ # ==== Options
+ # namespace:: When true, shows the namespace in the output before the usage.
+ # skip_inherited:: When true, does not show tasks from superclass.
+ #
+ def help(shell, meth=nil, options={})
+ meth, options = nil, meth if meth.is_a?(Hash)
+
+ if meth
+ task = all_tasks[meth]
+ raise UndefinedTaskError, "task '#{meth}' could not be found in namespace '#{self.namespace}'" unless task
+
+ shell.say "Usage:"
+ shell.say " #{banner(task, options[:namespace], false)}"
+ shell.say
+ class_options_help(shell, "Class", :Method => task.options.map { |_, o| o })
+ shell.say task.description
+ else
+ list = (options[:short] ? tasks : all_tasks).map do |_, task|
+ item = [ banner(task, options[:namespace]) ]
+ item << "# #{task.short_description}" if task.short_description
+ item << " "
+ end
+
+ options[:ident] ||= 2
+ if options[:short]
+ shell.print_list(list, :ident => options[:ident])
+ else
+ shell.say "Tasks:"
+ shell.print_list(list, :ident => options[:ident])
+ end
+
+ Thor::Util.thor_classes_in(self).each do |subclass|
+ namespace = options[:namespace] == true || subclass.namespace.gsub(/^#{self.namespace}:/, '')
+ subclass.help(shell, options.merge(:short => true, :namespace => namespace))
+ end
+
+ class_options_help(shell, "Class") unless options[:short]
+ end
+ end
+
+ protected
+
+ # The banner for this class. You can customize it if you are invoking the
+ # thor class by another ways which is not the Thor::Runner. It receives
+ # the task that is going to be invoked and a boolean which indicates if
+ # the namespace should be displayed as arguments.
+ #
+ def banner(task, namespace=true, show_options=true)
+ task.formatted_usage(self, namespace, show_options)
+ end
+
+ def baseclass #:nodoc:
+ Thor
+ end
+
+ def create_task(meth) #:nodoc:
+ if @usage && @desc
+ tasks[meth.to_s] = Thor::Task.new(meth, @desc, @usage, method_options)
+ @usage, @desc, @method_options = nil
+ true
+ elsif self.all_tasks[meth.to_s] || meth.to_sym == :method_missing
+ true
+ else
+ puts "[WARNING] Attempted to create task #{meth.inspect} without usage or description. " <<
+ "Call desc if you want this method to be available as task or declare it inside a " <<
+ "no_tasks{} block. Invoked from #{caller[1].inspect}."
+ false
+ end
+ end
+
+ def initialize_added #:nodoc:
+ class_options.merge!(method_options)
+ @method_options = nil
+ 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.
+ #
+ def normalize_task_name(meth) #:nodoc:
+ mapping = map[meth.to_s]
+ meth = mapping || meth || default_task
+ meth.to_s.gsub('-','_') # treat foo-bar > foo_bar
+ end
+ end
+
+ include Thor::Base
+
+ map HELP_MAPPINGS => :help
+
+ desc "help [TASK]", "Describe available tasks or one specific task"
+ def help(task=nil)
+ self.class.help(shell, task, :namespace => task && task.include?(?:))
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions.rb
new file mode 100644
index 0000000000..d561ccb2aa
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions.rb
@@ -0,0 +1,273 @@
+require 'fileutils'
+
+Dir[File.join(File.dirname(__FILE__), "actions", "*.rb")].each do |action|
+ require action
+end
+
+class Thor
+ module Actions
+ attr_accessor :behavior
+
+ def self.included(base) #:nodoc:
+ base.extend ClassMethods
+ end
+
+ module ClassMethods
+ # Hold source paths for one Thor instance. source_paths_for_search is the
+ # method responsible to gather source_paths from this current class,
+ # inherited paths and the source root.
+ #
+ def source_paths
+ @source_paths ||= []
+ end
+
+ # Returns the source paths in the following order:
+ #
+ # 1) This class source paths
+ # 2) Source root
+ # 3) Parents source paths
+ #
+ def source_paths_for_search
+ paths = []
+ paths += self.source_paths
+ paths << self.source_root if self.respond_to?(:source_root)
+ paths += from_superclass(:source_paths, [])
+ paths
+ end
+
+ # Add runtime options that help actions execution.
+ #
+ def add_runtime_options!
+ class_option :pretend, :type => :boolean, :aliases => "-p", :group => :runtime,
+ :desc => "Run but do not make any changes"
+
+ class_option :force, :type => :boolean, :aliases => "-f", :group => :runtime,
+ :desc => "Overwrite files that already exist"
+
+ class_option :skip, :type => :boolean, :aliases => "-s", :group => :runtime,
+ :desc => "Skip files that already exist"
+
+ class_option :quiet, :type => :boolean, :aliases => "-q", :group => :runtime,
+ :desc => "Supress status output"
+ end
+ end
+
+ # Extends initializer to add more configuration options.
+ #
+ # ==== Configuration
+ # behavior<Symbol>:: The actions default behavior. Can be :invoke or :revoke.
+ # It also accepts :force, :skip and :pretend to set the behavior
+ # and the respective option.
+ #
+ # destination_root<String>:: The root directory needed for some actions.
+ #
+ def initialize(args=[], options={}, config={})
+ self.behavior = case config[:behavior].to_s
+ when "force", "skip"
+ _cleanup_options_and_set(options, config[:behavior])
+ :invoke
+ when "revoke"
+ :revoke
+ else
+ :invoke
+ end
+
+ super
+ self.destination_root = config[:destination_root]
+ end
+
+ # Wraps an action object and call it accordingly to the thor class behavior.
+ #
+ def action(instance) #:nodoc:
+ if behavior == :revoke
+ instance.revoke!
+ else
+ instance.invoke!
+ end
+ end
+
+ # Returns the root for this thor class (also aliased as destination root).
+ #
+ def destination_root
+ @destination_stack.last
+ end
+
+ # Sets the root for this thor class. Relatives path are added to the
+ # directory where the script was invoked and expanded.
+ #
+ def destination_root=(root)
+ @destination_stack ||= []
+ @destination_stack[0] = File.expand_path(root || '')
+ end
+
+ # Returns the given path relative to the absolute root (ie, root where
+ # the script started).
+ #
+ def relative_to_original_destination_root(path, remove_dot=true)
+ path = path.gsub(@destination_stack[0], '.')
+ remove_dot ? (path[2..-1] || '') : path
+ end
+
+ # Holds source paths in instance so they can be manipulated.
+ #
+ def source_paths
+ @source_paths ||= self.class.source_paths_for_search
+ end
+
+ # Receives a file or directory and search for it in the source paths.
+ #
+ def find_in_source_paths(file)
+ relative_root = relative_to_original_destination_root(destination_root, false)
+
+ source_paths.each do |source|
+ source_file = File.expand_path(file, File.join(source, relative_root))
+ return source_file if File.exists?(source_file)
+ end
+
+ if source_paths.empty?
+ raise Error, "You don't have any source path defined for class #{self.class.name}. To fix this, " <<
+ "you can define a source_root in your class."
+ else
+ raise Error, "Could not find #{file.inspect} in source paths."
+ end
+ end
+
+ # Do something in the root or on a provided subfolder. If a relative path
+ # is given it's referenced from the current root. The full path is yielded
+ # to the block you provide. The path is set back to the previous path when
+ # the method exits.
+ #
+ # ==== Parameters
+ # dir<String>:: the directory to move to.
+ # config<Hash>:: give :verbose => true to log and use padding.
+ #
+ def inside(dir='', config={}, &block)
+ verbose = config.fetch(:verbose, false)
+
+ say_status :inside, dir, verbose
+ shell.padding += 1 if verbose
+ @destination_stack.push File.expand_path(dir, destination_root)
+
+ FileUtils.mkdir_p(destination_root) unless File.exist?(destination_root)
+ FileUtils.cd(destination_root) { block.arity == 1 ? yield(destination_root) : yield }
+
+ @destination_stack.pop
+ shell.padding -= 1 if verbose
+ end
+
+ # Goes to the root and execute the given block.
+ #
+ def in_root
+ inside(@destination_stack.first) { yield }
+ end
+
+ # Loads an external file and execute it in the instance binding.
+ #
+ # ==== Parameters
+ # path<String>:: The path to the file to execute. Can be a web address or
+ # a relative path from the source root.
+ #
+ # ==== Examples
+ #
+ # apply "http://gist.github.com/103208"
+ #
+ # apply "recipes/jquery.rb"
+ #
+ def apply(path, config={})
+ verbose = config.fetch(:verbose, true)
+ path = find_in_source_paths(path) unless path =~ /^http\:\/\//
+
+ say_status :apply, path, verbose
+ shell.padding += 1 if verbose
+ instance_eval(open(path).read)
+ shell.padding -= 1 if verbose
+ end
+
+ # Executes a command.
+ #
+ # ==== Parameters
+ # command<String>:: the command to be executed.
+ # config<Hash>:: give :verbose => false to not log the status. Specify :with
+ # to append an executable to command executation.
+ #
+ # ==== Example
+ #
+ # inside('vendor') do
+ # run('ln -s ~/edge rails')
+ # end
+ #
+ def run(command, config={})
+ return unless behavior == :invoke
+
+ destination = relative_to_original_destination_root(destination_root, false)
+ desc = "#{command} from #{destination.inspect}"
+
+ if config[:with]
+ desc = "#{File.basename(config[:with].to_s)} #{desc}"
+ command = "#{config[:with]} #{command}"
+ end
+
+ say_status :run, desc, config.fetch(:verbose, true)
+ system(command) unless options[:pretend]
+ end
+
+ # Executes a ruby script (taking into account WIN32 platform quirks).
+ #
+ # ==== Parameters
+ # command<String>:: the command to be executed.
+ # config<Hash>:: give :verbose => false to not log the status.
+ #
+ def run_ruby_script(command, config={})
+ return unless behavior == :invoke
+ run "#{command}", config.merge(:with => Thor::Util.ruby_command)
+ end
+
+ # Run a thor command. A hash of options can be given and it's converted to
+ # switches.
+ #
+ # ==== Parameters
+ # task<String>:: the task to be invoked
+ # args<Array>:: arguments to the task
+ # config<Hash>:: give :verbose => false to not log the status. Other options
+ # are given as parameter to Thor.
+ #
+ # ==== Examples
+ #
+ # thor :install, "http://gist.github.com/103208"
+ # #=> thor install http://gist.github.com/103208
+ #
+ # thor :list, :all => true, :substring => 'rails'
+ # #=> thor list --all --substring=rails
+ #
+ def thor(task, *args)
+ config = args.last.is_a?(Hash) ? args.pop : {}
+ verbose = config.key?(:verbose) ? config.delete(:verbose) : true
+
+ args.unshift task
+ args.push Thor::Options.to_switches(config)
+ command = args.join(' ').strip
+
+ run command, :with => :thor, :verbose => verbose
+ end
+
+ protected
+
+ # Allow current root to be shared between invocations.
+ #
+ def _shared_configuration #:nodoc:
+ super.merge!(:destination_root => self.destination_root)
+ end
+
+ def _cleanup_options_and_set(options, key) #:nodoc:
+ case options
+ when Array
+ %w(--force -f --skip -s).each { |i| options.delete(i) }
+ options << "--#{key}"
+ when Hash
+ [:force, :skip, "force", "skip"].each { |i| options.delete(i) }
+ options.merge!(key => true)
+ end
+ end
+
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions/create_file.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions/create_file.rb
new file mode 100644
index 0000000000..8f6badee27
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions/create_file.rb
@@ -0,0 +1,102 @@
+require 'thor/actions/empty_directory'
+
+class Thor
+ module Actions
+
+ # Create a new file relative to the destination root with the given data,
+ # which is the return value of a block or a data string.
+ #
+ # ==== Parameters
+ # destination<String>:: the relative path to the destination root.
+ # data<String|NilClass>:: the data to append to the file.
+ # config<Hash>:: give :verbose => false to not log the status.
+ #
+ # ==== Examples
+ #
+ # create_file "lib/fun_party.rb" do
+ # hostname = ask("What is the virtual hostname I should use?")
+ # "vhost.name = #{hostname}"
+ # end
+ #
+ # create_file "config/apach.conf", "your apache config"
+ #
+ def create_file(destination, data=nil, config={}, &block)
+ action CreateFile.new(self, destination, block || data.to_s, config)
+ end
+ alias :add_file :create_file
+
+ # AddFile is a subset of Template, which instead of rendering a file with
+ # ERB, it gets the content from the user.
+ #
+ class CreateFile < EmptyDirectory #:nodoc:
+ attr_reader :data
+
+ def initialize(base, destination, data, config={})
+ @data = data
+ super(base, destination, config)
+ end
+
+ # Checks if the content of the file at the destination is identical to the rendered result.
+ #
+ # ==== Returns
+ # Boolean:: true if it is identical, false otherwise.
+ #
+ def identical?
+ exists? && File.read(destination) == render
+ end
+
+ # Holds the content to be added to the file.
+ #
+ def render
+ @render ||= if data.is_a?(Proc)
+ data.call
+ else
+ data
+ end
+ end
+
+ def invoke!
+ invoke_with_conflict_check do
+ FileUtils.mkdir_p(File.dirname(destination))
+ File.open(destination, 'w'){ |f| f.write render }
+ end
+ end
+
+ protected
+
+ # Now on conflict we check if the file is identical or not.
+ #
+ def on_conflict_behavior(&block)
+ if identical?
+ say_status :identical, :blue
+ else
+ options = base.options.merge(config)
+ force_or_skip_or_conflict(options[:force], options[:skip], &block)
+ end
+ end
+
+ # If force is true, run the action, otherwise check if it's not being
+ # skipped. If both are false, show the file_collision menu, if the menu
+ # returns true, force it, otherwise skip.
+ #
+ def force_or_skip_or_conflict(force, skip, &block)
+ if force
+ say_status :force, :yellow
+ block.call unless pretend?
+ elsif skip
+ say_status :skip, :yellow
+ else
+ say_status :conflict, :red
+ force_or_skip_or_conflict(force_on_collision?, true, &block)
+ end
+ end
+
+ # Shows the file collision menu to the user and gets the result.
+ #
+ def force_on_collision?
+ base.shell.file_collision(destination){ render }
+ end
+
+ end
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions/directory.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions/directory.rb
new file mode 100644
index 0000000000..be5eb822ac
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions/directory.rb
@@ -0,0 +1,87 @@
+require 'thor/actions/empty_directory'
+
+class Thor
+ module Actions
+
+ # Copies recursively the files from source directory to root directory.
+ # If any of the files finishes with .tt, it's considered to be a template
+ # and is placed in the destination without the extension .tt. If any
+ # empty directory is found, it's copied and all .empty_directory files are
+ # ignored. Remember that file paths can also be encoded, let's suppose a doc
+ # directory with the following files:
+ #
+ # doc/
+ # components/.empty_directory
+ # README
+ # rdoc.rb.tt
+ # %app_name%.rb
+ #
+ # When invoked as:
+ #
+ # directory "doc"
+ #
+ # It will create a doc directory in the destination with the following
+ # files (assuming that the app_name is "blog"):
+ #
+ # doc/
+ # components/
+ # README
+ # rdoc.rb
+ # blog.rb
+ #
+ # ==== Parameters
+ # source<String>:: the relative path to the source root.
+ # destination<String>:: the relative path to the destination root.
+ # config<Hash>:: give :verbose => false to not log the status.
+ # If :recursive => false, does not look for paths recursively.
+ #
+ # ==== Examples
+ #
+ # directory "doc"
+ # directory "doc", "docs", :recursive => false
+ #
+ def directory(source, destination=nil, config={})
+ action Directory.new(self, source, destination || source, config)
+ end
+
+ class Directory < EmptyDirectory #:nodoc:
+ attr_reader :source
+
+ def initialize(base, source, destination=nil, config={})
+ @source = File.expand_path(base.find_in_source_paths(source.to_s))
+ super(base, destination, { :recursive => true }.merge(config))
+ end
+
+ def invoke!
+ base.empty_directory given_destination, config
+ execute!
+ end
+
+ def revoke!
+ execute!
+ end
+
+ protected
+
+ def execute!
+ lookup = config[:recursive] ? File.join(source, '**') : source
+ lookup = File.join(lookup, '{*,.[a-z]*}')
+
+ Dir[lookup].each do |file_source|
+ next if File.directory?(file_source)
+ file_destination = File.join(given_destination, file_source.gsub(source, '.'))
+
+ case file_source
+ when /\.empty_directory$/
+ base.empty_directory(File.dirname(file_destination), config)
+ when /\.tt$/
+ base.template(file_source, file_destination[0..-4], config)
+ else
+ base.copy_file(file_source, file_destination, config)
+ end
+ end
+ end
+
+ end
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions/empty_directory.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions/empty_directory.rb
new file mode 100644
index 0000000000..03c1fe4af1
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions/empty_directory.rb
@@ -0,0 +1,133 @@
+class Thor
+ module Actions
+
+ # Creates an empty directory.
+ #
+ # ==== Parameters
+ # destination<String>:: the relative path to the destination root.
+ # config<Hash>:: give :verbose => false to not log the status.
+ #
+ # ==== Examples
+ #
+ # empty_directory "doc"
+ #
+ def empty_directory(destination, config={})
+ action EmptyDirectory.new(self, destination, config)
+ end
+
+ # Class which holds create directory logic. This is the base class for
+ # other actions like create_file and directory.
+ #
+ # This implementation is based in Templater actions, created by Jonas Nicklas
+ # and Michael S. Klishin under MIT LICENSE.
+ #
+ class EmptyDirectory #:nodoc:
+ attr_reader :base, :destination, :given_destination, :relative_destination, :config
+
+ # Initializes given the source and destination.
+ #
+ # ==== Parameters
+ # base<Thor::Base>:: A Thor::Base instance
+ # source<String>:: Relative path to the source of this file
+ # destination<String>:: Relative path to the destination of this file
+ # config<Hash>:: give :verbose => false to not log the status.
+ #
+ def initialize(base, destination, config={})
+ @base, @config = base, { :verbose => true }.merge(config)
+ self.destination = destination
+ end
+
+ # Checks if the destination file already exists.
+ #
+ # ==== Returns
+ # Boolean:: true if the file exists, false otherwise.
+ #
+ def exists?
+ ::File.exists?(destination)
+ end
+
+ def invoke!
+ invoke_with_conflict_check do
+ ::FileUtils.mkdir_p(destination)
+ end
+ end
+
+ def revoke!
+ say_status :remove, :red
+ ::FileUtils.rm_rf(destination) if !pretend? && exists?
+ end
+
+ protected
+
+ # Shortcut for pretend.
+ #
+ def pretend?
+ base.options[:pretend]
+ end
+
+ # Sets the absolute destination value from a relative destination value.
+ # It also stores the given and relative destination. Let's suppose our
+ # script is being executed on "dest", it sets the destination root to
+ # "dest". The destination, given_destination and relative_destination
+ # are related in the following way:
+ #
+ # inside "bar" do
+ # empty_directory "baz"
+ # end
+ #
+ # destination #=> dest/bar/baz
+ # relative_destination #=> bar/baz
+ # given_destination #=> baz
+ #
+ def destination=(destination)
+ if destination
+ @given_destination = convert_encoded_instructions(destination.to_s)
+ @destination = ::File.expand_path(@given_destination, base.destination_root)
+ @relative_destination = base.relative_to_original_destination_root(@destination)
+ end
+ end
+
+ # Filenames in the encoded form are converted. If you have a file:
+ #
+ # %class_name%.rb
+ #
+ # It gets the class name from the base and replace it:
+ #
+ # user.rb
+ #
+ def convert_encoded_instructions(filename)
+ filename.gsub(/%(.*?)%/) do |string|
+ instruction = $1.strip
+ base.respond_to?(instruction) ? base.send(instruction) : string
+ end
+ end
+
+ # Receives a hash of options and just execute the block if some
+ # conditions are met.
+ #
+ def invoke_with_conflict_check(&block)
+ if exists?
+ on_conflict_behavior(&block)
+ else
+ say_status :create, :green
+ block.call unless pretend?
+ end
+
+ destination
+ end
+
+ # What to do when the destination file already exists.
+ #
+ def on_conflict_behavior(&block)
+ say_status :exist, :blue
+ end
+
+ # Shortcut to say_status shell method.
+ #
+ def say_status(status, color)
+ base.shell.say_status status, relative_destination, color if config[:verbose]
+ end
+
+ end
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions/file_manipulation.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions/file_manipulation.rb
new file mode 100644
index 0000000000..d77d90d448
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions/file_manipulation.rb
@@ -0,0 +1,219 @@
+require 'erb'
+require 'open-uri'
+
+class Thor
+ module Actions
+
+ # Copies the file from the relative source to the relative destination. If
+ # the destination is not given it's assumed to be equal to the source.
+ #
+ # ==== Parameters
+ # source<String>:: the relative path to the source root.
+ # destination<String>:: the relative path to the destination root.
+ # config<Hash>:: give :verbose => false to not log the status.
+ #
+ # ==== Examples
+ #
+ # copy_file "README", "doc/README"
+ #
+ # copy_file "doc/README"
+ #
+ def copy_file(source, destination=nil, config={})
+ destination ||= source
+ source = File.expand_path(find_in_source_paths(source.to_s))
+
+ create_file destination, nil, config do
+ File.read(source)
+ end
+ end
+
+ # Gets the content at the given address and places it at the given relative
+ # destination. If a block is given instead of destination, the content of
+ # the url is yielded and used as location.
+ #
+ # ==== Parameters
+ # source<String>:: the address of the given content.
+ # destination<String>:: the relative path to the destination root.
+ # config<Hash>:: give :verbose => false to not log the status.
+ #
+ # ==== Examples
+ #
+ # get "http://gist.github.com/103208", "doc/README"
+ #
+ # get "http://gist.github.com/103208" do |content|
+ # content.split("\n").first
+ # end
+ #
+ def get(source, destination=nil, config={}, &block)
+ source = File.expand_path(find_in_source_paths(source.to_s)) unless source =~ /^http\:\/\//
+ render = open(source).read
+
+ destination ||= if block_given?
+ block.arity == 1 ? block.call(render) : block.call
+ else
+ File.basename(source)
+ end
+
+ create_file destination, render, config
+ end
+
+ # Gets an ERB template at the relative source, executes it and makes a copy
+ # at the relative destination. If the destination is not given it's assumed
+ # to be equal to the source removing .tt from the filename.
+ #
+ # ==== Parameters
+ # source<String>:: the relative path to the source root.
+ # destination<String>:: the relative path to the destination root.
+ # config<Hash>:: give :verbose => false to not log the status.
+ #
+ # ==== Examples
+ #
+ # template "README", "doc/README"
+ #
+ # template "doc/README"
+ #
+ def template(source, destination=nil, config={})
+ destination ||= source
+ source = File.expand_path(find_in_source_paths(source.to_s))
+ context = instance_eval('binding')
+
+ create_file destination, nil, config do
+ ERB.new(::File.read(source), nil, '-').result(context)
+ end
+ end
+
+ # Changes the mode of the given file or directory.
+ #
+ # ==== Parameters
+ # mode<Integer>:: the file mode
+ # path<String>:: the name of the file to change mode
+ # config<Hash>:: give :verbose => false to not log the status.
+ #
+ # ==== Example
+ #
+ # chmod "script/*", 0755
+ #
+ def chmod(path, mode, config={})
+ return unless behavior == :invoke
+ path = File.expand_path(path, destination_root)
+ say_status :chmod, relative_to_original_destination_root(path), config.fetch(:verbose, true)
+ FileUtils.chmod_R(mode, path) unless options[:pretend]
+ end
+
+ # Prepend text to a file. Since it depends on inject_into_file, it's reversible.
+ #
+ # ==== Parameters
+ # path<String>:: path of the file to be changed
+ # data<String>:: the data to prepend to the file, can be also given as a block.
+ # config<Hash>:: give :verbose => false to not log the status.
+ #
+ # ==== Example
+ #
+ # prepend_file 'config/environments/test.rb', 'config.gem "rspec"'
+ #
+ # prepend_file 'config/environments/test.rb' do
+ # 'config.gem "rspec"'
+ # end
+ #
+ def prepend_file(path, *args, &block)
+ config = args.last.is_a?(Hash) ? args.pop : {}
+ config.merge!(:after => /\A/)
+ inject_into_file(path, *(args << config), &block)
+ end
+
+ # Append text to a file. Since it depends on inject_into_file, it's reversible.
+ #
+ # ==== Parameters
+ # path<String>:: path of the file to be changed
+ # data<String>:: the data to append to the file, can be also given as a block.
+ # config<Hash>:: give :verbose => false to not log the status.
+ #
+ # ==== Example
+ #
+ # append_file 'config/environments/test.rb', 'config.gem "rspec"'
+ #
+ # append_file 'config/environments/test.rb' do
+ # 'config.gem "rspec"'
+ # end
+ #
+ def append_file(path, *args, &block)
+ config = args.last.is_a?(Hash) ? args.pop : {}
+ config.merge!(:before => /\z/)
+ inject_into_file(path, *(args << config), &block)
+ end
+
+ # Injects text right after the class definition. Since it depends on
+ # inject_into_file, it's reversible.
+ #
+ # ==== Parameters
+ # path<String>:: path of the file to be changed
+ # klass<String|Class>:: the class to be manipulated
+ # data<String>:: the data to append to the class, can be also given as a block.
+ # config<Hash>:: give :verbose => false to not log the status.
+ #
+ # ==== Examples
+ #
+ # inject_into_class "app/controllers/application_controller.rb", " filter_parameter :password\n"
+ #
+ # inject_into_class "app/controllers/application_controller.rb", ApplicationController do
+ # " filter_parameter :password\n"
+ # end
+ #
+ def inject_into_class(path, klass, *args, &block)
+ config = args.last.is_a?(Hash) ? args.pop : {}
+ config.merge!(:after => /class #{klass}\n|class #{klass} .*\n/)
+ inject_into_file(path, *(args << config), &block)
+ end
+
+ # Run a regular expression replacement on a file.
+ #
+ # ==== Parameters
+ # path<String>:: path of the file to be changed
+ # flag<Regexp|String>:: the regexp or string to be replaced
+ # replacement<String>:: the replacement, can be also given as a block
+ # config<Hash>:: give :verbose => false to not log the status.
+ #
+ # ==== Example
+ #
+ # gsub_file 'app/controllers/application_controller.rb', /#\s*(filter_parameter_logging :password)/, '\1'
+ #
+ # gsub_file 'README', /rake/, :green do |match|
+ # match << " no more. Use thor!"
+ # end
+ #
+ def gsub_file(path, flag, *args, &block)
+ return unless behavior == :invoke
+ config = args.last.is_a?(Hash) ? args.pop : {}
+
+ path = File.expand_path(path, destination_root)
+ say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true)
+
+ unless options[:pretend]
+ content = File.read(path)
+ content.gsub!(flag, *args, &block)
+ File.open(path, 'wb') { |file| file.write(content) }
+ end
+ end
+
+ # Removes a file at the given location.
+ #
+ # ==== Parameters
+ # path<String>:: path of the file to be changed
+ # config<Hash>:: give :verbose => false to not log the status.
+ #
+ # ==== Example
+ #
+ # remove_file 'README'
+ # remove_file 'app/controllers/application_controller.rb'
+ #
+ def remove_file(path, config={})
+ return unless behavior == :invoke
+ path = File.expand_path(path, destination_root)
+
+ say_status :remove, relative_to_original_destination_root(path), config.fetch(:verbose, true)
+ ::FileUtils.rm_rf(path) if !options[:pretend] && File.exists?(path)
+ end
+ alias :remove_dir :remove_file
+
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions/inject_into_file.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions/inject_into_file.rb
new file mode 100644
index 0000000000..0636ec6591
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/actions/inject_into_file.rb
@@ -0,0 +1,101 @@
+require 'thor/actions/empty_directory'
+
+class Thor
+ module Actions
+
+ # Injects the given content into a file. Different from gsub_file, this
+ # method is reversible.
+ #
+ # ==== Parameters
+ # destination<String>:: Relative path to the destination root
+ # data<String>:: Data to add to the file. Can be given as a block.
+ # config<Hash>:: give :verbose => false to not log the status and the flag
+ # for injection (:after or :before).
+ #
+ # ==== Examples
+ #
+ # inject_into_file "config/environment.rb", "config.gem :thor", :after => "Rails::Initializer.run do |config|\n"
+ #
+ # inject_into_file "config/environment.rb", :after => "Rails::Initializer.run do |config|\n" do
+ # gems = ask "Which gems would you like to add?"
+ # gems.split(" ").map{ |gem| " config.gem :#{gem}" }.join("\n")
+ # end
+ #
+ def inject_into_file(destination, *args, &block)
+ if block_given?
+ data, config = block, args.shift
+ else
+ data, config = args.shift, args.shift
+ end
+ action InjectIntoFile.new(self, destination, data, config)
+ end
+
+ class InjectIntoFile < EmptyDirectory #:nodoc:
+ attr_reader :replacement, :flag, :behavior
+
+ def initialize(base, destination, data, config)
+ super(base, destination, { :verbose => true }.merge(config))
+
+ @behavior, @flag = if @config.key?(:after)
+ [:after, @config.delete(:after)]
+ else
+ [:before, @config.delete(:before)]
+ end
+
+ @replacement = data.is_a?(Proc) ? data.call : data
+ @flag = Regexp.escape(@flag) unless @flag.is_a?(Regexp)
+ end
+
+ def invoke!
+ say_status :invoke
+
+ content = if @behavior == :after
+ '\0' + replacement
+ else
+ replacement + '\0'
+ end
+
+ replace!(/#{flag}/, content)
+ end
+
+ def revoke!
+ say_status :revoke
+
+ regexp = if @behavior == :after
+ content = '\1\2'
+ /(#{flag})(.*)(#{Regexp.escape(replacement)})/m
+ else
+ content = '\2\3'
+ /(#{Regexp.escape(replacement)})(.*)(#{flag})/m
+ end
+
+ replace!(regexp, content)
+ end
+
+ protected
+
+ def say_status(behavior)
+ status = if flag == /\A/
+ behavior == :invoke ? :prepend : :unprepend
+ elsif flag == /\z/
+ behavior == :invoke ? :append : :unappend
+ else
+ behavior == :invoke ? :inject : :deinject
+ end
+
+ super(status, config[:verbose])
+ end
+
+ # Adds the content to the file.
+ #
+ def replace!(regexp, string)
+ unless base.options[:pretend]
+ content = File.read(destination)
+ content.gsub!(regexp, string)
+ File.open(destination, 'wb') { |file| file.write(content) }
+ end
+ end
+
+ end
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/base.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/base.rb
new file mode 100644
index 0000000000..700d794123
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/base.rb
@@ -0,0 +1,517 @@
+require 'thor/core_ext/hash_with_indifferent_access'
+require 'thor/core_ext/ordered_hash'
+require 'thor/error'
+require 'thor/shell'
+require 'thor/invocation'
+require 'thor/parser'
+require 'thor/task'
+require 'thor/util'
+
+class Thor
+ # Shortcuts for help.
+ HELP_MAPPINGS = %w(-h -? --help -D)
+
+ # Thor methods that should not be overwritten by the user.
+ THOR_RESERVED_WORDS = %w(invoke shell options behavior root destination_root relative_root
+ action add_file create_file in_root inside run run_ruby_script)
+
+ module Base
+ attr_accessor :options
+
+ # It receives arguments in an Array and two hashes, one for options and
+ # other for configuration.
+ #
+ # Notice that it does not check if all required arguments were supplied.
+ # It should be done by the parser.
+ #
+ # ==== Parameters
+ # args<Array[Object]>:: An array of objects. The objects are applied to their
+ # respective accessors declared with <tt>argument</tt>.
+ #
+ # options<Hash>:: An options hash that will be available as self.options.
+ # The hash given is converted to a hash with indifferent
+ # access, magic predicates (options.skip?) and then frozen.
+ #
+ # config<Hash>:: Configuration for this Thor class.
+ #
+ def initialize(args=[], options={}, config={})
+ Thor::Arguments.parse(self.class.arguments, args).each do |key, value|
+ send("#{key}=", value)
+ end
+
+ parse_options = self.class.class_options
+
+ 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
+ array_options, hash_options = [], options
+ end
+
+ options = Thor::Options.parse(parse_options, array_options)
+ self.options = Thor::CoreExt::HashWithIndifferentAccess.new(options).merge!(hash_options)
+ self.options.freeze
+ end
+
+ class << self
+ def included(base) #:nodoc:
+ base.send :extend, ClassMethods
+ base.send :include, Invocation
+ base.send :include, Shell
+ end
+
+ # Returns the classes that inherits from Thor or Thor::Group.
+ #
+ # ==== Returns
+ # Array[Class]
+ #
+ def subclasses
+ @subclasses ||= []
+ end
+
+ # Returns the files where the subclasses are kept.
+ #
+ # ==== Returns
+ # Hash[path<String> => Class]
+ #
+ def subclass_files
+ @subclass_files ||= Hash.new{ |h,k| h[k] = [] }
+ end
+
+ # Whenever a class inherits from Thor or Thor::Group, we should track the
+ # class and the file on Thor::Base. This is the method responsable for it.
+ #
+ def register_klass_file(klass) #:nodoc:
+ file = caller[1].match(/(.*):\d+/)[1]
+ Thor::Base.subclasses << klass unless Thor::Base.subclasses.include?(klass)
+
+ file_subclasses = Thor::Base.subclass_files[File.expand_path(file)]
+ file_subclasses << klass unless file_subclasses.include?(klass)
+ end
+ end
+
+ module ClassMethods
+ # Adds an argument to the class and creates an attr_accessor for it.
+ #
+ # Arguments are different from options in several aspects. The first one
+ # is how they are parsed from the command line, arguments are retrieved
+ # from position:
+ #
+ # thor task NAME
+ #
+ # Instead of:
+ #
+ # thor task --name=NAME
+ #
+ # Besides, arguments are used inside your code as an accessor (self.argument),
+ # while options are all kept in a hash (self.options).
+ #
+ # Finally, arguments cannot have type :default or :boolean but can be
+ # optional (supplying :optional => :true or :required => false), although
+ # you cannot have a required argument after a non-required argument. If you
+ # try it, an error is raised.
+ #
+ # ==== Parameters
+ # name<Symbol>:: The name of the argument.
+ # options<Hash>:: Described below.
+ #
+ # ==== Options
+ # :desc - Description for the argument.
+ # :required - If the argument is required or not.
+ # :optional - If the argument is optional or not.
+ # :type - The type of the argument, can be :string, :hash, :array, :numeric.
+ # :default - Default value for this argument. It cannot be required and have default values.
+ # :banner - String to show on usage notes.
+ #
+ # ==== Errors
+ # ArgumentError:: Raised if you supply a required argument after a non required one.
+ #
+ def argument(name, options={})
+ is_thor_reserved_word?(name, :argument)
+ no_tasks { attr_accessor name }
+
+ required = if options.key?(:optional)
+ !options[:optional]
+ elsif options.key?(:required)
+ options[:required]
+ else
+ options[:default].nil?
+ end
+
+ remove_argument name
+
+ arguments.each do |argument|
+ next if argument.required?
+ raise ArgumentError, "You cannot have #{name.to_s.inspect} as required argument after " <<
+ "the non-required argument #{argument.human_name.inspect}."
+ end if required
+
+ arguments << Thor::Argument.new(name, options[:desc], required, options[:type],
+ options[:default], options[:banner])
+ end
+
+ # Returns this class arguments, looking up in the ancestors chain.
+ #
+ # ==== Returns
+ # Array[Thor::Argument]
+ #
+ def arguments
+ @arguments ||= from_superclass(:arguments, [])
+ end
+
+ # Adds a bunch of options to the set of class options.
+ #
+ # class_options :foo => false, :bar => :required, :baz => :string
+ #
+ # If you prefer more detailed declaration, check class_option.
+ #
+ # ==== Parameters
+ # Hash[Symbol => Object]
+ #
+ def class_options(options=nil)
+ @class_options ||= from_superclass(:class_options, {})
+ build_options(options, @class_options) if options
+ @class_options
+ end
+
+ # Adds an option to the set of class options
+ #
+ # ==== Parameters
+ # name<Symbol>:: The name of the argument.
+ # options<Hash>:: Described below.
+ #
+ # ==== Options
+ # :desc - Description for the argument.
+ # :required - If the argument is required or not.
+ # :default - Default value for this argument.
+ # :group - The group for this options. Use by class options to output options in different levels.
+ # :aliases - Aliases for this option.
+ # :type - The type of the argument, can be :string, :hash, :array, :numeric or :boolean.
+ # :banner - String to show on usage notes.
+ #
+ def class_option(name, options={})
+ build_option(name, options, class_options)
+ end
+
+ # Removes a previous defined argument. If :undefine is given, undefine
+ # accessors as well.
+ #
+ # ==== Paremeters
+ # names<Array>:: Arguments to be removed
+ #
+ # ==== Examples
+ #
+ # remove_argument :foo
+ # remove_argument :foo, :bar, :baz, :undefine => true
+ #
+ def remove_argument(*names)
+ options = names.last.is_a?(Hash) ? names.pop : {}
+
+ names.each do |name|
+ arguments.delete_if { |a| a.name == name.to_s }
+ undef_method name, "#{name}=" if options[:undefine]
+ end
+ end
+
+ # Removes a previous defined class option.
+ #
+ # ==== Paremeters
+ # names<Array>:: Class options to be removed
+ #
+ # ==== Examples
+ #
+ # remove_class_option :foo
+ # remove_class_option :foo, :bar, :baz
+ #
+ def remove_class_option(*names)
+ names.each do |name|
+ class_options.delete(name)
+ end
+ end
+
+ # Defines the group. This is used when thor list is invoked so you can specify
+ # that only tasks from a pre-defined group will be shown. Defaults to standard.
+ #
+ # ==== Parameters
+ # name<String|Symbol>
+ #
+ def group(name=nil)
+ case name
+ when nil
+ @group ||= from_superclass(:group, 'standard')
+ else
+ @group = name.to_s
+ end
+ end
+
+ # Returns the tasks for this Thor class.
+ #
+ # ==== Returns
+ # OrderedHash:: An ordered hash with tasks names as keys and Thor::Task
+ # objects as values.
+ #
+ def tasks
+ @tasks ||= Thor::CoreExt::OrderedHash.new
+ end
+
+ # Returns the tasks for this Thor class and all subclasses.
+ #
+ # ==== Returns
+ # OrderedHash:: An ordered hash with tasks names as keys and Thor::Task
+ # objects as values.
+ #
+ def all_tasks
+ @all_tasks ||= from_superclass(:all_tasks, Thor::CoreExt::OrderedHash.new)
+ @all_tasks.merge(tasks)
+ end
+
+ # Removes a given task from this Thor class. This is usually done if you
+ # are inheriting from another class and don't want it to be available
+ # anymore.
+ #
+ # By default it only remove the mapping to the task. But you can supply
+ # :undefine => true to undefine the method from the class as well.
+ #
+ # ==== Parameters
+ # name<Symbol|String>:: The name of the task to be removed
+ # options<Hash>:: You can give :undefine => true if you want tasks the method
+ # to be undefined from the class as well.
+ #
+ def remove_task(*names)
+ options = names.last.is_a?(Hash) ? names.pop : {}
+
+ names.each do |name|
+ tasks.delete(name.to_s)
+ all_tasks.delete(name.to_s)
+ undef_method name if options[:undefine]
+ end
+ end
+
+ # All methods defined inside the given block are not added as tasks.
+ #
+ # So you can do:
+ #
+ # class MyScript < Thor
+ # no_tasks do
+ # def this_is_not_a_task
+ # end
+ # end
+ # end
+ #
+ # You can also add the method and remove it from the task list:
+ #
+ # class MyScript < Thor
+ # def this_is_not_a_task
+ # end
+ # remove_task :this_is_not_a_task
+ # end
+ #
+ def no_tasks
+ @no_tasks = true
+ yield
+ @no_tasks = false
+ end
+
+ # Sets the namespace for the Thor or Thor::Group class. By default the
+ # namespace is retrieved from the class name. If your Thor class is named
+ # Scripts::MyScript, the help method, for example, will be called as:
+ #
+ # thor scripts:my_script -h
+ #
+ # If you change the namespace:
+ #
+ # namespace :my_scripts
+ #
+ # You change how your tasks are invoked:
+ #
+ # thor my_scripts -h
+ #
+ # Finally, if you change your namespace to default:
+ #
+ # namespace :default
+ #
+ # Your tasks can be invoked with a shortcut. Instead of:
+ #
+ # thor :my_task
+ #
+ def namespace(name=nil)
+ case name
+ when nil
+ @namespace ||= Thor::Util.namespace_from_thor_class(self, false)
+ else
+ @namespace = name.to_s
+ end
+ end
+
+ # Default way to start generators from the command line.
+ #
+ def start(given_args=ARGV, config={})
+ config[:shell] ||= Thor::Base.shell.new
+ yield
+ rescue Thor::Error => e
+ if given_args.include?("--debug")
+ raise e
+ else
+ config[:shell].error e.message
+ end
+ exit(1) if exit_on_failure?
+ end
+
+ protected
+
+ # Prints the class options per group. If an option does not belong to
+ # any group, it uses the ungrouped name value. This method provide to
+ # hooks to add extra options, one of them if the third argument called
+ # extra_group that should be a hash in the format :group => Array[Options].
+ #
+ # The second is by returning a lambda used to print values. The lambda
+ # requires two options: the group name and the array of options.
+ #
+ def class_options_help(shell, ungrouped_name=nil, extra_group=nil) #:nodoc:
+ groups = {}
+
+ class_options.each do |_, value|
+ groups[value.group] ||= []
+ groups[value.group] << value
+ end
+
+ printer = proc do |group_name, options|
+ list = []
+ padding = options.collect{ |o| o.aliases.size }.max.to_i * 4
+
+ options.each do |option|
+ item = [ option.usage(padding) ]
+ item.push(option.description ? "# #{option.description}" : "")
+
+ list << item
+ list << [ "", "# Default: #{option.default}" ] if option.show_default?
+ end
+
+ unless list.empty?
+ shell.say(group_name ? "#{group_name} options:" : "Options:")
+ shell.print_table(list, :ident => 2)
+ shell.say ""
+ end
+ end
+
+ # Deal with default group
+ global_options = groups.delete(nil) || []
+ printer.call(ungrouped_name, global_options) if global_options
+
+ # Print all others
+ groups = extra_group.merge(groups) if extra_group
+ groups.each(&printer)
+ printer
+ end
+
+ # Raises an error if the word given is a Thor reserved word.
+ #
+ def is_thor_reserved_word?(word, type) #:nodoc:
+ return false unless THOR_RESERVED_WORDS.include?(word.to_s)
+ raise "#{word.inspect} is a Thor reserved word and cannot be defined as #{type}"
+ end
+
+ # Build an option and adds it to the given scope.
+ #
+ # ==== Parameters
+ # name<Symbol>:: The name of the argument.
+ # options<Hash>:: Described in both class_option and method_option.
+ #
+ def build_option(name, options, scope) #:nodoc:
+ scope[name] = Thor::Option.new(name, options[:desc], options[:required],
+ options[:type], options[:default], options[:banner],
+ options[:group], options[:aliases])
+ end
+
+ # Receives a hash of options, parse them and add to the scope. This is a
+ # fast way to set a bunch of options:
+ #
+ # build_options :foo => true, :bar => :required, :baz => :string
+ #
+ # ==== Parameters
+ # Hash[Symbol => Object]
+ #
+ def build_options(options, scope) #:nodoc:
+ options.each do |key, value|
+ scope[key] = Thor::Option.parse(key, value)
+ end
+ end
+
+ # Finds a task with the given name. If the task belongs to the current
+ # class, just return it, otherwise dup it and add the fresh copy to the
+ # current task hash.
+ #
+ def find_and_refresh_task(name) #:nodoc:
+ task = if task = tasks[name.to_s]
+ task
+ elsif task = all_tasks[name.to_s]
+ tasks[name.to_s] = task.clone
+ else
+ raise ArgumentError, "You supplied :for => #{name.inspect}, but the task #{name.inspect} could not be found."
+ end
+ end
+
+ # Everytime someone inherits from a Thor class, register the klass
+ # and file into baseclass.
+ #
+ def inherited(klass)
+ Thor::Base.register_klass_file(klass)
+ end
+
+ # Fire this callback whenever a method is added. Added methods are
+ # tracked as tasks by invoking the create_task method.
+ #
+ def method_added(meth)
+ meth = meth.to_s
+
+ if meth == "initialize"
+ initialize_added
+ return
+ end
+
+ # Return if it's not a public instance method
+ return unless public_instance_methods.include?(meth) ||
+ public_instance_methods.include?(meth.to_sym)
+
+ return if @no_tasks || !create_task(meth)
+
+ is_thor_reserved_word?(meth, :task)
+ Thor::Base.register_klass_file(self)
+ end
+
+ # Retrieves a value from superclass. If it reaches the baseclass,
+ # returns default.
+ #
+ def from_superclass(method, default=nil)
+ if self == baseclass || !superclass.respond_to?(method, true)
+ default
+ else
+ value = superclass.send(method)
+ value.dup if value
+ end
+ end
+
+ # A flag that makes the process exit with status 1 if any error happens.
+ #
+ def exit_on_failure?
+ false
+ end
+
+ # SIGNATURE: Sets the baseclass. This is where the superclass lookup
+ # finishes.
+ def baseclass #:nodoc:
+ end
+
+ # SIGNATURE: Creates a new task if valid_task? is true. This method is
+ # called when a new method is added to the class.
+ def create_task(meth) #:nodoc:
+ end
+
+ # SIGNATURE: Defines behavior when the initialize method is added to the
+ # class.
+ def initialize_added #:nodoc:
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/core_ext/hash_with_indifferent_access.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/core_ext/hash_with_indifferent_access.rb
new file mode 100644
index 0000000000..78bc5cf4bf
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/core_ext/hash_with_indifferent_access.rb
@@ -0,0 +1,75 @@
+class Thor
+ module CoreExt #:nodoc:
+
+ # A hash with indifferent access and magic predicates.
+ #
+ # hash = Thor::CoreExt::HashWithIndifferentAccess.new 'foo' => 'bar', 'baz' => 'bee', 'force' => true
+ #
+ # hash[:foo] #=> 'bar'
+ # hash['foo'] #=> 'bar'
+ # hash.foo? #=> true
+ #
+ class HashWithIndifferentAccess < ::Hash #:nodoc:
+
+ def initialize(hash={})
+ super()
+ hash.each do |key, value|
+ self[convert_key(key)] = value
+ end
+ end
+
+ def [](key)
+ super(convert_key(key))
+ end
+
+ def []=(key, value)
+ super(convert_key(key), value)
+ end
+
+ def delete(key)
+ super(convert_key(key))
+ end
+
+ def values_at(*indices)
+ indices.collect { |key| self[convert_key(key)] }
+ end
+
+ def merge(other)
+ dup.merge!(other)
+ end
+
+ def merge!(other)
+ other.each do |key, value|
+ self[convert_key(key)] = value
+ end
+ self
+ end
+
+ protected
+
+ def convert_key(key)
+ key.is_a?(Symbol) ? key.to_s : key
+ end
+
+ # Magic predicates. For instance:
+ #
+ # options.force? # => !!options['force']
+ # options.shebang # => "/usr/lib/local/ruby"
+ # options.test_framework?(:rspec) # => options[:test_framework] == :rspec
+ #
+ def method_missing(method, *args, &block)
+ method = method.to_s
+ if method =~ /^(\w+)\?$/
+ if args.empty?
+ !!self[$1]
+ else
+ self[$1] == args.first
+ end
+ else
+ self[method]
+ end
+ end
+
+ end
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/core_ext/ordered_hash.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/core_ext/ordered_hash.rb
new file mode 100644
index 0000000000..27fea5bb35
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/core_ext/ordered_hash.rb
@@ -0,0 +1,100 @@
+class Thor
+ module CoreExt #:nodoc:
+
+ if RUBY_VERSION >= '1.9'
+ class OrderedHash < ::Hash
+ end
+ else
+ # This class is based on the Ruby 1.9 ordered hashes.
+ #
+ # It keeps the semantics and most of the efficiency of normal hashes
+ # while also keeping track of the order in which elements were set.
+ #
+ class OrderedHash #:nodoc:
+ include Enumerable
+
+ Node = Struct.new(:key, :value, :next, :prev)
+
+ def initialize
+ @hash = {}
+ end
+
+ def [](key)
+ @hash[key] && @hash[key].value
+ end
+
+ def []=(key, value)
+ if node = @hash[key]
+ node.value = value
+ else
+ node = Node.new(key, value)
+
+ if @first.nil?
+ @first = @last = node
+ else
+ node.prev = @last
+ @last.next = node
+ @last = node
+ end
+ end
+
+ @hash[key] = node
+ value
+ end
+
+ def delete(key)
+ if node = @hash[key]
+ prev_node = node.prev
+ next_node = node.next
+
+ next_node.prev = prev_node if next_node
+ prev_node.next = next_node if prev_node
+
+ @first = next_node if @first == node
+ @last = prev_node if @last == node
+
+ value = node.value
+ end
+
+ @hash.delete(key)
+ value
+ end
+
+ def keys
+ self.map { |k, v| k }
+ end
+
+ def values
+ self.map { |k, v| v }
+ end
+
+ def each
+ return unless @first
+ yield [@first.key, @first.value]
+ node = @first
+ yield [node.key, node.value] while node = node.next
+ self
+ end
+
+ def merge(other)
+ hash = self.class.new
+
+ self.each do |key, value|
+ hash[key] = value
+ end
+
+ other.each do |key, value|
+ hash[key] = value
+ end
+
+ hash
+ end
+
+ def empty?
+ @hash.empty?
+ end
+ end
+ end
+
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/error.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/error.rb
new file mode 100644
index 0000000000..f9b31a35d1
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/error.rb
@@ -0,0 +1,27 @@
+class Thor
+ # Thor::Error is raised when it's caused by wrong usage of thor classes. Those
+ # errors have their backtrace supressed and are nicely shown to the user.
+ #
+ # Errors that are caused by the developer, like declaring a method which
+ # overwrites a thor keyword, it SHOULD NOT raise a Thor::Error. This way, we
+ # ensure that developer errors are shown with full backtrace.
+ #
+ class Error < StandardError
+ end
+
+ # Raised when a task was not found.
+ #
+ class UndefinedTaskError < Error
+ end
+
+ # Raised when a task was found, but not invoked properly.
+ #
+ class InvocationError < Error
+ end
+
+ class RequiredArgumentMissingError < InvocationError
+ end
+
+ class MalformattedArgumentError < InvocationError
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/group.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/group.rb
new file mode 100644
index 0000000000..1e59df2313
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/group.rb
@@ -0,0 +1,263 @@
+# Thor has a special class called Thor::Group. The main difference to Thor class
+# is that it invokes all tasks at once. It also include some methods that allows
+# invocations to be done at the class method, which are not available to Thor
+# tasks.
+#
+class Thor::Group
+ class << self
+ # The descrition for this Thor::Group. If none is provided, but a source root
+ # exists, tries to find the USAGE one folder above it, otherwise searches
+ # in the superclass.
+ #
+ # ==== Parameters
+ # description<String>:: The description for this Thor::Group.
+ #
+ def desc(description=nil)
+ case description
+ when nil
+ @desc ||= from_superclass(:desc, nil)
+ else
+ @desc = description
+ end
+ end
+
+ # Start works differently in Thor::Group, it simply invokes all tasks
+ # inside the class.
+ #
+ def start(given_args=ARGV, config={})
+ super do
+ if Thor::HELP_MAPPINGS.include?(given_args.first)
+ help(config[:shell])
+ return
+ end
+
+ args, opts = Thor::Options.split(given_args)
+ new(args, opts, config).invoke
+ end
+ end
+
+ # Prints help information.
+ #
+ # ==== Options
+ # short:: When true, shows only usage.
+ #
+ def help(shell, options={})
+ if options[:short]
+ shell.say banner
+ else
+ shell.say "Usage:"
+ shell.say " #{banner}"
+ shell.say
+ class_options_help(shell)
+ shell.say self.desc if self.desc
+ end
+ end
+
+ # Stores invocations for this class merging with superclass values.
+ #
+ def invocations #:nodoc:
+ @invocations ||= from_superclass(:invocations, {})
+ end
+
+ # Stores invocation blocks used on invoke_from_option.
+ #
+ def invocation_blocks #:nodoc:
+ @invocation_blocks ||= from_superclass(:invocation_blocks, {})
+ end
+
+ # Invoke the given namespace or class given. It adds an instance
+ # method that will invoke the klass and task. You can give a block to
+ # configure how it will be invoked.
+ #
+ # The namespace/class given will have its options showed on the help
+ # usage. Check invoke_from_option for more information.
+ #
+ def invoke(*names, &block)
+ options = names.last.is_a?(Hash) ? names.pop : {}
+ verbose = options.fetch(:verbose, :white)
+
+ names.each do |name|
+ invocations[name] = false
+ invocation_blocks[name] = block if block_given?
+
+ class_eval <<-METHOD, __FILE__, __LINE__
+ def _invoke_#{name.to_s.gsub(/\W/, '_')}
+ klass, task = self.class.prepare_for_invocation(nil, #{name.inspect})
+
+ if klass
+ say_status :invoke, #{name.inspect}, #{verbose.inspect}
+ block = self.class.invocation_blocks[#{name.inspect}]
+ _invoke_for_class_method klass, task, &block
+ else
+ say_status :error, %(#{name.inspect} [not found]), :red
+ end
+ end
+ METHOD
+ end
+ end
+
+ # Invoke a thor class based on the value supplied by the user to the
+ # given option named "name". A class option must be created before this
+ # method is invoked for each name given.
+ #
+ # ==== Examples
+ #
+ # class GemGenerator < Thor::Group
+ # class_option :test_framework, :type => :string
+ # invoke_from_option :test_framework
+ # end
+ #
+ # ==== Boolean options
+ #
+ # In some cases, you want to invoke a thor class if some option is true or
+ # false. This is automatically handled by invoke_from_option. Then the
+ # option name is used to invoke the generator.
+ #
+ # ==== Preparing for invocation
+ #
+ # In some cases you want to customize how a specified hook is going to be
+ # invoked. You can do that by overwriting the class method
+ # prepare_for_invocation. The class method must necessarily return a klass
+ # and an optional task.
+ #
+ # ==== Custom invocations
+ #
+ # You can also supply a block to customize how the option is giong to be
+ # invoked. The block receives two parameters, an instance of the current
+ # class and the klass to be invoked.
+ #
+ def invoke_from_option(*names, &block)
+ options = names.last.is_a?(Hash) ? names.pop : {}
+ verbose = options.fetch(:verbose, :white)
+
+ names.each do |name|
+ unless class_options.key?(name)
+ raise ArgumentError, "You have to define the option #{name.inspect} " <<
+ "before setting invoke_from_option."
+ end
+
+ invocations[name] = true
+ invocation_blocks[name] = block if block_given?
+
+ class_eval <<-METHOD, __FILE__, __LINE__
+ def _invoke_from_option_#{name.to_s.gsub(/\W/, '_')}
+ return unless options[#{name.inspect}]
+
+ value = options[#{name.inspect}]
+ value = #{name.inspect} if TrueClass === value
+ klass, task = self.class.prepare_for_invocation(#{name.inspect}, value)
+
+ if klass
+ say_status :invoke, value, #{verbose.inspect}
+ block = self.class.invocation_blocks[#{name.inspect}]
+ _invoke_for_class_method klass, task, &block
+ else
+ say_status :error, %(\#{value} [not found]), :red
+ end
+ end
+ METHOD
+ end
+ end
+
+ # Remove a previously added invocation.
+ #
+ # ==== Examples
+ #
+ # remove_invocation :test_framework
+ #
+ def remove_invocation(*names)
+ names.each do |name|
+ remove_task(name)
+ remove_class_option(name)
+ invocations.delete(name)
+ invocation_blocks.delete(name)
+ end
+ end
+
+ # Overwrite class options help to allow invoked generators options to be
+ # shown recursively when invoking a generator.
+ #
+ def class_options_help(shell, ungrouped_name=nil, extra_group=nil) #:nodoc:
+ group_options = {}
+
+ get_options_from_invocations(group_options, class_options) do |klass|
+ klass.send(:get_options_from_invocations, group_options, class_options)
+ end
+
+ group_options.merge!(extra_group) if extra_group
+ super(shell, ungrouped_name, group_options)
+ end
+
+ # Get invocations array and merge options from invocations. Those
+ # options are added to group_options hash. Options that already exists
+ # in base_options are not added twice.
+ #
+ def get_options_from_invocations(group_options, base_options) #:nodoc:
+ invocations.each do |name, from_option|
+ value = if from_option
+ option = class_options[name]
+ option.type == :boolean ? name : option.default
+ else
+ name
+ end
+ next unless value
+
+ klass, task = prepare_for_invocation(name, value)
+ next unless klass && klass.respond_to?(:class_options)
+
+ value = value.to_s
+ 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 }
+ end
+
+ yield klass if block_given?
+ end
+ end
+
+ protected
+
+ # The banner for this class. You can customize it if you are invoking the
+ # thor class by another ways which is not the Thor::Runner.
+ #
+ def banner
+ "#{self.namespace} #{self.arguments.map {|a| a.usage }.join(' ')}"
+ end
+
+ def baseclass #:nodoc:
+ Thor::Group
+ end
+
+ def create_task(meth) #:nodoc:
+ tasks[meth.to_s] = Thor::Task.new(meth, nil, nil, nil)
+ true
+ end
+ end
+
+ include Thor::Base
+
+ protected
+
+ # Shortcut to invoke with padding and block handling. Use internally by
+ # invoke and invoke_from_option class methods.
+ #
+ def _invoke_for_class_method(klass, task=nil, *args, &block) #:nodoc:
+ shell.padding += 1
+
+ result = if block_given?
+ if block.arity == 2
+ block.call(self, klass)
+ else
+ block.call(self, klass, task)
+ end
+ else
+ invoke klass, task, *args
+ end
+
+ shell.padding -= 1
+ result
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/invocation.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/invocation.rb
new file mode 100644
index 0000000000..32e6a72454
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/invocation.rb
@@ -0,0 +1,178 @@
+class Thor
+ module Invocation
+ def self.included(base) #:nodoc:
+ base.extend ClassMethods
+ end
+
+ module ClassMethods
+ # Prepare for class methods invocations. This method must return a klass to
+ # have the invoked class options showed in help messages in generators.
+ #
+ def prepare_for_invocation(key, name) #:nodoc:
+ case name
+ when Symbol, String
+ Thor::Util.namespace_to_thor_class_and_task(name.to_s, false)
+ else
+ name
+ end
+ end
+ end
+
+ # Make initializer aware of invocations and the initializer proc.
+ #
+ def initialize(args=[], options={}, config={}, &block) #:nodoc:
+ @_invocations = config[:invocations] || Hash.new { |h,k| h[k] = [] }
+ @_initializer = [ args, options, config ]
+ super
+ end
+
+ # Receives a name and invokes it. The name can be a string (either "task" or
+ # "namespace:task"), a Thor::Task, a Class or a Thor instance. If the task
+ # cannot be guessed by name, it can also be supplied as second argument.
+ #
+ # You can also supply the arguments, options and configuration values for
+ # the task to be invoked, if none is given, the same values used to
+ # initialize the invoker are used to initialize the invoked.
+ #
+ # ==== Examples
+ #
+ # class A < Thor
+ # def foo
+ # invoke :bar
+ # invoke "b:hello", ["José"]
+ # end
+ #
+ # def bar
+ # invoke "b:hello", ["José"]
+ # end
+ # end
+ #
+ # class B < Thor
+ # def hello(name)
+ # puts "hello #{name}"
+ # end
+ # end
+ #
+ # You can notice that the method "foo" above invokes two tasks: "bar",
+ # which belongs to the same class and "hello" which belongs to the class B.
+ #
+ # By using an invocation system you ensure that a task is invoked only once.
+ # In the example above, invoking "foo" will invoke "b:hello" just once, even
+ # if it's invoked later by "bar" method.
+ #
+ # When class A invokes class B, all arguments used on A initialization are
+ # supplied to B. This allows lazy parse of options. Let's suppose you have
+ # some rspec tasks:
+ #
+ # class Rspec < Thor::Group
+ # class_option :mock_framework, :type => :string, :default => :rr
+ #
+ # def invoke_mock_framework
+ # invoke "rspec:#{options[:mock_framework]}"
+ # end
+ # end
+ #
+ # As you noticed, it invokes the given mock framework, which might have its
+ # own options:
+ #
+ # class Rspec::RR < Thor::Group
+ # class_option :style, :type => :string, :default => :mock
+ # end
+ #
+ # Since it's not rspec concern to parse mock framework options, when RR
+ # is invoked all options are parsed again, so RR can extract only the options
+ # that it's going to use.
+ #
+ # If you want Rspec::RR to be initialized with its own set of options, you
+ # have to do that explicitely:
+ #
+ # invoke "rspec:rr", [], :style => :foo
+ #
+ # Besides giving an instance, you can also give a class to invoke:
+ #
+ # invoke Rspec::RR, [], :style => :foo
+ #
+ def invoke(name=nil, task=nil, args=nil, opts=nil, config=nil)
+ task, args, opts, config = nil, task, args, opts if task.nil? || task.is_a?(Array)
+ args, opts, config = nil, args, opts if args.is_a?(Hash)
+
+ object, task = _prepare_for_invocation(name, task)
+ klass, instance = _initialize_klass_with_initializer(object, args, opts, config)
+
+ method_args = []
+ current = @_invocations[klass]
+
+ iterator = proc do |_, task|
+ unless current.include?(task.name)
+ current << task.name
+ task.run(instance, method_args)
+ end
+ end
+
+ if task
+ args ||= []
+ method_args = args[Range.new(klass.arguments.size, -1)] || []
+ iterator.call(nil, task)
+ else
+ klass.all_tasks.map(&iterator)
+ end
+ end
+
+ protected
+
+ # Configuration values that are shared between invocations.
+ #
+ def _shared_configuration #:nodoc:
+ { :invocations => @_invocations }
+ end
+
+ # Prepare for invocation in the instance level. In this case, we have to
+ # take into account that a just a task name from the current class was
+ # given or even a Thor::Task object.
+ #
+ def _prepare_for_invocation(name, sent_task=nil) #:nodoc:
+ if name.is_a?(Thor::Task)
+ task = name
+ elsif task = self.class.all_tasks[name.to_s]
+ object = self
+ else
+ object, task = self.class.prepare_for_invocation(nil, name)
+ task ||= sent_task
+ end
+
+ # If the object was not set, use self and use the name as task.
+ object, task = self, name unless object
+ return object, _validate_task(object, task)
+ end
+
+ # Check if the object given is a Thor class object and get a task object
+ # for it.
+ #
+ def _validate_task(object, task) #:nodoc:
+ klass = object.is_a?(Class) ? object : object.class
+ raise "Expected Thor class, got #{klass}" unless klass <= Thor::Base
+
+ task ||= klass.default_task if klass <= Thor
+ task = klass.all_tasks[task.to_s] || Thor::Task::Dynamic.new(task) if task && !task.is_a?(Thor::Task)
+ task
+ end
+
+ # Initialize klass using values stored in the @_initializer.
+ #
+ def _initialize_klass_with_initializer(object, args, opts, config) #:nodoc:
+ if object.is_a?(Class)
+ klass = object
+
+ stored_args, stored_opts, stored_config = @_initializer
+ args ||= stored_args.dup
+ opts ||= stored_opts.dup
+
+ config ||= {}
+ config = stored_config.merge(_shared_configuration).merge!(config)
+ [ klass, klass.new(args, opts, config) ]
+ else
+ [ object.class, object ]
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/parser.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/parser.rb
new file mode 100644
index 0000000000..57a3f6e1a5
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/parser.rb
@@ -0,0 +1,4 @@
+require 'thor/parser/argument'
+require 'thor/parser/arguments'
+require 'thor/parser/option'
+require 'thor/parser/options'
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/parser/argument.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/parser/argument.rb
new file mode 100644
index 0000000000..aa8ace4719
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/parser/argument.rb
@@ -0,0 +1,67 @@
+class Thor
+ class Argument #:nodoc:
+ VALID_TYPES = [ :numeric, :hash, :array, :string ]
+
+ attr_reader :name, :description, :required, :type, :default, :banner
+ alias :human_name :name
+
+ def initialize(name, description=nil, required=true, type=:string, default=nil, banner=nil)
+ class_name = self.class.name.split("::").last
+
+ raise ArgumentError, "#{class_name} name can't be nil." if name.nil?
+ raise ArgumentError, "Type :#{type} is not valid for #{class_name.downcase}s." if type && !valid_type?(type)
+
+ @name = name.to_s
+ @description = description
+ @required = required || false
+ @type = (type || :string).to_sym
+ @default = default
+ @banner = banner || default_banner
+
+ validate! # Trigger specific validations
+ end
+
+ def usage
+ required? ? banner : "[#{banner}]"
+ end
+
+ def required?
+ required
+ end
+
+ def show_default?
+ case default
+ when Array, String, Hash
+ !default.empty?
+ else
+ default
+ end
+ end
+
+ protected
+
+ def validate!
+ raise ArgumentError, "An argument cannot be required and have default value." if required? && !default.nil?
+ end
+
+ def valid_type?(type)
+ VALID_TYPES.include?(type.to_sym)
+ end
+
+ def default_banner
+ case type
+ when :boolean
+ nil
+ when :string, :default
+ human_name.upcase
+ when :numeric
+ "N"
+ when :hash
+ "key:value"
+ when :array
+ "one two three"
+ end
+ end
+
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/parser/arguments.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/parser/arguments.rb
new file mode 100644
index 0000000000..fb5d965e06
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/parser/arguments.rb
@@ -0,0 +1,145 @@
+class Thor
+ class Arguments #:nodoc:
+ NUMERIC = /(\d*\.\d+|\d+)/
+
+ # Receives an array of args and returns two arrays, one with arguments
+ # and one with switches.
+ #
+ def self.split(args)
+ arguments = []
+
+ args.each do |item|
+ break if item =~ /^-/
+ arguments << item
+ end
+
+ return arguments, args[Range.new(arguments.size, -1)]
+ end
+
+ def self.parse(base, args)
+ new(base).parse(args)
+ end
+
+ # Takes an array of Thor::Argument objects.
+ #
+ def initialize(arguments=[])
+ @assigns, @non_assigned_required = {}, []
+ @switches = arguments
+
+ arguments.each do |argument|
+ if argument.default
+ @assigns[argument.human_name] = argument.default
+ elsif argument.required?
+ @non_assigned_required << argument
+ end
+ end
+ end
+
+ def parse(args)
+ @pile = args.dup
+
+ @switches.each do |argument|
+ break unless peek
+ @non_assigned_required.delete(argument)
+ @assigns[argument.human_name] = send(:"parse_#{argument.type}", argument.human_name)
+ end
+
+ check_requirement!
+ @assigns
+ end
+
+ private
+
+ def peek
+ @pile.first
+ end
+
+ def shift
+ @pile.shift
+ end
+
+ def unshift(arg)
+ unless arg.kind_of?(Array)
+ @pile.unshift(arg)
+ else
+ @pile = arg + @pile
+ end
+ end
+
+ def current_is_value?
+ peek && peek.to_s !~ /^-/
+ end
+
+ # Runs through the argument array getting strings that contains ":" and
+ # mark it as a hash:
+ #
+ # [ "name:string", "age:integer" ]
+ #
+ # Becomes:
+ #
+ # { "name" => "string", "age" => "integer" }
+ #
+ def parse_hash(name)
+ return shift if peek.is_a?(Hash)
+ hash = {}
+
+ while current_is_value? && peek.include?(?:)
+ key, value = shift.split(':')
+ hash[key] = value
+ end
+ hash
+ end
+
+ # Runs through the argument array getting all strings until no string is
+ # found or a switch is found.
+ #
+ # ["a", "b", "c"]
+ #
+ # And returns it as an array:
+ #
+ # ["a", "b", "c"]
+ #
+ def parse_array(name)
+ return shift if peek.is_a?(Array)
+ array = []
+
+ while current_is_value?
+ array << shift
+ end
+ array
+ end
+
+ # Check if the peel is numeric ofrmat and return a Float or Integer.
+ # Otherwise raises an error.
+ #
+ def parse_numeric(name)
+ return shift if peek.is_a?(Numeric)
+
+ unless peek =~ NUMERIC && $& == peek
+ raise MalformattedArgumentError, "expected numeric value for '#{name}'; got #{peek.inspect}"
+ end
+
+ $&.index('.') ? shift.to_f : shift.to_i
+ end
+
+ # Parse string, i.e., just return the current value in the pile.
+ #
+ def parse_string(name)
+ shift
+ end
+
+ # Raises an error if @non_assigned_required array is not empty.
+ #
+ def check_requirement!
+ unless @non_assigned_required.empty?
+ names = @non_assigned_required.map do |o|
+ o.respond_to?(:switch_name) ? o.switch_name : o.human_name
+ end.join("', '")
+
+ class_name = self.class.name.split('::').last.downcase
+ raise RequiredArgumentMissingError, "no value provided for required #{class_name} '#{names}'"
+ end
+ end
+
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/parser/option.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/parser/option.rb
new file mode 100644
index 0000000000..9e40ec73fa
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/parser/option.rb
@@ -0,0 +1,132 @@
+class Thor
+ class Option < Argument #:nodoc:
+ attr_reader :aliases, :group
+
+ VALID_TYPES = [:boolean, :numeric, :hash, :array, :string]
+
+ def initialize(name, description=nil, required=nil, type=nil, default=nil, banner=nil, group=nil, aliases=nil)
+ super(name, description, required, type, default, banner)
+ @aliases = [*aliases].compact
+ @group = group.to_s.capitalize if group
+ end
+
+ # This parse quick options given as method_options. It makes several
+ # assumptions, but you can be more specific using the option method.
+ #
+ # parse :foo => "bar"
+ # #=> Option foo with default value bar
+ #
+ # parse [:foo, :baz] => "bar"
+ # #=> Option foo with default value bar and alias :baz
+ #
+ # parse :foo => :required
+ # #=> Required option foo without default value
+ #
+ # parse :foo => 2
+ # #=> Option foo with default value 2 and type numeric
+ #
+ # parse :foo => :numeric
+ # #=> Option foo without default value and type numeric
+ #
+ # parse :foo => true
+ # #=> Option foo with default value true and type boolean
+ #
+ # The valid types are :boolean, :numeric, :hash, :array and :string. If none
+ # is given a default type is assumed. This default type accepts arguments as
+ # string (--foo=value) or booleans (just --foo).
+ #
+ # By default all options are optional, unless :required is given.
+ #
+ def self.parse(key, value)
+ if key.is_a?(Array)
+ name, *aliases = key
+ else
+ name, aliases = key, []
+ end
+
+ name = name.to_s
+ default = value
+
+ type = case value
+ when Symbol
+ default = nil
+
+ if VALID_TYPES.include?(value)
+ value
+ elsif required = (value == :required)
+ :string
+ elsif value == :optional
+ # TODO Remove this warning in the future.
+ warn "Optional type is deprecated. Choose :boolean or :string instead. Assumed to be :boolean."
+ :boolean
+ end
+ when TrueClass, FalseClass
+ :boolean
+ when Numeric
+ :numeric
+ when Hash, Array, String
+ value.class.name.downcase.to_sym
+ end
+
+ self.new(name.to_s, nil, required, type, default, nil, nil, aliases)
+ end
+
+ def switch_name
+ @switch_name ||= dasherized? ? name : dasherize(name)
+ end
+
+ def human_name
+ @human_name ||= dasherized? ? undasherize(name) : name
+ end
+
+ def usage(padding=0)
+ sample = if banner && !banner.to_s.empty?
+ "#{switch_name}=#{banner}"
+ else
+ switch_name
+ end
+
+ sample = "[#{sample}]" unless required?
+
+ if aliases.empty?
+ (" " * padding) << sample
+ else
+ "#{aliases.join(', ')}, #{sample}"
+ end
+ end
+
+ # Allow some type predicates as: boolean?, string? and etc.
+ #
+ def method_missing(method, *args, &block)
+ given = method.to_s.sub(/\?$/, '').to_sym
+ if valid_type?(given)
+ self.type == given
+ else
+ super
+ end
+ end
+
+ protected
+
+ def validate!
+ raise ArgumentError, "An option cannot be boolean and required." if boolean? && required?
+ end
+
+ def valid_type?(type)
+ VALID_TYPES.include?(type.to_sym)
+ end
+
+ def dasherized?
+ name.index('-') == 0
+ end
+
+ def undasherize(str)
+ str.sub(/^-{1,2}/, '')
+ end
+
+ def dasherize(str)
+ (str.length > 1 ? "--" : "-") + str.gsub('_', '-')
+ end
+
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/parser/options.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/parser/options.rb
new file mode 100644
index 0000000000..75092308b5
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/parser/options.rb
@@ -0,0 +1,142 @@
+class Thor
+ # This is a modified version of Daniel Berger's Getopt::Long class, licensed
+ # under Ruby's license.
+ #
+ class Options < Arguments #:nodoc:
+ LONG_RE = /^(--\w+[-\w+]*)$/
+ SHORT_RE = /^(-[a-z])$/i
+ EQ_RE = /^(--\w+[-\w+]*|-[a-z])=(.*)$/i
+ SHORT_SQ_RE = /^-([a-z]{2,})$/i # Allow either -x -v or -xv style for single char args
+ SHORT_NUM = /^(-[a-z])#{NUMERIC}$/i
+
+ # Receives a hash and makes it switches.
+ #
+ def self.to_switches(options)
+ options.map do |key, value|
+ case value
+ when true
+ "--#{key}"
+ when Array
+ "--#{key} #{value.map{ |v| v.inspect }.join(' ')}"
+ when Hash
+ "--#{key} #{value.map{ |k,v| "#{k}:#{v}" }.join(' ')}"
+ when nil, false
+ ""
+ else
+ "--#{key} #{value.inspect}"
+ end
+ end.join(" ")
+ end
+
+ # Takes a hash of Thor::Option objects.
+ #
+ def initialize(options={})
+ options = options.values
+ super(options)
+ @shorts, @switches = {}, {}
+
+ options.each do |option|
+ @switches[option.switch_name] = option
+
+ option.aliases.each do |short|
+ @shorts[short.to_s] ||= option.switch_name
+ end
+ end
+ end
+
+ def parse(args)
+ @pile = args.dup
+
+ while peek
+ if current_is_switch?
+ case shift
+ when SHORT_SQ_RE
+ unshift($1.split('').map { |f| "-#{f}" })
+ next
+ when EQ_RE, SHORT_NUM
+ unshift($2)
+ switch = $1
+ when LONG_RE, SHORT_RE
+ switch = $1
+ end
+
+ switch = normalize_switch(switch)
+ next unless option = switch_option(switch)
+
+ @assigns[option.human_name] = parse_peek(switch, option)
+ else
+ shift
+ end
+ end
+
+ check_requirement!
+ @assigns
+ end
+
+ protected
+
+ # Returns true if the current value in peek is a registered switch.
+ #
+ def current_is_switch?
+ case peek
+ when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM
+ switch?($1)
+ when SHORT_SQ_RE
+ $1.split('').any? { |f| switch?("-#{f}") }
+ end
+ end
+
+ def switch?(arg)
+ switch_option(arg) || @shorts.key?(arg)
+ end
+
+ def switch_option(arg)
+ if match = no_or_skip?(arg)
+ @switches[arg] || @switches["--#{match}"]
+ else
+ @switches[arg]
+ end
+ end
+
+ def no_or_skip?(arg)
+ arg =~ /^--(no|skip)-([-\w]+)$/
+ $2
+ end
+
+ # Check if the given argument is actually a shortcut.
+ #
+ def normalize_switch(arg)
+ @shorts.key?(arg) ? @shorts[arg] : arg
+ end
+
+ # Parse boolean values which can be given as --foo=true, --foo or --no-foo.
+ #
+ def parse_boolean(switch)
+ if current_is_value?
+ ["true", "TRUE", "t", "T", true].include?(shift)
+ else
+ @switches.key?(switch) || !no_or_skip?(switch)
+ end
+ end
+
+ # Parse the value at the peek analyzing if it requires an input or not.
+ #
+ def parse_peek(switch, option)
+ unless current_is_value?
+ if option.boolean?
+ # No problem for boolean types
+ elsif no_or_skip?(switch)
+ return nil # User set value to nil
+ elsif option.string? && !option.required?
+ return option.human_name # Return the option name
+ else
+ raise MalformattedArgumentError, "no value provided for option '#{switch}'"
+ end
+ end
+
+ @non_assigned_required.delete(option)
+ send(:"parse_#{option.type}", switch)
+ end
+
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/rake_compat.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/rake_compat.rb
new file mode 100644
index 0000000000..3ab6bb21f5
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/rake_compat.rb
@@ -0,0 +1,67 @@
+require 'rake'
+
+class Thor
+ # Adds a compatibility layer to your Thor classes which allows you to use
+ # rake package tasks. For example, to use rspec rake tasks, one can do:
+ #
+ # require 'thor/rake_compat'
+ #
+ # class Default < Thor
+ # include Thor::RakeCompat
+ #
+ # Spec::Rake::SpecTask.new(:spec) do |t|
+ # t.spec_opts = ['--options', "spec/spec.opts"]
+ # t.spec_files = FileList['spec/**/*_spec.rb']
+ # end
+ # end
+ #
+ module RakeCompat
+ def self.rake_classes
+ @rake_classes ||= []
+ end
+
+ def self.included(base)
+ # Hack. Make rakefile point to invoker, so rdoc task is generated properly.
+ Rake.application.instance_variable_set(:@rakefile, caller[0].match(/(.*):\d+/)[1])
+ self.rake_classes << base
+ end
+ end
+end
+
+class Object #:nodoc:
+ alias :rake_task :task
+ alias :rake_namespace :namespace
+
+ def task(*args, &block)
+ task = rake_task(*args, &block)
+
+ if klass = Thor::RakeCompat.rake_classes.last
+ non_namespaced_name = task.name.split(':').last
+
+ description = non_namespaced_name
+ description << task.arg_names.map{ |n| n.to_s.upcase }.join(' ')
+ description.strip!
+
+ klass.desc description, task.comment || non_namespaced_name
+ klass.class_eval <<-METHOD
+ def #{non_namespaced_name}(#{task.arg_names.join(', ')})
+ Rake::Task[#{task.name.to_sym.inspect}].invoke(#{task.arg_names.join(', ')})
+ end
+ METHOD
+ end
+
+ task
+ end
+
+ def namespace(name, &block)
+ 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)
+ Thor::RakeCompat.rake_classes.pop
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/runner.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/runner.rb
new file mode 100644
index 0000000000..43da09b336
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/runner.rb
@@ -0,0 +1,299 @@
+require 'fileutils'
+require 'open-uri'
+require 'yaml'
+require 'digest/md5'
+require 'pathname'
+
+class Thor::Runner < Thor #:nodoc:
+ map "-T" => :list, "-i" => :install, "-u" => :update
+
+ # Override Thor#help so it can give information about any class and any method.
+ #
+ def help(meth=nil)
+ if meth && !self.respond_to?(meth)
+ initialize_thorfiles(meth)
+ klass, task = Thor::Util.namespace_to_thor_class_and_task(meth)
+ # Send mapping -h because it works with Thor::Group too
+ klass.start(["-h", task].compact, :shell => self.shell)
+ else
+ super
+ end
+ end
+
+ # If a task is not found on Thor::Runner, method missing is invoked and
+ # Thor::Runner is then responsable for finding the task in all classes.
+ #
+ def method_missing(meth, *args)
+ meth = meth.to_s
+ initialize_thorfiles(meth)
+ klass, task = Thor::Util.namespace_to_thor_class_and_task(meth)
+ args.unshift(task) if task
+ klass.start(args, :shell => shell)
+ end
+
+ desc "install NAME", "Install an optionally named Thor file into your system tasks"
+ method_options :as => :string, :relative => :boolean
+ def install(name)
+ initialize_thorfiles
+
+ # If a directory name is provided as the argument, look for a 'main.thor'
+ # task in said directory.
+ begin
+ if File.directory?(File.expand_path(name))
+ base, package = File.join(name, "main.thor"), :directory
+ contents = open(base).read
+ else
+ base, package = name, :file
+ contents = open(name).read
+ end
+ rescue OpenURI::HTTPError
+ raise Error, "Error opening URI '#{name}'"
+ rescue Errno::ENOENT
+ raise Error, "Error opening file '#{name}'"
+ end
+
+ say "Your Thorfile contains:"
+ say contents
+
+ return false if no?("Do you wish to continue [y/N]?")
+
+ as = options["as"] || begin
+ first_line = contents.split("\n")[0]
+ (match = first_line.match(/\s*#\s*module:\s*([^\n]*)/)) ? match[1].strip : nil
+ end
+
+ unless as
+ basename = File.basename(name)
+ as = ask("Please specify a name for #{name} in the system repository [#{basename}]:")
+ as = basename if as.empty?
+ end
+
+ location = if options[:relative] || name =~ /^http:\/\//
+ name
+ else
+ File.expand_path(name)
+ end
+
+ thor_yaml[as] = {
+ :filename => Digest::MD5.hexdigest(name + as),
+ :location => location,
+ :namespaces => Thor::Util.namespaces_in_content(contents, base)
+ }
+
+ save_yaml(thor_yaml)
+ say "Storing thor file in your system repository"
+ destination = File.join(thor_root, thor_yaml[as][:filename])
+
+ if package == :file
+ File.open(destination, "w") { |f| f.puts contents }
+ else
+ FileUtils.cp_r(name, destination)
+ end
+
+ thor_yaml[as][:filename] # Indicate success
+ end
+
+ desc "uninstall NAME", "Uninstall a named Thor module"
+ def uninstall(name)
+ raise Error, "Can't find module '#{name}'" unless thor_yaml[name]
+ say "Uninstalling #{name}."
+ FileUtils.rm_rf(File.join(thor_root, "#{thor_yaml[name][:filename]}"))
+
+ thor_yaml.delete(name)
+ save_yaml(thor_yaml)
+
+ puts "Done."
+ end
+
+ desc "update NAME", "Update a Thor file from its original location"
+ def update(name)
+ raise Error, "Can't find module '#{name}'" if !thor_yaml[name] || !thor_yaml[name][:location]
+
+ say "Updating '#{name}' from #{thor_yaml[name][:location]}"
+
+ old_filename = thor_yaml[name][:filename]
+ self.options = self.options.merge("as" => name)
+ filename = install(thor_yaml[name][:location])
+
+ unless filename == old_filename
+ File.delete(File.join(thor_root, old_filename))
+ end
+ end
+
+ desc "installed", "List the installed Thor modules and tasks"
+ method_options :internal => :boolean
+ def installed
+ initialize_thorfiles(nil, true)
+
+ klasses = Thor::Base.subclasses
+ klasses -= [Thor, Thor::Runner] unless options["internal"]
+
+ display_klasses(true, klasses)
+ end
+
+ desc "list [SEARCH]", "List the available thor tasks (--substring means .*SEARCH)"
+ method_options :substring => :boolean, :group => :string, :all => :boolean
+ def list(search="")
+ initialize_thorfiles
+
+ search = ".*#{search}" if options["substring"]
+ search = /^#{search}.*/i
+ group = options[:group] || "standard"
+
+ klasses = Thor::Base.subclasses.select do |k|
+ (options[:all] || k.group == group) && k.namespace =~ search
+ end
+
+ display_klasses(false, klasses)
+ end
+
+ private
+
+ def thor_root
+ Thor::Util.thor_root
+ end
+
+ def thor_yaml
+ @thor_yaml ||= begin
+ yaml_file = File.join(thor_root, "thor.yml")
+ yaml = YAML.load_file(yaml_file) if File.exists?(yaml_file)
+ yaml || {}
+ end
+ end
+
+ # Save the yaml file. If none exists in thor root, creates one.
+ #
+ def save_yaml(yaml)
+ yaml_file = File.join(thor_root, "thor.yml")
+
+ unless File.exists?(yaml_file)
+ FileUtils.mkdir_p(thor_root)
+ yaml_file = File.join(thor_root, "thor.yml")
+ FileUtils.touch(yaml_file)
+ end
+
+ File.open(yaml_file, "w") { |f| f.puts yaml.to_yaml }
+ end
+
+ def self.exit_on_failure?
+ true
+ end
+
+ # Load the thorfiles. If relevant_to is supplied, looks for specific files
+ # in the thor_root instead of loading them all.
+ #
+ # By default, it also traverses the current path until find Thor files, as
+ # described in thorfiles. This look up can be skipped by suppliying
+ # skip_lookup true.
+ #
+ def initialize_thorfiles(relevant_to=nil, skip_lookup=false)
+ thorfiles(relevant_to, skip_lookup).each do |f|
+ Thor::Util.load_thorfile(f) unless Thor::Base.subclass_files.keys.include?(File.expand_path(f))
+ end
+ end
+
+ # Finds Thorfiles by traversing from your current directory down to the root
+ # directory of your system. If at any time we find a Thor file, we stop.
+ #
+ # We also ensure that system-wide Thorfiles are loaded first, so local
+ # Thorfiles can override them.
+ #
+ # ==== Example
+ #
+ # If we start at /Users/wycats/dev/thor ...
+ #
+ # 1. /Users/wycats/dev/thor
+ # 2. /Users/wycats/dev
+ # 3. /Users/wycats <-- we find a Thorfile here, so we stop
+ #
+ # Suppose we start at c:\Documents and Settings\james\dev\thor ...
+ #
+ # 1. c:\Documents and Settings\james\dev\thor
+ # 2. c:\Documents and Settings\james\dev
+ # 3. c:\Documents and Settings\james
+ # 4. c:\Documents and Settings
+ # 5. c:\ <-- no Thorfiles found!
+ #
+ def thorfiles(relevant_to=nil, skip_lookup=false)
+ # Deal with deprecated thor when :namespaces: is available as constants
+ save_yaml(thor_yaml) if Thor::Util.convert_constants_to_namespaces(thor_yaml)
+
+ thorfiles = []
+
+ unless skip_lookup
+ Pathname.pwd.ascend do |path|
+ thorfiles = Thor::Util.globs_for(path).map { |g| Dir[g] }.flatten
+ break unless thorfiles.empty?
+ end
+ end
+
+ files = (relevant_to ? thorfiles_relevant_to(relevant_to) : Thor::Util.thor_root_glob)
+ files += thorfiles
+ files -= ["#{thor_root}/thor.yml"]
+
+ files.map! do |file|
+ File.directory?(file) ? File.join(file, "main.thor") : file
+ end
+ end
+
+ # Load thorfiles relevant to the given method. If you provide "foo:bar" it
+ # will load all thor files in the thor.yaml that has "foo" e "foo:bar"
+ # namespaces registered.
+ #
+ def thorfiles_relevant_to(meth)
+ lookup = [ meth, meth.split(":")[0...-1].join(":") ]
+
+ files = thor_yaml.select do |k, v|
+ v[:namespaces] && !(v[:namespaces] & lookup).empty?
+ end
+
+ files.map { |k, v| File.join(thor_root, "#{v[:filename]}") }
+ end
+
+ # Display information about the given klasses. If with_module is given,
+ # it shows a table with information extracted from the yaml file.
+ #
+ def display_klasses(with_modules=false, klasses=Thor.subclasses)
+ klasses -= [Thor, Thor::Runner] unless with_modules
+ raise Error, "No Thor tasks available" if klasses.empty?
+
+ if with_modules && !thor_yaml.empty?
+ info = []
+ labels = ["Modules", "Namespaces"]
+
+ info << labels
+ info << [ "-" * labels[0].size, "-" * labels[1].size ]
+
+ thor_yaml.each do |name, hash|
+ info << [ name, hash[:namespaces].join(", ") ]
+ end
+
+ print_table info
+ say ""
+ end
+
+ unless klasses.empty?
+ klasses.dup.each do |klass|
+ klasses -= Thor::Util.thor_classes_in(klass)
+ end
+
+ klasses.each { |k| display_tasks(k) }
+ else
+ say "\033[1;34mNo Thor tasks available\033[0m"
+ end
+ end
+
+ # Display tasks from the given Thor class.
+ #
+ def display_tasks(klass)
+ unless klass.tasks.empty?
+ base = klass.namespace
+
+ color = base == "default" ? :magenta : :blue
+ say shell.set_color(base, color, true)
+ say "-" * base.length
+
+ klass.help(shell, :short => true, :ident => 0, :namespace => true)
+ end
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/shell.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/shell.rb
new file mode 100644
index 0000000000..0d3f4d5951
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/shell.rb
@@ -0,0 +1,72 @@
+require 'thor/shell/color'
+
+class Thor
+ module Base
+ # Returns the shell used in all Thor classes. Default to color one.
+ #
+ def self.shell
+ @shell ||= Thor::Shell::Color
+ end
+
+ # Sets the shell used in all Thor classes.
+ #
+ def self.shell=(klass)
+ @shell = klass
+ end
+ end
+
+ module Shell
+ SHELL_DELEGATED_METHODS = [:ask, :yes?, :no?, :say, :say_status, :print_list, :print_table]
+
+ # Add shell to initialize config values.
+ #
+ # ==== Configuration
+ # shell<Object>:: An instance of the shell to be used.
+ #
+ # ==== Examples
+ #
+ # class MyScript < Thor
+ # argument :first, :type => :numeric
+ # end
+ #
+ # MyScript.new [1.0], { :foo => :bar }, :shell => Thor::Shell::Basic.new
+ #
+ def initialize(args=[], options={}, config={})
+ super
+ self.shell = config[:shell]
+ self.shell.base ||= self if self.shell.respond_to?(:base)
+ end
+
+ # Holds the shell for the given Thor instance. If no shell is given,
+ # it gets a default shell from Thor::Base.shell.
+ #
+ def shell
+ @shell ||= Thor::Base.shell.new
+ end
+
+ # Sets the shell for this thor class.
+ #
+ def shell=(shell)
+ @shell = shell
+ end
+
+ # Common methods that are delegated to the shell.
+ #
+ SHELL_DELEGATED_METHODS.each do |method|
+ module_eval <<-METHOD, __FILE__, __LINE__
+ def #{method}(*args)
+ shell.#{method}(*args)
+ end
+ METHOD
+ end
+
+ protected
+
+ # Allow shell to be shared between invocations.
+ #
+ def _shared_configuration #:nodoc:
+ super.merge!(:shell => self.shell)
+ end
+
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/shell/basic.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/shell/basic.rb
new file mode 100644
index 0000000000..ea9665380b
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/shell/basic.rb
@@ -0,0 +1,219 @@
+require 'tempfile'
+
+class Thor
+ module Shell
+ class Basic
+ attr_accessor :base, :padding
+
+ # Initialize base and padding to nil.
+ #
+ def initialize #:nodoc:
+ @base, @padding = nil, 0
+ end
+
+ # Sets the output padding, not allowing less than zero values.
+ #
+ def padding=(value)
+ @padding = [0, value].max
+ end
+
+ # Ask something to the user and receives a response.
+ #
+ # ==== Example
+ # ask("What is your name?")
+ #
+ def ask(statement, color=nil)
+ say("#{statement} ", color)
+ $stdin.gets.strip
+ end
+
+ # Say (print) something to the user. If the sentence ends with a whitespace
+ # or tab character, a new line is not appended (print + flush). Otherwise
+ # are passed straight to puts (behavior got from Highline).
+ #
+ # ==== Example
+ # say("I know you knew that.")
+ #
+ def say(message="", color=nil, force_new_line=(message.to_s !~ /( |\t)$/))
+ message = message.to_s
+ message = set_color(message, color) if color
+
+ if force_new_line
+ $stdout.puts(message)
+ else
+ $stdout.print(message)
+ $stdout.flush
+ end
+ end
+
+ # Say a status with the given color and appends the message. Since this
+ # method is used frequently by actions, it allows nil or false to be given
+ # in log_status, avoiding the message from being shown. If a Symbol is
+ # given in log_status, it's used as the color.
+ #
+ def say_status(status, message, log_status=true)
+ return if quiet? || log_status == false
+ spaces = " " * (padding + 1)
+ color = log_status.is_a?(Symbol) ? log_status : :green
+
+ status = status.to_s.rjust(12)
+ status = set_color status, color, true if color
+ say "#{status}#{spaces}#{message}", nil, true
+ end
+
+ # Make a question the to user and returns true if the user replies "y" or
+ # "yes".
+ #
+ def yes?(statement, color=nil)
+ ask(statement, color) =~ is?(:yes)
+ end
+
+ # Make a question the to user and returns true if the user replies "n" or
+ # "no".
+ #
+ def no?(statement, color=nil)
+ !yes?(statement, color)
+ end
+
+ # Prints a list of items.
+ #
+ # ==== Parameters
+ # list<Array[String, String, ...]>
+ #
+ # ==== Options
+ # mode:: Can be :rows or :inline. Defaults to :rows.
+ # ident:: Ident each item with the value given.
+ #
+ def print_list(list, options={})
+ return if list.empty?
+
+ ident = " " * (options[:ident] || 0)
+ content = case options[:mode]
+ when :inline
+ last = list.pop
+ "#{list.join(", ")}, and #{last}"
+ else # rows
+ ident + list.join("\n#{ident}")
+ end
+
+ $stdout.puts content
+ end
+
+ # Prints a table.
+ #
+ # ==== Parameters
+ # Array[Array[String, String, ...]]
+ #
+ # ==== Options
+ # ident<Integer>:: Ident the first column by ident value.
+ #
+ def print_table(table, options={})
+ return if table.empty?
+
+ formats = []
+ 0.upto(table.first.length - 2) do |i|
+ maxima = table.max{ |a,b| a[i].size <=> b[i].size }[i].size
+ formats << "%-#{maxima + 2}s"
+ end
+
+ formats[0] = formats[0].insert(0, " " * options[:ident]) if options[:ident]
+ formats << "%s"
+
+ table.each do |row|
+ row.each_with_index do |column, i|
+ $stdout.print formats[i] % column.to_s
+ end
+ $stdout.puts
+ end
+ end
+
+ # Deals with file collision and returns true if the file should be
+ # overwriten and false otherwise. If a block is given, it uses the block
+ # response as the content for the diff.
+ #
+ # ==== Parameters
+ # destination<String>:: the destination file to solve conflicts
+ # block<Proc>:: an optional block that returns the value to be used in diff
+ #
+ def file_collision(destination)
+ return true if @always_force
+ options = block_given? ? "[Ynaqdh]" : "[Ynaqh]"
+
+ while true
+ answer = ask %[Overwrite #{destination}? (enter "h" for help) #{options}]
+
+ case answer
+ when is?(:yes), is?(:force)
+ return true
+ when is?(:no), is?(:skip)
+ return false
+ when is?(:always)
+ return @always_force = true
+ when is?(:quit)
+ say 'Aborting...'
+ raise SystemExit
+ when is?(:diff)
+ show_diff(destination, yield) if block_given?
+ say 'Retrying...'
+ else
+ say file_collision_help
+ end
+ end
+ end
+
+ # Called if something goes wrong during the execution. This is used by Thor
+ # internally and should not be used inside your scripts. If someone went
+ # wrong, you can always raise an exception. If you raise a Thor::Error, it
+ # will be rescued and wrapped in the method below.
+ #
+ def error(statement)
+ $stderr.puts statement
+ end
+
+ # Apply color to the given string with optional bold. Disabled in the
+ # Thor::Shell::Basic class.
+ #
+ def set_color(string, color, bold=false) #:nodoc:
+ string
+ end
+
+ protected
+
+ def is?(value) #:nodoc:
+ value = value.to_s
+
+ if value.size == 1
+ /\A#{value}\z/i
+ else
+ /\A(#{value}|#{value[0,1]})\z/i
+ end
+ end
+
+ def file_collision_help #:nodoc:
+<<HELP
+Y - yes, overwrite
+n - no, do not overwrite
+a - all, overwrite this and all others
+q - quit, abort
+d - diff, show the differences between the old and the new
+h - help, show this help
+HELP
+ end
+
+ def show_diff(destination, content) #:nodoc:
+ diff_cmd = ENV['THOR_DIFF'] || ENV['RAILS_DIFF'] || 'diff -u'
+
+ Tempfile.open(File.basename(destination), File.dirname(destination)) do |temp|
+ temp.write content
+ temp.rewind
+ system %(#{diff_cmd} "#{destination}" "#{temp.path}")
+ end
+ end
+
+ def quiet? #:nodoc:
+ base && base.options[:quiet]
+ end
+
+ end
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/shell/color.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/shell/color.rb
new file mode 100644
index 0000000000..24704f7885
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/shell/color.rb
@@ -0,0 +1,108 @@
+require 'thor/shell/basic'
+
+class Thor
+ module Shell
+ # Inherit from Thor::Shell::Basic and add set_color behavior. Check
+ # Thor::Shell::Basic to see all available methods.
+ #
+ class Color < Basic
+ # Embed in a String to clear all previous ANSI sequences.
+ CLEAR = "\e[0m"
+ # The start of an ANSI bold sequence.
+ BOLD = "\e[1m"
+
+ # Set the terminal's foreground ANSI color to black.
+ BLACK = "\e[30m"
+ # Set the terminal's foreground ANSI color to red.
+ RED = "\e[31m"
+ # Set the terminal's foreground ANSI color to green.
+ GREEN = "\e[32m"
+ # Set the terminal's foreground ANSI color to yellow.
+ YELLOW = "\e[33m"
+ # Set the terminal's foreground ANSI color to blue.
+ BLUE = "\e[34m"
+ # Set the terminal's foreground ANSI color to magenta.
+ MAGENTA = "\e[35m"
+ # Set the terminal's foreground ANSI color to cyan.
+ CYAN = "\e[36m"
+ # Set the terminal's foreground ANSI color to white.
+ WHITE = "\e[37m"
+
+ # Set the terminal's background ANSI color to black.
+ ON_BLACK = "\e[40m"
+ # Set the terminal's background ANSI color to red.
+ ON_RED = "\e[41m"
+ # Set the terminal's background ANSI color to green.
+ ON_GREEN = "\e[42m"
+ # Set the terminal's background ANSI color to yellow.
+ ON_YELLOW = "\e[43m"
+ # Set the terminal's background ANSI color to blue.
+ ON_BLUE = "\e[44m"
+ # Set the terminal's background ANSI color to magenta.
+ ON_MAGENTA = "\e[45m"
+ # Set the terminal's background ANSI color to cyan.
+ ON_CYAN = "\e[46m"
+ # Set the terminal's background ANSI color to white.
+ ON_WHITE = "\e[47m"
+
+ # Set color by using a string or one of the defined constants. If a third
+ # option is set to true, it also adds bold to the string. This is based
+ # on Highline implementation and it automatically appends CLEAR to the end
+ # of the returned String.
+ #
+ def set_color(string, color, bold=false)
+ color = self.class.const_get(color.to_s.upcase) if color.is_a?(Symbol)
+ bold = bold ? BOLD : ""
+ "#{bold}#{color}#{string}#{CLEAR}"
+ end
+
+ protected
+
+ # Overwrite show_diff to show diff with colors if Diff::LCS is
+ # available.
+ #
+ def show_diff(destination, content) #:nodoc:
+ if diff_lcs_loaded? && ENV['THOR_DIFF'].nil? && ENV['RAILS_DIFF'].nil?
+ actual = File.read(destination).to_s.split("\n")
+ content = content.to_s.split("\n")
+
+ Diff::LCS.sdiff(actual, content).each do |diff|
+ output_diff_line(diff)
+ end
+ else
+ super
+ end
+ end
+
+ def output_diff_line(diff) #:nodoc:
+ case diff.action
+ when '-'
+ say "- #{diff.old_element.chomp}", :red, true
+ when '+'
+ say "+ #{diff.new_element.chomp}", :green, true
+ when '!'
+ say "- #{diff.old_element.chomp}", :red, true
+ say "+ #{diff.new_element.chomp}", :green, true
+ else
+ say " #{diff.old_element.chomp}", nil, true
+ end
+ end
+
+ # Check if Diff::LCS is loaded. If it is, use it to create pretty output
+ # for diff.
+ #
+ def diff_lcs_loaded? #:nodoc:
+ return true if defined?(Diff::LCS)
+ return @diff_lcs_loaded unless @diff_lcs_loaded.nil?
+
+ @diff_lcs_loaded = begin
+ require 'diff/lcs'
+ true
+ rescue LoadError
+ false
+ end
+ end
+
+ end
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/task.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/task.rb
new file mode 100644
index 0000000000..91c7564d3f
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/task.rb
@@ -0,0 +1,122 @@
+class Thor
+ class Task < Struct.new(:name, :description, :usage, :options)
+
+ # A dynamic task that handles method missing scenarios.
+ #
+ class Dynamic < Task
+ def initialize(name)
+ super(name.to_s, "A dynamically-generated task", name.to_s)
+ end
+
+ def run(instance, args=[])
+ unless (instance.methods & [name.to_s, name.to_sym]).empty?
+ raise Error, "could not find Thor class or task '#{name}'"
+ end
+ super
+ end
+ end
+
+ def initialize(name, description, usage, options=nil)
+ super(name.to_s, description, usage, options || {})
+ end
+
+ def initialize_copy(other) #:nodoc:
+ super(other)
+ self.options = other.options.dup if other.options
+ end
+
+ def short_description
+ description.split("\n").first if description
+ end
+
+ # By default, a task invokes a method in the thor class. You can change this
+ # implementation to create custom tasks.
+ #
+ def run(instance, args=[])
+ raise UndefinedTaskError, "the '#{name}' task of #{instance.class} is private" unless public_method?(instance)
+ instance.send(name, *args)
+ rescue ArgumentError => e
+ parse_argument_error(instance, e, caller)
+ rescue NoMethodError => e
+ parse_no_method_error(instance, e)
+ end
+
+ # Returns the formatted usage. If a class is given, the class arguments are
+ # injected in the usage.
+ #
+ def formatted_usage(klass=nil, namespace=false, show_options=true)
+ formatted = if namespace.is_a?(String)
+ "#{namespace}:"
+ elsif klass && namespace
+ "#{klass.namespace.gsub(/^default/,'')}:"
+ else
+ ""
+ end
+
+ formatted << formatted_arguments(klass)
+ formatted << " #{formatted_options}" if show_options
+ formatted.strip!
+ formatted
+ end
+
+ # Injects the class arguments into the task usage.
+ #
+ def formatted_arguments(klass)
+ if klass && !klass.arguments.empty?
+ usage.to_s.gsub(/^#{name}/) do |match|
+ match << " " << klass.arguments.map{ |a| a.usage }.join(' ')
+ end
+ else
+ usage.to_s
+ end
+ end
+
+ # Returns the options usage for this task.
+ #
+ def formatted_options
+ @formatted_options ||= options.map{ |_, o| o.usage }.sort.join(" ")
+ end
+
+ protected
+
+ # Given a target, checks if this class name is not a private/protected method.
+ #
+ def public_method?(instance) #:nodoc:
+ collection = instance.private_methods + instance.protected_methods
+ (collection & [name.to_s, name.to_sym]).empty?
+ end
+
+ # Clean everything that comes from the Thor gempath and remove the caller.
+ #
+ def sans_backtrace(backtrace, caller) #:nodoc:
+ dirname = /^#{Regexp.escape(File.dirname(__FILE__))}/
+ saned = backtrace.reject { |frame| frame =~ dirname }
+ saned -= caller
+ end
+
+ def parse_argument_error(instance, e, caller) #:nodoc:
+ backtrace = sans_backtrace(e.backtrace, caller)
+
+ if backtrace.empty? && e.message =~ /wrong number of arguments/
+ if instance.is_a?(Thor::Group)
+ raise e, "'#{name}' was called incorrectly. Are you sure it has arity equals to 0?"
+ else
+ raise InvocationError, "'#{name}' was called incorrectly. Call as " <<
+ "'#{formatted_usage(instance.class, true)}'"
+ end
+ else
+ raise e
+ end
+ end
+
+ def parse_no_method_error(instance, e) #:nodoc:
+ if e.message =~ /^undefined method `#{name}' for #{Regexp.escape(instance.to_s)}$/
+ raise UndefinedTaskError, "The #{instance.class.namespace} namespace " <<
+ "doesn't have a '#{name}' task"
+ else
+ raise e
+ end
+ end
+
+ end
+end
diff --git a/railties/lib/rails/vendor/thor-0.11.6/lib/thor/util.rb b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/util.rb
new file mode 100644
index 0000000000..fd820d7462
--- /dev/null
+++ b/railties/lib/rails/vendor/thor-0.11.6/lib/thor/util.rb
@@ -0,0 +1,251 @@
+require 'rbconfig'
+
+class Thor
+ module Sandbox #:nodoc:
+ end
+
+ # This module holds several utilities:
+ #
+ # 1) Methods to convert thor namespaces to constants and vice-versa.
+ #
+ # Thor::Utils.namespace_from_thor_class(Foo::Bar::Baz) #=> "foo:bar:baz"
+ #
+ # 2) Loading thor files and sandboxing:
+ #
+ # Thor::Utils.load_thorfile("~/.thor/foo")
+ #
+ module Util
+
+ # Receives a namespace and search for it in the Thor::Base subclasses.
+ #
+ # ==== Parameters
+ # namespace<String>:: The namespace to search for.
+ #
+ def self.find_by_namespace(namespace)
+ namespace = "default#{namespace}" if namespace.empty? || namespace =~ /^:/
+
+ Thor::Base.subclasses.find do |klass|
+ klass.namespace == namespace
+ end
+ end
+
+ # Receives a constant and converts it to a Thor namespace. Since Thor tasks
+ # can be added to a sandbox, this method is also responsable for removing
+ # the sandbox namespace.
+ #
+ # This method should not be used in general because it's used to deal with
+ # older versions of Thor. On current versions, if you need to get the
+ # namespace from a class, just call namespace on it.
+ #
+ # ==== Parameters
+ # constant<Object>:: The constant to be converted to the thor path.
+ #
+ # ==== Returns
+ # String:: If we receive Foo::Bar::Baz it returns "foo:bar:baz"
+ #
+ def self.namespace_from_thor_class(constant, remove_default=true)
+ constant = constant.to_s.gsub(/^Thor::Sandbox::/, "")
+ constant = snake_case(constant).squeeze(":")
+ constant.gsub!(/^default/, '') if remove_default
+ constant
+ end
+
+ # Given the contents, evaluate it inside the sandbox and returns the
+ # namespaces defined in the sandbox.
+ #
+ # ==== Parameters
+ # contents<String>
+ #
+ # ==== Returns
+ # Array[Object]
+ #
+ def self.namespaces_in_content(contents, file=__FILE__)
+ old_constants = Thor::Base.subclasses.dup
+ Thor::Base.subclasses.clear
+
+ load_thorfile(file, contents)
+
+ new_constants = Thor::Base.subclasses.dup
+ Thor::Base.subclasses.replace(old_constants)
+
+ new_constants.map!{ |c| c.namespace }
+ new_constants.compact!
+ new_constants
+ end
+
+ # Returns the thor classes declared inside the given class.
+ #
+ def self.thor_classes_in(klass)
+ Thor::Base.subclasses.select do |subclass|
+ klass.constants.include?(subclass.name.gsub("#{klass.name}::", ''))
+ end
+ end
+
+ # Receives a string and convert it to snake case. SnakeCase returns snake_case.
+ #
+ # ==== Parameters
+ # String
+ #
+ # ==== Returns
+ # String
+ #
+ def self.snake_case(str)
+ return str.downcase if str =~ /^[A-Z_]+$/
+ str.gsub(/\B[A-Z]/, '_\&').squeeze('_') =~ /_*(.*)/
+ return $+.downcase
+ end
+
+ # Receives a string and convert it to camel case. camel_case returns CamelCase.
+ #
+ # ==== Parameters
+ # String
+ #
+ # ==== Returns
+ # String
+ #
+ def self.camel_case(str)
+ return str if str !~ /_/ && str =~ /[A-Z]+.*/
+ str.split('_').map { |i| i.capitalize }.join
+ end
+
+ # Receives a namespace and tries to retrieve a Thor or Thor::Group class
+ # from it. It first searches for a class using the all the given namespace,
+ # if it's not found, removes the highest entry and searches for the class
+ # again. If found, returns the highest entry as the class name.
+ #
+ # ==== Examples
+ #
+ # class Foo::Bar < Thor
+ # def baz
+ # end
+ # end
+ #
+ # class Baz::Foo < Thor::Group
+ # end
+ #
+ # Thor::Util.namespace_to_thor_class("foo:bar") #=> Foo::Bar, nil # will invoke default task
+ # Thor::Util.namespace_to_thor_class("baz:foo") #=> Baz::Foo, nil
+ # Thor::Util.namespace_to_thor_class("foo:bar:baz") #=> Foo::Bar, "baz"
+ #
+ # ==== Parameters
+ # namespace<String>
+ #
+ # ==== Errors
+ # Thor::Error:: raised if the namespace cannot be found.
+ #
+ # Thor::Error:: raised if the namespace evals to a class which does not
+ # inherit from Thor or Thor::Group.
+ #
+ def self.namespace_to_thor_class_and_task(namespace, raise_if_nil=true)
+ if namespace.include?(?:)
+ pieces = namespace.split(":")
+ task = pieces.pop
+ klass = Thor::Util.find_by_namespace(pieces.join(":"))
+ end
+
+ unless klass
+ klass, task = Thor::Util.find_by_namespace(namespace), nil
+ end
+
+ raise Error, "could not find Thor class or task '#{namespace}'" if raise_if_nil && klass.nil?
+ return klass, task
+ end
+
+ # Receives a path and load the thor file in the path. The file is evaluated
+ # inside the sandbox to avoid namespacing conflicts.
+ #
+ def self.load_thorfile(path, content=nil)
+ content ||= File.read(path)
+
+ begin
+ Thor::Sandbox.class_eval(content, path)
+ rescue Exception => e
+ $stderr.puts "WARNING: unable to load thorfile #{path.inspect}: #{e.message}"
+ end
+ end
+
+ # Receives a yaml (hash) and updates all constants entries to namespace.
+ # This was added to deal with deprecated versions of Thor.
+ #
+ # TODO Deprecate this method in the future.
+ #
+ # ==== Returns
+ # TrueClass|FalseClass:: Returns true if any change to the yaml file was made.
+ #
+ def self.convert_constants_to_namespaces(yaml)
+ yaml_changed = false
+
+ yaml.each do |k, v|
+ next unless v[:constants] && v[:namespaces].nil?
+ yaml_changed = true
+ yaml[k][:namespaces] = v[:constants].map{|c| Thor::Util.namespace_from_thor_class(c)}
+ end
+
+ yaml_changed
+ end
+
+ def self.user_home
+ @@user_home ||= if ENV["HOME"]
+ ENV["HOME"]
+ elsif ENV["USERPROFILE"]
+ ENV["USERPROFILE"]
+ elsif ENV["HOMEDRIVE"] && ENV["HOMEPATH"]
+ File.join(ENV["HOMEDRIVE"], ENV["HOMEPATH"])
+ elsif ENV["APPDATA"]
+ ENV["APPDATA"]
+ else
+ begin
+ File.expand_path("~")
+ rescue
+ if File::ALT_SEPARATOR
+ "C:/"
+ else
+ "/"
+ end
+ end
+ end
+ end
+
+ # Returns the root where thor files are located, dependending on the OS.
+ #
+ def self.thor_root
+ File.join(user_home, ".thor")
+ end
+
+ # Returns the files in the thor root. On Windows thor_root will be something
+ # like this:
+ #
+ # C:\Documents and Settings\james\.thor
+ #
+ # If we don't #gsub the \ character, Dir.glob will fail.
+ #
+ def self.thor_root_glob
+ files = Dir["#{thor_root.gsub(/\\/, '/')}/*"]
+
+ files.map! do |file|
+ File.directory?(file) ? File.join(file, "main.thor") : file
+ end
+ end
+
+ # Where to look for Thor files.
+ #
+ def self.globs_for(path)
+ ["#{path}/Thorfile", "#{path}/*.thor", "#{path}/tasks/*.thor", "#{path}/lib/tasks/*.thor"]
+ end
+
+ # Return the path to the ruby interpreter taking into account multiple
+ # installations and windows extensions.
+ #
+ def self.ruby_command
+ @ruby_command ||= begin
+ ruby = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
+ ruby << Config::CONFIG['EXEEXT']
+
+ # escape string in case path to ruby executable contain spaces.
+ ruby.sub!(/.*\s.*/m, '"\&"')
+ ruby
+ end
+ end
+
+ end
+end