summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Lerche <carllerche@mac.com>2010-03-11 01:12:13 -0800
committerCarl Lerche <carllerche@mac.com>2010-03-11 01:12:13 -0800
commitb3db2c37c688ab76badc429bbc52912f37a2e003 (patch)
tree2a673e5dfe9f67b9f32250f76dd97a234da9d322
parent0d5e87b89617fabb175ed8d0b54bee764b454f2c (diff)
downloadbundler-b3db2c37c688ab76badc429bbc52912f37a2e003.tar.gz
Refactor spec grouping to use the SpecSet
-rw-r--r--lib/bundler/environment.rb33
-rw-r--r--lib/bundler/installer.rb4
-rw-r--r--lib/bundler/runtime.rb4
-rw-r--r--lib/bundler/spec_set.rb45
-rw-r--r--spec/resolver/basic_spec.rb15
-rw-r--r--spec/spec_helper.rb1
-rw-r--r--spec/support/builders.rb33
-rw-r--r--spec/support/indexes.rb71
8 files changed, 165 insertions, 41 deletions
diff --git a/lib/bundler/environment.rb b/lib/bundler/environment.rb
index 3602f12dd1..15028ba3b9 100644
--- a/lib/bundler/environment.rb
+++ b/lib/bundler/environment.rb
@@ -28,28 +28,18 @@ module Bundler
end
end
- def specs_for(*groups)
- groups = @definition.groups if groups.empty?
- groups -= Bundler.settings.without
- groups.map! { |g| g.to_sym }
- specs.select { |s| (s.groups & groups).any? }
- end
-
- def group_specs(specs)
- dependencies.each do |d|
- spec = specs.find { |s| s.name == d.name }
- group_spec(specs, spec, d.groups)
+ def requested_specs
+ @requested_specs ||= begin
+ groups = @definition.groups - Bundler.settings.without
+ groups.map! { |g| g.to_sym }
+ groups.any? ? specs_for(groups) : []
end
- specs
end
- def group_spec(specs, spec, groups)
- spec.groups.concat(groups)
- spec.groups.uniq!
- spec.dependencies.select { |d| d.type != :development }.each do |d|
- spec = specs.find { |s| s.name == d.name }
- group_spec(specs, spec, groups)
- end
+ def specs_for(groups)
+ deps = dependencies.select { |d| (d.groups & groups).any? }
+ # deps.any? ? specs.for(deps) : specs
+ specs.for(deps)
end
# ==== Locking
@@ -77,7 +67,7 @@ module Bundler
end
def specs_for_lock_file
- specs_for.map do |s|
+ requested_specs.map do |s|
hash = {}
hash[:loaded_from] = s.loaded_from.to_s
hash[:load_paths] = s.load_paths
@@ -90,7 +80,8 @@ module Bundler
autorequires = Hash.new { |h,k| h[k] = [] }
ordered_deps = []
- specs_for(*groups).each do |g|
+ specs = groups.any? ? specs_for(groups) : requested_specs
+ specs.each do |g|
dep = @definition.dependencies.find{|d| d.name == g.name }
ordered_deps << dep if dep && !ordered_deps.include?(dep)
end
diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb
index 13ff9d8deb..b92e362879 100644
--- a/lib/bundler/installer.rb
+++ b/lib/bundler/installer.rb
@@ -21,7 +21,7 @@ module Bundler
specs.each do |spec|
spec.source.fetch(spec) if spec.source.respond_to?(:fetch)
- if spec.groups & Bundler.settings.without == spec.groups
+ unless requested_specs.include?(spec)
Bundler.ui.debug " * Not in requested group; skipping."
next
end
@@ -49,7 +49,7 @@ module Bundler
end
def specs
- @specs ||= group_specs(resolve_locally || resolve_remotely)
+ @specs ||= resolve_locally || resolve_remotely
end
private
diff --git a/lib/bundler/runtime.rb b/lib/bundler/runtime.rb
index e5de8b3968..80df72f4cb 100644
--- a/lib/bundler/runtime.rb
+++ b/lib/bundler/runtime.rb
@@ -15,7 +15,7 @@ module Bundler
# Has to happen first
clean_load_path
- specs = specs_for(*groups)
+ specs = groups.any? ? specs_for(groups) : requested_specs
cripple_rubygems(specs)
@@ -83,7 +83,7 @@ module Bundler
source_requirements[dep.name] = dep.source.local_specs
end
- group_specs(Resolver.resolve(@definition.actual_dependencies, index, source_requirements))
+ Resolver.resolve(@definition.actual_dependencies, index, source_requirements)
end
end
diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb
index fad3d635cd..16764cd747 100644
--- a/lib/bundler/spec_set.rb
+++ b/lib/bundler/spec_set.rb
@@ -5,21 +5,52 @@ module Bundler
include TSort, Enumerable
def initialize(specs)
- @specs = specs.sort_by { |s| s.name }
- @lookup = Hash.new do |h,k|
- h[k] = specs.find { |s| s.name == k }
- end
- @sorted = ([@lookup['rake']] + tsort).compact.uniq
+ @specs = specs.sort_by { |s| s.name }
end
def each
- @sorted.each { |s| yield s }
+ sorted.each { |s| yield s }
end
def length
@specs.length
end
+ def for(*deps)
+ specs = {}
+ deps.flatten.each do |dep|
+ current = lookup[dep.respond_to?(:name) ? dep.name : dep]
+ append_subgraph(specs, current)
+ end
+
+ sorted.select { |s| specs[s.name] }
+ end
+
+ def to_a
+ sorted.dup
+ end
+
+ private
+
+ def append_subgraph(specs, current)
+ return if specs[current.name]
+ specs[current.name] = true
+ current.dependencies.each do |dep|
+ next unless dep.type == :runtime
+ append_subgraph(specs, lookup[dep.name])
+ end
+ end
+
+ def sorted
+ @sorted ||= ([lookup['rake']] + tsort).compact.uniq
+ end
+
+ def lookup
+ @lookup ||= Hash.new do |h,k|
+ h[k] = @specs.find { |s| s.name == k }
+ end
+ end
+
def tsort_each_node
@specs.each { |s| yield s }
end
@@ -27,7 +58,7 @@ module Bundler
def tsort_each_child(s)
s.dependencies.sort_by { |d| d.name }.each do |d|
next if d.type == :development
- yield @lookup[d.name]
+ yield lookup[d.name]
end
end
end
diff --git a/spec/resolver/basic_spec.rb b/spec/resolver/basic_spec.rb
new file mode 100644
index 0000000000..c3695b7280
--- /dev/null
+++ b/spec/resolver/basic_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../spec_helper', __FILE__)
+
+describe "Resolving" do
+
+ before :each do
+ @deps = []
+ @index = an_awesome_index
+ end
+
+ it "resolves" do
+ dep "rack"
+
+ should_resolve_as [gem "rack", "1.1"]
+ end
+end \ No newline at end of file
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index d92e9571a5..6b704359b5 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -19,6 +19,7 @@ FileUtils.rm_rf(Spec::Path.gem_repo1)
Spec::Runner.configure do |config|
config.include Spec::Builders
config.include Spec::Helpers
+ config.include Spec::Indexes
config.include Spec::Matchers
config.include Spec::Path
config.include Spec::Rubygems
diff --git a/spec/support/builders.rb b/spec/support/builders.rb
index f8ad30d70c..18c29def7b 100644
--- a/spec/support/builders.rb
+++ b/spec/support/builders.rb
@@ -4,6 +4,10 @@ module Spec
name.gsub('-', '').upcase
end
+ def v(version)
+ Gem::Version.new(version)
+ end
+
def build_repo1
build_repo gem_repo1 do
build_gem "rack", %w(0.9.1 1.0.0) do |s|
@@ -224,18 +228,19 @@ module Spec
end
def build_index(&block)
- index = Gem::SourceIndex.new
+ index = Bundler::Index.new
IndexBuilder.run(index, &block) if block_given?
index
end
def build_spec(name, version, platform = nil, &block)
- spec = Gem::Specification.new
- spec.instance_variable_set(:@name, name)
- spec.instance_variable_set(:@version, Gem::Version.new(version))
- spec.platform = Gem::Platform.new(platform) if platform
- DepBuilder.run(spec, &block) if block_given?
- spec
+ Array(version).map do |v|
+ Gem::Specification.new do |s|
+ s.name = name
+ s.version = Gem::Version.new(v)
+ DepBuilder.run(s, &block) if block_given?
+ end
+ end
end
def build_dep(name, requirements = Gem::Requirement.default, type = :runtime)
@@ -289,12 +294,20 @@ module Spec
instance_eval(&block)
end
- def add_spec(*args, &block)
- @index.add_spec(build_spec(*args, &block))
+ def gem(*args, &block)
+ build_spec(*args, &block).each do |s|
+ @index << s
+ end
+ end
+
+ def versions(versions)
+ versions.split(/\s+/).each { |version| yield v version }
end
end
class DepBuilder
+ include Builders
+
def self.run(spec, &block)
new(spec).run(&block)
end
@@ -310,6 +323,8 @@ module Spec
def runtime(name, requirements)
@spec.add_runtime_dependency(name, requirements)
end
+
+ alias dep runtime
end
class LibBuilder
diff --git a/spec/support/indexes.rb b/spec/support/indexes.rb
new file mode 100644
index 0000000000..da168ada88
--- /dev/null
+++ b/spec/support/indexes.rb
@@ -0,0 +1,71 @@
+module Spec
+ module Indexes
+ def dep(name, reqs = nil)
+ @deps << Bundler::Dependency.new(name, :version => reqs)
+ end
+
+ def should_resolve_as(specs)
+ got = Bundler::Resolver.resolve(@deps, @index)
+ got = got.map { |s| s.full_name }
+
+ got.should == specs.flatten.map { |s| s.full_name }
+ end
+
+ def gem(*args, &blk)
+ build_spec(*args, &blk)
+ end
+
+ def an_awesome_index
+ build_index do
+ gem "rack", %w(0.8 0.9 0.9.1 0.9.2 1.0 1.1)
+ gem "rack-mount", %w(0.4 0.5 0.5.1 0.5.2 0.6)
+
+ # --- Rails
+ versions "1.2.3 2.2.3 2.3.5 3.0.0.beta 3.0.0.beta1" do |version|
+ gem "activesupport", version
+ gem "actionpack", version do
+ dep "activesupport", version
+ if version >= v('3.0.0.beta')
+ dep "rack", '~> 1.1'
+ dep "rack-mount", ">= 0.5"
+ elsif version > v('2.3.5') then dep "rack", '~> 1.0'
+ elsif version > v('2.0.0') then dep "rack", '~> 0.9'
+ end
+ end
+ gem "activerecord", version do
+ dep "activesupport", version
+ dep "arel", ">= 0.2" if version >= v('3.0.0.beta')
+ end
+ gem "actionmailer", version do
+ dep "activesupport", version
+ dep "actionmailer", version
+ end
+ if version < v('3.0.0.beta')
+ gem "railties", version do
+ dep "activerecord", version
+ dep "actionpack", version
+ dep "actionmailer", version
+ dep "activesupport", version
+ end
+ else
+ gem "railties", version
+ gem "rails", version do
+ dep "activerecord", version
+ dep "actionpack", version
+ dep "actionmailer", version
+ dep "activesupport", version
+ dep "railties", version
+ end
+ end
+ end
+
+ # --- Rails related
+ versions '1.2.3 2.2.3 2.3.5' do |version|
+ gem "activemerchant", version do
+ dep "activesupport", ">= #{version}"
+ end
+ end
+ end
+ end
+ end
+end \ No newline at end of file