class Bundler::Repository
def add_spec(spec)
def add_spec(spec) destination = path.join('specifications') destination.mkdir unless destination.exist? File.open(destination.join("#{spec.full_name}.gemspec"), 'w') do |f| f.puts spec.to_ruby end end
def cache(*gemfiles)
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 cleanup(valid, options)
def cleanup(valid, options) to_delete = gems to_delete.delete_if do |spec| valid.any? { |other| spec.name == other.name && spec.version == other.version } end valid_executables = valid.map { |s| s.executables }.flatten.compact to_delete.each do |spec| Bundler.logger.info "Deleting gem: #{spec.name} (#{spec.version})" FileUtils.rm_rf(@path.join("specifications", "#{spec.full_name}.gemspec")) FileUtils.rm_rf(@path.join("gems", spec.full_name)) # Cleanup the bin directory spec.executables.each do |bin| next if valid_executables.include?(bin) Bundler.logger.info "Deleting bin file: #{bin}" FileUtils.rm_rf(@bindir.join(bin)) end end end
def configure(specs, options)
def configure(specs, options) generate_environment(specs, options) end
def do_install(bundle, options)
def do_install(bundle, options) bundle.each do |spec| next if options[:no_bundle].include?(spec.name) spec.loaded_from = @path.join("specifications", "#{spec.full_name}.gemspec") # Do nothing if the gem is already expanded next if @path.join("gems", spec.full_name).directory? case spec.source when GemSource, GemDirectorySource, SystemGemSource expand_gemfile(spec, options) else expand_vendored_gem(spec, options) end end end
def download(bundle, options)
def download(bundle, options) bundle.sort_by {|s| s.full_name.downcase }.each do |spec| next if options[:no_bundle].include?(spec.name) spec.source.download(spec) end end
def download_path_for(type)
def download_path_for(type) @repos[type].download_path_for end
def expand(options)
def expand(options) each_repo do |repo| repo.expand(options) end end
def expand_gemfile(spec, options)
def expand_gemfile(spec, options) Bundler.logger.info "Installing #{spec.name} (#{spec.version})" gemfile = @path.join("cache", "#{spec.full_name}.gem").to_s if build_args = options[:build_options] && options[:build_options][spec.name] Gem::Command.build_args = build_args.map {|k,v| "--with-#{k}=#{v}"} end installer = Gem::Installer.new(gemfile, options.merge( :install_dir => @path, :ignore_dependencies => true, :env_shebang => true, :wrappers => true, :bin_dir => @bindir )) installer.install ensure Gem::Command.build_args = [] end
def expand_vendored_gem(spec, options)
def expand_vendored_gem(spec, options) add_spec(spec) FileUtils.mkdir_p(@path.join("gems")) File.symlink(spec.location, @path.join("gems", spec.full_name)) end
def gems
def gems source_index.gems.values end
def generate_bins(bundle, options)
def generate_bins(bundle, options) bundle.each do |spec| next if options[:no_bundle].include?(spec.name) # HAX -- Generate the bin bin_dir = @bindir path = @path installer = Gem::Installer.allocate installer.instance_eval do @spec = spec @bin_dir = bin_dir @gem_dir = path.join("gems", "#{spec.full_name}") @gem_home = path @wrappers = true @format_executable = false @env_shebang = false end installer.generate_bin end end
def generate_environment(specs, options)
def generate_environment(specs, options) FileUtils.mkdir_p(path) load_paths = load_paths_for_specs(specs, options) bindir = @bindir.relative_path_from(path).to_s filename = options[:manifest].relative_path_from(path).to_s File.open(path.join("environment.rb"), "w") do |file| template = File.read(File.join(File.dirname(__FILE__), "templates", "environment.erb")) erb = ERB.new(template, nil, '-') file.puts erb.result(binding) end end
def initialize(path, bindir)
def initialize(path, bindir) FileUtils.mkdir_p(path) @path = Pathname.new(path) @bindir = Pathname.new(bindir) @cache = GemDirectorySource.new(:location => @path.join("cache")) end
def install(dependencies, sources, options = {})
def install(dependencies, sources, options = {}) # TODO: clean this up sources.each do |s| s.repository = self s.local = options[:cached] end source_requirements = {} options[:no_bundle].each do |name| source_requirements[name] = SystemGemSource.instance end # Check to see whether the existing cache meets all the requirements begin valid = Resolver.resolve(dependencies, [source_index], source_requirements) rescue Bundler::GemNotFound end sources = only_local(sources) if options[:cached] # Check the remote sources if the existing cache does not meet the requirements # or the user passed --update if options[:update] || !valid Bundler.logger.info "Calculating dependencies..." bundle = Resolver.resolve(dependencies, [@cache] + sources, source_requirements) download(bundle, options) do_install(bundle, options) valid = bundle end generate_bins(valid, options) cleanup(valid, options) configure(valid, options) end
def load_path_for(gem_path, path)
def load_path_for(gem_path, path) gem_path.join(path).relative_path_from(@path).to_s end
def load_paths_for_specs(specs, options)
def load_paths_for_specs(specs, options) load_paths = [] specs.each do |spec| next if options[:no_bundle].include?(spec.name) gem_path = Pathname.new(spec.full_gem_path) load_paths << load_path_for(gem_path, spec.bindir) if spec.bindir spec.require_paths.each do |path| load_paths << load_path_for(gem_path, path) end end load_paths end
def only_local(sources)
def only_local(sources) sources.select { |s| s.can_be_local? } end
def outdated_gems
def outdated_gems source_index.outdated.sort end
def prune(dependencies, sources)
def prune(dependencies, sources) sources.each do |s| s.repository = self s.local = true end sources = only_local(sources) bundle = Resolver.resolve(dependencies, [@cache] + sources) @cache.gems.each do |name, specs| specs.each do |spec| unless bundle.any? { |s| s.name == spec.name && s.version == spec.version } Bundler.logger.info "Pruning #{spec.name} (#{spec.version}) from the cache" FileUtils.rm @path.join("cache", "#{spec.full_name}.gem") end end end end
def require_code(file, dep)
def require_code(file, dep) constraint = case when dep.only then %{ if #{dep.only.inspect}.include?(env)} when dep.except then %{ unless #{dep.except.inspect}.include?(env)} end "require #{file.inspect}#{constraint}" end
def source_index
def source_index index = Gem::SourceIndex.from_gems_in(@path.join("specifications")) index.each { |n, spec| spec.loaded_from = @path.join("specifications", "#{spec.full_name}.gemspec") } index end
def spec_file_for(spec)
def spec_file_for(spec) spec.loaded_from.relative_path_from(@path).to_s end