Created
May 23, 2011 23:49
-
-
Save mipearson/987885 to your computer and use it in GitHub Desktop.
Attempting to speed up bundler's index.rb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Bundler | |
class Index | |
include Enumerable | |
def self.build | |
i = new | |
yield i | |
i | |
end | |
attr_reader :specs | |
protected :specs | |
def initialize | |
@cache = {} | |
@specs = {} | |
# @specs = Hash.new { |h,k| h[k] = [] } | |
end | |
def initialize_copy(o) | |
super | |
@cache = {} | |
@specs = {} | |
# @specs = Hash.new { |h,k| h[k] = [] } | |
o.specs.each do |name, array| | |
@specs[name] = array.dup | |
end | |
end | |
def empty? | |
each { return false } | |
true | |
end | |
def search(query) | |
case query | |
when Gem::Specification, RemoteSpecification, LazySpecification then search_by_spec(query) | |
when String then (@specs[query] || []) | |
else search_by_dependency(query) | |
end | |
end | |
def search_for_all_platforms(dependency, base = []) | |
specs = @specs[dependency.name] + base | |
wants_prerelease = dependency.requirement.prerelease? | |
only_prerelease = specs.all? {|spec| spec.version.prerelease? } | |
found = specs.select { |spec| dependency.matches_spec?(spec) } | |
unless wants_prerelease || only_prerelease | |
found.reject! { |spec| spec.version.prerelease? } | |
end | |
found.sort_by {|s| [s.version, s.platform.to_s == 'ruby' ? "\0" : s.platform.to_s] } | |
end | |
def sources | |
@specs.values.map do |specs| | |
specs.map{|s| s.source.class } | |
end.flatten.uniq | |
end | |
alias [] search | |
def <<(spec) | |
@specs[spec.name] ||= [] | |
arr = @specs[spec.name] | |
# arr.delete_if do |s| | |
# same_version?(s.version, spec.version) && s.platform == spec.platform | |
# end | |
arr << spec | |
spec | |
end | |
def each(&blk) | |
@specs.values.each do |specs| | |
specs.each(&blk) | |
end | |
end | |
def use(other) | |
return unless other | |
other.each do |s| | |
next if search_by_spec(s).any? | |
@specs[s.name] ||= [] | |
@specs[s.name] << s | |
end | |
self | |
end | |
def ==(o) | |
all? do |s| | |
s2 = o[s].first and (s.dependencies & s2.dependencies).empty? | |
end | |
end | |
private | |
def search_by_spec(spec) | |
return [] unless @specs.include?(spec.name) | |
@specs[spec.name].select do |s| | |
same_version?(s.version, spec.version) && Gem::Platform.new(s.platform) == Gem::Platform.new(spec.platform) | |
end | |
end | |
def same_version?(a, b) | |
regex = /^(.*?)(?:\.0)*$/ | |
a.to_s[regex, 1] == b.to_s[regex, 1] | |
end | |
def spec_satisfies_dependency?(spec, dep) | |
return false unless dep.name === spec.name | |
dep.requirement.satisfied_by?(spec.version) | |
end | |
def search_by_dependency(dependency) | |
@cache[dependency.hash] ||= begin | |
specs = @specs[dependency.name] | |
found = specs.select { |spec| dependency.matches_spec?(spec) && Gem::Platform.match(spec.platform) } | |
wants_prerelease = dependency.requirement.prerelease? | |
only_prerelease = specs.all? {|spec| spec.version.prerelease? } | |
unless wants_prerelease || only_prerelease | |
found.reject! { |spec| spec.version.prerelease? } | |
end | |
found.sort_by {|s| [s.version, s.platform.to_s == 'ruby' ? "\0" : s.platform.to_s] } | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment