diff options
author | Yehuda Katz + Carl Lerche <ykatz+clerche@engineyard.com> | 2009-07-29 17:29:34 -0700 |
---|---|---|
committer | Yehuda Katz + Carl Lerche <ykatz+clerche@engineyard.com> | 2009-07-29 17:29:34 -0700 |
commit | 59d238b4f5063749b4f7d2aa425074897ff27829 (patch) | |
tree | 5e8ac2ed0b74a113c2cc6572c4deed404534b7d3 | |
parent | 4eaf065c6944ba385cbd57a874c3c0767bb269a4 (diff) | |
download | bundler-59d238b4f5063749b4f7d2aa425074897ff27829.tar.gz |
Switch from gem_bundler to gem bundle and gem exec
-rw-r--r-- | README.markdown | 156 | ||||
-rw-r--r-- | README.rdoc | 168 | ||||
-rw-r--r-- | Rakefile | 4 | ||||
-rwxr-xr-x | bin/gem_bundler | 4 | ||||
-rw-r--r-- | lib/bundler/cli.rb | 49 | ||||
-rw-r--r-- | lib/bundler/commands/bundle_command.rb | 29 | ||||
-rw-r--r-- | lib/bundler/commands/exec_command.rb | 29 | ||||
-rw-r--r-- | lib/rubygems_plugin.rb | 7 | ||||
-rw-r--r-- | spec/bundler/cli_spec.rb | 36 | ||||
-rw-r--r-- | spec/bundler/manifest_spec.rb | 2 | ||||
-rw-r--r-- | spec/spec_helper.rb | 6 |
11 files changed, 261 insertions, 229 deletions
diff --git a/README.markdown b/README.markdown new file mode 100644 index 0000000000..b9178d5a5d --- /dev/null +++ b/README.markdown @@ -0,0 +1,156 @@ +## Bundler : A gem to bundle gems + + Github: http://github.com/wycats/bundler + Mailing list: http://groups.google.com/group/ruby-bundler + +## 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/environments/default.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', 'environments', 'default')) + +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. + +## 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/README.rdoc b/README.rdoc deleted file mode 100644 index fe53386994..0000000000 --- a/README.rdoc +++ /dev/null @@ -1,168 +0,0 @@ -== Bundler : A gem to bundle gems - - Github: http://github.com/wycats/bundler - -== 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_bundler'. 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 not require rubygems automatically (bundled gems are - # available without rubygems), but rubygems can still be required and it - # behaves normally. - disable_rubygems - -=== Running Bundler - -Once a manifest file has been created, the only thing that needs to be done -is to run the "gem_bundler" 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_bundler" again to -get the changes installed. - -=== 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_bundler command. For example: - - gem_bundler ruby my_ruby_script.rb - -Yet another way is to manually require the environment file first. This is -located in [bundle_path]/environments/[environment_name].rb. The default -environment file is default.rb. For example: - - ruby -r vendor/gems/environments/default.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" - - # Requiring rubygems seems to be the safest way to go currently. - require_rubygems - - # Optionally, you can disable system gems all together and only - # use bundled gems. - disable_system_gems - -I would suggest to require_rubygems as of now. - -* Run gem_bundler - -* You can now use rails if you append "gem_bundler" 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', 'environments', 'default')) - -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. - -Bundler will mock 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. Otherwise, add "require_rubygems" to your Gemfile. - -== Environments - -More to come... - -== Reporting bugs - -Please report all bugs on the github issue tracker for the project located -at: - - http://github.com/wycats/bundler/issues/ - -== Known issues - -* Running ruby code with 'gem_bundler ruby my_ruby_script.rb' will require - the entire Bundler source code which also requires rubygems.
\ No newline at end of file @@ -16,10 +16,8 @@ spec = Gem::Specification.new do |s| s.has_rdoc = true s.extra_rdoc_files = ["README.rdoc", "LICENSE"] - s.bindir = "bin" - s.executables = %w( gem_bundler ) s.require_path = 'lib' - s.files = %w(LICENSE README.rdoc Rakefile) + Dir.glob("{bin,lib,spec}/**/*") + s.files = %w(LICENSE README.rdoc Rakefile) + Dir.glob("lib/**/*") end task :default => :spec diff --git a/bin/gem_bundler b/bin/gem_bundler deleted file mode 100755 index f4e5777423..0000000000 --- a/bin/gem_bundler +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env ruby - -require "bundler" -Bundler::CLI.run diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index 092a63d80f..2ff3847289 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -2,24 +2,29 @@ require "optparse" module Bundler class CLI - def self.run(args = ARGV) - new(args).run + def self.run(command, options = {}) + new(options).run(command) end - def initialize(args) - @args = args + def initialize(options) + @options = options + @manifest_file = Bundler::ManifestFile.load(@options[:manifest]) end - def run - parser.parse!(@args) + def bundle + @manifest_file.install(@options[:update]) + end + + def exec + @manifest_file.setup_environment + # w0t? + super(*@options[:args]) + end + + def run(command) + + send(command) - manifest_file = Bundler::ManifestFile.load(@manifest) - if @args.empty? - manifest_file.install(@update) - else - manifest_file.setup_environment - exec(*@args) - end rescue DefaultManifestNotFound => e Bundler.logger.error "Could not find a Gemfile to use" exit 2 @@ -34,23 +39,5 @@ module Bundler exit end - def parser - @parser ||= OptionParser.new do |op| - op.banner = "Usage: gem_bundler [OPTIONS] [PATH]" - - op.on("-m", "--manifest MANIFEST") do |manifest| - @manifest = Pathname.new(manifest) - end - - op.on("-u", "--update", "Force a remote check for newer gems") do - @update = true - end - - op.on_tail("-h", "--help", "Show this message") do - puts op - exit - end - end - end end end diff --git a/lib/bundler/commands/bundle_command.rb b/lib/bundler/commands/bundle_command.rb new file mode 100644 index 0000000000..cbfd9cf99e --- /dev/null +++ b/lib/bundler/commands/bundle_command.rb @@ -0,0 +1,29 @@ +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] = Pathname.new(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 + Bundler::CLI.run(:bundle, options) + end + +end
\ No newline at end of file diff --git a/lib/bundler/commands/exec_command.rb b/lib/bundler/commands/exec_command.rb new file mode 100644 index 0000000000..433b54a1ff --- /dev/null +++ b/lib/bundler/commands/exec_command.rb @@ -0,0 +1,29 @@ +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] = Pathname.new(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 + Bundler::CLI.run(:exec, options) + end + +end
\ No newline at end of file diff --git a/lib/rubygems_plugin.rb b/lib/rubygems_plugin.rb new file mode 100644 index 0000000000..09aa2b8512 --- /dev/null +++ b/lib/rubygems_plugin.rb @@ -0,0 +1,7 @@ +require 'rubygems/command_manager' +require 'bundler' +require 'bundler/commands/bundle_command' +require 'bundler/commands/exec_command' + +Gem::CommandManager.instance.register_command :bundle +Gem::CommandManager.instance.register_command :exec
\ No newline at end of file diff --git a/spec/bundler/cli_spec.rb b/spec/bundler/cli_spec.rb index 4e2add24a6..25dc6646d2 100644 --- a/spec/bundler/cli_spec.rb +++ b/spec/bundler/cli_spec.rb @@ -12,11 +12,8 @@ describe "Bundler::CLI" do gem "rack", :only => :web Gemfile - lib = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib')) - bin = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin', 'gem_bundler')) - Dir.chdir(tmp_dir) do - @output = `#{Gem.ruby} -I #{lib} #{bin}` + @output = gem_command :bundle end end @@ -42,7 +39,7 @@ describe "Bundler::CLI" do end it "creates an executable for rake in ./bin" do - out = `#{tmp_file('bin', 'rake')} -e 'puts $:'` + out = run_in_context "puts $:" out.should include(tmp_file("vendor", "gems", "gems", "rake-0.8.7", "lib").to_s) 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) @@ -98,7 +95,7 @@ describe "Bundler::CLI" do Gemfile Dir.chdir(tmp_file) - Bundler::CLI.run(["-m", tmp_file('manifest.rb').to_s]) + gem_command :bundle, "-m #{tmp_file('manifest.rb')}" tmp_file("gems").should have_cached_gems("rake-0.8.7") end @@ -111,7 +108,7 @@ describe "Bundler::CLI" do Gemfile Dir.chdir(tmp_file) - Bundler::CLI.run(["-m", tmp_file('config', 'manifest.rb').to_s]) + gem_command :bundle, "-m #{tmp_file('config', 'manifest.rb')}" tmp_file("gems").should have_cached_gems("rake-0.8.7") end end @@ -128,32 +125,29 @@ describe "Bundler::CLI" do disable_rubygems Gemfile - lib = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib')) - bin = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin', 'gem_bundler')) - Dir.chdir(tmp_dir) do - @output = `#{Gem.ruby} -I #{lib} #{bin}` + @output = gem_command :bundle end end it "does not load rubygems when required" do - out = `#{tmp_file('bin', 'rake')} -e 'require "rubygems" ; puts Gem.respond_to?(:sources)'` - out.should =~ /false/ + out = run_in_context 'require "rubygems" ; puts Gem.respond_to?(:sources)' + out.should == "false" end it "does not blow up if #gem is used" do - out = `#{tmp_file('bin', 'rake')} -e 'gem("merb-core") ; puts "Win!"'` - out.should =~ /Win!/ + out = run_in_context 'gem("merb-core") ; puts "Win!"' + out.should == "Win!" end it "does not blow up if Gem errors are referred to" do - out = `#{tmp_file('bin', 'rake')} -e 'Gem::LoadError ; Gem::Exception ; puts "Win!"'` - out.should =~ /Win!/ + out = run_in_context 'Gem::LoadError ; Gem::Exception ; puts "Win!"' + out.should == "Win!" end it "stubs out Gem.ruby" do - out = `#{tmp_file("bin", "rake")} -e 'puts Gem.ruby'` - out.should == "#{Gem.ruby}\n" + out = run_in_context "puts Gem.ruby" + out.should == Gem.ruby end end @@ -174,10 +168,8 @@ describe "Bundler::CLI" do gem "rack" Gemfile - lib = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib')) - bin = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin', 'gem_bundler')) Dir.chdir(tmp_dir) do - `#{Gem.ruby} -I #{lib} #{bin} --update` + gem_command :bundle, "--update" end tmp_file("vendor", "gems").should have_cached_gems("rack-1.0.0") tmp_file("vendor", "gems").should have_installed_gems("rack-1.0.0") diff --git a/spec/bundler/manifest_spec.rb b/spec/bundler/manifest_spec.rb index c2bf8977f4..b843e5262e 100644 --- a/spec/bundler/manifest_spec.rb +++ b/spec/bundler/manifest_spec.rb @@ -132,7 +132,7 @@ describe "Bundler::Manifest" do Dir.chdir(tmp_dir) lambda do - Bundler::CLI.run([]) + Bundler::CLI.run(:bundle) end.should raise_error(SystemExit) @log_output.should have_log_message(/rails \(= 2\.3\.2.*rack \(= 0\.9\.1.*active_support \(= 2\.0/m) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 5f771d6f6c..a4cd2df389 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -74,6 +74,12 @@ module Spec %x{#{Gem.ruby} -r #{env} -e "#{cmd}"}.strip end + def gem_command(command, args = "") + args = args.gsub(/(?=")/, "\\") + lib = File.join(File.dirname(__FILE__), '..', 'lib') + %x{#{Gem.ruby} -I#{lib} -rubygems -S gem #{command} #{args}} + end + def build_manifest_file(*args) path = tmp_file("Gemfile") path = args.shift if args.first.is_a?(Pathname) |