class Bundix

Constants

NIX_HASH
NIX_INSTANTIATE
NIX_PREFETCH_GIT
NIX_PREFETCH_URL
NIX_SHELL
PLATFORM_MAPPING
SHA256_32
VERSION

Attributes

fetcher[RW]
options[R]

Public Class Methods

new(options) click to toggle source
# File lib/bundix.rb, line 33
def initialize(options)
  @options = { quiet: false, tempfile: nil }.merge(options)
  @fetcher = Fetcher.new
end
sh(*args, &block) click to toggle source
# File lib/bundix.rb, line 175
def self.sh(*args, &block)
  out, status = Open3.capture2(*args)
  unless block_given? ? block.call(status, out) : status.success?
    puts "$ #{args.join(' ')}" if $VERBOSE
    puts out if $VERBOSE
    fail "command execution failed: #{status}"
  end
  out
end

Public Instance Methods

build_depcache(lock) click to toggle source
# File lib/bundix.rb, line 121
def build_depcache(lock)
  definition = Bundler::Definition.build(options[:gemfile], options[:lockfile], false)
  dep_cache = {}

  definition.dependencies.each do |dep|
    dep_cache[dep.name] = dep
  end

  lock.specs.each do |spec|
    dep_cache[spec.name] ||= Dependency.new(spec.name, nil, {})
  end

  begin
    changed = false
    lock.specs.each do |spec|
      as_dep = dep_cache.fetch(spec.name)

      spec.dependencies.each do |dep|
        cached = dep_cache.fetch(dep.name) do |name|
          if name != "bundler"
            raise KeyError, "Gem dependency '#{name}' not specified in #{lockfile}"
          end
          dep_cache[name] = Dependency.new(name, lock.bundler_version, {})
        end

        if !((as_dep.groups - cached.groups) - [:default]).empty? or !(as_dep.platforms - cached.platforms).empty?
          changed = true
          dep_cache[cached.name] = (Dependency.new(cached.name, nil, {
            "group" => as_dep.groups | cached.groups,
            "platforms" => as_dep.platforms | cached.platforms
          }))

          cc = dep_cache[cached.name]
        end
      end
    end
  end while changed

  return dep_cache
end
convert() click to toggle source
# File lib/bundix.rb, line 38
def convert
  cache = parse_gemset
  lock = parse_lockfile
  dep_cache = build_depcache(lock)

  # reverse so git comes last
  lock.specs.reverse_each.with_object({}) do |spec, gems|
    gem = find_cached_spec(spec, cache) || convert_spec(spec, cache, dep_cache)
    gems.merge!(gem)

    if spec.dependencies.any?
      gems[spec.name]['dependencies'] = spec.dependencies.map(&:name) - ['bundler']
    end
  end
end
convert_spec(spec, cache, dep_cache) click to toggle source
# File lib/bundix.rb, line 88
def convert_spec(spec, cache, dep_cache)
  {
    spec.name => {
      version: spec.version.to_s,
      source: Source.new(spec, fetcher).convert
    }.merge(platforms(spec, dep_cache)).merge(groups(spec, dep_cache))
  }
rescue => ex
  warn "Skipping #{spec.name}: #{ex}"
  puts ex.backtrace
  {spec.name => {}}
end
find_cached_spec(spec, cache) click to toggle source
# File lib/bundix.rb, line 101
def find_cached_spec(spec, cache)
  name, cached = cache.find{|k, v|
    next unless k == spec.name
    next unless cached_source = v['source']

    case spec_source = spec.source
    when Bundler::Source::Git
      next unless cached_source['type'] == 'git'
      next unless cached_rev = cached_source['rev']
      next unless spec_rev = spec_source.options['revision']
      spec_rev == cached_rev
    when Bundler::Source::Rubygems
      next unless cached_source['type'] == 'gem'
      v['version'] == spec.version.to_s
    end
  }

  {name => cached} if cached
end
groups(spec, dep_cache) click to toggle source
# File lib/bundix.rb, line 54
def groups(spec, dep_cache)
  {groups: dep_cache.fetch(spec.name).groups}
end
parse_gemset() click to toggle source
# File lib/bundix.rb, line 162
def parse_gemset
  path = File.expand_path(options[:gemset])
  return {} unless File.file?(path)
  json = Bundix.sh(NIX_INSTANTIATE, '--eval', '-E', %(
    builtins.toJSON (import #{Nixer.serialize(path)}))
  )
  JSON.parse(json.strip.gsub(/\\"/, '"')[1..-2])
end
parse_lockfile() click to toggle source
# File lib/bundix.rb, line 171
def parse_lockfile
  Bundler::LockfileParser.new(File.read(options[:lockfile]))
end
platforms(spec, dep_cache) click to toggle source
# File lib/bundix.rb, line 79
def platforms(spec, dep_cache)
  # c.f. Bundler::CurrentRuby
  platforms = dep_cache.fetch(spec.name).platforms.map do |platform_name|
    PLATFORM_MAPPING[platform_name.to_s]
  end.flatten

  {platforms: platforms}
end