aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib
diff options
context:
space:
mode:
authorCarl Lerche <carllerche@mac.com>2009-09-03 09:31:04 -0700
committerCarl Lerche <carllerche@mac.com>2009-09-03 09:31:04 -0700
commitf416f9f0aef654fea94cae10027aca866d07c659 (patch)
treeade716f1abda2ab0f5d64fcbccb170b17fb19498 /railties/lib
parente3f5fd536e7124c3e34b74e6ece94570cf6f7028 (diff)
downloadrails-f416f9f0aef654fea94cae10027aca866d07c659.tar.gz
rails-f416f9f0aef654fea94cae10027aca866d07c659.tar.bz2
rails-f416f9f0aef654fea94cae10027aca866d07c659.zip
Vendor the latest version of the bundler
Diffstat (limited to 'railties/lib')
-rw-r--r--railties/lib/vendor/bundler/README.markdown162
-rw-r--r--railties/lib/vendor/bundler/Rakefile55
-rwxr-xr-xrailties/lib/vendor/bundler/bin/gem_bundler40
-rw-r--r--railties/lib/vendor/bundler/lib/bundler.rb28
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/cli.rb50
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/commands/bundle_command.rb31
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/commands/exec_command.rb31
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/dependency.rb31
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/dsl.rb109
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/environment.rb111
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/finder.rb67
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/gem_bundle.rb18
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/gem_ext.rb25
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/gem_specification.rb10
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/installer.rb44
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/manifest.rb130
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/repository.rb151
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/repository/directory_repository.rb46
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/repository/gem_repository.rb108
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/resolver.rb194
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/resolver/builders.rb61
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/resolver/engine.rb38
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/resolver/inspect.rb24
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/resolver/search.rb71
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/resolver/stack.rb72
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/resolver/state.rb172
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/runtime.rb41
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/source.rb150
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/templates/app_script.erb3
-rw-r--r--railties/lib/vendor/bundler/lib/bundler/templates/environment.erb127
30 files changed, 1389 insertions, 811 deletions
diff --git a/railties/lib/vendor/bundler/README.markdown b/railties/lib/vendor/bundler/README.markdown
new file mode 100644
index 0000000000..26863e96f2
--- /dev/null
+++ b/railties/lib/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/vendor/bundler/Rakefile b/railties/lib/vendor/bundler/Rakefile
index fd39fbff77..dc4c3d6d46 100644
--- a/railties/lib/vendor/bundler/Rakefile
+++ b/railties/lib/vendor/bundler/Rakefile
@@ -1,52 +1,57 @@
require 'rubygems' unless ENV['NO_RUBYGEMS']
-require 'rake/gempackagetask'
require 'rubygems/specification'
require 'date'
-require 'spec/rake/spectask'
spec = Gem::Specification.new do |s|
- s.name = "bundler"
- s.version = "0.0.1"
- s.author = "Your Name"
- s.email = "Your Email"
- s.homepage = "http://example.com"
- s.description = s.summary = "A gem that provides..."
+ 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", "LICENSE"]
- s.summary = ""
+ s.extra_rdoc_files = ["README.markdown", "LICENSE"]
- # Uncomment this to add a dependency
- # s.add_dependency "foo"
+ s.required_rubygems_version = ">= 1.3.5"
- s.bindir = "bin"
- s.executables = %w( gem_bundler )
s.require_path = 'lib'
- s.files = %w(LICENSE README Rakefile) + Dir.glob("{bin,lib,spec}/**/*")
+ s.files = %w(LICENSE README.markdown Rakefile) + Dir.glob("lib/**/*")
end
task :default => :spec
-desc "Run specs"
-Spec::Rake::SpecTask.new do |t|
- t.spec_files = FileList['spec/**/*_spec.rb']
- t.spec_opts = %w(-fs --color)
+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
-
-Rake::GemPackageTask.new(spec) do |pkg|
- pkg.gem_spec = spec
+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 %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
+ sh %{gem install pkg/#{spec.name}-#{spec.version}}
end
desc "create a gemspec file"
task :make_spec do
- File.open("#{GEM}.gemspec", "w") do |file|
+ File.open("#{spec.name}.gemspec", "w") do |file|
file.puts spec.to_ruby
end
-end \ No newline at end of file
+end
diff --git a/railties/lib/vendor/bundler/bin/gem_bundler b/railties/lib/vendor/bundler/bin/gem_bundler
deleted file mode 100755
index 7a8771efee..0000000000
--- a/railties/lib/vendor/bundler/bin/gem_bundler
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env ruby
-require "optparse"
-require "bundler"
-
-options = {}
-
-parser = OptionParser.new do |op|
- op.banner = "Usage: gem_bundler [OPTIONS] [PATH]"
-
- op.on("-m", "--manifest MANIFEST") do |manifest|
- options[:manifest] = manifest
- end
-
- op.on_tail("-h", "--help", "Show this message") do
- puts op
- exit
- end
-end
-parser.parse!
-
-options[:path] = ARGV.shift
-
-unless options[:path]
- puts parser
- puts %(
- [PATH] must be specified
- )
- exit
-end
-
-unless options[:manifest] && File.exist?(options[:manifest])
- puts parser
- puts %(
- MANIFEST must be a valid manifest file
- )
- exit
-end
-
-
-Bundler.run(options) \ No newline at end of file
diff --git a/railties/lib/vendor/bundler/lib/bundler.rb b/railties/lib/vendor/bundler/lib/bundler.rb
index 4dcab20da9..1ede3517dd 100644
--- a/railties/lib/vendor/bundler/lib/bundler.rb
+++ b/railties/lib/vendor/bundler/lib/bundler.rb
@@ -1,24 +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/installer"
+require "bundler/source"
require "bundler/finder"
-require "bundler/gem_specification"
+require "bundler/gem_ext"
require "bundler/resolver"
-require "bundler/manifest"
-require "bundler/dependency"
-require "bundler/runtime"
+require "bundler/environment"
+require "bundler/dsl"
require "bundler/cli"
+require "bundler/repository"
+require "bundler/dependency"
module Bundler
VERSION = "0.5.0"
- def self.run(options = {})
- manifest = ManifestBuilder.load(options[:path], options[:manifest])
- manifest.install
+ 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 \ No newline at end of file
+end
diff --git a/railties/lib/vendor/bundler/lib/bundler/cli.rb b/railties/lib/vendor/bundler/lib/bundler/cli.rb
index ed49ef88f0..df9181fbc4 100644
--- a/railties/lib/vendor/bundler/lib/bundler/cli.rb
+++ b/railties/lib/vendor/bundler/lib/bundler/cli.rb
@@ -1,24 +1,44 @@
-module Bundler
- module CLI
+require "optparse"
- def default_manifest
- current = Pathname.new(Dir.pwd)
+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
- begin
- manifest = current.join("Gemfile")
- return manifest.to_s if File.exist?(manifest)
- current = current.parent
- end until current.root?
- nil
+ def initialize(options)
+ @options = options
+ @manifest = Bundler::Environment.load(@options[:manifest])
end
- module_function :default_manifest
+ def bundle
+ @manifest.install(@options[:update])
+ end
- def default_path
- Pathname.new(File.dirname(default_manifest)).join("vendor").join("gems").to_s
+ def exec
+ @manifest.setup_environment
+ # w0t?
+ super(*@options[:args])
end
- module_function :default_path
+ def run(command)
+ send(command)
+ end
end
-end \ No newline at end of file
+end
diff --git a/railties/lib/vendor/bundler/lib/bundler/commands/bundle_command.rb b/railties/lib/vendor/bundler/lib/bundler/commands/bundle_command.rb
new file mode 100644
index 0000000000..a1f9590f75
--- /dev/null
+++ b/railties/lib/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/vendor/bundler/lib/bundler/commands/exec_command.rb b/railties/lib/vendor/bundler/lib/bundler/commands/exec_command.rb
new file mode 100644
index 0000000000..228aa60619
--- /dev/null
+++ b/railties/lib/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/vendor/bundler/lib/bundler/dependency.rb b/railties/lib/vendor/bundler/lib/bundler/dependency.rb
index 739a7a117d..b627b58662 100644
--- a/railties/lib/vendor/bundler/lib/bundler/dependency.rb
+++ b/railties/lib/vendor/bundler/lib/bundler/dependency.rb
@@ -1,9 +1,10 @@
module Bundler
- class Dependency
+ class InvalidEnvironmentName < StandardError; end
+ class Dependency
attr_reader :name, :version, :require_as, :only, :except
- def initialize(name, options = {})
+ def initialize(name, options = {}, &block)
options.each do |k, v|
options[k.to_s] = v
end
@@ -11,8 +12,13 @@ module Bundler
@name = name
@version = options["version"] || ">= 0"
@require_as = Array(options["require_as"] || name)
- @only = Array(options["only"]).map {|e| e.to_s } if options["only"]
- @except = Array(options["except"]).map {|e| e.to_s } if options["except"]
+ @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)
@@ -27,9 +33,24 @@ module Bundler
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 \ No newline at end of file
+end
diff --git a/railties/lib/vendor/bundler/lib/bundler/dsl.rb b/railties/lib/vendor/bundler/lib/bundler/dsl.rb
new file mode 100644
index 0000000000..d9a86ee1fd
--- /dev/null
+++ b/railties/lib/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/vendor/bundler/lib/bundler/environment.rb b/railties/lib/vendor/bundler/lib/bundler/environment.rb
new file mode 100644
index 0000000000..f07a9e2c6f
--- /dev/null
+++ b/railties/lib/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/vendor/bundler/lib/bundler/finder.rb b/railties/lib/vendor/bundler/lib/bundler/finder.rb
index 43ff370ae4..b77ca65709 100644
--- a/railties/lib/vendor/bundler/lib/bundler/finder.rb
+++ b/railties/lib/vendor/bundler/lib/bundler/finder.rb
@@ -1,42 +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
- def initialize(*sources)
- @results = {}
- @index = Hash.new { |h,k| h[k] = {} }
- sources.each { |source| fetch(source) }
+ # 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
- def resolve(*dependencies)
- resolved = Resolver.resolve(dependencies, self)
- resolved && GemBundle.new(resolved.all_specs)
+ # 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
- def fetch(source)
- deflated = Gem::RemoteFetcher.fetcher.fetch_path("#{source}/Marshal.4.8.Z")
- inflated = Gem.inflate deflated
+ private
- append(Marshal.load(inflated), source)
- rescue Gem::RemoteFetcher::FetchError => e
- raise ArgumentError, "#{source} is not a valid source: #{e.message}"
- end
-
- def append(index, source)
- index.gems.values.each do |spec|
- next unless Gem::Platform.match(spec.platform)
- spec.source = source
- @index[spec.name][spec.version] ||= spec
+ def find_by_name(name)
+ matches = @index[name] ||= begin
+ versions = {}
+ @sources.reverse_each do |source|
+ versions.merge! source.specs[name] || {}
+ end
+ versions
end
- self
+ matches.values
end
- def search(dependency)
- @results[dependency.hash] ||= begin
- possibilities = @index[dependency.name].values
- possibilities.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/vendor/bundler/lib/bundler/gem_bundle.rb b/railties/lib/vendor/bundler/lib/bundler/gem_bundle.rb
index b749720fd9..80d7710683 100644
--- a/railties/lib/vendor/bundler/lib/bundler/gem_bundle.rb
+++ b/railties/lib/vendor/bundler/lib/bundler/gem_bundle.rb
@@ -1,22 +1,10 @@
module Bundler
class GemBundle < Array
- def download(directory)
- FileUtils.mkdir_p(directory)
-
- current = Dir[File.join(directory, "cache", "*.gem*")]
-
- each do |spec|
- cached = File.join(directory, "cache", "#{spec.full_name}.gem")
-
- unless File.file?(cached)
- Gem::RemoteFetcher.fetcher.download(spec, spec.source, directory)
- end
-
- current.delete(cached)
+ def download(repository)
+ sort_by {|s| s.full_name.downcase }.each do |spec|
+ spec.source.download(spec, repository)
end
- current.each { |file| File.delete(file) }
-
self
end
end
diff --git a/railties/lib/vendor/bundler/lib/bundler/gem_ext.rb b/railties/lib/vendor/bundler/lib/bundler/gem_ext.rb
new file mode 100644
index 0000000000..155ad04c7e
--- /dev/null
+++ b/railties/lib/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/vendor/bundler/lib/bundler/gem_specification.rb b/railties/lib/vendor/bundler/lib/bundler/gem_specification.rb
deleted file mode 100644
index 680b61fd69..0000000000
--- a/railties/lib/vendor/bundler/lib/bundler/gem_specification.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-module Gem
- class Specification
- attribute :source
-
- def source=(source)
- @source = source.is_a?(URI) ? source : URI.parse(source)
- raise ArgumentError, "The source must be an absolute URI" unless @source.absolute?
- end
- end
-end \ No newline at end of file
diff --git a/railties/lib/vendor/bundler/lib/bundler/installer.rb b/railties/lib/vendor/bundler/lib/bundler/installer.rb
deleted file mode 100644
index 581d9d3c8e..0000000000
--- a/railties/lib/vendor/bundler/lib/bundler/installer.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-module Bundler
- class Installer
- def initialize(path)
- if !File.directory?(path)
- raise ArgumentError, "#{path} is not a directory"
- elsif !File.directory?(File.join(path, "cache"))
- raise ArgumentError, "#{path} is not a valid environment (it does not contain a cache directory)"
- end
-
- @path = path
- @gems = Dir[(File.join(path, "cache", "*.gem"))]
- end
-
- def install(options = {})
- bin_dir = options[:bin_dir] ||= File.join(@path, "bin")
-
- specs = Dir[File.join(@path, "specifications", "*.gemspec")]
- gems = Dir[File.join(@path, "gems", "*")]
-
- @gems.each do |gem|
- name = File.basename(gem).gsub(/\.gem$/, '')
- installed = specs.any? { |g| File.basename(g) == "#{name}.gemspec" } &&
- gems.any? { |g| File.basename(g) == name }
-
- unless installed
- installer = Gem::Installer.new(gem, :install_dir => @path,
- :ignore_dependencies => true,
- :env_shebang => true,
- :wrappers => true,
- :bin_dir => bin_dir)
- installer.install
- end
-
- # remove this spec
- specs.delete_if { |g| File.basename(g) == "#{name}.gemspec"}
- gems.delete_if { |g| File.basename(g) == name }
- end
-
- (specs + gems).each do |path|
- FileUtils.rm_rf(path)
- end
- end
- end
-end \ No newline at end of file
diff --git a/railties/lib/vendor/bundler/lib/bundler/manifest.rb b/railties/lib/vendor/bundler/lib/bundler/manifest.rb
deleted file mode 100644
index 847a41940d..0000000000
--- a/railties/lib/vendor/bundler/lib/bundler/manifest.rb
+++ /dev/null
@@ -1,130 +0,0 @@
-require "rubygems/source_index"
-require "pathname"
-
-module Bundler
- class VersionConflict < StandardError; end
-
- class Manifest
- attr_reader :sources, :dependencies, :path
-
- def initialize(sources, dependencies, path)
- sources.map! {|s| s.is_a?(URI) ? s : URI.parse(s) }
- @sources, @dependencies, @path = sources, dependencies, Pathname.new(path)
- end
-
- def fetch
- return if all_gems_installed?
-
- finder = Finder.new(*sources)
- unless bundle = finder.resolve(*gem_dependencies)
- gems = @dependencies.map {|d| " #{d.to_s}" }.join("\n")
- raise VersionConflict, "No compatible versions could be found for:\n#{gems}"
- end
-
- bundle.download(@path)
- end
-
- def install(options = {})
- fetch
- installer = Installer.new(@path)
- installer.install # options come here
- create_load_paths_files(File.join(@path, "environments"))
- create_fake_rubygems(File.join(@path, "environments"))
- end
-
- def activate(environment = "default")
- require File.join(@path, "environments", "#{environment}.rb")
- end
-
- def require_all
- dependencies.each do |dep|
- dep.require_as.each {|file| require file }
- end
- end
-
- def gems_for(environment)
- deps = dependencies.select { |d| d.in?(environment) }
- deps.map! { |d| d.to_gem_dependency }
- index = Gem::SourceIndex.from_gems_in(File.join(@path, "specifications"))
- Resolver.resolve(deps, index).all_specs
- end
-
- def environments
- envs = dependencies.map {|dep| Array(dep.only) + Array(dep.except) }.flatten
- envs << "default"
- end
-
- private
-
- def gem_dependencies
- @gem_dependencies ||= dependencies.map { |d| d.to_gem_dependency }
- end
-
- def all_gems_installed?
- gem_versions = {}
-
- Dir[File.join(@path, "cache", "*.gem")].each do |file|
- file =~ /\/([^\/]+)-([\d\.]+)\.gem$/
- name, version = $1, $2
- gem_versions[name] = Gem::Version.new(version)
- end
-
- gem_dependencies.all? do |dep|
- gem_versions[dep.name] &&
- dep.version_requirements.satisfied_by?(gem_versions[dep.name])
- end
- end
-
- def create_load_paths_files(path)
- FileUtils.mkdir_p(path)
- environments.each do |environment|
- gem_specs = gems_for(environment)
- File.open(File.join(path, "#{environment}.rb"), "w") do |file|
- file.puts <<-RUBY_EVAL
- module Bundler
- def self.rubygems_required
- #{create_gem_stubs(path, gem_specs)}
- end
- end
- RUBY_EVAL
- file.puts "$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__))"
- load_paths_for_specs(gem_specs).each do |load_path|
- file.puts "$LOAD_PATH.unshift #{load_path.inspect}"
- end
- end
- end
- end
-
- def create_gem_stubs(path, gem_specs)
- gem_specs.map do |spec|
- path = File.expand_path(File.join(path, '..', 'specifications', "#{spec.full_name}.gemspec"))
- %{
- Gem.loaded_specs["#{spec.name}"] = eval(File.read("#{path}"))
- }
- end.join("\n")
- end
-
- def create_fake_rubygems(path)
- File.open(File.join(path, "rubygems.rb"), "w") do |file|
- file.puts <<-RUBY_EVAL
- $:.delete File.expand_path(File.dirname(__FILE__))
- load "rubygems.rb"
- if defined?(Bundler) && Bundler.respond_to?(:rubygems_required)
- Bundler.rubygems_required
- end
- RUBY_EVAL
- end
- end
-
- def load_paths_for_specs(specs)
- load_paths = []
- specs.each do |spec|
- load_paths << File.join(spec.full_gem_path, spec.bindir) if spec.bindir
- spec.require_paths.each do |path|
- load_paths << File.join(spec.full_gem_path, path)
- end
- end
- load_paths
- end
- end
-end \ No newline at end of file
diff --git a/railties/lib/vendor/bundler/lib/bundler/repository.rb b/railties/lib/vendor/bundler/lib/bundler/repository.rb
new file mode 100644
index 0000000000..1a1dc7497d
--- /dev/null
+++ b/railties/lib/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/vendor/bundler/lib/bundler/repository/directory_repository.rb b/railties/lib/vendor/bundler/lib/bundler/repository/directory_repository.rb
new file mode 100644
index 0000000000..e97dd38dd5
--- /dev/null
+++ b/railties/lib/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/vendor/bundler/lib/bundler/repository/gem_repository.rb b/railties/lib/vendor/bundler/lib/bundler/repository/gem_repository.rb
new file mode 100644
index 0000000000..90de49d83d
--- /dev/null
+++ b/railties/lib/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/vendor/bundler/lib/bundler/resolver.rb b/railties/lib/vendor/bundler/lib/bundler/resolver.rb
index 1ec89e53c4..2a6a6371c2 100644
--- a/railties/lib/vendor/bundler/lib/bundler/resolver.rb
+++ b/railties/lib/vendor/bundler/lib/bundler/resolver.rb
@@ -1,19 +1,189 @@
-require 'bundler/resolver/inspect'
-require 'bundler/resolver/search'
-require 'bundler/resolver/engine'
-require 'bundler/resolver/stack'
-require 'bundler/resolver/state'
+# 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
- module Resolver
- def self.resolve(deps, source_index = Gem.source_index, logger = nil)
- unless logger
- logger = Logger.new($stderr)
- logger.datetime_format = ""
- logger.level = ENV["GEM_RESOLVER_DEBUG"] ? Logger::DEBUG : Logger::ERROR
+ 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
- Engine.resolve(deps, source_index, logger)
+ # 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/vendor/bundler/lib/bundler/resolver/builders.rb b/railties/lib/vendor/bundler/lib/bundler/resolver/builders.rb
deleted file mode 100644
index 2b7b48211c..0000000000
--- a/railties/lib/vendor/bundler/lib/bundler/resolver/builders.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-module Bundler
- module Resolver
- module Builders
- def build_index(&block)
- index = Gem::SourceIndex.new
- IndexBuilder.run(index, &block) if block_given?
- index
- end
-
- def build_spec(name, version, &block)
- spec = Gem::Specification.new
- spec.instance_variable_set(:@name, name)
- spec.instance_variable_set(:@version, Gem::Version.new(version))
- DepBuilder.run(spec, &block) if block_given?
- spec
- end
-
- def build_dep(name, requirements, type = :runtime)
- Gem::Dependency.new(name, requirements, type)
- end
-
- class IndexBuilder
- include Builders
-
- def self.run(index, &block)
- new(index).run(&block)
- end
-
- def initialize(index)
- @index = index
- end
-
- def run(&block)
- instance_eval(&block)
- end
-
- def add_spec(*args, &block)
- @index.add_spec(build_spec(*args, &block))
- end
- end
-
- class DepBuilder
- def self.run(spec, &block)
- new(spec).run(&block)
- end
-
- def initialize(spec)
- @spec = spec
- end
-
- def run(&block)
- instance_eval(&block)
- end
-
- def runtime(name, requirements)
- @spec.add_runtime_dependency(name, requirements)
- end
- end
- end
- end
-end \ No newline at end of file
diff --git a/railties/lib/vendor/bundler/lib/bundler/resolver/engine.rb b/railties/lib/vendor/bundler/lib/bundler/resolver/engine.rb
deleted file mode 100644
index 475ba516ff..0000000000
--- a/railties/lib/vendor/bundler/lib/bundler/resolver/engine.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-module Bundler
- module Resolver
- class ClosedSet < Set
- end
-
- class Engine
- include Search, Inspect
-
- def self.resolve(deps, source_index, logger)
- new(deps, source_index, logger).resolve
- end
-
- def initialize(deps, source_index, logger)
- @deps, @source_index, @logger = deps, source_index, logger
- logger.debug "searching for #{gem_resolver_inspect(@deps)}"
- end
- attr_reader :deps, :source_index, :logger, :solution
-
- def resolve
- state = State.initial(self, [], Stack.new, Stack.new([[[], @deps.dup]]))
- if solution = search(state)
- logger.info "got the solution with #{solution.all_specs.size} specs"
- solution.dump(Logger::INFO)
- solution
- end
- end
-
- def open
- @open ||= []
- end
-
- def closed
- @closed ||= ClosedSet.new
- end
- end
- end
-
-end \ No newline at end of file
diff --git a/railties/lib/vendor/bundler/lib/bundler/resolver/inspect.rb b/railties/lib/vendor/bundler/lib/bundler/resolver/inspect.rb
deleted file mode 100644
index 59640aa5f3..0000000000
--- a/railties/lib/vendor/bundler/lib/bundler/resolver/inspect.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-module Bundler
- module Resolver
- module Inspect
- def gem_resolver_inspect(o)
- case o
- when Gem::Specification
- "#<Spec: #{o.full_name}>"
- when Array
- '[' + o.map {|x| gem_resolver_inspect(x)}.join(", ") + ']'
- when Set
- gem_resolver_inspect(o.to_a)
- when Hash
- '{' + o.map {|k,v| "#{gem_resolver_inspect(k)} => #{gem_resolver_inspect(v)}"}.join(", ") + '}'
- when Stack
- o.gem_resolver_inspect
- else
- o.inspect
- end
- end
-
- module_function :gem_resolver_inspect
- end
- end
-end \ No newline at end of file
diff --git a/railties/lib/vendor/bundler/lib/bundler/resolver/search.rb b/railties/lib/vendor/bundler/lib/bundler/resolver/search.rb
deleted file mode 100644
index 34102ff04c..0000000000
--- a/railties/lib/vendor/bundler/lib/bundler/resolver/search.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-module Bundler
- module Resolver
- module Search
- def search(initial, max_depth = (1.0 / 0.0))
- if initial.goal_met?
- return initial
- end
-
- open << initial
-
- while open.any?
- current = open.pop
- closed << current
-
- new = []
- current.each_possibility do |attempt|
- unless closed.include?(attempt)
- if attempt.goal_met?
- return attempt
- elsif attempt.depth < max_depth
- new << attempt
- end
- end
- end
- new.reverse.each do |state|
- open << state
- end
- end
-
- nil
- end
-
- def open
- raise "implement #open in #{self.class}"
- end
-
- def closed
- raise "implement #closed in #{self.class}"
- end
-
- module Node
- def self.included(base)
- base.extend(ClassMethods)
- end
-
- module ClassMethods
- def initial(*data)
- new(0, *data)
- end
- end
-
- def initialize(depth)
- @depth = depth
- end
- attr_reader :depth
-
- def child(*data)
- self.class.new(@depth + 1, *data)
- end
-
- def each_possibility
- raise "implement #each_possibility on #{self.class}"
- end
-
- def goal_met?
- raise "implement #goal_met? on #{self.class}"
- end
- end
- end
- end
-end \ No newline at end of file
diff --git a/railties/lib/vendor/bundler/lib/bundler/resolver/stack.rb b/railties/lib/vendor/bundler/lib/bundler/resolver/stack.rb
deleted file mode 100644
index 6e1ac67e1f..0000000000
--- a/railties/lib/vendor/bundler/lib/bundler/resolver/stack.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-module Bundler
- module Resolver
- class Stack
- def initialize(initial = [])
- @data = []
- initial.each do |(path,value)|
- self[path] = value
- end
- end
-
- def last
- @data.last
- end
-
- def []=(path, value)
- raise ArgumentError, "#{path.inspect} already has a value" if key?(path)
- @data << [path.dup, value]
- end
-
- def [](path)
- if key?(path)
- _, value = @data.find do |(k,v)|
- k == path
- end
- value
- else
- raise "No value for #{path.inspect}"
- end
- end
-
- def key?(path)
- @data.any? do |(k,v)|
- k == path
- end
- end
-
- def each
- @data.each do |(k,v)|
- yield k, v
- end
- end
-
- def map
- @data.map do |(k,v)|
- yield k, v
- end
- end
-
- def each_value
- @data.each do |(k,v)|
- yield v
- end
- end
-
- def dup
- self.class.new(@data.dup)
- end
-
- def to_s
- @data.to_s
- end
-
- def inspect
- @data.inspect
- end
-
- def gem_resolver_inspect
- Inspect.gem_resolver_inspect(@data)
- end
- end
- end
-end \ No newline at end of file
diff --git a/railties/lib/vendor/bundler/lib/bundler/resolver/state.rb b/railties/lib/vendor/bundler/lib/bundler/resolver/state.rb
deleted file mode 100644
index f13ecbbee7..0000000000
--- a/railties/lib/vendor/bundler/lib/bundler/resolver/state.rb
+++ /dev/null
@@ -1,172 +0,0 @@
-module Bundler
- module Resolver
- class State
- include Search::Node, Inspect
-
- def initialize(depth, engine, path, spec_stack, dep_stack)
- super(depth)
- @engine, @path, @spec_stack, @dep_stack = engine, path, spec_stack, dep_stack
- end
- attr_reader :path
-
- def logger
- @engine.logger
- end
-
- def goal_met?
- logger.info "checking if goal is met"
- dump
- no_duplicates?
- all_deps.all? do |dep|
- dependency_satisfied?(dep)
- end
- end
-
- def no_duplicates?
- names = []
- all_specs.each do |s|
- if names.include?(s.name)
- raise "somehow got duplicates for #{s.name}"
- end
- names << s.name
- end
- end
-
- def dependency_satisfied?(dep)
- all_specs.any? do |spec|
- spec.satisfies_requirement?(dep)
- end
- end
-
- def each_possibility(&block)
- index, dep = remaining_deps.first
- if dep
- logger.warn "working on #{dep} for #{spec_name}"
- handle_dep(index, dep, &block)
- else
- logger.warn "no dependencies left for #{spec_name}"
- jump_to_parent(&block)
- end
- end
-
- def handle_dep(index, dep)
- specs = @engine.source_index.search(dep)
-
- specs.reverse.each do |s|
- logger.info "attempting with spec: #{s.full_name}"
- new_path = @path + [index]
- new_spec_stack = @spec_stack.dup
- new_dep_stack = @dep_stack.dup
-
- new_spec_stack[new_path] = s
- new_dep_stack[new_path] = s.runtime_dependencies.sort_by do |dep|
- @engine.source_index.search(dep).size
- end
- yield child(@engine, new_path, new_spec_stack, new_dep_stack)
- end
- end
-
- def jump_to_parent
- if @path.empty?
- dump
- logger.warn "at the end"
- return
- end
-
- logger.info "jumping to parent for #{spec_name}"
- new_path = @path[0..-2]
- new_spec_stack = @spec_stack.dup
- new_dep_stack = @dep_stack.dup
-
- yield child(@engine, new_path, new_spec_stack, new_dep_stack)
- end
-
- def remaining_deps
- remaining_deps_for(@path)
- end
-
- def remaining_deps_for(path)
- no_duplicates?
- remaining = []
- @dep_stack[path].each_with_index do |dep,i|
- remaining << [i, dep] unless all_specs.find {|s| s.name == dep.name}
- end
- remaining
- end
-
- def deps
- @dep_stack[@path]
- end
-
- def spec
- @spec_stack[@path]
- end
-
- def spec_name
- @path.empty? ? "<top>" : spec.full_name
- end
-
- def all_deps
- all_deps = Set.new
- @dep_stack.each_value do |deps|
- all_deps.merge(deps)
- end
- all_deps.to_a
- end
-
- def all_specs
- @spec_stack.map do |path,spec|
- spec
- end
- end
-
- def dump(level = Logger::DEBUG)
- logger.add level, "v" * 80
- logger.add level, "path: #{@path.inspect}"
- logger.add level, "deps: (#{deps.size})"
- deps.map do |dep|
- logger.add level, gem_resolver_inspect(dep)
- end
- logger.add level, "remaining_deps: (#{remaining_deps.size})"
- remaining_deps.each do |dep|
- logger.add level, gem_resolver_inspect(dep)
- end
- logger.add level, "dep_stack: "
- @dep_stack.each do |path,deps|
- logger.add level, "#{path.inspect} (#{deps.size})"
- deps.each do |dep|
- logger.add level, "-> #{gem_resolver_inspect(dep)}"
- end
- end
- logger.add level, "spec_stack: "
- @spec_stack.each do |path,spec|
- logger.add level, "#{path.inspect}: #{gem_resolver_inspect(spec)}"
- end
- logger.add level, "^" * 80
- end
-
- def to_dot
- io = StringIO.new
- io.puts 'digraph deps {'
- io.puts ' fontname = "Courier";'
- io.puts ' mincross = 4.0;'
- io.puts ' ratio = "auto";'
- dump_to_dot(io, "<top>", [])
- io.puts '}'
- io.string
- end
-
- def dump_to_dot(io, name, path)
- @dep_stack[path].each_with_index do |dep,i|
- new_path = path + [i]
- spec_name = all_specs.find {|x| x.name == dep.name}.full_name
- io.puts ' "%s" -> "%s";' % [name, dep.to_s]
- io.puts ' "%s" -> "%s";' % [dep.to_s, spec_name]
- if @spec_stack.key?(new_path)
- dump_to_dot(io, spec_name, new_path)
- end
- end
- end
- end
- end
-end \ No newline at end of file
diff --git a/railties/lib/vendor/bundler/lib/bundler/runtime.rb b/railties/lib/vendor/bundler/lib/bundler/runtime.rb
index 2376deef28..27e0254966 100644
--- a/railties/lib/vendor/bundler/lib/bundler/runtime.rb
+++ b/railties/lib/vendor/bundler/lib/bundler/runtime.rb
@@ -1,39 +1,2 @@
-module Bundler
- class ManifestBuilder
-
- attr_reader :sources
-
- def self.build(path, string)
- builder = new(path)
- builder.instance_eval(string)
- builder.to_manifest
- end
-
- def self.load(path, file)
- string = File.read(file)
- build(path, string)
- end
-
- def initialize(path)
- @path = path
- @sources = %w(http://gems.rubyforge.org)
- @dependencies = []
- end
-
- def to_manifest
- Manifest.new(@sources, @dependencies, @path)
- end
-
- def source(source)
- @sources << source
- end
-
- def gem(name, *args)
- options = args.last.is_a?(Hash) ? args.pop : {}
- version = args.last
-
- @dependencies << Dependency.new(name, options.merge(:version => version))
- end
-
- end
-end \ No newline at end of file
+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/vendor/bundler/lib/bundler/source.rb b/railties/lib/vendor/bundler/lib/bundler/source.rb
new file mode 100644
index 0000000000..37828ca316
--- /dev/null
+++ b/railties/lib/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/vendor/bundler/lib/bundler/templates/app_script.erb b/railties/lib/vendor/bundler/lib/bundler/templates/app_script.erb
new file mode 100644
index 0000000000..3e47a53ca8
--- /dev/null
+++ b/railties/lib/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/vendor/bundler/lib/bundler/templates/environment.erb b/railties/lib/vendor/bundler/lib/bundler/templates/environment.erb
new file mode 100644
index 0000000000..21f3de8854
--- /dev/null
+++ b/railties/lib/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