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

How Does Bundle Install Work?

How Does Bundle Install Work?

Bundler is part of every ruby developers workflow but have you ever wondered what happens when you run bundle install? We'll take a look at the parts that make up Bundler such as the Bundler Definition, CLI, RubyGems and the version resolver. We'll also take a quick look at the upcoming changes for Bundler 2

Colby Swandale

August 30, 2017
Tweet

More Decks by Colby Swandale

Other Decks in Technology

Transcript

  1. › bundle install Using bundler 1.15.4 Using diff-lcs 1.3 Using

    rack 2.0.3 Using rspec-support 3.6.0 Using rspec-core 3.6.0 Using rspec-expectations 3.6.0 Using rspec-mocks 3.6.0 Using rspec 3.6.0 Bundle complete! 2 Gemfile dependencies, 8 gems now installed. Use `bundle info [gemname]` to see where a bundled gem is installed.
  2. $ ls lib/bundler/cli add.rb common.rb gem.rb issue.rb package.rb update.rb binstubs.rb

    config.rb info.rb list.rb platform.rb viz.rb cache.rb console.rb init.rb lock.rb plugin.rb check.rb doctor.rb inject.rb open.rb pristine.rb clean.rb exec.rb install.rb outdated.rb show.rb
  3. # lib/bundler/cli/install.rb 
 module Bundler class CLI::Install attr_reader :options def

    initialize(options) @options = options end def run Bundler.ui.level = "error" if options[:quiet] warn_if_root normalize_groups ..
  4. Holds all the information and operations about your Gemfile &

    Gemfile.lock Definition Deps Sources Groups Platforms Runtime
  5. source 'https://rubygems.org' gem "rails", "4.2.8" gem "addressable", "2.4.0" if RUBY_VERSION

    < "2.0" require 'erb' require 'yaml' database_file = File.join(File.dirname(__FILE__), "config/database.yml") if File.exist?(database_file) database_config = YAML::load(ERB.new(IO.read(database_file)).result) adapters = database_config.values.map {|c| c['adapter']}.compact.uniq if adapters.any? adapters.each do |adapter| case adapter when 'mysql2' gem "mysql2", "~> 0.4.6", :platforms => [:mri, :mingw, :x64_mingw] when /postgresql/ gem "pg", "~> 0.18.1", :platforms => [:mri, :mingw, :x64_mingw] when /sqlite3/ gem "sqlite3", (RUBY_VERSION < "2.0" && RUBY_PLATFORM =~ /mingw/ ? "1.3.12" : "~>1.3.12"), :platforms => [:mri, :mingw, :x64_mingw] when /sqlserver/ gem "tiny_tds", (RUBY_VERSION >= "2.0" ? "~> 1.0.5" : "~> 0.7.0"), :platforms => [:mri, :mingw, :x64_mingw] gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw, :x64_mingw] else warn("Unknown database adapter `#{adapter}` found in config/database.yml, use Gemfile.local to load your own database gems") end end else warn("No adapter found in config/database.yml, please configure it first") end else warn("Please configure your config/database.yml first") end
  6. DSL

  7. # lib/bundler/dsl.rb module Bundler class Dsl def self.evaluate(gemfile, lockfile, unlock)

    builder = new builder.eval_gemfile(gemfile) builder.to_definition(lockfile, unlock) end end end
  8. # lib/bundler/lockfile_parser.rb lockfile.split(/(?:\r?\n)+/).each do |line| if SOURCE.include?(line) @state = :source

    parse_source(line) elsif line == DEPENDENCIES @state = :dependency elsif line == PLATFORMS @state = :platform elsif line == RUBY @state = :ruby elsif line == BUNDLED @state = :bundled_with elsif line =~ /^[^\s]/ @state = nil elsif @state send("parse_#{@state}", line) end end
  9. GEM remote: https://rubygems.org/ specs: actioncable (5.1.3) actionpack (= 5.1.3) nio4r

    (~> 2.0) nio4r (2.1.0) actionpack (5.1.3) rails (5.1.3) actioncable (= 5.1.3) DEPENDENCIES rails (~> 5.1.3)
  10. › curl https://index.rubygems.org/versions | head -n 30 - 1 05d0116933ba44b0b5d0ee19bfd35ccc

    .cat 0.0.1 631fd60a806eaf5026c86fff3155c289 0mq 0.1.0,0.1.1,0.1.2,0.2.0,0.2.1,0.3.0,0.4.0,0.4.1,0.5.0,0.5.1,0.5.2,0.5.3 61 0xffffff 0.0.1,0.1.0 0a4a9aeae24152cdb467be02f40482f9 10to1-crack 0.1.1,0.1.2,0.1.3 e7218e76477e2137355d2e7ded094925 1234567890_ 1.0,1.1 233e818c2db65d2dad9f9ea9a27b1a30 12_hour_time 0.0.2,0.0.3,0.0.4 4e58bc03e301f704950410b713c20b69 16watts-fluently 0.3.0,0.3.1 555088e2b18e97e0293cab1d90dbb0d2 189seg 0.0.1 c4d329f7d3eb88b6e602358968be0242 196demo 0.0.0 e00c558565f7b03a438fbd93d854b7de 1_as_identity_function 1.0.0,1.0.1 bee2f0fbbc3c5c83008c0b8fc64cb168 1and1 1.1 1853e4495b036ddc5da2035523d48f0d 1hdoc 0.1.3,0.2.0,0.2.2,0.2.3,0.2.4 7076f29c196df12047a3700c4d6e5915 1pass 0.1.0,0.1.1,0.1.2 d209547aae4b8f3d67123f18f738ac99 21-day-challenge-countdown 0.1.0,0.1.1,0.1.2 57e8873fe713063f4e54e85bbbd709bb 24games 0.2.1,0.2.2,0.2.3,0.2.4 9e4d164dec466b7fe285653289e8468f 24point 0.0.1,0.0.2 80d1d0efb3811e31f40160237cc9c115 2DArray 0.1.0,0.1.2,0.1.3,0.1.5,0.1.6 848ea9e77b596cad24688a44c57a25c3 2Performant 0.0.1,0.0.2,0.0.3,0.0.4,0.0.5,0.0.6,0.0.7,0.0.8,0.1.0,0.1.1,0.1.3
  11. › curl https://index.rubygems.org/info/activerecord 5.1.0 activemodel:= 5.1.0,activesupport:= 5.1.0,arel:~> 8.0|checksum:b57713e8d 5.0.3 activemodel:=

    5.0.3,activesupport:= 5.0.3,arel:~> 7.0|checksum:6a38454ba 5.1.1 activemodel:= 5.1.1,activesupport:= 5.1.1,arel:~> 8.0|checksum:61c0dba29 4.2.9.rc1 activemodel:= 4.2.9.rc1,activesupport:= 4.2.9.rc1,arel:~> 6.0|checks 5.0.4.rc1 activemodel:= 5.0.4.rc1,activesupport:= 5.0.4.rc1,arel:~> 7.0|checks 5.0.4 activemodel:= 5.0.4,activesupport:= 5.0.4,arel:~> 7.0|checksum:d82ba1b35 4.2.9.rc2 activemodel:= 4.2.9.rc2,activesupport:= 4.2.9.rc2,arel:~> 6.0|checks 5.1.2.rc1 activemodel:= 5.1.2.rc1,activesupport:= 5.1.2.rc1,arel:~> 8.0|checks 4.2.9 activemodel:= 4.2.9,activesupport:= 4.2.9,arel:~> 6.0|checksum:0be77a1f7 5.1.2 activemodel:= 5.1.2,activesupport:= 5.1.2,arel:~> 8.0|checksum:a3757003b 5.1.3.rc1 activemodel:= 5.1.3.rc1,activesupport:= 5.1.3.rc1,arel:~> 8.0|checks 5.0.5.rc1 activemodel:= 5.0.5.rc1,activesupport:= 5.0.5.rc1,arel:~> 7.0|checks 5.1.3.rc2 activemodel:= 5.1.3.rc2,activesupport:= 5.1.3.rc2,arel:~> 8.0|checks 5.0.5.rc2 activemodel:= 5.0.5.rc2,activesupport:= 5.0.5.rc2,arel:~> 7.0|checks 5.0.5 activemodel:= 5.0.5,activesupport:= 5.0.5,arel:~> 7.0|checksum:89651a138 5.1.3.rc3 activemodel:= 5.1.3.rc3,activesupport:= 5.1.3.rc3,arel:~> 8.0|checks 5.1.3 activemodel:= 5.1.3,activesupport:= 5.1.3,arel:~> 8.0|checksum:e83b04f42 5.0.6.rc1 activemodel:= 5.0.6.rc1,activesupport:= 5.0.6.rc1,arel:~> 7.0|checks 5.1.4.rc1 activemodel:= 5.1.4.rc1,activesupport:= 5.1.4.rc1,arel:~> 8.0|checks
  12. # lib/bundler/source/rubygems.rb installed_spec = Bundler::RubyGemsGemInstaller.at(path, :install_dir => install_path.to_s, :bin_dir =>

    bin_path.to_s, :ignore_dependencies => true, :wrappers => true, :env_shebang => true, :build_args => opts[:build_args], :bundler_expected_checksum => spec.respond_to?(:checksum) && spec.checksum, :bundler_extension_cache_path => extension_cache_path(spec) ).install