summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYehuda Katz + Carl Lerche <ykatz+clerche@engineyard.com>2009-08-17 17:20:25 -0700
committerYehuda Katz + Carl Lerche <ykatz+clerche@engineyard.com>2009-08-17 17:20:25 -0700
commit0c9043049ff3d9554dd0736c518bf22f8a5ee00d (patch)
treedd58674b438017ab93d978a3ccefc6d6c8345e42
parent4d1aa38bb72be5b3b225255b346883190cb92b26 (diff)
downloadbundler-0c9043049ff3d9554dd0736c518bf22f8a5ee00d.tar.gz
Implemented Bundler.require for runtime requiring
-rw-r--r--lib/bundler.rb2
-rw-r--r--lib/bundler/dependency.rb13
-rw-r--r--lib/bundler/dsl.rb61
-rw-r--r--lib/bundler/manifest.rb12
-rw-r--r--lib/bundler/manifest_file.rb2
-rw-r--r--lib/bundler/runtime.rb67
-rw-r--r--lib/bundler/templates/environment.rb6
-rw-r--r--spec/bundler/cli_spec.rb12
-rw-r--r--spec/bundler/manifest_spec.rb60
-rw-r--r--spec/bundler/runtime_spec.rb109
-rw-r--r--spec/spec_helper.rb9
11 files changed, 234 insertions, 119 deletions
diff --git a/lib/bundler.rb b/lib/bundler.rb
index fc7b51f749..8fdeb22696 100644
--- a/lib/bundler.rb
+++ b/lib/bundler.rb
@@ -14,7 +14,7 @@ require "bundler/resolver"
require "bundler/manifest_file"
require "bundler/manifest"
require "bundler/dependency"
-require "bundler/runtime"
+require "bundler/dsl"
require "bundler/cli"
require "bundler/repository"
diff --git a/lib/bundler/dependency.rb b/lib/bundler/dependency.rb
index 9c40431013..75d15a27fa 100644
--- a/lib/bundler/dependency.rb
+++ b/lib/bundler/dependency.rb
@@ -4,7 +4,7 @@ module Bundler
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
@@ -14,6 +14,7 @@ module Bundler
@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"]
+ @block = block
if (@only && @only.include?("rubygems")) || (@except && @except.include?("rubygems"))
raise InvalidEnvironmentName, "'rubygems' is not a valid environment name"
@@ -32,6 +33,16 @@ 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
diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb
new file mode 100644
index 0000000000..3cc87826f5
--- /dev/null
+++ b/lib/bundler/dsl.rb
@@ -0,0 +1,61 @@
+module Bundler
+ class ManifestFileNotFound < StandardError; end
+
+ class ManifestBuilder
+ def self.build(manifest_file, string)
+ builder = new(manifest_file)
+ builder.instance_eval(string)
+ builder
+ end
+
+ def self.load(manifest_file, filename)
+ unless File.exist?(filename)
+ raise ManifestFileNotFound, "#{filename.inspect} does not exist"
+ end
+ string = File.read(filename)
+ build(manifest_file, string)
+ end
+
+ def initialize(manifest_file)
+ @manifest_file = manifest_file
+ end
+
+ def bundle_path(path)
+ path = Pathname.new(path)
+ @manifest_file.gem_path = (path.relative? ?
+ @manifest_file.root.join(path) : path).expand_path
+ end
+
+ def bin_path(path)
+ path = Pathname.new(path)
+ @manifest_file.bindir = (path.relative? ?
+ @manifest_file.root.join(path) : path).expand_path
+ end
+
+ def disable_rubygems
+ @manifest_file.rubygems = false
+ end
+
+ def disable_system_gems
+ @manifest_file.system_gems = false
+ end
+
+ def source(source)
+ source = Source.new(source)
+ unless @manifest_file.sources.include?(source)
+ @manifest_file.add_source(source)
+ end
+ end
+
+ def clear_sources
+ @manifest_file.clear_sources
+ end
+
+ def gem(name, *args)
+ options = args.last.is_a?(Hash) ? args.pop : {}
+ version = args.last
+
+ @manifest_file.dependencies << Dependency.new(name, options.merge(:version => version))
+ end
+ end
+end
diff --git a/lib/bundler/manifest.rb b/lib/bundler/manifest.rb
index 356089e0d8..fb4f32023e 100644
--- a/lib/bundler/manifest.rb
+++ b/lib/bundler/manifest.rb
@@ -4,9 +4,10 @@ module Bundler
class VersionConflict < StandardError; end
class Manifest
- attr_reader :sources, :dependencies, :path
+ attr_reader :filename, :sources, :dependencies, :path
- def initialize(sources, dependencies, bindir, path, rubygems, system_gems)
+ def initialize(filename, sources, dependencies, bindir, path, rubygems, system_gems)
+ @filename = filename
@sources = sources
@dependencies = dependencies
@bindir = bindir
@@ -25,18 +26,17 @@ module Bundler
end
def activate(environment = "default")
- require repository.path.join("environments", "#{environment}.rb")
+ require repository.path.join("environments", "#{environment}")
end
def require_all
dependencies.each do |dep|
- dep.require_as.each {|file| require file }
+ dep.require
end
end
def gems_for(environment = nil)
deps = dependencies
- deps = deps.select { |d| d.in?(environment) } if environment
deps = deps.map { |d| d.to_gem_dependency }
Resolver.resolve(deps, repository.source_index)
end
@@ -94,7 +94,7 @@ module Bundler
def create_environment_files(path)
FileUtils.mkdir_p(path)
- environments.each do |environment|
+ ["default"].each do |environment|
specs = gems_for(environment)
files = spec_files_for_specs(specs, path)
load_paths = load_paths_for_specs(specs)
diff --git a/lib/bundler/manifest_file.rb b/lib/bundler/manifest_file.rb
index 7502c912e0..581ff08f19 100644
--- a/lib/bundler/manifest_file.rb
+++ b/lib/bundler/manifest_file.rb
@@ -55,7 +55,7 @@ module Bundler
def load_manifest
ManifestBuilder.load(self, filename)
- Manifest.new(sources, dependencies, bindir, gem_path, rubygems, system_gems)
+ Manifest.new(filename, sources, dependencies, bindir, gem_path, rubygems, system_gems)
end
def gem_path
diff --git a/lib/bundler/runtime.rb b/lib/bundler/runtime.rb
index 3cc87826f5..3af2f5cdf8 100644
--- a/lib/bundler/runtime.rb
+++ b/lib/bundler/runtime.rb
@@ -1,61 +1,46 @@
+require "bundler/dependency"
+
module Bundler
class ManifestFileNotFound < StandardError; end
- class ManifestBuilder
- def self.build(manifest_file, string)
- builder = new(manifest_file)
- builder.instance_eval(string)
- builder
- end
+ def self.require(environment = nil)
+ ManifestBuilder.run(@gemfile, environment || :default)
+ end
- def self.load(manifest_file, filename)
- unless File.exist?(filename)
- raise ManifestFileNotFound, "#{filename.inspect} does not exist"
+ class ManifestBuilder
+ def self.run(gemfile, environment)
+ unless File.exist?(gemfile)
+ raise ManifestFileNotFound, "#{gemfile.inspect} does not exist"
end
- string = File.read(filename)
- build(manifest_file, string)
- end
- def initialize(manifest_file)
- @manifest_file = manifest_file
+ builder = new(environment)
+ builder.instance_eval(File.read(gemfile))
+ builder
end
- def bundle_path(path)
- path = Pathname.new(path)
- @manifest_file.gem_path = (path.relative? ?
- @manifest_file.root.join(path) : path).expand_path
+ def initialize(environment)
+ @environment = environment
end
- def bin_path(path)
- path = Pathname.new(path)
- @manifest_file.bindir = (path.relative? ?
- @manifest_file.root.join(path) : path).expand_path
- end
+ def bundle_path(*) ; end
- def disable_rubygems
- @manifest_file.rubygems = false
- end
+ def bin_path(*) ; end
- def disable_system_gems
- @manifest_file.system_gems = false
- end
+ def disable_rubygems(*) ; end
- def source(source)
- source = Source.new(source)
- unless @manifest_file.sources.include?(source)
- @manifest_file.add_source(source)
- end
- end
+ def disable_system_gems(*) ; end
- def clear_sources
- @manifest_file.clear_sources
- end
+ def source(*) ; end
+
+ def clear_sources(*) ; end
- def gem(name, *args)
+ def gem(name, *args, &blk)
options = args.last.is_a?(Hash) ? args.pop : {}
version = args.last
- @manifest_file.dependencies << Dependency.new(name, options.merge(:version => version))
+ dep = Dependency.new(name, options.merge(:version => version), &blk)
+ dep.require(@environment)
+ dep
end
end
-end
+end \ No newline at end of file
diff --git a/lib/bundler/templates/environment.rb b/lib/bundler/templates/environment.rb
index fc6c4f37e6..6aeec99267 100644
--- a/lib/bundler/templates/environment.rb
+++ b/lib/bundler/templates/environment.rb
@@ -14,6 +14,8 @@ require "rubygems"
module Bundler
+ @gemfile = "<%= @filename %>"
+
@bundled_specs = {}
<% spec_files.each do |name, path| %>
@bundled_specs["<%= name %>"] = eval(File.read("<%= path %>"))
@@ -79,4 +81,6 @@ module Gem
class SystemExitException < SystemExit; end
end
-<% end %> \ No newline at end of file
+<% end %>
+
+require "bundler/runtime" \ No newline at end of file
diff --git a/spec/bundler/cli_spec.rb b/spec/bundler/cli_spec.rb
index 3ebdd68ad1..16184d2740 100644
--- a/spec/bundler/cli_spec.rb
+++ b/spec/bundler/cli_spec.rb
@@ -27,14 +27,8 @@ describe "Bundler::CLI" do
tmp_file('vendor', 'gems', 'environments', 'default.rb').should have_load_paths(tmp_file("vendor", "gems"),
"extlib-0.9.12" => %w(lib),
"rake-0.8.7" => %w(bin lib),
- "very-simple-1.0" => %w(bin lib)
- )
-
- tmp_file('vendor', 'gems', 'environments', 'web.rb').should have_load_paths(tmp_file("vendor", "gems"),
- "extlib-0.9.12" => %w(lib),
- "rake-0.8.7" => %w(bin lib),
- "rack-0.9.1" => %w(bin lib),
- "very-simple-1.0" => %w(bin lib)
+ "very-simple-1.0" => %w(bin lib),
+ "rack-0.9.1" => %w(bin lib)
)
end
@@ -44,7 +38,7 @@ describe "Bundler::CLI" do
out.should include(tmp_file("vendor", "gems", "gems", "rake-0.8.7", "bin").to_s)
out.should include(tmp_file("vendor", "gems", "gems", "extlib-0.9.12", "lib").to_s)
out.should include(tmp_file("vendor", "gems", "gems", "very-simple-1.0", "lib").to_s)
- out.should_not include(tmp_file("vendor", "gems", "gems", "rack-0.9.1").to_s)
+ out.should include(tmp_file("vendor", "gems", "gems", "rack-0.9.1").to_s)
end
it "maintains the correct environment when shelling out" do
diff --git a/spec/bundler/manifest_spec.rb b/spec/bundler/manifest_spec.rb
index b5e47570f3..cd085fe285 100644
--- a/spec/bundler/manifest_spec.rb
+++ b/spec/bundler/manifest_spec.rb
@@ -136,48 +136,13 @@ describe "Bundler::Manifest" do
describe "runtime" do
- it "makes gems available via Manifest#activate" do
- m = build_manifest <<-Gemfile
- clear_sources
- source "file://#{gem_repo1}"
- source "file://#{gem_repo2}"
- gem "very-simple", "1.0.0"
- Gemfile
-
- m.install
- m.manifest.activate
-
- $:.any? do |p|
- File.expand_path(p) == File.expand_path(tmp_gem_path("gems", "very-simple-1.0", "lib"))
- end.should be_true
- end
-
- it "makes gems available" do
- m = build_manifest <<-Gemfile
- clear_sources
- source "file://#{gem_repo1}"
- source "file://#{gem_repo2}"
- gem "very-simple", "1.0.0"
- Gemfile
-
- m.install
- m.manifest.activate
- m.manifest.require_all
-
- $".any? do |f|
- File.expand_path(f) ==
- File.expand_path(tmp_gem_path("gems", "very-simple-1.0", "lib", "very-simple.rb"))
- end
- end
-
it "is able to work system gems" do
- m = build_manifest <<-Gemfile
+ install_manifest <<-Gemfile
clear_sources
source "file://#{gem_repo1}"
gem "very-simple"
Gemfile
- m.install
out = run_in_context "require 'rake' ; puts Rake"
out.should == "Rake"
end
@@ -243,27 +208,6 @@ describe "Bundler::Manifest" do
@manifest.environments.should == ["testing", "default"]
end
- it "knows what gems are in an environment" do
- @manifest.gems_for("testing").should match_gems(
- "very-simple" => ["1.0"], "rack" => ["1.0.0"])
-
- @manifest.gems_for("production").should match_gems(
- "rack" => ["1.0.0"])
- end
-
- it "can create load path files for each environment" do
- tmp_gem_path('environments', 'testing.rb').should have_load_paths(tmp_gem_path,
- "very-simple-1.0" => %w(bin lib),
- "rack-1.0.0" => %w(bin lib)
- )
-
- tmp_gem_path('environments', 'default.rb').should have_load_paths(tmp_gem_path,
- "rack-1.0.0" => %w(bin lib)
- )
-
- File.exist?(tmp_gem_path('environments', "production.rb")).should be_false
- end
-
it "requires the Rubygems library" do
out = run_in_context "puts 'Gem'"
out.should == "Gem"
@@ -275,7 +219,7 @@ describe "Bundler::Manifest" do
end
it "Gem.loaded_specs has the gems that are included in the testing environment" do
- env = tmp_gem_path('environments', 'testing.rb')
+ env = tmp_gem_path('environments', 'default.rb')
out = run_in_context env, %'puts Gem.loaded_specs.map{|k,v|"\#{k} - \#{v.version}"}'
out.should include("rack - 1.0.0")
out.should include("very-simple - 1.0")
diff --git a/spec/bundler/runtime_spec.rb b/spec/bundler/runtime_spec.rb
new file mode 100644
index 0000000000..4112582068
--- /dev/null
+++ b/spec/bundler/runtime_spec.rb
@@ -0,0 +1,109 @@
+require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
+
+describe "Bundler runtime" do
+
+ describe "basic runtime options" do
+ it "requires files for all gems" do
+ install_manifest <<-Gemfile
+ clear_sources
+ source "file://#{gem_repo1}"
+ gem "very-simple"
+ Gemfile
+
+ out = run_in_context <<-RUBY
+ Bundler.require
+ puts VerySimpleForTests
+ RUBY
+
+ out.should == "VerySimpleForTests"
+ end
+
+ it "correctly requires the specified files" do
+ install_manifest <<-Gemfile
+ clear_sources
+ source "file://#{gem_repo2}"
+ gem "actionpack", :require_as => %w(action_controller action_view)
+ Gemfile
+
+ out = run_in_context <<-RUBY
+ Bundler.require
+ puts "\#{ActionController} -- \#{ActionView}"
+ RUBY
+
+ out.should == "ActionController -- ActionView"
+ end
+
+ it "executes blocks at require time" do
+ install_manifest <<-Gemfile
+ clear_sources
+ source "file://#{gem_repo1}"
+ gem "very-simple" do
+ puts "Requiring"
+ end
+ Gemfile
+
+ out = run_in_context <<-RUBY
+ puts "Before"
+ Bundler.require
+ puts "After"
+ RUBY
+
+ out.should == "Before\nRequiring\nAfter"
+ end
+ end
+
+ describe "with environments" do
+ it "requires specific environments" do
+ install_manifest <<-Gemfile
+ clear_sources
+ source "file://#{gem_repo1}"
+ gem "very-simple"
+ Gemfile
+
+ out = run_in_context <<-RUBY
+ Bundler.require :test
+ puts VerySimpleForTests
+ RUBY
+
+ out.should == "VerySimpleForTests"
+ end
+
+ it "only requires gems in the environments they are exclusive to" do
+ install_manifest <<-Gemfile
+ clear_sources
+ source "file://#{gem_repo1}"
+ gem "very-simple", :only => :bar
+ Gemfile
+
+ out = run_in_context <<-RUBY
+ Bundler.require ; puts defined?(VerySimpleForTests)
+ Bundler.require :foo ; puts defined?(VerySimpleForTests)
+ Bundler.require :bar ; puts defined?(VerySimpleForTests)
+ RUBY
+
+ out.should == "nil\nnil\nconstant"
+ end
+
+ it "does not require gems in environments that they are excluded from" do
+ install_manifest <<-Gemfile
+ clear_sources
+ source "file://#{gem_repo1}"
+ gem "very-simple", :except => :bar
+ Gemfile
+
+ out = run_in_context <<-RUBY
+ Bundler.require :bar ; puts defined?(VerySimpleForTests)
+ Bundler.require :foo ; puts defined?(VerySimpleForTests)
+ RUBY
+
+ out.should == "nil\nconstant"
+
+ out = run_in_context <<-RUBY
+ Bundler.require ; puts defined?(VerySimpleForTests)
+ RUBY
+
+ out.should == "constant"
+ end
+ end
+
+end \ No newline at end of file
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index fe2bb68b12..29dd00adc8 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -72,7 +72,8 @@ module Spec
def run_in_context(*args)
cmd = args.pop.gsub(/(?=")/, "\\")
env = args.pop || tmp_file("vendor", "gems", "environments", "default")
- %x{#{Gem.ruby} -r #{env} -e "#{cmd}"}.strip
+ lib = File.join(File.dirname(__FILE__), '..', 'lib')
+ %x{#{Gem.ruby} -I#{lib} -r #{env} -e "#{cmd}"}.strip
end
def gem_command(command, args = "")
@@ -102,6 +103,12 @@ module Spec
end
end
+ def install_manifest(*args)
+ m = build_manifest(*args)
+ m.install
+ m
+ end
+
def reset!
tmp_dir.rmtree if tmp_dir.exist?
tmp_dir.mkdir