mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Vendor the bundler project
This commit is contained in:
parent
d80316ad32
commit
e7a2496fda
19 changed files with 940 additions and 0 deletions
20
railties/lib/vendor/bundler/LICENSE
vendored
Normal file
20
railties/lib/vendor/bundler/LICENSE
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
Copyright (c) 2009 Engine Yard
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
52
railties/lib/vendor/bundler/Rakefile
vendored
Normal file
52
railties/lib/vendor/bundler/Rakefile
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
require 'rubygems' unless ENV['NO_RUBYGEMS']
|
||||
require 'rake/gempackagetask'
|
||||
require 'rubygems/specification'
|
||||
require 'date'
|
||||
require 'spec/rake/spectask'
|
||||
|
||||
spec = Gem::Specification.new do |s|
|
||||
s.name = "bundler"
|
||||
s.version = "0.0.1"
|
||||
s.author = "Your Name"
|
||||
s.email = "Your Email"
|
||||
s.homepage = "http://example.com"
|
||||
s.description = s.summary = "A gem that provides..."
|
||||
|
||||
s.platform = Gem::Platform::RUBY
|
||||
s.has_rdoc = true
|
||||
s.extra_rdoc_files = ["README", "LICENSE"]
|
||||
s.summary = ""
|
||||
|
||||
# Uncomment this to add a dependency
|
||||
# s.add_dependency "foo"
|
||||
|
||||
s.bindir = "bin"
|
||||
s.executables = %w( gem_bundler )
|
||||
s.require_path = 'lib'
|
||||
s.files = %w(LICENSE README Rakefile) + Dir.glob("{bin,lib,spec}/**/*")
|
||||
end
|
||||
|
||||
task :default => :spec
|
||||
|
||||
desc "Run specs"
|
||||
Spec::Rake::SpecTask.new do |t|
|
||||
t.spec_files = FileList['spec/**/*_spec.rb']
|
||||
t.spec_opts = %w(-fs --color)
|
||||
end
|
||||
|
||||
|
||||
Rake::GemPackageTask.new(spec) do |pkg|
|
||||
pkg.gem_spec = spec
|
||||
end
|
||||
|
||||
desc "install the gem locally"
|
||||
task :install => [:package] do
|
||||
sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
|
||||
end
|
||||
|
||||
desc "create a gemspec file"
|
||||
task :make_spec do
|
||||
File.open("#{GEM}.gemspec", "w") do |file|
|
||||
file.puts spec.to_ruby
|
||||
end
|
||||
end
|
40
railties/lib/vendor/bundler/bin/gem_bundler
vendored
Executable file
40
railties/lib/vendor/bundler/bin/gem_bundler
vendored
Executable file
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env ruby
|
||||
require "optparse"
|
||||
require "bundler"
|
||||
|
||||
options = {}
|
||||
|
||||
parser = OptionParser.new do |op|
|
||||
op.banner = "Usage: gem_bundler [OPTIONS] [PATH]"
|
||||
|
||||
op.on("-m", "--manifest MANIFEST") do |manifest|
|
||||
options[:manifest] = manifest
|
||||
end
|
||||
|
||||
op.on_tail("-h", "--help", "Show this message") do
|
||||
puts op
|
||||
exit
|
||||
end
|
||||
end
|
||||
parser.parse!
|
||||
|
||||
options[:path] = ARGV.shift
|
||||
|
||||
unless options[:path]
|
||||
puts parser
|
||||
puts %(
|
||||
[PATH] must be specified
|
||||
)
|
||||
exit
|
||||
end
|
||||
|
||||
unless options[:manifest] && File.exist?(options[:manifest])
|
||||
puts parser
|
||||
puts %(
|
||||
MANIFEST must be a valid manifest file
|
||||
)
|
||||
exit
|
||||
end
|
||||
|
||||
|
||||
Bundler.run(options)
|
24
railties/lib/vendor/bundler/lib/bundler.rb
vendored
Normal file
24
railties/lib/vendor/bundler/lib/bundler.rb
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
require 'logger'
|
||||
require 'set'
|
||||
# Required elements of rubygems
|
||||
require "rubygems/remote_fetcher"
|
||||
require "rubygems/installer"
|
||||
|
||||
require "bundler/gem_bundle"
|
||||
require "bundler/installer"
|
||||
require "bundler/finder"
|
||||
require "bundler/gem_specification"
|
||||
require "bundler/resolver"
|
||||
require "bundler/manifest"
|
||||
require "bundler/dependency"
|
||||
require "bundler/runtime"
|
||||
require "bundler/cli"
|
||||
|
||||
module Bundler
|
||||
VERSION = "0.5.0"
|
||||
|
||||
def self.run(options = {})
|
||||
manifest = ManifestBuilder.load(options[:path], options[:manifest])
|
||||
manifest.install
|
||||
end
|
||||
end
|
24
railties/lib/vendor/bundler/lib/bundler/cli.rb
vendored
Normal file
24
railties/lib/vendor/bundler/lib/bundler/cli.rb
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
module Bundler
|
||||
module CLI
|
||||
|
||||
def default_manifest
|
||||
current = Pathname.new(Dir.pwd)
|
||||
|
||||
begin
|
||||
manifest = current.join("Gemfile")
|
||||
return manifest.to_s if File.exist?(manifest)
|
||||
current = current.parent
|
||||
end until current.root?
|
||||
nil
|
||||
end
|
||||
|
||||
module_function :default_manifest
|
||||
|
||||
def default_path
|
||||
Pathname.new(File.dirname(default_manifest)).join("vendor").join("gems").to_s
|
||||
end
|
||||
|
||||
module_function :default_path
|
||||
|
||||
end
|
||||
end
|
35
railties/lib/vendor/bundler/lib/bundler/dependency.rb
vendored
Normal file
35
railties/lib/vendor/bundler/lib/bundler/dependency.rb
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
module Bundler
|
||||
class Dependency
|
||||
|
||||
attr_reader :name, :version, :require_as, :only, :except
|
||||
|
||||
def initialize(name, options = {})
|
||||
options.each do |k, v|
|
||||
options[k.to_s] = v
|
||||
end
|
||||
|
||||
@name = name
|
||||
@version = options["version"] || ">= 0"
|
||||
@require_as = Array(options["require_as"] || name)
|
||||
@only = Array(options["only"]).map {|e| e.to_s } if options["only"]
|
||||
@except = Array(options["except"]).map {|e| e.to_s } if options["except"]
|
||||
end
|
||||
|
||||
def in?(environment)
|
||||
environment = environment.to_s
|
||||
|
||||
return false unless !@only || @only.include?(environment)
|
||||
return false if @except && @except.include?(environment)
|
||||
true
|
||||
end
|
||||
|
||||
def to_s
|
||||
to_gem_dependency.to_s
|
||||
end
|
||||
|
||||
def to_gem_dependency
|
||||
@gem_dep ||= Gem::Dependency.new(name, version)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
42
railties/lib/vendor/bundler/lib/bundler/finder.rb
vendored
Normal file
42
railties/lib/vendor/bundler/lib/bundler/finder.rb
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
module Bundler
|
||||
class Finder
|
||||
def initialize(*sources)
|
||||
@results = {}
|
||||
@index = Hash.new { |h,k| h[k] = {} }
|
||||
|
||||
sources.each { |source| fetch(source) }
|
||||
end
|
||||
|
||||
def resolve(*dependencies)
|
||||
resolved = Resolver.resolve(dependencies, self)
|
||||
resolved && GemBundle.new(resolved.all_specs)
|
||||
end
|
||||
|
||||
def fetch(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
|
||||
|
||||
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
|
||||
|
||||
def search(dependency)
|
||||
@results[dependency.hash] ||= begin
|
||||
possibilities = @index[dependency.name].values
|
||||
possibilities.select do |spec|
|
||||
dependency =~ spec
|
||||
end.sort_by {|s| s.version }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
23
railties/lib/vendor/bundler/lib/bundler/gem_bundle.rb
vendored
Normal file
23
railties/lib/vendor/bundler/lib/bundler/gem_bundle.rb
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
module Bundler
|
||||
class GemBundle < Array
|
||||
def download(directory)
|
||||
FileUtils.mkdir_p(directory)
|
||||
|
||||
current = Dir[File.join(directory, "cache", "*.gem*")]
|
||||
|
||||
each do |spec|
|
||||
cached = File.join(directory, "cache", "#{spec.full_name}.gem")
|
||||
|
||||
unless File.file?(cached)
|
||||
Gem::RemoteFetcher.fetcher.download(spec, spec.source, directory)
|
||||
end
|
||||
|
||||
current.delete(cached)
|
||||
end
|
||||
|
||||
current.each { |file| File.delete(file) }
|
||||
|
||||
self
|
||||
end
|
||||
end
|
||||
end
|
10
railties/lib/vendor/bundler/lib/bundler/gem_specification.rb
vendored
Normal file
10
railties/lib/vendor/bundler/lib/bundler/gem_specification.rb
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
module Gem
|
||||
class Specification
|
||||
attribute :source
|
||||
|
||||
def source=(source)
|
||||
@source = source.is_a?(URI) ? source : URI.parse(source)
|
||||
raise ArgumentError, "The source must be an absolute URI" unless @source.absolute?
|
||||
end
|
||||
end
|
||||
end
|
44
railties/lib/vendor/bundler/lib/bundler/installer.rb
vendored
Normal file
44
railties/lib/vendor/bundler/lib/bundler/installer.rb
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
module Bundler
|
||||
class Installer
|
||||
def initialize(path)
|
||||
if !File.directory?(path)
|
||||
raise ArgumentError, "#{path} is not a directory"
|
||||
elsif !File.directory?(File.join(path, "cache"))
|
||||
raise ArgumentError, "#{path} is not a valid environment (it does not contain a cache directory)"
|
||||
end
|
||||
|
||||
@path = path
|
||||
@gems = Dir[(File.join(path, "cache", "*.gem"))]
|
||||
end
|
||||
|
||||
def install(options = {})
|
||||
bin_dir = options[:bin_dir] ||= File.join(@path, "bin")
|
||||
|
||||
specs = Dir[File.join(@path, "specifications", "*.gemspec")]
|
||||
gems = Dir[File.join(@path, "gems", "*")]
|
||||
|
||||
@gems.each do |gem|
|
||||
name = File.basename(gem).gsub(/\.gem$/, '')
|
||||
installed = specs.any? { |g| File.basename(g) == "#{name}.gemspec" } &&
|
||||
gems.any? { |g| File.basename(g) == name }
|
||||
|
||||
unless installed
|
||||
installer = Gem::Installer.new(gem, :install_dir => @path,
|
||||
:ignore_dependencies => true,
|
||||
:env_shebang => true,
|
||||
:wrappers => true,
|
||||
:bin_dir => bin_dir)
|
||||
installer.install
|
||||
end
|
||||
|
||||
# remove this spec
|
||||
specs.delete_if { |g| File.basename(g) == "#{name}.gemspec"}
|
||||
gems.delete_if { |g| File.basename(g) == name }
|
||||
end
|
||||
|
||||
(specs + gems).each do |path|
|
||||
FileUtils.rm_rf(path)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
130
railties/lib/vendor/bundler/lib/bundler/manifest.rb
vendored
Normal file
130
railties/lib/vendor/bundler/lib/bundler/manifest.rb
vendored
Normal file
|
@ -0,0 +1,130 @@
|
|||
require "rubygems/source_index"
|
||||
require "pathname"
|
||||
|
||||
module Bundler
|
||||
class VersionConflict < StandardError; end
|
||||
|
||||
class Manifest
|
||||
attr_reader :sources, :dependencies, :path
|
||||
|
||||
def initialize(sources, dependencies, path)
|
||||
sources.map! {|s| s.is_a?(URI) ? s : URI.parse(s) }
|
||||
@sources, @dependencies, @path = sources, dependencies, Pathname.new(path)
|
||||
end
|
||||
|
||||
def fetch
|
||||
return if all_gems_installed?
|
||||
|
||||
finder = Finder.new(*sources)
|
||||
unless bundle = finder.resolve(*gem_dependencies)
|
||||
gems = @dependencies.map {|d| " #{d.to_s}" }.join("\n")
|
||||
raise VersionConflict, "No compatible versions could be found for:\n#{gems}"
|
||||
end
|
||||
|
||||
bundle.download(@path)
|
||||
end
|
||||
|
||||
def install(options = {})
|
||||
fetch
|
||||
installer = Installer.new(@path)
|
||||
installer.install # options come here
|
||||
create_load_paths_files(File.join(@path, "environments"))
|
||||
create_fake_rubygems(File.join(@path, "environments"))
|
||||
end
|
||||
|
||||
def activate(environment = "default")
|
||||
require File.join(@path, "environments", "#{environment}.rb")
|
||||
end
|
||||
|
||||
def require_all
|
||||
dependencies.each do |dep|
|
||||
dep.require_as.each {|file| require file }
|
||||
end
|
||||
end
|
||||
|
||||
def gems_for(environment)
|
||||
deps = dependencies.select { |d| d.in?(environment) }
|
||||
deps.map! { |d| d.to_gem_dependency }
|
||||
index = Gem::SourceIndex.from_gems_in(File.join(@path, "specifications"))
|
||||
Resolver.resolve(deps, index).all_specs
|
||||
end
|
||||
|
||||
def environments
|
||||
envs = dependencies.map {|dep| Array(dep.only) + Array(dep.except) }.flatten
|
||||
envs << "default"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def gem_dependencies
|
||||
@gem_dependencies ||= dependencies.map { |d| d.to_gem_dependency }
|
||||
end
|
||||
|
||||
def all_gems_installed?
|
||||
gem_versions = {}
|
||||
|
||||
Dir[File.join(@path, "cache", "*.gem")].each do |file|
|
||||
file =~ /\/([^\/]+)-([\d\.]+)\.gem$/
|
||||
name, version = $1, $2
|
||||
gem_versions[name] = Gem::Version.new(version)
|
||||
end
|
||||
|
||||
gem_dependencies.all? do |dep|
|
||||
gem_versions[dep.name] &&
|
||||
dep.version_requirements.satisfied_by?(gem_versions[dep.name])
|
||||
end
|
||||
end
|
||||
|
||||
def create_load_paths_files(path)
|
||||
FileUtils.mkdir_p(path)
|
||||
environments.each do |environment|
|
||||
gem_specs = gems_for(environment)
|
||||
File.open(File.join(path, "#{environment}.rb"), "w") do |file|
|
||||
file.puts <<-RUBY_EVAL
|
||||
module Bundler
|
||||
def self.rubygems_required
|
||||
#{create_gem_stubs(path, gem_specs)}
|
||||
end
|
||||
end
|
||||
RUBY_EVAL
|
||||
file.puts "$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__))"
|
||||
load_paths_for_specs(gem_specs).each do |load_path|
|
||||
file.puts "$LOAD_PATH.unshift #{load_path.inspect}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create_gem_stubs(path, gem_specs)
|
||||
gem_specs.map do |spec|
|
||||
path = File.expand_path(File.join(path, '..', 'specifications', "#{spec.full_name}.gemspec"))
|
||||
%{
|
||||
Gem.loaded_specs["#{spec.name}"] = eval(File.read("#{path}"))
|
||||
}
|
||||
end.join("\n")
|
||||
end
|
||||
|
||||
def create_fake_rubygems(path)
|
||||
File.open(File.join(path, "rubygems.rb"), "w") do |file|
|
||||
file.puts <<-RUBY_EVAL
|
||||
$:.delete File.expand_path(File.dirname(__FILE__))
|
||||
load "rubygems.rb"
|
||||
if defined?(Bundler) && Bundler.respond_to?(:rubygems_required)
|
||||
Bundler.rubygems_required
|
||||
end
|
||||
RUBY_EVAL
|
||||
end
|
||||
end
|
||||
|
||||
def load_paths_for_specs(specs)
|
||||
load_paths = []
|
||||
specs.each do |spec|
|
||||
load_paths << File.join(spec.full_gem_path, spec.bindir) if spec.bindir
|
||||
spec.require_paths.each do |path|
|
||||
load_paths << File.join(spec.full_gem_path, path)
|
||||
end
|
||||
end
|
||||
load_paths
|
||||
end
|
||||
end
|
||||
end
|
19
railties/lib/vendor/bundler/lib/bundler/resolver.rb
vendored
Normal file
19
railties/lib/vendor/bundler/lib/bundler/resolver.rb
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
require 'bundler/resolver/inspect'
|
||||
require 'bundler/resolver/search'
|
||||
require 'bundler/resolver/engine'
|
||||
require 'bundler/resolver/stack'
|
||||
require 'bundler/resolver/state'
|
||||
|
||||
module Bundler
|
||||
module Resolver
|
||||
def self.resolve(deps, source_index = Gem.source_index, logger = nil)
|
||||
unless logger
|
||||
logger = Logger.new($stderr)
|
||||
logger.datetime_format = ""
|
||||
logger.level = ENV["GEM_RESOLVER_DEBUG"] ? Logger::DEBUG : Logger::ERROR
|
||||
end
|
||||
|
||||
Engine.resolve(deps, source_index, logger)
|
||||
end
|
||||
end
|
||||
end
|
61
railties/lib/vendor/bundler/lib/bundler/resolver/builders.rb
vendored
Normal file
61
railties/lib/vendor/bundler/lib/bundler/resolver/builders.rb
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
module Bundler
|
||||
module Resolver
|
||||
module Builders
|
||||
def build_index(&block)
|
||||
index = Gem::SourceIndex.new
|
||||
IndexBuilder.run(index, &block) if block_given?
|
||||
index
|
||||
end
|
||||
|
||||
def build_spec(name, version, &block)
|
||||
spec = Gem::Specification.new
|
||||
spec.instance_variable_set(:@name, name)
|
||||
spec.instance_variable_set(:@version, Gem::Version.new(version))
|
||||
DepBuilder.run(spec, &block) if block_given?
|
||||
spec
|
||||
end
|
||||
|
||||
def build_dep(name, requirements, type = :runtime)
|
||||
Gem::Dependency.new(name, requirements, type)
|
||||
end
|
||||
|
||||
class IndexBuilder
|
||||
include Builders
|
||||
|
||||
def self.run(index, &block)
|
||||
new(index).run(&block)
|
||||
end
|
||||
|
||||
def initialize(index)
|
||||
@index = index
|
||||
end
|
||||
|
||||
def run(&block)
|
||||
instance_eval(&block)
|
||||
end
|
||||
|
||||
def add_spec(*args, &block)
|
||||
@index.add_spec(build_spec(*args, &block))
|
||||
end
|
||||
end
|
||||
|
||||
class DepBuilder
|
||||
def self.run(spec, &block)
|
||||
new(spec).run(&block)
|
||||
end
|
||||
|
||||
def initialize(spec)
|
||||
@spec = spec
|
||||
end
|
||||
|
||||
def run(&block)
|
||||
instance_eval(&block)
|
||||
end
|
||||
|
||||
def runtime(name, requirements)
|
||||
@spec.add_runtime_dependency(name, requirements)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
38
railties/lib/vendor/bundler/lib/bundler/resolver/engine.rb
vendored
Normal file
38
railties/lib/vendor/bundler/lib/bundler/resolver/engine.rb
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
module Bundler
|
||||
module Resolver
|
||||
class ClosedSet < Set
|
||||
end
|
||||
|
||||
class Engine
|
||||
include Search, Inspect
|
||||
|
||||
def self.resolve(deps, source_index, logger)
|
||||
new(deps, source_index, logger).resolve
|
||||
end
|
||||
|
||||
def initialize(deps, source_index, logger)
|
||||
@deps, @source_index, @logger = deps, source_index, logger
|
||||
logger.debug "searching for #{gem_resolver_inspect(@deps)}"
|
||||
end
|
||||
attr_reader :deps, :source_index, :logger, :solution
|
||||
|
||||
def resolve
|
||||
state = State.initial(self, [], Stack.new, Stack.new([[[], @deps.dup]]))
|
||||
if solution = search(state)
|
||||
logger.info "got the solution with #{solution.all_specs.size} specs"
|
||||
solution.dump(Logger::INFO)
|
||||
solution
|
||||
end
|
||||
end
|
||||
|
||||
def open
|
||||
@open ||= []
|
||||
end
|
||||
|
||||
def closed
|
||||
@closed ||= ClosedSet.new
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
24
railties/lib/vendor/bundler/lib/bundler/resolver/inspect.rb
vendored
Normal file
24
railties/lib/vendor/bundler/lib/bundler/resolver/inspect.rb
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
module Bundler
|
||||
module Resolver
|
||||
module Inspect
|
||||
def gem_resolver_inspect(o)
|
||||
case o
|
||||
when Gem::Specification
|
||||
"#<Spec: #{o.full_name}>"
|
||||
when Array
|
||||
'[' + o.map {|x| gem_resolver_inspect(x)}.join(", ") + ']'
|
||||
when Set
|
||||
gem_resolver_inspect(o.to_a)
|
||||
when Hash
|
||||
'{' + o.map {|k,v| "#{gem_resolver_inspect(k)} => #{gem_resolver_inspect(v)}"}.join(", ") + '}'
|
||||
when Stack
|
||||
o.gem_resolver_inspect
|
||||
else
|
||||
o.inspect
|
||||
end
|
||||
end
|
||||
|
||||
module_function :gem_resolver_inspect
|
||||
end
|
||||
end
|
||||
end
|
71
railties/lib/vendor/bundler/lib/bundler/resolver/search.rb
vendored
Normal file
71
railties/lib/vendor/bundler/lib/bundler/resolver/search.rb
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
module Bundler
|
||||
module Resolver
|
||||
module Search
|
||||
def search(initial, max_depth = (1.0 / 0.0))
|
||||
if initial.goal_met?
|
||||
return initial
|
||||
end
|
||||
|
||||
open << initial
|
||||
|
||||
while open.any?
|
||||
current = open.pop
|
||||
closed << current
|
||||
|
||||
new = []
|
||||
current.each_possibility do |attempt|
|
||||
unless closed.include?(attempt)
|
||||
if attempt.goal_met?
|
||||
return attempt
|
||||
elsif attempt.depth < max_depth
|
||||
new << attempt
|
||||
end
|
||||
end
|
||||
end
|
||||
new.reverse.each do |state|
|
||||
open << state
|
||||
end
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
def open
|
||||
raise "implement #open in #{self.class}"
|
||||
end
|
||||
|
||||
def closed
|
||||
raise "implement #closed in #{self.class}"
|
||||
end
|
||||
|
||||
module Node
|
||||
def self.included(base)
|
||||
base.extend(ClassMethods)
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
def initial(*data)
|
||||
new(0, *data)
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(depth)
|
||||
@depth = depth
|
||||
end
|
||||
attr_reader :depth
|
||||
|
||||
def child(*data)
|
||||
self.class.new(@depth + 1, *data)
|
||||
end
|
||||
|
||||
def each_possibility
|
||||
raise "implement #each_possibility on #{self.class}"
|
||||
end
|
||||
|
||||
def goal_met?
|
||||
raise "implement #goal_met? on #{self.class}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
72
railties/lib/vendor/bundler/lib/bundler/resolver/stack.rb
vendored
Normal file
72
railties/lib/vendor/bundler/lib/bundler/resolver/stack.rb
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
module Bundler
|
||||
module Resolver
|
||||
class Stack
|
||||
def initialize(initial = [])
|
||||
@data = []
|
||||
initial.each do |(path,value)|
|
||||
self[path] = value
|
||||
end
|
||||
end
|
||||
|
||||
def last
|
||||
@data.last
|
||||
end
|
||||
|
||||
def []=(path, value)
|
||||
raise ArgumentError, "#{path.inspect} already has a value" if key?(path)
|
||||
@data << [path.dup, value]
|
||||
end
|
||||
|
||||
def [](path)
|
||||
if key?(path)
|
||||
_, value = @data.find do |(k,v)|
|
||||
k == path
|
||||
end
|
||||
value
|
||||
else
|
||||
raise "No value for #{path.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
def key?(path)
|
||||
@data.any? do |(k,v)|
|
||||
k == path
|
||||
end
|
||||
end
|
||||
|
||||
def each
|
||||
@data.each do |(k,v)|
|
||||
yield k, v
|
||||
end
|
||||
end
|
||||
|
||||
def map
|
||||
@data.map do |(k,v)|
|
||||
yield k, v
|
||||
end
|
||||
end
|
||||
|
||||
def each_value
|
||||
@data.each do |(k,v)|
|
||||
yield v
|
||||
end
|
||||
end
|
||||
|
||||
def dup
|
||||
self.class.new(@data.dup)
|
||||
end
|
||||
|
||||
def to_s
|
||||
@data.to_s
|
||||
end
|
||||
|
||||
def inspect
|
||||
@data.inspect
|
||||
end
|
||||
|
||||
def gem_resolver_inspect
|
||||
Inspect.gem_resolver_inspect(@data)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
172
railties/lib/vendor/bundler/lib/bundler/resolver/state.rb
vendored
Normal file
172
railties/lib/vendor/bundler/lib/bundler/resolver/state.rb
vendored
Normal file
|
@ -0,0 +1,172 @@
|
|||
module Bundler
|
||||
module Resolver
|
||||
class State
|
||||
include Search::Node, Inspect
|
||||
|
||||
def initialize(depth, engine, path, spec_stack, dep_stack)
|
||||
super(depth)
|
||||
@engine, @path, @spec_stack, @dep_stack = engine, path, spec_stack, dep_stack
|
||||
end
|
||||
attr_reader :path
|
||||
|
||||
def logger
|
||||
@engine.logger
|
||||
end
|
||||
|
||||
def goal_met?
|
||||
logger.info "checking if goal is met"
|
||||
dump
|
||||
no_duplicates?
|
||||
all_deps.all? do |dep|
|
||||
dependency_satisfied?(dep)
|
||||
end
|
||||
end
|
||||
|
||||
def no_duplicates?
|
||||
names = []
|
||||
all_specs.each do |s|
|
||||
if names.include?(s.name)
|
||||
raise "somehow got duplicates for #{s.name}"
|
||||
end
|
||||
names << s.name
|
||||
end
|
||||
end
|
||||
|
||||
def dependency_satisfied?(dep)
|
||||
all_specs.any? do |spec|
|
||||
spec.satisfies_requirement?(dep)
|
||||
end
|
||||
end
|
||||
|
||||
def each_possibility(&block)
|
||||
index, dep = remaining_deps.first
|
||||
if dep
|
||||
logger.warn "working on #{dep} for #{spec_name}"
|
||||
handle_dep(index, dep, &block)
|
||||
else
|
||||
logger.warn "no dependencies left for #{spec_name}"
|
||||
jump_to_parent(&block)
|
||||
end
|
||||
end
|
||||
|
||||
def handle_dep(index, dep)
|
||||
specs = @engine.source_index.search(dep)
|
||||
|
||||
specs.reverse.each do |s|
|
||||
logger.info "attempting with spec: #{s.full_name}"
|
||||
new_path = @path + [index]
|
||||
new_spec_stack = @spec_stack.dup
|
||||
new_dep_stack = @dep_stack.dup
|
||||
|
||||
new_spec_stack[new_path] = s
|
||||
new_dep_stack[new_path] = s.runtime_dependencies.sort_by do |dep|
|
||||
@engine.source_index.search(dep).size
|
||||
end
|
||||
yield child(@engine, new_path, new_spec_stack, new_dep_stack)
|
||||
end
|
||||
end
|
||||
|
||||
def jump_to_parent
|
||||
if @path.empty?
|
||||
dump
|
||||
logger.warn "at the end"
|
||||
return
|
||||
end
|
||||
|
||||
logger.info "jumping to parent for #{spec_name}"
|
||||
new_path = @path[0..-2]
|
||||
new_spec_stack = @spec_stack.dup
|
||||
new_dep_stack = @dep_stack.dup
|
||||
|
||||
yield child(@engine, new_path, new_spec_stack, new_dep_stack)
|
||||
end
|
||||
|
||||
def remaining_deps
|
||||
remaining_deps_for(@path)
|
||||
end
|
||||
|
||||
def remaining_deps_for(path)
|
||||
no_duplicates?
|
||||
remaining = []
|
||||
@dep_stack[path].each_with_index do |dep,i|
|
||||
remaining << [i, dep] unless all_specs.find {|s| s.name == dep.name}
|
||||
end
|
||||
remaining
|
||||
end
|
||||
|
||||
def deps
|
||||
@dep_stack[@path]
|
||||
end
|
||||
|
||||
def spec
|
||||
@spec_stack[@path]
|
||||
end
|
||||
|
||||
def spec_name
|
||||
@path.empty? ? "<top>" : spec.full_name
|
||||
end
|
||||
|
||||
def all_deps
|
||||
all_deps = Set.new
|
||||
@dep_stack.each_value do |deps|
|
||||
all_deps.merge(deps)
|
||||
end
|
||||
all_deps.to_a
|
||||
end
|
||||
|
||||
def all_specs
|
||||
@spec_stack.map do |path,spec|
|
||||
spec
|
||||
end
|
||||
end
|
||||
|
||||
def dump(level = Logger::DEBUG)
|
||||
logger.add level, "v" * 80
|
||||
logger.add level, "path: #{@path.inspect}"
|
||||
logger.add level, "deps: (#{deps.size})"
|
||||
deps.map do |dep|
|
||||
logger.add level, gem_resolver_inspect(dep)
|
||||
end
|
||||
logger.add level, "remaining_deps: (#{remaining_deps.size})"
|
||||
remaining_deps.each do |dep|
|
||||
logger.add level, gem_resolver_inspect(dep)
|
||||
end
|
||||
logger.add level, "dep_stack: "
|
||||
@dep_stack.each do |path,deps|
|
||||
logger.add level, "#{path.inspect} (#{deps.size})"
|
||||
deps.each do |dep|
|
||||
logger.add level, "-> #{gem_resolver_inspect(dep)}"
|
||||
end
|
||||
end
|
||||
logger.add level, "spec_stack: "
|
||||
@spec_stack.each do |path,spec|
|
||||
logger.add level, "#{path.inspect}: #{gem_resolver_inspect(spec)}"
|
||||
end
|
||||
logger.add level, "^" * 80
|
||||
end
|
||||
|
||||
def to_dot
|
||||
io = StringIO.new
|
||||
io.puts 'digraph deps {'
|
||||
io.puts ' fontname = "Courier";'
|
||||
io.puts ' mincross = 4.0;'
|
||||
io.puts ' ratio = "auto";'
|
||||
dump_to_dot(io, "<top>", [])
|
||||
io.puts '}'
|
||||
io.string
|
||||
end
|
||||
|
||||
def dump_to_dot(io, name, path)
|
||||
@dep_stack[path].each_with_index do |dep,i|
|
||||
new_path = path + [i]
|
||||
spec_name = all_specs.find {|x| x.name == dep.name}.full_name
|
||||
io.puts ' "%s" -> "%s";' % [name, dep.to_s]
|
||||
io.puts ' "%s" -> "%s";' % [dep.to_s, spec_name]
|
||||
if @spec_stack.key?(new_path)
|
||||
dump_to_dot(io, spec_name, new_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
39
railties/lib/vendor/bundler/lib/bundler/runtime.rb
vendored
Normal file
39
railties/lib/vendor/bundler/lib/bundler/runtime.rb
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
module Bundler
|
||||
class ManifestBuilder
|
||||
|
||||
attr_reader :sources
|
||||
|
||||
def self.build(path, string)
|
||||
builder = new(path)
|
||||
builder.instance_eval(string)
|
||||
builder.to_manifest
|
||||
end
|
||||
|
||||
def self.load(path, file)
|
||||
string = File.read(file)
|
||||
build(path, string)
|
||||
end
|
||||
|
||||
def initialize(path)
|
||||
@path = path
|
||||
@sources = %w(http://gems.rubyforge.org)
|
||||
@dependencies = []
|
||||
end
|
||||
|
||||
def to_manifest
|
||||
Manifest.new(@sources, @dependencies, @path)
|
||||
end
|
||||
|
||||
def source(source)
|
||||
@sources << source
|
||||
end
|
||||
|
||||
def gem(name, *args)
|
||||
options = args.last.is_a?(Hash) ? args.pop : {}
|
||||
version = args.last
|
||||
|
||||
@dependencies << Dependency.new(name, options.merge(:version => version))
|
||||
end
|
||||
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue