diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/bundler/endpoint_specification.rb | 19 | ||||
-rw-r--r-- | lib/bundler/fetcher.rb | 8 | ||||
-rw-r--r-- | lib/bundler/fetcher/compact_dependency.rb | 29 | ||||
-rw-r--r-- | lib/bundler/fetcher/compact_gem_list.rb | 48 | ||||
-rw-r--r-- | lib/bundler/fetcher/compact_gem_list/cache.rb | 79 | ||||
-rw-r--r-- | lib/bundler/fetcher/compact_gem_list/updater.rb | 17 | ||||
-rw-r--r-- | lib/bundler/fetcher/compact_index.rb | 21 | ||||
-rw-r--r-- | lib/bundler/fetcher/dependency.rb | 4 |
8 files changed, 218 insertions, 7 deletions
diff --git a/lib/bundler/endpoint_specification.rb b/lib/bundler/endpoint_specification.rb index 21a6c85c5a..c46f4cd277 100644 --- a/lib/bundler/endpoint_specification.rb +++ b/lib/bundler/endpoint_specification.rb @@ -3,14 +3,16 @@ module Bundler class EndpointSpecification < Gem::Specification include MatchPlatform - attr_reader :name, :version, :platform, :dependencies + attr_reader :name, :version, :platform, :dependencies, :required_rubygems_version, :required_ruby_version, :checksum attr_accessor :source, :remote - def initialize(name, version, platform, dependencies) + def initialize(name, version, platform, dependencies, metadata = {}) @name = name @version = version @platform = platform @dependencies = dependencies + + parse_metadata(metadata) end def fetch_platform @@ -96,5 +98,18 @@ module Bundler def local_specification_path "#{base_dir}/specifications/#{full_name}.gemspec" end + + def parse_metadata(data) + data.each do |k, v| + case k.to_s + when "checksum" + @checksum = v.last + when "rubygems" + @required_rubygems_version = Gem::Requirement.new(v) if v + when "ruby" + @required_ruby_version = Gem::Requirement.new(v) if v + end + end + end end end diff --git a/lib/bundler/fetcher.rb b/lib/bundler/fetcher.rb index c8c21a92ff..4146d2b38b 100644 --- a/lib/bundler/fetcher.rb +++ b/lib/bundler/fetcher.rb @@ -6,6 +6,8 @@ require "zlib" module Bundler # Handles all the fetching with the rubygems server class Fetcher + autoload :CompactIndex, 'bundler/fetcher/compact_index' + autoload :CompactDependency, 'bundler/fetcher/compact_dependency' autoload :Downloader, "bundler/fetcher/downloader" autoload :Dependency, "bundler/fetcher/dependency" autoload :Index, "bundler/fetcher/index" @@ -117,11 +119,11 @@ module Bundler end @use_api = false if fetchers.none?(&:api_fetcher?) - specs[remote_uri].each do |name, version, platform, dependencies| + specs[remote_uri].each do |name, version, platform, dependencies, metadata| next if name == "bundler" spec = nil if dependencies - spec = EndpointSpecification.new(name, version, platform, dependencies) + spec = EndpointSpecification.new(name, version, platform, dependencies, metadata) else spec = RemoteSpecification.new(name, version, platform, self) end @@ -200,7 +202,7 @@ module Bundler private - FETCHERS = [Dependency, Index] + FETCHERS = [CompactDependency, Dependency, CompactIndex, Index] def cis env_cis = { diff --git a/lib/bundler/fetcher/compact_dependency.rb b/lib/bundler/fetcher/compact_dependency.rb new file mode 100644 index 0000000000..0ec9da0c38 --- /dev/null +++ b/lib/bundler/fetcher/compact_dependency.rb @@ -0,0 +1,29 @@ +require 'bundler/fetcher/dependency' + +module Bundler + class Fetcher + class CompactDependency < Dependency + def dependency_specs(gem_names) + dependency_names = [] + specs = compact_gem_list.dependencies(gem_names).each do |spec| + spec[1] = Gem::Version.new spec[1] + dependency_names.concat spec[3].map! { |name, args| Gem::Dependency.new(name, args) }.map(&:name) + end + [specs, dependency_names] + end + + def dependency_api_uri(gem_names = []) + fetch_uri + "api/v2/info" + end + + private + + def compact_gem_list + @compact_gem_list ||= begin + uri_part = [display_uri.hostname, display_uri.port, Digest.hexencode(display_uri.path)].compact.join('.') + CompactGemList.new(self, Bundler.cache + 'compact_index' + uri_part) + end + end + end + end +end diff --git a/lib/bundler/fetcher/compact_gem_list.rb b/lib/bundler/fetcher/compact_gem_list.rb new file mode 100644 index 0000000000..450350e24e --- /dev/null +++ b/lib/bundler/fetcher/compact_gem_list.rb @@ -0,0 +1,48 @@ +module Bundler + class Fetcher + class CompactGemList + require_relative 'compact_gem_list/cache.rb' + require_relative 'compact_gem_list/updater.rb' + + attr_reader :fetcher, :directory + + def initialize(fetcher, directory) + @fetcher = fetcher + @directory = Pathname(directory) + FileUtils.mkdir_p(@directory) + @updater = Updater.new(@fetcher) + @cache = Cache.new(@directory) + end + + def names + @updater.update([[@cache.names_path, url('names.list')]]) + @cache.names + end + + def versions + @updater.update([[@cache.versions_path, url('versions.list')]]) + @cache.versions + end + + def dependencies(names) + @updater.update(names.map do |name| + raise "Not string (#{name.inspect})" unless name.is_a?(String) + [@cache.dependencies_path(name), url("info/#{name}")] + end) + names.map do |name| + @cache.dependencies(name).map { |d| d.unshift(name) } + end.flatten(1) + end + + def spec(name, version, platform = nil) + specific_dependency(name, version, platform) + end + + private + + def url(path) + ['api/v2', path].compact.join("/") + end + end + end +end diff --git a/lib/bundler/fetcher/compact_gem_list/cache.rb b/lib/bundler/fetcher/compact_gem_list/cache.rb new file mode 100644 index 0000000000..a7d617a03c --- /dev/null +++ b/lib/bundler/fetcher/compact_gem_list/cache.rb @@ -0,0 +1,79 @@ +module Bundler + class Fetcher::CompactGemList + class Cache + attr_reader :directory + + def initialize(directory) + @directory = p Pathname(directory).expand_path + FileUtils.mkdir_p dependencies_path(nil) + end + + def names + lines(names_path) + end + + def names_path + directory + 'names' + end + + def versions + versions_by_name = {} + lines(versions_path).map do |line| + name, versions_string = line.split(" ", 2) + versions_string.split(",").map! do |version| + version.split("-", 2).unshift(name) + end + end + versions_by_name + end + + def versions_path + directory + 'versions' + end + + def dependencies(name) + lines(dependencies_path(name)).map do |line| + parse_gem(line) + end + end + + def dependencies_path(name) + directory + 'dependencies' + name.to_s + end + + def specific_dependency(name, version, platform) + pattern = [version, platform].compact!.join("-") + matcher = %r{\A#{Regexp.escape(pattern)} } unless pattern.empty? + lines(dependencies_path(name)).each do |line| + return parse_gem(line) if line =~ matcher + end if matcher + nil + end + + private + + def lines(path) + return [] unless path.file? + lines = path.read.lines + header = lines.index("---\n") + lines = header ? lines[header+1..-1] : lines + lines.map!(&:strip!) + end + + def parse_gem(string) + version_and_platform, rest = string.split(" ", 2) + version, platform = version_and_platform.split("-", 2) + dependencies, requirements = rest.split("|", 2).map { |s| s.split(",") } if rest + dependencies = dependencies ? dependencies.map { |d| parse_dependency(d) } : [] + requirements = requirements ? requirements.map { |r| parse_dependency(r) } : [] + [version, platform, dependencies, requirements] + end + + def parse_dependency(string) + dependency = string.split(":") + dependency[-1] = dependency[-1].split("&") + dependency + end + end + end +end diff --git a/lib/bundler/fetcher/compact_gem_list/updater.rb b/lib/bundler/fetcher/compact_gem_list/updater.rb new file mode 100644 index 0000000000..c392b2679c --- /dev/null +++ b/lib/bundler/fetcher/compact_gem_list/updater.rb @@ -0,0 +1,17 @@ +module Bundler + class Fetcher::CompactGemList + class Updater + attr_reader :fetcher + def initialize(fetcher) + @fetcher = fetcher + end + + def update(files) + files.each do |path, remote_path| + response = fetcher.downloader.fetch(fetcher.fetch_uri + remote_path) + path.open("w") { |f| f.write response } + end + end + end + end +end diff --git a/lib/bundler/fetcher/compact_index.rb b/lib/bundler/fetcher/compact_index.rb new file mode 100644 index 0000000000..2f41fb8db7 --- /dev/null +++ b/lib/bundler/fetcher/compact_index.rb @@ -0,0 +1,21 @@ +require 'bundler/fetcher/base' +require 'bundler/fetcher/compact_gem_list' + +module Bundler + class Fetcher + class CompactIndex < Base + def specs(_gem_names) + { remote_uri => compact_gem_list.versions } + end + + private + + def compact_gem_list + @compact_gem_list ||= begin + uri_part = [display_uri.hostname, display_uri.port, Digest.hexencode(display_uri.path)].compact.join('.') + CompactGemList.new(self, Bundler.cache + 'compact_index' + uri_part) + end + end + end + end +end diff --git a/lib/bundler/fetcher/dependency.rb b/lib/bundler/fetcher/dependency.rb index 29af0dc318..d0677b0286 100644 --- a/lib/bundler/fetcher/dependency.rb +++ b/lib/bundler/fetcher/dependency.rb @@ -19,7 +19,7 @@ module Bundler end def specs(gem_names, full_dependency_list = [], last_spec_list = []) - query_list = gem_names - full_dependency_list + query_list = gem_names.uniq - full_dependency_list log_specs(query_list) @@ -64,7 +64,7 @@ module Bundler [s[:name], Gem::Version.new(s[:number]), s[:platform], dependencies] end - [spec_list, deps_list.uniq] + [spec_list, deps_list] end def dependency_api_uri(gem_names = []) |