Skip to content

Commit

Permalink
Starting to refactor the Bundler to get it ready for multiple kinds o…
Browse files Browse the repository at this point in the history
…f sources
  • Loading branch information
Carl Lerche committed Jul 30, 2009
1 parent d14390b commit 0785b65
Show file tree
Hide file tree
Showing 14 changed files with 138 additions and 248 deletions.
1 change: 1 addition & 0 deletions lib/bundler.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
require "rubygems/installer" require "rubygems/installer"


require "bundler/gem_bundle" require "bundler/gem_bundle"
require "bundler/source"
require "bundler/finder" require "bundler/finder"
require "bundler/gem_ext" require "bundler/gem_ext"
require "bundler/resolver" require "bundler/resolver"
Expand Down
59 changes: 19 additions & 40 deletions lib/bundler/finder.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ class Finder
# ==== Parameters # ==== Parameters
# *sources<String>:: URI pointing to the gem repository # *sources<String>:: URI pointing to the gem repository
def initialize(*sources) def initialize(*sources)
@results = {} @cache = {}
@index = Hash.new { |h,k| h[k] = {} } @index = {}

@sources = sources
sources.each { |source| fetch(source) }
end end


# Figures out the best possible configuration of gems that satisfies # Figures out the best possible configuration of gems that satisfies
Expand All @@ -36,39 +35,6 @@ def resolve(*dependencies)
resolved && GemBundle.new(resolved) resolved && GemBundle.new(resolved)
end end


# Fetches the index from the remote source
#
# ==== Parameters
# source<String>:: URI pointing to the gem repository
#
# ==== Raises
# ArgumentError:: If the source is not a valid gem repository
def fetch(source)
Bundler.logger.info "Updating source: #{source}"

deflated = Gem::RemoteFetcher.fetcher.fetch_path("#{source}/Marshal.4.8.Z")
inflated = Gem.inflate deflated

append(Marshal.load(inflated), source)
rescue Gem::RemoteFetcher::FetchError => e
raise ArgumentError, "#{source} is not a valid source: #{e.message}"
end

# Adds a new gem index linked to a gem source to the over all
# gem index that gets searched.
#
# ==== Parameters
# index<Gem::SourceIndex>:: The index to append to the list
# source<String>:: The original source
def append(index, source)
index.gems.values.each do |spec|
next unless Gem::Platform.match(spec.platform)
spec.source = source
@index[spec.name][spec.version] ||= spec
end
self
end

# Searches for a gem that matches the dependency # Searches for a gem that matches the dependency
# #
# ==== Parameters # ==== Parameters
Expand All @@ -78,12 +44,25 @@ def append(index, source)
# [Gem::Specification]:: A collection of gem specifications # [Gem::Specification]:: A collection of gem specifications
# matching the search # matching the search
def search(dependency) def search(dependency)
@results[dependency.hash] ||= begin @cache[dependency.hash] ||= begin
possibilities = @index[dependency.name].values find_by_name(dependency.name).select do |spec|
possibilities.select do |spec|
dependency =~ spec dependency =~ spec
end.sort_by {|s| s.version } end.sort_by {|s| s.version }
end end
end end

private

def find_by_name(name)
matches = @index[name] ||= begin
versions = {}
@sources.reverse_each do |source|
versions.merge! source.specs[name] || {}
end
versions
end
matches.values
end

end end
end end
9 changes: 2 additions & 7 deletions lib/bundler/gem_bundle.rb
Original file line number Original file line Diff line number Diff line change
@@ -1,13 +1,8 @@
module Bundler module Bundler
class GemBundle < Array class GemBundle < Array
def download(directory) def download(repository)
FileUtils.mkdir_p(directory)

sort_by {|s| s.full_name.downcase }.each do |spec| sort_by {|s| s.full_name.downcase }.each do |spec|
unless directory.join("cache", "#{spec.full_name}.gem").file? repository.download(spec)
Bundler.logger.info "Downloading #{spec.full_name}.gem"
Gem::RemoteFetcher.fetcher.download(spec, spec.source, directory)
end
end end


self self
Expand Down
4 changes: 2 additions & 2 deletions lib/bundler/gem_ext.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ class Specification
attribute :source attribute :source


def source=(source) def source=(source)
@source = source.is_a?(URI) ? source : URI.parse(source) source = Bundler::Source.new(source) unless source.is_a?(Bundler::Source)
raise ArgumentError, "The source must be an absolute URI" unless @source.absolute? @source = source
end end
end end
end end
3 changes: 1 addition & 2 deletions lib/bundler/manifest.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ class Manifest
attr_reader :sources, :dependencies, :path attr_reader :sources, :dependencies, :path


def initialize(sources, dependencies, bindir, repository_path, rubygems, system_gems) def initialize(sources, dependencies, bindir, repository_path, rubygems, system_gems)
sources.map! {|s| s.is_a?(URI) ? s : URI.parse(s) }
@sources = sources @sources = sources
@dependencies = dependencies @dependencies = dependencies
@bindir = bindir @bindir = bindir
Expand Down Expand Up @@ -58,7 +57,7 @@ def fetch(update)
raise VersionConflict, "No compatible versions could be found for:\n#{gems}" raise VersionConflict, "No compatible versions could be found for:\n#{gems}"
end end


bundle.download(@repository.path) bundle.download(@repository)
end end


def gem_dependencies def gem_dependencies
Expand Down
2 changes: 1 addition & 1 deletion lib/bundler/manifest_file.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def self.load(filename = nil)


def initialize(filename) def initialize(filename)
@filename = filename @filename = filename
@sources = %w(http://gems.rubyforge.org) @sources = [Source.new("http://gems.rubyforge.org")]
@dependencies = [] @dependencies = []
@rubygems = true @rubygems = true
@system_gems = true @system_gems = true
Expand Down
8 changes: 8 additions & 0 deletions lib/bundler/repository.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ def valid?
(Dir[@path.join("*")] - Dir[@path.join("{cache,doc,gems,environments,specifications}")]).empty? (Dir[@path.join("*")] - Dir[@path.join("{cache,doc,gems,environments,specifications}")]).empty?
end end


def download(spec)
FileUtils.mkdir_p(@path)

unless @path.join("cache", "#{spec.full_name}.gem").file?
spec.source.download(spec, @path)
end
end

# Checks whether a gem is installed # Checks whether a gem is installed
def install_cached_gems(options = {}) def install_cached_gems(options = {})
cached_gems.each do |name, version| cached_gems.each do |name, version|
Expand Down
6 changes: 4 additions & 2 deletions lib/bundler/runtime.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ def disable_system_gems
end end


def source(source) def source(source)
@manifest_file.sources << source source = Source.new(source)
@manifest_file.sources.uniq! unless @manifest_file.sources.include?(source)
@manifest_file.sources << source
end
end end


def sources def sources
Expand Down
51 changes: 51 additions & 0 deletions lib/bundler/source.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,51 @@
module Bundler
# Represents a source of rubygems. Initially, this is only gem repositories, but
# eventually, this will be git, svn, HTTP
class Source
attr_reader :uri

def initialize(uri)
@uri = uri.is_a?(URI) ? uri : URI.parse(uri)
raise ArgumentError, "The source must be an absolute URI" unless @uri.absolute?
end

def specs
@specs ||= fetch_specs
end

def ==(other)
uri == other.uri
end

def to_s
@uri.to_s
end

def download(spec, destination)
Bundler.logger.info "Downloading #{spec.full_name}.gem"
Gem::RemoteFetcher.fetcher.download(spec, uri, destination)
end

private

def fetch_specs
Bundler.logger.info "Updating source: #{to_s}"

deflated = Gem::RemoteFetcher.fetcher.fetch_path("#{uri}/Marshal.4.8.Z")
inflated = Gem.inflate deflated

index = Marshal.load(inflated)
specs = Hash.new { |h,k| h[k] = {} }

index.gems.values.each do |spec|
next unless Gem::Platform.match(spec.platform)
spec.source = self
specs[spec.name][spec.version] = spec
end

specs
rescue Gem::RemoteFetcher::FetchError => e
raise ArgumentError, "#{to_s} is not a valid source: #{e.message}"
end
end
end
125 changes: 0 additions & 125 deletions spec/bundler/dsl_spec.rb

This file was deleted.

Loading

0 comments on commit 0785b65

Please sign in to comment.