summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/bundler/endpoint_specification.rb19
-rw-r--r--lib/bundler/fetcher.rb8
-rw-r--r--lib/bundler/fetcher/compact_dependency.rb29
-rw-r--r--lib/bundler/fetcher/compact_gem_list.rb48
-rw-r--r--lib/bundler/fetcher/compact_gem_list/cache.rb79
-rw-r--r--lib/bundler/fetcher/compact_gem_list/updater.rb17
-rw-r--r--lib/bundler/fetcher/compact_index.rb21
-rw-r--r--lib/bundler/fetcher/dependency.rb4
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 = [])