Skip to content
This repository
Browse code

Vendor the latest version of the bundler

  • Loading branch information...
commit f416f9f0aef654fea94cae10027aca866d07c659 1 parent e3f5fd5
Carl Lerche authored

Showing 30 changed files with 1,389 additions and 811 deletions. Show diff stats Hide diff stats

  1. +162 0 railties/lib/vendor/bundler/README.markdown
  2. +30 25 railties/lib/vendor/bundler/Rakefile
  3. +0 40 railties/lib/vendor/bundler/bin/gem_bundler
  4. +19 9 railties/lib/vendor/bundler/lib/bundler.rb
  5. +35 15 railties/lib/vendor/bundler/lib/bundler/cli.rb
  6. +31 0 railties/lib/vendor/bundler/lib/bundler/commands/bundle_command.rb
  7. +31 0 railties/lib/vendor/bundler/lib/bundler/commands/exec_command.rb
  8. +26 5 railties/lib/vendor/bundler/lib/bundler/dependency.rb
  9. +109 0 railties/lib/vendor/bundler/lib/bundler/dsl.rb
  10. +111 0 railties/lib/vendor/bundler/lib/bundler/environment.rb
  11. +38 29 railties/lib/vendor/bundler/lib/bundler/finder.rb
  12. +3 15 railties/lib/vendor/bundler/lib/bundler/gem_bundle.rb
  13. +25 0 railties/lib/vendor/bundler/lib/bundler/gem_ext.rb
  14. +0 10 railties/lib/vendor/bundler/lib/bundler/gem_specification.rb
  15. +0 44 railties/lib/vendor/bundler/lib/bundler/installer.rb
  16. +0 130 railties/lib/vendor/bundler/lib/bundler/manifest.rb
  17. +151 0 railties/lib/vendor/bundler/lib/bundler/repository.rb
  18. +46 0 railties/lib/vendor/bundler/lib/bundler/repository/directory_repository.rb
  19. +108 0 railties/lib/vendor/bundler/lib/bundler/repository/gem_repository.rb
  20. +182 12 railties/lib/vendor/bundler/lib/bundler/resolver.rb
  21. +0 61 railties/lib/vendor/bundler/lib/bundler/resolver/builders.rb
  22. +0 38 railties/lib/vendor/bundler/lib/bundler/resolver/engine.rb
  23. +0 24 railties/lib/vendor/bundler/lib/bundler/resolver/inspect.rb
  24. +0 71 railties/lib/vendor/bundler/lib/bundler/resolver/search.rb
  25. +0 72 railties/lib/vendor/bundler/lib/bundler/resolver/stack.rb
  26. +0 172 railties/lib/vendor/bundler/lib/bundler/resolver/state.rb
  27. +2 39 railties/lib/vendor/bundler/lib/bundler/runtime.rb
  28. +150 0 railties/lib/vendor/bundler/lib/bundler/source.rb
  29. +3 0  railties/lib/vendor/bundler/lib/bundler/templates/app_script.erb
  30. +127 0 railties/lib/vendor/bundler/lib/bundler/templates/environment.erb
162 railties/lib/vendor/bundler/README.markdown
Source Rendered
... ... @@ -0,0 +1,162 @@
  1 +## Bundler : A gem to bundle gems
  2 +
  3 + Github: http://github.com/wycats/bundler
  4 + Mailing list: http://groups.google.com/group/ruby-bundler
  5 + IRC: #carlhuda on freenode
  6 +
  7 +## Intro
  8 +
  9 +Bundler is a tool that manages gem dependencies for your ruby application. It
  10 +takes a gem manifest file and is able to fetch, download, and install the gems
  11 +and all child dependencies specified in this manifest. It can manage any update
  12 +to the gem manifest file and update the bundled gems accordingly. It also lets
  13 +you run any ruby code in context of the bundled gem environment.
  14 +
  15 +## Disclaimer
  16 +
  17 +This project is under rapid development. It is usable today, but there will be
  18 +many changes in the near future, including to the Gemfile DSL. We will bump up
  19 +versions with changes though. We greatly appreciate feedback.
  20 +
  21 +## Installation
  22 +
  23 +Bundler has no dependencies. Just clone the git repository and install the gem
  24 +with the following rake task:
  25 +
  26 + rake install
  27 +
  28 +## Usage
  29 +
  30 +Bundler requires a gem manifest file to be created. This should be a file named
  31 +`Gemfile` located in the root directory of your application. After the manifest
  32 +has been created, in your shell, cd into your application's directory and run
  33 +`gem bundle`. This will start the bundling process.
  34 +
  35 +### Manifest file
  36 +
  37 +This is where you specify all of your application's dependencies. By default
  38 +this should be in a file named `Gemfile` located in your application's root
  39 +directory. The following is an example of a potential `Gemfile`. For more
  40 +information, please refer to Bundler::ManifestBuilder.
  41 +
  42 + # Specify a dependency on rails. When the bundler downloads gems,
  43 + # it will download rails as well as all of rails' dependencies (such as
  44 + # activerecord, actionpack, etc...)
  45 + #
  46 + # At least one dependency must be specified
  47 + gem "rails"
  48 +
  49 + # Specify a dependency on rack v.1.0.0. The version is optional. If present,
  50 + # it can be specified the same way as with rubygems' #gem method.
  51 + gem "rack", "1.0.0"
  52 +
  53 + # Specify a dependency rspec, but only activate that gem in the "testing"
  54 + # environment (read more about environments later). :except is also a valid
  55 + # option to specify environment restrictions.
  56 + gem "rspec", :only => :testing
  57 +
  58 + # Add http://gems.github.com as a source that the bundler will use
  59 + # to find gems listed in the manifest. By default,
  60 + # http://gems.rubyforge.org is already added to the list.
  61 + #
  62 + # This is an optional setting.
  63 + source "http://gems.github.com"
  64 +
  65 + # Specify where the bundled gems should be stashed. This directory will
  66 + # be a gem repository where all gems are downloaded to and installed to.
  67 + #
  68 + # This is an optional setting.
  69 + # The default is: vendor/gems
  70 + bundle_path "my/bundled/gems"
  71 +
  72 + # Specify where gem executables should be copied to.
  73 + #
  74 + # This is an optional setting.
  75 + # The default is: bin
  76 + bin_path "my/executables"
  77 +
  78 + # Specify that rubygems should be completely disabled. This means that it
  79 + # will be impossible to require it and that available gems will be
  80 + # limited exclusively to gems that have been bundled.
  81 + #
  82 + # The default is to automatically require rubygems. There is also a
  83 + # `disable_system_gems` option that will limit available rubygems to
  84 + # the ones that have been bundled.
  85 + disable_rubygems
  86 +
  87 +### Running Bundler
  88 +
  89 +Once a manifest file has been created, the only thing that needs to be done
  90 +is to run the `gem bundle` command anywhere in your application. The script
  91 +will load the manifest file, resole all the dependencies, download all
  92 +needed gems, and install them into the specified directory.
  93 +
  94 +Every time an update is made to the manifest file, run `gem bundle` again to
  95 +get the changes installed. This will only check the remote sources if your
  96 +currently installed gems do not satisfy the `Gemfile`. If you want to force
  97 +checking for updates on the remote sources, use the `--update` option.
  98 +
  99 +### Running your application
  100 +
  101 +The easiest way to run your application is to start it with an executable
  102 +copied to the specified bin directory (by default, simply bin). For example,
  103 +if the application in question is a rack app, start it with `bin/rackup`.
  104 +This will automatically set the gem environment correctly.
  105 +
  106 +Another way to run arbitrary ruby code in context of the bundled gems is to
  107 +run it with the `gem exec` command. For example:
  108 +
  109 + gem exec ruby my_ruby_script.rb
  110 +
  111 +Yet another way is to manually require the environment file first. This is
  112 +located in `[bundle_path]/environments/default.rb`. For example:
  113 +
  114 + ruby -r vendor/gems/environment.rb my_ruby_script.rb
  115 +
  116 +### Using Bundler with Rails today
  117 +
  118 +It should be possible to use Bundler with Rails today. Here are the steps
  119 +to follow.
  120 +
  121 +* In your rails app, create a Gemfile and specify the gems that your
  122 + application depends on. Make sure to specify rails as well:
  123 +
  124 + gem "rails", "2.1.2"
  125 + gem "will_paginate"
  126 +
  127 + # Optionally, you can disable system gems all together and only
  128 + # use bundled gems.
  129 + disable_system_gems
  130 +
  131 +* Run `gem bundle`
  132 +
  133 +* You can now use rails if you prepend `gem exec` to every call to `script/*`
  134 + but that isn't fun.
  135 +
  136 +* At the top of `config/boot.rb`, add the following line:
  137 +
  138 + require File.expand_path(File.join(File.dirname(__FILE__), '..', 'vendor', 'gems', 'environment'))
  139 +
  140 +In theory, this should be enough to get going.
  141 +
  142 +## To require rubygems or not
  143 +
  144 +Ideally, no gem would assume the presence of rubygems at runtime. Rubygems provides
  145 +enough features so that this isn't necessary. However, there are a number of gems
  146 +that require specific rubygem features.
  147 +
  148 +If the `disable_rubygems` option is used, Bundler will stub out the most common
  149 +of these features, but it is possible that things will not go as intended quite
  150 +yet. So, if you are brave, try your code without rubygems at runtime.
  151 +
  152 +## Known Issues
  153 +
  154 +* When a gem points to a git repository, the git repository will be cloned
  155 + every time Bundler does a gem dependency resolve.
  156 +
  157 +## Reporting bugs
  158 +
  159 +Please report all bugs on the github issue tracker for the project located
  160 +at:
  161 +
  162 + http://github.com/wycats/bundler/issues/
55 railties/lib/vendor/bundler/Rakefile
... ... @@ -1,52 +1,57 @@
1 1 require 'rubygems' unless ENV['NO_RUBYGEMS']
2   -require 'rake/gempackagetask'
3 2 require 'rubygems/specification'
4 3 require 'date'
5   -require 'spec/rake/spectask'
6 4
7 5 spec = Gem::Specification.new do |s|
8   - s.name = "bundler"
9   - s.version = "0.0.1"
10   - s.author = "Your Name"
11   - s.email = "Your Email"
12   - s.homepage = "http://example.com"
13   - s.description = s.summary = "A gem that provides..."
  6 + s.name = "bundler"
  7 + s.version = "0.5.0.pre"
  8 + s.author = "Yehuda Katz"
  9 + s.email = "wycats@gmail.com"
  10 + s.homepage = "http://github.com/wycats/bundler"
  11 + s.description = s.summary = "An easy way to vendor gem dependencies"
14 12
15 13 s.platform = Gem::Platform::RUBY
16 14 s.has_rdoc = true
17   - s.extra_rdoc_files = ["README", "LICENSE"]
18   - s.summary = ""
  15 + s.extra_rdoc_files = ["README.markdown", "LICENSE"]
19 16
20   - # Uncomment this to add a dependency
21   - # s.add_dependency "foo"
  17 + s.required_rubygems_version = ">= 1.3.5"
22 18
23   - s.bindir = "bin"
24   - s.executables = %w( gem_bundler )
25 19 s.require_path = 'lib'
26   - s.files = %w(LICENSE README Rakefile) + Dir.glob("{bin,lib,spec}/**/*")
  20 + s.files = %w(LICENSE README.markdown Rakefile) + Dir.glob("lib/**/*")
27 21 end
28 22
29 23 task :default => :spec
30 24
31   -desc "Run specs"
32   -Spec::Rake::SpecTask.new do |t|
33   - t.spec_files = FileList['spec/**/*_spec.rb']
34   - t.spec_opts = %w(-fs --color)
  25 +begin
  26 + require 'spec/rake/spectask'
  27 +rescue LoadError
  28 + task(:spec) { $stderr.puts '`gem install rspec` to run specs' }
  29 +else
  30 + desc "Run specs"
  31 + Spec::Rake::SpecTask.new do |t|
  32 + t.spec_files = FileList['spec/**/*_spec.rb'] - FileList['spec/fixtures/**/*_spec.rb']
  33 + t.spec_opts = %w(-fs --color)
  34 + end
35 35 end
36 36
37   -
38   -Rake::GemPackageTask.new(spec) do |pkg|
39   - pkg.gem_spec = spec
  37 +begin
  38 + require 'rake/gempackagetask'
  39 +rescue LoadError
  40 + task(:gem) { $stderr.puts '`gem install rake` to package gems' }
  41 +else
  42 + Rake::GemPackageTask.new(spec) do |pkg|
  43 + pkg.gem_spec = spec
  44 + end
40 45 end
41 46
42 47 desc "install the gem locally"
43 48 task :install => [:package] do
44   - sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
  49 + sh %{gem install pkg/#{spec.name}-#{spec.version}}
45 50 end
46 51
47 52 desc "create a gemspec file"
48 53 task :make_spec do
49   - File.open("#{GEM}.gemspec", "w") do |file|
  54 + File.open("#{spec.name}.gemspec", "w") do |file|
50 55 file.puts spec.to_ruby
51 56 end
52   -end
  57 +end
40 railties/lib/vendor/bundler/bin/gem_bundler
... ... @@ -1,40 +0,0 @@
1   -#!/usr/bin/env ruby
2   -require "optparse"
3   -require "bundler"
4   -
5   -options = {}
6   -
7   -parser = OptionParser.new do |op|
8   - op.banner = "Usage: gem_bundler [OPTIONS] [PATH]"
9   -
10   - op.on("-m", "--manifest MANIFEST") do |manifest|
11   - options[:manifest] = manifest
12   - end
13   -
14   - op.on_tail("-h", "--help", "Show this message") do
15   - puts op
16   - exit
17   - end
18   -end
19   -parser.parse!
20   -
21   -options[:path] = ARGV.shift
22   -
23   -unless options[:path]
24   - puts parser
25   - puts %(
26   - [PATH] must be specified
27   - )
28   - exit
29   -end
30   -
31   -unless options[:manifest] && File.exist?(options[:manifest])
32   - puts parser
33   - puts %(
34   - MANIFEST must be a valid manifest file
35   - )
36   - exit
37   -end
38   -
39   -
40   -Bundler.run(options)
28 railties/lib/vendor/bundler/lib/bundler.rb
... ... @@ -1,24 +1,34 @@
  1 +require 'pathname'
1 2 require 'logger'
2 3 require 'set'
  4 +require 'erb'
3 5 # Required elements of rubygems
4 6 require "rubygems/remote_fetcher"
5 7 require "rubygems/installer"
6 8
7 9 require "bundler/gem_bundle"
8   -require "bundler/installer"
  10 +require "bundler/source"
9 11 require "bundler/finder"
10   -require "bundler/gem_specification"
  12 +require "bundler/gem_ext"
11 13 require "bundler/resolver"
12   -require "bundler/manifest"
13   -require "bundler/dependency"
14   -require "bundler/runtime"
  14 +require "bundler/environment"
  15 +require "bundler/dsl"
15 16 require "bundler/cli"
  17 +require "bundler/repository"
  18 +require "bundler/dependency"
16 19
17 20 module Bundler
18 21 VERSION = "0.5.0"
19 22
20   - def self.run(options = {})
21   - manifest = ManifestBuilder.load(options[:path], options[:manifest])
22   - manifest.install
  23 + class << self
  24 + attr_writer :logger
  25 +
  26 + def logger
  27 + @logger ||= begin
  28 + logger = Logger.new(STDOUT, Logger::INFO)
  29 + logger.formatter = proc {|_,_,_,msg| "#{msg}\n" }
  30 + logger
  31 + end
  32 + end
23 33 end
24   -end
  34 +end
50 railties/lib/vendor/bundler/lib/bundler/cli.rb
... ... @@ -1,24 +1,44 @@
1   -module Bundler
2   - module CLI
  1 +require "optparse"
3 2
4   - def default_manifest
5   - current = Pathname.new(Dir.pwd)
  3 +module Bundler
  4 + class CLI
  5 + def self.run(command, options = {})
  6 + new(options).run(command)
  7 + rescue DefaultManifestNotFound => e
  8 + Bundler.logger.error "Could not find a Gemfile to use"
  9 + exit 2
  10 + rescue InvalidEnvironmentName => e
  11 + Bundler.logger.error "Gemfile error: #{e.message}"
  12 + exit
  13 + rescue InvalidRepository => e
  14 + Bundler.logger.error e.message
  15 + exit
  16 + rescue VersionConflict => e
  17 + Bundler.logger.error e.message
  18 + exit
  19 + rescue GemNotFound => e
  20 + Bundler.logger.error e.message
  21 + exit
  22 + end
6 23
7   - begin
8   - manifest = current.join("Gemfile")
9   - return manifest.to_s if File.exist?(manifest)
10   - current = current.parent
11   - end until current.root?
12   - nil
  24 + def initialize(options)
  25 + @options = options
  26 + @manifest = Bundler::Environment.load(@options[:manifest])
13 27 end
14 28
15   - module_function :default_manifest
  29 + def bundle
  30 + @manifest.install(@options[:update])
  31 + end
16 32
17   - def default_path
18   - Pathname.new(File.dirname(default_manifest)).join("vendor").join("gems").to_s
  33 + def exec
  34 + @manifest.setup_environment
  35 + # w0t?
  36 + super(*@options[:args])
19 37 end
20 38
21   - module_function :default_path
  39 + def run(command)
  40 + send(command)
  41 + end
22 42
23 43 end
24   -end
  44 +end
31 railties/lib/vendor/bundler/lib/bundler/commands/bundle_command.rb
... ... @@ -0,0 +1,31 @@
  1 +class Gem::Commands::BundleCommand < Gem::Command
  2 +
  3 + def initialize
  4 + super('bundle', 'Create a gem bundle based on your Gemfile', {:manifest => nil, :update => false})
  5 +
  6 + add_option('-m', '--manifest MANIFEST', "Specify the path to the manifest file") do |manifest, options|
  7 + options[:manifest] = manifest
  8 + end
  9 +
  10 + add_option('-u', '--update', "Force a remote check for newer gems") do
  11 + options[:update] = true
  12 + end
  13 + end
  14 +
  15 + def usage
  16 + "#{program_name}"
  17 + end
  18 +
  19 + def description # :nodoc:
  20 + <<-EOF
  21 +Bundle stuff
  22 + EOF
  23 + end
  24 +
  25 + def execute
  26 + # Prevent the bundler from getting required unless it is actually being used
  27 + require 'bundler'
  28 + Bundler::CLI.run(:bundle, options)
  29 + end
  30 +
  31 +end
31 railties/lib/vendor/bundler/lib/bundler/commands/exec_command.rb
... ... @@ -0,0 +1,31 @@
  1 +class Gem::Commands::ExecCommand < Gem::Command
  2 +
  3 + def initialize
  4 + super('exec', 'Run a command in context of a gem bundle', {:manifest => nil})
  5 +
  6 + add_option('-m', '--manifest MANIFEST', "Specify the path to the manifest file") do |manifest, options|
  7 + options[:manifest] = manifest
  8 + end
  9 + end
  10 +
  11 + def usage
  12 + "#{program_name} COMMAND"
  13 + end
  14 +
  15 + def arguments # :nodoc:
  16 + "COMMAND command to run in context of the gem bundle"
  17 + end
  18 +
  19 + def description # :nodoc:
  20 + <<-EOF.gsub(' ', '')
  21 + Run in context of a bundle
  22 + EOF
  23 + end
  24 +
  25 + def execute
  26 + # Prevent the bundler from getting required unless it is actually being used
  27 + require 'bundler'
  28 + Bundler::CLI.run(:exec, options)
  29 + end
  30 +
  31 +end
31 railties/lib/vendor/bundler/lib/bundler/dependency.rb
... ... @@ -1,9 +1,10 @@
1 1 module Bundler
2   - class Dependency
  2 + class InvalidEnvironmentName < StandardError; end
3 3
  4 + class Dependency
4 5 attr_reader :name, :version, :require_as, :only, :except
5 6
6   - def initialize(name, options = {})
  7 + def initialize(name, options = {}, &block)
7 8 options.each do |k, v|
8 9 options[k.to_s] = v
9 10 end
@@ -11,8 +12,13 @@ def initialize(name, options = {})
11 12 @name = name
12 13 @version = options["version"] || ">= 0"
13 14 @require_as = Array(options["require_as"] || name)
14   - @only = Array(options["only"]).map {|e| e.to_s } if options["only"]
15   - @except = Array(options["except"]).map {|e| e.to_s } if options["except"]
  15 + @only = options["only"]
  16 + @except = options["except"]
  17 + @block = block
  18 +
  19 + if (@only && @only.include?("rubygems")) || (@except && @except.include?("rubygems"))
  20 + raise InvalidEnvironmentName, "'rubygems' is not a valid environment name"
  21 + end
16 22 end
17 23
18 24 def in?(environment)
@@ -27,9 +33,24 @@ def to_s
27 33 to_gem_dependency.to_s
28 34 end
29 35
  36 + def require(environment)
  37 + return unless in?(environment)
  38 +
  39 + @require_as.each do |file|
  40 + super(file)
  41 + end
  42 +
  43 + @block.call if @block
  44 + end
  45 +
30 46 def to_gem_dependency
31 47 @gem_dep ||= Gem::Dependency.new(name, version)
32 48 end
33 49
  50 + def ==(o)
  51 + [name, version, require_as, only, except] ==
  52 + [o.name, o.version, o.require_as, o.only, o.except]
  53 + end
  54 +
34 55 end
35   -end
  56 +end
109 railties/lib/vendor/bundler/lib/bundler/dsl.rb
... ... @@ -0,0 +1,109 @@
  1 +module Bundler
  2 + class ManifestFileNotFound < StandardError; end
  3 +
  4 + class Dsl
  5 + def initialize(environment)
  6 + @environment = environment
  7 + @sources = Hash.new { |h,k| h[k] = {} }
  8 + end
  9 +
  10 + def bundle_path(path)
  11 + path = Pathname.new(path)
  12 + @environment.gem_path = (path.relative? ?
  13 + @environment.root.join(path) : path).expand_path
  14 + end
  15 +
  16 + def bin_path(path)
  17 + path = Pathname.new(path)
  18 + @environment.bindir = (path.relative? ?
  19 + @environment.root.join(path) : path).expand_path
  20 + end
  21 +
  22 + def disable_rubygems
  23 + @environment.rubygems = false
  24 + end
  25 +
  26 + def disable_system_gems
  27 + @environment.system_gems = false
  28 + end
  29 +
  30 + def source(source)
  31 + source = GemSource.new(:uri => source)
  32 + unless @environment.sources.include?(source)
  33 + @environment.add_source(source)
  34 + end
  35 + end
  36 +
  37 + def only(env)
  38 + old, @only = @only, _combine_onlys(env)
  39 + yield
  40 + @only = old
  41 + end
  42 +
  43 + def except(env)
  44 + old, @except = @except, _combine_excepts(env)
  45 + yield
  46 + @except = old
  47 + end
  48 +
  49 + def clear_sources
  50 + @environment.clear_sources
  51 + end
  52 +
  53 + def gem(name, *args)
  54 + options = args.last.is_a?(Hash) ? args.pop : {}
  55 + version = args.last
  56 +
  57 + options[:only] = _combine_onlys(options[:only] || options["only"])
  58 + options[:except] = _combine_excepts(options[:except] || options["except"])
  59 +
  60 + dep = Dependency.new(name, options.merge(:version => version))
  61 +
  62 + # OMG REFACTORZ. KTHX
  63 + if vendored_at = options[:vendored_at]
  64 + vendored_at = Pathname.new(vendored_at)
  65 + vendored_at = @environment.filename.dirname.join(vendored_at) if vendored_at.relative?
  66 +
  67 + @sources[:directory][vendored_at.to_s] ||= begin
  68 + source = DirectorySource.new(
  69 + :name => name,
  70 + :version => version,
  71 + :location => vendored_at
  72 + )
  73 + @environment.add_priority_source(source)
  74 + true
  75 + end
  76 + elsif git = options[:git]
  77 + @sources[:git][git] ||= begin
  78 + source = GitSource.new(
  79 + :name => name,
  80 + :version => version,
  81 + :uri => git,
  82 + :ref => options[:commit] || options[:tag],
  83 + :branch => options[:branch]
  84 + )
  85 + @environment.add_priority_source(source)
  86 + true
  87 + end
  88 + end
  89 +
  90 + @environment.dependencies << dep
  91 + end
  92 +
  93 + private
  94 +
  95 + def _combine_onlys(only)
  96 + return @only unless only
  97 + only = [only].flatten.compact.uniq.map { |o| o.to_s }
  98 + only &= @only if @only
  99 + only
  100 + end
  101 +
  102 + def _combine_excepts(except)
  103 + return @except unless except
  104 + except = [except].flatten.compact.uniq.map { |o| o.to_s }
  105 + except |= @except if @except
  106 + except
  107 + end
  108 + end
  109 +end
111 railties/lib/vendor/bundler/lib/bundler/environment.rb
... ... @@ -0,0 +1,111 @@
  1 +require "rubygems/source_index"
  2 +
  3 +module Bundler
  4 + class DefaultManifestNotFound < StandardError; end
  5 +
  6 + class Environment
  7 + attr_reader :filename, :dependencies
  8 + attr_accessor :rubygems, :system_gems, :gem_path, :bindir
  9 +
  10 + def self.load(gemfile = nil)
  11 + gemfile = gemfile ? Pathname.new(gemfile) : default_manifest_file
  12 +
  13 + unless gemfile.file?
  14 + raise ManifestFileNotFound, "#{filename.inspect} does not exist"
  15 + end
  16 +
  17 + new(gemfile)
  18 + end
  19 +
  20 + def self.default_manifest_file
  21 + current = Pathname.new(Dir.pwd)
  22 +
  23 + until current.root?
  24 + filename = current.join("Gemfile")
  25 + return filename if filename.exist?
  26 + current = current.parent
  27 + end
  28 +
  29 + raise DefaultManifestNotFound
  30 + end
  31 +
  32 + def initialize(filename) #, sources, dependencies, bindir, path, rubygems, system_gems)
  33 + @filename = filename
  34 + @default_sources = [GemSource.new(:uri => "http://gems.rubyforge.org")]
  35 + @sources = []
  36 + @priority_sources = []
  37 + @dependencies = []
  38 + @rubygems = true
  39 + @system_gems = true
  40 +
  41 + # Evaluate the Gemfile
  42 + builder = Dsl.new(self)
  43 + builder.instance_eval(File.read(filename))
  44 + end
  45 +
  46 + def install(update = false)
  47 + begin
  48 + tmp_path = filename.dirname.join(".tmp")
  49 + FileUtils.mkdir_p(tmp_path)
  50 + sources.each { |s| s.tmp_path = tmp_path }
  51 + repository.install(gem_dependencies, sources,
  52 + :rubygems => rubygems,
  53 + :system_gems => system_gems,
  54 + :manifest => filename,
  55 + :update => update
  56 + )
  57 + ensure
  58 + FileUtils.rm_rf(tmp_path)
  59 + end
  60 + Bundler.logger.info "Done."
  61 + end
  62 +
  63 + def setup_environment
  64 + unless system_gems
  65 + ENV["GEM_HOME"] = gem_path
  66 + ENV["GEM_PATH"] = gem_path
  67 + end
  68 + ENV["PATH"] = "#{bindir}:#{ENV["PATH"]}"
  69 + ENV["RUBYOPT"] = "-r#{gem_path}/environment #{ENV["RUBYOPT"]}"
  70 + end
  71 +
  72 + def root
  73 + filename.parent
  74 + end
  75 +
  76 + def gem_path
  77 + @gem_path ||= root.join("vendor", "gems")
  78 + end
  79 +
  80 + def bindir
  81 + @bindir ||= root.join("bin")
  82 + end
  83 +
  84 + def sources
  85 + @priority_sources + @sources + @default_sources
  86 + end
  87 +
  88 + def add_source(source)
  89 + @sources << source
  90 + end
  91 +
  92 + def add_priority_source(source)
  93 + @priority_sources << source
  94 + end
  95 +
  96 + def clear_sources
  97 + @sources.clear
  98 + @default_sources.clear
  99 + end
  100 +
  101 + private
  102 +
  103 + def repository
  104 + @repository ||= Repository.new(gem_path, bindir)
  105 + end
  106 +
  107 + def gem_dependencies
  108 + @gem_dependencies ||= dependencies.map { |d| d.to_gem_dependency }
  109 + end
  110 + end
  111 +end
67 railties/lib/vendor/bundler/lib/bundler/finder.rb
... ... @@ -1,42 +1,51 @@
1 1 module Bundler
  2 + # Finder behaves like a rubygems source index in that it responds
  3 + # to #search. It also resolves a list of dependencies finding the
  4 + # best possible configuration of gems that satisifes all requirements
  5 + # without causing any gem activation errors.
2 6 class Finder
3   - def initialize(*sources)
4   - @results = {}
5   - @index = Hash.new { |h,k| h[k] = {} }
6 7
7   - sources.each { |source| fetch(source) }
  8 + # Takes an array of gem sources and fetches the full index of
  9 + # gems from each one. It then combines the indexes together keeping
  10 + # track of the original source so that any resolved gem can be
  11 + # fetched from the correct source.
  12 + #
  13 + # ==== Parameters
  14 + # *sources<String>:: URI pointing to the gem repository
  15 + def initialize(*sources)
  16 + @cache = {}
  17 + @index = {}
  18 + @sources = sources
8 19 end
9 20
10   - def resolve(*dependencies)
11   - resolved = Resolver.resolve(dependencies, self)
12   - resolved && GemBundle.new(resolved.all_specs)
  21 + # Searches for a gem that matches the dependency
  22 + #
  23 + # ==== Parameters
  24 + # dependency<Gem::Dependency>:: The gem dependency to search for
  25 + #
  26 + # ==== Returns
  27 + # [Gem::Specification]:: A collection of gem specifications
  28 + # matching the search
  29 + def search(dependency)
  30 + @cache[dependency.hash] ||= begin
  31 + find_by_name(dependency.name).select do |spec|
  32 + dependency =~ spec
  33 + end.sort_by {|s| s.version }
  34 + end
13 35 end
14 36
15   - def fetch(source)
16   - deflated = Gem::RemoteFetcher.fetcher.fetch_path("#{source}/Marshal.4.8.Z")
17   - inflated = Gem.inflate deflated
  37 + private
18 38
19   - append(Marshal.load(inflated), source)
20   - rescue Gem::RemoteFetcher::FetchError => e
21   - raise ArgumentError, "#{source} is not a valid source: #{e.message}"
22   - end
23   -
24   - def append(index, source)
25   - index.gems.values.each do |spec|
26   - next unless Gem::Platform.match(spec.platform)
27   - spec.source = source
28   - @index[spec.name][spec.version] ||= spec
  39 + def find_by_name(name)
  40 + matches = @index[name] ||= begin
  41 + versions = {}
  42 + @sources.reverse_each do |source|
  43 + versions.merge! source.specs[name] || {}
  44 + end
  45 + versions
29 46 end
30   - self
  47 + matches.values
31 48 end
32 49
33   - def search(dependency)
34   - @results[dependency.hash] ||= begin
35   - possibilities = @index[dependency.name].values
36   - possibilities.select do |spec|
37   - dependency =~ spec
38   - end.sort_by {|s| s.version }
39   - end
40   - end
41 50 end
42 51 end
18 railties/lib/vendor/bundler/lib/bundler/gem_bundle.rb
... ... @@ -1,22 +1,10 @@
1 1 module Bundler
2 2 class GemBundle < Array
3   - def download(directory)
4   - FileUtils.mkdir_p(directory)
5   -
6   - current = Dir[File.join(directory, "cache", "*.gem*")]
7   -
8   - each do |spec|
9   - cached = File.join(directory, "cache", "#{spec.full_name}.gem")
10   -
11   - unless File.file?(cached)
12   - Gem::RemoteFetcher.fetcher.download(spec, spec.source, directory)
13   - end
14   -
15   - current.delete(cached)
  3 + def download(repository)
  4 + sort_by {|s| s.full_name.downcase }.each do |spec|
  5 + spec.source.download(spec, repository)
16 6 end
17 7
18   - current.each { |file| File.delete(file) }
19   -
20 8 self
21 9 end
22 10 end
25 railties/lib/vendor/bundler/lib/bundler/gem_ext.rb
... ... @@ -0,0 +1,25 @@
  1 +module Gem
  2 + class Installer
  3 + def app_script_text(bin_file_name)
  4 + path = @gem_home
  5 + template = File.read(File.join(File.dirname(__FILE__), "templates", "app_script.erb"))
  6 + erb = ERB.new(template, nil, '-')
  7 + erb.result(binding)
  8 + end
  9 + end
  10 +
  11 + class Specification
  12 + attr_accessor :source
  13 + attr_accessor :location
  14 +
  15 + # Hack to fix github's strange marshal file
  16 + def specification_version
  17 + @specification_version && @specification_version.to_i
  18 + end
  19 +
  20 + alias full_gem_path_without_location full_gem_path
  21 + def full_gem_path
  22 + @location ? @location : full_gem_path_without_location
  23 + end
  24 + end
  25 +end
10 railties/lib/vendor/bundler/lib/bundler/gem_specification.rb
... ... @@ -1,10 +0,0 @@
1   -module Gem
2   - class Specification
3   - attribute :source
4   -
5   - def source=(source)
6   - @source = source.is_a?(URI) ? source : URI.parse(source)
7   - raise ArgumentError, "The source must be an absolute URI" unless @source.absolute?
8   - end
9   - end
10   -end
44 railties/lib/vendor/bundler/lib/bundler/installer.rb
... ... @@ -1,44 +0,0 @@
1   -module Bundler
2   - class Installer
3   - def initialize(path)
4   - if !File.directory?(path)
5   - raise ArgumentError, "#{path} is not a directory"
6   - elsif !File.directory?(File.join(path, "cache"))
7   - raise ArgumentError, "#{path} is not a valid environment (it does not contain a cache directory)"
8   - end
9   -
10   - @path = path
11   - @gems = Dir[(File.join(path, "cache", "*.gem"))]
12   - end
13   -
14   - def install(options = {})
15   - bin_dir = options[:bin_dir] ||= File.join(@path, "bin")
16   -
17   - specs = Dir[File.join(@path, "specifications", "*.gemspec")]
18   - gems = Dir[File.join(@path, "gems", "*")]
19   -
20   - @gems.each do |gem|
21   - name = File.basename(gem).gsub(/\.gem$/, '')
22   - installed = specs.any? { |g| File.basename(g) == "#{name}.gemspec" } &&
23   - gems.any? { |g| File.basename(g) == name }
24   -
25   - unless installed
26   - installer = Gem::Installer.new(gem, :install_dir => @path,
27   - :ignore_dependencies => true,
28   - :env_shebang => true,
29   - :wrappers => true,
30   - :bin_dir => bin_dir)
31   - installer.install
32   - end
33   -
34   - # remove this spec
35   - specs.delete_if { |g| File.basename(g) == "#{name}.gemspec"}
36   - gems.delete_if { |g| File.basename(g) == name }
37   - end
38   -
39   - (specs + gems).each do |path|
40   - FileUtils.rm_rf(path)
41   - end
42   - end
43   - end
44   -end
130 railties/lib/vendor/bundler/lib/bundler/manifest.rb
... ... @@ -1,130 +0,0 @@
1   -require "rubygems/source_index"
2   -require "pathname"
3   -
4   -module Bundler
5   - class VersionConflict < StandardError; end
6   -
7   - class Manifest
8   - attr_reader :sources, :dependencies, :path
9   -
10   - def initialize(sources, dependencies, path)
11   - sources.map! {|s| s.is_a?(URI) ? s : URI.parse(s) }
12   - @sources, @dependencies, @path = sources, dependencies, Pathname.new(path)
13   - end
14   -
15   - def fetch
16   - return if all_gems_installed?
17   -
18   - finder = Finder.new(*sources)
19   - unless bundle = finder.resolve(*gem_dependencies)
20   - gems = @dependencies.map {|d| " #{d.to_s}" }.join("\n")
21   - raise VersionConflict, "No compatible versions could be found for:\n#{gems}"
22   - end
23   -
24   - bundle.download(@path)
25   - end
26   -
27   - def install(options = {})
28   - fetch
29   - installer = Installer.new(@path)
30   - installer.install # options come here
31   - create_load_paths_files(File.join(@path, "environments"))
32   - create_fake_rubygems(File.join(@path, "environments"))
33   - end
34   -
35   - def activate(environment = "default")
36   - require File.join(@path, "environments", "#{environment}.rb")
37   - end
38   -
39   - def require_all
40   - dependencies.each do |dep|
41   - dep.require_as.each {|file| require file }
42   - end
43   - end
44   -
45   - def gems_for(environment)
46   - deps = dependencies.select { |d| d.in?(environment) }
47   - deps.map! { |d| d.to_gem_dependency }
48   - index = Gem::SourceIndex.from_gems_in(File.join(@path, "specifications"))
49   - Resolver.resolve(deps, index).all_specs
50   - end
51   -
52   - def environments
53   - envs = dependencies.map {|dep| Array(dep.only) + Array(dep.except) }.flatten
54   - envs << "default"
55   - end
56   -
57   - private
58   -
59   - def gem_dependencies
60   - @gem_dependencies ||= dependencies.map { |d| d.to_gem_dependency }
61   - end
62   -
63   - def all_gems_installed?
64   - gem_versions = {}
65   -
66   - Dir[File.join(@path, "cache", "*.gem")].each do |file|
67   - file =~ /\/([^\/]+)-([\d\.]+)\.gem$/
68   - name, version = $1, $2
69   - gem_versions[name] = Gem::Version.new(version)
70   - end
71   -
72   - gem_dependencies.all? do |dep|
73   - gem_versions[dep.name] &&
74   - dep.version_requirements.satisfied_by?(gem_versions[dep.name])
75   - end
76   - end
77   -
78   - def create_load_paths_files(path)
79   - FileUtils.mkdir_p(path)
80   - environments.each do |environment|
81   - gem_specs = gems_for(environment)
82   - File.open(File.join(path, "#{environment}.rb"), "w") do |file|
83   - file.puts <<-RUBY_EVAL
84   - module Bundler
85   - def self.rubygems_required
86   - #{create_gem_stubs(path, gem_specs)}
87   - end
88   - end
89   - RUBY_EVAL
90   - file.puts "$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__))"
91   - load_paths_for_specs(gem_specs).each do |load_path|
92   - file.puts "$LOAD_PATH.unshift #{load_path.inspect}"
93   - end
94   - end
95   - end
96   - end
97   -
98   - def create_gem_stubs(path, gem_specs)
99   - gem_specs.map do |spec|
100   - path = File.expand_path(File.join(path, '..', 'specifications', "#{spec.full_name}.gemspec"))
101   - %{
102   - Gem.loaded_specs["#{spec.name}"] = eval(File.read("#{path}"))
103   - }
104   - end.join("\n")
105   - end
106   -
107   - def create_fake_rubygems(path)
108   - File.open(File.join(path, "rubygems.rb"), "w") do |file|
109   - file.puts <<-RUBY_EVAL
110   - $:.delete File.expand_path(File.dirname(__FILE__))
111   - load "rubygems.rb"
112   - if defined?(Bundler) && Bundler.respond_to?(:rubygems_required)
113   - Bundler.rubygems_required
114   - end
115   - RUBY_EVAL
116   - end
117   - end
118   -
119   - def load_paths_for_specs(specs)
120   - load_paths = []
121   - specs.each do |spec|
122   - load_paths << File.join(spec.full_gem_path, spec.bindir) if spec.bindir
123   - spec.require_paths.each do |path|
124   - load_paths << File.join(spec.full_gem_path, path)
125   - end
126   - end
127   - load_paths
128   - end
129   - end
130   -end
151 railties/lib/vendor/bundler/lib/bundler/repository.rb
... ... @@ -0,0 +1,151 @@
  1 +require "bundler/repository/gem_repository"
  2 +require "bundler/repository/directory_repository"
  3 +
  4 +module Bundler
  5 + class InvalidRepository < StandardError ; end
  6 +
  7 + class Repository
  8 + attr_reader :path
  9 +
  10 + def initialize(path, bindir)
  11 + FileUtils.mkdir_p(path)
  12 +
  13 + @path = Pathname.new(path)
  14 + @bindir = Pathname.new(bindir)
  15 +
  16 + @repos = {
  17 + :gem => Gems.new(@path, @bindir),
  18 + :directory => Directory.new(@path.join("dirs"), @bindir)
  19 + }
  20 + end
  21 +
  22 + def install(dependencies, sources, options = {})
  23 + if options[:update] || !satisfies?(dependencies)
  24 + fetch(dependencies, sources)
  25 + expand(options)
  26 + else
  27 + # Remove any gems that are still around if the Gemfile changed without
  28 + # requiring new gems to be download (e.g. a line in the Gemfile was
  29 + # removed)
  30 + cleanup(Resolver.resolve(dependencies, [source_index]