From 99570e5d2c7c3f4294028a244c55bd643d1a06ce Mon Sep 17 00:00:00 2001 From: Michael Fellinger Date: Mon, 18 Apr 2016 00:30:21 +0200 Subject: [PATCH 1/5] resolve Gemfile to support groups --- bin/bundix | 161 +++++++++++++------------- default.nix | 2 +- lib/bundix.rb | 65 ++++++----- lib/bundix/gemfile_dependency_tree.rb | 66 +++++++++++ lib/bundix/source.rb | 41 ++++--- 5 files changed, 212 insertions(+), 123 deletions(-) create mode 100644 lib/bundix/gemfile_dependency_tree.rb diff --git a/bin/bundix b/bin/bundix index 3df5754..13b4edf 100755 --- a/bin/bundix +++ b/bin/bundix @@ -1,92 +1,93 @@ -#!/usr/bin/env ruby +#! /usr/bin/env ruby require 'optparse' require 'tmpdir' require 'pathname' -require_relative '../lib/bundix' - -options = { - ruby: 'ruby', - bundle_pack_path: 'vendor/bundle', - lockfile: 'Gemfile.lock', - gemset: 'gemset.nix' -} - -op = OptionParser.new do |o| - o.on '-m', '--magic', 'lock, pack, and write dependencies' do - options[:magic] = true - end - - o.on '--ruby=ruby', 'ruby version to use for magic and init, defaults to latest' do |value| - options[:ruby] = value - end - - o.on '--bundle-pack-path=vendor/bundle', "path to pack the magic" do |value| - options[:bundle_pack_path] = value +require_relative '../lib/bundix/version' + +class Bundix + OPTIONS = { + ruby: 'ruby', + bundle_pack_path: 'vendor/bundle', + gemfile: 'Gemfile', + lockfile: 'Gemfile.lock', + gemset: 'gemset.nix', + lock: false, + cache: false, + groups: [] + } + + op = OptionParser.new do |o| + o.on '--ruby=ruby', 'ruby version to use for init, defaults to latest' do |value| + OPTIONS[:ruby] = value + end + + o.on '-i', '--init', "initialize a new shell.nix for nix-shell (won't overwrite old ones)" do + OPTIONS[:init] = true + end + + o.on '--gemset=gemset.nix', 'path to the gemset.nix' do |value| + OPTIONS[:gemset] = File.expand_path(value) + end + + o.on '--gemfile=Gemfile', 'path to the Gemfile' do |value| + OPTIONS[:gemfile] = File.expand_path(value) + end + + o.on '--lockfile=Gemfile.lock', 'path to the Gemfile.lock' do |value| + OPTIONS[:lockfile] = File.expand_path(value) + end + + o.on '-l', '--lock', 'create Gemfile.lock for given groups' do |groups| + OPTIONS[:lock] = true + end + + o.on '-c', '--cache', 'resolve dependencies from cache' do + OPTIONS[:cache] = true + end + + o.on '-g', '--groups [GROUP1,GROUP2]', Array, 'only use these groups for the lockfile' do |groups| + OPTIONS[:groups].concat groups.map(&:to_sym) + end + + o.on '-q', '--quiet', 'only output errors' do + OPTIONS[:quiet] = true + end + + o.on '-v', '--version', 'show the version of bundix' do + puts Bundix::VERSION + exit + end end - o.on '-i', '--init', "initialize a new shell.nix for nix-shell (won't overwrite old ones)" do - options[:init] = true + op.parse! + $VERBOSE = !OPTIONS[:quiet] + + require_relative '../lib/bundix' + + if OPTIONS[:init] + if File.file?('shell.nix') + warn "won't override existing shell.nix" + else + shell_nix = File.read(File.expand_path('../template/shell.nix', __dir__)) + shell_nix.gsub!('PROJECT', File.basename(Dir.pwd)) + shell_nix.gsub!('RUBY', OPTIONS[:ruby]) + shell_nix.gsub!('LOCKFILE', "./#{Pathname(OPTIONS[:lockfile]).relative_path_from(Pathname('./'))}") + shell_nix.gsub!('GEMSET', "./#{Pathname(OPTIONS[:gemset]).relative_path_from(Pathname('./'))}") + File.write('shell.nix', shell_nix) + end end - o.on '--gemset=gemset.nix', 'path to the gemset.nix' do |value| - options[:gemset] = File.expand_path(value) - end - - o.on '--lockfile=Gemfile.lock', 'path to the Gemfile.lock' do |value| - options[:lockfile] = File.expand_path(value) - end - - o.on '-d', '--dependencies', 'include gem dependencies' do - options[:deps] = true - end + gemset = Bundix.new(OPTIONS).convert - o.on '-q', '--quiet', 'only output errors' do - options[:quiet] = true + tempfile = Tempfile.new('gemset.nix', encoding: 'UTF-8') + begin + Bundix.object2nix(gemset, 2, tempfile) + tempfile.flush + FileUtils.cp(tempfile.path, OPTIONS[:gemset]) + ensure + tempfile.close! + tempfile.unlink end - - o.on '-v', '--version', 'show the version of bundix' do - puts Bundix::VERSION - exit - end -end - -op.parse! -$VERBOSE = !options[:quiet] - -if options[:magic] - fail unless system( - Bundix::NIX_SHELL, '-p', options[:ruby], - "bundler.override { ruby = #{options[:ruby]}; }", - "--command", "bundle lock --lockfile=#{options[:lockfile]}") - fail unless system( - Bundix::NIX_SHELL, '-p', options[:ruby], - "bundler.override { ruby = #{options[:ruby]}; }", - "--command", "bundle pack --all --path #{options[:bundle_pack_path]}") -end - -if options[:init] - if File.file?('shell.nix') - warn "won't override existing shell.nix" - else - shell_nix = File.read(File.expand_path('../template/shell.nix', __dir__)) - shell_nix.gsub!('PROJECT', File.basename(Dir.pwd)) - shell_nix.gsub!('RUBY', options[:ruby]) - shell_nix.gsub!('LOCKFILE', "./#{Pathname(options[:lockfile]).relative_path_from(Pathname('./'))}") - shell_nix.gsub!('GEMSET', "./#{Pathname(options[:gemset]).relative_path_from(Pathname('./'))}") - File.write('shell.nix', shell_nix) - end -end - -gemset = Bundix.new(options).convert - -tempfile = Tempfile.new('gemset.nix', encoding: 'UTF-8') -begin - Bundix.object2nix(gemset, 2, tempfile) - tempfile.flush - FileUtils.cp(tempfile.path, options[:gemset]) -ensure - tempfile.close! - tempfile.unlink end diff --git a/default.nix b/default.nix index 12d73bf..4abcc70 100644 --- a/default.nix +++ b/default.nix @@ -11,5 +11,5 @@ let }; in stdenv.mkDerivation { name = "bundix"; - buildInputs = [bundix]; + buildInputs = [bundler bundix]; } diff --git a/lib/bundix.rb b/lib/bundix.rb index da410a1..cc353af 100755 --- a/lib/bundix.rb +++ b/lib/bundix.rb @@ -2,20 +2,21 @@ require 'json' require 'open-uri' require 'open3' +require 'tsort' +require 'set' require 'pp' require_relative 'bundix/version' require_relative 'bundix/source' +require_relative 'bundix/gemfile_dependency_tree' class Bundix NIX_INSTANTIATE = 'nix-instantiate' NIX_PREFETCH_URL = 'nix-prefetch-url' NIX_PREFETCH_GIT = 'nix-prefetch-git' - NIX_HASH = 'nix-hash' NIX_SHELL = 'nix-shell' SHA256_32 = %r(^[a-z0-9]{52}$) - SHA256_16 = %r(^[a-f0-9]{64}$) attr_reader :options @@ -23,52 +24,62 @@ def initialize(options) @options = { quiet: false, tempfile: nil, + gemfile: Bundler.default_gemfile, + lockfile: Bundler.default_lockfile, + lock: false, deps: false }.merge(options) end def convert - cache = parse_gemset - lock = parse_lockfile + @cache = parse_gemset + puts "resolving dependencies..." if $VERBOSE + tree = GemfileDependencyTree.run(options) + gems = {} + + tree.each do |name, node| + gems[name] = convert_one(name, node) + @cache[name] = gems[name] + end - # reverse so git comes last - lock.specs.reverse_each.with_object({}) do |spec, gems| - gem = find_cached_spec(spec, cache) || convert_spec(spec, cache) - gems.merge!(gem) + gems + end - if options[:deps] && spec.dependencies.any? - gems[spec.name]['dependencies'] = spec.dependencies.map(&:name) - ['bundler'] - end - end + def convert_one(name, node) + find_cached_spec(node) || convert_spec(node) end - def convert_spec(spec, cache) - {spec.name => {version: spec.version.to_s, source: Source.new(spec).convert}} + def convert_spec(spec, definition = nil) + { + 'version' => spec.version.to_s, + 'groups' => spec.groups, + 'dependencies' => spec.dependencies, + 'source' => Source.new(spec, definition).convert + } rescue => ex warn "Skipping #{spec.name}: #{ex}" puts ex.backtrace - {spec.name => {}} + {} end - def find_cached_spec(spec, cache) - name, cached = cache.find{|k, v| - next unless k == spec.name + def find_cached_spec(node) + _, cached = @cache.find{|k, v| + next unless k == node.name next unless cached_source = v['source'] - case spec_source = spec.source + case spec_source = node.source when Bundler::Source::Git next unless cached_rev = cached_source['rev'] next unless spec_rev = spec_source.options['revision'] spec_rev == cached_rev when Bundler::Source::Rubygems - v['version'] == spec.version.to_s + v['version'] == node.version end } - {name => cached} if cached + cached end - def parse_gemset path = File.expand_path(options[:gemset]) return {} unless File.file?(path) @@ -77,10 +88,6 @@ def parse_gemset JSON.parse(json.strip.gsub(/\\"/, '"')[1..-2]) end - def parse_lockfile - Bundler::LockfileParser.new(File.read(options[:lockfile])) - end - def self.object2nix(obj, level = 2, out = '') case obj when Hash @@ -97,7 +104,7 @@ def self.object2nix(obj, level = 2, out = '') out << (v.is_a?(Hash) ? "\n" : ";\n") end out << (' ' * (level - 2)) << (level == 2 ? '}' : '};') - when Array + when Array, Set out << '[' << obj.sort.map{|o| o.to_str.dump }.join(' ') << ']' when String out << obj.dump @@ -110,6 +117,10 @@ def self.object2nix(obj, level = 2, out = '') end end + def sh(*args) + self.class.sh(*args) + end + def self.sh(*args) out, status = Open3.capture2e(*args) unless status.success? diff --git a/lib/bundix/gemfile_dependency_tree.rb b/lib/bundix/gemfile_dependency_tree.rb new file mode 100644 index 0000000..c0e5928 --- /dev/null +++ b/lib/bundix/gemfile_dependency_tree.rb @@ -0,0 +1,66 @@ +require 'bundler' + +class GemfileDependencyTree + Spec = Struct.new(:name, :groups, :source, :version, :dependencies) + + def self.run(options) + definitions = Bundler::Dsl.evaluate(options.fetch(:gemfile), nil, {}) + specs = + if options.fetch(:cache) + definitions.resolve_with_cache! + else + definitions.resolve_remotely! + end + definitions.lock(Bundler.default_lockfile) if options.fetch(:lock) + + result = {} + definitions.dependencies.each do |dependency| + new(dependency, specs, dependency.groups).run([], result) + end + + result + end + + def initialize(dep, specs, groups) + @dep = dep + @spec = specs.find{|s| s.name == dep.name } + @groups = groups.map(&:to_s) + @children = dependencies.map{|d| self.class.new(d, specs, groups) } + end + + def run(seen = [], result = {}) + children = @children.reject{|c| seen.include?(c.name) } + add_group(result, @spec) + + children.each do |child| + seen << child.name + child.run(seen, result) + end + + result + end + + def name + @spec.name + end + + private + + def add_group(result, dep) + if result[dep.name] + result[dep.name].groups |= @groups + else + result[dep.name] = Spec.new( + dep.name, + @groups, + dep.source, + dep.version.to_s, + dependencies.map(&:name) + ) + end + end + + def dependencies + @spec.dependencies.reject{|d| d.type == :development } + end +end diff --git a/lib/bundix/source.rb b/lib/bundix/source.rb index 7e3d482..874e168 100644 --- a/lib/bundix/source.rb +++ b/lib/bundix/source.rb @@ -1,5 +1,5 @@ class Bundix - class Source < Struct.new(:spec) + class Source < Struct.new(:spec, :definition) def convert case spec.source when Bundler::Source::Rubygems @@ -58,32 +58,43 @@ def fetch_remote_hash(spec, remote) end def convert_rubygems - remotes = spec.source.remotes.map{|remote| remote.to_s.sub(/\/+$/, '') } hash = fetch_local_hash(spec) - remote, hash = fetch_remotes_hash(spec, remotes) unless hash - hash = sh(NIX_HASH, '--type', 'sha256', '--to-base32', hash)[SHA256_32] + + if definition && definition.source + remotes = [definition.source.remotes.first.to_s.sub(/\/+$/, '')] + else + remotes = spec.source.remotes.map{|r| r.to_s.sub(/\/+$/, '') } + end + + _, hash = fetch_remotes_hash(spec, remotes) unless hash fail "couldn't fetch hash for #{spec.name}-#{spec.version}" unless hash puts "#{hash} => #{spec.name}-#{spec.version}.gem" if $VERBOSE - { type: 'gem', - remotes: (remote ? [remote] : remotes), - sha256: hash } + { 'type' => 'gem', + 'remotes' => remotes, + 'sha256' => hash } end def convert_git - revision = spec.source.options.fetch('revision') - uri = spec.source.options.fetch('uri') - output = nix_prefetch_git(uri, revision) + if definition + rev = definition.source.revision + uri = definition.source.uri + else + rev = spec.source.revision + uri = spec.source.uri + end + + output = nix_prefetch_git(uri, rev) # FIXME: this is a hack, we should separate $stdout/$stderr in the sh call hash = JSON.parse(output[/({[^}]+})\s*\z/m])['sha256'] fail "couldn't fetch hash for #{spec.name}-#{spec.version}" unless hash puts "#{hash} => #{uri}" if $VERBOSE - { type: 'git', - url: uri.to_s, - rev: revision, - sha256: hash, - fetchSubmodules: false } + { 'type' => 'git', + 'url' => uri, + 'rev' => rev, + 'sha256' => hash, + 'fetchSubmodules' => false } end end end From 84da0ad73a8e6cbc39a2ed1c325a42f389fc25a0 Mon Sep 17 00:00:00 2001 From: Michael Fellinger Date: Mon, 18 Apr 2016 10:49:31 +0200 Subject: [PATCH 2/5] a bit of cleanup --- bin/bundix | 12 ++++++++---- lib/bundix.rb | 12 +----------- lib/bundix/gemfile_dependency_tree.rb | 5 +++-- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/bin/bundix b/bin/bundix index 13b4edf..a2266fc 100755 --- a/bin/bundix +++ b/bin/bundix @@ -4,17 +4,20 @@ require 'optparse' require 'tmpdir' require 'pathname' +ENV.delete('SSL_CERT_FILE') if ENV['SSL_CERT_FILE'] == '/no-cert-file.crt' + +require_relative '../lib/bundix' require_relative '../lib/bundix/version' class Bundix OPTIONS = { ruby: 'ruby', - bundle_pack_path: 'vendor/bundle', - gemfile: 'Gemfile', - lockfile: 'Gemfile.lock', + gemfile: nil, + lockfile: nil, gemset: 'gemset.nix', lock: false, cache: false, + quiet: false, groups: [] } @@ -64,7 +67,8 @@ class Bundix op.parse! $VERBOSE = !OPTIONS[:quiet] - require_relative '../lib/bundix' + OPTIONS[:gemfile] ||= Bundler.default_gemfile + OPTIONS[:lockfile] ||= Bundler.default_lockfile if OPTIONS[:init] if File.file?('shell.nix') diff --git a/lib/bundix.rb b/lib/bundix.rb index cc353af..7bd76fa 100755 --- a/lib/bundix.rb +++ b/lib/bundix.rb @@ -1,10 +1,7 @@ require 'bundler' require 'json' -require 'open-uri' require 'open3' -require 'tsort' require 'set' -require 'pp' require_relative 'bundix/version' require_relative 'bundix/source' @@ -21,14 +18,7 @@ class Bundix attr_reader :options def initialize(options) - @options = { - quiet: false, - tempfile: nil, - gemfile: Bundler.default_gemfile, - lockfile: Bundler.default_lockfile, - lock: false, - deps: false - }.merge(options) + @options = options end def convert diff --git a/lib/bundix/gemfile_dependency_tree.rb b/lib/bundix/gemfile_dependency_tree.rb index c0e5928..8176226 100644 --- a/lib/bundix/gemfile_dependency_tree.rb +++ b/lib/bundix/gemfile_dependency_tree.rb @@ -1,4 +1,5 @@ require 'bundler' +require 'set' class GemfileDependencyTree Spec = Struct.new(:name, :groups, :source, :version, :dependencies) @@ -11,7 +12,7 @@ def self.run(options) else definitions.resolve_remotely! end - definitions.lock(Bundler.default_lockfile) if options.fetch(:lock) + definitions.lock(optons.fetch(:lockfile)) if options.fetch(:lock) result = {} definitions.dependencies.each do |dependency| @@ -28,7 +29,7 @@ def initialize(dep, specs, groups) @children = dependencies.map{|d| self.class.new(d, specs, groups) } end - def run(seen = [], result = {}) + def run(seen = Set.new, result = {}) children = @children.reject{|c| seen.include?(c.name) } add_group(result, @spec) From c1dfb3222a18c147313852f79f653afe62be7db8 Mon Sep 17 00:00:00 2001 From: Michael Fellinger Date: Tue, 19 Apr 2016 12:13:35 +0200 Subject: [PATCH 3/5] option shuffle --- bin/bundix | 17 +++++++---------- lib/bundix/gemfile_dependency_tree.rb | 22 ++++++++++++++++------ template/shell.nix | 2 +- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/bin/bundix b/bin/bundix index a2266fc..e22344d 100755 --- a/bin/bundix +++ b/bin/bundix @@ -12,15 +12,14 @@ require_relative '../lib/bundix/version' class Bundix OPTIONS = { ruby: 'ruby', - gemfile: nil, - lockfile: nil, gemset: 'gemset.nix', - lock: false, cache: false, quiet: false, groups: [] } + Bundler.settings[:frozen] = true + op = OptionParser.new do |o| o.on '--ruby=ruby', 'ruby version to use for init, defaults to latest' do |value| OPTIONS[:ruby] = value @@ -35,15 +34,15 @@ class Bundix end o.on '--gemfile=Gemfile', 'path to the Gemfile' do |value| - OPTIONS[:gemfile] = File.expand_path(value) + Bundler.settings[:gemfile] = Pathname(value) end o.on '--lockfile=Gemfile.lock', 'path to the Gemfile.lock' do |value| - OPTIONS[:lockfile] = File.expand_path(value) + Bundler.settings[:lockfile] = Pathname(value) end o.on '-l', '--lock', 'create Gemfile.lock for given groups' do |groups| - OPTIONS[:lock] = true + Bundler.settings[:frozen] = false end o.on '-c', '--cache', 'resolve dependencies from cache' do @@ -67,9 +66,6 @@ class Bundix op.parse! $VERBOSE = !OPTIONS[:quiet] - OPTIONS[:gemfile] ||= Bundler.default_gemfile - OPTIONS[:lockfile] ||= Bundler.default_lockfile - if OPTIONS[:init] if File.file?('shell.nix') warn "won't override existing shell.nix" @@ -77,7 +73,8 @@ class Bundix shell_nix = File.read(File.expand_path('../template/shell.nix', __dir__)) shell_nix.gsub!('PROJECT', File.basename(Dir.pwd)) shell_nix.gsub!('RUBY', OPTIONS[:ruby]) - shell_nix.gsub!('LOCKFILE', "./#{Pathname(OPTIONS[:lockfile]).relative_path_from(Pathname('./'))}") + shell_nix.gsub!('GEMFILE', "./#{Bundler.settings[:gemfile].relative_path_from(Pathname('./'))}") + shell_nix.gsub!('LOCKFILE', "./#{Bundler.settings[:lockfile].relative_path_from(Pathname('./'))}") shell_nix.gsub!('GEMSET', "./#{Pathname(OPTIONS[:gemset]).relative_path_from(Pathname('./'))}") File.write('shell.nix', shell_nix) end diff --git a/lib/bundix/gemfile_dependency_tree.rb b/lib/bundix/gemfile_dependency_tree.rb index 8176226..f1f0607 100644 --- a/lib/bundix/gemfile_dependency_tree.rb +++ b/lib/bundix/gemfile_dependency_tree.rb @@ -1,21 +1,30 @@ require 'bundler' require 'set' -class GemfileDependencyTree +class Bundix::GemfileDependencyTree Spec = Struct.new(:name, :groups, :source, :version, :dependencies) def self.run(options) - definitions = Bundler::Dsl.evaluate(options.fetch(:gemfile), nil, {}) + definition = Bundler::Dsl.evaluate(Bundler.settings[:gemfile], nil, {}) specs = if options.fetch(:cache) - definitions.resolve_with_cache! + puts "resolving #{Bundler.settings[:gemfile]} dependencies with cache" if $VERBOSE + definition.resolve_with_cache! else - definitions.resolve_remotely! + puts "resolving #{Bundler.settings[:gemfile]} dependencies remotely" if $VERBOSE + definition.resolve_remotely! end - definitions.lock(optons.fetch(:lockfile)) if options.fetch(:lock) + + unless Bundler.settings[:frozen] + puts "writing #{Bundler.settings[:lockfile]}" if $VERBOSE + puts definition.to_lock + p definition.lock(Bundler.settings[:lockfile]) + end result = {} - definitions.dependencies.each do |dependency| + definition.dependencies.each do |dependency| + p specs.map(&:name) + p specs.map(&:name).size new(dependency, specs, dependency.groups).run([], result) end @@ -25,6 +34,7 @@ def self.run(options) def initialize(dep, specs, groups) @dep = dep @spec = specs.find{|s| s.name == dep.name } + p @spec @groups = groups.map(&:to_s) @children = dependencies.map{|d| self.class.new(d, specs, groups) } end diff --git a/template/shell.nix b/template/shell.nix index cfe9ac0..c22b6e6 100644 --- a/template/shell.nix +++ b/template/shell.nix @@ -3,7 +3,7 @@ let env = bundlerEnv { name = "PROJECT-bundler-env"; inherit RUBY; - gemfile = ./Gemfile; + gemfile = GEMFILE; lockfile = LOCKFILE; gemset = GEMSET; }; From 270a910659e639f3b39e6c7a88fddeb029c500d0 Mon Sep 17 00:00:00 2001 From: Michael Fellinger Date: Tue, 19 Apr 2016 12:31:13 +0200 Subject: [PATCH 4/5] add pp --- lib/bundix/source.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/bundix/source.rb b/lib/bundix/source.rb index 874e168..f2a09b3 100644 --- a/lib/bundix/source.rb +++ b/lib/bundix/source.rb @@ -1,3 +1,5 @@ +require 'pp' + class Bundix class Source < Struct.new(:spec, :definition) def convert From 7605ae5a794baa2b006f816c2082d9dfe0afcb03 Mon Sep 17 00:00:00 2001 From: Michael Fellinger Date: Tue, 19 Apr 2016 16:33:24 +0200 Subject: [PATCH 5/5] dev deps prototype --- bin/bundix | 5 +++++ lib/bundix/gemfile_dependency_tree.rb | 21 ++++++++++++--------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/bin/bundix b/bin/bundix index e22344d..60fbbdd 100755 --- a/bin/bundix +++ b/bin/bundix @@ -15,6 +15,7 @@ class Bundix gemset: 'gemset.nix', cache: false, quiet: false, + development_dependencies: false, groups: [] } @@ -53,6 +54,10 @@ class Bundix OPTIONS[:groups].concat groups.map(&:to_sym) end + o.on '--development-dependencies', 'include development dependencies from gemspecs in the set' do + OPTIONS[:development_dependencies] = true + end + o.on '-q', '--quiet', 'only output errors' do OPTIONS[:quiet] = true end diff --git a/lib/bundix/gemfile_dependency_tree.rb b/lib/bundix/gemfile_dependency_tree.rb index f1f0607..0266622 100644 --- a/lib/bundix/gemfile_dependency_tree.rb +++ b/lib/bundix/gemfile_dependency_tree.rb @@ -4,6 +4,8 @@ class Bundix::GemfileDependencyTree Spec = Struct.new(:name, :groups, :source, :version, :dependencies) + attr_reader :options + def self.run(options) definition = Bundler::Dsl.evaluate(Bundler.settings[:gemfile], nil, {}) specs = @@ -17,26 +19,23 @@ def self.run(options) unless Bundler.settings[:frozen] puts "writing #{Bundler.settings[:lockfile]}" if $VERBOSE - puts definition.to_lock - p definition.lock(Bundler.settings[:lockfile]) + definition.lock(Bundler.settings[:lockfile]) end result = {} definition.dependencies.each do |dependency| - p specs.map(&:name) - p specs.map(&:name).size - new(dependency, specs, dependency.groups).run([], result) + new(dependency, specs, dependency.groups, options).run([], result) end result end - def initialize(dep, specs, groups) + def initialize(dep, specs, groups, options) @dep = dep @spec = specs.find{|s| s.name == dep.name } - p @spec @groups = groups.map(&:to_s) - @children = dependencies.map{|d| self.class.new(d, specs, groups) } + @options = options + @children = dependencies.map{|d| self.class.new(d, specs, groups, options) } end def run(seen = Set.new, result = {}) @@ -72,6 +71,10 @@ def add_group(result, dep) end def dependencies - @spec.dependencies.reject{|d| d.type == :development } + if options[:development_dependencies] + @spec.dependencies + else + @spec.dependencies.reject{|d| d.type == :development } + end end end