diff options
author | Yehuda Katz + Carl Lerche <ykatz+clerche@engineyard.com> | 2009-08-17 17:20:25 -0700 |
---|---|---|
committer | Yehuda Katz + Carl Lerche <ykatz+clerche@engineyard.com> | 2009-08-17 17:20:25 -0700 |
commit | 0c9043049ff3d9554dd0736c518bf22f8a5ee00d (patch) | |
tree | dd58674b438017ab93d978a3ccefc6d6c8345e42 | |
parent | 4d1aa38bb72be5b3b225255b346883190cb92b26 (diff) | |
download | bundler-0c9043049ff3d9554dd0736c518bf22f8a5ee00d.tar.gz |
Implemented Bundler.require for runtime requiring
-rw-r--r-- | lib/bundler.rb | 2 | ||||
-rw-r--r-- | lib/bundler/dependency.rb | 13 | ||||
-rw-r--r-- | lib/bundler/dsl.rb | 61 | ||||
-rw-r--r-- | lib/bundler/manifest.rb | 12 | ||||
-rw-r--r-- | lib/bundler/manifest_file.rb | 2 | ||||
-rw-r--r-- | lib/bundler/runtime.rb | 67 | ||||
-rw-r--r-- | lib/bundler/templates/environment.rb | 6 | ||||
-rw-r--r-- | spec/bundler/cli_spec.rb | 12 | ||||
-rw-r--r-- | spec/bundler/manifest_spec.rb | 60 | ||||
-rw-r--r-- | spec/bundler/runtime_spec.rb | 109 | ||||
-rw-r--r-- | spec/spec_helper.rb | 9 |
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 |