1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
require "rubygems/source_index"
module Bundler
class VersionConflict < StandardError; end
class Manifest
attr_reader :sources, :dependencies, :path
def initialize(sources, dependencies, bindir, repository_path, rubygems, system_gems)
sources.map! {|s| s.is_a?(URI) ? s : URI.parse(s) }
@sources = sources
@dependencies = dependencies
@bindir = bindir
@repository = Repository.new(repository_path)
@rubygems = rubygems
@system_gems = system_gems
end
def install(update)
fetch(update)
@repository.install_cached_gems(:bin_dir => @bindir || @repository.path.join("bin"))
cleanup_removed_gems
create_environment_files(@repository.path.join("environments"))
Bundler.logger.info "Done."
end
def activate(environment = "default")
require @repository.path.join("environments", "#{environment}.rb")
end
def require_all
dependencies.each do |dep|
dep.require_as.each {|file| require file }
end
end
def gems_for(environment = nil)
deps = dependencies
deps = deps.select { |d| d.in?(environment) } if environment
deps = deps.map { |d| d.to_gem_dependency }
Resolver.resolve(deps, @repository.source_index)
end
alias gems gems_for
def environments
envs = dependencies.map {|dep| Array(dep.only) + Array(dep.except) }.flatten
envs << "default"
end
private
def fetch(update)
return unless update || !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(@repository.path)
end
def gem_dependencies
@gem_dependencies ||= dependencies.map { |d| d.to_gem_dependency }
end
def all_gems_installed?
downloaded_gems = {}
Dir[@repository.path.join("cache", "*.gem")].each do |file|
file =~ /\/([^\/]+)-([\d\.]+)\.gem$/
name, version = $1, $2
downloaded_gems[name] = Gem::Version.new(version)
end
gem_dependencies.all? do |dep|
downloaded_gems[dep.name] &&
dep.version_requirements.satisfied_by?(downloaded_gems[dep.name])
end
end
def cleanup_removed_gems
glob = gems.map { |g| g.full_name }.join(',')
base = @repository.path.join("{cache,specifications,gems}")
(Dir[base.join("*")] - Dir[base.join("{#{glob}}{.gemspec,.gem,}")]).each do |file|
Bundler.logger.info "Deleting gem: #{File.basename(file, ".gem")}" if File.basename(file) =~ /\.gem$/
FileUtils.rm_rf(file)
end
glob = gems.map { |g| g.executables }.flatten.join(',')
(Dir[@bindir.join("*")] - Dir[@bindir.join("{#{glob}}")]).each do |file|
Bundler.logger.info "Deleting bin file: #{File.basename(file)}"
FileUtils.rm_rf(file)
end
end
def create_environment_files(path)
FileUtils.mkdir_p(path)
environments.each do |environment|
specs = gems_for(environment)
files = spec_files_for_specs(specs, path)
load_paths = load_paths_for_specs(specs)
create_environment_file(path, environment, files, load_paths)
end
end
def create_environment_file(path, environment, spec_files, load_paths)
File.open(path.join("#{environment}.rb"), "w") do |file|
template = File.read(File.join(File.dirname(__FILE__), "templates", "environment.rb"))
erb = ERB.new(template)
file.puts erb.result(binding)
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
def spec_files_for_specs(specs, path)
files = {}
specs.each do |s|
files[s.name] = path.join("..", "specifications", "#{s.full_name}.gemspec").expand_path
end
files
end
end
end
|