1require 'rubygems/source' 2 3class Gem::Source::Local < Gem::Source 4 def initialize 5 @uri = nil 6 end 7 8 def load_specs(type) 9 names = [] 10 11 @specs = {} 12 13 Dir["*.gem"].each do |file| 14 begin 15 pkg = Gem::Package.new(file) 16 rescue SystemCallError, Gem::Package::FormatError 17 # ignore 18 else 19 tup = pkg.spec.name_tuple 20 @specs[tup] = [File.expand_path(file), pkg] 21 22 case type 23 when :released 24 unless pkg.spec.version.prerelease? 25 names << pkg.spec.name_tuple 26 end 27 when :prerelease 28 if pkg.spec.version.prerelease? 29 names << pkg.spec.name_tuple 30 end 31 when :latest 32 tup = pkg.spec.name_tuple 33 34 cur = names.find { |x| x.name == tup.name } 35 if !cur 36 names << tup 37 elsif cur.version < tup.version 38 names.delete cur 39 names << tup 40 end 41 else 42 names << pkg.spec.name_tuple 43 end 44 end 45 end 46 47 names 48 end 49 50 def find_gem(gem_name, version=Gem::Requirement.default, 51 prerelease=false) 52 load_specs :complete 53 54 found = [] 55 56 @specs.each do |n, data| 57 if n.name == gem_name 58 s = data[1].spec 59 60 if version.satisfied_by?(s.version) 61 if prerelease 62 found << s 63 elsif !s.version.prerelease? 64 found << s 65 end 66 end 67 end 68 end 69 70 found.sort_by { |s| s.version }.last 71 end 72 73 def fetch_spec(name) 74 load_specs :complete 75 76 if data = @specs[name] 77 data.last.spec 78 else 79 raise Gem::Exception, "Unable to find spec for '#{name}'" 80 end 81 end 82 83 def download(spec, cache_dir=nil) 84 load_specs :complete 85 86 @specs.each do |name, data| 87 return data[0] if data[1].spec == spec 88 end 89 90 raise Gem::Exception, "Unable to find file for '#{spec.full_name}'" 91 end 92end 93