Upgrade to Pro — share decks privately, control downloads, hide ads and more …

From Whence Rubygems - Mark 2

From Whence Rubygems - Mark 2

Where do Rubygems come from? We will trace the journey a Gem takes on its way into your codebase, mapping paths through tools like RVM, rbenv and Bundler. Along the way we will learn how these tools wrangle third party Ruby code into place and what methods they share.

Tim Uruski

August 16, 2014
Tweet

More Decks by Tim Uruski

Other Decks in Programming

Transcript

  1. ‣ Introduction *You are here ‣ Part 1: Gems primer

    ‣ Part 2: Rubygems ‣ Part 3: Bundler ‣ Part 4: Gemsets ‣ Conclusion
  2. ‣ Where new gems are installed ‣ Environment: GEM_HOME ‣

    Command line: gem env gemdir ‣ Ruby: Gem.dir Gem Home
  3. ‣ A list of paths to search for gems ‣

    Environment: GEM_PATH ‣ Command line: gem env gempath ‣ Ruby: Gem.path Gem Path
  4. $ gem env gempath /home/timuruski/.gem/ruby/2.1.2 /opt/rubies/ruby-2.1.2/lib/ruby/gems/2.1.0 ! $ ruby -e

    "puts Gem.path" /home/timuruski/.gem/ruby/2.1.2 /opt/rubies/ruby-2.1.2/lib/ruby/gems/2.1.0
  5. Gem::Specification.new do |s| s.name = 'hola' s.version = '1.0.0' s.date

    = '2014-02-17' s.summary = "Hola!" s.description = "A simple hello world gem" s.author = 'Tim Uruski' s.email = '[email protected]' s.files = ['lib/hola.rb'] s.homepage = 'http://rubygems.org/gems/hola' s.license = 'MIT' end
  6. # -*- encoding: utf-8 -*- # stub: hola 1.0.0 ruby

    lib ! Gem::Specification.new do |s| s.name = "hola" s.version = "1.0.0" ! s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.require_paths = ["lib"] s.authors = ["Tim Uruski"] s.date = "2014-02-17" s.description = "A simple hello world gem" s.email = "[email protected]" s.homepage = "http://rubygems.org/gems/hola" s.licenses = ["MIT"] s.rubygems_version = "2.4.1" s.summary = "Hola!" ! s.installed_by_version = "2.4.1" if s.respond_to? :installed_by_version end
  7. # -*- encoding: utf-8 -*- # stub: hola 1.0.0 ruby

    lib ! Gem::Specification.new do |s| s.name = "hola" s.version = "1.0.0" ! s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.require_paths = ["lib"] s.authors = ["Tim Uruski"] s.date = "2014-02-17" s.description = "A simple hello world gem" s.email = "[email protected]" s.homepage = "http://rubygems.org/gems/hola" s.licenses = ["MIT"] s.rubygems_version = "2.4.1" s.summary = "Hola!" ! s.installed_by_version = "2.4.1" if s.respond_to? :installed_by_version end Version Name Require paths
  8. # -*- encoding: utf-8 -*- # stub: hola 1.0.0 ruby

    lib ! Gem::Specification.new do |s| s.name = "hola" s.version = "1.0.0" ! s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.require_paths = ["lib"] s.authors = ["Tim Uruski"] s.date = "2014-02-17" s.description = "A simple hello world gem" s.email = "[email protected]" s.homepage = "http://rubygems.org/gems/hola" s.licenses = ["MIT"] s.rubygems_version = "2.4.1" s.summary = "Hola!" ! s.installed_by_version = "2.4.1" if s.respond_to? :installed_by_version end stub: hola 1.0.0 ruby lib Name Version Require paths
  9. module Kernel def require(path) # ... end end require 'hola'

    rubygems/lib/rubygems/core_ext/kernel_require.rb >
  10. module Kernel if defined?(gem_original_require) then # Ruby ships with a

    custom_require, override its require remove_method :require else # The Kernel#require from before RubyGems was loaded. alias gem_original_require require private :gem_original_require end end
  11. def require path RUBYGEMS_ACTIVATION_MONITOR.enter ! path = path.to_path if path.respond_to?

    :to_path ! spec = Gem.find_unresolved_default_spec(path) if spec Gem.remove_unresolved_default_spec(spec) gem(spec.name) end ! if Gem::Specification.unresolved_deps.empty? then RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) end ! spec = Gem::Specification.stubs.find { |s| s.activated? and s.contains_requirable_file? path } ! begin RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) end if spec ! found_specs = Gem::Specification.find_in_unresolved path ! if found_specs.empty? then found_specs = Gem::Specification.find_in_unresolved_tree path ! found_specs.each do |found_spec| found_spec.activate end else names = found_specs.map(&:name).uniq ! if names.size > 1 then RUBYGEMS_ACTIVATION_MONITOR.exit raise Gem::LoadError, "#{path} found in multiple gems: #{names.join ', '}" end ! valid = found_specs.select { |s| s.conflicts.empty? }.last ! unless valid then le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate" le.name = names.first RUBYGEMS_ACTIVATION_MONITOR.exit raise le end ! valid.activate end ! RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) rescue LoadError => load_error RUBYGEMS_ACTIVATION_MONITOR.enter ! if load_error.message.start_with?("Could not find") or (load_error.message.end_with?(path) and Gem.try_activate(path)) then RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) else RUBYGEMS_ACTIVATION_MONITOR.exit end ! raise load_error end
  12. def require path RUBYGEMS_ACTIVATION_MONITOR.enter ! path = path.to_path if path.respond_to?

    :to_path ! spec = Gem.find_unresolved_default_spec(path) if spec Gem.remove_unresolved_default_spec(spec) gem(spec.name) end ! if Gem::Specification.unresolved_deps.empty? then RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) end ! spec = Gem::Specification.stubs.find { |s| s.activated? and s.contains_requirable_file? path } ! begin RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) end if spec ! found_specs = Gem::Specification.find_in_unresolved path ! if found_specs.empty? then found_specs = Gem::Specification.find_in_unresolved_tree path ! found_specs.each do |found_spec| found_spec.activate end else names = found_specs.map(&:name).uniq ! if names.size > 1 then RUBYGEMS_ACTIVATION_MONITOR.exit raise Gem::LoadError, "#{path} found in multiple gems: #{names.join ', '}" end ! valid = found_specs.select { |s| s.conflicts.empty? }.last ! unless valid then le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate" le.name = names.first RUBYGEMS_ACTIVATION_MONITOR.exit raise le end ! valid.activate end ! RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) rescue LoadError => load_error RUBYGEMS_ACTIVATION_MONITOR.enter ! if load_error.message.start_with?("Could not find") or (load_error.message.end_with?(path) and Gem.try_activate(path)) then RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) else RUBYGEMS_ACTIVATION_MONITOR.exit end ! raise load_error end RUBYGEMS_ACTIVATION_MONITOR.enter RUBYGEMS_ACTIVATION_MONITOR.exit
  13. def require path RUBYGEMS_ACTIVATION_MONITOR.enter ! path = path.to_path if path.respond_to?

    :to_path ! spec = Gem.find_unresolved_default_spec(path) if spec Gem.remove_unresolved_default_spec(spec) gem(spec.name) end ! if Gem::Specification.unresolved_deps.empty? then RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) end ! spec = Gem::Specification.stubs.find { |s| s.activated? and s.contains_requirable_file? path } ! begin RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) end if spec ! found_specs = Gem::Specification.find_in_unresolved path ! if found_specs.empty? then found_specs = Gem::Specification.find_in_unresolved_tree path ! found_specs.each do |found_spec| found_spec.activate end else names = found_specs.map(&:name).uniq ! if names.size > 1 then RUBYGEMS_ACTIVATION_MONITOR.exit raise Gem::LoadError, "#{path} found in multiple gems: #{names.join ', '}" end ! valid = found_specs.select { |s| s.conflicts.empty? }.last ! unless valid then le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate" le.name = names.first RUBYGEMS_ACTIVATION_MONITOR.exit raise le end ! valid.activate end ! RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) rescue LoadError => load_error RUBYGEMS_ACTIVATION_MONITOR.enter ! if load_error.message.start_with?("Could not find") or (load_error.message.end_with?(path) and Gem.try_activate(path)) then RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) else RUBYGEMS_ACTIVATION_MONITOR.exit end ! raise load_error end def require(path) path = path.to_path if path.respond_to?(:to_path) ! if spec = Gem.find_unresolved_default_spec(path) Gem.remove_unresolved_default_spec(spec) gem(spec.name) end ! if Gem::Specification.unresolved_deps.empty? return gem_original_require(path) end ! spec = Gem::Specification.stubs.find { |s| s.activated? and s.contains_requirable_file?(path) } ! return gem_original_require(path) if spec ! found_specs = Gem::Specification.find_in_unresolved(path) if found_specs.empty? found_specs = Gem::Specification.find_in_unresolved_tree(path) found_specs.each(&:activate) else names = found_specs.map(&:name).uniq raise Gem::LoadError, "#{path} found in multiple gems" if names.size > 1 ! valid = found_specs.select { |s| s.conflicts.empty? }.last raise Gem::LoadError, "unable to find a version to activate" if valid.nil? ! valid.activate end ! return gem_original_require(path) rescue LoadError => load_error if load_error.message.start_with?("Could not find") or (load_error.message.end_with?(path) and Gem.try_activate(path)) return gem_original_require(path) end ! raise load_error end
  14. def require path RUBYGEMS_ACTIVATION_MONITOR.enter ! path = path.to_path if path.respond_to?

    :to_path ! spec = Gem.find_unresolved_default_spec(path) if spec Gem.remove_unresolved_default_spec(spec) gem(spec.name) end ! if Gem::Specification.unresolved_deps.empty? then RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) end ! spec = Gem::Specification.stubs.find { |s| s.activated? and s.contains_requirable_file? path } ! begin RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) end if spec ! found_specs = Gem::Specification.find_in_unresolved path ! if found_specs.empty? then found_specs = Gem::Specification.find_in_unresolved_tree path ! found_specs.each do |found_spec| found_spec.activate end else names = found_specs.map(&:name).uniq ! if names.size > 1 then RUBYGEMS_ACTIVATION_MONITOR.exit raise Gem::LoadError, "#{path} found in multiple gems: #{names.join ', '}" end ! valid = found_specs.select { |s| s.conflicts.empty? }.last ! unless valid then le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate" le.name = names.first RUBYGEMS_ACTIVATION_MONITOR.exit raise le end ! valid.activate end ! RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) rescue LoadError => load_error RUBYGEMS_ACTIVATION_MONITOR.enter ! if load_error.message.start_with?("Could not find") or (load_error.message.end_with?(path) and Gem.try_activate(path)) then RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) else RUBYGEMS_ACTIVATION_MONITOR.exit end ! raise load_error end def require(path) path = path.to_path if path.respond_to?(:to_path) ! if spec = Gem.find_unresolved_default_spec(path) Gem.remove_unresolved_default_spec(spec) gem(spec.name) end ! if Gem::Specification.unresolved_deps.empty? return gem_original_require(path) end ! spec = Gem::Specification.stubs.find { |s| s.activated? and s.contains_requirable_file?(path) } ! return gem_original_require(path) if spec ! found_specs = Gem::Specification.find_in_unresolved(path) if found_specs.empty? found_specs = Gem::Specification.find_in_unresolved_tree(path) found_specs.each(&:activate) else names = found_specs.map(&:name).uniq raise Gem::LoadError, "#{path} found in multiple gems" if names.size > 1 ! valid = found_specs.select { |s| s.conflicts.empty? }.last raise Gem::LoadError, "unable to find a version to activate" if valid.nil? ! valid.activate end ! return gem_original_require(path) rescue LoadError => load_error if load_error.message.start_with?("Could not find") or (load_error.message.end_with?(path) and Gem.try_activate(path)) return gem_original_require(path) end ! raise load_error end gem_original_require(path)
  15. def require path RUBYGEMS_ACTIVATION_MONITOR.enter ! path = path.to_path if path.respond_to?

    :to_path ! spec = Gem.find_unresolved_default_spec(path) if spec Gem.remove_unresolved_default_spec(spec) gem(spec.name) end ! if Gem::Specification.unresolved_deps.empty? then RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) end ! spec = Gem::Specification.stubs.find { |s| s.activated? and s.contains_requirable_file? path } ! begin RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) end if spec ! found_specs = Gem::Specification.find_in_unresolved path ! if found_specs.empty? then found_specs = Gem::Specification.find_in_unresolved_tree path ! found_specs.each do |found_spec| found_spec.activate end else names = found_specs.map(&:name).uniq ! if names.size > 1 then RUBYGEMS_ACTIVATION_MONITOR.exit raise Gem::LoadError, "#{path} found in multiple gems: #{names.join ', '}" end ! valid = found_specs.select { |s| s.conflicts.empty? }.last ! unless valid then le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate" le.name = names.first RUBYGEMS_ACTIVATION_MONITOR.exit raise le end ! valid.activate end ! RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) rescue LoadError => load_error RUBYGEMS_ACTIVATION_MONITOR.enter ! if load_error.message.start_with?("Could not find") or (load_error.message.end_with?(path) and Gem.try_activate(path)) then RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) else RUBYGEMS_ACTIVATION_MONITOR.exit end ! raise load_error end def require(path) path = path.to_path if path.respond_to?(:to_path) ! if spec = Gem.find_unresolved_default_spec(path) Gem.remove_unresolved_default_spec(spec) gem(spec.name) end ! if Gem::Specification.unresolved_deps.empty? return gem_original_require(path) end ! spec = Gem::Specification.stubs.find { |s| s.activated? and s.contains_requirable_file?(path) } ! return gem_original_require(path) if spec ! found_specs = Gem::Specification.find_in_unresolved(path) if found_specs.empty? found_specs = Gem::Specification.find_in_unresolved_tree(path) found_specs.each(&:activate) else names = found_specs.map(&:name).uniq raise Gem::LoadError, "#{path} found in multiple gems" if names.size > 1 ! valid = found_specs.select { |s| s.conflicts.empty? }.last raise Gem::LoadError, "unable to find a version to activate" if valid.nil? ! valid.activate end ! return gem_original_require(path) rescue LoadError => load_error if load_error.message.start_with?("Could not find") or (load_error.message.end_with?(path) and Gem.try_activate(path)) return gem_original_require(path) end ! raise load_error end rescue LoadError => load_error
  16. def require(path) path = path.to_path if path.respond_to?(:to_path) ! if spec

    = Gem.find_unresolved_default_spec(path) Gem.remove_unresolved_default_spec(spec) gem(spec.name) end ! if Gem::Specification.unresolved_deps.empty? return gem_original_require(path) end ! spec = Gem::Specification.stubs.find { |s| s.activated? and s.contains_requirable_file?(path) } ! return gem_original_require(path) if spec ! found_specs = Gem::Specification.find_in_unresolved(path) if found_specs.empty? found_specs = Gem::Specification.find_in_unresolved_tree(path) found_specs.each(&:activate) else names = found_specs.map(&:name).uniq raise Gem::LoadError, "#{path} found in multiple gems" if names.size > 1 ! valid = found_specs.select { |s| s.conflicts.empty? }.last raise Gem::LoadError, "unable to find a version to activate" if valid.nil? ! valid.activate end ! return gem_original_require(path) rescue LoadError => load_error if load_error.message.start_with?("Could not find") or (load_error.message.end_with?(path) and Gem.try_activate(path)) return gem_original_require(path) end ! raise load_error end def require path RUBYGEMS_ACTIVATION_MONITOR.enter ! path = path.to_path if path.respond_to? :to_path ! spec = Gem.find_unresolved_default_spec(path) if spec Gem.remove_unresolved_default_spec(spec) gem(spec.name) end ! if Gem::Specification.unresolved_deps.empty? then RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) end ! spec = Gem::Specification.stubs.find { |s| s.activated? and s.contains_requirable_file? path } ! begin RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) end if spec ! found_specs = Gem::Specification.find_in_unresolved path ! if found_specs.empty? then found_specs = Gem::Specification.find_in_unresolved_tree path ! found_specs.each do |found_spec| found_spec.activate end else names = found_specs.map(&:name).uniq ! if names.size > 1 then RUBYGEMS_ACTIVATION_MONITOR.exit raise Gem::LoadError, "#{path} found in multiple gems: #{names.join ', '}" end ! valid = found_specs.select { |s| s.conflicts.empty? }.last ! unless valid then le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate" le.name = names.first RUBYGEMS_ACTIVATION_MONITOR.exit raise le end ! valid.activate end ! RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) rescue LoadError => load_error RUBYGEMS_ACTIVATION_MONITOR.enter ! if load_error.message.start_with?("Could not find") or (load_error.message.end_with?(path) and Gem.try_activate(path)) then RUBYGEMS_ACTIVATION_MONITOR.exit return gem_original_require(path) else RUBYGEMS_ACTIVATION_MONITOR.exit end ! raise load_error end def require(path) gem_original_require(path) rescue LoadError => load_error if Gem.try_activate(path) gem_original_require(path) else raise load_error end end
  17. def self.try_activate(path) spec = Gem::Specification.find_inactive_by_path(path) ! if spec.nil? spec =

    Gem::Specification.find_by_path(path) return true if spec && spec.activated? return false end ! begin spec.activate rescue Gem::LoadError # This could fail due to gem dep collisions, go lax. Gem::Specification.find_by_name(spec.name).activate end ! return true end
  18. def self.try_activate(path) spec = Gem::Specification.find_inactive_by_path(path) ! if spec.nil? spec =

    Gem::Specification.find_by_path(path) return true if spec && spec.activated? return false end ! begin spec.activate rescue Gem::LoadError # This could fail due to gem dep collisions, go lax. Gem::Specification.find_by_name(spec.name).activate end ! return true end
  19. def self.try_activate(path) spec = Gem::Specification.find_inactive_by_path(path) ! if spec.nil? spec =

    Gem::Specification.find_by_path(path) return true if spec && spec.activated? return false end ! begin spec.activate rescue Gem::LoadError # This could fail due to gem dep collisions, go lax. Gem::Specification.find_by_name(spec.name).activate end ! return true end
  20. def self.try_activate(path) spec = Gem::Specification.find_inactive_by_path(path) ! if spec.nil? spec =

    Gem::Specification.find_by_path(path) return true if spec && spec.activated? return false end ! begin spec.activate rescue Gem::LoadError # This could fail due to gem dep collisions, go lax. Gem::Specification.find_by_name(spec.name).activate end ! return true end
  21. def self.try_activate(path) spec = Gem::Specification.find_inactive_by_path(path) ! if spec.nil? spec =

    Gem::Specification.find_by_path(path) return true if spec && spec.activated? return false end ! begin spec.activate rescue Gem::LoadError # This could fail due to gem dep collisions, go lax. Gem::Specification.find_by_name(spec.name).activate end ! return true end def activate other = Gem.loaded_specs[self.name] if other then check_version_conflict(other) return false end ! raise_if_conflicts ! activate_dependencies add_self_to_load_path ! Gem.loaded_specs[self.name] = self @activated = true @loaded = true ! return true end
  22. def self.try_activate(path) spec = Gem::Specification.find_inactive_by_path(path) ! if spec.nil? spec =

    Gem::Specification.find_by_path(path) return true if spec && spec.activated? return false end ! begin spec.activate rescue Gem::LoadError # This could fail due to gem dep collisions, go lax. Gem::Specification.find_by_name(spec.name).activate end ! return true end def activate other = Gem.loaded_specs[self.name] if other then check_version_conflict(other) return false end ! raise_if_conflicts ! activate_dependencies add_self_to_load_path ! Gem.loaded_specs[self.name] = self @activated = true @loaded = true ! return true end
  23. def self.try_activate(path) spec = Gem::Specification.find_inactive_by_path(path) ! if spec.nil? spec =

    Gem::Specification.find_by_path(path) return true if spec && spec.activated? return false end ! begin spec.activate rescue Gem::LoadError # This could fail due to gem dep collisions, go lax. Gem::Specification.find_by_name(spec.name).activate end ! return true end def activate other = Gem.loaded_specs[self.name] if other then check_version_conflict(other) return false end ! raise_if_conflicts ! activate_dependencies add_self_to_load_path ! Gem.loaded_specs[self.name] = self @activated = true @loaded = true ! return true end
  24. def self.try_activate(path) spec = Gem::Specification.find_inactive_by_path(path) ! if spec.nil? spec =

    Gem::Specification.find_by_path(path) return true if spec && spec.activated? return false end ! begin spec.activate rescue Gem::LoadError # This could fail due to gem dep collisions, go lax. Gem::Specification.find_by_name(spec.name).activate end ! return true end def add_self_to_load_path return if default_gem? ! paths = full_require_paths ! # Gem directories must come after -I and ENV['RUBYLIB'] insert_index = Gem.load_path_insert_index || 0 $LOAD_PATH.insert(insert_index, *paths) end *
  25. def self.try_activate(path) spec = Gem::Specification.find_inactive_by_path(path) ! if spec.nil? spec =

    Gem::Specification.find_by_path(path) return true if spec && spec.activated? return false end ! begin spec.activate rescue Gem::LoadError # This could fail due to gem dep collisions, go lax. Gem::Specification.find_by_name(spec.name).activate end ! return true end
  26. def self.try_activate(path) spec = Gem::Specification.find_inactive_by_path(path) ! if spec.nil? spec =

    Gem::Specification.find_by_path(path) return true if spec && spec.activated? return false end ! begin spec.activate rescue Gem::LoadError # This could fail due to gem dep collisions, go lax. Gem::Specification.find_by_name(spec.name).activate end ! return true end ! def self.path paths.path end def self.paths @paths ||= Gem::PathSupport.new end ! def initialize(env=ENV) @env = env @home = env["GEM_HOME"] || ENV["GEM_HOME"] || Gem.default_dir self.path = env["GEM_PATH"] || ENV["GEM_PATH"] ! @spec_cache_dir = env["GEM_SPEC_CACHE"] || ENV["GEM_SPEC_CACHE"] || Gem.default_spec_cache_dir ! @spec_cache_dir = @spec_cache_dir.dup.untaint end Gem > Gem::PathSupport > ! def self.find_inactive_by_path path stub = stubs.find { |s| s.contains_requirable_file? path unless s.activated? } stub && stub.to_spec end Gem::Specification > def self.stubs @@stubs ||= begin stubs = {} each_stub([default_specifications_dir] + dirs) do |stub| stubs[stub.full_name] ||= stub end ! stubs = stubs.values _resort!(stubs) stubs end end def self.each_stub(dirs) each_gemspec(dirs) do |path| stub = Gem::StubSpecification.new(path) yield stub if stub.valid? end end def self.each_gemspec(dirs) dirs.each do |dir| Dir[File.join(dir, "*.gemspec")].each do |path| yield path.untaint end end end def self.dirs @@dirs ||= Gem.path.collect { |dir| File.join dir.dup.untaint, "specifications" } end
  27. def self.try_activate(path) spec = Gem::Specification.find_inactive_by_path(path) ! if spec.nil? spec =

    Gem::Specification.find_by_path(path) return true if spec && spec.activated? return false end ! begin spec.activate rescue Gem::LoadError # This could fail due to gem dep collisions, go lax. Gem::Specification.find_by_name(spec.name).activate end ! return true end ! def self.path paths.path end def self.paths @paths ||= Gem::PathSupport.new end ! def initialize(env=ENV) @env = env @home = env["GEM_HOME"] || ENV["GEM_HOME"] || Gem.default_dir self.path = env["GEM_PATH"] || ENV["GEM_PATH"] ! @spec_cache_dir = env["GEM_SPEC_CACHE"] || ENV["GEM_SPEC_CACHE"] || Gem.default_spec_cache_dir ! @spec_cache_dir = @spec_cache_dir.dup.untaint end Gem > Gem::PathSupport > ! def self.find_inactive_by_path path stub = stubs.find { |s| s.contains_requirable_file? path unless s.activated? } stub && stub.to_spec end Gem::Specification > def self.stubs @@stubs ||= begin stubs = {} each_stub([default_specifications_dir] + dirs) do |stub| stubs[stub.full_name] ||= stub end ! stubs = stubs.values _resort!(stubs) stubs end end def self.each_stub(dirs) each_gemspec(dirs) do |path| stub = Gem::StubSpecification.new(path) yield stub if stub.valid? end end def self.each_gemspec(dirs) dirs.each do |dir| Dir[File.join(dir, "*.gemspec")].each do |path| yield path.untaint end end end def self.dirs @@dirs ||= Gem.path.collect { |dir| File.join dir.dup.untaint, "specifications" } end A giant call stack appears!
  28. def self.try_activate(path) spec = Gem::Specification.find_inactive_by_path(path) ! if spec.nil? spec =

    Gem::Specification.find_by_path(path) return true if spec && spec.activated? return false end ! begin spec.activate rescue Gem::LoadError # This could fail due to gem dep collisions, go lax. Gem::Specification.find_by_name(spec.name).activate end ! return true end def find_inactive_by_path(path) stubs = Gem.path.flat_map { |dir| pattern = File.join(dir, 'specifications', '*.gemspec') Dir.glob(pattern).map { |path| Gem::StubSpecification.new(path) } } ! stubs.select!(&:valid?) stubs.sort!(MultiSort.new(name: ASC, version: DESC)) ! inactive_stub = stubs.find { |stub| stub.contains_requirable_file?(path) unless stub.activated? } ! inactive_stub.to_spec unless inactive_stub.nil? end *
  29. def self.try_activate(path) spec = Gem::Specification.find_inactive_by_path(path) ! if spec.nil? spec =

    Gem::Specification.find_by_path(path) return true if spec && spec.activated? return false end ! begin spec.activate rescue Gem::LoadError # This could fail due to gem dep collisions, go lax. Gem::Specification.find_by_name(spec.name).activate end ! return true end def find_inactive_by_path(path) stubs = Gem.path.flat_map { |dir| pattern = File.join(dir, 'specifications', '*.gemspec') Dir.glob(pattern).map { |path| Gem::StubSpecification.new(path) } } ! stubs.select!(&:valid?) stubs.sort!(MultiSort.new(name: ASC, version: DESC)) ! inactive_stub = stubs.find { |stub| stub.contains_requirable_file?(path) unless stub.activated? } ! inactive_stub.to_spec unless inactive_stub.nil? end *
  30. def self.try_activate(path) spec = Gem::Specification.find_inactive_by_path(path) ! if spec.nil? spec =

    Gem::Specification.find_by_path(path) return true if spec && spec.activated? return false end ! begin spec.activate rescue Gem::LoadError # This could fail due to gem dep collisions, go lax. Gem::Specification.find_by_name(spec.name).activate end ! return true end def find_inactive_by_path(path) stubs = Gem.path.flat_map { |dir| pattern = File.join(dir, 'specifications', '*.gemspec') Dir.glob(pattern).map { |path| Gem::StubSpecification.new(path) } } ! stubs.select!(&:valid?) stubs.sort!(MultiSort.new(name: ASC, version: DESC)) ! inactive_stub = stubs.find { |stub| stub.contains_requirable_file?(path) unless stub.activated? } ! inactive_stub.to_spec unless inactive_stub.nil? end *
  31. def self.try_activate(path) spec = Gem::Specification.find_inactive_by_path(path) ! if spec.nil? spec =

    Gem::Specification.find_by_path(path) return true if spec && spec.activated? return false end ! begin spec.activate rescue Gem::LoadError # This could fail due to gem dep collisions, go lax. Gem::Specification.find_by_name(spec.name).activate end ! return true end def find_inactive_by_path(path) stubs = Gem.path.flat_map { |dir| pattern = File.join(dir, 'specifications', '*.gemspec') Dir.glob(pattern).map { |path| Gem::StubSpecification.new(path) } } ! stubs.select!(&:valid?) stubs.sort!(MultiSort.new(name: ASC, version: DESC)) ! inactive_stub = stubs.find { |stub| stub.contains_requirable_file?(path) unless stub.activated? } ! inactive_stub.to_spec unless inactive_stub.nil? end def contains_requirable_file?(file) suffixes = Gem.suffixes ! full_require_paths.any? do |dir| base = "#{dir}/#{file}" suffixes.any? { |suf| File.file?("#{base}#{suf}") } end end ["", ".rb", ".bundle"] /home/timuruski/.gem/ruby/2.1.2/gems/hola-1.0.0/lib/hola /home/timuruski/.gem/ruby/2.1.2/gems/hola-1.0.0/lib/hola.rb /home/timuruski/.gem/ruby/2.1.2/gems/hola-1.0.0/lib/hola.bundle
  32. ‣ Try to load the file as usual ‣ If

    it fails, walk the GEM_PATH and load the stub lines ‣ Find a gem that contains the file being required ‣ Add its lib/ and other directories to the LOAD_PATH ‣ Try to load the file as usual
  33. require 'bundler/setup' require 'bundler' Bundler.setup ! bundler_lib = File.expand_path("../..", __FILE__)

    unless $LOAD_PATH.include?(bundler_lib) $LOAD_PATH.unshift(bundler_lib) end bundler/lib/bundler.rb >
  34. def setup(*groups) return @setup if defined?(@setup) ! definition.validate_ruby! ! if

    groups.empty? @setup = load.setup else @completed_groups ||= [] unloaded = groups - @completed_groups @completed_groups = groups unloaded.any? ? load.setup(*groups) : load end end > Bundler.setup
  35. def setup(*groups) return @setup if defined?(@setup) ! definition.validate_ruby! ! if

    groups.empty? @setup = load.setup else @completed_groups ||= [] unloaded = groups - @completed_groups @completed_groups = groups unloaded.any? ? load.setup(*groups) : load end end > Bundler.setup
  36. def setup(*groups) return @setup if defined?(@setup) ! definition.validate_ruby! ! if

    groups.empty? @setup = load.setup else @completed_groups ||= [] unloaded = groups - @completed_groups @completed_groups = groups unloaded.any? ? load.setup(*groups) : load end end def load @load ||= Runtime.new(root, definition) end def root default_gemfile.dirname.expand_path end def definition(unlock = nil) @definition = nil if unlock @definition ||= begin configure upgrade_lockfile Definition.build(default_gemfile, default_lockfile, unlock) end end > Bundler.setup
  37. def setup(*groups) return @setup if defined?(@setup) ! definition.validate_ruby! ! if

    groups.empty? @setup = load.setup else @completed_groups ||= [] unloaded = groups - @completed_groups @completed_groups = groups unloaded.any? ? load.setup(*groups) : load end end def load @load ||= Runtime.new(root, definition) end def root default_gemfile.dirname.expand_path end def definition(unlock = nil) @definition = nil if unlock @definition ||= begin configure upgrade_lockfile Definition.build(default_gemfile, default_lockfile, unlock) end end > Bundler.setup
  38. def configure @configured ||= configure_gem_home_and_path end def configure_gem_home_and_path blank_home =

    ENV['GEM_HOME'].nil? || ENV['GEM_HOME'].empty? if settings[:disable_shared_gems] ENV['GEM_PATH'] = '' elsif blank_home || Bundler.rubygems.gem_dir != bundle_path.to_s possibles = [Bundler.rubygems.gem_dir, Bundler.rubygems.gem_path] paths = possibles.flatten.compact.uniq.reject { |p| p.empty? } ENV["GEM_PATH"] = paths.join(File::PATH_SEPARATOR) end ! configure_gem_home bundle_path end
  39. def configure @configured ||= configure_gem_home_and_path end def configure_gem_home_and_path blank_home =

    ENV['GEM_HOME'].nil? || ENV['GEM_HOME'].empty? if settings[:disable_shared_gems] ENV['GEM_PATH'] = '' elsif blank_home || Bundler.rubygems.gem_dir != bundle_path.to_s possibles = [Bundler.rubygems.gem_dir, Bundler.rubygems.gem_path] paths = possibles.flatten.compact.uniq.reject { |p| p.empty? } ENV["GEM_PATH"] = paths.join(File::PATH_SEPARATOR) end ! configure_gem_home bundle_path end
  40. def configure @configured ||= configure_gem_home_and_path end def configure_gem_home_and_path blank_home =

    ENV['GEM_HOME'].nil? || ENV['GEM_HOME'].empty? if settings[:disable_shared_gems] ENV['GEM_PATH'] = '' elsif blank_home || Bundler.rubygems.gem_dir != bundle_path.to_s possibles = [Bundler.rubygems.gem_dir, Bundler.rubygems.gem_path] paths = possibles.flatten.compact.uniq.reject { |p| p.empty? } ENV["GEM_PATH"] = paths.join(File::PATH_SEPARATOR) end ! configure_gem_home bundle_path end
  41. def configure @configured ||= configure_gem_home_and_path end def configure_gem_home_and_path blank_home =

    ENV['GEM_HOME'].nil? || ENV['GEM_HOME'].empty? if settings[:disable_shared_gems] ENV['GEM_PATH'] = '' elsif blank_home || Bundler.rubygems.gem_dir != bundle_path.to_s possibles = [Bundler.rubygems.gem_dir, Bundler.rubygems.gem_path] paths = possibles.flatten.compact.uniq.reject { |p| p.empty? } ENV["GEM_PATH"] = paths.join(File::PATH_SEPARATOR) end ! configure_gem_home bundle_path end
  42. def configure @configured ||= configure_gem_home_and_path end def configure_gem_home_and_path blank_home =

    ENV['GEM_HOME'].nil? || ENV['GEM_HOME'].empty? if settings[:disable_shared_gems] ENV['GEM_PATH'] = '' elsif blank_home || Bundler.rubygems.gem_dir != bundle_path.to_s possibles = [Bundler.rubygems.gem_dir, Bundler.rubygems.gem_path] paths = possibles.flatten.compact.uniq.reject { |p| p.empty? } ENV["GEM_PATH"] = paths.join(File::PATH_SEPARATOR) end ! configure_gem_home bundle_path end configure_gem_home FileUtils.mkdir_p bundle_path.to_s rescue nil ! ENV['GEM_HOME'] = File.expand_path(bundle_path, root) Bundler.rubygems.clear_paths end
  43. def setup(*groups) return @setup if defined?(@setup) ! definition.validate_ruby! ! if

    groups.empty? @setup = load.setup else @completed_groups ||= [] unloaded = groups - @completed_groups @completed_groups = groups unloaded.any? ? load.setup(*groups) : load end end > Bundler.setup
  44. def setup(*groups) clean_load_path setup_environment ! groups.map! { |g| g.to_sym }

    specs = groups.any? ? @definition.specs_for(groups) : requested_specs Bundler.rubygems.replace_entrypoints(specs) ! specs.each do |spec| Bundler.rubygems.mark_loaded(spec) load_paths = spec.load_paths.reject {|p| $LOAD_PATH.include?(p)} $LOAD_PATH.unshift(*load_paths) end ! setup_manpath lock end > Runtime#setup *
  45. def setup(*groups) clean_load_path setup_environment ! groups.map! { |g| g.to_sym }

    specs = groups.any? ? @definition.specs_for(groups) : requested_specs Bundler.rubygems.replace_entrypoints(specs) ! specs.each do |spec| Bundler.rubygems.mark_loaded(spec) load_paths = spec.load_paths.reject {|p| $LOAD_PATH.include?(p)} $LOAD_PATH.unshift(*load_paths) end ! setup_manpath lock end > Runtime#setup * Removes 1.9 system gems
  46. def setup(*groups) clean_load_path setup_environment ! groups.map! { |g| g.to_sym }

    specs = groups.any? ? @definition.specs_for(groups) : requested_specs Bundler.rubygems.replace_entrypoints(specs) ! specs.each do |spec| Bundler.rubygems.mark_loaded(spec) load_paths = spec.load_paths.reject {|p| $LOAD_PATH.include?(p)} $LOAD_PATH.unshift(*load_paths) end ! setup_manpath lock end > Runtime#setup * Sets ENV: - BUNDLE_BIN_PATH - PATH - BUNDLE_GEMFILE - RUBYOPT - RUBYLIB
  47. def setup(*groups) clean_load_path setup_environment ! groups.map! { |g| g.to_sym }

    specs = groups.any? ? @definition.specs_for(groups) : requested_specs Bundler.rubygems.replace_entrypoints(specs) ! specs.each do |spec| Bundler.rubygems.mark_loaded(spec) load_paths = spec.load_paths.reject {|p| $LOAD_PATH.include?(p)} $LOAD_PATH.unshift(*load_paths) end ! setup_manpath lock end > Runtime#setup *
  48. def setup(*groups) clean_load_path setup_environment ! groups.map! { |g| g.to_sym }

    specs = groups.any? ? @definition.specs_for(groups) : requested_specs Bundler.rubygems.replace_entrypoints(specs) ! specs.each do |spec| Bundler.rubygems.mark_loaded(spec) load_paths = spec.load_paths.reject {|p| $LOAD_PATH.include?(p)} $LOAD_PATH.unshift(*load_paths) end ! setup_manpath lock end > Runtime#setup *
  49. def setup(*groups) clean_load_path setup_environment ! groups.map! { |g| g.to_sym }

    specs = groups.any? ? @definition.specs_for(groups) : requested_specs Bundler.rubygems.replace_entrypoints(specs) ! specs.each do |spec| Bundler.rubygems.mark_loaded(spec) load_paths = spec.load_paths.reject {|p| $LOAD_PATH.include?(p)} $LOAD_PATH.unshift(*load_paths) end ! setup_manpath lock end > Runtime#setup *
  50. def Kernel.gem(dep, *reqs) dep = Gem::Dependency.new(dep, reqs) spec = Bundler.definition.specs.find

    { |s| s.name == dep.name } ! if spec.nil? raise Gem::LoadError, "#{dep.name} is not part of the bundle. Add it to Gemfile." elsif dep !~ spec raise Gem::LoadError, "can't activate #{dep}, already activated #{spec.full_name}." end ! true end gem 'hola', '~> 1.0' *
  51. ‣ Bundler builds a single runtime definition ‣ Configure and

    constrains the Rubygems environment ‣ Adds a fixed list of gem paths to LOAD_PATH ‣ Disables Rubygems Kernel integration
  52. ‣ An alternate path for GEM_HOME ‣ The same path

    prepended or set to GEM_PATH ‣ You can "stack" by adding multiple paths to GEM_PATH A gemset is just...
  53. 1. Configure runtime environment (shim) 2. Configure local environment 3.

    Configure sub-environment (subshell) Ways to implement:
  54. ! $ export GEM_HOME=/project/.gem $ export GEM_PATH=/project/.gem ! $ gem

    install hola $ ruby -r hola -e Hola.hi Configure local environment
  55. ! $ GEM_HOME=/project/.gem GEM_PATH=/project/.gem bash ! $ gem install hola

    $ ruby -r hola -e Hola.hi $ exit Configure sub-environment
  56. $ chgems /home/timuruski/project Entering /home/timuruski/project with gems in .gem/ruby/2.1.2/ ...

    ! $ gem install sinatra $ ruby app.rb ! $ exit Leaving /home/timuruski/project ...
  57. #!/usr/bin/env bash ! chgems_version="0.3.3" ! case "$1" in -V|--version) echo

    "chgems $chgems_version" exit ;; -h|--help) echo "usage: chgems [ROOT [COMMAND [ARGS]...]]" exit ;; esac ! if [[ -n "$1" ]]; then root="$1" shift && command=$@ else root="$PWD" command="" fi ! if [[ ! -d "$root" ]]; then echo "chgems: cannot use $root as a gem dir: No such directory" >&2 exit 1 fi ! cd "$root" ! eval `ruby - <<EOF require 'rubygems' puts "ruby_engine=#{defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'}" puts "ruby_version=#{RUBY_VERSION}" puts "gem_path=\"#{Gem.path.join(':')}\"" EOF` ! gem_dir="$PWD/.gem/$ruby_engine/$ruby_version" ! export PATH="$gem_dir/bin:$PATH" export GEM_HOME="$gem_dir" export GEM_PATH="$gem_dir:$gem_path" ! if [[ -n "${command[@]}" ]]; then eval $command else echo "Entering $PWD with gems in .gem/$ruby_engine/$ruby_version/ ..." $SHELL echo "Leaving $PWD ..." fi
  58. #!/usr/bin/env bash ! chgems_version="0.3.3" ! case "$1" in -V|--version) echo

    "chgems $chgems_version" exit ;; -h|--help) echo "usage: chgems [ROOT [COMMAND [ARGS]...]]" exit ;; esac ! if [[ -n "$1" ]]; then root="$1" shift && command=$@ else root="$PWD" command="" fi ! if [[ ! -d "$root" ]]; then echo "chgems: cannot use $root as a gem dir: No such directory" >&2 exit 1 fi ! cd "$root" ! eval `ruby - <<EOF require 'rubygems' puts "ruby_engine=#{defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'}" puts "ruby_version=#{RUBY_VERSION}" puts "gem_path=\"#{Gem.path.join(':')}\"" EOF` ! gem_dir="$PWD/.gem/$ruby_engine/$ruby_version" ! export PATH="$gem_dir/bin:$PATH" export GEM_HOME="$gem_dir" export GEM_PATH="$gem_dir:$gem_path" ! if [[ -n "${command[@]}" ]]; then eval $command else echo "Entering $PWD with gems in .gem/$ruby_engine/$ruby_version/ ..." $SHELL echo "Leaving $PWD ..." fi chgems_version="0.3.3" ! case "$1" in -V|--version) echo "chgems $chgems_version" exit ;; -h|--help) echo "usage: chgems [ROOT [COMMAND [ARGS]...]]" exit ;; esac
  59. #!/usr/bin/env bash ! chgems_version="0.3.3" ! case "$1" in -V|--version) echo

    "chgems $chgems_version" exit ;; -h|--help) echo "usage: chgems [ROOT [COMMAND [ARGS]...]]" exit ;; esac ! if [[ -n "$1" ]]; then root="$1" shift && command=$@ else root="$PWD" command="" fi ! if [[ ! -d "$root" ]]; then echo "chgems: cannot use $root as a gem dir: No such directory" >&2 exit 1 fi ! cd "$root" ! eval `ruby - <<EOF require 'rubygems' puts "ruby_engine=#{defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'}" puts "ruby_version=#{RUBY_VERSION}" puts "gem_path=\"#{Gem.path.join(':')}\"" EOF` ! gem_dir="$PWD/.gem/$ruby_engine/$ruby_version" ! export PATH="$gem_dir/bin:$PATH" export GEM_HOME="$gem_dir" export GEM_PATH="$gem_dir:$gem_path" ! if [[ -n "${command[@]}" ]]; then eval $command else echo "Entering $PWD with gems in .gem/$ruby_engine/$ruby_version/ ..." $SHELL echo "Leaving $PWD ..." fi if ARGV.first.present? root = ARGV.shift command = ARGV.dup else root = Dir.pwd command = [] end if [[ -n "$1" ]]; then root="$1" shift && command=$@ else root="$PWD" command="" fi
  60. #!/usr/bin/env bash ! chgems_version="0.3.3" ! case "$1" in -V|--version) echo

    "chgems $chgems_version" exit ;; -h|--help) echo "usage: chgems [ROOT [COMMAND [ARGS]...]]" exit ;; esac ! if [[ -n "$1" ]]; then root="$1" shift && command=$@ else root="$PWD" command="" fi ! if [[ ! -d "$root" ]]; then echo "chgems: cannot use $root as a gem dir: No such directory" >&2 exit 1 fi ! cd "$root" ! eval `ruby - <<EOF require 'rubygems' puts "ruby_engine=#{defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'}" puts "ruby_version=#{RUBY_VERSION}" puts "gem_path=\"#{Gem.path.join(':')}\"" EOF` ! gem_dir="$PWD/.gem/$ruby_engine/$ruby_version" ! export PATH="$gem_dir/bin:$PATH" export GEM_HOME="$gem_dir" export GEM_PATH="$gem_dir:$gem_path" ! if [[ -n "${command[@]}" ]]; then eval $command else echo "Entering $PWD with gems in .gem/$ruby_engine/$ruby_version/ ..." $SHELL echo "Leaving $PWD ..." fi if [[ ! -d "$root" ]]; then echo "chgems: cannot use $root as a gem dir: No such directory" >&2 exit 1 fi ! cd "$root"
  61. #!/usr/bin/env bash ! chgems_version="0.3.3" ! case "$1" in -V|--version) echo

    "chgems $chgems_version" exit ;; -h|--help) echo "usage: chgems [ROOT [COMMAND [ARGS]...]]" exit ;; esac ! if [[ -n "$1" ]]; then root="$1" shift && command=$@ else root="$PWD" command="" fi ! if [[ ! -d "$root" ]]; then echo "chgems: cannot use $root as a gem dir: No such directory" >&2 exit 1 fi ! cd "$root" ! eval `ruby - <<EOF require 'rubygems' puts "ruby_engine=#{defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'}" puts "ruby_version=#{RUBY_VERSION}" puts "gem_path=\"#{Gem.path.join(':')}\"" EOF` ! gem_dir="$PWD/.gem/$ruby_engine/$ruby_version" ! export PATH="$gem_dir/bin:$PATH" export GEM_HOME="$gem_dir" export GEM_PATH="$gem_dir:$gem_path" ! if [[ -n "${command[@]}" ]]; then eval $command else echo "Entering $PWD with gems in .gem/$ruby_engine/$ruby_version/ ..." $SHELL echo "Leaving $PWD ..." fi eval `ruby - <<EOF require 'rubygems' puts "ruby_engine=#{defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'}" puts "ruby_version=#{RUBY_VERSION}" puts "gem_path=\"#{Gem.path.join(':')}\"" EOF` ! gem_dir="$PWD/.gem/$ruby_engine/$ruby_version"
  62. #!/usr/bin/env bash ! chgems_version="0.3.3" ! case "$1" in -V|--version) echo

    "chgems $chgems_version" exit ;; -h|--help) echo "usage: chgems [ROOT [COMMAND [ARGS]...]]" exit ;; esac ! if [[ -n "$1" ]]; then root="$1" shift && command=$@ else root="$PWD" command="" fi ! if [[ ! -d "$root" ]]; then echo "chgems: cannot use $root as a gem dir: No such directory" >&2 exit 1 fi ! cd "$root" ! eval `ruby - <<EOF require 'rubygems' puts "ruby_engine=#{defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'}" puts "ruby_version=#{RUBY_VERSION}" puts "gem_path=\"#{Gem.path.join(':')}\"" EOF` ! gem_dir="$PWD/.gem/$ruby_engine/$ruby_version" ! export PATH="$gem_dir/bin:$PATH" export GEM_HOME="$gem_dir" export GEM_PATH="$gem_dir:$gem_path" ! if [[ -n "${command[@]}" ]]; then eval $command else echo "Entering $PWD with gems in .gem/$ruby_engine/$ruby_version/ ..." $SHELL echo "Leaving $PWD ..." fi export PATH="$gem_dir/bin:$PATH" export GEM_HOME="$gem_dir" export GEM_PATH="$gem_dir:$gem_path" ! if [[ -n "${command[@]}" ]]; then eval $command else echo "Entering $PWD with gems in .gem/$ruby_engine/$ruby_version/ ..." $SHELL echo "Leaving $PWD ..." fi
  63. $ rbenv local 2.1.2 ! $ cat .rbenv-gemsets project rails^D

    ! $ gem install sinatra $ ruby app.rb Primary gemset
  64. rbenv-gemset/bin/rbenv.d/exec/gemset.bash > $ gem install sinatra └── ~/.rbenv/shims/gem ├── libexec/rbenv-exec

    ├── libexec/hooks │ ├── plugins/rbenv-gemset/bin/rbenv.d/exec/gemset.bash │ └── plugins/rbenv-gemset/libexec/rbenv-gemset-file └── ~/.rbenv/rubies/2.1.2/bin/gem
  65. [[ $RBENV_GEMSET_ALREADY = yes ]] && return [[ $RBENV_GEMSET_ALREADY =

    "" ]] && export RBENV_GEMSET_ALREADY=yes ! unset GEM_HOME GEM_PATH ! if [ "$(rbenv-version-name)" = "system" ]; then RBENV_GEMSET_ROOT="$RBENV_GEMSET_SYSTEM_ROOT" else RBENV_GEMSET_ROOT="$(rbenv-prefix)/gemsets" fi ! RBENV_GEMSET_DIR="$(dirname "$(rbenv-gemset file 2>/dev/null)" 2>/dev/null)" project_gemset='^\..+' OLDIFS="$IFS" IFS=$' \t\n' for gemset in $(rbenv-gemset active 2>/dev/null); do if [[ $gemset =~ $project_gemset ]]; then path="${RBENV_GEMSET_DIR}/$gemset" else path="${RBENV_GEMSET_ROOT}/$gemset" fi PATH="$path/bin:$PATH" ! if [ -z "$GEM_HOME" ]; then GEM_HOME="$path" GEM_PATH="$path" else GEM_PATH="$GEM_PATH:$path" fi done IFS="$OLDIFS" ! GEM_PATH="$GEM_PATH:$("$(rbenv which gem)" env gemdir)" ! if [ -n "$GEM_HOME" ]; then export GEM_HOME GEM_PATH PATH fi
  66. [[ $RBENV_GEMSET_ALREADY = yes ]] && return [[ $RBENV_GEMSET_ALREADY =

    "" ]] && export RBENV_GEMSET_ALREADY=yes ! unset GEM_HOME GEM_PATH ! if [ "$(rbenv-version-name)" = "system" ]; then RBENV_GEMSET_ROOT="$RBENV_GEMSET_SYSTEM_ROOT" else RBENV_GEMSET_ROOT="$(rbenv-prefix)/gemsets" fi ! RBENV_GEMSET_DIR="$(dirname "$(rbenv-gemset file 2>/dev/null)" 2>/dev/null)" project_gemset='^\..+' OLDIFS="$IFS" IFS=$' \t\n' for gemset in $(rbenv-gemset active 2>/dev/null); do if [[ $gemset =~ $project_gemset ]]; then path="${RBENV_GEMSET_DIR}/$gemset" else path="${RBENV_GEMSET_ROOT}/$gemset" fi PATH="$path/bin:$PATH" ! if [ -z "$GEM_HOME" ]; then GEM_HOME="$path" GEM_PATH="$path" else GEM_PATH="$GEM_PATH:$path" fi done IFS="$OLDIFS" ! GEM_PATH="$GEM_PATH:$("$(rbenv which gem)" env gemdir)" ! if [ -n "$GEM_HOME" ]; then export GEM_HOME GEM_PATH PATH fi exec/gemset.bash [[ $RBENV_GEMSET_ALREADY = yes ]] && return [[ $RBENV_GEMSET_ALREADY = "" ]] && export RBENV_GEMSET_ALREADY=yes ! unset GEM_HOME GEM_PATH ! if [ "$(rbenv-version-name)" = "system" ]; then RBENV_GEMSET_ROOT="$RBENV_GEMSET_SYSTEM_ROOT" else RBENV_GEMSET_ROOT="$(rbenv-prefix)/gemsets" fi
  67. [[ $RBENV_GEMSET_ALREADY = yes ]] && return [[ $RBENV_GEMSET_ALREADY =

    "" ]] && export RBENV_GEMSET_ALREADY=yes ! unset GEM_HOME GEM_PATH ! if [ "$(rbenv-version-name)" = "system" ]; then RBENV_GEMSET_ROOT="$RBENV_GEMSET_SYSTEM_ROOT" else RBENV_GEMSET_ROOT="$(rbenv-prefix)/gemsets" fi ! RBENV_GEMSET_DIR="$(dirname "$(rbenv-gemset file 2>/dev/null)" 2>/dev/null)" project_gemset='^\..+' OLDIFS="$IFS" IFS=$' \t\n' for gemset in $(rbenv-gemset active 2>/dev/null); do if [[ $gemset =~ $project_gemset ]]; then path="${RBENV_GEMSET_DIR}/$gemset" else path="${RBENV_GEMSET_ROOT}/$gemset" fi PATH="$path/bin:$PATH" ! if [ -z "$GEM_HOME" ]; then GEM_HOME="$path" GEM_PATH="$path" else GEM_PATH="$GEM_PATH:$path" fi done IFS="$OLDIFS" ! GEM_PATH="$GEM_PATH:$("$(rbenv which gem)" env gemdir)" ! if [ -n "$GEM_HOME" ]; then export GEM_HOME GEM_PATH PATH fi RBENV_GEMSET_DIR="$(dirname "$(rbenv-gemset file)"" project_gemset='^\..+' OLDIFS="$IFS" IFS=$' \t\n' # ... IFS="$OLDIFS"
  68. [[ $RBENV_GEMSET_ALREADY = yes ]] && return [[ $RBENV_GEMSET_ALREADY =

    "" ]] && export RBENV_GEMSET_ALREADY=yes ! unset GEM_HOME GEM_PATH ! if [ "$(rbenv-version-name)" = "system" ]; then RBENV_GEMSET_ROOT="$RBENV_GEMSET_SYSTEM_ROOT" else RBENV_GEMSET_ROOT="$(rbenv-prefix)/gemsets" fi ! RBENV_GEMSET_DIR="$(dirname "$(rbenv-gemset file 2>/dev/null)" 2>/dev/null)" project_gemset='^\..+' OLDIFS="$IFS" IFS=$' \t\n' for gemset in $(rbenv-gemset active 2>/dev/null); do if [[ $gemset =~ $project_gemset ]]; then path="${RBENV_GEMSET_DIR}/$gemset" else path="${RBENV_GEMSET_ROOT}/$gemset" fi PATH="$path/bin:$PATH" ! if [ -z "$GEM_HOME" ]; then GEM_HOME="$path" GEM_PATH="$path" else GEM_PATH="$GEM_PATH:$path" fi done IFS="$OLDIFS" ! GEM_PATH="$GEM_PATH:$("$(rbenv which gem)" env gemdir)" ! if [ -n "$GEM_HOME" ]; then export GEM_HOME GEM_PATH PATH fi for gemset in $(rbenv-gemset active 2>/dev/null); do if [[ $gemset =~ $project_gemset ]]; then path="${RBENV_GEMSET_DIR}/$gemset" else path="${RBENV_GEMSET_ROOT}/$gemset" fi PATH="$path/bin:$PATH" ! if [ -z "$GEM_HOME" ]; then GEM_HOME="$path" GEM_PATH="$path" else GEM_PATH="$GEM_PATH:$path" fi done
  69. [[ $RBENV_GEMSET_ALREADY = yes ]] && return [[ $RBENV_GEMSET_ALREADY =

    "" ]] && export RBENV_GEMSET_ALREADY=yes ! unset GEM_HOME GEM_PATH ! if [ "$(rbenv-version-name)" = "system" ]; then RBENV_GEMSET_ROOT="$RBENV_GEMSET_SYSTEM_ROOT" else RBENV_GEMSET_ROOT="$(rbenv-prefix)/gemsets" fi ! RBENV_GEMSET_DIR="$(dirname "$(rbenv-gemset file 2>/dev/null)" 2>/dev/null)" project_gemset='^\..+' OLDIFS="$IFS" IFS=$' \t\n' for gemset in $(rbenv-gemset active 2>/dev/null); do if [[ $gemset =~ $project_gemset ]]; then path="${RBENV_GEMSET_DIR}/$gemset" else path="${RBENV_GEMSET_ROOT}/$gemset" fi PATH="$path/bin:$PATH" ! if [ -z "$GEM_HOME" ]; then GEM_HOME="$path" GEM_PATH="$path" else GEM_PATH="$GEM_PATH:$path" fi done IFS="$OLDIFS" ! GEM_PATH="$GEM_PATH:$("$(rbenv which gem)" env gemdir)" ! if [ -n "$GEM_HOME" ]; then export GEM_HOME GEM_PATH PATH fi GEM_PATH="$GEM_PATH:$("$(rbenv which gem)" env gemdir)" ! if [ -n "$GEM_HOME" ]; then export GEM_HOME GEM_PATH PATH fi
  70. $ rvm use ruby-2.1.2@project --create Using ruby-2.1.2 with gemset project

    ruby-2.1.2 - #gemset created /usr/local/rvm/gems/ruby-2.1.2@project ruby-2.1.2 - #generating project wrappers... ! $ gem install sinatra $ ruby app.rb
  71. __rvm_use_() { rvm_ruby_home="${rvm_ruby_home%%@*}" ! if [[ ! -d "$rvm_ruby_home" ]]

    then if [[ ${rvm_install_on_use_flag:-0} -eq 1 ]] then rvm_warn "$rvm_ruby_string is not installed - installing." __rvm_run_wrapper manage "install" "$rvm_ruby_string" else rvm_error "$rvm_ruby_string is not installed." rvm_log "To install do: 'rvm install $rvm_ruby_string'" export rvm_recommended_ruby="rvm install $rvm_ruby_string" return 1 fi fi ! __rvm_gemset_use_ensure || return $? ! export GEM_HOME GEM_PATH MY_RUBY_HOME RUBY_VERSION IRBRC GEM_HOME="$rvm_ruby_gem_home" GEM_PATH="$rvm_ruby_gem_path" MY_RUBY_HOME="$rvm_ruby_home" RUBY_VERSION="$rvm_ruby_string" IRBRC="$rvm_ruby_irbrc" unset BUNDLE_PATH # Ensure that BUNDLE_PATH is not set! ! # Handle MagLev pre-installed gems if [[ "maglev" == "$rvm_ruby_interpreter" ]] then GEM_PATH="$GEM_PATH:$MAGLEV_HOME/lib/maglev/gems/1.8/" fi ! [[ -n "${IRBRC:-}" ]] || unset IRBRC ! if (( ${rvm_use_flag:-1} >= 2 && ${rvm_internal_use_flag:-0} == 0 )) || (( ${rvm_use_flag:-1} == 1 && ${rvm_verbose_flag:-0} == 1 )) then rvm_log "Using ${GEM_HOME/${rvm_gemset_separator:-'@'}/ with gemset }" fi ! if [[ "$GEM_HOME" != "$rvm_ruby_global_gems_path" ]] then __path_prefix="$GEM_HOME/bin:$rvm_ruby_global_gems_path/bin:${rvm_ruby_binary%/*}:${rvm_bin_path}" else __path_prefix="$GEM_HOME/bin:${rvm_ruby_binary%/*}:${rvm_bin_path}" fi __path_suffix="" }
  72. __rvm_use_() { rvm_ruby_home="${rvm_ruby_home%%@*}" ! if [[ ! -d "$rvm_ruby_home" ]]

    then if [[ ${rvm_install_on_use_flag:-0} -eq 1 ]] then rvm_warn "$rvm_ruby_string is not installed - installing." __rvm_run_wrapper manage "install" "$rvm_ruby_string" else rvm_error "$rvm_ruby_string is not installed." rvm_log "To install do: 'rvm install $rvm_ruby_string'" export rvm_recommended_ruby="rvm install $rvm_ruby_string" return 1 fi fi ! __rvm_gemset_use_ensure || return $? ! export GEM_HOME GEM_PATH MY_RUBY_HOME RUBY_VERSION IRBRC GEM_HOME="$rvm_ruby_gem_home" GEM_PATH="$rvm_ruby_gem_path" MY_RUBY_HOME="$rvm_ruby_home" RUBY_VERSION="$rvm_ruby_string" IRBRC="$rvm_ruby_irbrc" unset BUNDLE_PATH # Ensure that BUNDLE_PATH is not set! ! # Handle MagLev pre-installed gems if [[ "maglev" == "$rvm_ruby_interpreter" ]] then GEM_PATH="$GEM_PATH:$MAGLEV_HOME/lib/maglev/gems/1.8/" fi ! [[ -n "${IRBRC:-}" ]] || unset IRBRC ! if (( ${rvm_use_flag:-1} >= 2 && ${rvm_internal_use_flag:-0} == 0 )) || (( ${rvm_use_flag:-1} == 1 && ${rvm_verbose_flag:-0} == 1 )) then rvm_log "Using ${GEM_HOME/${rvm_gemset_separator:-'@'}/ with gemset }" fi ! if [[ "$GEM_HOME" != "$rvm_ruby_global_gems_path" ]] then __path_prefix="$GEM_HOME/bin:$rvm_ruby_global_gems_path/bin:${rvm_ruby_binary%/*}:${rvm_bin_path}" else __path_prefix="$GEM_HOME/bin:${rvm_ruby_binary%/*}:${rvm_bin_path}" fi __path_suffix="" } export GEM_HOME GEM_PATH MY_RUBY_HOME RUBY_VERSION IRBRC GEM_HOME="$rvm_ruby_gem_home" GEM_PATH="$rvm_ruby_gem_path" MY_RUBY_HOME="$rvm_ruby_home" RUBY_VERSION="$rvm_ruby_string" IRBRC="$rvm_ruby_irbrc"
  73. $ ag "rvm_ruby_gem_(home|path)=" rvm ! scripts/cli 158: rvm_ruby_gem_home="$rvm_ruby_gem_home${rvm_gemset_separator:-"@"}$rvm_gemset_name" ! scripts/functions/manage/base

    44: rvm_ruby_gem_home="${rvm_ruby_gem_home%%${rvm_gemset_separator:-"@"}*}" ! scripts/functions/selector_gemsets 54: rvm_ruby_gem_home="${rvm_gems_path:-"$rvm_path/gems"}/$rvm_ruby_string" 60: rvm_ruby_gem_path="${rvm_ruby_gem_home}" 67: rvm_ruby_gem_home="${rvm_ruby_gem_home}${rvm_gemset_separator:-"@"}${rvm_gemset_name}" 71: rvm_ruby_gem_path="${rvm_ruby_gem_home}" 73: rvm_ruby_gem_path="${rvm_ruby_gem_home}:${rvm_ruby_global_gems_path}" ! scripts/gemsets 639: rvm_ruby_gem_home="${rvm_ruby_gem_home:-$GEM_HOME}" 644: rvm_ruby_gem_home="$(gem env home)" ! scripts/info 200: rvm_ruby_gem_home="${rvm_ruby_gem_home:-${GEM_HOME:-""}}"
  74. __rvm_gemset_select_only() { rvm_ruby_gem_home="${rvm_gems_path:-"$rvm_path/gems"}/$rvm_ruby_string" ! : rvm_ignore_gemsets_flag:${rvm_ignore_gemsets_flag:=0}: if (( rvm_ignore_gemsets_flag ))

    then rvm_ruby_global_gems_path="${rvm_ruby_gem_home}" rvm_ruby_gem_path="${rvm_ruby_gem_home}" rvm_gemset_name="" else rvm_ruby_global_gems_path="${rvm_ruby_gem_home}${rvm_gemset_separator:-"@"}global" ! __rvm_gemset_handle_default [[ -z "$rvm_gemset_name" ]] || rvm_ruby_gem_home="${rvm_ruby_gem_home}${rvm_gemset_separator:-"@"}${rvm_gemset_name}" ! if [[ "$rvm_gemset_name" == "global" ]] then rvm_ruby_gem_path="${rvm_ruby_gem_home}" else rvm_ruby_gem_path="${rvm_ruby_gem_home}:${rvm_ruby_global_gems_path}" fi fi ! if [[ -n "${rvm_gemset_name}" ]] then rvm_env_string="${rvm_ruby_string}@${rvm_gemset_name}" else rvm_env_string=${rvm_ruby_string} fi true # OSX --trace FIX }
  75. __rvm_gemset_select_only() { rvm_ruby_gem_home="${rvm_gems_path:-"$rvm_path/gems"}/$rvm_ruby_string" ! : rvm_ignore_gemsets_flag:${rvm_ignore_gemsets_flag:=0}: if (( rvm_ignore_gemsets_flag ))

    then rvm_ruby_global_gems_path="${rvm_ruby_gem_home}" rvm_ruby_gem_path="${rvm_ruby_gem_home}" rvm_gemset_name="" else rvm_ruby_global_gems_path="${rvm_ruby_gem_home}${rvm_gemset_separator:-"@"}global" ! __rvm_gemset_handle_default [[ -z "$rvm_gemset_name" ]] || rvm_ruby_gem_home="${rvm_ruby_gem_home}${rvm_gemset_separator:-"@"}${rvm_gemset_name}" ! if [[ "$rvm_gemset_name" == "global" ]] then rvm_ruby_gem_path="${rvm_ruby_gem_home}" else rvm_ruby_gem_path="${rvm_ruby_gem_home}:${rvm_ruby_global_gems_path}" fi fi ! if [[ -n "${rvm_gemset_name}" ]] then rvm_env_string="${rvm_ruby_string}@${rvm_gemset_name}" else rvm_env_string=${rvm_ruby_string} fi true # OSX --trace FIX } rvm_ruby_gem_home= "${rvm_gems_path:-"$rvm_path/gems"}/$rvm_ruby_string"
  76. __rvm_gemset_select_only() { rvm_ruby_gem_home="${rvm_gems_path:-"$rvm_path/gems"}/$rvm_ruby_string" ! : rvm_ignore_gemsets_flag:${rvm_ignore_gemsets_flag:=0}: if (( rvm_ignore_gemsets_flag ))

    then rvm_ruby_global_gems_path="${rvm_ruby_gem_home}" rvm_ruby_gem_path="${rvm_ruby_gem_home}" rvm_gemset_name="" else rvm_ruby_global_gems_path="${rvm_ruby_gem_home}${rvm_gemset_separator:-"@"}global" ! __rvm_gemset_handle_default [[ -z "$rvm_gemset_name" ]] || rvm_ruby_gem_home="${rvm_ruby_gem_home}${rvm_gemset_separator:-"@"}${rvm_gemset_name}" ! if [[ "$rvm_gemset_name" == "global" ]] then rvm_ruby_gem_path="${rvm_ruby_gem_home}" else rvm_ruby_gem_path="${rvm_ruby_gem_home}:${rvm_ruby_global_gems_path}" fi fi ! if [[ -n "${rvm_gemset_name}" ]] then rvm_env_string="${rvm_ruby_string}@${rvm_gemset_name}" else rvm_env_string=${rvm_ruby_string} fi true # OSX --trace FIX } if (( rvm_ignore_gemsets_flag )) then rvm_ruby_global_gems_path="${rvm_ruby_gem_home}" rvm_ruby_gem_path="${rvm_ruby_gem_home}" rvm_gemset_name="" else
  77. __rvm_gemset_select_only() { rvm_ruby_gem_home="${rvm_gems_path:-"$rvm_path/gems"}/$rvm_ruby_string" ! : rvm_ignore_gemsets_flag:${rvm_ignore_gemsets_flag:=0}: if (( rvm_ignore_gemsets_flag ))

    then rvm_ruby_global_gems_path="${rvm_ruby_gem_home}" rvm_ruby_gem_path="${rvm_ruby_gem_home}" rvm_gemset_name="" else rvm_ruby_global_gems_path="${rvm_ruby_gem_home}${rvm_gemset_separator:-"@"}global" ! __rvm_gemset_handle_default [[ -z "$rvm_gemset_name" ]] || rvm_ruby_gem_home="${rvm_ruby_gem_home}${rvm_gemset_separator:-"@"}${rvm_gemset_name}" ! if [[ "$rvm_gemset_name" == "global" ]] then rvm_ruby_gem_path="${rvm_ruby_gem_home}" else rvm_ruby_gem_path="${rvm_ruby_gem_home}:${rvm_ruby_global_gems_path}" fi fi ! if [[ -n "${rvm_gemset_name}" ]] then rvm_env_string="${rvm_ruby_string}@${rvm_gemset_name}" else rvm_env_string=${rvm_ruby_string} fi true # OSX --trace FIX } else rvm_ruby_global_gems_path="${rvm_ruby_gem_home}@global" ! __rvm_gemset_handle_default ! [[ -z "$rvm_gemset_name" ]] || rvm_ruby_gem_home="${rvm_ruby_gem_home}@${rvm_gemset_name}" ! if [[ "$rvm_gemset_name" == "global" ]] then rvm_ruby_gem_path="${rvm_ruby_gem_home}" else rvm_ruby_gem_path="${rvm_ruby_gem_home}:${rvm_ruby_global_gems_path}" fi fi
  78. __rvm_use_() { rvm_ruby_home="${rvm_ruby_home%%@*}" ! if [[ ! -d "$rvm_ruby_home" ]]

    then if [[ ${rvm_install_on_use_flag:-0} -eq 1 ]] then rvm_warn "$rvm_ruby_string is not installed - installing." __rvm_run_wrapper manage "install" "$rvm_ruby_string" else rvm_error "$rvm_ruby_string is not installed." rvm_log "To install do: 'rvm install $rvm_ruby_string'" export rvm_recommended_ruby="rvm install $rvm_ruby_string" return 1 fi fi ! __rvm_gemset_use_ensure || return $? ! export GEM_HOME GEM_PATH MY_RUBY_HOME RUBY_VERSION IRBRC GEM_HOME="$rvm_ruby_gem_home" GEM_PATH="$rvm_ruby_gem_path" MY_RUBY_HOME="$rvm_ruby_home" RUBY_VERSION="$rvm_ruby_string" IRBRC="$rvm_ruby_irbrc" unset BUNDLE_PATH # Ensure that BUNDLE_PATH is not set! ! # Handle MagLev pre-installed gems if [[ "maglev" == "$rvm_ruby_interpreter" ]] then GEM_PATH="$GEM_PATH:$MAGLEV_HOME/lib/maglev/gems/1.8/" fi ! [[ -n "${IRBRC:-}" ]] || unset IRBRC ! if (( ${rvm_use_flag:-1} >= 2 && ${rvm_internal_use_flag:-0} == 0 )) || (( ${rvm_use_flag:-1} == 1 && ${rvm_verbose_flag:-0} == 1 )) then rvm_log "Using ${GEM_HOME/${rvm_gemset_separator:-'@'}/ with gemset }" fi ! if [[ "$GEM_HOME" != "$rvm_ruby_global_gems_path" ]] then __path_prefix="$GEM_HOME/bin:$rvm_ruby_global_gems_path/bin:${rvm_ruby_binary%/*}:${rvm_bin_path}" else __path_prefix="$GEM_HOME/bin:${rvm_ruby_binary%/*}:${rvm_bin_path}" fi __path_suffix="" } export GEM_HOME GEM_PATH MY_RUBY_HOME RUBY_VERSION IRBRC GEM_HOME="$rvm_ruby_gem_home" GEM_PATH="$rvm_ruby_gem_path" MY_RUBY_HOME="$rvm_ruby_home" RUBY_VERSION="$rvm_ruby_string" IRBRC="$rvm_ruby_irbrc"
  79. ‣ Introduction ‣ Part 1: Gems primer ‣ Part 2:

    Rubygems ‣ Part 3: Bundler ‣ Part 4: Gemsets ‣ Conclusion *You are here