class Bundler::Runtime
def actual_dependencies
def actual_dependencies @definition.actual_dependencies end
def autorequires_for_groups(*groups)
def autorequires_for_groups(*groups) groups.map! { |g| g.to_sym } autorequires = Hash.new { |h,k| h[k] = [] } @definition.dependencies.each do |dep| dep.groups.each do |group| # If there is no autorequire, then rescue from # autorequiring the gems name if dep.autorequire dep.autorequire.each do |file| autorequires[group] << [file, true] end else autorequires[group] << [dep.name, false] end end end if groups.empty? autorequires else groups.inject({}) { |h,g| h[g] = autorequires[g]; h } end end
def cripple_rubygems(specs)
def cripple_rubygems(specs) reverse_rubygems_kernel_mixin executables = specs.map { |s| s.executables }.flatten # TODO: This is duplicated a bit too much in environment.erb. # Let's figure out how to improve that. ::Kernel.send(:define_method, :gem) do |dep, *reqs| if executables.include? File.basename(caller.first.split(':').first) return end opts = reqs.last.is_a?(Hash) ? reqs.pop : {} unless dep.respond_to?(:name) && dep.respond_to?(:version_requirements) dep = Gem::Dependency.new(dep, reqs) end spec = specs.find { |s| s.name == dep.name } if spec.nil? e = Gem::LoadError.new "#{dep} is not part of the bundle. Add it to Gemfile." e.name = dep.name e.version_requirement = dep.version_requirements raise e elsif dep !~ spec e = Gem::LoadError.new "can't activate #{dep}, already activated #{spec.full_name}. " \ "Make sure all dependencies are added to Gemfile." e.name = dep.name e.version_requirement = dep.version_requirements raise e end true end # === Following hacks are to improve on the generated bin wrappers === # Yeah, talk about a hack source_index_class = (class << Gem::SourceIndex ; self ; end) source_index_class.send(:define_method, :from_gems_in) do |*args| source_index = Gem::SourceIndex.new source_index.add_specs *specs source_index end # OMG more hacks gem_class = (class << Gem ; self ; end) gem_class.send(:define_method, :bin_path) do |name, *args| exec_name, *reqs = args spec = nil if exec_name spec = specs.find { |s| s.executables.include?(exec_name) } spec or raise Gem::Exception, "can't find executable #{exec_name}" else spec = specs.find { |s| s.name == name } exec_name = spec.default_executable or raise Gem::Exception, "no default executable for #{spec.full_name}" end File.join(spec.full_gem_path, spec.bindir, exec_name) end end
def dependencies
def dependencies @definition.dependencies end
def dependencies_for(*groups)
def dependencies_for(*groups) if groups.empty? dependencies else dependencies.select { |d| (groups & d.groups).any? } end end
def details
def details details = {} details["hash"] = gemfile_fingerprint details["sources"] = sources.map { |s| { s.class.name.split("::").last => s.options} } details["specs"] = specs.map do |s| options = {"version" => s.version.to_s} options["source"] = sources.index(s.source) if sources.include?(s.source) { s.name => options } end details["dependencies"] = @definition.dependencies.inject({}) do |h,d| h.merge!({d.name => {"version" => d.version_requirements.to_s, "group" => d.groups} }) h[d.name]['require'] = d.autorequire if d.autorequire h end details end
def gemfile_fingerprint
def gemfile_fingerprint Digest::SHA1.hexdigest(File.read("#{root}/Gemfile")) end
def index
def index @definition.local_index end
def initialize(*)
def initialize(*) super if locked? # && !rb_lock_file.exist? write_rb_lock end end
def load_paths
def load_paths specs.map { |s| s.load_paths }.flatten end
def lock
def lock Bundler.ui.info("The bundle is already locked, relocking.") if locked? sources.each { |s| s.lock if s.respond_to?(:lock) } FileUtils.mkdir_p("#{root}/.bundle") write_yml_lock write_rb_lock Bundler.ui.info("The bundle is now locked. Use `bundle show` to list the gems in the environment.") end
def locked?
def locked? File.exist?("#{root}/Gemfile.lock") || File.exist?("#{root}/.bundle/environment.rb") end
def pack
def pack pack_path = "#{root}/vendor/cache/" FileUtils.mkdir_p(pack_path) Bundler.ui.info "Copying .gem files into vendor/cache" specs.each do |spec| next unless spec.source.is_a?(Source::SystemGems) || spec.source.is_a?(Source::Rubygems) possibilities = Gem.path.map { |p| "#{p}/cache/#{spec.full_name}.gem" } cached_path = possibilities.find { |p| File.exist? p } Bundler.ui.info " * #{File.basename(cached_path)}" next if File.expand_path(File.dirname(cached_path)) == File.expand_path(pack_path) FileUtils.cp(cached_path, pack_path) end end
def rb_lock_file
def rb_lock_file root.join(".bundle/environment.rb") end
def require(*groups)
def require(*groups) groups.map! { |g| g.to_sym } groups = [:default] if groups.empty? autorequires = autorequires_for_groups(*groups) groups.each do |group| (autorequires[group] || [[]]).each do |path, explicit| if explicit Kernel.require(path) else begin Kernel.require(path) rescue LoadError end end end end end
def setup(*groups)
def setup(*groups) # Has to happen first clean_load_path specs = specs_for(*groups) cripple_rubygems(specs) # Activate the specs specs.each do |spec| Gem.loaded_specs[spec.name] = spec $LOAD_PATH.unshift(*spec.load_paths) end self end
def sources
def sources @definition.sources end
def specs
def specs @specs ||= begin source_requirements = {} actual_dependencies.each do |dep| next unless dep.source && dep.source.respond_to?(:local_specs) source_requirements[dep.name] = dep.source.local_specs end group_specs(Resolver.resolve(@definition.actual_dependencies, index, source_requirements)) end end
def specs_for(*groups)
def specs_for(*groups) groups.map! { |g| g.to_sym } if groups.empty? specs else Resolver.resolve(dependencies_for(*groups), index) end end
def specs_for_lock_file
def specs_for_lock_file specs.map do |spec| dep = @definition.dependencies.find { |d| d.name == spec.name } hash = {} hash[:name] = spec.name hash[:version] = spec.version.to_s hash[:groups] = spec.groups hash[:load_paths] = spec.load_paths hash end end
def write_rb_lock
def write_rb_lock shared_helpers = File.read(File.expand_path("../shared_helpers.rb", __FILE__)) template = File.read(File.expand_path("../templates/environment.erb", __FILE__)) erb = ERB.new(template, nil, '-') File.open(rb_lock_file, 'w') do |f| f.puts erb.result(binding) end end
def write_yml_lock
def write_yml_lock yml = details.to_yaml File.open("#{root}/Gemfile.lock", 'w') do |f| f.puts yml end end