Skip to content
This repository has been archived by the owner on Apr 14, 2021. It is now read-only.

Commit

Permalink
Add an option to cache gems
Browse files Browse the repository at this point in the history
  • Loading branch information
Carl Lerche committed Sep 22, 2009
1 parent 7b472f1 commit 58f2a94
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 12 deletions.
17 changes: 12 additions & 5 deletions lib/bundler/cli.rb
Expand Up @@ -6,19 +6,22 @@ def self.run(command, options = {})
new(options).run(command)
rescue DefaultManifestNotFound => e
Bundler.logger.error "Could not find a Gemfile to use"
exit 2
exit 3
rescue InvalidEnvironmentName => e
Bundler.logger.error "Gemfile error: #{e.message}"
exit
exit 4
rescue InvalidRepository => e
Bundler.logger.error e.message
exit 1
exit 5
rescue VersionConflict => e
Bundler.logger.error e.message
exit 1
exit 6
rescue GemNotFound => e
Bundler.logger.error e.message
exit 1
exit 7
rescue InvalidCacheArgument => e
Bundler.logger.error e.message
exit 8
end

def initialize(options)
Expand All @@ -30,6 +33,10 @@ def bundle
@manifest.install(@options)
end

def cache
@manifest.cache(@options)
end

def exec
@manifest.setup_environment
# w0t?
Expand Down
10 changes: 9 additions & 1 deletion lib/bundler/commands/bundle_command.rb
Expand Up @@ -14,6 +14,10 @@ def initialize
add_option('--cached', "Only use cached gems when expanding the bundle") do
options[:cached] = true
end

add_option('--cache GEM', "Specify a path to a .gem file to add to the bundled gem cache") do |gem, options|
options[:cache] = gem
end
end

def usage
Expand All @@ -29,7 +33,11 @@ def description # :nodoc:
def execute
# Prevent the bundler from getting required unless it is actually being used
require 'bundler'
Bundler::CLI.run(:bundle, options)
if options[:cache]
Bundler::CLI.run(:cache, options)
else
Bundler::CLI.run(:bundle, options)
end
end

end
31 changes: 31 additions & 0 deletions lib/bundler/environment.rb
Expand Up @@ -2,6 +2,7 @@

module Bundler
class DefaultManifestNotFound < StandardError; end
class InvalidCacheArgument < StandardError; end

class Environment
attr_reader :filename, :dependencies
Expand Down Expand Up @@ -58,6 +59,36 @@ def install(options = {})
Bundler.logger.info "Done."
end

def cache(options = {})
gemfile = options[:cache]

if File.extname(gemfile) == ".gem"
if !File.exist?(gemfile)
raise InvalidCacheArgument, "'#{gemfile}' does not exist."
end
repository.cache(gemfile)
elsif File.directory?(gemfile) || gemfile.include?('/')
if !File.directory?(gemfile)
raise InvalidCacheArgument, "'#{gemfile}' does not exist."
end
gemfiles = Dir["#{gemfile}/*.gem"]
if gemfiles.empty?
raise InvalidCacheArgument, "'#{gemfile}' contains no gemfiles"
end
repository.cache(*gemfiles)
else
local = Gem::SourceIndex.from_installed_gems.find_name(gemfile).last

if !local
raise InvalidCacheArgument, "w0t? '#{gemfile}' means nothing to me."
end

gemfile = Pathname.new(local.loaded_from)
gemfile = gemfile.dirname.join('..', 'cache', "#{local.full_name}.gem").expand_path
repository.cache(File.join(Gem.dir, "cache", "#{local.full_name}.gem"))
end
end

def setup_environment
unless system_gems
ENV["GEM_HOME"] = gem_path
Expand Down
8 changes: 8 additions & 0 deletions lib/bundler/repository.rb
Expand Up @@ -38,6 +38,14 @@ def install(dependencies, sources, options = {})
configure(valid, options)
end

def cache(*gemfiles)
FileUtils.mkdir_p(@path.join("cache"))
gemfiles.each do |gemfile|
Bundler.logger.info "Caching: #{File.basename(gemfile)}"
FileUtils.cp(gemfile, @path.join("cache"))
end
end

def gems
source_index.gems.values
end
Expand Down
79 changes: 79 additions & 0 deletions spec/bundler/cli_spec.rb
Expand Up @@ -260,4 +260,83 @@
end
end
end

describe "caching gems to the bundle" do
before(:each) do
build_manifest <<-Gemfile
clear_sources
Gemfile
end

it "adds a single gem to the cache" do
build_manifest <<-Gemfile
clear_sources
gem "rack"
Gemfile

Dir.chdir(bundled_app) do
out = gem_command :bundle, "--cache #{gem_repo1('gems', 'rack-0.9.1.gem')}"
gem_command :bundle, "--cached"
out.should include("Caching: rack-0.9.1.gem")
tmp_gem_path.should include_cached_gems("rack-0.9.1")
tmp_gem_path.should include_installed_gems("rack-0.9.1")
end
end

it "adds a gem directory to the cache" do
build_manifest <<-Gemfile
clear_sources
gem "rack"
gem "abstract"
Gemfile

Dir.chdir(bundled_app) do
out = gem_command :bundle, "--cache #{gem_repo1('gems')}"
gem_command :bundle, "--cached"

%w(abstract-1.0.0 actionmailer-2.3.2 activerecord-2.3.2 addressable-2.0.2 builder-2.1.2).each do |gemfile|
out.should include("Caching: #{gemfile}.gem")
end
tmp_gem_path.should include_cached_gems("rack-0.9.1", "abstract-1.0.0")
tmp_gem_path.should have_installed_gems("rack-0.9.1", "abstract-1.0.0")
end
end

it "adds a gem from the local repository" do
build_manifest <<-Gemfile
clear_sources
gem "rspec"
disable_system_gems
Gemfile

Dir.chdir(bundled_app) do
out = gem_command :bundle, "--cache rspec"
gem_command :bundle, "--cached"
out = run_in_context "require 'spec' ; puts Spec"
out.should == "Spec"
end
end

it "outputs an error when trying to cache a gem that doesn't exist." do
Dir.chdir(bundled_app) do
out = gem_command :bundle, "--cache foo/bar.gem"
out.should == "'foo/bar.gem' does not exist."
end
end

it "outputs an error when trying to cache a directory that doesn't exist." do
Dir.chdir(bundled_app) do
out = gem_command :bundle, "--cache foo/bar"
out.should == "'foo/bar' does not exist."
end
end

it "outputs an error when trying to cache a directory with no gems." do
Dir.chdir(bundled_app) do
FileUtils.mkdir_p("foo/bar")
out = gem_command :bundle, "--cache foo/bar"
out.should == "'foo/bar' contains no gemfiles"
end
end
end
end
12 changes: 6 additions & 6 deletions spec/support/path_utils.rb
Expand Up @@ -40,16 +40,16 @@ def fixture_dir
root.join("spec", "fixtures")
end

def gem_repo1
fixture_dir.join("repository1").expand_path
def gem_repo1(*path)
fixture_dir.join("repository1", *path).expand_path
end

def gem_repo2
fixture_dir.join("repository2").expand_path
def gem_repo2(*path)
fixture_dir.join("repository2", *path).expand_path
end

def gem_repo3
fixture_dir.join("repository3").expand_path
def gem_repo3(*path)
fixture_dir.join("repository3", *path).expand_path
end

def fixture(gem_name)
Expand Down

0 comments on commit 58f2a94

Please sign in to comment.